Skip to content

Commit 177244b

Browse files
committed
Add option to clear urc data and fix external interrupt logic in low power
1 parent b324413 commit 177244b

File tree

7 files changed

+70
-31
lines changed

7 files changed

+70
-31
lines changed

src/examples/low_power/low_power.ino

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,51 @@
44
#include <log.h>
55
#include <low_power.h>
66
#include <lte.h>
7+
#include <sequans_controller.h>
78

8-
void setup() {
9+
#ifdef __AVR_AVR128DB48__ // MINI
910

10-
LedCtrl.begin();
11+
#define SerialDebug Serial3
12+
13+
#else
14+
#ifdef __AVR_AVR128DB64__ // Non-Mini
15+
16+
#define SerialDebug Serial5
17+
18+
#else
19+
#error "INCOMPATIBLE_DEVICE_SELECTED"
20+
#endif
21+
#endif
22+
23+
void setup() {
1124

1225
Log.begin(115200);
13-
Log.setLogLevel(LogLevel::DEBUG);
26+
27+
LedCtrl.begin();
28+
LedCtrl.startupCycle();
1429

1530
// Configure the power save configuration, start the LTE modem and wait
1631
// until we are connected to the operator
1732
//
1833
// Here we say that we want to sleep for 30 seconds * 2 = 60 seconds each
1934
// time we invoke sleep
20-
LowPower.begin(SleepMultiplier::THIRTY_SECONDS, 2, SleepMode::DEEP);
35+
LowPower.begin(SleepMultiplier::THIRTY_SECONDS, 2, SleepMode::REGULAR);
2136
Lte.begin();
22-
37+
Log.infof("Connecting to operator");
2338
while (!Lte.isConnected()) {
24-
Log.info("Waiting for connection...\r\n");
25-
delay(2000);
39+
Log.raw(".");
40+
delay(1000);
2641
}
2742

28-
Log.info("Connected to operator!\r\n");
43+
Log.raw("\r\n");
44+
Log.infof("Connected to operator: %s\r\n", Lte.getOperator().c_str());
2945
}
3046

3147
void loop() {
3248

49+
Log.raw("\r\n");
50+
Log.info("Going to sleep...");
51+
delay(100);
3352
WakeUpReason wakeup_reason = LowPower.sleep();
3453
Log.infof("Got out of sleep with wake up reason %d, doing work...\r\n",
3554
wakeup_reason);

src/examples/sandbox/sandbox.ino

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <mcp9808.h>
1616
#include <mqtt_client.h>
1717

18+
#include <Wire.h>
19+
1820
#define HEARTBEAT_INTERVAL_MS 10000
1921

2022
// AWS defines which topic you are allowed to subscribe and publish too. This is
@@ -218,7 +220,6 @@ void decodeMessage(const char *message) {
218220

219221
void setup() {
220222
Log.begin(115200);
221-
Log.setLogLevel(LogLevel::DEBUG);
222223

223224
LedCtrl.begin();
224225
LedCtrl.startupCycle();
@@ -229,7 +230,7 @@ void setup() {
229230
Log.infof("Starting sandbox / landing page procedure. Version = %s\r\n",
230231
SANDBOX_VERSION);
231232

232-
if (Mcp9808.begin(0x18) == -1) {
233+
if (Mcp9808.begin(0x18)) {
233234
Log.error("Could not initialize the temperature sensor");
234235
}
235236

@@ -257,6 +258,8 @@ void setup() {
257258

258259
void loop() {
259260

261+
// ----------------------------------------------------------
262+
260263
if (event_flags & NETWORK_CONN_FLAG) {
261264
switch (state) {
262265
case NOT_CONNECTED:

src/low_power.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ static uint32_t retrieveOperatorSleepTime(void) {
211211
SequansController.clearReceiveBuffer();
212212
SequansController.writeCommand(AT_COMMAND_CONNECTION_STATUS);
213213

214-
char response[RESPONSE_CONNECTION_STATUS_SIZE];
214+
char response[RESPONSE_CONNECTION_STATUS_SIZE] = "";
215215
const ResponseResult response_result = SequansController.readResponse(
216216
response, RESPONSE_CONNECTION_STATUS_SIZE);
217217

@@ -227,7 +227,7 @@ static uint32_t retrieveOperatorSleepTime(void) {
227227
}
228228

229229
// Find the sleep timer token in the response
230-
char sleep_timer_token[TIMER_LENGTH];
230+
char sleep_timer_token[TIMER_LENGTH] = "";
231231
const bool found_token = SequansController.extractValueFromCommandResponse(
232232
response, TIMER_SLEEP_INDEX, sleep_timer_token, TIMER_LENGTH);
233233

@@ -336,6 +336,7 @@ static WakeUpReason regularSleep(void) {
336336
Log.debugf("Got invalid sleep time: %d\r\n", sleep_time);
337337
return WakeUpReason::INVALID_SLEEP_TIME;
338338
} else {
339+
Log.debugf("Sleep time set to: %d seconds\r\n", sleep_time);
339340
retrieved_sleep_time = true;
340341
}
341342
}
@@ -369,6 +370,12 @@ static WakeUpReason regularSleep(void) {
369370

370371
sleep_cpu();
371372

373+
// Woken up by some external interrupt
374+
if (!pit_triggered && modem_is_in_power_save) {
375+
wakeup_reason = WakeUpReason::EXTERNAL_INTERRUPT;
376+
break;
377+
}
378+
372379
// Got woken up by the PIT interrupt
373380
if (pit_triggered) {
374381
remaining_time_seconds -= 1;
@@ -385,9 +392,6 @@ static WakeUpReason regularSleep(void) {
385392
wakeup_reason = WakeUpReason::AWOKEN_BY_MODEM_PREMATURELY;
386393
break;
387394
}
388-
} else {
389-
wakeup_reason = WakeUpReason::EXTERNAL_INTERRUPT;
390-
break;
391395
}
392396
}
393397

src/low_power.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,20 @@ 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 = 3,
23+
INVALID_SLEEP_TIME = 4,
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 = 2,
28+
MODEM_TIMEOUT = 3,
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 = 1,
33+
AWOKEN_BY_MODEM_PREMATURELY = 2,
3434

3535
// External interrup caused the AVR to go out of sleep
36-
EXTERNAL_INTERRUPT,
36+
EXTERNAL_INTERRUPT = 1,
3737

3838
OK = 0,
3939
};

src/lte.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ void LteClass::begin(void) {
125125
}
126126

127127
// Enable the default callback
128-
SequansController.registerCallback(CEREG_CALLBACK, connectionStatus);
128+
SequansController.registerCallback(CEREG_CALLBACK, connectionStatus, false);
129129

130130
// This is convenient when the MCU has been issued a reset, but the lte
131131
// modem is already connected, which will be the case during development for

src/sequans_controller.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ static volatile uint16_t tx_num_elements = 0;
8888
// We keep two buffers for identifier and data so that data won't be overwritten
8989
// whilst we are looking for a new URC. In that way the data buffer will only be
9090
// overwritten if we find an URC we are looking for.
91-
static uint8_t urc_identifier_buffer[URC_IDENTIFIER_BUFFER_SIZE];
92-
static char urc_data_buffer[URC_DATA_BUFFER_SIZE];
93-
static volatile uint8_t urc_identifier_buffer_length = 0;
94-
static volatile uint8_t urc_data_buffer_length = 0;
91+
static volatile uint8_t urc_identifier_buffer[URC_IDENTIFIER_BUFFER_SIZE];
92+
static volatile char urc_data_buffer[URC_DATA_BUFFER_SIZE];
93+
static volatile uint16_t urc_identifier_buffer_length = 0;
94+
static volatile uint16_t urc_data_buffer_length = 0;
9595

9696
typedef enum {
9797
URC_PARSING_IDENTIFIER,
@@ -101,8 +101,11 @@ typedef enum {
101101

102102
static UrcParseState urc_parse_state = URC_NOT_PARSING;
103103

104-
static char urc_lookup_table[MAX_URC_CALLBACKS][URC_IDENTIFIER_BUFFER_SIZE];
105-
static uint8_t urc_lookup_table_length[MAX_URC_CALLBACKS];
104+
static volatile uint8_t urc_index = 0;
105+
static volatile char urc_lookup_table[MAX_URC_CALLBACKS]
106+
[URC_IDENTIFIER_BUFFER_SIZE];
107+
static volatile uint8_t urc_lookup_table_length[MAX_URC_CALLBACKS];
108+
static volatile bool urc_lookup_table_clear_data[MAX_URC_CALLBACKS];
106109
void (*urc_callbacks[MAX_URC_CALLBACKS])(char *);
107110

108111
// Used to keep a pointer to the URC we are processing and found to be matching,
@@ -215,6 +218,8 @@ ISR(USART1_RXC_vect) {
215218
if (memcmp(urc_identifier_buffer,
216219
urc_lookup_table[i],
217220
urc_lookup_table_length[i]) == 0) {
221+
222+
urc_index = i;
218223
urc_current_callback = urc_callbacks[i];
219224
urc_parse_state = URC_PARSING_DATA;
220225

@@ -243,9 +248,11 @@ ISR(USART1_RXC_vect) {
243248
if (urc_current_callback != NULL) {
244249
// Clear the buffer for the URC since we're passing the data
245250
// with the URC callback
246-
rx_head_index =
247-
(rx_head_index - urc_data_buffer_length) & RX_BUFFER_MASK;
248-
rx_num_elements -= urc_data_buffer_length;
251+
if (urc_lookup_table_clear_data[urc_index]) {
252+
rx_head_index = (rx_head_index - urc_data_buffer_length) &
253+
RX_BUFFER_MASK;
254+
rx_num_elements -= urc_data_buffer_length;
255+
}
249256

250257
urc_current_callback(urc_data_buffer);
251258
urc_current_callback = NULL;
@@ -623,14 +630,16 @@ bool SequansControllerClass::extractValueFromCommandResponse(
623630
}
624631

625632
bool SequansControllerClass::registerCallback(const char *urc_identifier,
626-
void (*urc_callback)(char *)) {
633+
void (*urc_callback)(char *),
634+
const bool clear_data) {
627635

628636
// Check if we can override first
629637
uint8_t urc_identifier_length = strlen(urc_identifier);
630638
for (uint8_t i = 0; i < MAX_URC_CALLBACKS; i++) {
631639
if (urc_lookup_table_length[i] == urc_identifier_length &&
632640
strcmp(urc_identifier, urc_lookup_table[i]) == 0) {
633641
urc_callbacks[i] = urc_callback;
642+
urc_lookup_table_clear_data[i] = clear_data;
634643
return true;
635644
}
636645
}
@@ -641,6 +650,7 @@ bool SequansControllerClass::registerCallback(const char *urc_identifier,
641650
strcpy(urc_lookup_table[i], urc_identifier);
642651
urc_lookup_table_length[i] = strlen(urc_identifier);
643652
urc_callbacks[i] = urc_callback;
653+
urc_lookup_table_clear_data[i] = clear_data;
644654
return true;
645655
}
646656
}

src/sequans_controller.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,15 @@ class SequansControllerClass {
170170
* registration.
171171
*
172172
* @param urc_callback Callback with URC data as argument.
173+
* @param clear_data Whether the UART RX buffer will be cleared of the URC
174+
* or not. This is to save space in the buffer.
173175
*
174176
* @return true if we didn't surpass the fixed amount of URC callbacks
175177
* allowed for registration.
176178
*/
177179
bool registerCallback(const char *urc_identifier,
178-
void (*urc_callback)(char *));
180+
void (*urc_callback)(char *),
181+
const bool clear_data = true);
179182

180183
/**
181184
* @brief Unregister callback for a given URC identifier.

0 commit comments

Comments
 (0)