main.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * Project: Arrow
  3. * Author: curiousmuch
  4. * Description: This project is an APRS transceiver based on the ESP32 and CC1200.
  5. * TODO: Refactor Code to isolate into seperate components
  6. * TODO: Isolate BT_SPP.C functionality
  7. * TODO: Isolate KISS.C functionality
  8. * TODO: Remove any dependancies on Direwolf.
  9. * TODO: Transfer DSP functions to APRS folder
  10. * TODO: Abstract includes to be nicer (#include aprs.h) for example
  11. * TODO: Isolate CC1200 functions from other parts / maybe integrate most of TX scheme into task.
  12. */
  13. /* Standard Includes */
  14. #include <stdio.h>
  15. /* ESP-IDF */
  16. #include "sdkconfig.h"
  17. #include "freertos/FreeRTOS.h"
  18. #include "freertos/task.h"
  19. #include "freertos/semphr.h"
  20. #include "freertos/ringbuf.h"
  21. #include "nvs.h"
  22. #include "nvs_flash.h"
  23. #include "esp_log.h"
  24. /* Application Specific */
  25. #include "bt_spp.h"
  26. #include "board.h"
  27. #include "radio.h"
  28. #include "kiss.h"
  29. #include "fcs_calc.h"
  30. /* Data Structures */
  31. typedef struct {
  32. uint8_t tnc_number;
  33. uint8_t tx_delay;
  34. uint8_t P;
  35. uint8_t slot_time;
  36. uint8_t full_duplex;
  37. uint8_t tx_tail;
  38. } tnc_settings_t;
  39. /* Public Variables */
  40. static tnc_settings_t tnc_settings;
  41. static SemaphoreHandle_t xRadioTXSemaphore;
  42. uint8_t ax25_rx_buf[1024];
  43. RingbufHandle_t ax25_tx_buf;
  44. /* Radio Callback Functions */
  45. void radio_rx_ax25_cb(uint8_t *frame, uint32_t len)
  46. {
  47. // TODO: move kiss processing to other core
  48. kiss_transmit(KISS_DATAFRAME, frame, len);
  49. }
  50. void radio_tx_ax25_cb(void)
  51. {
  52. // unlock scheduling task to allow next packet to be sent
  53. xSemaphoreGive(xRadioTXSemaphore);
  54. }
  55. /* KISS callback Functions */
  56. void kiss_tx_cb(uint8_t *frame, uint32_t len)
  57. {
  58. // TODO: move function to other core
  59. // TODO: Add functionality which indicates if BLE connection is present or not
  60. // send data to UART via bluetooth
  61. bt_spp_tx(frame, len);
  62. ESP_LOGI("tnc", "kiss packet sent");
  63. }
  64. void kiss_rx_cb(uint8_t *frame, uint32_t len)
  65. {
  66. uint8_t data_byte;
  67. data_byte = frame[0] & 0x0F; // tnc_number information
  68. // process dataframe
  69. if (data_byte == KISS_DATAFRAME)
  70. {
  71. ESP_LOGI("tnc", "kiss packet received");
  72. // feed packet to ring buffer
  73. uint32_t fcs = fcs_calc(&frame[1], len-1);
  74. frame[len] = fcs & 0xFF;
  75. frame[len+1] = fcs>>8 & 0xFF;
  76. if (xRingbufferSend(ax25_tx_buf, &frame[1], ((len+1)*sizeof(uint8_t)),10/portTICK_PERIOD_MS) == pdFALSE)
  77. {
  78. ESP_LOGE("tnc", "packet buffer overflow");
  79. }
  80. }
  81. else // assume command
  82. {
  83. switch(data_byte)
  84. {
  85. case KISS_CMD_TXDELAY:
  86. ESP_LOGI("tnc", "updated tx delay");
  87. tnc_settings.tx_delay = frame[1];
  88. break;
  89. case KISS_CMD_P:
  90. ESP_LOGI("tnc", "updated persistance");
  91. tnc_settings.P = frame[1];
  92. break;
  93. case KISS_CMD_SLOTTIME:
  94. ESP_LOGI("tnc", "updated slot time");
  95. tnc_settings.slot_time = frame[1];
  96. break;
  97. case KISS_CMD_TXTAIL:
  98. ESP_LOGI("tnc", "updated tx tail");
  99. tnc_settings.tx_tail = frame[1];
  100. break;
  101. case KISS_CMD_FULLDUPLEX:
  102. ESP_LOGI("tnc", "updated duplex setting");
  103. tnc_settings.full_duplex = frame[1];
  104. break;
  105. case KISS_CMD_SETHARDWARE:
  106. ESP_LOGI("tnc", "updated hardware settings");
  107. break;
  108. case KISS_CMD_RETURN:
  109. ESP_LOGI("tnc", "wtf is return");
  110. break;
  111. default:
  112. ESP_LOGE("tnc", "unknown data byte for KISS protocol");
  113. }
  114. // reload for parameter changes to take effect
  115. }
  116. }
  117. /* TNC Tasks */
  118. void tnc_task(void *para)
  119. {
  120. uint8_t *packet;
  121. size_t packet_size;
  122. uint8_t P;
  123. radio_packet_rx(NULL);
  124. while(1)
  125. {
  126. // indicate RX
  127. enable_green_led();
  128. disable_red_led();
  129. // check ring buffer for packet
  130. packet = xRingbufferReceive(ax25_tx_buf, &packet_size, portMAX_DELAY);
  131. ESP_LOGI("tnc", "scheduling transmission");
  132. if (packet != NULL)
  133. {
  134. // wait based on persistance algorithm
  135. while (1)
  136. {
  137. // TODO: carrier detect is causing a crash somehow when it gets locked on
  138. // to high. I'm confused as the unit should continue to run despite this...
  139. if (radio_get_cs() == 0)
  140. {
  141. ESP_LOGV("radio", "carrier not detected");
  142. P = (uint8_t) esp_random();
  143. if (P <= tnc_settings.P)
  144. {
  145. ESP_LOGI("radio", "transmission scheduled");
  146. break;
  147. }
  148. else
  149. {
  150. ESP_LOGV("radio", "transmission postponed");
  151. vTaskDelay(tnc_settings.slot_time * 10 / portTICK_PERIOD_MS);
  152. }
  153. }
  154. else
  155. {
  156. ESP_LOGV("radio", "carrier detected");
  157. vTaskDelay(10 / portTICK_PERIOD_MS); // re-check in 10ms
  158. }
  159. }
  160. // indicate TX
  161. enable_red_led();
  162. disable_green_led();
  163. // TODO: modify code so the full TX DELAY isn't used when multiple packets are sent.
  164. // dump all the packets in the buffer
  165. while(packet != NULL)
  166. {
  167. // setup packet to be transmitted
  168. radio_packet_tx(packet, packet_size, NULL);
  169. // sleep until packet is finished being sent
  170. xSemaphoreTake(xRadioTXSemaphore, portMAX_DELAY);
  171. // remove packet from ring buffer and load next one if it exists
  172. vRingbufferReturnItem(ax25_tx_buf, (void *)packet);
  173. packet = xRingbufferReceive(ax25_tx_buf, &packet_size, 0);
  174. }
  175. }
  176. else
  177. {
  178. ESP_LOGE("tnc", "buffer error");
  179. }
  180. // setup again for reception
  181. radio_packet_rx(NULL);
  182. }
  183. }
  184. void IRAM_ATTR app_main()
  185. {
  186. // Inter-Task Communication
  187. ax25_tx_buf = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
  188. xRadioTXSemaphore = xSemaphoreCreateBinary();
  189. // Initialize Flash
  190. esp_err_t ret = nvs_flash_init();
  191. if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  192. ESP_ERROR_CHECK(nvs_flash_erase());
  193. ret = nvs_flash_init();
  194. }
  195. ESP_ERROR_CHECK( ret );
  196. // Board IO Initialize
  197. board_init();
  198. // Load Settings from Flash
  199. // Radio Initialize
  200. ax25_param_t ax25_param;
  201. ax25_param.tx_tail = 10;
  202. ax25_param.tx_delay = 100;
  203. ax25_param.sample_rate = 13200;
  204. ax25_param.symbol0_freq = 1200;
  205. ax25_param.symbol1_freq = 2200;
  206. ax25_param.rx_cb = radio_rx_ax25_cb;
  207. ax25_param.tx_cb = radio_tx_ax25_cb;
  208. ax25_param.rx_buf = ax25_rx_buf;
  209. ax25_param.rx_buf_len = sizeof(ax25_rx_buf) / sizeof(ax25_rx_buf[0]);
  210. ax25_param.cpu_core = 1;
  211. radio_init(AX25, &ax25_param);
  212. // Kiss Decoder and Encoder
  213. kiss_init(0, kiss_tx_cb, kiss_rx_cb);
  214. // BLE and SPP
  215. bt_spp_init();
  216. // TNC Settings
  217. tnc_settings.slot_time = 10;
  218. tnc_settings.P = 63;
  219. tnc_settings.tnc_number = 0;
  220. // Tasks
  221. xTaskCreatePinnedToCore(tnc_task, "tnc task", 1024*4, 0, 2, NULL, 1);
  222. }