Implement a secure ICS protocol targeting LoRa Node151 microcontroller for controlling irrigation.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

340 lines
7.3 KiB

  1. /*-
  2. * Copyright 2021 John-Mark Gurney.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  14. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23. * SUCH DAMAGE.
  24. *
  25. */
  26. #include <usbd_cdc_if.h>
  27. #include <strobe_rng_init.h>
  28. #include <string.h>
  29. #include <board.h>
  30. #include <misc.h>
  31. #include <radio.h>
  32. #include <delay.h>
  33. char *
  34. findeol(char *pos, size_t len)
  35. {
  36. while (len) {
  37. if (*pos == '\r' || *pos == '\n')
  38. return pos;
  39. pos++;
  40. len--;
  41. }
  42. return NULL;
  43. }
  44. void
  45. hexdump(uint8_t *ptr, size_t len)
  46. {
  47. int i;
  48. for (i = 0; i < len; i++)
  49. usb_printf("%02x", ptr[i]);
  50. }
  51. void
  52. txdone(void)
  53. {
  54. usb_printf("txdone\r\n");
  55. }
  56. void
  57. txtimeout(void)
  58. {
  59. usb_printf("txtimeout\r\n");
  60. }
  61. void
  62. rxdone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
  63. {
  64. usb_printf("rxdone: size: %hu, rssi: %hd, snr: %d\r\ndata: ", size, rssi, snr);
  65. hexdump(payload, size);
  66. usb_printf("\r\n");
  67. }
  68. void
  69. rxtimeout(void)
  70. {
  71. usb_printf("rxtimeout\r\n");
  72. }
  73. void
  74. rxerr(void)
  75. {
  76. usb_printf("rxerr\r\n");
  77. }
  78. RadioEvents_t revents = {
  79. .TxDone = txdone,
  80. .TxTimeout = txtimeout,
  81. .RxDone = rxdone,
  82. .RxTimeout = rxtimeout,
  83. .RxError = rxerr,
  84. };
  85. static uint8_t
  86. hexchartonib(char s)
  87. {
  88. switch (s) {
  89. case '0'...'9':
  90. return s - '0';
  91. case 'a'...'f':
  92. return s - 'a' + 10;
  93. case 'A'...'F':
  94. return s - 'A' + 10;
  95. default:
  96. return -1;
  97. }
  98. }
  99. static bool
  100. hexdecode(char *buf, size_t len, uint8_t *out)
  101. {
  102. uint8_t topchr, botchr;
  103. if (len % 2)
  104. return false;
  105. /* NB: only needed to silence a bad gcc warning */
  106. topchr = -1;
  107. while (len) {
  108. if (len % 2) {
  109. /* bottom nibble */
  110. botchr = hexchartonib(*buf);
  111. if (topchr == -1 || botchr == -1)
  112. return false;
  113. *out = topchr << 4 | botchr;
  114. out++;
  115. } else {
  116. /* top nibble */
  117. topchr = hexchartonib(*buf);
  118. }
  119. len--;
  120. buf++;
  121. }
  122. return true;
  123. }
  124. static const char pktstart[] = "pkt:";
  125. static const size_t pktstartlen = sizeof pktstart - 1;
  126. static uint8_t pktbuf[128];
  127. static void
  128. process_line(char *start, char *end)
  129. {
  130. size_t len;
  131. /* trim off leading CR/NL */
  132. while (start < end && (*start == '\r' || *start == '\n'))
  133. start++;
  134. len = end - start;
  135. if (len >= pktstartlen && memcmp(start, pktstart, sizeof pktstart - 1) == 0) {
  136. start += pktstartlen;
  137. len -= pktstartlen;
  138. if (len % 2) {
  139. usb_printf("invalid pkt len\r\n");
  140. return;
  141. }
  142. if (!hexdecode(start, len, pktbuf)) {
  143. usb_printf("invalid pkt\r\n");
  144. return;
  145. }
  146. Radio.Send(pktbuf, len / 2);
  147. return;
  148. }
  149. usb_printf("line: %.*s", end - start, start);
  150. }
  151. int
  152. main(void)
  153. {
  154. uint8_t bytes[8];
  155. strobe_rng_init();
  156. BoardInitMcu();
  157. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
  158. #if 1
  159. wait_for_vcp();
  160. usb_printf("starting...\r\n");
  161. bare_strobe_randomize(bytes, sizeof bytes);
  162. hexdump(bytes, sizeof bytes);
  163. usb_printf("\r\n");
  164. #endif
  165. Radio.Init(&revents);
  166. usb_printf("foo\r\n");
  167. Radio.ReadBuffer(0x00, bytes, sizeof bytes);
  168. usb_printf("regs 0x00: ");
  169. hexdump(bytes, sizeof bytes);
  170. usb_printf("\r\n");
  171. Radio.ReadBuffer(0x40, bytes, sizeof bytes);
  172. usb_printf("regs 0x40: ");
  173. hexdump(bytes, sizeof bytes);
  174. usb_printf("\r\n");
  175. uint32_t v;
  176. v = Radio.Random();
  177. usb_printf("rr: %#x\r\n", v);
  178. v = Radio.Random();
  179. usb_printf("rr: %#x\r\n", v);
  180. v = Radio.Random();
  181. usb_printf("rr: %#x\r\n", v);
  182. usb_printf("gs: %#x\r\n", Radio.GetStatus());
  183. usb_printf("set modem\r\n", v);
  184. Radio.SetModem(MODEM_LORA);
  185. usb_printf("check rffreq: %d\r\n", (int)Radio.CheckRfFrequency(914350 * 1000));
  186. usb_printf("set channel\r\n", v);
  187. Radio.SetChannel(914350 * 1000);
  188. v = Radio.Random();
  189. usb_printf("rr: %#x\r\n", v);
  190. usb_printf("rssi: %#hx\r\n", Radio.Rssi(MODEM_LORA));
  191. /* RX/TX parameters */
  192. const uint8_t modem = MODEM_LORA;
  193. const uint8_t bandwidth = 0 /* 128 kHz */;
  194. const uint8_t datarate = 7 /* 128 chips */;
  195. const uint8_t coderate = 1 /* 4/5 */;
  196. const uint8_t preambleLen = 4 /* symbols */;
  197. const uint8_t fixLen = 0 /* variable */;
  198. const uint8_t crcOn = 1 /* on */;
  199. const uint8_t freqHopOn = 0 /* off */;
  200. const bool iqInverted = false /* not inverted */;
  201. Radio.SetRxConfig(modem, bandwidth, datarate, coderate, 0/*afc*/,
  202. preambleLen, 5/*symTimeout*/, fixLen, 0/*payloadlen*/, crcOn,
  203. freqHopOn, 0/*hopPeriod*/, iqInverted, true/*rxcont*/);
  204. Radio.SetTxConfig(modem, 11/*power*/, 0/*fdev*/, bandwidth, datarate,
  205. coderate, preambleLen, fixLen, crcOn, freqHopOn, 0/*hopPeriod*/,
  206. iqInverted, 1000/*timeout*/);
  207. uint8_t sendmsg[] = "testing lora123";
  208. usb_printf("sending...\r\n");
  209. Radio.Send(sendmsg, sizeof sendmsg);
  210. DelayMs(200);
  211. Radio.Send(sendmsg, sizeof sendmsg);
  212. DelayMs(200);
  213. Radio.Send(sendmsg, sizeof sendmsg);
  214. DelayMs(200);
  215. usb_printf("rx(0)...\r\n");
  216. Radio.Rx(0);
  217. char inpbuf[1024];
  218. char *lastcheck;
  219. char *endchr;
  220. int inpbufpos = 0;
  221. int cpylen;
  222. loop:
  223. BoardLowPowerHandler();
  224. if (Radio.IrqProcess != NULL)
  225. Radio.IrqProcess();
  226. /* while we have data */
  227. while (CDC_RX_LEN) {
  228. /* store last position */
  229. lastcheck = &inpbuf[inpbufpos];
  230. /* calculate how much space left */
  231. cpylen = MIN(sizeof inpbuf - inpbufpos, CDC_RX_LEN);
  232. /* copy into buffer */
  233. memcpy(&inpbuf[inpbufpos], CDC_RX_BUFFER, cpylen);
  234. /* and point to end of buffer */
  235. inpbufpos += cpylen;
  236. do {
  237. /* find first end of line characters */
  238. endchr = findeol(lastcheck, cpylen);
  239. if (endchr != NULL) {
  240. /* if so, process it */
  241. process_line(inpbuf, endchr);
  242. /* skip end of line char */
  243. endchr++;
  244. /* move remaining buffer to the beginning */
  245. memmove(inpbuf, endchr, inpbufpos - (endchr - inpbuf));
  246. /* and store new length */
  247. inpbufpos = inpbufpos - (endchr - inpbuf);
  248. /* mark begining of stream as last checked */
  249. lastcheck = inpbuf;
  250. /* and try to process another line */
  251. continue;
  252. } else if (inpbufpos == sizeof inpbuf) {
  253. /* we overflowed the buffer */
  254. /* XXX - best way is to throw away this line */
  255. inpbufpos = 0;
  256. }
  257. } while (0);
  258. /* if we copied all the data */
  259. if (cpylen == CDC_RX_LEN) {
  260. /* declare that we are ready to receive more data */
  261. CDC_RX_LEN = 0;
  262. USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  263. } else {
  264. /* if not, move the remaining to the begining and try again */
  265. memmove(CDC_RX_BUFFER, &CDC_RX_BUFFER[cpylen], CDC_RX_LEN - cpylen);
  266. CDC_RX_LEN -= cpylen;
  267. }
  268. }
  269. goto loop;
  270. }