diff --git a/.gitignore b/.gitignore index ef58455..2fa0e82 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ /nbproject/private/ /build -/avrrfm.elf -/avrrfm.hex -/avrrfm.lst +*.elf +*.hex +*.lst +# *.a +*.d +*.o +*.map diff --git a/Makefile b/Makefile index 4e7e320..0627ffc 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,8 @@ VFLIP = 0 MAIN = avrrfm.c -SRC = bitmaps.h colorspace.c dejavu.c display.c font.c i2c.c mcp9808.c rfm69.c \ - sdcard.c spi.c tft.c unifont.c usart.c +SRC = bitmaps.c colorspace.c dejavu.c display.c font.c i2c.c mcp9808.c \ + sdcard.c spi.c tft.c unifont.c usart.c rfm.c CC = avr-gcc OBJCOPY = avr-objcopy @@ -43,12 +43,13 @@ TARGET = $(strip $(basename $(MAIN))) SRC += $(TARGET).c +SRC += librfm.a OBJ = $(SRC:.c=.o) OBJ = $(SRC:.S=.o) $(TARGET).elf: bitmaps.h colorspace.h dejavu.h display.h font.h i2c.h \ - mcp9808.h pins.h rfm69.h sdcard.h spi.h tft.h types.h unifont.h \ + mcp9808.h pins.h sdcard.h spi.h tft.h types.h unifont.h \ usart.h utils.h Makefile all: $(TARGET).hex diff --git a/README.md b/README.md index 72fc3b6..84d36e9 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,8 @@ ## About -Experimental project to drive an RFM69HCW radio module with plain avr-libc -and an Atmega328p MCU. - -This is work in progress. Simple Tx-Rx with response is working so far. - -I'm impressed how well these radio modules work; the range achieved with -simple wire antennas as well as the reliable packet transmission. +Experimental project around RFM radio modules using an ATmega328P MCU +and [librfm](https://github.com/gitdode/librfm/tree/main). To do something really extraordinary, the temperature reading of an MCP9808 sensor is periodically transmitted to the receiver. @@ -31,33 +26,6 @@ ![IMG_20250315_175920c](https://github.com/user-attachments/assets/03405774-57c2-42f1-a39a-8fa4cc2801ac) -## Range - -Setting `RegPaLevel` to `0x5f`, which gives +13 dBm with `PA1`, indoor range is -very good and in an actual "field" test, packet reception was still reliable -with an RSSI of about -90 dBm at about 2.2 km distance - with simple wire -antennas. What would be the range with +20 dBm and decent antennas? - -![FieldTest3](https://github.com/user-attachments/assets/f2289f8e-1f81-4b85-9146-07c2ce1bb563) - -## Susceptibility to Temperature Changes - -With the default frequency deviation of 5 kHz and receiver bandwidth of -10.4 kHz, packet transmission is very unreliable and fails completely for me; -when the temperature of the transmitter is below 10°C and above 40°C, while -the receiver temperature is at 20°C. The receiver does not seem to be prone to -temperature changes. -Increasing frequency deviation to 10 kHz and receiver bandwidth to 20.8 kHz, -temperature susceptibility is eliminated; when testing with transmitter -temperature from -20°C to 50°C, packet transmission is perfectly reliable. - -Frequency Deviation = 10 kHz (transmitter) -`RegFdevMsb` = `0x00` -`RegFdevLsb` = `0xa4` - -Receiver Bandwidth = 20.8 kHz -`RegRxBw` = `0x54` - ## Fun Stuff Looking at the payload in the transmitted signal in URH (with an RTL-SDR Blog V4): diff --git a/avrrfm.c b/avrrfm.c index 45a0aed..8506bd2 100644 --- a/avrrfm.c +++ b/avrrfm.c @@ -26,7 +26,7 @@ #include "usart.h" #include "spi.h" #include "utils.h" -#include "rfm69.h" +#include "librfm.h" #include "mcp9808.h" #include "sdcard.h" #include "tft.h" @@ -47,7 +47,7 @@ #define NODE2 0x42 #ifndef RECEIVER - #define RECEIVER 1 + #define RECEIVER 0 #endif static volatile uint8_t watchdogInts = 0; @@ -72,14 +72,14 @@ * Called while the controller isn't in power down sleep mode. */ ISR(TIMER0_COMPA_vect) { - timeRadio(); + rfmTimer(); } /** * Called when an INT0 interrupt occurs. */ ISR(INT0_vect) { - intRadio(); + rfmInt(); } /** @@ -192,9 +192,9 @@ */ static void transmitTemp(uint8_t node) { uint16_t temp = readTSens(); - uint8_t power = getOutputPower(); + uint8_t power = rfmGetOutputPower(); uint8_t payload[] = {(temp >> 8), temp & 0x00ff, power}; - transmitPayload(payload, sizeof (payload), node); + rfmTransmitPayload(payload, sizeof (payload), node); // printString("Transmitted\r\n"); } @@ -240,7 +240,7 @@ */ static Temperature readTemp(void) { uint8_t payload[3]; - readPayload(payload, sizeof (payload)); + rfmReadPayload(payload, sizeof (payload)); Temperature temp = {0}; temp.raw |= payload[0] << 8; temp.raw |= payload[1]; @@ -255,15 +255,15 @@ * @param flags */ static void handlePayload(PayloadFlags flags) { - uint8_t rssi = getRssi(); + uint8_t rssi = rfmGetRssi(); Temperature temp = readTemp(); // communicate RSSI back to transmitter uint8_t payload[] = {rssi}; - transmitPayload(payload, sizeof (payload), NODE2); + rfmTransmitPayload(payload, sizeof (payload), NODE2); displayTemp(rssi, flags.crc, &temp); - startReceive(); + rfmStartReceive(); } /** @@ -273,11 +273,11 @@ */ static bool waitResponse(void) { uint8_t response[1]; - int8_t len = receivePayload(response, sizeof (response), true); + int8_t len = rfmReceivePayload(response, sizeof (response), true); if (len > 0) { // receiver RSSI int8_t rssi = divRoundNearest(response[0], 2); - setOutputPower(rssi); + rfmSetOutputPower(rssi); return false; } @@ -292,14 +292,14 @@ */ static void receiveData(PayloadFlags flags) { uint8_t payload[MESSAGE_SIZE + 1]; // + address byte - uint8_t len = readPayload(payload, sizeof (payload)); + uint8_t len = rfmReadPayload(payload, sizeof (payload)); char buf[MESSAGE_SIZE + 1]; snprintf(buf, len, "%s", payload); printString(buf); _delay_ms(10); - startReceive(); + rfmStartReceive(); } /** @@ -312,13 +312,13 @@ void *start = █ div_t packets = div(SD_BLOCK_SIZE, MESSAGE_SIZE); for (size_t i = 0; i < packets.quot; i++) { - transmitPayload(start, MESSAGE_SIZE, NODE0); + rfmTransmitPayload(start, MESSAGE_SIZE, NODE0); start += MESSAGE_SIZE; // a little break in between packets for now _delay_ms(100); } if (packets.rem > 0) { - transmitPayload(start, packets.rem, NODE0); + rfmTransmitPayload(start, packets.rem, NODE0); } } } @@ -344,13 +344,13 @@ sei(); uint8_t node = RECEIVER ? NODE1 : NODE2; - initRadio(868600, node); + rfmInit(868600, node); if (RECEIVER) { initDisplay(); setFrame(WHITE); fillArea(0, 0, DISPLAY_WIDTH, 16, BLACK); // initial rx mode - startReceive(); + rfmStartReceive(); } while (true) { @@ -364,7 +364,7 @@ enableSPI(); wakeTSens(); - wakeRadio(); + rfmWake(); if (sdcard) { transmitData(); } else { @@ -381,11 +381,11 @@ } } sleepTSens(); - sleepRadio(); + rfmSleep(); disableSPI(); } } else { - PayloadFlags flags = payloadReady(); + PayloadFlags flags = rfmPayloadReady(); if (flags.ready) { handlePayload(flags); // receiveData(flags); diff --git a/bitmaps.h b/bitmaps.h index dbf36ae..326521e 100644 --- a/bitmaps.h +++ b/bitmaps.h @@ -8,8 +8,6 @@ #ifndef BITMAPS_H #define BITMAPS_H -#include -#include #include "types.h" #include "colorspace.h" diff --git a/librfm.a b/librfm.a new file mode 100644 index 0000000..0a14ec8 --- /dev/null +++ b/librfm.a Binary files differ diff --git a/librfm.h b/librfm.h new file mode 100644 index 0000000..332d475 --- /dev/null +++ b/librfm.h @@ -0,0 +1,227 @@ +/* + * File: librfm.h + * Author: torsten.roemer@luniks.net + * + * Created on 23. März 2025, 23:04 + */ + +#ifndef LIBRFM_H +#define LIBRFM_H + +#include +#include +#include + +#define FIFO 0x00 +#define OP_MODE 0x01 +#define DATA_MOD 0x02 +#define BITRATE_MSB 0x03 +#define BITRATE_LSB 0x04 +#define FDEV_MSB 0x05 +#define FDEV_LSB 0x06 +#define FRF_MSB 0x07 +#define FRF_MID 0x08 +#define FRF_LSB 0x09 +#define OSC1 0x0a +#define PA_LEVEL 0x11 +#define LNA 0x18 +#define RX_BW 0x19 +#define AFC_FEI 0x1e +#define AFC_BW 0x20 +#define RSSI_CONFIG 0x23 +#define RSSI_VALUE 0x24 +#define DIO_MAP1 0x25 +#define DIO_MAP2 0x26 +#define IRQ_FLAGS1 0x27 +#define RSSI_THRESH 0x29 +#define RX_TIMEOUT1 0x2a +#define RX_TIMEOUT2 0x2b +#define PREAMB_MSB 0x2c +#define PREAMB_LSB 0x2d +#define IRQ_FLAGS2 0x28 +#define SYNC_CONF 0x2e +#define SYNC_VAL1 0x2f +#define SYNC_VAL2 0x30 +#define SYNC_VAL3 0x31 +#define SYNC_VAL4 0x32 +#define SYNC_VAL5 0x33 +#define SYNC_VAL6 0x34 +#define SYNC_VAL7 0x35 +#define SYNC_VAL8 0x36 +#define PCK_CFG1 0x37 +#define PAYLOAD_LEN 0x38 +#define NODE_ADDR 0x39 +#define CAST_ADDR 0x3a +#define AUTO_MODES 0x3b +#define FIFO_THRESH 0x3c +#define PCK_CFG2 0x3d +#define TEST_LNA 0x58 +#define TEST_PA1 0x5a +#define TEST_PA2 0x5c +#define TEST_DAGC 0x6f +#define TEST_AFC 0x71 + +#define MASK_MODE 0x1c + +#define MODE_SLEEP 0x00 +#define MODE_STDBY 0x04 +#define MODE_FS 0x08 +#define MODE_TX 0x0c +#define MODE_RX 0x10 + +#define PA_MIN 16 +#define PA_MAX 31 + +#define MESSAGE_SIZE 63 +#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; +} PayloadFlags; + +/** + * F_CPU dependent delay of 5 milliseconds. + * _delay_ms(5); + * + * @param ms + */ +void _rfmDelay5(void); + +/** + * Turns the radio on by pulling its reset pin LOW. + * PORT_RFM &= ~(1 << PIN_RRST); + */ +void _rfmOn(void); + +/** + * Selects the radio to talk to via SPI. + * PORT_RFM &= ~(1 << PIN_RCS); + */ +void _rfmSel(void); + +/** + * Deselects the radio to talk to via SPI. + * PORT_RFM |= (1 << PIN_RCS); + */ +void _rfmDes(void); + +/** + * SPI transmits/receives given data/returns it. + * + * @param data + * @return data + */ +uint8_t _rfmTx(uint8_t data); + +/** + * Initializes the radio module with the given carrier frequency in kilohertz + * and node address. + */ +void rfmInit(uint64_t freq, uint8_t node); + +/** + * Should be called when a radio interrupt occurred, i.e. 'PayloadReady'. + */ +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); + +/** + * Shuts down the radio. + */ +void rfmSleep(void); + +/** + * Wakes up the radio. + */ +void rfmWake(void); + +/** + * Sets the node address. + * + * @param address + */ +void rfmSetNodeAddress(uint8_t address); + +/** + * Returns the current RSSI value. + * + * @return rssi value + */ +uint8_t rfmGetRssi(void); + +/** + * Sets the output power based on the given receiver RSSI. + * + * @param rssi + */ +void rfmSetOutputPower(uint8_t rssi); + +/** + * Returns the current output power setting. + * + * @return ouput power + */ +uint8_t rfmGetOutputPower(void); + +/** + * Sets the radio to receive mode and maps "PayloadReady" to DIO0. + */ +void rfmStartReceive(void); + +/** + * Returns true if a "PayloadReady" interrupt arrived and clears the + * interrupt state. + * + * @return true if "PayloadReady" + */ +PayloadFlags rfmPayloadReady(void); + +/** + * Sets the radio in standby mode, puts the payload into the given array + * with the given size, and returns the length of the payload. + * + * @param payload buffer for payload + * @param size of payload buffer + * @return payload bytes actually received + */ +size_t rfmReadPayload(uint8_t *payload, size_t size); + +/** + * Waits for "PayloadReady", puts the payload into the given array with the + * given size, and returns the length of the payload, or 0 if a timeout + * occurred. + * + * @param payload buffer for payload + * @param size of payload buffer + * @param timeout enable timeout + * @return payload bytes actually received + */ +size_t rfmReceivePayload(uint8_t *payload, size_t size, bool timeout); + +/** + * Transmits up to 64 bytes of the given payload with the given node address. + * + * @param payload to be sent + * @param size of payload + * @param node address + * @return payload bytes actually sent + */ +size_t rfmTransmitPayload(uint8_t *payload, size_t size, uint8_t node); + +#endif /* LIBRFM_H */ + diff --git a/nbproject/Makefile-Custom.mk b/nbproject/Makefile-Custom.mk index 0ffb8db..bc953e0 100644 --- a/nbproject/Makefile-Custom.mk +++ b/nbproject/Makefile-Custom.mk @@ -43,12 +43,12 @@ ${OBJECTDIR}/_ext/48b9ad18/font.o \ ${OBJECTDIR}/_ext/48b9ad18/i2c.o \ ${OBJECTDIR}/_ext/48b9ad18/mcp9808.o \ - ${OBJECTDIR}/_ext/48b9ad18/rfm69.o \ ${OBJECTDIR}/_ext/48b9ad18/sdcard.o \ ${OBJECTDIR}/_ext/48b9ad18/spi.o \ ${OBJECTDIR}/_ext/48b9ad18/tft.o \ ${OBJECTDIR}/_ext/48b9ad18/unifont.o \ - ${OBJECTDIR}/_ext/48b9ad18/usart.o + ${OBJECTDIR}/_ext/48b9ad18/usart.o \ + ${OBJECTDIR}/rfm.o # C Compiler Flags @@ -107,10 +107,6 @@ ${MKDIR} -p ${OBJECTDIR}/_ext/48b9ad18 $(COMPILE.c) -g -DBAUD=38400 -DDRIVER=1 -DF_CPU=16000000UL -D__AVR_ATmega328P__ -D__flash=volatile -I. -o ${OBJECTDIR}/_ext/48b9ad18/mcp9808.o /home/dode/dev/avrrfm/mcp9808.c -${OBJECTDIR}/_ext/48b9ad18/rfm69.o: /home/dode/dev/avrrfm/rfm69.c - ${MKDIR} -p ${OBJECTDIR}/_ext/48b9ad18 - $(COMPILE.c) -g -DBAUD=38400 -DDRIVER=1 -DF_CPU=16000000UL -D__AVR_ATmega328P__ -D__flash=volatile -I. -o ${OBJECTDIR}/_ext/48b9ad18/rfm69.o /home/dode/dev/avrrfm/rfm69.c - ${OBJECTDIR}/_ext/48b9ad18/sdcard.o: /home/dode/dev/avrrfm/sdcard.c ${MKDIR} -p ${OBJECTDIR}/_ext/48b9ad18 $(COMPILE.c) -g -DBAUD=38400 -DDRIVER=1 -DF_CPU=16000000UL -D__AVR_ATmega328P__ -D__flash=volatile -I. -o ${OBJECTDIR}/_ext/48b9ad18/sdcard.o /home/dode/dev/avrrfm/sdcard.c @@ -131,6 +127,10 @@ ${MKDIR} -p ${OBJECTDIR}/_ext/48b9ad18 $(COMPILE.c) -g -DBAUD=38400 -DDRIVER=1 -DF_CPU=16000000UL -D__AVR_ATmega328P__ -D__flash=volatile -I. -o ${OBJECTDIR}/_ext/48b9ad18/usart.o /home/dode/dev/avrrfm/usart.c +${OBJECTDIR}/rfm.o: rfm.c + ${MKDIR} -p ${OBJECTDIR} + $(COMPILE.c) -g -DBAUD=38400 -DDRIVER=1 -DF_CPU=16000000UL -D__AVR_ATmega328P__ -D__flash=volatile -I. -o ${OBJECTDIR}/rfm.o rfm.c + # Subprojects .build-subprojects: diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml index 39dfecd..3dcff70 100644 --- a/nbproject/configurations.xml +++ b/nbproject/configurations.xml @@ -11,8 +11,7 @@ i2c.c mcp9808.c mcp9808.h - rfm69.c - rfm69.h + rfm.c sdcard.c spi.c tft.c @@ -71,10 +70,6 @@ - - - - @@ -85,6 +80,8 @@ + + diff --git a/rfm.c b/rfm.c new file mode 100644 index 0000000..469f49e --- /dev/null +++ b/rfm.c @@ -0,0 +1,32 @@ +/* + * File: rfm.c + * Author: torsten.roemer@luniks.net + * + * Created on 24.03.2025, 21:07 + */ + +#include + +#include "librfm.h" +#include "pins.h" +#include "spi.h" + +void _rfmDelay5() { + _delay_ms(5); +} + +void _rfmOn() { + PORT_RFM &= ~(1 << PIN_RRST); +} + +void _rfmSel() { + PORT_RFM &= ~(1 << PIN_RCS); +} + +void _rfmDes() { + PORT_RFM |= (1 << PIN_RCS); +} + +uint8_t _rfmTx(uint8_t data) { + return transmit(data); +} \ No newline at end of file diff --git a/rfm69.c b/rfm69.c deleted file mode 100644 index 66738ca..0000000 --- a/rfm69.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * File: rfm69.c - * Author: torsten.roemer@luniks.net - * - * Created on 28. Januar 2025, 19:57 - */ - -#include "rfm69.h" -#include "types.h" - -static volatile uint8_t irqFlags1 = 0; -static volatile uint8_t irqFlags2 = 0; -static volatile uint8_t timeoutInts = 0; -static volatile bool timeoutEnabled = false; - -/** - * Selects the radio to talk to via SPI. - */ -static void spiSel(void) { - PORT_RFM &= ~(1 << PIN_RCS); -} - -/** - * Deselects the radio to talk to via SPI. - */ -static void spiDes(void) { - PORT_RFM |= (1 << PIN_RCS); -} - -/** - * Writes the given value to the given register. - * - * @param reg - * @param value - */ -static void regWrite(uint8_t reg, uint8_t value) { - spiSel(); - transmit(reg | 0x80); - transmit(value); - spiDes(); -} - -/** - * Reads and returns the value of the given register. - * - * @param reg - * @return value - */ -static uint8_t regRead(uint8_t reg) { - spiSel(); - transmit(reg & 0x7f); - uint8_t value = transmit(0x00); - spiDes(); - - return value; -} - -/** - * Sets the module to the given operating mode. - */ -static void setMode(uint8_t mode) { - regWrite(OP_MODE, (regRead(OP_MODE) & ~MASK_MODE) | (mode & MASK_MODE)); -} - -/** - * Clears the IRQ flags read from the module. - */ -static void clearIrqFlags(void) { - irqFlags1 = 0; - irqFlags2 = 0; -} - -/** - * Enables timeout (sets timeout interrupt flag on expiration). - * - * @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); -} - -void initRadio(uint64_t freq, uint8_t node) { - // wait a bit after power on - _delay_ms(10); - - // pull reset LOW to turn on the module - PORT_RFM &= ~(1 << PIN_RRST); - - _delay_ms(5); - - uint8_t version = regRead(0x10); - printString("Version: "); - printHex(version); - - // packet mode, FSK modulation, no shaping (default) - regWrite(DATA_MOD, 0x00); - - // bit rate 9.6 kBit/s - // regWrite(BITRATE_MSB, 0x0d); - // regWrite(BITRATE_LSB, 0x05); - - // frequency deviation (default 5 kHz) - increasing to 10 kHz - // completely removes susceptibility to temperature changes - // RX_BW must be increased accordingly - regWrite(FDEV_MSB, 0x00); - regWrite(FDEV_LSB, 0xa4); - - // RC calibration, automatically done at device power-up - // regWrite(OSC1, 0x80); - // do { } while (!(regRead(OSC1) & 0x40)); - - // PA level (default +13 dBm with PA0, yields very weak output power, why?) - // regWrite(PA_LEVEL, 0x9f); - // +13 dBm on PA1, yields the expected output power - regWrite(PA_LEVEL, 0x5f); - // +17 dBm - doesn't seem to work just like that? - // regWrite(PA_LEVEL, 0x7f); - - // LNA 200 Ohm, gain AGC (default) - regWrite(LNA, 0x88); - // LNA 50 Ohm, gain AGC - // regWrite(LNA, 0x08); - - // LNA high sensitivity mode - // regWrite(TEST_LNA, 0x2d); - - // freq of DC offset canceller and channel filter bandwith (default 10.4 kHz) - // increasing to 20.8 kHz in connection with setting FDEV_*SB to 10 kHz - // completely removes susceptibility to temperature changes - regWrite(RX_BW, 0x54); - - // RX_BW during AFC (default 0x8b) - regWrite(AFC_BW, 0x54); - - // AFC auto on - // regWrite(AFC_FEI, 0x04); - - // RSSI threshold (default, POR 0xff) - regWrite(RSSI_THRESH, 0xe4); - - // Preamble size - regWrite(PREAMB_MSB, 0x00); - regWrite(PREAMB_LSB, 0x0f); - - // turn off CLKOUT (not used) - regWrite(DIO_MAP2, 0x07); - - // set the carrier frequency - uint32_t frf = freq * 100000000000ULL / F_STEP; - regWrite(FRF_MSB, frf >> 16); - regWrite(FRF_MID, frf >> 8); - regWrite(FRF_LSB, frf >> 0); - - // enable sync word generation and detection, FIFO fill on sync address, - // 4 bytes sync word, tolerate 3 bit errors - regWrite(SYNC_CONF, 0x9b); - - // just set all sync word values to some really creative value - regWrite(SYNC_VAL1, 0x2f); - regWrite(SYNC_VAL2, 0x30); - regWrite(SYNC_VAL3, 0x31); - regWrite(SYNC_VAL4, 0x32); - regWrite(SYNC_VAL5, 0x33); - regWrite(SYNC_VAL6, 0x34); - regWrite(SYNC_VAL7, 0x35); - regWrite(SYNC_VAL8, 0x36); - - // variable payload length, crc on, no address matching - // regWrite(PCK_CFG1, 0x90); - // match broadcast or node address - // regWrite(PCK_CFG1, 0x94); - // + CrcAutoClearOff - regWrite(PCK_CFG1, 0x9c); - - // disable automatic RX restart - regWrite(PCK_CFG2, 0x00); - - // node and broadcast address - regWrite(NODE_ADDR, node); - regWrite(CAST_ADDR, CAST_ADDRESS); - - // set TX start condition to "at least one byte in FIFO" - regWrite(FIFO_THRESH, 0x8f); - - // Fading Margin Improvement, improved margin, use if AfcLowBetaOn=0 - regWrite(TEST_DAGC, 0x30); - - printString("Radio init done\r\n"); -} - -/** - * Reads interrupt flags when a radio interrupt occurs. - */ -void intRadio(void) { - irqFlags1 = regRead(IRQ_FLAGS1); - irqFlags2 = regRead(IRQ_FLAGS2); -} - -void timeRadio(void) { - if (timeoutEnabled && timeoutInts++ >= TIMEOUT_INTS) { - timeoutEnable(false); - timeout(); - } -} - -void sleepRadio(void) { - setMode(MODE_SLEEP); -} - -void wakeRadio(void) { - setMode(MODE_STDBY); - // should better wait for ModeReady irq? - _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); - - setMode(MODE_RX); -} - -PayloadFlags payloadReady(void) { - PayloadFlags flags = {.ready = false, .crc = false}; - if (irqFlags2 & (1 << 2)) { - flags.ready = true; - flags.crc = irqFlags2 & (1 << 1); - clearIrqFlags(); - setMode(MODE_STDBY); - } - - return flags; -} - -size_t readPayload(uint8_t *payload, size_t size) { - size_t len = regRead(FIFO); - len = min(len, size); - - // TODO assume and ignore address for now - regRead(FIFO); - - spiSel(); - transmit(FIFO); - for (size_t i = 0; i < len; i++) { - payload[i] = transmit(FIFO); - } - spiDes(); - - return len; -} - -size_t receivePayload(uint8_t *payload, size_t size, bool timeout) { - timeoutEnable(timeout); - startReceive(); - - // wait until "PayloadReady" or timeout - do {} while (!(irqFlags2 & (1 << 2)) && !(irqFlags1 & (1 << 2))); - bool ready = irqFlags2 & (1 << 2); - bool timedout = irqFlags1 & (1 << 2); - - clearIrqFlags(); - if (ready) { - timeoutEnable(false); - } - setMode(MODE_STDBY); - - if (timedout) { - // full power as last resort - regWrite(PA_LEVEL, 0x5f); - - return 0; - } - - return readPayload(payload, size); -} - -size_t transmitPayload(uint8_t *payload, size_t size, uint8_t node) { - // message + address byte - size_t len = min(size, MESSAGE_SIZE) + 1; - - spiSel(); - transmit(FIFO | 0x80); - transmit(len); - transmit(node); - for (size_t i = 0; i < size; i++) { - transmit(payload[i]); - } - spiDes(); - - // get "PacketSent" on DIO0 (default) - regWrite(DIO_MAP1, 0x00); - - setMode(MODE_TX); - - loop_until_bit_is_set(irqFlags2, 3); - clearIrqFlags(); - - setMode(MODE_STDBY); - - return len; -} diff --git a/rfm69.h b/rfm69.h deleted file mode 100644 index 1f87026..0000000 --- a/rfm69.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * File: rfm69.h - * Author: torsten.roemer@luniks.net - * - * Created on 28. Januar 2025, 19:55 - */ - -#ifndef RFM69_H -#define RFM69_H - -#include -#include - -#include "rfm69.h" -#include "pins.h" -#include "types.h" -#include "spi.h" -#include "usart.h" - -#define FIFO 0x00 -#define OP_MODE 0x01 -#define DATA_MOD 0x02 -#define BITRATE_MSB 0x03 -#define BITRATE_LSB 0x04 -#define FDEV_MSB 0x05 -#define FDEV_LSB 0x06 -#define FRF_MSB 0x07 -#define FRF_MID 0x08 -#define FRF_LSB 0x09 -#define OSC1 0x0a -#define PA_LEVEL 0x11 -#define LNA 0x18 -#define RX_BW 0x19 -#define AFC_FEI 0x1e -#define AFC_BW 0x20 -#define RSSI_CONFIG 0x23 -#define RSSI_VALUE 0x24 -#define DIO_MAP1 0x25 -#define DIO_MAP2 0x26 -#define IRQ_FLAGS1 0x27 -#define RSSI_THRESH 0x29 -#define RX_TIMEOUT1 0x2a -#define RX_TIMEOUT2 0x2b -#define PREAMB_MSB 0x2c -#define PREAMB_LSB 0x2d -#define IRQ_FLAGS2 0x28 -#define SYNC_CONF 0x2e -#define SYNC_VAL1 0x2f -#define SYNC_VAL2 0x30 -#define SYNC_VAL3 0x31 -#define SYNC_VAL4 0x32 -#define SYNC_VAL5 0x33 -#define SYNC_VAL6 0x34 -#define SYNC_VAL7 0x35 -#define SYNC_VAL8 0x36 -#define PCK_CFG1 0x37 -#define PAYLOAD_LEN 0x38 -#define NODE_ADDR 0x39 -#define CAST_ADDR 0x3a -#define AUTO_MODES 0x3b -#define FIFO_THRESH 0x3c -#define PCK_CFG2 0x3d -#define TEST_LNA 0x58 -#define TEST_PA1 0x5a -#define TEST_PA2 0x5c -#define TEST_DAGC 0x6f -#define TEST_AFC 0x71 - -#define MASK_MODE 0x1c - -#define MODE_SLEEP 0x00 -#define MODE_STDBY 0x04 -#define MODE_FS 0x08 -#define MODE_TX 0x0c -#define MODE_RX 0x10 - -#define PA_MIN 16 -#define PA_MAX 31 - -#define MESSAGE_SIZE 63 -#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 - -/** - * Initializes the radio module with the given carrier frequency in kilohertz - * and node address. - */ -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 - */ -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 - */ -void setOutputPower(uint8_t rssi); - -/** - * Returns the current output power setting. - * - * @return ouput power - */ -uint8_t getOutputPower(void); - -/** - * Sets the radio to receive mode and maps "PayloadReady" to DIO0. - */ -void startReceive(void); - -/** - * Returns true if a "PayloadReady" interrupt arrived and clears the - * interrupt state. - * - * @return true if "PayloadReady" - */ -PayloadFlags payloadReady(void); - -/** - * Sets the radio in standby mode, puts the payload into the given array - * with the given size, and returns the length of the payload. - * - * @param payload buffer for payload - * @param size of payload buffer - * @return payload bytes actually received - */ -size_t readPayload(uint8_t *payload, size_t size); - -/** - * Waits for "PayloadReady", puts the payload into the given array with the - * given size, and returns the length of the payload, or 0 if a timeout - * occurred. - * - * @param payload buffer for payload - * @param size of payload buffer - * @param timeout enable timeout - * @return payload bytes actually received - */ -size_t receivePayload(uint8_t *payload, size_t size, bool timeout); - -/** - * Transmits up to 64 bytes of the given payload with the given node address. - * - * @param payload to be sent - * @param size of payload - * @param node address - * @return payload bytes actually sent - */ -size_t transmitPayload(uint8_t *payload, size_t size, uint8_t node); - -#endif /* RFM69_H */ - diff --git a/types.h b/types.h index f15e271..3203134 100644 --- a/types.h +++ b/types.h @@ -38,14 +38,6 @@ } Point; /** - * Flags for "payload ready" event. - */ -typedef struct { - bool ready; - bool crc; -} PayloadFlags; - -/** * Temperature read from transmitter including * additional information. */