diff --git a/src/energenie/drv/hrfm69.c b/src/energenie/drv/hrfm69.c index 2f89775..1a85575 100644 --- a/src/energenie/drv/hrfm69.c +++ b/src/energenie/drv/hrfm69.c @@ -9,6 +9,9 @@ #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) { @@ -48,11 +51,7 @@ } -//TODO: where is the buffer memory defined? -//perhaps pass in buffer memory and maxlen -//how do we know the actual length of buffer written to? -//pass in ptr to len variable -uint8_t* HRF_readfifo_burst(void) +void HRF_readfifo_burst(uint8_t* buf, uint8_t len) { //def HRF_readfifo_burst(): // """Read bytes from the payload FIFO using burst read""" @@ -71,7 +70,6 @@ // buf.append(data) // spi.deselect() // return buf - return (void*)0; // TODO } @@ -93,19 +91,17 @@ } -// Wait for HRF to be ready after last command -void HRF_wait_ready(void) +// Clear any data in the HRF payload FIFO, by reading until empty +void HRF_clear_fifo(void) { - HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY); + while ((HRF_readreg(HRF_ADDR_IRQFLAGS2) & HRF_MASK_FIFONOTEMPTY) == HRF_MASK_FIFONOTEMPTY) + { + HRF_readreg(HRF_ADDR_FIFO); + } } -// 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); -} - +/***** HIGH LEVEL PAYLOAD INTERFACE ******************************************/ // Change the operating mode of the HRF radi void HRF_change_mode(uint8_t mode) @@ -114,16 +110,31 @@ } -// Clear any data in the HRF payload FIFO, by reading until empty -void HRF_clear_fifo(void) +// Wait for HRF to be ready after last command +void HRF_wait_ready(void) { - while ((HRF_readreg(HRF_ADDR_IRQFLAGS2) & HRF_MASK_FIFONOTEMPTY) == HRF_MASK_FIFONOTEMPTY) + 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_readreg(HRF_ADDR_FIFO); + 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) { @@ -135,14 +146,9 @@ } -//TODO: unnecessary level of runtime indirection? -//TODO: where is the buffer memory defined? -//perhaps pass in buffer memory and maxlen -//how do we know the actual length of buffer written to? -//pass in ptr to len variable -uint8_t* HRF_receive_payload(void) +void HRF_receive_payload(uint8_t* buf, uint8_t len) { - return HRF_readfifo_burst(); + return HRF_readfifo_burst(buf, len); } @@ -159,15 +165,5 @@ } -// 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++; - } -} +/***** END OF FILE *****/ - -//# END diff --git a/src/energenie/drv/hrfm69.h b/src/energenie/drv/hrfm69.h index 253dfa9..986d4d3 100644 --- a/src/energenie/drv/hrfm69.h +++ b/src/energenie/drv/hrfm69.h @@ -103,44 +103,39 @@ #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); extern void HRF_writefifo_burst(uint8_t* buf, uint8_t len); -//TODO unnecessary level of runtime indirection? -//TODO where is the buffer memory defined? -//perhaps pass in buffer memory and maxlen -//how do we know the actual length of buffer written to? -//pass in ptr to len variable -extern uint8_t* HRF_readfifo_burst(void); +extern void HRF_readfifo_burst(uint8_t* buf, uint8_t len); extern HRF_RESULT HRF_checkreg(uint8_t addr, uint8_t mask, uint8_t value); extern void HRF_pollreg(uint8_t addr, uint8_t mask, uint8_t value); +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_change_mode(uint8_t mode); - -extern void HRF_clear_fifo(void); +extern void HRF_config(HRF_CONFIG_REC* config, uint8_t len); extern HRF_RESULT HRF_check_payload(void); - -//TODO unnecessary level of runtime indirection? -//TODO where is the buffer memory defined? -//perhaps pass in buffer memory and maxlen -//how do we know the actual length of buffer written to? -//pass in ptr to len variable -extern uint8_t* HRF_receive_payload(void); +extern void HRF_receive_payload(uint8_t* buf, uint8_t len); extern void HRF_send_payload(uint8_t* payload, uint8_t len); -extern void HRF_config(HRF_CONFIG_REC* config, uint8_t len); #endif diff --git a/src/energenie/drv/hrfm69_test.c b/src/energenie/drv/hrfm69_test.c index 452a3f3..3a99674 100644 --- a/src/energenie/drv/hrfm69_test.c +++ b/src/energenie/drv/hrfm69_test.c @@ -54,7 +54,9 @@ static uint8_t read_ver(void); static void reset(void); + void hrf_test_send_ook_tone(void); +void hrf_test_send_energenie_ook_switch(void); #if defined(HRFM69_TEST) @@ -86,8 +88,9 @@ TRACE_OUTS("testing...\n"); hrf_test_send_ook_tone(); - //spi_finished(); + //hrf_test_send_energenie_ook_switch(); + //spi_finished(); gpio_finished(); return 0; @@ -115,30 +118,32 @@ HRF_CONFIG_REC config_OOK[] = { - {HRF_ADDR_REGDATAMODUL, HRF_VAL_REGDATAMODUL_OOK}, // modulation scheme OOK - {HRF_ADDR_FDEVMSB, 0}, // frequency deviation -> 0kHz - {HRF_ADDR_FDEVLSB, 0}, // frequency deviation -> 0kHz - {HRF_ADDR_FRMSB, HRF_VAL_FRMSB433}, // carrier freq -> 433.92MHz 0x6C7AE1 - {HRF_ADDR_FRMID, HRF_VAL_FRMID433}, // carrier freq -> 433.92MHz 0x6C7AE1 - {HRF_ADDR_FRLSB, HRF_VAL_FRLSB433}, // carrier freq -> 433.92MHz 0x6C7AE1 - {HRF_ADDR_RXBW, HRF_VAL_RXBW120}, // channel filter bandwidth 120kHz - {HRF_ADDR_BITRATEMSB, 0x1A}, // 4800b/s - {HRF_ADDR_BITRATELSB, 0x0B}, // 4800b/s - {HRF_ADDR_PREAMBLELSB, 0}, // preamble size LSB 0 - {HRF_ADDR_SYNCCONFIG, HRF_VAL_SYNCCONFIG0}, // Size of the Sync word - //{HRF_ADDR_SYNCVALUE1, 0x81}, - //{HRF_ADDR_SYNCVALUE2, 0x00}, - //{HRF_ADDR_SYNCVALUE3, 0x00}, - //{HRF_ADDR_SYNCVALUE4, 0x00}, - {HRF_ADDR_PACKETCONFIG1, 0x00}, // Fixed length, no Manchester coding - {HRF_ADDR_PAYLOADLEN, 2}, // Payload Length - {HRF_ADDR_FIFOTHRESH, 1} // Condition to start packet transmission: exceeds 7 bytes in FIFO + {HRF_ADDR_REGDATAMODUL, HRF_VAL_REGDATAMODUL_OOK}, // modulation scheme OOK + {HRF_ADDR_FDEVMSB, 0}, // frequency deviation:0kHz + {HRF_ADDR_FDEVLSB, 0}, // frequency deviation:0kHz + {HRF_ADDR_FRMSB, HRF_VAL_FRMSB433}, // carrier freq:433.92MHz 0x6C7AE1 + {HRF_ADDR_FRMID, HRF_VAL_FRMID433}, // carrier freq:433.92MHz 0x6C7AE1 + {HRF_ADDR_FRLSB, HRF_VAL_FRLSB433}, // carrier freq:433.92MHz 0x6C7AE1 + {HRF_ADDR_RXBW, HRF_VAL_RXBW120}, // channel filter bandwidth:120kHz + {HRF_ADDR_BITRATEMSB, 0x1A}, // bitrate:4800b/s + {HRF_ADDR_BITRATELSB, 0x0B}, // bitrate:4800b/s + {HRF_ADDR_PREAMBLELSB, 0}, // preamble size LSB + {HRF_ADDR_SYNCCONFIG, HRF_VAL_SYNCCONFIG0}, // Size of sync word + {HRF_ADDR_PACKETCONFIG1, 0x00}, // Fixed length, no Manchester coding + //{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)) + // Send a test tone using OOK modulation void hrf_test_send_ook_tone(void) { + /* two blips, to help prove the 01 at start */ + static uint8_t payload[] = { + 0x41, 0x40 + }; + int i; TRACE_OUTS("standby mode\n"); @@ -147,6 +152,8 @@ TRACE_OUTS("config\n"); HRF_config(config_OOK, CONFIG_OOK_COUNT); + HRF_writereg(HRF_ADDR_PAYLOADLEN, sizeof(payload)); + HRF_writereg(HRF_ADDR_FIFOTHRESH, sizeof(payload)-1); TRACE_OUTS("transmitter mode\n"); HRF_change_mode(HRF_MODE_TRANSMITTER); @@ -165,20 +172,24 @@ TRACE_OUTS("wait for txready in irqflags1\n"); HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY|HRF_MASK_TXREADY, HRF_MASK_MODEREADY|HRF_MASK_TXREADY); - /* A regular tone */ - static uint8_t payload[] = { - 0x81, 0x00 //0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA - }; + //NOTE: This uses a payloadlen of 2, and polls PACKETSENT in the repeat loop. + //A better way to do it would be to set payloadlen to the total length, + //check FIFOLEVEL < limit before putting more into FIFO + //and check PACKETSENT at the end. That's how the original C code does it, + //but there seems to be an error in the payload length calculation. while (1) { for (i=0; i<1; i++) { TRACE_OUTS("tx\n"); HRF_writefifo_burst(payload, sizeof(payload)); + //TODO: should check FIFO level here?? HRF_pollreg(HRF_ADDR_IRQFLAGS2, HRF_MASK_PACKETSENT, HRF_MASK_PACKETSENT); // wait for Packet sent } + //TODO: should check PACKETSENT here?? + uint8_t irqflags1 = HRF_readreg(HRF_ADDR_IRQFLAGS1); uint8_t irqflags2 = HRF_readreg(HRF_ADDR_IRQFLAGS2); @@ -196,6 +207,130 @@ } delaysec(1); } + + //NOTE: packetsent is only cleared when exiting TX (i.e. to STANDBY or RECEIVE) +} + + +/* Note, D0123 are transmitted as D3210 + # Coded as per the (working) C code would be: + # b 3210 + # 0000 UNUSED 0 + # 0001 UNUSED 1 + # 0010 socket 4 off 2 + # 0011 socket 4 on 3 + # 0100 UNUSED 4 + # 0101 UNUSED 5 + # 0110 socket 2 off 6 + # 0111 socket 2 on 7 + # 1000 UNUSED 8 + # 1001 UNUSED 9 + # 1010 socket 3 off A + # 1011 socket 3 on B + # 1100 all off C + # 1101 all on D + # 1110 socket 1 off E + # 1111 socket 1 on F +*/ + + +// A hard coded test of switching an Energenie switch on and off +void hrf_test_send_energenie_ook_switch(void) +{ + /* manual preamble, 20 bit encoded address, 4 encoded data bits */ + static uint8_t payload[17] = { + 0x00, // pad away from the radio inserted 01 at start + 0x80, 0x00, 0x00, 0x00, // preamble pulse with timing violation gap + // Energenie 'random' 20 bit address is 6C6C6 + // 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 +#define REPEATS 1 + + int i; + + TRACE_OUTS("standby mode\n"); + HRF_change_mode(HRF_MODE_STANDBY); + HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY); + + TRACE_OUTS("config\n"); + HRF_config(config_OOK, CONFIG_OOK_COUNT); + HRF_writereg(HRF_ADDR_PAYLOADLEN, sizeof(payload)); + HRF_writereg(HRF_ADDR_FIFOTHRESH, sizeof(payload)-1); + + TRACE_OUTS("transmitter mode\n"); + HRF_change_mode(HRF_MODE_TRANSMITTER); + HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY); + + uint8_t irqflags1 = HRF_readreg(HRF_ADDR_IRQFLAGS1); + uint8_t irqflags2 = HRF_readreg(HRF_ADDR_IRQFLAGS2); + TRACE_OUTS("irqflags1,2="); + TRACE_OUTN(irqflags1); + TRACE_OUTC(','); + TRACE_OUTN(irqflags2); + TRACE_NL(); + + TRACE_OUTS("wait for txready in irqflags1\n"); + HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY|HRF_MASK_TXREADY, HRF_MASK_MODEREADY|HRF_MASK_TXREADY); + + + uint8_t last_byte = ON; + + while (1) + { + payload[sizeof(payload)-1] = last_byte; + TRACE_OUTS("tx:"); + TRACE_OUTN(last_byte); + TRACE_NL(); + + for (i=0; i30 bytes in FIFO #----- HOPERF RADIO INTERFACE ------------------------------------------------- @@ -332,21 +334,42 @@ #} +# first payload +# (radio sync 4 bytes, not counted) +# address 10 bytes +# command 2 bytes +# i.e. 12 bytes +# so, >30 is 2 and a bit payloads loaded. +# 66 byte FIFO size +# so that means FIFO roughly half full before starts tx, +# FIFO at or below half full before another payload will be added + +# packetsent is based on the fixed payload length +# which is (13 + 8 * 17) = 149 +# This maths looks wrong. +# 10 bytes of address, two bytes of command = 12 +# 13 includes the dummy byte at the start, but that is for the SPI address and not counted + def HRF_send_OOK_payload(payload): """Send a payload multiple times""" + #TODO: note the zero at the start was the C method of reserving space for address byte p1 = [0x00] + payload # This sync pattern does not match C code, but it works. # The sync pattern from the C code does not work here # Note that buf[0] in the C is undefined due to being uninitialised + # but it is a space for the address byte in the C fifo burst routine pn = [0x00,0x80,0x00,0x00,0x00] + payload # from the C - # Currently there is no explanation for this. (looks like baud rate was wrong) + #TODO: note the zero at the start was the C method of reserving space for address byte + # which is not needed here in this python. + # This is old test data due to wrong baud rate - deprecated #pn = [0x80,0x80,0x80,0x80,0x80] + payload HRF_pollreg(ADDR_IRQFLAGS1, MASK_MODEREADY|MASK_TXREADY, MASK_MODEREADY|MASK_TXREADY) HRF_writefifo_burst(p1) for i in range(8): + # waits for <31 bytes in FIFO HRF_pollreg(ADDR_IRQFLAGS2, MASK_FIFOLEVEL, 0) HRF_writefifo_burst(pn) @@ -357,6 +380,8 @@ if (reg & (MASK_FIFONOTEMPTY) != 0) or ((reg & MASK_FIFOOVERRUN) != 0): warning("Failed to send repeated payload to HRF") + # Note: packetsent is only cleared on exit from TX (i.e to STANDBY or RECEIVE) + #----- RADIO API --------------------------------------------------------------