/* hrf69.c 03/04/2016 D.J.Whale * * Hope RF RFM69 radio controller low level register interface. */ #include <stdlib.h> #include "system.h" #include "hrfm69.h" #include "spi.h" #include "trace.h" #include "gpio.h" /*---------------------------------------------------------------------------*/ // Write an 8 bit value to a register void HRF_writereg(uint8_t addr, uint8_t data) { TRACE_OUTS("writereg "); TRACE_OUTN(addr); TRACE_OUTC(' '); TRACE_OUTN(data); TRACE_NL(); spi_select(); spi_byte(addr | HRF_MASK_WRITE_DATA); spi_byte(data); spi_deselect(); } /*---------------------------------------------------------------------------*/ // Read an 8 bit value from a register uint8_t HRF_readreg(uint8_t addr) { uint8_t result; spi_select(); spi_byte(addr); result = spi_byte(0x00); spi_deselect(); return result; } /*---------------------------------------------------------------------------*/ // Write all bytes in buf to the payload FIFO, in a single burst void HRF_writefifo_burst(uint8_t* buf, uint8_t len) { spi_select(); spi_byte(HRF_ADDR_FIFO | HRF_MASK_WRITE_DATA); spi_frame(buf, NULL, len); spi_deselect(); } /*---------------------------------------------------------------------------*/ // Read bytes from FIFO in burst mode. // Never reads more than buflen bytes // If rxlen != NULL, assumes payload is count byte preceded // and will read that number of bytes following it, // and report actual bytes read in *rxlen. // count byte is always returned as first byte of buffer HRF_RESULT HRF_readfifo_burst(uint8_t* buf, uint8_t buflen, uint8_t* rxlen) { uint8_t data; uint8_t count; spi_select(); /* Read the first byte, and then decide how to do byte counting */ data = spi_byte(ADDR_FIFO); count = 1; /* Already received 1 byte */ *(buf++) = data; /* always return to user, regardless of if count byte */ /* Decide byte-counting strategy */ if (rxlen != NULL) { /* count-byte preceeded */ if (data > buflen) { /* Payload won't fit into user buffer */ spi_deselect(); return HRF_RESULT_ERR_BUFFER_TOO_SMALL; } /* else, first byte is count byte, reduce buflen and use as count */ buflen = data; } else { /* buflen is expected length of payload */ buflen--; /* Have already received one byte */ } /* buflen is now expected length, count is byte received counter */ while (buflen != 0) { data = spi_byte(ADDR_FIFO); *(buf++) = data; buflen--; count++; } spi_deselect(); if (rxlen != NULL) { /* Record count of actual bytes received */ *rxlen = count; } return HRF_RESULT_OK; } /*---------------------------------------------------------------------------*/ // Check to see if a register matches a specific value or not HRF_RESULT HRF_checkreg(uint8_t addr, uint8_t mask, uint8_t value) { uint8_t regval = HRF_readreg(addr); if ((regval & mask) == value) { return HRF_RESULT_OK_TRUE; } return HRF_RESULT_OK_FALSE; } /*---------------------------------------------------------------------------*/ // Poll a register until it meets some criteria void HRF_pollreg(uint8_t addr, uint8_t mask, uint8_t value) { if (gpio_sim) { TRACE_OUTS("gpio simulated, bailing early to prevent lockup\n"); return; } while (! HRF_checkreg(addr, mask, value)) { // busy wait //TODO: No timeout or error recovery? Can cause permanent lockup } } /*---------------------------------------------------------------------------*/ // Clear any data in the HRF payload FIFO, by reading until empty void HRF_clear_fifo(void) { //TODO: max fifolen is 66, should bail after that to prevent lockup //especially if radio crashed and SPI always returns stuck flag bit while ((HRF_readreg(HRF_ADDR_IRQFLAGS2) & HRF_MASK_FIFONOTEMPTY) == HRF_MASK_FIFONOTEMPTY) { HRF_readreg(HRF_ADDR_FIFO); } } /***** END OF FILE *****/