cc1200.c 14 KB

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