|
- /*-
- * Copyright 2021 John-Mark Gurney.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
- #include <usb_device.h>
- #include <usbd_cdc_if.h>
-
- #include <string.h>
-
- /* LoRaMac headers */
- #include <board.h>
- #include <adc.h>
- #include <radio.h>
- #include <delay.h>
-
- /* lora-irr headers */
- #include <misc.h>
-
- #include <sysinit.h>
-
- /* Start up USB */
- SYSINIT_VF(usb_cdc, SI_SUB_USB, SI_ORDER_MIDDLE, MX_USB_DEVICE_Init);
-
- /* XXX - where's a better place? */
- extern PCD_HandleTypeDef hpcd_USB_FS;
-
- void
- USB_LP_IRQHandler(void)
- {
-
- HAL_PCD_IRQHandler(&hpcd_USB_FS);
- }
-
- char *
- findeol(char *pos, size_t len)
- {
-
- while (len) {
- if (*pos == '\r' || *pos == '\n')
- return pos;
- pos++;
- len--;
- }
-
- return NULL;
- }
-
- void
- hexdump(const uint8_t *ptr, size_t len)
- {
- int i;
-
- for (i = 0; i < len; i++)
- usb_printf("%02x", ptr[i]);
- }
-
- void
- txdone(void)
- {
-
- usb_printf("txdone\r\n");
- Radio.Rx(0);
- }
-
- void
- txtimeout(void)
- {
-
- usb_printf("txtimeout\r\n");
- }
-
- void
- rxdone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
- {
-
- usb_printf("rxdone: size: %hu, rssi: %hd, snr: %d\r\ndata: ", size, rssi, snr);
- hexdump(payload, size);
- usb_printf("\r\n");
- }
-
- void
- rxtimeout(void)
- {
-
- usb_printf("rxtimeout\r\n");
- }
-
- void
- rxerr(void)
- {
- usb_printf("rxerr\r\n");
- }
-
- RadioEvents_t revents = {
- .TxDone = txdone,
- .TxTimeout = txtimeout,
- .RxDone = rxdone,
- .RxTimeout = rxtimeout,
- .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 false;
-
- /* 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);
- fflush(vcp_usb);
- }
-
- void
- radio_init(void)
- {
-
- Radio.Init(&revents);
- }
-
- SYSINIT_VF(radio_init, SI_SUB_STANDARD, SI_ORDER_ANY, radio_init);
-
- int
- main(void)
- {
-
- debug_printf("starting...\n");
-
- /* turn on LED */
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
-
- setlinebuf(vcp_usb);
-
- #if 1
- wait_for_vcp();
-
- /*
- * This is required to use w/ FreeBSD. This is an issue w/ the
- * STM32 Core USB library:
- * https://github.com/STMicroelectronics/STM32CubeL1/issues/10
- */
- DelayMs(100);
- usb_printf("starting...\r\n");
-
- #endif
-
- uint32_t v;
-
- usb_printf("gs: %#x\r\n", Radio.GetStatus());
-
- usb_printf("set modem\r\n");
- Radio.SetModem(MODEM_LORA);
-
- usb_printf("check rffreq: %d\r\n", (int)Radio.CheckRfFrequency(914350 * 1000));
- usb_printf("set channel\r\n");
- Radio.SetChannel(914350 * 1000);
-
- v = Radio.Random();
- usb_printf("rr: %#lx\r\n", v);
-
- usb_printf("rssi: %#hx\r\n", Radio.Rssi(MODEM_LORA));
-
- /* RX/TX parameters */
- const uint8_t modem = MODEM_LORA;
- const uint8_t bandwidth = 0 /* 128 kHz */;
- const uint8_t datarate = 7 /* 128 chips */;
- const uint8_t coderate = 1 /* 4/5 */;
- const uint8_t preambleLen = 8 /* symbols */;
- const uint8_t fixLen = 0 /* variable */;
- const uint8_t crcOn = 1 /* on */;
- const uint8_t freqHopOn = 0 /* off */;
- const bool iqInverted = false /* not inverted */;
-
- Radio.SetRxConfig(modem, bandwidth, datarate, coderate, 0/*afc*/,
- preambleLen, 5/*symTimeout*/, fixLen, 0/*payloadlen*/, crcOn,
- freqHopOn, 0/*hopPeriod*/, iqInverted, true/*rxcont*/);
- Radio.SetTxConfig(modem, 11/*power*/, 0/*fdev*/, bandwidth, datarate,
- coderate, preambleLen, fixLen, crcOn, freqHopOn, 0/*hopPeriod*/,
- iqInverted, 1000/*timeout*/);
-
- uint8_t sendmsg[] = "testing lora123";
-
- usb_printf("sending...\r\n");
- Radio.Send(sendmsg, sizeof sendmsg);
- DelayMs(200);
- Radio.Send(sendmsg, sizeof sendmsg);
- DelayMs(200);
- Radio.Send(sendmsg, sizeof sendmsg);
- DelayMs(200);
-
- usb_printf("rx(0)...\r\n");
- Radio.Rx(0);
-
- char inpbuf[1024];
- char *lastcheck;
- char *endchr;
- int inpbufpos = 0;
- int cpylen;
-
- loop:
- BoardLowPowerHandler();
- if (Radio.IrqProcess != NULL)
- 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;
- }
|