c1120.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /*
  2. * Project: Arrow
  3. * Author: curiousmuch
  4. */
  5. #include <stdio.h>
  6. #include <math.h>
  7. #include "freertos/FreeRTOS.h"
  8. #include "freertos/task.h"
  9. #include "driver/gpio.h"
  10. #include "sdkconfig.h"
  11. #include "driver/spi_master.h"
  12. #include "esp_err.h"
  13. #include "cc1120.h"
  14. #include "cc1120_protocol.h"
  15. #include "board.h"
  16. #include "esp_task_wdt.h"
  17. #define CC1120_WRITE_BIT 0
  18. #define CC1120_READ_BIT BIT(1)
  19. #define CC1120_BURST_BIT BIT(0)
  20. // Public Configurations for CC1120 SPI Driver
  21. spi_bus_config_t bus_config =
  22. {
  23. .miso_io_num = CC1120_MISO,
  24. .mosi_io_num = CC1120_MOSI,
  25. .sclk_io_num = CC1120_SCLK,
  26. .quadwp_io_num = -1,
  27. .quadhd_io_num = -1,
  28. .max_transfer_sz = 150,
  29. .flags = ESP_INTR_FLAG_IRAM
  30. };
  31. spi_device_interface_config_t interface_config =
  32. {
  33. .command_bits = 2,
  34. .address_bits = 6,
  35. .dummy_bits = 0,
  36. .mode = 0,
  37. .spics_io_num = CC1120_CS,
  38. .clock_speed_hz = (APB_CLK_FREQ/20),
  39. .flags = 0,
  40. .queue_size = 20
  41. };
  42. spi_device_handle_t spi;
  43. // Private CC1120 Driver Functions
  44. void cc1120_gpio_init(void)
  45. {
  46. gpio_config_t reset_pin_config =
  47. {
  48. .pin_bit_mask = (uint64_t)(BIT64(CC1120_RESET)),
  49. .mode = GPIO_MODE_OUTPUT,
  50. .pull_up_en = GPIO_PULLUP_DISABLE,
  51. .pull_down_en = GPIO_PULLDOWN_DISABLE,
  52. .intr_type = GPIO_INTR_DISABLE
  53. };
  54. gpio_config_t gpio_pin_config =
  55. {
  56. .pin_bit_mask = (uint64_t) (BIT64(CC1120_GPIO0)|BIT64(CC1120_GPIO2)|BIT64(CC1120_GPIO3)),
  57. .mode = GPIO_MODE_INPUT,
  58. .pull_up_en = GPIO_PULLUP_DISABLE,
  59. .pull_down_en = GPIO_PULLDOWN_DISABLE,
  60. .intr_type = GPIO_INTR_DISABLE
  61. };
  62. gpio_config_t debug_pin_config =
  63. {
  64. .pin_bit_mask = (uint64_t) (BIT64(DEBUG_0)|BIT64(DEBUG_1)),
  65. .mode = GPIO_MODE_OUTPUT,
  66. .pull_up_en = GPIO_PULLUP_DISABLE,
  67. .pull_down_en = GPIO_PULLDOWN_DISABLE,
  68. .intr_type = GPIO_INTR_DISABLE
  69. };
  70. gpio_config(&reset_pin_config);
  71. gpio_config(&gpio_pin_config);
  72. gpio_config(&debug_pin_config);
  73. gpio_set_level(CC1120_RESET, 1);
  74. }
  75. void cc1120_spi_init(void)
  76. {
  77. esp_err_t ret;
  78. ret = spi_bus_initialize(VSPI_HOST, &bus_config, 0); // this uses DMA channel 1
  79. ESP_ERROR_CHECK(ret);
  80. ret = spi_bus_add_device(VSPI_HOST, &interface_config, &spi);
  81. ESP_ERROR_CHECK(ret);
  82. }
  83. void IRAM_ATTR cc1120_spi_write_byte(uint16_t addr, uint8_t data)
  84. {
  85. esp_err_t ret;
  86. spi_transaction_t tx_trans =
  87. {
  88. .flags = SPI_TRANS_USE_TXDATA,
  89. .cmd = CC1120_WRITE_BIT,
  90. .addr = addr,
  91. .length = 8,
  92. .rxlength = 0,
  93. .tx_data[0] = data
  94. };
  95. if ((addr & 0xFF00) != 0) // send data with extended address in command field
  96. {
  97. tx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
  98. spi_transaction_ext_t tx_trans_ext =
  99. {
  100. .base = tx_trans,
  101. .command_bits = 2,
  102. .address_bits = 14
  103. };
  104. ret = spi_device_polling_transmit(spi, (spi_transaction_t*)&tx_trans_ext);
  105. }
  106. else
  107. {
  108. ret = spi_device_polling_transmit(spi, &tx_trans);
  109. }
  110. ESP_ERROR_CHECK(ret);
  111. }
  112. void IRAM_ATTR cc1120_spi_write_bytes(uint16_t addr, uint8_t* data, uint8_t len)
  113. {
  114. esp_err_t ret;
  115. spi_transaction_t tx_trans =
  116. {
  117. .cmd = (CC1120_WRITE_BIT | CC1120_BURST_BIT),
  118. .addr = addr,
  119. .length = 8*len,
  120. .tx_buffer = data
  121. };
  122. if ((addr & 0xFF00) != 0) // send data with extended address in command field
  123. {
  124. tx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
  125. spi_transaction_ext_t tx_trans_ext =
  126. {
  127. .base = tx_trans,
  128. .command_bits = 2,
  129. .address_bits = 14
  130. };
  131. ret = spi_device_transmit(spi, (spi_transaction_t*)&tx_trans_ext);
  132. }
  133. else
  134. {
  135. ret = spi_device_transmit(spi, &tx_trans);
  136. }
  137. ESP_ERROR_CHECK(ret);
  138. }
  139. void cc1120_spi_read_byte(uint16_t addr, uint8_t* data)
  140. {
  141. esp_err_t ret;
  142. spi_transaction_t rx_trans =
  143. {
  144. .cmd = CC1120_READ_BIT,
  145. .addr = addr,
  146. .length = 8,
  147. .rxlength = 8,
  148. .rx_buffer = data
  149. };
  150. if ((addr & 0xFF00) != 0) // read data with extended address in command field
  151. {
  152. rx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
  153. spi_transaction_ext_t rx_trans_ext =
  154. {
  155. .base = rx_trans,
  156. .command_bits = 2,
  157. .address_bits = 14
  158. };
  159. ret = spi_device_transmit(spi, (spi_transaction_t*)&rx_trans_ext);
  160. }
  161. else
  162. {
  163. ret = spi_device_transmit(spi, &rx_trans);
  164. }
  165. ESP_ERROR_CHECK(ret);
  166. }
  167. void cc1120_spi_read_bytes(uint16_t addr, uint8_t* data, uint8_t len)
  168. {
  169. esp_err_t ret;
  170. spi_transaction_t rx_trans =
  171. {
  172. .cmd = (CC1120_READ_BIT | CC1120_BURST_BIT),
  173. .addr = addr,
  174. .length = 8*len,
  175. .rxlength = 8*len,
  176. .rx_buffer = data
  177. };
  178. if ((addr & 0xFF00) != 0) // read data with extended address in command field
  179. {
  180. rx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
  181. spi_transaction_ext_t rx_trans_ext =
  182. {
  183. .base = rx_trans,
  184. .command_bits = 2,
  185. .address_bits = 14
  186. };
  187. ret = spi_device_transmit(spi, (spi_transaction_t*)&rx_trans_ext);
  188. }
  189. else
  190. {
  191. ret = spi_device_transmit(spi, &rx_trans);
  192. }
  193. ESP_ERROR_CHECK(ret);
  194. }
  195. rf_status_t IRAM_ATTR cc1120_spi_strobe(uint8_t cmd)
  196. {
  197. esp_err_t ret;
  198. uint8_t temp=0;
  199. spi_transaction_t rx_trans =
  200. {
  201. .flags = (SPI_TRANS_USE_TXDATA | SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR),
  202. .length = 8,
  203. .rxlength = 8,
  204. .rx_buffer = &temp,
  205. .tx_data[0] = cmd
  206. };
  207. spi_transaction_ext_t rx_trans_ext =
  208. {
  209. .base = rx_trans,
  210. .command_bits = 0,
  211. .address_bits = 0
  212. };
  213. ret = spi_device_transmit(spi, (spi_transaction_t*)&rx_trans_ext);
  214. ESP_ERROR_CHECK(ret);
  215. return (temp & 0xF0);
  216. }
  217. // Public CC1120 Driver Functions
  218. // These function should have there own error codes as they're dependent upon the radio and
  219. // not the ESP32 :)
  220. rf_status_t cc1120_radio_reset(void)
  221. {
  222. rf_status_t status;
  223. uint8_t retry_count = 0;
  224. cc1120_spi_strobe(CC112X_SRES);
  225. status = cc1120_spi_strobe(CC112X_SNOP);
  226. vTaskDelay(10 / portTICK_PERIOD_MS);
  227. while((CC112X_RDYn_BIT & (status & 0x80)))
  228. {
  229. vTaskDelay(10 / portTICK_PERIOD_MS);
  230. if (retry_count > 3)
  231. {
  232. // place error CC1120 timeout
  233. printf("CC1120 Reset Failure\n");
  234. break;
  235. }
  236. status = cc1120_spi_strobe(CC112X_SNOP);
  237. retry_count++;
  238. }
  239. printf("%x\n", retry_count);
  240. return status;
  241. }
  242. esp_err_t cc1120_radio_frequency(uint32_t freq)
  243. {
  244. return ESP_OK;
  245. }
  246. esp_err_t cc1120_radio_sleep(void)
  247. {
  248. return ESP_OK;
  249. }
  250. esp_err_t cc1120_radio_power(uint8_t txPower)
  251. {
  252. return ESP_OK;
  253. }
  254. #define HDLC_FLAG 0x7E
  255. #define HDLC_FLAG_LEN 10
  256. uint8_t packet_len = 0;
  257. uint8_t test_vector[] = {0x71, 0x01, 023, 0xAE, 0x75};
  258. volatile uint8_t sample_count = 0;
  259. uint8_t toggle;
  260. uint8_t toggle2;
  261. uint8_t prev_sample_count = 0;
  262. uint32_t tx_symbol = 0;
  263. uint8_t prev_tx_symbol = 0;
  264. #define SAMPLE_FREQUENCY 13200
  265. #define DAC_MAX 64
  266. #define LUT_SIZE 128
  267. DRAM_ATTR int8_t LUT[LUT_SIZE];
  268. int32_t phase_i = 0;
  269. volatile uint8_t new_sample = 0;
  270. float phase = 0.0f;
  271. float delta_phi = 0.0f;
  272. float const delta_phi_1 = (float) 1200 / SAMPLE_FREQUENCY * LUT_SIZE;
  273. float const delta_phi_2 = (float) 2200 / SAMPLE_FREQUENCY * LUT_SIZE;
  274. const uint8_t APRS_TEST_PACKET[] = {168,138,166,168, 64, 64,224,174,132,100,158,166,180,255, 3,240, 44, 84,
  275. 104,101, 32,113,117,105, 99,107, 32, 98,114,111,119,110, 32,102,111,120,
  276. 32,106,117,109,112,115, 32,111,118,101,114, 32,116,104,101, 32,108, 97,
  277. 122,121, 32,100,111,103, 33, 32, 32, 49, 32,111,102, 32, 52, 40,110};
  278. //const uint8_t APRS_TEST_PACKET[] = {0xFF, 0xFF, 0xFF};
  279. // The output needs to be continous phase.
  280. typedef struct {
  281. uint8_t one_count;
  282. uint32_t sample_count;
  283. uint32_t byte;
  284. uint32_t packet_len;
  285. uint8_t prev_bit;
  286. uint8_t cur_bit;
  287. uint8_t tone;
  288. } aprs_flags_t;
  289. aprs_flags_t DRAM_ATTR aprs_flags = {
  290. .one_count = 0,
  291. .sample_count = 0,
  292. .byte = 0,
  293. .packet_len = sizeof(APRS_TEST_PACKET)/sizeof(uint8_t),
  294. .prev_bit = 0,
  295. .cur_bit = 0,
  296. .tone = 0
  297. };
  298. static void IRAM_ATTR LUT_lookup(void)
  299. {
  300. if (aprs_flags.tone)
  301. delta_phi = delta_phi_1;
  302. else
  303. delta_phi = delta_phi_2;
  304. phase_i = (int32_t)phase; // get integer part of our phase
  305. phase += delta_phi; // increment phase
  306. if (phase >= (float)LUT_SIZE) // handle wraparound
  307. phase -= (float)LUT_SIZE;
  308. }
  309. static void IRAM_ATTR cc1120_aprs_tx_isr(void* arg)
  310. {
  311. cc1120_spi_write_byte(CC112X_CFM_TX_DATA_IN, LUT[phase_i]);
  312. sample_count++;
  313. new_sample = 1;
  314. toggle = toggle ^ 1;
  315. gpio_set_level(DEBUG_1, toggle);
  316. }
  317. void cc1120_lut_init(void)
  318. {
  319. int16_t i=0;
  320. for (i=0; i<LUT_SIZE; ++i)
  321. {
  322. LUT[i] = (int8_t)roundf(DAC_MAX * sinf(2.0f * M_PI * (float)i / LUT_SIZE));
  323. //printf("%d,\n", LUT[i]);
  324. }
  325. }
  326. #define PREAMBLE_LENGTH 20
  327. #define SUFFIX_LENGTH 1
  328. // test function to generate APRS s1 or s2
  329. void IRAM_ATTR cc1120_radio_APRSTXPacket(void)
  330. {
  331. // start CW transmission
  332. cc1120_spi_write_byte(CC112X_FIFO, 0x12);
  333. cc1120_spi_strobe(CC112X_STX);
  334. // enable interrupt pin for CC1120 for timing packets
  335. gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
  336. gpio_isr_handler_add(CC1120_GPIO3, cc1120_aprs_tx_isr, NULL);
  337. gpio_set_intr_type(CC1120_GPIO3, GPIO_INTR_POSEDGE);
  338. // acquire SPI bus for fastest possible SPI transactions
  339. spi_device_acquire_bus(spi, portMAX_DELAY);
  340. int16_t i,j;
  341. while(1)
  342. {
  343. // start CW transmission
  344. cc1120_spi_write_byte(CC112X_FIFO, 0x12);
  345. cc1120_spi_strobe(CC112X_STX);
  346. sample_count = 0;
  347. new_sample = 0;
  348. /* Send Flag */
  349. for (i = 0; i<PREAMBLE_LENGTH; i++)
  350. {
  351. aprs_flags.byte = 0x7E;
  352. for(j=0; j<8; j++)
  353. {
  354. aprs_flags.cur_bit = aprs_flags.byte & 0x01;
  355. // NRZ-I Encoding
  356. if (aprs_flags.cur_bit)
  357. {
  358. // do nothing
  359. aprs_flags.one_count++;
  360. }
  361. else
  362. {
  363. aprs_flags.tone = aprs_flags.tone ^ 1; // switch tone
  364. aprs_flags.one_count = 0;
  365. }
  366. aprs_flags.byte = (aprs_flags.byte >> 1);
  367. while(sample_count < 11) // wait for symbol to be sent
  368. {
  369. if ( new_sample )
  370. {
  371. LUT_lookup();
  372. new_sample = 0;
  373. }
  374. }
  375. sample_count = 0;
  376. //printf("Symbol: %x\n", aprs_flags.cur_bit);
  377. }
  378. }
  379. aprs_flags.one_count = 0;
  380. /* Send Packet */
  381. for (i=0;i<aprs_flags.packet_len;i++)
  382. {
  383. aprs_flags.byte = APRS_TEST_PACKET[i];
  384. for(j=0; j<8; j++)
  385. {
  386. aprs_flags.cur_bit = aprs_flags.byte & 0x01; // bool of first bit
  387. // Zero Stuffing
  388. if (aprs_flags.one_count == 5)
  389. {
  390. aprs_flags.tone = aprs_flags.tone ^ 1;
  391. aprs_flags.one_count = 0;
  392. // wait for symbol to be sent
  393. while(sample_count < 11)
  394. {
  395. if ( new_sample )
  396. {
  397. LUT_lookup();
  398. new_sample = 0;
  399. }
  400. }
  401. toggle2 = toggle2 ^ 1;
  402. gpio_set_level(DEBUG_0, toggle2);
  403. sample_count = 0;
  404. }
  405. // NRZ-I Encoding
  406. if (aprs_flags.cur_bit)
  407. {
  408. // do nothing
  409. aprs_flags.one_count++;
  410. }
  411. else
  412. {
  413. aprs_flags.tone = aprs_flags.tone ^ 1; // switch tone
  414. aprs_flags.one_count = 0;
  415. }
  416. aprs_flags.byte = (aprs_flags.byte >> 1);
  417. while(sample_count < 11) // wait for symbol to be sent
  418. {
  419. if ( new_sample )
  420. {
  421. LUT_lookup();
  422. new_sample = 0;
  423. }
  424. }
  425. toggle2 = toggle2 ^ 1;
  426. gpio_set_level(DEBUG_0, toggle2);
  427. sample_count = 0;
  428. //printf("Symbol: %x\n", aprs_flags.cur_bit);
  429. }
  430. }
  431. aprs_flags.one_count = 0;
  432. /* Send Flag */
  433. for (i = 0; i<SUFFIX_LENGTH; i++)
  434. {
  435. aprs_flags.byte = 0x7E;
  436. for(j=0; j<8;j++)
  437. {
  438. aprs_flags.cur_bit = aprs_flags.byte & 0x01;
  439. // NRZ-I Encoding
  440. if (aprs_flags.cur_bit)
  441. {
  442. // do nothing
  443. aprs_flags.one_count++;
  444. }
  445. else
  446. {
  447. aprs_flags.tone = aprs_flags.tone ^ 1; // switch tone
  448. aprs_flags.one_count = 0;
  449. }
  450. aprs_flags.byte = (aprs_flags.byte >> 1);
  451. while(sample_count < 11) // wait for symbol to be sent
  452. {
  453. if ( new_sample )
  454. {
  455. LUT_lookup();
  456. new_sample = 0;
  457. }
  458. }
  459. sample_count = 0;
  460. }
  461. }
  462. cc1120_spi_strobe(CC112X_SIDLE);
  463. vTaskDelay(10000/portTICK_PERIOD_MS);
  464. }
  465. }
  466. void cc1120_radio_init(const cc1120_reg_settings_t* rf_settings, uint8_t len)
  467. {
  468. cc1120_gpio_init();
  469. cc1120_spi_init();
  470. cc1120_lut_init();
  471. cc1120_radio_reset(); gpio_set_level(CC1120_RESET, 1);
  472. uint8_t i;
  473. for (i=0;i<len;i++)
  474. {
  475. cc1120_spi_write_byte(rf_settings[i].addr, rf_settings[i].data);
  476. }
  477. }