| @@ -2,11 +2,27 @@ | |||||
| #include <strobe_rng_init.h> | #include <strobe_rng_init.h> | ||||
| #include <string.h> | |||||
| #include <board.h> | #include <board.h> | ||||
| #include <misc.h> | #include <misc.h> | ||||
| #include <radio.h> | #include <radio.h> | ||||
| #include <delay.h> | #include <delay.h> | ||||
| char * | |||||
| findeol(char *pos, size_t len) | |||||
| { | |||||
| while (len) { | |||||
| if (*pos == '\r' || *pos == '\n') | |||||
| return pos; | |||||
| pos++; | |||||
| len--; | |||||
| } | |||||
| return NULL; | |||||
| } | |||||
| void | void | ||||
| hexdump(uint8_t *ptr, size_t len) | hexdump(uint8_t *ptr, size_t len) | ||||
| { | { | ||||
| @@ -60,6 +76,86 @@ RadioEvents_t revents = { | |||||
| .RxError = rxerr, | .RxError = rxerr, | ||||
| }; | }; | ||||
| static uint8_t | |||||
| hexchartonib(char s) | |||||
| { | |||||
| switch (s) { | |||||
| case '0'...'9': | |||||
| return s - '0'; | |||||
| case 'a'...'f': | |||||
| return s - 'a' + 10; | |||||
| case 'A'...'F': | |||||
| return s - 'A' + 10; | |||||
| default: | |||||
| return -1; | |||||
| } | |||||
| } | |||||
| static bool | |||||
| hexdecode(char *buf, size_t len, uint8_t *out) | |||||
| { | |||||
| uint8_t topchr, botchr; | |||||
| if (len % 2) | |||||
| return -1; | |||||
| /* NB: only needed to silence a bad gcc warning */ | |||||
| topchr = -1; | |||||
| while (len) { | |||||
| if (len % 2) { | |||||
| /* bottom nibble */ | |||||
| botchr = hexchartonib(*buf); | |||||
| if (topchr == -1 || botchr == -1) | |||||
| return false; | |||||
| *out = topchr << 4 | botchr; | |||||
| out++; | |||||
| } else { | |||||
| /* top nibble */ | |||||
| topchr = hexchartonib(*buf); | |||||
| } | |||||
| len--; | |||||
| buf++; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| static const char pktstart[] = "pkt:"; | |||||
| static const size_t pktstartlen = sizeof pktstart - 1; | |||||
| static uint8_t pktbuf[128]; | |||||
| static void | |||||
| process_line(char *start, char *end) | |||||
| { | |||||
| size_t len; | |||||
| /* trim off leading CR/NL */ | |||||
| while (start < end && (*start == '\r' || *start == '\n')) | |||||
| start++; | |||||
| len = end - start; | |||||
| if (len >= pktstartlen && memcmp(start, pktstart, sizeof pktstart - 1) == 0) { | |||||
| start += pktstartlen; | |||||
| len -= pktstartlen; | |||||
| if (len % 2) { | |||||
| usb_printf("invalid pkt len\r\n"); | |||||
| return; | |||||
| } | |||||
| if (!hexdecode(start, len, pktbuf)) { | |||||
| usb_printf("invalid pkt\r\n"); | |||||
| return; | |||||
| } | |||||
| Radio.Send(pktbuf, len / 2); | |||||
| return; | |||||
| } | |||||
| usb_printf("line: %.*s", end - start, start); | |||||
| } | |||||
| int | int | ||||
| main(void) | main(void) | ||||
| { | { | ||||
| @@ -148,10 +244,70 @@ main(void) | |||||
| usb_printf("rx(0)...\r\n"); | usb_printf("rx(0)...\r\n"); | ||||
| Radio.Rx(0); | Radio.Rx(0); | ||||
| char inpbuf[1024]; | |||||
| char *lastcheck; | |||||
| char *endchr; | |||||
| int inpbufpos = 0; | |||||
| int cpylen; | |||||
| loop: | loop: | ||||
| BoardLowPowerHandler(); | BoardLowPowerHandler(); | ||||
| if (Radio.IrqProcess != NULL) | if (Radio.IrqProcess != NULL) | ||||
| Radio.IrqProcess(); | Radio.IrqProcess(); | ||||
| /* while we have data */ | |||||
| while (CDC_RX_LEN) { | |||||
| /* store last position */ | |||||
| lastcheck = &inpbuf[inpbufpos]; | |||||
| /* calculate how much space left */ | |||||
| cpylen = MIN(sizeof inpbuf - inpbufpos, CDC_RX_LEN); | |||||
| /* copy into buffer */ | |||||
| memcpy(&inpbuf[inpbufpos], CDC_RX_BUFFER, cpylen); | |||||
| /* and point to end of buffer */ | |||||
| inpbufpos += cpylen; | |||||
| do { | |||||
| /* find first end of line characters */ | |||||
| endchr = findeol(lastcheck, cpylen); | |||||
| if (endchr != NULL) { | |||||
| /* if so, process it */ | |||||
| process_line(inpbuf, endchr); | |||||
| /* skip end of line char */ | |||||
| endchr++; | |||||
| /* move remaining buffer to the beginning */ | |||||
| memmove(inpbuf, endchr, inpbufpos - (endchr - inpbuf)); | |||||
| /* and store new length */ | |||||
| inpbufpos = inpbufpos - (endchr - inpbuf); | |||||
| /* mark begining of stream as last checked */ | |||||
| lastcheck = inpbuf; | |||||
| /* and try to process another line */ | |||||
| continue; | |||||
| } else if (inpbufpos == sizeof inpbuf) { | |||||
| /* we overflowed the buffer */ | |||||
| /* XXX - best way is to throw away this line */ | |||||
| inpbufpos = 0; | |||||
| } | |||||
| } while (0); | |||||
| /* if we copied all the data */ | |||||
| if (cpylen == CDC_RX_LEN) { | |||||
| /* declare that we are ready to receive more data */ | |||||
| CDC_RX_LEN = 0; | |||||
| USBD_CDC_ReceivePacket(&hUsbDeviceFS); | |||||
| } else { | |||||
| /* if not, move the remaining to the begining and try again */ | |||||
| memmove(CDC_RX_BUFFER, &CDC_RX_BUFFER[cpylen], CDC_RX_LEN - cpylen); | |||||
| CDC_RX_LEN -= cpylen; | |||||
| } | |||||
| } | |||||
| goto loop; | goto loop; | ||||
| } | } | ||||