From 50deb9d280254c8e17624b368ea778f69dd86767 Mon Sep 17 00:00:00 2001 From: Sadeep Madurange Date: Sat, 1 Feb 2025 11:25:19 +0800 Subject: Start work on nRF24L01. --- rf69/radio.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 rf69/radio.c (limited to 'rf69/radio.c') diff --git a/rf69/radio.c b/rf69/radio.c new file mode 100644 index 0000000..f5d98c8 --- /dev/null +++ b/rf69/radio.c @@ -0,0 +1,212 @@ +#include + +#include +#include + +#include "radio.h" +#include "serial.h" + +#define SPI_SS PB2 +#define SPI_SCK PB5 +#define SPI_MISO PB4 +#define SPI_MOSI PB3 +#define SPI_DDR DDRB +#define SPI_PORT PORTB + +#define RF69_OPMODE_RX 0x10 +#define RF69_OPMODE_TX 0x0C +#define RF69_OPMODE_STDBY 0x04 + +#define RF69_REG_FIFO 0x01 +#define RF69_REG_OPMODE 0x01 +#define RF69_REG_PALEVEL 0x11 +#define RF69_REG_TESTPA1 0x5A +#define RF69_REG_TESTPA2 0x5C +#define RF69_REG_IRQFLAGS1 0x27 +#define RF69_REG_IRQFLAGS2 0x28 +#define RF69_REG_DIOMAPPING1 0x25 + +#define RF69_PALEVEL_PA1 0x40 +#define RF69_PALEVEL_PA2 0x20 +#define RF69_TESTPA1_BOOST 0x5D +#define RF69_TESTPA2_BOOST 0x7C +#define RF69_TESTPA1_NORMAL 0x55 +#define RF69_TESTPA2_NORMAL 0x70 +#define RF69_DIOMAPPING1_PACKET_SENT 0x00 +#define RF69_DIOMAPPING1_PAYLOAD_READY 0x40 + +static int8_t power = 0; +static uint8_t opmode = 0; + +static inline uint8_t read_reg(uint8_t reg) +{ + SPI_PORT &= ~(1 << SPI_SS); + SPDR = reg & 0x7F; + while (!(SPSR & (1 << SPIF))) + ; + SPDR = 0; + while (!(SPSR & (1 << SPIF))) + ; + SPI_PORT |= (1 << SPI_SS); + return SPDR; +} + +static inline void write_reg(uint8_t reg, uint8_t val) +{ + SPI_PORT &= ~(1 << SPI_SS); + SPDR = reg | 0x80; + while (!(SPSR & (1 << SPIF))) + ; + SPDR = val; + while (!(SPSR & (1 << SPIF))) + ; + SPI_PORT |= (1 << SPI_SS); +} + +static inline void set_mode(uint8_t mode) +{ + uint8_t val; + + if (opmode != mode) { + if (mode == RF69_OPMODE_TX) { + if (power >= 18) { + write_reg(RF69_REG_TESTPA1, RF69_TESTPA1_BOOST); + write_reg(RF69_REG_TESTPA2, RF69_TESTPA2_BOOST); + } + write_reg(RF69_REG_DIOMAPPING1, RF69_DIOMAPPING1_PACKET_SENT); + } else { + if (power >= 18) { + write_reg(RF69_REG_TESTPA1, RF69_TESTPA1_NORMAL); + write_reg(RF69_REG_TESTPA2, RF69_TESTPA2_NORMAL); + } + if (mode == RF69_OPMODE_RX) + write_reg(RF69_REG_DIOMAPPING1, RF69_DIOMAPPING1_PAYLOAD_READY); + } + + val = read_reg(RF69_REG_OPMODE); + val &= ~0x1C; + val |= (mode & 0x1C); + + write_reg(RF69_REG_OPMODE, val); + while (!(read_reg(RF69_REG_IRQFLAGS1) & 0x80)) + ; + + opmode = mode; + } +} + +void radio_set_tx_power(int8_t val) +{ + uint8_t pa; + + power = val; + + if (power < -2) + power = -2; + + if (power <= 13) + pa = (RF69_PALEVEL_PA1 | ((power + 18) & 0x1F)); + else if (power >= 18) + pa = (RF69_PALEVEL_PA1 | RF69_PALEVEL_PA2 | ((power + 11) & 0x1F)); + else + pa = (RF69_PALEVEL_PA1 | RF69_PALEVEL_PA2 | ((power + 14) & 0x1F)); + + write_reg(RF69_REG_PALEVEL, pa); +} + +void radio_send(const char *data, uint8_t n) +{ + uint8_t i, mode; + + mode = opmode; + set_mode(RF69_OPMODE_STDBY); + + SPI_PORT &= ~(1 << SPI_SS); + + SPDR = RF69_REG_FIFO | 0x80; + while (!(SPSR & (1 << SPIF))) + ; + + for (i = 0; i < n; i++) { + SPDR = data[i]; + while (!(SPSR & (1 << SPIF))) + ; + } + + SPI_PORT |= (1 << SPI_SS); + + set_mode(RF69_OPMODE_TX); + while (!(read_reg(RF69_REG_IRQFLAGS2) & 0x08)) + ; + + set_mode(mode); +} + +uint8_t radio_recv(char *buf, uint8_t n) +{ + uint8_t read_len, mode; + + read_len = 0; + mode = opmode; + + set_mode(RF69_OPMODE_STDBY); + + SPI_PORT &= ~(1 << SPI_SS); + + SPDR = RF69_REG_FIFO | 0x7F; + while (!(SPSR & (1 << SPIF))) + ; + + while (read_len < n) { + SPDR = 0; + while (!(SPSR & (1 << SPIF))) + ; + buf[read_len++] = SPDR; + } + + SPI_PORT |= (1 << SPI_SS); + + set_mode(mode); + return read_len; +} + +void radio_listen(void) +{ + set_mode(RF69_OPMODE_RX); +} + +void radio_init(const struct radio_cfg *cfg) +{ + SPI_DDR |= (1 << SPI_SS) | (1 << SPI_SCK) | (1 << SPI_MOSI); + SPI_PORT |= (1 << SPI_SS); + SPCR |= (1 << SPE) | (1 << MSTR); + + set_mode(RF69_OPMODE_STDBY); + + // LNA, AFC and RXBW settings + write_reg(0x18, 0x88); + write_reg(0x19, 0x55); + write_reg(0x1A, 0x8B); + + // DIO mappings: IRQ on DIO0 + write_reg(0x25, 0x40); + write_reg(0x26, 0x07); + + // RSSI threshold + write_reg(0x29, 0xE4); + + // sync config + write_reg(0x2E, 0x80); + write_reg(0x2F, cfg->netid); + + // packet config + write_reg(0x37, 0x10); + write_reg(0x38, cfg->payload_len); + write_reg(0x39, cfg->nodeid); + + // fifo config + write_reg(0x3C, 0x8F); + + // DAGC config + write_reg(0x6F, 0x30); +} -- cgit v1.2.3