diff --git a/src/energenie/drv/hrfm69.c b/src/energenie/drv/hrfm69.c index 1a85575..27f1757 100644 --- a/src/energenie/drv/hrfm69.c +++ b/src/energenie/drv/hrfm69.c @@ -1,18 +1,17 @@ /* hrf69.c 03/04/2016 D.J.Whale * - * Hope RF RFM69 radio controller code. + * Hope RF RFM69 radio controller low level register interface. */ -#include #include "system.h" #include "hrfm69.h" #include "spi.h" #include "trace.h" -/***** LOW LEVEL REGISTER INTERFACE ******************************************/ - +/*---------------------------------------------------------------------------*/ // Write an 8 bit value to a register + void HRF_writereg(uint8_t addr, uint8_t data) { TRACE_OUTS("writereg "); @@ -28,7 +27,9 @@ } +/*---------------------------------------------------------------------------*/ // Read an 8 bit value from a register + uint8_t HRF_readreg(uint8_t addr) { uint8_t result; @@ -41,7 +42,9 @@ } +/*---------------------------------------------------------------------------*/ // 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(); @@ -51,6 +54,8 @@ } +/*---------------------------------------------------------------------------*/ + void HRF_readfifo_burst(uint8_t* buf, uint8_t len) { //def HRF_readfifo_burst(): @@ -73,7 +78,9 @@ } +/*---------------------------------------------------------------------------*/ // 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); @@ -81,7 +88,9 @@ } +/*---------------------------------------------------------------------------*/ // Poll a register until it meets some criteria + void HRF_pollreg(uint8_t addr, uint8_t mask, uint8_t value) { while (! HRF_checkreg(addr, mask, value)) @@ -91,7 +100,9 @@ } +/*---------------------------------------------------------------------------*/ // Clear any data in the HRF payload FIFO, by reading until empty + void HRF_clear_fifo(void) { while ((HRF_readreg(HRF_ADDR_IRQFLAGS2) & HRF_MASK_FIFONOTEMPTY) == HRF_MASK_FIFONOTEMPTY) @@ -101,69 +112,5 @@ } -/***** HIGH LEVEL PAYLOAD INTERFACE ******************************************/ - -// Change the operating mode of the HRF radi -void HRF_change_mode(uint8_t mode) -{ - HRF_writereg(HRF_ADDR_OPMODE, mode); -} - - -// Wait for HRF to be ready after last command -void HRF_wait_ready(void) -{ - HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY); -} - - -// Load a table of configuration values into HRF registers -void HRF_config(HRF_CONFIG_REC* config, uint8_t count) -{ - while (count-- != 0) - { - HRF_writereg(config->addr, config->value); - config++; - } -} - - -// Wait for the HRF to be ready, and ready for tx, after last command -void HRF_wait_txready(void) -{ - HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY|HRF_MASK_TXREADY, HRF_MASK_MODEREADY|HRF_MASK_TXREADY); -} - - -// Check if there is a payload in the FIFO waiting to be processed -HRF_RESULT HRF_check_payload(void) -{ - //TODO: First read might be superflous, but left in just in case - uint8_t irqflags1 = HRF_readreg(HRF_ADDR_IRQFLAGS1); - - uint8_t irqflags2 = HRF_readreg(HRF_ADDR_IRQFLAGS2); - return (irqflags2 & HRF_MASK_PAYLOADRDY) == HRF_MASK_PAYLOADRDY; -} - - -void HRF_receive_payload(uint8_t* buf, uint8_t len) -{ - return HRF_readfifo_burst(buf, len); -} - - -// Send a preformatted payload of data -void HRF_send_payload(uint8_t* payload, uint8_t len) -{ - uint8_t reg; - - HRF_writefifo_burst(payload, len); - HRF_pollreg(HRF_ADDR_IRQFLAGS2, HRF_MASK_PACKETSENT, HRF_MASK_PACKETSENT); - reg = HRF_readreg(HRF_ADDR_IRQFLAGS2); - //if ((reg & HRF_MASK_FIFONOTEMPTY) != 0) or ((reg & HRF_MASK_FIFOOVERRUN) != 0): - // warning("Failed to send payload to HRF") -} - - /***** END OF FILE *****/ diff --git a/src/energenie/drv/hrfm69.h b/src/energenie/drv/hrfm69.h index 362dde1..3223fe8 100644 --- a/src/energenie/drv/hrfm69.h +++ b/src/energenie/drv/hrfm69.h @@ -107,8 +107,6 @@ #define HRF_VAL_FIFOTHRESH30 0x1E // Condition to start packet transmission: wait for 30 bytes in FIFO -/* Low level register interface */ - extern void HRF_writereg(uint8_t addr, uint8_t data); extern uint8_t HRF_readreg(uint8_t addr); @@ -124,23 +122,6 @@ extern void HRF_clear_fifo(void); -/* High level payload interface */ - -extern void HRF_change_mode(uint8_t mode); - -extern void HRF_wait_ready(void); - -extern void HRF_wait_txready(void); - -extern void HRF_config(HRF_CONFIG_REC* config, uint8_t len); - -extern HRF_RESULT HRF_check_payload(void); - -extern void HRF_receive_payload(uint8_t* buf, uint8_t len); - -extern void HRF_send_payload(uint8_t* payload, uint8_t len); - - #endif /***** END OF FILE *****/ diff --git a/src/energenie/drv/hrfm69_test.c b/src/energenie/drv/hrfm69_test.c index eaa69b4..66c6569 100644 --- a/src/energenie/drv/hrfm69_test.c +++ b/src/energenie/drv/hrfm69_test.c @@ -85,7 +85,7 @@ } TRACE_OUTS("standby mode\n"); - HRF_change_mode(HRF_MODE_STANDBY); + HRF_writereg(HRF_ADDR_OPMODE, HRF_MODE_STANDBY); HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY); @@ -144,7 +144,7 @@ //{HRF_ADDR_PAYLOADLEN, 2}, // Payload Length //{HRF_ADDR_FIFOTHRESH, 1} // Start tx when this is exceeded }; -#define CONFIG_OOK_COUNT (sizeof(config_OOK)/sizeof(HRF_CONFIG_REC)) +#define CONFIG_OOK_LEN (sizeof(config_OOK)/sizeof(HRF_CONFIG_REC)) // Send a test tick using OOK modulation @@ -158,12 +158,17 @@ int i; TRACE_OUTS("config\n"); - HRF_config(config_OOK, CONFIG_OOK_COUNT); + for (i=0; iaddr, config->value); + config++; + } +} + + +/*---------------------------------------------------------------------------*/ +// Wait for the HRF to be ready, and ready for tx, after last command + +static void _wait_txready(void) +{ + HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY|HRF_MASK_TXREADY, HRF_MASK_MODEREADY|HRF_MASK_TXREADY); +} + + +/*---------------------------------------------------------------------------*/ +// Check if there is a payload in the FIFO waiting to be processed + +static int _payload_waiting(void) +{ + //TODO: First read might be superflous, but left in just in case + uint8_t irqflags1 = HRF_readreg(HRF_ADDR_IRQFLAGS1); + + uint8_t irqflags2 = HRF_readreg(HRF_ADDR_IRQFLAGS2); + return (irqflags2 & HRF_MASK_PAYLOADRDY) == HRF_MASK_PAYLOADRDY; +} + + +/***** PUBLIC ****************************************************************/ + + +/*---------------------------------------------------------------------------*/ void radio_init(void) { -#if 0 - - TRACE_OUTS("start\n"); + TRACE_OUTS("radio_init\n"); //gpio_init(); done by spi_init at moment spi_init(&radioConfig); @@ -148,36 +211,10 @@ } TRACE_OUTS("standby mode\n"); - HRF_change_mode(HRF_MODE_STANDBY); + _change_mode(HRF_MODE_STANDBY); HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY); - - - TRACE_OUTS("testing...\n"); - //hrf_test_send_ook_tick(); - hrf_test_send_energenie_ook_switch(); - - //spi_finished(); - gpio_finished(); - - return 0; -#endif -// // -// def init(): -// """Initialise the module ready for use""" -// spi.init_defaults() -// trace("RESET") -// -// # Note that if another program left GPIO pins in a different state -// # and did a dirty exit, the reset fails to work and the clear fifo hangs. -// # Might have to make the spi.init() set everything to inputs first, -// # then set to outputs, to make sure that the -// # GPIO registers are in a deterministic start state. -// spi.reset() # send a hardware reset to ensure radio in clean state -// -// HRF_clear_fifo() // not needed? } - /*---------------------------------------------------------------------------*/ void radio_modulation(RADIO_MODULATION mod) @@ -209,15 +246,11 @@ void radio_transmitter(RADIO_MODULATION mod) { -// def transmitter(fsk=None, ook=None): -// """Change into transmitter mode""" -// global mode -// -// trace("transmitter mode") -// modulation(fsk, ook) -// HRF_change_mode(MODE_TRANSMITER) -// mode = "TRANSMITTER" -// HRF_wait_txready() + TRACE_OUTS("radio_transmitter\n"); + radio_modulation(mod); + _change_mode(HRF_MODE_TRANSMITTER); + _wait_txready(); + //radio_data.modulation = mod; } @@ -225,89 +258,22 @@ void radio_transmit(uint8_t* payload, uint8_t len, uint8_t repeats) { -// NOTE: repeats parameter, needs to configure HRF payload sender to repeat -// packet that number of times. -// NOTE: Payload should already be bit encoded and preambled by time it gets here - -// def transmit(payload): -// """Transmit a single payload using the present modulation scheme""" -// if not modulation_fsk: -// HRF_send_OOK_payload(payload, repeats) // might not actually be different -// else: -// HRF_send_payload(payload, repeats) + TRACE_OUTS("radio_transmit\n"); + radio_transmitter(RADIO_MODULATION_OOK); //TODO use present state + radio_send_payload(payload, len, repeats); + radio_standby(); } /*---------------------------------------------------------------------------*/ +// Send a payload of data +//TODO: Rewrite this to use FIFOLEV and FIFOEMPTY with payloadlen=0 +//rather than PACKETSENT, as it will allow any number of repeats. -void radio_receiver(RADIO_MODULATION mod) +void radio_send_payload(uint8_t* payload, uint8_t len, uint8_t repeats) { -// def receiver(fsk=None, ook=None): -// """Change into receiver mode""" -// global mode -// -// trace("receiver mode") -// modulation(fsk, ook) -// HRF_change_mode(MODE_RECEIVER) -// HRF_wait_ready() -// mode = "RECEIVER" -} + TRACE_OUTS("send_payload\n"); - -/*---------------------------------------------------------------------------*/ - -RADIO_RESULT radio_isReceiveWaiting(void) -{ -// def isReceiveWaiting(): -// """Check to see if a payload is waiting in the receive buffer""" -// return HRF_check_payload() - return RADIO_RESULT_ERR_UNIMPLEMENTED; -} - - -/*---------------------------------------------------------------------------*/ - -RADIO_RESULT radio_receive(uint8_t* buf, uint8_t len) -{ -// def receive(): -// """Receive a single payload from the buffer using the present modulation scheme""" -// return HRF_receive_payload() - return RADIO_RESULT_ERR_UNIMPLEMENTED; -} - - -/*---------------------------------------------------------------------------*/ - -void radio_standby(void) -{ - //TODO: change radio mode to STANDBY to turn PA off and preserve power. -} - - -/*---------------------------------------------------------------------------*/ - -void radio_finished(void) -{ -// def finished(): -// """Close the library down cleanly when finished""" -// radio.standby() ?? -// spi.finished() ?? -// gpio.finished() ?? -} - - -/*---------------------------------------------------------------------------*/ - -// A hard coded test of switching an Energenie switch on and off -//TODO this is for testing only, will be simplified and moved into radio_transmit. -// -//TODO note that we want to change this to use FIFO level rather than PACKETSENT -//so that we can send arbitrary length packets with arbitrary number of repeats -//(i.e. not limited by the U8 size of the payloadlen register in HRF) - -static void hrf_test_send_energenie_ook_switch(void) -{ -#if 0 // Note, when PA starts up, radio inserts a 01 at start before any user data // we might need to pad away from this by sending a sync of many zero bits // to prevent it being misinterpreted as a preamble, and prevent it causing @@ -316,128 +282,150 @@ // Also need to confirm this bit only occurs when transmit actually starts, // and not on every FIFO load. - /* manual preamble, 20 bit encoded address, 4 encoded data bits */ - static uint8_t payload[16] = { - 0x80, 0x00, 0x00, 0x00, // preamble pulse with timing violation gap - // Energenie 'random' 20 bit address is 0x6C6C6 - // 0110 1100 0110 1100 0110 - // 0 encoded as 8 (1000) - // 1 encoded as E (1110) - 0x8E, 0xE8, 0xEE, 0x88, 0x8E, 0xE8, 0xEE, 0x88, 0x8E, 0xE8, - // Energenie 'switch 1 ON' command F 1111 (0xEE, 0xEE) - 0xEE, 0xEE - // Energenie 'switch 1 OFF' command E 1110 (0xEE, 0xE8) - //0xEE, 0xE8 - }; -/* Last byte of the payload for switch 1 */ -#define ON 0xEE -#define OFF 0xE8 -// Limited by U8 size of PAYLOADLEN reg (15*16=240) -#define REPEATS 15 -// To get longer repeats, we'll have to design a new 'unlimited' -// payload sender, and use FIFOEMPTY as a way to detect end of transmit. - int i; uint8_t irqflags1; uint8_t irqflags2; + /* CONFIGURE: Setup the radio for transmit of the correct payload length */ TRACE_OUTS("config\n"); - HRF_config(config_OOK, CONFIG_OOK_COUNT); + if ((unsigned int)repeats * (unsigned int)len > 255) + { + // This is a temporary situation until the new 'indefinite transmit' + // scheme is implemented using fifolevel only, and ignoring packetsent. + TRACE_FAIL("repeats*payloadlen > 255, can't configure\n"); + } + // the full packet/burst consists of repeated payloads // packetsent will trigger when this number of bytes have been transmitted - HRF_writereg(HRF_ADDR_PAYLOADLEN, sizeof(payload) * REPEATS); + HRF_writereg(HRF_ADDR_PAYLOADLEN, sizeof(payload) * repeats); // but the FIFO is filled in 1 message (4+10+2=16 byte) sections // level triggers when it 'strictly exceeds' level (i.e. 16 bytes starts tx, // and <=15 bytes triggers fifolevel irqflag to be cleared) HRF_writereg(HRF_ADDR_FIFOTHRESH, sizeof(payload)-1); - uint8_t last_byte = ON; - while (1) + /* Bring into transmitter mode and ramp up the PA */ + TRACE_OUTS("transmitter mode\n"); + _change_mode(HRF_MODE_TRANSMITTER); + + TRACE_OUTS("wait for modeready,txready in irqflags1\n"); + HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY|HRF_MASK_TXREADY, HRF_MASK_MODEREADY|HRF_MASK_TXREADY); + + irqflags1 = HRF_readreg(HRF_ADDR_IRQFLAGS1); + irqflags2 = HRF_readreg(HRF_ADDR_IRQFLAGS2); + TRACE_OUTS("irqflags1,2="); + TRACE_OUTN(irqflags1); + TRACE_OUTC(','); + TRACE_OUTN(irqflags2); + TRACE_NL(); + + + /* TRANSMIT: Transmit a number of bursts back to back */ + TRACE_OUTS("tx repeats in a single burst\n"); + + // send a number of payload repeats for the whole packet burst + for (i=0; i