Newer
Older
avrrfm / rfm69.c
/* 
 * File:   rfm69.c
 * Author: torsten.roemer@luniks.net
 *
 * Created on 28. Januar 2025, 19:57
 */

#include "rfm69.h"

static volatile uint8_t irqFlags1;
static volatile uint8_t irqFlags2;

/**
 * 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);
    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));
}

ISR(INT0_vect) {
    irqFlags1 = regRead(IRQ_FLAGS1);
    irqFlags2 = regRead(IRQ_FLAGS2);
    // printString("irq\r\n");
}

void initRadio(uint32_t kHz) {
    // 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);
    
    setFreq(kHz);
}

void setFreq(uint32_t freq) {
    freq = freq * 1000 / 61;
    
    regWrite(FRF_MSB, freq >> 16);
    regWrite(FRF_MID, freq >> 8);
    regWrite(FRF_LSB, freq >> 0);
}

void sendByte(uint8_t payload) {
    uint8_t opMode = regRead(OP_MODE);
    printString("OpMode: ");
    printByte(opMode);
    
    /*
    regWrite(NODE_ADDR, 0xaa);
    uint8_t nodeAddr = regRead(NODE_ADDR);
    printString("NodeAddr: ");
    printByte(nodeAddr);
     */
    
    // set variable packet length, turn off CRC for now
    regWrite(PCK_CFG1, (regRead(PCK_CFG1) | 0x80) & ~0x10);
    
    // set TX start condition to "at least one byte in FIFO"
    regWrite(FIFO_THRESH, regRead(FIFO_THRESH) | 0x80);
    
    regWrite(FIFO, 1); // packet length
    regWrite(FIFO, payload); // 1 byte payload
    
    // get "PacketSent" on DIO0 (default)
    regWrite(DIO_MAP1, regRead(DIO_MAP1) & ~0xc0);
    
    printString("Sending payload: ");
    printByte(payload);
    
    setMode(MODE_TX);
    
    loop_until_bit_is_set(irqFlags2, 3);
    printString("PacketSent\r\n");

    // better wait a bit before going to standby?
    _delay_ms(10);
    setMode(MODE_STDBY);
}

size_t sendString(char *payload) {
    size_t len = fmin(strlen(payload), 64);
    
    regWrite(PCK_CFG1, (regRead(PCK_CFG1) | 0x80) & ~0x10);
    regWrite(FIFO_THRESH, regRead(FIFO_THRESH) | 0x80);
    
    spiSel();
    transmit(FIFO);
    transmit(len);
    for (size_t i = 0; i < len; i++) {
        transmit(payload[i]);
    }
    spiDes();
    
    printString("Sending payload...\r\n");    
    setMode(MODE_TX);
    
    loop_until_bit_is_set(irqFlags2, 3);
    printString("PacketSent\r\n");
    
    _delay_ms(10);
    setMode(MODE_STDBY);
    
    return len;
}

uint8_t receiveByte(void) {
    
    // set variable packet length, turn off CRC for now
    regWrite(PCK_CFG1, (regRead(PCK_CFG1) | 0x80) & ~0x10);
    
    // get "PayloadReady" on DIO0
    regWrite(DIO_MAP1, (regRead(DIO_MAP1) & ~0x80) | 0x40);
    
    printString("Starting receiving...\r\n");    
    setMode(MODE_RX);
    
    loop_until_bit_is_set(irqFlags2, 2);
    printString("PayloadReady\r\n");
    
    // can also read FIFO after going to standby
    uint8_t len = regRead(FIFO);
    uint8_t payload = regRead(FIFO);
    
    printString("Length: ");
    printUint(len);
    printString("Payload: ");
    printByte(payload);
    
    _delay_ms(10);
    setMode(MODE_STDBY);
    
    return payload;
}