Skip to content

Commit

Permalink
Merge pull request #274 from dbuezas/Better_wdt_lib
Browse files Browse the repository at this point in the history
Better wdt lib and lgt low power lib
  • Loading branch information
dbuezas authored May 9, 2023
2 parents b2f00c8 + 811d490 commit 636c741
Show file tree
Hide file tree
Showing 22 changed files with 3,116 additions and 80 deletions.
40 changes: 20 additions & 20 deletions lgt8f/libraries/PMU/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,27 @@
#######################################
# Methods and Functions (KEYWORD2)
#######################################
sleep KEYWORD2
addWakeupPin KEYWORD2
removeWakeupPin KEYWORD2
pullupUnusedPin KEYWORD2
PMU KEYWORD2
sleep KEYWORD2
addWakeupPin KEYWORD2
removeWakeupPin KEYWORD2
pullupUnusedPin KEYWORD2
PMU KEYWORD2

#######################################
# Constants (LITERAL1)
#######################################
PM_IDLE LITERAL1
PM_POWERDWN LITERAL1
PM_POFFS0 LITERAL1
PM_POFFS1 LITERAL1
SLEEP_FOREVER LITERAL1
SLEEP_16MS LITERAL1
SLEEP_32MS LITERAL1
SLEEP_64MS LITERAL1
SLEEP_128MS LITERAL1
SLEEP_256MS LITERAL1
SLEEP_512MS LITERAL1
SLEEP_1S LITERAL1
SLEEP_2S LITERAL1
SLEEP_4S LITERAL1
SLEEP_8S LITERAL1
PM_IDLE LITERAL1
PM_POWERDWN LITERAL1
PM_POFFS0 LITERAL1
PM_POFFS1 LITERAL1
SLEEP_FOREVER LITERAL1
SLEEP_16MS LITERAL1
SLEEP_32MS LITERAL1
SLEEP_64MS LITERAL1
SLEEP_128MS LITERAL1
SLEEP_256MS LITERAL1
SLEEP_512MS LITERAL1
SLEEP_1S LITERAL1
SLEEP_2S LITERAL1
SLEEP_4S LITERAL1
SLEEP_8S LITERAL1
112 changes: 81 additions & 31 deletions lgt8f/libraries/WDT/WDT.h
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
/*
WDT.h - WDT library
Copyright (c) 2006 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**************************************************************************
* WDT.cpp - Watchdog library for LogicGreen LGT8F328x microcontrollers *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin St,Fifth Floor,Boston, MA 02110-1301 USA *
**************************************************************************/

#ifndef WDT_h
#define WDT_h

#include <avr/wdt.h>
#include "Arduino.h"

#if defined(__LGT8FX8P__)
#define WTO_64MS 0
#define WTO_128MS 1
#define WTO_256MS 2
Expand All @@ -34,28 +32,80 @@
#define WTO_8S 7
#define WTO_16S 8
#define WTO_32S 9
#else
#define WTO_1MS 0
#define WTO_2MS 1
#define WTO_4MS 2
#define WTO_8MS 3
#define WTO_16MS 4
#define WTO_64MS 6
#define WTO_128MS 7
#define WTO_256MS 8
#define WTO_512MS 9
#endif

#if defined(__LGT8FX8P__)
class LGTWDT
{
public:
// enable 32kRC for WDT
static void begin() __attribute__((always_inline)) {
uint8_t btmp = PMCR | 0x10;
PMCR = 0x80;
PMCR = btmp;
}
};

static void __inline__ __attribute__ ((__always_inline__)) wdt_ienable(const uint8_t value)
{
__asm__ __volatile__ (
"in __tmp_reg__,__SREG__ \n\t"
"cli \n\t"
"wdr \n\t"
"sts %[wdtcsr], %[wdce_wde] \n\t"
"out __SREG__,__tmp_reg__ \n\t"
"sts %[wdtcsr], %[wdie_val] \n\t"
: /* no outputs */
: [wdtcsr] "n" (_SFR_MEM_ADDR(WDTCSR)),
[wdce_wde] "r" ((uint8_t)((1 << WDCE) | (1 << WDE))),
[wdie_val] "r" ((uint8_t) ((1 << WDIE) | (value & 0x08 ? 0x20 : 0x00) | (value & 0x07)))
: "r0"
); }

volatile uint8_t o_sreg __attribute__ ((section (".noinit")));
volatile uint8_t s_tempreg __attribute__ ((section (".noinit")));

void softRepairedWdtIsr(void) __attribute__ ((naked)) __attribute__ ((used)) __attribute__ ((section (".init0")));
void softRepairedWdtIsr(void)
{
__asm__ __volatile__ (
"sts (s_tempreg), r24\n\t" // s_tempreg = uint8_t register temp_reg; Save a register
"in r24, __SREG__ \n\t" // o_sreg = SREG;
"sts (o_sreg) , r24 \n\t"
"lds r24, %[wdtcsr] \n\t" // temp_reg = WDTCSR;
#if defined(__LGT8FX8P__)
"sbrs r24, %[wdif] \n\t" // if (temp_reg & (1 << WDIF))
#else
"sbrs r24, %[wdie] \n\t" // if (temp_reg & (1 << WDIE))
#endif
"rjmp 1f \n\t"
// WDT interrupt
"andi r24, %[nwdie] \n\t" // WDTCSR = temp_reg & ~(1 << WDIE);
"sts %[wdtcsr] , r24 \n\t"
"lds r24, (o_sreg) \n\t" // SREG = o_sreg;
"out __SREG__ , r24 \n\t"
"lds r24, (s_tempreg)\n\t" // temp_reg = s_tempreg;
"jmp __vector_6 \n\t"
"1: \n\t"

: /* No outputs */
: [wdtcsr] "n" (_SFR_MEM_ADDR(WDTCSR)),
[wdif] "i" (WDIF),
[wdie] "i" (WDIE),
[nwdie] "i" (~(1 << WDIE))
);

/*
o_sreg = SREG;
uint8_t temp_reg = WDTCSR;
if (temp_reg & (1 << WDIF)) {
// WDT interrupt
WDTCSR = temp_reg & ~(1 << WDIE);
SREG = o_sreg;
__asm__ __volatile__ ("jmp __vector_6 \n");
}
*/

}

#endif
49 changes: 49 additions & 0 deletions lgt8f/libraries/WDT/examples/wdt_interrupt/wdt_interrupt.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/********************************************************
* This example shows how the watchdog interrupt works. *
* About every 4 seconds there will be a wdt interrupt. *
* If you uncomment the line containing wdt_reset() the *
* sketch will not detect wdt interrupt signal. *
********************************************************
* When writing an Interrupt Service Routine (ISR): *
* Keep short,don't use delay(), don't do serial prints *
* Make variables shared with the main code volatile *
* Read this: https://gammon.com.au/interrupts *
********************************************************/
#include <WDT.h>

volatile boolean isrflag;

void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Serial.begin(19200);
Serial.println(F("Skech started."));
isrflag = false;
wdt_ienable(WTO_4S);
}

void loop() {
int n = 0;
do {
Serial.print(F(" Elapsed time: "));
Serial.print(n);
Serial.println(" s");
delay(999);
if (digitalRead(LED_BUILTIN))
digitalWrite(LED_BUILTIN, LOW );
else
digitalWrite(LED_BUILTIN, HIGH);
if (isrflag) {
Serial.println(F("--There was a wdt interrupt.--"));
isrflag = false;
wdt_ienable(WTO_4S);
}
//wdt_reset();
} while( n++ < 1000 );
}

ISR (WDT_vect)
{
isrflag = true;
wdt_reset();
}
29 changes: 29 additions & 0 deletions lgt8f/libraries/WDT/examples/wdt_reset/wdt_reset.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/****************************************************
* This example shows how the watchdog reset works. *
* It restarts every 4 seconds. If you uncomment *
* the line containing wdt_reset() the sketch will *
* run continuously. *
****************************************************/
#include <WDT.h>

void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Serial.begin(19200);
Serial.println(F("Skech started."));
wdt_enable(WTO_4S);
}

void loop() {
int n = 0;
do {
Serial.print(F("Elapsed time: "));
Serial.print(n);
Serial.println(" s");
delay(499);
digitalWrite(LED_BUILTIN, HIGH);
delay(499);
digitalWrite(LED_BUILTIN, LOW);
//wdt_reset();
} while( n++ < 1000 );
}
22 changes: 0 additions & 22 deletions lgt8f/libraries/WDT/examples/wdt_test/wdt_test.ino

This file was deleted.

16 changes: 9 additions & 7 deletions lgt8f/libraries/WDT/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,24 @@
#######################################
# Datatypes (KEYWORD1)
#######################################
WTO_1MS KEYWORD1
WTO_2MS KEYWORD1
WTO_4MS KEYWORD1
WTO_8MS KEYWORD1
WTO_16MS KEYWORD1
WTO_32MS KEYWORD1
WTO_64MS KEYWORD1
WTO_128MS KEYWORD1
WTO_256MS KEYWORD1
WTO_512MS KEYWORD1
WTO_1S KEYWORD1
WTO_2S KEYWORD1
WTO_4S KEYWORD1
WTO_8S KEYWORD1
WTO_16S KEYWORD1
WTO_32S KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################
wdt_enable KEYWORD2
wdt_reset KEYWORD2
wdt_enable KEYWORD2
wdt_ienable KEYWORD2
wdt_disable KEYWORD2

#######################################
# Constants (LITERAL1)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*******************************************************************************
* This example shows how to use Noise Reduction mode. ( In short Noise *
* Reduction mode stops the core and most of the pheripherials clocks and *
* an ADC conversion starts automatically. ) *
* The example periodically read A0 input. The sleep time is shorter than the *
* specified because the ADC wakes it up at the end of the conversion. This *
* library clears the WDT immediately after waking up. *
* This example also show how to clear ADIF flag before entering sleep mode. *
* *
* - You should pay attention to that reading any analalog input with ADC *
* ( analogRead() ) the intrerrupt flag of the ADC ( ADIF ) is set. *
* This is causes the MCU wakes up immediately from any sleep mode. To avoid *
* waking up immediately must clear the ADIF bit in ADCSRA before sleep. *
*******************************************************************************/

#include "lgt_LowPower.h"

int avalue;
int measuredpin = A0;

void setup()
{
// No setup is required for LowPower library
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(measuredpin,INPUT);
analogReference(INTERNAL1V024);
// analogReadResolution(12);
avalue = analogRead(measuredpin); // Sets the ADMUX for the later use
}

void loop()
{

// Clear ADC interrupt flag before sleep guarantees waiting until the
// conversion is completed.
ADCSRA |= (1 << ADIF);

// Enter idle state for 8 s with the rest of peripherals turned off
// LGT8Fx8P
LowPower.adcNoiseReduction(SLEEP_8S, ADC_ON, TIMER2_OFF);

// Do something here. Example: Read sensor, data logging, data transmission.
digitalToggle(LED_BUILTIN);

// Reading directly the ADC register the resolution will always 12 bits
// regardless of what was set with the analogReadResolution().

avalue = ADC; // Reading the result made while sleeping.
avalue -= (avalue >> 7); // Gain-error correction of LGT8F328P

Serial.print(F("Measued value: "));
Serial.print(avalue/4);
Serial.println(F(" mV"));

// Waiting for the end of data transmission. The Noise Reduction sleep mode
// stops serial port during next ADC conversion.
Serial.flush();
}
Loading

0 comments on commit 636c741

Please sign in to comment.