radio.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * radio.c
  3. *
  4. * Created on: Oct 11, 2019
  5. * Author: curiousmuch
  6. */
  7. #include <stdio.h>
  8. #include <stdint.h>
  9. #include <math.h>
  10. #include "freertos/FreeRTOS.h"
  11. #include "freertos/semphr.h"
  12. #include "freertos/task.h"
  13. #include "sdkconfig.h"
  14. #include "esp_log.h"
  15. #include "radio.h"
  16. #include "cc1200.h"
  17. #include "afsk_modulator.h"
  18. #include "afsk_demodulator.h"
  19. #include "aprs_decoder.h"
  20. #include "aprs_encoder.h"
  21. /* Debugging Tag */
  22. #define RADIO_TAG "Radio"
  23. /* Public Variables */
  24. radio_param_t radio_param; // radio configuraiton
  25. SemaphoreHandle_t xRadioSemaphore; // semphore for sample timing
  26. /* Private Functions */
  27. void IRAM_ATTR radio_timer_isr(void *param)
  28. {
  29. //GPIO.out_w1ts = (1 << DEBUG_0);
  30. int timer_idx = (int) param; // cast to int for timer index
  31. TIMERG0.int_clr_timers.t0 = 1; // clear interrupt
  32. TIMERG0.hw_timer[0].config.alarm_en = TIMER_ALARM_EN; // re-enable timer alarm
  33. // provide unblocking semaphore
  34. static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  35. xSemaphoreGiveFromISR(xRadioSemaphore, &xHigherPriorityTaskWoken);
  36. if (xHigherPriorityTaskWoken == pdTRUE)
  37. {
  38. portYIELD_FROM_ISR();
  39. }
  40. //GPIO.out_w1tc = (1 << DEBUG_0);
  41. }
  42. #define RADIO_TIMER_GROUP TIMER_GROUP_0
  43. #define RADIO_TIMER TIMER_0
  44. void timer_radio_init(uint32_t sample_rate, void *timer_isr)
  45. {
  46. timer_config_t timer_config;
  47. timer_config.divider = 2;
  48. timer_config.counter_dir = TIMER_COUNT_UP;
  49. timer_config.counter_en = TIMER_PAUSE;
  50. timer_config.alarm_en = TIMER_ALARM_EN;
  51. timer_config.intr_type = TIMER_INTR_LEVEL;
  52. timer_config.auto_reload = TIMER_AUTORELOAD_EN;
  53. uint32_t timer_alarm;
  54. timer_alarm = (uint32_t)(40000000 / sample_rate);
  55. // TODO: confirm timer_alarm calculation
  56. timer_init(RADIO_TIMER_GROUP, RADIO_TIMER, &timer_config);
  57. timer_set_counter_value(RADIO_TIMER_GROUP, RADIO_TIMER, 0x00000000ULL);
  58. timer_set_alarm_value(RADIO_TIMER_GROUP, RADIO_TIMER, 3030);
  59. timer_isr_register(RADIO_TIMER_GROUP, RADIO_TIMER, timer_isr,
  60. (void *) RADIO_TIMER, ESP_INTR_FLAG_IRAM, NULL);
  61. }
  62. void timer_radio_start(void)
  63. {
  64. timer_enable_intr(RADIO_TIMER_GROUP, RADIO_TIMER);
  65. timer_set_counter_value(RADIO_TIMER_GROUP, RADIO_TIMER, 0x00000000ULL);
  66. timer_start(RADIO_TIMER_GROUP, RADIO_TIMER);
  67. }
  68. void timer_radio_stop(void)
  69. {
  70. timer_disable_intr(RADIO_TIMER_GROUP, RADIO_TIMER);
  71. timer_pause(RADIO_TIMER_GROUP, RADIO_TIMER);
  72. }
  73. /* HAL Layer */
  74. void radio_tx(void)
  75. {
  76. cc1200_radio_tx();
  77. radio_param.status = RADIO_TX;
  78. }
  79. void radio_rx(void)
  80. {
  81. cc1200_radio_rx();
  82. radio_param.status = RADIO_RX;
  83. }
  84. void radio_idle(void)
  85. {
  86. cc1200_radio_idle();
  87. radio_param.status = RADIO_IDLE;
  88. }
  89. void radio_init(radio_config_t type, void *settings)
  90. {
  91. switch(type)
  92. {
  93. case AX25: {
  94. ESP_LOGI("Radio", "APRS Mode");
  95. radio_param.type = AX25;
  96. // cast setting struct
  97. ax25_param_t p = (ax25_param_t)settings;
  98. // setup LUT for AFSK demodulator
  99. afsk_mod_init(p->sample_rate, p->symbol0_freq, p->symbol1_freq);
  100. // setup frequency detectors for AFSK demodulator
  101. afsk_demod_init(p->sample_rate, p->symbol0_freq, p->symbol1_freq);
  102. // setup encoder for ax25
  103. ax25_encoder_init(p->tx_delay, p->tx_tail);
  104. // setup timer for TX / RX
  105. timer_radio_init(p->sample_rate, radio_timer_isr);
  106. // create task for sampling
  107. // TODO: Reduce stack requirements?
  108. // TODO: Should there be an option on which core the driver pins the task too>
  109. xTaskCreatePinnedToCore(radio_rx_task, "AFSK Sample Task", 1024*4, 0, 1, NULL, 1);
  110. // xTaskCreatePinnedToCore()
  111. vTaskSuspend(radio_rx_task);
  112. // configure CC1200
  113. cc1200_radio_init(AX25_SETTINGS, sizeof(AX25_SETTINGS)/sizeof(cc1200_reg_settings_t));
  114. // put chip to idle
  115. radio_idle();
  116. break;
  117. }
  118. default: {
  119. ESP_LOGE(RADIO_TAG, "invalid configuration");
  120. radio_param.type = NOT_CONFIGURED;
  121. //TODO: Add assert to stop functionality
  122. break;
  123. }
  124. }
  125. }
  126. // this function will block and configure
  127. // the cc1200 for tx using the protocol setup by "radio_init"
  128. // the buffer holding the packet isn't copied and therefore must be held until
  129. // the function returns
  130. // TODO: Should this be non-blocking and start up a task / wait for an interrupt
  131. // then fire a callback function?
  132. void radio_packet_tx(uint8_t *data, int32_t len, void *settings)
  133. {
  134. switch(radio_param.type)
  135. {
  136. case AX25: {
  137. ESP_LOGV(RADIO_TAG, "transmitting AX25 packet");
  138. // load ax25 encoder state machine
  139. ax25_encoder_encode(data, len);
  140. // variables for symbol timing (11 samples per symbol)
  141. uint32_t sample_count = 0; int8_t tone;
  142. uint8_t bit = ax25_encoder_get_bit();
  143. // configure radio to send CW
  144. radio_tx();
  145. // start sampling timer
  146. timer_radio_start();
  147. while(ax25_encoder_get_status == READY)
  148. {
  149. // TODO: Do we need to feed the WDT here?
  150. // get amplitude for AFSK
  151. tone = afsk_get_amplitude(bit);
  152. // pause for semphore
  153. if (xSemaphoreTake(xRadioSemaphore, portMAX_DELAY) == pdTRUE)
  154. {
  155. // update carrier for AFSK
  156. cc1200_radio_write_CFM(tone);
  157. // inc symbol count
  158. sample_count++;
  159. if (sample_count > 11)
  160. {
  161. bit = ax25_encoder_get_bit();
  162. sample_count = 0;
  163. }
  164. }
  165. else
  166. {
  167. ESP_LOGE(RADIO_TAG, "sample timeout error");
  168. break;
  169. }
  170. }
  171. radio_idle();
  172. ESP_LOGV(RADIO_TAG, "transmit complete");
  173. break;
  174. }
  175. default: {
  176. ESP_LOGE(RADIO_TAG, "invalid configuration");
  177. break;
  178. }
  179. }
  180. }
  181. void radio_rx_task(void *para)
  182. {
  183. // setup
  184. // task
  185. while(1)
  186. {
  187. }
  188. }
  189. // Functionality will depend on protocol
  190. // AX.25 - Non-Block and will activate callback function
  191. void radio_packet_rx(void *settings)
  192. {
  193. switch(radio_param.type)
  194. {
  195. case AX25: {
  196. // setup sampling timer
  197. // un-suspend sampling task
  198. break;
  199. }
  200. default: {
  201. ESP_LOGE(RADIO_TAG, "invalid configuration");
  202. break;
  203. }
  204. }
  205. cc1200_radio_rx();
  206. }