Skip to content

Commit edadc72

Browse files
committed
Merge remote-tracking branch 'origin' into sandbox
2 parents 3c48d74 + e85f6a0 commit edadc72

File tree

4 files changed

+94
-62
lines changed

4 files changed

+94
-62
lines changed
Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,9 @@
1-
#include <Arduino.h>
1+
#include <avr/cpufunc.h>
2+
#include <avr/io.h>
23
#include <led_ctrl.h>
34
#include <log.h>
45
#include <low_power.h>
56
#include <lte.h>
6-
#include <sequans_controller.h>
7-
8-
#ifdef __AVR_AVR128DB48__ // MINI
9-
10-
#define SerialDebug Serial3
11-
#define TIMING_PIN PIN_PE2
12-
#else
13-
#ifdef __AVR_AVR128DB64__ // Non-Mini
14-
15-
#define SerialDebug Serial5
16-
#define TIMING_PIN PIN_PE7
17-
18-
#else
19-
#error "INCOMPATIBLE_DEVICE_SELECTED"
20-
#endif
21-
#endif
227

238
void setup() {
249

@@ -27,12 +12,12 @@ void setup() {
2712
Log.begin(115200);
2813
Log.setLogLevel(LogLevel::DEBUG);
2914

30-
// Start LTE modem, configure the power save configuration and wait until we
31-
// are connected to the operator
15+
// Configure the power save configuration, start the LTE modem and wait
16+
// until we are connected to the operator
3217
//
3318
// Here we say that we want to sleep for 30 seconds * 2 = 60 seconds each
3419
// time we invoke sleep
35-
LowPower.begin(SleepMultiplier::THIRTY_SECONDS, 2, SleepMode::REGULAR);
20+
LowPower.begin(SleepMultiplier::THIRTY_SECONDS, 2, SleepMode::DEEP);
3621
Lte.begin();
3722

3823
while (!Lte.isConnected()) {
@@ -41,15 +26,14 @@ void setup() {
4126
}
4227

4328
Log.info("Connected to operator!\r\n");
44-
45-
pinConfigure(TIMING_PIN, PIN_DIR_OUTPUT);
4629
}
4730

4831
void loop() {
4932

50-
digitalWrite(TIMING_PIN, digitalRead(TIMING_PIN) ? 0 : 1);
51-
5233
WakeUpReason wakeup_reason = LowPower.sleep();
5334
Log.infof("Got out of sleep with wake up reason %d, doing work...\r\n",
5435
wakeup_reason);
36+
37+
delay(10000);
38+
// Do work ...
5539
}

src/led_ctrl.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ class LedCtrlClass {
1616
*/
1717
LedCtrlClass(){};
1818

19-
uint8_t getLedPin(Led led);
20-
2119
public:
2220
/**
2321
* @brief Singleton instance.
@@ -35,6 +33,11 @@ class LedCtrlClass {
3533
*/
3634
void begin(const bool manual_control = false);
3735

36+
/**
37+
* @return The pin associated with the given LED.
38+
*/
39+
uint8_t getLedPin(Led led);
40+
3841
/**
3942
* @brief Toggle @p led.
4043
*

src/low_power.cpp

Lines changed: 78 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
#include "led_ctrl.h"
12
#include "log.h"
23
#include "low_power.h"
34
#include "lte.h"
45
#include "sequans_controller.h"
56

67
#include <Arduino.h>
8+
#include <avr/cpufunc.h>
79
#include <avr/io.h>
810
#include <avr/sleep.h>
911

@@ -50,9 +52,23 @@
5052
#define TIMER_LENGTH 11
5153
#define TIMER_SLEEP_INDEX 8
5254

53-
#define RING_PORT VPORTC
55+
#define RING_PORT VPORTC
56+
57+
#ifdef __AVR_AVR128DB48__ // MINI
58+
59+
#define RING_PIN_bm PIN6_bm
60+
61+
#else
62+
63+
#ifdef __AVR_AVR128DB64__ // Non-Mini
64+
5465
#define RING_PIN_bm PIN4_bm
5566

67+
#else
68+
#error "INCOMPATIBLE_DEVICE_SELECTED"
69+
#endif
70+
#endif
71+
5672
// Singleton. Defined for use of the rest of the library.
5773
LowPowerClass LowPower = LowPowerClass::instance();
5874

@@ -64,6 +80,9 @@ static SleepMode sleep_mode;
6480
static bool retrieved_sleep_time = false;
6581
static uint32_t sleep_time = 0;
6682

83+
static uint8_t cell_led_state = 0;
84+
static uint8_t con_led_state = 0;
85+
6786
ISR(RTC_PIT_vect) {
6887
RTC.PITINTFLAGS = RTC_PI_bm;
6988
pit_triggered = true;
@@ -93,7 +112,7 @@ static void uint8ToStringOfBits(const uint8_t value, char *string) {
93112

94113
static uint8_t stringOfBitsToUint8(const char *string) {
95114

96-
uint8_t value;
115+
uint8_t value = 0;
97116

98117
for (uint8_t i = 0; i < 8; i++) {
99118
// We assume all other values are zero, so we only shift the ones
@@ -234,32 +253,33 @@ static uint32_t retrieveOperatorSleepTime(void) {
234253

235254
static void enablePIT(void) {
236255

237-
// TODO: Fix this, should use external crystal
238-
// Setup the clock for RTC. CTRL_SETUP is stored here just for convenience
239-
// so that we discard the modifications in the register later
240-
//
241-
// CLKCTRL.XOSC32KCTRLA |= CLKCTRL_RUNSTBY_bm | CLKCTRL_LPMODE_bm |
242-
// CLKCTRL_ENABLE_bm;
256+
uint8_t temp;
243257

244-
// Wait for clock to stabilize
245-
// while (CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm &&
246-
// CLKCTRL.XOSC32KCTRLA & CLKCTRL_SEL_bm) {}
258+
// Disable first and wait for clock to stabilize
259+
temp = CLKCTRL.XOSC32KCTRLA;
260+
temp &= ~CLKCTRL_ENABLE_bm;
261+
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, temp);
262+
while (CLKCTRL.MCLKSTATUS & CLKCTRL_XOSC32KS_bm) {}
247263

248-
// Now we configure RTC which keeps track of the time during sleep. We do
249-
// this here as we yield the RTC afterwards, so a setup every time is just
250-
// to safe guard ourselves if other modules use the RTC
251-
//
252-
// Wait for all registers to be synchronized
264+
// We want the external crystal to run in standby and in low power mode
265+
temp = CLKCTRL.XOSC32KCTRLA;
266+
temp |= CLKCTRL_RUNSTBY_bm | CLKCTRL_LPMODE_bm;
267+
temp &= ~(CLKCTRL_SEL_bm);
268+
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, temp);
269+
270+
// Choose to use external crystal on XTAL32K1 and XTAL32K2 pins and enable
271+
// the clock
272+
temp = CLKCTRL.XOSC32KCTRLA;
273+
temp |= CLKCTRL_ENABLE_bm;
274+
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, temp);
275+
276+
// Wait for registers to synchronize
253277
while (RTC.PITSTATUS) {}
254278

255-
// TODO: use XOSC32K instead
256-
RTC.CLKSEL |= RTC_CLKSEL_INT32K_gc;
279+
RTC.CLKSEL |= RTC_CLKSEL_XOSC32K_gc;
257280
RTC.PITINTCTRL |= RTC_PI_bm;
258281
RTC.PITCTRLA |= RTC_PERIOD_CYC32768_gc | RTC_PITEN_bm;
259282

260-
// Now we setup the sleep mode so it is ready.
261-
SLPCTRL.CTRLA |= SLPCTRL_SMODE_PDOWN_gc | SLPCTRL_SEN_bm;
262-
263283
// The first PIT intterupt will not necessarily be at the period specified,
264284
// so we just wait until it has triggered and track the reminaing time from
265285
// there
@@ -269,13 +289,37 @@ static void enablePIT(void) {
269289

270290
static void disablePIT(void) {
271291

272-
SLPCTRL.CTRLA &= ~SLPCTRL_SEN_bm;
273-
274292
// Disable external clock and turn off RTC PIT
275-
CLKCTRL.XOSC32KCTRLA &= (~CLKCTRL_ENABLE_bm);
293+
uint8_t temp;
294+
temp = CLKCTRL.XOSC32KCTRLA;
295+
temp &= ~(CLKCTRL_ENABLE_bm);
296+
_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, temp);
297+
276298
RTC.PITCTRLA &= ~RTC_PITEN_bm;
277299
}
278300

301+
static void powerDownPeripherals(void) {
302+
303+
cell_led_state = digitalRead(LedCtrl.getLedPin(Led::CELL));
304+
con_led_state = digitalRead(LedCtrl.getLedPin(Led::CON));
305+
306+
LedCtrl.off(Led::CELL, true);
307+
LedCtrl.off(Led::CON, true);
308+
LedCtrl.off(Led::DATA, true);
309+
LedCtrl.off(Led::ERROR, true);
310+
LedCtrl.off(Led::USER, true);
311+
}
312+
313+
static void powerUpPeripherals(void) {
314+
if (cell_led_state) {
315+
LedCtrl.on(Led::CELL, true);
316+
}
317+
318+
if (con_led_state) {
319+
LedCtrl.on(Led::CON, true);
320+
}
321+
}
322+
279323
/**
280324
* Modem sleeping and CPU deep sleep.
281325
*/
@@ -289,6 +333,7 @@ static WakeUpReason regularSleep(void) {
289333
sleep_time = retrieveOperatorSleepTime();
290334

291335
if (sleep_time == 0) {
336+
Log.debugf("Got invalid sleep time: %d\r\n", sleep_time);
292337
return WakeUpReason::INVALID_SLEEP_TIME;
293338
} else {
294339
retrieved_sleep_time = true;
@@ -297,7 +342,8 @@ static WakeUpReason regularSleep(void) {
297342

298343
// The timeout here is arbitrary as we attempt to put the modem in sleep in
299344
// a loop, so we just choose 30 seconds = 30000 ms
300-
while (!attemptToEnterPowerSaveModeForModem(30000)) {}
345+
while (!attemptToEnterPowerSaveModeForModem(30000) &&
346+
millis() - start_time_ms < sleep_time * 1000) {}
301347

302348
// If we surpassed the sleep time during setting the LTE to sleep, we
303349
// don't have any more time to sleep the CPU, so just return.
@@ -360,17 +406,13 @@ static WakeUpReason deepSleep(void) {
360406
const unsigned long start_time_ms = millis();
361407

362408
Lte.end();
363-
364409
enablePIT();
365410

366411
uint32_t remaining_time_seconds =
367412
sleep_time - (uint32_t)(((millis() - start_time_ms) / 1000.0f));
368413

369414
while (remaining_time_seconds > 0) {
370415

371-
Log.debugf("Remaining time: %d \r\n", remaining_time_seconds);
372-
delay(10);
373-
374416
sleep_cpu();
375417

376418
if (pit_triggered) {
@@ -380,7 +422,6 @@ static WakeUpReason deepSleep(void) {
380422
}
381423

382424
disablePIT();
383-
384425
Lte.begin();
385426

386427
return WakeUpReason::OK;
@@ -453,12 +494,19 @@ bool LowPowerClass::begin(const SleepMultiplier sleep_multiplier,
453494
}
454495

455496
WakeUpReason LowPowerClass::sleep(void) {
497+
498+
powerDownPeripherals();
499+
SLPCTRL.CTRLA |= SLPCTRL_SMODE_PDOWN_gc | SLPCTRL_SEN_bm;
500+
456501
switch (sleep_mode) {
457502
case SleepMode::REGULAR:
458503
return regularSleep();
459504
case SleepMode::DEEP:
460505
return deepSleep();
461506
}
462507

508+
SLPCTRL.CTRLA &= ~SLPCTRL_SEN_bm;
509+
powerUpPeripherals();
510+
463511
return WakeUpReason::OK;
464512
}

src/low_power.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,17 @@ enum class SleepMultiplier {
2020

2121
enum class WakeUpReason {
2222
// Invoked if the sleep time retrieved from the operator wasn't valid
23-
INVALID_SLEEP_TIME = 4,
23+
INVALID_SLEEP_TIME = 3,
2424

2525
// Invoked if it took so long to put the modem in sleep that it wasn't time
2626
// left for the CPU to sleep. The sleep time should be considered to be
2727
// increased.
28-
MODEM_TIMEOUT = 3,
28+
MODEM_TIMEOUT = 2,
2929

3030
// The modem went out of sleep before the total time, which may happen if
3131
// e.g. the interval of needing to send MQTT heartbeat is lower than the
3232
// sleep time.
33-
AWOKEN_BY_MODEM_PREMATURELY = 2,
34-
35-
// If some unknown external interrupt caused the CPU to wake up
36-
AWOKEN_BY_EXTERNAL_EVENT = 1,
33+
AWOKEN_BY_MODEM_PREMATURELY = 1,
3734

3835
OK = 0,
3936
};

0 commit comments

Comments
 (0)