cc1200.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  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 "freertos/semphr.h"
  10. #include "freertos/portmacro.h"
  11. #include "driver/gpio.h"
  12. #include "sdkconfig.h"
  13. #include "driver/spi_master.h"
  14. #include "esp_err.h"
  15. #include "cc1200.h"
  16. #include "cc1200_protocol.h"
  17. #include "board.h"
  18. #include "esp_task_wdt.h"
  19. #include "freertos/ringbuf.h"
  20. #include "esp_log.h"
  21. #include "driver/timer.h"
  22. #define CC_TAG "CC1200_Driver"
  23. #define CC1200_WRITE_BIT 0
  24. #define CC1200_READ_BIT BIT(1)
  25. #define CC1200_BURST_BIT BIT(0)
  26. // Public Configurations for CC1120 SPI Driver
  27. spi_bus_config_t bus_config =
  28. {
  29. .miso_io_num = CC1120_MISO,
  30. .mosi_io_num = CC1120_MOSI,
  31. .sclk_io_num = CC1120_SCLK,
  32. .quadwp_io_num = -1,
  33. .quadhd_io_num = -1,
  34. .max_transfer_sz = 150,
  35. .flags = SPICOMMON_BUSFLAG_MASTER,
  36. .intr_flags = ESP_INTR_FLAG_IRAM
  37. };
  38. spi_device_interface_config_t interface_config =
  39. {
  40. .command_bits = 2,
  41. .address_bits = 6,
  42. .dummy_bits = 0,
  43. .mode = 0,
  44. .spics_io_num = CC1120_CS,
  45. .clock_speed_hz = (APB_CLK_FREQ/16),
  46. .flags = 0,
  47. .queue_size = 20
  48. };
  49. spi_device_handle_t spi;
  50. // Private CC1120 Driver Functions
  51. void cc1200_gpio_init(void)
  52. {
  53. gpio_config_t reset_pin_config =
  54. {
  55. .pin_bit_mask = (uint64_t)(BIT64(CC1120_RESET)),
  56. .mode = GPIO_MODE_OUTPUT,
  57. .pull_up_en = GPIO_PULLUP_DISABLE,
  58. .pull_down_en = GPIO_PULLDOWN_DISABLE,
  59. .intr_type = GPIO_INTR_DISABLE
  60. };
  61. gpio_config_t gpio_pin_config =
  62. {
  63. .pin_bit_mask = (uint64_t) (BIT64(CC1120_GPIO0)|BIT64(CC1120_GPIO2)|BIT64(CC1120_GPIO3)),
  64. .mode = GPIO_MODE_INPUT,
  65. .pull_up_en = GPIO_PULLUP_DISABLE,
  66. .pull_down_en = GPIO_PULLDOWN_DISABLE,
  67. .intr_type = GPIO_INTR_DISABLE
  68. };
  69. gpio_config(&reset_pin_config);
  70. gpio_config(&gpio_pin_config);
  71. gpio_set_level(CC1120_RESET, 1);
  72. }
  73. void cc1200_spi_init(void)
  74. {
  75. esp_err_t ret;
  76. ret = spi_bus_initialize(VSPI_HOST, &bus_config, 0); // this uses DMA channel 1
  77. ESP_ERROR_CHECK(ret);
  78. ret = spi_bus_add_device(VSPI_HOST, &interface_config, &spi);
  79. ESP_ERROR_CHECK(ret);
  80. }
  81. void IRAM_ATTR cc1200_spi_write_byte(uint16_t addr, uint8_t data)
  82. {
  83. esp_err_t ret;
  84. spi_transaction_t tx_trans =
  85. {
  86. .flags = SPI_TRANS_USE_TXDATA,
  87. .cmd = CC1200_WRITE_BIT,
  88. .addr = addr,
  89. .length = 8,
  90. .rxlength = 0,
  91. .tx_data[0] = data
  92. };
  93. if ((addr & 0xFF00) != 0) // send data with extended address in command field
  94. {
  95. tx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
  96. spi_transaction_ext_t tx_trans_ext =
  97. {
  98. .base = tx_trans,
  99. .command_bits = 2,
  100. .address_bits = 14
  101. };
  102. ret = spi_device_polling_transmit(spi, (spi_transaction_t*)&tx_trans_ext);
  103. }
  104. else
  105. {
  106. ret = spi_device_polling_transmit(spi, &tx_trans);
  107. }
  108. ESP_ERROR_CHECK(ret);
  109. }
  110. void IRAM_ATTR cc1200_spi_write_bytes(uint16_t addr, uint8_t* data, uint8_t len)
  111. {
  112. esp_err_t ret;
  113. spi_transaction_t tx_trans =
  114. {
  115. .cmd = (CC1200_WRITE_BIT | CC1200_BURST_BIT),
  116. .addr = addr,
  117. .length = 8*len,
  118. .tx_buffer = data
  119. };
  120. if ((addr & 0xFF00) != 0) // send data with extended address in command field
  121. {
  122. tx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
  123. spi_transaction_ext_t tx_trans_ext =
  124. {
  125. .base = tx_trans,
  126. .command_bits = 2,
  127. .address_bits = 14
  128. };
  129. ret = spi_device_polling_transmit(spi, (spi_transaction_t*)&tx_trans_ext);
  130. }
  131. else
  132. {
  133. ret = spi_device_polling_transmit(spi, &tx_trans);
  134. }
  135. ESP_ERROR_CHECK(ret);
  136. }
  137. void IRAM_ATTR cc1200_spi_read_byte(uint16_t addr, uint8_t* data)
  138. {
  139. esp_err_t ret;
  140. spi_transaction_t rx_trans =
  141. {
  142. .cmd = CC1200_READ_BIT,
  143. .addr = addr,
  144. .length = 8,
  145. .rxlength = 8,
  146. .rx_buffer = data
  147. };
  148. if ((addr & 0xFF00) != 0) // read data with extended address in command field
  149. {
  150. rx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
  151. spi_transaction_ext_t rx_trans_ext =
  152. {
  153. .base = rx_trans,
  154. .command_bits = 2,
  155. .address_bits = 14
  156. };
  157. ret = spi_device_polling_transmit(spi, (spi_transaction_t*)&rx_trans_ext);
  158. }
  159. else
  160. {
  161. ret = spi_device_polling_transmit(spi, &rx_trans);
  162. }
  163. ESP_ERROR_CHECK(ret);
  164. }
  165. uint8_t IRAM_ATTR cc1200_radio_read_RSSI(void)
  166. {
  167. uint8_t data = 0;
  168. cc1200_spi_read_byte(CC120X_RSSI1, &data);
  169. return data;
  170. }
  171. uint8_t IRAM_ATTR cc1200_radio_read_CFM(void)
  172. {
  173. uint8_t data = 0;
  174. cc1200_spi_read_byte(CC120X_CFM_RX_DATA_OUT, &data);
  175. return data;
  176. }
  177. void cc1200_spi_read_bytes(uint16_t addr, uint8_t* data, uint8_t len)
  178. {
  179. esp_err_t ret;
  180. spi_transaction_t rx_trans =
  181. {
  182. .cmd = (CC1200_READ_BIT | CC1200_BURST_BIT),
  183. .addr = addr,
  184. .length = 8*len,
  185. .rxlength = 8*len,
  186. .rx_buffer = data
  187. };
  188. if ((addr & 0xFF00) != 0) // read data with extended address in command field
  189. {
  190. rx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
  191. spi_transaction_ext_t rx_trans_ext =
  192. {
  193. .base = rx_trans,
  194. .command_bits = 2,
  195. .address_bits = 14
  196. };
  197. ret = spi_device_polling_transmit(spi, (spi_transaction_t*)&rx_trans_ext);
  198. }
  199. else
  200. {
  201. ret = spi_device_polling_transmit(spi, &rx_trans);
  202. }
  203. ESP_ERROR_CHECK(ret);
  204. }
  205. rf_status_t IRAM_ATTR cc1200_spi_strobe(uint8_t cmd)
  206. {
  207. esp_err_t ret;
  208. uint8_t temp=0;
  209. spi_transaction_t rx_trans =
  210. {
  211. .flags = (SPI_TRANS_USE_TXDATA | SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR),
  212. .length = 8,
  213. .rxlength = 8,
  214. .rx_buffer = &temp,
  215. .tx_data[0] = cmd
  216. };
  217. spi_transaction_ext_t rx_trans_ext =
  218. {
  219. .base = rx_trans,
  220. .command_bits = 0,
  221. .address_bits = 0
  222. };
  223. ret = spi_device_polling_transmit(spi, (spi_transaction_t*)&rx_trans_ext); // switched to spi poll as test
  224. ESP_ERROR_CHECK(ret);
  225. return (temp & 0xF0);
  226. }
  227. // Public CC1120 Driver Functions
  228. // These function should have there own error codes as they're dependent upon the radio and
  229. // not the ESP32 :)
  230. rf_status_t cc1200_radio_reset(void)
  231. {
  232. rf_status_t status;
  233. uint8_t retry_count = 0;
  234. cc1200_spi_strobe(CC120X_SRES);
  235. status = cc1200_spi_strobe(CC120X_SNOP);
  236. vTaskDelay(10 / portTICK_PERIOD_MS);
  237. while((CC120X_RDYn_BIT & (status & 0x80)))
  238. {
  239. vTaskDelay(10 / portTICK_PERIOD_MS);
  240. if (retry_count > 3)
  241. {
  242. // place error CC1120 timeout
  243. printf("CC1120 Reset Failure\n");
  244. break;
  245. }
  246. status = cc1200_spi_strobe(CC120X_SNOP);
  247. retry_count++;
  248. }
  249. printf("%x\n", retry_count);
  250. return status;
  251. }
  252. // f_RF = f_VCO / LO Divider
  253. #define CC1200_LO_DIVIDER 24 // 136.7 - 160 MHz Band
  254. #define CC1200_XOSC 40000000 // 40MHz
  255. // f_VCO = FREQ / 2^16 * f_XOSX + FREQOFF / 2^18 * F_XOSC
  256. esp_err_t cc1200_radio_frequency(uint32_t freq)
  257. {
  258. // calculate FREQ0, FREQ, FREQ2 registers
  259. volatile double temp_freq;
  260. temp_freq = ((double) freq * 65536 * CC1200_LO_DIVIDER) / CC1200_XOSC;
  261. freq = (uint32_t)temp_freq;
  262. cc1200_spi_write_byte(CC120X_FREQ0, ((uint8_t *)&freq)[0]);
  263. cc1200_spi_write_byte(CC120X_FREQ1, ((uint8_t *)&freq)[1]);
  264. cc1200_spi_write_byte(CC120X_FREQ2, ((uint8_t *)&freq)[2]);
  265. return ESP_OK;
  266. }
  267. esp_err_t cc1200_radio_sleep(void)
  268. {
  269. return ESP_OK;
  270. }
  271. esp_err_t cc1200_radio_power(uint8_t txPower)
  272. {
  273. return ESP_OK;
  274. }
  275. void cc1200_radio_write(const cc1200_reg_settings_t* rf_settings, uint8_t len)
  276. {
  277. uint8_t i;
  278. for (i=0;i<len;i++)
  279. {
  280. cc1200_spi_write_byte(rf_settings[i].addr, rf_settings[i].data);
  281. }
  282. }
  283. #define HDLC_FLAG 0x7E
  284. #define HDLC_FLAG_LEN 10
  285. uint8_t packet_len = 0;
  286. uint8_t test_vector[] = {0x71, 0x01, 023, 0xAE, 0x75};
  287. volatile uint8_t sample_count = 0;
  288. uint8_t toggle;
  289. uint8_t toggle2;
  290. uint8_t prev_sample_count = 0;
  291. uint32_t tx_symbol = 0;
  292. uint8_t prev_tx_symbol = 0;
  293. #define SAMPLE_FREQUENCY 13200
  294. #define DAC_MAX 64
  295. #define LUT_SIZE 128
  296. DRAM_ATTR int8_t LUT[LUT_SIZE];
  297. int32_t phase_i = 0;
  298. volatile uint8_t new_sample = 0;
  299. float phase = 0.0f;
  300. float delta_phi = 0.0f;
  301. float const delta_phi_1 = (float) 1200 / SAMPLE_FREQUENCY * LUT_SIZE;
  302. float const delta_phi_2 = (float) 2200 / SAMPLE_FREQUENCY * LUT_SIZE;
  303. uint8_t data;
  304. // The output needs to be continous phase.
  305. typedef struct {
  306. uint8_t one_count;
  307. uint32_t sample_count;
  308. uint32_t byte;
  309. uint32_t packet_len;
  310. uint8_t prev_bit;
  311. uint8_t cur_bit;
  312. uint8_t tone;
  313. } aprs_flags_t;
  314. aprs_flags_t DRAM_ATTR aprs_flags = {
  315. .one_count = 0,
  316. .sample_count = 0,
  317. .byte = 0,
  318. // .packet_len = sizeof(APRS_TEST_PACKET)/sizeof(uint8_t),
  319. .prev_bit = 0,
  320. .cur_bit = 0,
  321. .tone = 0
  322. };
  323. static void IRAM_ATTR LUT_lookup(void)
  324. {
  325. if (aprs_flags.tone)
  326. delta_phi = delta_phi_1;
  327. else
  328. delta_phi = delta_phi_2;
  329. phase_i = (int32_t)phase; // get integer part of our phase
  330. phase += delta_phi; // increment phase
  331. if (phase >= (float)LUT_SIZE) // handle wraparound
  332. phase -= (float)LUT_SIZE;
  333. }
  334. static void IRAM_ATTR cc1200_aprs_tx_isr(void* arg)
  335. {
  336. cc1200_spi_write_byte(CC120X_CFM_TX_DATA_IN, LUT[phase_i]);
  337. sample_count++;
  338. new_sample = 1;
  339. toggle = toggle ^ 1;
  340. gpio_set_level(DEBUG_1, toggle);
  341. }
  342. void cc1200_lut_init(void)
  343. {
  344. int16_t i=0;
  345. for (i=0; i<LUT_SIZE; ++i)
  346. {
  347. LUT[i] = (int8_t)roundf(DAC_MAX * sinf(2.0f * M_PI * (float)i / LUT_SIZE));
  348. //printf("%d,\n", LUT[i]);
  349. }
  350. }
  351. #define PREAMBLE_LENGTH 20
  352. #define SUFFIX_LENGTH 1
  353. void IRAM_ATTR cc1200_radio_APRSTXPacket(uint8_t *f, uint16_t f_len, uint8_t tx_delay, uint8_t tx_tail)
  354. {
  355. // acquire SPI bus for fastest possible SPI transactions
  356. spi_device_acquire_bus(spi, portMAX_DELAY);
  357. vTaskSuspendAll();
  358. // setup data rate for CFM TX
  359. cc1200_radio_write(APRS_TX_SETTINGS, sizeof(APRS_TX_SETTINGS)/sizeof(cc1200_reg_settings_t));
  360. cc1200_radio_frequency(144390000-6000);
  361. // start CW transmission
  362. cc1200_spi_write_byte(CC120X_FIFO, 0x12);
  363. while(cc1200_spi_strobe(CC120X_STX) != CC120X_STATE_TX);
  364. // enable interrupt pin for CC1120 for timing packets
  365. gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
  366. gpio_isr_handler_add(CC1120_GPIO3, cc1200_aprs_tx_isr, NULL);
  367. gpio_set_intr_type(CC1120_GPIO3, GPIO_INTR_POSEDGE);
  368. gpio_intr_enable(CC1120_GPIO3);
  369. int16_t i,j;
  370. uint16_t p_len = tx_delay * 12;
  371. uint16_t t_len = tx_tail * 12 + 1;
  372. // Start CW transmission
  373. cc1200_spi_write_byte(CC120X_FIFO, 0x12);
  374. cc1200_spi_strobe(CC120X_STX);
  375. sample_count = 0;
  376. new_sample = 0;
  377. // Send HDLC Flag for TX Delay Time
  378. for (i = 0; i<p_len; i++)
  379. {
  380. esp_task_wdt_reset();
  381. aprs_flags.byte = 0x7E;
  382. for(j=0; j<8; j++)
  383. {
  384. aprs_flags.cur_bit = aprs_flags.byte & 0x01;
  385. // NRZ-I Encoding
  386. if (aprs_flags.cur_bit)
  387. {
  388. // do nothing
  389. aprs_flags.one_count++;
  390. }
  391. else
  392. {
  393. aprs_flags.tone = aprs_flags.tone ^ 1; // switch tone
  394. aprs_flags.one_count = 0;
  395. }
  396. aprs_flags.byte = (aprs_flags.byte >> 1);
  397. while(sample_count < 11) // wait for symbol to be sent
  398. {
  399. if ( new_sample )
  400. {
  401. LUT_lookup();
  402. new_sample = 0;
  403. }
  404. }
  405. sample_count = 0;
  406. //printf("Symbol: %x\n", aprs_flags.cur_bit);
  407. }
  408. }
  409. aprs_flags.one_count = 0;
  410. // Send Packet / Frame
  411. //for (i=0;i<aprs_flags.packet_len;i++)
  412. for (i=0;i<f_len;i++)
  413. {
  414. esp_task_wdt_reset();
  415. aprs_flags.byte = f[i];
  416. for(j=0; j<8; j++)
  417. {
  418. aprs_flags.cur_bit = aprs_flags.byte & 0x01; // bool of first bit
  419. // Zero Stuffing
  420. if (aprs_flags.one_count == 5)
  421. {
  422. aprs_flags.tone = aprs_flags.tone ^ 1;
  423. aprs_flags.one_count = 0;
  424. // wait for symbol to be sent
  425. while(sample_count < 11)
  426. {
  427. if ( new_sample )
  428. {
  429. LUT_lookup();
  430. new_sample = 0;
  431. }
  432. }
  433. toggle2 = toggle2 ^ 1;
  434. //gpio_set_level(DEBUG_0, toggle2);
  435. sample_count = 0;
  436. }
  437. // NRZ-I Encoding
  438. if (aprs_flags.cur_bit)
  439. {
  440. // do nothing
  441. aprs_flags.one_count++;
  442. }
  443. else
  444. {
  445. aprs_flags.tone = aprs_flags.tone ^ 1; // switch tone
  446. aprs_flags.one_count = 0;
  447. }
  448. aprs_flags.byte = (aprs_flags.byte >> 1);
  449. while(sample_count < 11) // wait for symbol to be sent
  450. {
  451. if ( new_sample )
  452. {
  453. LUT_lookup();
  454. new_sample = 0;
  455. }
  456. }
  457. toggle2 = toggle2 ^ 1;
  458. //gpio_set_level(DEBUG_0, toggle2);
  459. sample_count = 0;
  460. //printf("Symbol: %x\n", aprs_flags.cur_bit);
  461. }
  462. }
  463. aprs_flags.one_count = 0;
  464. // Send HDLC Flag for TX Tail
  465. for (i = 0; i<t_len; i++)
  466. {
  467. esp_task_wdt_reset();
  468. aprs_flags.byte = 0x7E;
  469. for(j=0; j<8;j++)
  470. {
  471. aprs_flags.cur_bit = aprs_flags.byte & 0x01;
  472. // NRZ-I Encoding
  473. if (aprs_flags.cur_bit)
  474. {
  475. // do nothing
  476. aprs_flags.one_count++;
  477. }
  478. else
  479. {
  480. aprs_flags.tone = aprs_flags.tone ^ 1; // switch tone
  481. aprs_flags.one_count = 0;
  482. }
  483. aprs_flags.byte = (aprs_flags.byte >> 1);
  484. while(sample_count < 11) // wait for symbol to be sent
  485. {
  486. if ( new_sample )
  487. {
  488. LUT_lookup();
  489. new_sample = 0;
  490. }
  491. }
  492. sample_count = 0;
  493. }
  494. }
  495. gpio_intr_disable(CC1120_GPIO3);
  496. gpio_set_intr_type(CC1120_GPIO3, GPIO_INTR_DISABLE);
  497. while(cc1200_spi_strobe(CC120X_SIDLE)!= CC120X_STATE_IDLE);
  498. xTaskResumeAll();
  499. spi_device_release_bus(spi);
  500. gpio_uninstall_isr_service();
  501. }
  502. extern SemaphoreHandle_t xRadioRXISRSemaphore;
  503. extern TaskHandle_t xRadioRXTaskHandle;
  504. int8_t EXTERNAL_DATA;
  505. static void IRAM_ATTR cc1200_aprs_rx_isr(void* arg)
  506. {
  507. //uint8_t data = 0;
  508. //cc1200_spi_read_byte(CC120X_CFM_RX_DATA_OUT, &data);
  509. //GPIO.out_w1ts = (1 << DEBUG_0);
  510. static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  511. //vTaskNotifyGiveFromISR( xRadioRXTaskHandle, &xHigherPriorityTaskWoken );
  512. xSemaphoreGiveFromISR(xRadioRXISRSemaphore, &xHigherPriorityTaskWoken);
  513. if (xHigherPriorityTaskWoken == pdTRUE)
  514. {
  515. portYIELD_FROM_ISR( );
  516. }
  517. //GPIO.out_w1tc = (1 << DEBUG_0);
  518. }
  519. void IRAM_ATTR cc1200_radio_start_APRSRX(void)
  520. {
  521. // acquire SPI bus for fastest possible SPI transactions
  522. spi_device_acquire_bus(spi, portMAX_DELAY);
  523. // start RX transmission
  524. cc1200_radio_write(APRS_RX_SETTINGS, sizeof(APRS_RX_SETTINGS)/sizeof(cc1200_reg_settings_t));
  525. cc1200_radio_frequency(144390000-6000);
  526. // enable ISR for CC1120 for timing packets
  527. // gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
  528. // gpio_isr_handler_add(CC1120_GPIO2, cc1200_aprs_rx_isr, NULL);
  529. // gpio_set_intr_type(CC1120_GPIO2, GPIO_INTR_POSEDGE);
  530. // gpio_intr_enable(CC1120_GPIO2);
  531. while(cc1200_spi_strobe(CC120X_SRX) != CC120X_STATE_RX);
  532. }
  533. void cc1200_radio_stop_APRSRX(void)
  534. {
  535. // disable interrupt
  536. // gpio_intr_disable(CC1120_GPIO2);
  537. // gpio_set_intr_type(CC1120_GPIO2, GPIO_INTR_DISABLE);
  538. // gpio_uninstall_isr_service();
  539. while(cc1200_spi_strobe(CC120X_SIDLE) != CC120X_STATE_IDLE);
  540. spi_device_release_bus(spi);
  541. }
  542. void cc1200_radio_init(const cc1200_reg_settings_t* rf_settings, uint8_t len)
  543. {
  544. cc1200_gpio_init();
  545. cc1200_spi_init();
  546. cc1200_lut_init();
  547. cc1200_radio_reset(); gpio_set_level(CC1120_RESET, 1);
  548. //uint8_t data;
  549. //cc1200_spi_read_byte(CC120X_PARTNUMBER, &data);
  550. //printf("%x", data);
  551. uint8_t i;
  552. for (i=0;i<len;i++)
  553. {
  554. cc1200_spi_write_byte(rf_settings[i].addr, rf_settings[i].data);
  555. }
  556. while(cc1200_spi_strobe(CC120X_SIDLE) != CC120X_STATE_IDLE);
  557. }