Refactor firmware for clarity; no functional changes
- main.c: file-header comment describing the hardware and operation, logic split into named phases (sleep_until_interrupt, wake_peripheral_rails, take_counts_snapshot, send_wheel_counts_report, handle_minute_alarm, init_all_hardware); shared state renamed to say what it is and made static. - rfm69.c: reorganized into six labeled sections; cond_1/2/3 and hash scratch globals replaced by a reply_acknowledges() helper with clear locals; packet layout and every init register write documented. - LOG() macro (compiled out when DO_UART is off) replaces the #if DO_UART blocks that obscured the logic. - Drivers: file-header comments; named RTC_REG_*/RTC_ALM_MASK_BIT constants; EEPROM spool scheme documented; ADC_CHANNEL_BANDGAP named; repeated pin if/else helpers collapsed to SET_PIN_TO(). - Removed unused globals/buffers and commented-out code; ran clang-format with the project style. Register writes and radio protocol are byte-identical. Builds clean under -Wall -Wextra on gnu17 and c23; flash 13028 -> 12830 B, static RAM 1038 -> 999 B. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YVJKatfeMJjAmuH9KYiLuv
This commit is contained in:
+249
-206
@@ -1,3 +1,24 @@
|
||||
// Wheel revolution counter
|
||||
// ========================
|
||||
//
|
||||
// Battery-powered node that counts exercise-wheel revolutions and reports them
|
||||
// over an RFM69 radio.
|
||||
//
|
||||
// Hardware (ATmega328PB @ 8 MHz):
|
||||
// PD3/INT1 reed switch, closes to ground once per wheel revolution
|
||||
// PD2/INT0 MAX31329 RTC alarm output (open drain), fires once per minute
|
||||
// SPI1 RFM69 packet radio + M95128 EEPROM (used as a retry spool)
|
||||
// I2C MAX31329 RTC + ST25DV NFC tag (holds "<name>,<diameter>")
|
||||
//
|
||||
// Operation:
|
||||
// 1. Sleep in power-down. A reed pulse increments the count for the
|
||||
// current minute slot; an RTC alarm advances to the next slot.
|
||||
// 2. Every SEND_INTERVAL minutes, pack the per-minute counts into one
|
||||
// radio packet (name, diameter, battery, timestamp, counts, hash).
|
||||
// 3. If the base station does not acknowledge, spool the packet to
|
||||
// EEPROM; whenever a live packet is acknowledged, retry one spooled
|
||||
// packet.
|
||||
|
||||
#include "adc.h"
|
||||
#include "defines.h"
|
||||
#include "interrupts.h"
|
||||
@@ -8,20 +29,18 @@
|
||||
#include "rfm69.h"
|
||||
#include "st25dv.h"
|
||||
#include "states.h"
|
||||
|
||||
#if DO_UART
|
||||
#include "uart.h"
|
||||
#endif
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/power.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <util/atomic.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
// How many minute slots are collected before a packet is sent. ITERATING is a
|
||||
// bench-test mode that sends every minute (and lets the reed switch stand in
|
||||
// for the minute alarm).
|
||||
#if ITERATING
|
||||
#define SEND_INTERVAL 1
|
||||
#else
|
||||
@@ -30,59 +49,74 @@
|
||||
|
||||
#define WHEEL_COUNT_SLOTS 15
|
||||
|
||||
// Erased EEPROM reads back as 0xFF; anything else is a real page count.
|
||||
// Erased EEPROM reads back as 0xFF; anything else is a real spool depth.
|
||||
#define EEPROM_LAST_PAGE_UNINIT 0xFF
|
||||
|
||||
uint16_t self_value;
|
||||
volatile uint8_t is_debouncing = 0;
|
||||
volatile bool increment_minute_index = false;
|
||||
volatile bool increment_wheel_count = false;
|
||||
volatile uint8_t index_wheel_count = 0;
|
||||
volatile uint16_t total_wheel_counts[WHEEL_COUNT_SLOTS];
|
||||
// ---------------------------------------------------------------------------
|
||||
// State shared with the interrupt handlers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
RTC_RFM69_STATUS rtc_rfm69_status;
|
||||
static volatile bool minute_alarm_fired = false; // Set by INT0, consumed by main loop
|
||||
static volatile bool reed_is_debouncing = false; // Set by INT1, cleared by WDT expiry
|
||||
static volatile uint8_t minute_slot = 0; // Which wheel_counts[] slot is being filled
|
||||
static volatile uint16_t wheel_counts[WHEEL_COUNT_SLOTS]; // Revolutions per minute slot
|
||||
|
||||
ISR(INT0_vect) {
|
||||
// The RTC holds INTB low until its flag registers are read, and this is a
|
||||
// level-triggered interrupt, so mask it here and let main re-arm it once
|
||||
// the RTC has released the line.
|
||||
// Whether we ever got a valid timestamp from the base station
|
||||
static RTC_RFM69_STATUS time_sync_status;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Interrupt handlers
|
||||
//
|
||||
// Both external interrupts are low-level triggered (the only mode that can
|
||||
// wake the MCU from power-down), so each handler must mask itself while its
|
||||
// source still holds the line low. See interrupts.c.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// RTC minute alarm. The RTC holds INTB low until main reads its flag
|
||||
// registers, so mask INT0 here; main re-arms it after clearing the flags.
|
||||
ISR(INT0_vect)
|
||||
{
|
||||
EIMSK &= ~(1 << INT0);
|
||||
#if DO_UART
|
||||
uart_sendString("\t\t\t\tMINUTE INTERRUPT\n");
|
||||
#endif
|
||||
increment_minute_index = true;
|
||||
minute_alarm_fired = true;
|
||||
LOG("\t\t\t\tMINUTE INTERRUPT\n");
|
||||
}
|
||||
|
||||
ISR(INT1_vect) {
|
||||
|
||||
// Reed switch: one revolution. The magnet holds the reed closed far longer
|
||||
// than one bounce, so mask INT1 for a WDT-timed debounce window; the WDT
|
||||
// handler below re-arms it.
|
||||
ISR(INT1_vect)
|
||||
{
|
||||
#if ITERATING
|
||||
increment_minute_index = true;
|
||||
minute_alarm_fired = true;
|
||||
#endif
|
||||
LOG("\t\t\t\tREED INTERRUPT\n");
|
||||
|
||||
#if DO_UART
|
||||
uart_sendString("\t\t\t\tREED INTERRUPT\n");
|
||||
#endif
|
||||
|
||||
if (!is_debouncing) {
|
||||
if (index_wheel_count < WHEEL_COUNT_SLOTS) {
|
||||
total_wheel_counts[index_wheel_count]++;
|
||||
if (!reed_is_debouncing) {
|
||||
if (minute_slot < WHEEL_COUNT_SLOTS) {
|
||||
wheel_counts[minute_slot]++;
|
||||
}
|
||||
is_debouncing = 1;
|
||||
// Mask INT1 for the debounce window: the magnet holds the reed closed
|
||||
// (and the pin low) for far longer than one revolution's worth of
|
||||
// bounce, and a level-triggered interrupt would retrigger continuously.
|
||||
reed_is_debouncing = true;
|
||||
EIMSK &= ~(1 << INT1);
|
||||
wdt_isr_enable();
|
||||
}
|
||||
}
|
||||
|
||||
ISR(WDT_vect) {
|
||||
is_debouncing = 0;
|
||||
// Debounce window over: allow the next reed pulse to count.
|
||||
ISR(WDT_vect)
|
||||
{
|
||||
reed_is_debouncing = false;
|
||||
wdt_isr_disable();
|
||||
reed_interrupt_enable();
|
||||
}
|
||||
|
||||
void start_sleeping(void) {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Power management
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Cut power to every peripheral and enter power-down until the reed switch,
|
||||
// the RTC alarm, or the debounce watchdog wakes us.
|
||||
static void sleep_until_interrupt(void)
|
||||
{
|
||||
spi_eeprom_select(false);
|
||||
spi_rfm69_select(false);
|
||||
rfid_set_low_power_down(true);
|
||||
@@ -92,13 +126,13 @@ void start_sleeping(void) {
|
||||
|
||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
||||
|
||||
// avr-libc sleep idiom: test for pending work with interrupts off, and
|
||||
// sei() only immediately before sleep_cpu() (the next instruction always
|
||||
// executes before any pending interrupt), so an alarm that fired while the
|
||||
// rails were dropping cannot be slept through. sleep_bod_disable() is a
|
||||
// timed 3-cycle sequence and must sit directly before sleep_cpu().
|
||||
cli();
|
||||
// Don't sleep through work that arrived while we were dropping the rails.
|
||||
// Testing the flag with interrupts off, then sei() immediately before
|
||||
// sleep_cpu(), is the avr-libc idiom that closes that race -- and
|
||||
// sleep_bod_disable() is a timed sequence, so it belongs here and not
|
||||
// before sleep_enable() where it had no effect at all.
|
||||
if (!increment_minute_index) {
|
||||
if (!minute_alarm_fired) {
|
||||
sleep_enable();
|
||||
sleep_bod_disable();
|
||||
sei();
|
||||
@@ -108,62 +142,168 @@ void start_sleeping(void) {
|
||||
sei();
|
||||
}
|
||||
|
||||
uint16_t get_battery_reading(void) {
|
||||
adc_Enable();
|
||||
adc_GetConversion(14);
|
||||
adc_GetConversion(14);
|
||||
self_value = adc_GetConversion(14);
|
||||
adc_Disable();
|
||||
return self_value;
|
||||
// Restore the supplies that sleep_until_interrupt() dropped. Everything on the
|
||||
// I2C bus is dead until this runs.
|
||||
static void wake_peripheral_rails(void)
|
||||
{
|
||||
ldo_set_state(true);
|
||||
rfid_set_i2c_power(true);
|
||||
_delay_ms(1);
|
||||
}
|
||||
|
||||
// i2c Addresses
|
||||
// ---------------------------------------------------------------------------
|
||||
// Measurement helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// RTC
|
||||
// 0x68 (0xD0 W) (0xD1 R)
|
||||
// Battery level via the internal 1.1 V bandgap: the first conversions after
|
||||
// enabling the ADC read low, so take three and keep the last.
|
||||
static uint16_t read_battery_level(void)
|
||||
{
|
||||
adc_Enable();
|
||||
adc_GetConversion(ADC_CHANNEL_BANDGAP);
|
||||
adc_GetConversion(ADC_CHANNEL_BANDGAP);
|
||||
uint16_t level = adc_GetConversion(ADC_CHANNEL_BANDGAP);
|
||||
adc_Disable();
|
||||
return level;
|
||||
}
|
||||
|
||||
// NFC
|
||||
// 0x2D (0x5A W) (0x5B R)
|
||||
// 0x53 (0xA6 W) (0xA7 R)
|
||||
// 0x57 (0xAE W) (0xAF R)
|
||||
// Atomically hand out the collected counts and start the next collection
|
||||
// period, so a reed pulse landing mid-copy is neither lost nor double-counted.
|
||||
static void take_counts_snapshot(uint16_t snapshot[WHEEL_COUNT_SLOTS])
|
||||
{
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
||||
{
|
||||
for (uint8_t c = 0; c < WHEEL_COUNT_SLOTS; c++) {
|
||||
snapshot[c] = wheel_counts[c];
|
||||
wheel_counts[c] = 0;
|
||||
}
|
||||
minute_slot = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Radio reporting
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Build and send the periodic counts packet. Unacknowledged packets go to the
|
||||
// EEPROM spool; each acknowledged one buys a retry of one spooled packet.
|
||||
static void send_wheel_counts_report(void)
|
||||
{
|
||||
rfm69_init();
|
||||
rfid_set_low_power_down(false);
|
||||
_delay_ms(1);
|
||||
|
||||
// Re-read the tag each period so a renamed nugget takes effect without a
|
||||
// reset.
|
||||
IDENTIFIER = get_nugget_data();
|
||||
|
||||
if (time_sync_status == RTC_RFM69_SET_TIME_FAILED) {
|
||||
time_sync_status = set_time_from_rfm69(IDENTIFIER);
|
||||
}
|
||||
|
||||
uint16_t counts_snapshot[WHEEL_COUNT_SLOTS];
|
||||
take_counts_snapshot(counts_snapshot);
|
||||
|
||||
reset_txrx_struct(&TX_DATA);
|
||||
TX_DATA = generate_wheel_counts_message(
|
||||
IDENTIFIER, rtc_read_time(), read_battery_level(), counts_snapshot);
|
||||
LOG("TX DATA Sent\n");
|
||||
#if DO_UART
|
||||
uart_print_tx_rx_data(TX_DATA);
|
||||
#endif
|
||||
|
||||
DATA_SEND_STATUS result = send_message(TX_DATA);
|
||||
if (result == DATA_NOT_SENT) {
|
||||
LOG(" TX DATA not sent, writing to SPI\n");
|
||||
write_struct_to_last_page(TX_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
// The base station is listening -- use the chance to drain one packet from
|
||||
// the spool.
|
||||
if (get_last_page() > 0) {
|
||||
reset_txrx_struct(&TX_DATA);
|
||||
TX_DATA = read_struct_last_page();
|
||||
TX_DATA.flags = MSG_RESENT_COUNTS;
|
||||
_delay_ms(250);
|
||||
|
||||
result = send_message(TX_DATA);
|
||||
LOG("TX DATA From SPI Memory\n");
|
||||
#if DO_UART
|
||||
uart_print_tx_rx_data(TX_DATA);
|
||||
#endif
|
||||
|
||||
// Only drop the spooled page once it is actually acknowledged;
|
||||
// deleting on failure would lose the data.
|
||||
if (result == DATA_SEND_SUCCESS) {
|
||||
delete_last_page();
|
||||
} else {
|
||||
LOG(" SPI not sent\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// One RTC alarm has fired: clear it, advance the minute slot, and send a
|
||||
// report if a full period has been collected.
|
||||
static void handle_minute_alarm(void)
|
||||
{
|
||||
LOG("In minute index\n");
|
||||
|
||||
uint8_t slots_filled;
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
||||
{
|
||||
if (minute_slot < WHEEL_COUNT_SLOTS) {
|
||||
minute_slot += 1;
|
||||
}
|
||||
slots_filled = minute_slot;
|
||||
}
|
||||
|
||||
wake_peripheral_rails();
|
||||
|
||||
// Reading the RTC flag registers releases the (level-triggered) INTB line,
|
||||
// after which INT0 can safely be re-armed.
|
||||
rtc_read_interrupt_register();
|
||||
rtc_read_status_register();
|
||||
minute_interrupt_enable();
|
||||
|
||||
if (slots_filled >= SEND_INTERVAL) {
|
||||
send_wheel_counts_report();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Start-up
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void init_all_hardware(void)
|
||||
{
|
||||
ldo_set_state(true);
|
||||
_delay_ms(10);
|
||||
init_pins();
|
||||
|
||||
#if DO_UART
|
||||
uart_init();
|
||||
uart_sendString("---- STARTING ----\n");
|
||||
LOG("---- STARTING ----\n");
|
||||
uart_wait_until_sent();
|
||||
#endif
|
||||
|
||||
i2c_init();
|
||||
|
||||
init_spi();
|
||||
adc_Initialize();
|
||||
|
||||
|
||||
set_up_reed_interrupt();
|
||||
set_up_minute_interrupt();
|
||||
#if DO_UART
|
||||
uart_sendString("Set up AVR interrupts\n");
|
||||
#endif
|
||||
LOG("Set up AVR interrupts\n");
|
||||
|
||||
rtc_set_per_minute_alarm();
|
||||
rtc_set_alarm_config();
|
||||
rtc_enable_interrupts();
|
||||
rtc_read_interrupt_register();
|
||||
rtc_read_interrupt_register(); // Clear any alarm already pending
|
||||
rtc_read_status_register();
|
||||
#if DO_UART
|
||||
uart_sendString("Set up RTC interrupts\n");
|
||||
#endif
|
||||
|
||||
|
||||
LOG("Set up RTC interrupts\n");
|
||||
|
||||
rfm69_init();
|
||||
#if DO_UART
|
||||
uart_sendString("Initialized RFM69\n");
|
||||
#endif
|
||||
LOG("Initialized RFM69\n");
|
||||
|
||||
// Only initialise the spool pointer when it has never been written --
|
||||
// clearing it unconditionally would discard every unsent message across a
|
||||
@@ -171,157 +311,60 @@ int main(void) {
|
||||
if (get_last_page() == EEPROM_LAST_PAGE_UNINIT) {
|
||||
write_last_page_value(0);
|
||||
}
|
||||
#if DO_UART
|
||||
uart_sendString("Set up last page value for SPI flash\n");
|
||||
#endif
|
||||
LOG("Set up last page value for SPI flash\n");
|
||||
}
|
||||
|
||||
for (uint8_t c = 0; c < WHEEL_COUNT_SLOTS; c++) {
|
||||
total_wheel_counts[c] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Get the nugget's name and wheel diameter
|
||||
IDENTIFIER = get_nugget_data();
|
||||
#if DO_UART
|
||||
uart_sendString("Got nugget data from RFID\n");
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Request time from radio
|
||||
rtc_rfm69_status = set_time_from_rfm69(IDENTIFIER);
|
||||
if (rtc_rfm69_status == RTC_RFM69_SET_TIME_SUCCESS) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
led_1_set_state(true);
|
||||
// Five long blinks for a successful time sync, five short ones for a failure.
|
||||
static void blink_time_sync_result(bool success)
|
||||
{
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
led_1_set_state(true);
|
||||
if (success) {
|
||||
_delay_ms(90);
|
||||
led_1_set_state(false);
|
||||
} else {
|
||||
_delay_ms(10);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
led_1_set_state(true);
|
||||
led_1_set_state(false);
|
||||
if (success) {
|
||||
_delay_ms(10);
|
||||
led_1_set_state(false);
|
||||
} else {
|
||||
_delay_ms(90);
|
||||
}
|
||||
}
|
||||
#if DO_UART
|
||||
if (rtc_rfm69_status == RTC_RFM69_SET_TIME_FAILED) {
|
||||
uart_sendString("Failed to get time \n");
|
||||
} else {
|
||||
uart_sendString("Success in get time \n");
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
int main(void)
|
||||
{
|
||||
init_all_hardware();
|
||||
|
||||
for (uint8_t c = 0; c < WHEEL_COUNT_SLOTS; c++) {
|
||||
wheel_counts[c] = 0;
|
||||
}
|
||||
|
||||
get_battery_reading();
|
||||
while (1) {
|
||||
// The nugget's name and wheel diameter live on the NFC tag
|
||||
IDENTIFIER = get_nugget_data();
|
||||
LOG("Got nugget data from RFID\n");
|
||||
|
||||
// Ask the base station for the current time and load it into the RTC
|
||||
time_sync_status = set_time_from_rfm69(IDENTIFIER);
|
||||
blink_time_sync_result(time_sync_status == RTC_RFM69_SET_TIME_SUCCESS);
|
||||
LOG(time_sync_status == RTC_RFM69_SET_TIME_SUCCESS ? "Success in get time \n"
|
||||
: "Failed to get time \n");
|
||||
|
||||
spi_rfm69_select(false);
|
||||
spi_eeprom_select(false);
|
||||
read_battery_level(); // Throwaway read to settle the ADC path
|
||||
|
||||
start_sleeping();
|
||||
while (1) {
|
||||
sleep_until_interrupt();
|
||||
|
||||
// Short critical sections around the shared variables only. The old
|
||||
// blanket cli() stayed in force through the whole radio/EEPROM
|
||||
// sequence, so every reed pulse in that multi-second window was lost.
|
||||
bool minute_elapsed;
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
minute_elapsed = increment_minute_index;
|
||||
increment_minute_index = false;
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
||||
{
|
||||
minute_elapsed = minute_alarm_fired;
|
||||
minute_alarm_fired = false;
|
||||
}
|
||||
|
||||
if (minute_elapsed) {
|
||||
#if DO_UART
|
||||
uart_sendString("In minute index\n");
|
||||
#endif
|
||||
uint8_t slot;
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
if (index_wheel_count < WHEEL_COUNT_SLOTS) {
|
||||
index_wheel_count += 1;
|
||||
}
|
||||
slot = index_wheel_count;
|
||||
}
|
||||
|
||||
// The I2C rail has to be back up before we touch the RTC: sleeping
|
||||
// dropped both the LDO and the tag's supply.
|
||||
ldo_set_state(true);
|
||||
rfid_set_i2c_power(true);
|
||||
_delay_ms(1);
|
||||
|
||||
rtc_read_interrupt_register();
|
||||
rtc_read_status_register();
|
||||
|
||||
// Reading the flags releases INTB, so INT0 can safely be re-armed.
|
||||
minute_interrupt_enable();
|
||||
|
||||
if (slot >= SEND_INTERVAL) {
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { index_wheel_count = 0; }
|
||||
rfm69_init();
|
||||
rfid_set_low_power_down(false);
|
||||
_delay_ms(1);
|
||||
IDENTIFIER = get_nugget_data();
|
||||
|
||||
// Request time from radio if we don't have a good time stamp yet
|
||||
if (rtc_rfm69_status == RTC_RFM69_SET_TIME_FAILED) {
|
||||
rtc_rfm69_status = set_time_from_rfm69(IDENTIFIER);
|
||||
}
|
||||
|
||||
// Snapshot and clear the counters in one critical section so
|
||||
// a reed pulse landing mid-packet is neither lost nor double
|
||||
// counted.
|
||||
uint16_t counts_snapshot[WHEEL_COUNT_SLOTS];
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
for (uint8_t c = 0; c < WHEEL_COUNT_SLOTS; c++) {
|
||||
counts_snapshot[c] = total_wheel_counts[c];
|
||||
total_wheel_counts[c] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate wheel counts message
|
||||
reset_txrx_struct(&TX_DATA);
|
||||
TX_DATA = generate_wheel_counts_message(
|
||||
IDENTIFIER, rtc_read_time(), get_battery_reading(), counts_snapshot);
|
||||
|
||||
#if DO_UART
|
||||
uart_sendString("TX DATA Sent\n");
|
||||
uart_print_tx_rx_data(TX_DATA);
|
||||
#endif
|
||||
|
||||
|
||||
DATA_SEND_STATUS result = send_message(TX_DATA);
|
||||
if (result == DATA_NOT_SENT) {
|
||||
#if DO_UART
|
||||
uart_sendString(" TX DATA not sent, writing to SPI\n");
|
||||
#endif
|
||||
write_struct_to_last_page(TX_DATA);
|
||||
}
|
||||
|
||||
if ((result == DATA_SEND_SUCCESS) && (get_last_page() > 0)) {
|
||||
reset_txrx_struct(&TX_DATA);
|
||||
TX_DATA = read_struct_last_page();
|
||||
TX_DATA.flags = MSG_RESENT_COUNTS;
|
||||
_delay_ms(250);
|
||||
result = send_message(TX_DATA);
|
||||
#if DO_UART
|
||||
uart_sendString("TX DATA From SPI Memory\n");
|
||||
uart_print_tx_rx_data(TX_DATA);
|
||||
#endif
|
||||
// Only drop the spooled page once it is actually
|
||||
// acknowledged, otherwise a failed retry loses the data.
|
||||
if (result == DATA_SEND_SUCCESS) {
|
||||
delete_last_page();
|
||||
}
|
||||
#if DO_UART
|
||||
else {
|
||||
uart_sendString(" SPI not sent\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
handle_minute_alarm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user