diff --git a/.gitignore b/.gitignore index 50d898c..ef58455 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /nbproject/private/ +/build /avrrfm.elf /avrrfm.hex /avrrfm.lst diff --git a/avrrfm.c b/avrrfm.c index 658bfb8..45a0aed 100644 --- a/avrrfm.c +++ b/avrrfm.c @@ -34,6 +34,9 @@ #include "dejavu.h" #include "unifont.h" +#define TRANSMIT_FAST 4 // 4 ~ 32 seconds +#define TRANSMIT_SLOW 38 // 38 ~ 5 minutes + #define LABEL_OFFSET 10 #define BLACK 0x0000 #define RED 0xf800 @@ -47,6 +50,10 @@ #define RECEIVER 1 #endif +static volatile uint8_t watchdogInts = 0; +static uint8_t measureInts = TRANSMIT_FAST; +static uint8_t timeoutCount = 0; + /* Temp. label coordinates */ static x_t xl = 0; static y_t yl = 0; @@ -58,7 +65,7 @@ * Called when the watchdog barks to wake up the transmitter. */ ISR(WDT_vect) { - barkRadio(); + watchdogInts++; } /** @@ -69,6 +76,13 @@ } /** + * Called when an INT0 interrupt occurs. + */ +ISR(INT0_vect) { + intRadio(); +} + +/** * Sets up the pins. */ static void initPins(void) { @@ -241,7 +255,7 @@ * @param flags */ static void handlePayload(PayloadFlags flags) { - uint8_t rssi = readRssi(); + uint8_t rssi = getRssi(); Temperature temp = readTemp(); // communicate RSSI back to transmitter @@ -254,15 +268,21 @@ /** * Waits for a response from the receiver with timeout. + * + * @return true if timeout occurred, false otherwise */ -static void waitResponse(void) { +static bool waitResponse(void) { uint8_t response[1]; int8_t len = receivePayload(response, sizeof (response), true); if (len > 0) { // receiver RSSI int8_t rssi = divRoundNearest(response[0], 2); setOutputPower(rssi); + + return false; } + + return true; } /** @@ -339,7 +359,9 @@ // _delay_ms(1000); if (!RECEIVER) { - if (wouldTransmit()) { + if (watchdogInts % measureInts == 0) { + watchdogInts = 0; + enableSPI(); wakeTSens(); wakeRadio(); @@ -347,7 +369,16 @@ transmitData(); } else { transmitTemp(NODE1); - waitResponse(); + bool timeout = waitResponse(); + if (timeout) { + if (++timeoutCount > MAX_TIMEOUTS) { + measureInts = TRANSMIT_SLOW; + timeoutCount = 0; + } + } else { + timeoutCount = 0; + measureInts = TRANSMIT_FAST; + } } sleepTSens(); sleepRadio(); diff --git a/rfm69.c b/rfm69.c index f751713..66738ca 100644 --- a/rfm69.c +++ b/rfm69.c @@ -10,12 +10,8 @@ static volatile uint8_t irqFlags1 = 0; static volatile uint8_t irqFlags2 = 0; - -static uint8_t watchdogInts = 0; -static uint8_t measureInts = TRANSMIT_FAST; -static uint8_t timeoutInts = 0; -static uint8_t timeoutCount = 0; -static bool timeoutEnabled = false; +static volatile uint8_t timeoutInts = 0; +static volatile bool timeoutEnabled = false; /** * Selects the radio to talk to via SPI. @@ -89,19 +85,6 @@ */ static void timeout(void) { irqFlags1 |= (1 << 2); - if (++timeoutCount > MAX_TIMEOUTS) { - measureInts = TRANSMIT_SLOW; - timeoutCount = 0; - } -} - -/** - * Reads interrupt flags when a radio interrupt occurs. - */ -ISR(INT0_vect) { - irqFlags1 = regRead(IRQ_FLAGS1); - irqFlags2 = regRead(IRQ_FLAGS2); - // printString("irq\r\n"); } void initRadio(uint64_t freq, uint8_t node) { @@ -213,33 +196,12 @@ printString("Radio init done\r\n"); } -void setNodeAddress(uint8_t address) { - regWrite(NODE_ADDR, address); -} - -void setOutputPower(uint8_t rssi) { - uint8_t pa = 0x40; // -18 dBm with PA1 - // adjust power from -2 to +13 dBm - pa += min(max(rssi - 69, PA_MIN), PA_MAX); - regWrite(PA_LEVEL, pa); -} - -uint8_t getOutputPower(void) { - return regRead(PA_LEVEL); -} - -void barkRadio(void) { - watchdogInts++; -} - -bool wouldTransmit(void) { - if (watchdogInts % measureInts == 0) { - watchdogInts = 0; - - return true; - } - - return false; +/** + * Reads interrupt flags when a radio interrupt occurs. + */ +void intRadio(void) { + irqFlags1 = regRead(IRQ_FLAGS1); + irqFlags2 = regRead(IRQ_FLAGS2); } void timeRadio(void) { @@ -259,6 +221,25 @@ _delay_ms(5); } +void setNodeAddress(uint8_t address) { + regWrite(NODE_ADDR, address); +} + +uint8_t getRssi(void) { + return regRead(RSSI_VALUE); +} + +void setOutputPower(uint8_t rssi) { + uint8_t pa = 0x40; // -18 dBm with PA1 + // adjust power from -2 to +13 dBm + pa += min(max(rssi - 69, PA_MIN), PA_MAX); + regWrite(PA_LEVEL, pa); +} + +uint8_t getOutputPower(void) { + return regRead(PA_LEVEL); +} + void startReceive(void) { // get "PayloadReady" on DIO0 regWrite(DIO_MAP1, 0x40); @@ -266,10 +247,6 @@ setMode(MODE_RX); } -uint8_t readRssi(void) { - return regRead(RSSI_VALUE); -} - PayloadFlags payloadReady(void) { PayloadFlags flags = {.ready = false, .crc = false}; if (irqFlags2 & (1 << 2)) { @@ -311,8 +288,6 @@ clearIrqFlags(); if (ready) { timeoutEnable(false); - timeoutCount = 0; - measureInts = TRANSMIT_FAST; } setMode(MODE_STDBY); diff --git a/rfm69.h b/rfm69.h index bb470e2..1f87026 100644 --- a/rfm69.h +++ b/rfm69.h @@ -81,9 +81,7 @@ #define F_STEP 6103515625ULL #define CAST_ADDRESS 0x84 -#define TRANSMIT_FAST 4 // 4 ~ 32 seconds -#define TRANSMIT_SLOW 38 // 38 ~ 5 minutes -#define TIMEOUT_INTS 3 // about 100 milliseconds +#define TIMEOUT_INTS 3 // about 100 milliseconds @ 30 Hz #define MAX_TIMEOUTS 9 // slow down tx attempts after so many timeouts /** @@ -93,6 +91,29 @@ void initRadio(uint64_t freq, uint8_t node); /** + * Should be called when a radio interrupt occurred, i.e. 'PayloadReady'. + */ +void intRadio(void); + +/** + * Gives a timer pulse to the radio. Used to time-out blocking functions, + * i.e. transmitter waiting for a response from the receiver. + * TIMEOUT_INTS must be adjusted according to the frequency with that + * this function is called. + */ +void timeRadio(void); + +/** + * Shuts down the radio. + */ +void sleepRadio(void); + +/** + * Wakes up the radio. + */ +void wakeRadio(void); + +/** * Sets the node address. * * @param address @@ -100,6 +121,13 @@ void setNodeAddress(uint8_t address); /** + * Returns the current RSSI value. + * + * @return rssi value + */ +uint8_t getRssi(void); + +/** * Sets the output power based on the given receiver RSSI. * * @param rssi @@ -114,45 +142,11 @@ uint8_t getOutputPower(void); /** - * Gives a watchdog "wakeup" pulse to the radio. - */ -void barkRadio(void); - -/** - * Returns true if the transmitter would actually transmit. - * - * @return transmit or not - */ -bool wouldTransmit(void); - -/** - * Gives a timer pulse to the radio. - */ -void timeRadio(void); - -/** - * Shuts down the radio. - */ -void sleepRadio(void); - -/** - * Wakes up the radio. - */ -void wakeRadio(void); - -/** * Sets the radio to receive mode and maps "PayloadReady" to DIO0. */ void startReceive(void); /** - * Returns the current RSSI value. - * - * @return rssi value - */ -uint8_t readRssi(void); - -/** * Returns true if a "PayloadReady" interrupt arrived and clears the * interrupt state. * diff --git a/sdcard.c b/sdcard.c index f791d85..aecdf5f 100644 --- a/sdcard.c +++ b/sdcard.c @@ -200,12 +200,12 @@ // CMD0 - go to idle state response[0] = sendIdle(); - if (response[0] > 0x01) { + if (response[0] != 0x01) { // retry solves failure possibly caused by another component // on the same SPI bus response[0] = sendIdle(); } - if (response[0] > 0x01) { + if (response[0] != 0x01) { printString("SD card error 0\r\n"); return false; } diff --git a/types.h b/types.h index 6378677..f15e271 100644 --- a/types.h +++ b/types.h @@ -55,6 +55,11 @@ } Temperature; /** + * Pointer to a function that takes no argument and returns void. + */ +typedef void (*Function)(void); + +/** * Pointer to a function that takes an array of bytes * and returns a boolean. */