diff --git a/librfm.c b/librfm.c index 2e6436f..f4715f9 100644 --- a/librfm.c +++ b/librfm.c @@ -10,8 +10,6 @@ static volatile uint8_t irqFlags1 = 0; static volatile uint8_t irqFlags2 = 0; -static volatile uint8_t timeoutInts = 0; -static volatile bool timeoutEnabled = false; /** * Writes the given value to the given register. @@ -57,20 +55,21 @@ } /** - * Enables timeout (sets timeout interrupt flag on expiration). + * Enables or disables timeouts. * * @param enable */ static void timeoutEnable(bool enable) { - timeoutEnabled = enable; - if (!enable) timeoutInts = 0; -} - -/** - * Times out the current operation. - */ -static void timeout(void) { - irqFlags1 |= (1 << 2); + if (enable) { + // get "Timeout" on DIO4 (default) + regWrite(DIO_MAP2, 0x00); + // both sum up to about 100 ms + regWrite(RX_TO_RSSI, 0x1f); + regWrite(RX_TO_PRDY, 0x1f); + } else { + regWrite(RX_TO_RSSI, 0x00); + regWrite(RX_TO_PRDY, 0x00); + } } void rfmInit(uint64_t freq, uint8_t node) { @@ -135,7 +134,7 @@ // Preamble size regWrite(PREAMB_MSB, 0x00); - regWrite(PREAMB_LSB, 0x0f); + regWrite(PREAMB_LSB, 0x03); // turn off CLKOUT (not used) regWrite(DIO_MAP2, 0x07); @@ -183,21 +182,11 @@ // printString("Radio init done\r\n"); } -/** - * Reads interrupt flags when a radio interrupt occurs. - */ -void rfmInt(void) { +void rfmIrq(void) { irqFlags1 = regRead(IRQ_FLAGS1); irqFlags2 = regRead(IRQ_FLAGS2); } -void rfmTimer(void) { - if (timeoutEnabled && timeoutInts++ >= TIMEOUT_INTS) { - timeoutEnable(false); - timeout(); - } -} - void rfmSleep(void) { setMode(MODE_SLEEP); } @@ -212,20 +201,15 @@ regWrite(NODE_ADDR, address); } -uint8_t rfmGetRssi(void) { - return regRead(RSSI_VALUE); -} - -// TODO make pure setter -void rfmSetOutputPower(uint8_t rssi) { +void rfmSetOutputPower(int8_t dBm) { uint8_t pa = 0x40; // -18 dBm with PA1 // adjust power from -2 to +13 dBm - pa += min(max(rssi - 69, PA_MIN), PA_MAX); + pa |= (min(max(dBm + PA_OFF, PA_MIN), PA_MAX)) & 0x1f; regWrite(PA_LEVEL, pa); } -uint8_t rfmGetOutputPower(void) { - return regRead(PA_LEVEL); +int8_t rfmGetOutputPower(void) { + return (regRead(PA_LEVEL) & 0x1f) - PA_OFF; } void rfmStartReceive(void) { @@ -236,11 +220,13 @@ } PayloadFlags rfmPayloadReady(void) { - PayloadFlags flags = {.ready = false, .crc = false}; + PayloadFlags flags = {.ready = false, .rssi = 255, .crc = false}; if (irqFlags2 & (1 << 2)) { - flags.ready = true; - flags.crc = irqFlags2 & (1 << 1); clearIrqFlags(); + + flags.ready = true; + flags.rssi = regRead(RSSI_VALUE); + flags.crc = regRead(IRQ_FLAGS2) & (1 << 1); setMode(MODE_STDBY); } @@ -268,7 +254,7 @@ timeoutEnable(timeout); rfmStartReceive(); - // wait until "PayloadReady" or timeout + // wait until "PayloadReady" or "Timeout" do {} while (!(irqFlags2 & (1 << 2)) && !(irqFlags1 & (1 << 2))); bool ready = irqFlags2 & (1 << 2); bool timedout = irqFlags1 & (1 << 2); @@ -277,10 +263,11 @@ if (ready) { timeoutEnable(false); } + setMode(MODE_STDBY); if (timedout) { - // full power as last resort + // full power as last resort, indicate timeout regWrite(PA_LEVEL, 0x5f); return 0; diff --git a/librfm.h b/librfm.h index 949cc86..f8d598f 100644 --- a/librfm.h +++ b/librfm.h @@ -34,8 +34,8 @@ #define DIO_MAP2 0x26 #define IRQ_FLAGS1 0x27 #define RSSI_THRESH 0x29 -#define RX_TIMEOUT1 0x2a -#define RX_TIMEOUT2 0x2b +#define RX_TO_RSSI 0x2a +#define RX_TO_PRDY 0x2b #define PREAMB_MSB 0x2c #define PREAMB_LSB 0x2d #define IRQ_FLAGS2 0x28 @@ -69,6 +69,7 @@ #define MODE_TX 0x0c #define MODE_RX 0x10 +#define PA_OFF 18 #define PA_MIN 16 #define PA_MAX 31 @@ -76,15 +77,13 @@ #define F_STEP 6103515625ULL #define CAST_ADDRESS 0x84 -#define TIMEOUT_INTS 3 // about 100 milliseconds @ 30 Hz -#define MAX_TIMEOUTS 9 // slow down tx attempts after so many timeouts - /** * Flags for "payload ready" event. */ typedef struct { bool ready; bool crc; + uint8_t rssi; } PayloadFlags; /** @@ -128,17 +127,10 @@ void rfmInit(uint64_t freq, uint8_t node); /** - * Should be called when a radio interrupt occurred, i.e. 'PayloadReady'. + * Reads interrupt flags. Should be called when any interrupt occurs + * on DIO0 or DIO4. */ -void rfmInt(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 rfmTimer(void); +void rfmIrq(void); /** * Shuts down the radio. @@ -158,25 +150,19 @@ void rfmSetNodeAddress(uint8_t address); /** - * Returns the current RSSI value. + * Sets the output power to -2 to +13 dBm. + * Values outside that range are ignored. * - * @return rssi value + * @param dBm ouput power */ -uint8_t rfmGetRssi(void); +void rfmSetOutputPower(int8_t dBm); /** - * Sets the output power based on the given receiver RSSI. - * - * @param rssi - */ -void rfmSetOutputPower(uint8_t rssi); - -/** - * Returns the current output power setting. + * Returns the current output power setting in dBm. * * @return ouput power */ -uint8_t rfmGetOutputPower(void); +int8_t rfmGetOutputPower(void); /** * Sets the radio to receive mode and maps "PayloadReady" to DIO0.