diff --git a/src/energenie/drv/hrfm69.c b/src/energenie/drv/hrfm69.c index 0f28ba1..01160cb 100644 --- a/src/energenie/drv/hrfm69.c +++ b/src/energenie/drv/hrfm69.c @@ -60,53 +60,71 @@ /*---------------------------------------------------------------------------*/ // 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 +// First received byte is the count of remaining bytes +// That byte is also returned in the user buffer. +// Note the user buffer can be > FIFO_MAX, but there is no flow control +// in the HRF driver yet, so you might get an underflow error if data is read +// quicker than it comes in on-air. You might get an overflow error if +// data comes in quicker than it is read. -HRF_RESULT HRF_readfifo_burst(uint8_t* buf, uint8_t buflen, uint8_t* rxlen) + +HRF_RESULT HRF_readfifo_burst_cbp(uint8_t* buf, uint8_t buflen) { uint8_t data; - uint8_t count; spi_select(); - /* Read the first byte, and then decide how to do byte counting */ + /* Read the first byte, and then decide how many remaining bytes to receive */ data = spi_byte(ADDR_FIFO); - count = 1; /* Already received 1 byte */ - *(buf++) = data; /* always return to user, regardless of if count byte */ + *(buf++) = data; /* the count byte is always returned as first byte of user buffer */ - /* 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 */ + /* Validate the payload len against the supplied user buffer */ + if (data > buflen) + { + spi_deselect(); + return HRF_RESULT_ERR_BUFFER_TOO_SMALL; } - /* buflen is now expected length, count is byte received counter */ + buflen = data; /* now the expected payload length */ + 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; + //TODO: Read irqflags + //if underflow, this is an error (reading out too quick) + //if overflow, this is an error (not reading out quick enough) + //if not empty at end, this is a warning (might be ok, but user might want to clear_fifo after) + return HRF_RESULT_OK; +} + + +/*---------------------------------------------------------------------------*/ +// Read bytes from FIFO in burst mode. +// Tries to read exactly buflen bytes + +HRF_RESULT HRF_readfifo_burst_len(uint8_t* buf, uint8_t buflen) +{ + uint8_t data; + + spi_select(); + + while (buflen != 0) + { + data = spi_byte(ADDR_FIFO); + *(buf++) = data; + buflen--; } + spi_deselect(); + + //TODO: Read irqflags + //if underflow, this is an error (reading out too quick) + //if overflow, this is an error (not reading out quick enough) + //if not empty at end, this is a warning (might be ok, but user might want to clear_fifo after) return HRF_RESULT_OK; } diff --git a/src/energenie/drv/hrfm69.h b/src/energenie/drv/hrfm69.h index ab200c3..aab23a0 100644 --- a/src/energenie/drv/hrfm69.h +++ b/src/energenie/drv/hrfm69.h @@ -118,7 +118,9 @@ extern void HRF_writefifo_burst(uint8_t* buf, uint8_t len); -extern HRF_RESULT HRF_readfifo_burst(uint8_t* buf, uint8_t buflen, uint8_t* rxlen); +extern HRF_RESULT HRF_readfifo_burst_cbp(uint8_t* buf, uint8_t buflen); + +extern HRF_RESULT HRF_readfifo_burst_len(uint8_t* buf, uint8_t buflen); extern HRF_RESULT HRF_checkreg(uint8_t addr, uint8_t mask, uint8_t value); diff --git a/src/energenie/drv/radio.c b/src/energenie/drv/radio.c index 6a620d8..c5b8ab6 100644 --- a/src/energenie/drv/radio.c +++ b/src/energenie/drv/radio.c @@ -468,16 +468,39 @@ /*---------------------------------------------------------------------------*/ // read a single payload from the payload buffer +// this reads a fixed length payload -RADIO_RESULT radio_get_payload(uint8_t* buf, uint8_t buflen, uint8_t* rxlen) +RADIO_RESULT radio_get_payload_len(uint8_t* buf, uint8_t buflen) { if (buflen > MAX_FIFO_BUFFER) - { /* At the moment, the receiver cannot cope with payloads > 1 FIFO buffer. + { /* At the moment, the receiver cannot reliably cope with payloads > 1 FIFO buffer. * It *might* be able to in the future. */ return RADIO_RESULT_ERR_LONG_PAYLOAD; } - HRF_RESULT r = HFR_readfifo_burst(buf, buflen, rxlen); + HRF_RESULT r = HFR_readfifo_burst_len(buf, buflen); + if (r != HRF_RESULT_OK) + { + return RADIO_RESULT_ERR_READ_FAILED; + } + return RADIO_RESULT_OK; +} + +/*---------------------------------------------------------------------------*/ +// read a single payload from the payload buffer +// this reads count byte preceeded payloads. +// The CBP payload always has the count byte in the first byte +// and this is returned in the user buffer too. + +RADIO_RESULT radio_get_payload_cbp(uint8_t* buf, uint8_t buflen) +{ + if (buflen > MAX_FIFO_BUFFER) + { /* At the moment, the receiver cannot reliably cope with payloads > 1 FIFO buffer. + * It *might* be able to in the future. + */ + return RADIO_RESULT_ERR_LONG_PAYLOAD; + } + HRF_RESULT r = HFR_readfifo_burst_cbp(buf, buflen); if (r != HRF_RESULT_OK) { return RADIO_RESULT_ERR_READ_FAILED; diff --git a/src/energenie/drv/radio.h b/src/energenie/drv/radio.h index bb00197..7097075 100644 --- a/src/energenie/drv/radio.h +++ b/src/energenie/drv/radio.h @@ -39,7 +39,9 @@ extern RADIO_RESULT radio_is_receive_waiting(void); -extern RADIO_RESULT radio_get_payload(uint8_t* buf, uint8_t buflen, uint8_t* rxlen) +extern RADIO_RESULT radio_get_payload_len(uint8_t* buf, uint8_t buflen); + +extern RADIO_RESULT radio_get_payload_cbp(uint8_t* buf, uint8_t buflen); extern void radio_standby(void); diff --git a/src/energenie/radio2.py b/src/energenie/radio2.py index d289b37..b96099d 100644 --- a/src/energenie/radio2.py +++ b/src/energenie/radio2.py @@ -33,7 +33,8 @@ radio_send_payload_fn = libradio["radio_send_payload"] radio_receiver_fn = libradio["radio_receiver"] radio_is_receive_waiting_fn = libradio["radio_is_receive_waiting"] -radio_get_payload_fn = libradio["radio_get_payload"] +radio_get_payload_len_fn = libradio["radio_get_payload_len"] +radio_get_payload_cbp_fn = libradio["radio_get_payload_cbp"] radio_standby_fn = libradio["radio_standby"] radio_finished_fn = libradio["radio_finished"] @@ -186,24 +187,54 @@ @untested def receive(size=None): """Receive a single payload""" - #NOTE for OOK, need to put in expected size of 16 bytes (includes preamble) - if size == None: # count byte preceeded - size = MAX_RX_SIZE - rxsize = ctypes.byref(size) + if size == None: + return receive_cbp() + else: + return receive_len(size) - else: # fixed size receive - rxsize = ctypes.c_ubyte(None) - Buffer = ctypes.c_ubyte * size +@untested +def receive_cbp(): + """Receive a count byte preceded payload""" + + bufsize = MAX_RX_SIZE + + Buffer = ctypes.c_ubyte * bufsize rxbuf = Buffer() - buflen = ctypes.c_ubyte(size) + buflen = ctypes.c_ubyte(bufsize) + #RADIO_RESULT radio_get_payload_cbp(uint8_t* buf, uint8_t buflen) - #RADIO_RESULT radio_get_payload(uint8_t* buf, uint8_t buflen, uint8_t* rxlen) + result = radio_get_payload_cbp_fn(rxbuf, buflen) - result = radio_get_payload_fn(rxbuf, buflen, rxsize) if result != 0: # RADIO_RESULT_OK - raise RuntimeError("Receive failed, error code %d" % result) + raise RuntimeError("Receive failed, error code %s" % hex(result)) + + size = 1+rxbuf[0] # The count byte in the payload + + # turn buffer into a list of bytes, using 'size' as the counter + rxlist = [] + for i in range(size): + rxlist.append(rxbuf[i]) + + return rxlist # Python len(rxlist) tells us how many bytes including length byte if present + + +@untested +def receive_len(size): + """Receive a fixed payload size""" + + bufsize = size + + Buffer = ctypes.c_ubyte * bufsize + rxbuf = Buffer() + buflen = ctypes.c_ubyte(bufsize) + #RADIO_RESULT radio_get_payload_len(uint8_t* buf, uint8_t buflen) + + result = radio_get_payload_len_fn(rxbuf, buflen) + + if result != 0: # RADIO_RESULT_OK + raise RuntimeError("Receive failed, error code %s" % hex(result)) # turn buffer into a list of bytes, using 'size' as the counter rxlist = [] diff --git a/src/monitor.py b/src/monitor.py index d1e56b9..dd9a061 100644 --- a/src/monitor.py +++ b/src/monitor.py @@ -32,7 +32,7 @@ while True: # See if there is a payload, and if there is, process it if radio.is_receive_waiting(): - ##trace("receiving payload") + trace("receiving payload") payload = radio.receive() try: decoded = OpenThings.decode(payload)