si446x_api_lib.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. /*!
  2. * File:
  3. * si446x_api_lib.c
  4. *
  5. * Description:
  6. * This file contains the Si446x API library.
  7. *
  8. * Silicon Laboratories Confidential
  9. * Copyright 2011 Silicon Laboratories, Inc.
  10. */
  11. #include <stdarg.h>
  12. #include "radio_comm.h"
  13. #include "radio_hal.h"
  14. #include "si446x_api_lib.h"
  15. #include "si446x_cmd.h"
  16. #define RADIO_DRIVER_EXTENDED_SUPPORT
  17. union si446x_cmd_reply_union Si446xCmd;
  18. uint8_t Pro2Cmd[16];
  19. #ifdef SI446X_PATCH_CMDS
  20. uint8_t Si446xPatchCommands[][8] = { SI446X_PATCH_CMDS };
  21. #endif
  22. /*!
  23. * This functions is used to reset the si446x radio by applying shutdown and
  24. * releasing it. After this function @ref si446x_boot should be called. You
  25. * can check if POR has completed by waiting 4 ms or by polling GPIO 0, 2, or 3.
  26. * When these GPIOs are high, it is safe to call @ref si446x_boot.
  27. */
  28. void si446x_reset(void)
  29. {
  30. uint8_t loopCount;
  31. /* Put radio in shutdown, wait then release */
  32. radio_hal_AssertShutdown();
  33. //! @todo this needs to be a better delay function.
  34. for (loopCount = 255; loopCount != 0; loopCount--);
  35. radio_hal_DeassertShutdown();
  36. for (loopCount = 255; loopCount != 0; loopCount--);
  37. radio_comm_ClearCTS();
  38. }
  39. /*!
  40. * This function is used to initialize after power-up the radio chip.
  41. * Before this function @si446x_reset should be called.
  42. */
  43. void si446x_power_up(uint8_t BOOT_OPTIONS, uint8_t XTAL_OPTIONS, uint32_t XO_FREQ)
  44. {
  45. Pro2Cmd[0] = SI446X_CMD_ID_POWER_UP;
  46. Pro2Cmd[1] = BOOT_OPTIONS;
  47. Pro2Cmd[2] = XTAL_OPTIONS;
  48. Pro2Cmd[3] = (uint8_t)(XO_FREQ >> 24);
  49. Pro2Cmd[4] = (uint8_t)(XO_FREQ >> 16);
  50. Pro2Cmd[5] = (uint8_t)(XO_FREQ >> 8);
  51. Pro2Cmd[6] = (uint8_t)(XO_FREQ);
  52. radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_POWER_UP, Pro2Cmd );
  53. }
  54. /*!
  55. * This function is used to load all properties and commands with a list of NULL terminated commands.
  56. * Before this function @si446x_reset should be called.
  57. */
  58. uint8_t si446x_configuration_init(const uint8_t* pSetPropCmd)
  59. {
  60. uint8_t col;
  61. uint8_t numOfBytes;
  62. /* While cycle as far as the pointer points to a command */
  63. while (*pSetPropCmd != 0x00)
  64. {
  65. /* Commands structure in the array:
  66. * --------------------------------
  67. * LEN | <LEN length of data>
  68. */
  69. numOfBytes = *pSetPropCmd++;
  70. if (numOfBytes > 16)
  71. {
  72. /* Number of command bytes exceeds maximal allowable length */
  73. return SI446X_COMMAND_ERROR;
  74. }
  75. for (col = 0; col < numOfBytes; col++)
  76. {
  77. Pro2Cmd[col] = *pSetPropCmd;
  78. pSetPropCmd++;
  79. }
  80. if (radio_comm_SendCmdGetResp(numOfBytes, Pro2Cmd, 0, 0) != 0xFF)
  81. {
  82. /* Timeout occured */
  83. return SI446X_CTS_TIMEOUT;
  84. }
  85. if (radio_hal_NirqLevel() == 0)
  86. {
  87. /* Get and clear all interrupts. An error has occured... */
  88. si446x_get_int_status(0, 0, 0);
  89. if (Si446xCmd.GET_INT_STATUS.CHIP_PEND & SI446X_CMD_GET_CHIP_STATUS_REP_CHIP_PEND_CMD_ERROR_PEND_MASK)
  90. {
  91. return SI446X_COMMAND_ERROR;
  92. }
  93. }
  94. }
  95. return SI446X_SUCCESS;
  96. }
  97. /*! This function sends the PART_INFO command to the radio and receives the answer
  98. * into @Si446xCmd union.
  99. */
  100. void si446x_part_info(void)
  101. {
  102. Pro2Cmd[0] = SI446X_CMD_ID_PART_INFO;
  103. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_PART_INFO,
  104. Pro2Cmd,
  105. SI446X_CMD_REPLY_COUNT_PART_INFO,
  106. Pro2Cmd );
  107. Si446xCmd.PART_INFO.CHIPREV = Pro2Cmd[0];
  108. Si446xCmd.PART_INFO.PART = ((uint16_t)Pro2Cmd[1] << 8) & 0xFF00;
  109. Si446xCmd.PART_INFO.PART |= (uint16_t)Pro2Cmd[2] & 0x00FF;
  110. Si446xCmd.PART_INFO.PBUILD = Pro2Cmd[3];
  111. Si446xCmd.PART_INFO.ID = ((uint16_t)Pro2Cmd[4] << 8) & 0xFF00;
  112. Si446xCmd.PART_INFO.ID |= (uint16_t)Pro2Cmd[5] & 0x00FF;
  113. Si446xCmd.PART_INFO.CUSTOMER = Pro2Cmd[6];
  114. Si446xCmd.PART_INFO.ROMID = Pro2Cmd[7];
  115. }
  116. /*! Sends START_TX command to the radio.
  117. *
  118. * @param CHANNEL Channel number.
  119. * @param CONDITION Start TX condition.
  120. * @param TX_LEN Payload length (exclude the PH generated CRC).
  121. */
  122. void si446x_start_tx(uint8_t CHANNEL, uint8_t CONDITION, uint16_t TX_LEN)
  123. {
  124. Pro2Cmd[0] = SI446X_CMD_ID_START_TX;
  125. Pro2Cmd[1] = CHANNEL;
  126. Pro2Cmd[2] = CONDITION;
  127. Pro2Cmd[3] = (uint8_t)(TX_LEN >> 8);
  128. Pro2Cmd[4] = (uint8_t)(TX_LEN);
  129. Pro2Cmd[5] = 0x00;
  130. // Don't repeat the packet,
  131. // ie. transmit the packet only once
  132. Pro2Cmd[6] = 0x00;
  133. radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_START_TX, Pro2Cmd );
  134. }
  135. /*!
  136. * Sends START_RX command to the radio.
  137. *
  138. * @param CHANNEL Channel number.
  139. * @param CONDITION Start RX condition.
  140. * @param RX_LEN Payload length (exclude the PH generated CRC).
  141. * @param NEXT_STATE1 Next state when Preamble Timeout occurs.
  142. * @param NEXT_STATE2 Next state when a valid packet received.
  143. * @param NEXT_STATE3 Next state when invalid packet received (e.g. CRC error).
  144. */
  145. void si446x_start_rx(uint8_t CHANNEL, uint8_t CONDITION, uint16_t RX_LEN, uint8_t NEXT_STATE1, uint8_t NEXT_STATE2, uint8_t NEXT_STATE3)
  146. {
  147. Pro2Cmd[0] = SI446X_CMD_ID_START_RX;
  148. Pro2Cmd[1] = CHANNEL;
  149. Pro2Cmd[2] = CONDITION;
  150. Pro2Cmd[3] = (uint8_t)(RX_LEN >> 8);
  151. Pro2Cmd[4] = (uint8_t)(RX_LEN);
  152. Pro2Cmd[5] = NEXT_STATE1;
  153. Pro2Cmd[6] = NEXT_STATE2;
  154. Pro2Cmd[7] = NEXT_STATE3;
  155. radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_START_RX, Pro2Cmd );
  156. }
  157. /*!
  158. * Get the Interrupt status/pending flags form the radio and clear flags if requested.
  159. *
  160. * @param PH_CLR_PEND Packet Handler pending flags clear.
  161. * @param MODEM_CLR_PEND Modem Status pending flags clear.
  162. * @param CHIP_CLR_PEND Chip State pending flags clear.
  163. */
  164. void si446x_get_int_status(uint8_t PH_CLR_PEND, uint8_t MODEM_CLR_PEND, uint8_t CHIP_CLR_PEND)
  165. {
  166. Pro2Cmd[0] = SI446X_CMD_ID_GET_INT_STATUS;
  167. Pro2Cmd[1] = PH_CLR_PEND;
  168. Pro2Cmd[2] = MODEM_CLR_PEND;
  169. Pro2Cmd[3] = CHIP_CLR_PEND;
  170. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_INT_STATUS,
  171. Pro2Cmd,
  172. SI446X_CMD_REPLY_COUNT_GET_INT_STATUS,
  173. Pro2Cmd );
  174. Si446xCmd.GET_INT_STATUS.INT_PEND = Pro2Cmd[0];
  175. Si446xCmd.GET_INT_STATUS.INT_STATUS = Pro2Cmd[1];
  176. Si446xCmd.GET_INT_STATUS.PH_PEND = Pro2Cmd[2];
  177. Si446xCmd.GET_INT_STATUS.PH_STATUS = Pro2Cmd[3];
  178. Si446xCmd.GET_INT_STATUS.MODEM_PEND = Pro2Cmd[4];
  179. Si446xCmd.GET_INT_STATUS.MODEM_STATUS = Pro2Cmd[5];
  180. Si446xCmd.GET_INT_STATUS.CHIP_PEND = Pro2Cmd[6];
  181. Si446xCmd.GET_INT_STATUS.CHIP_STATUS = Pro2Cmd[7];
  182. }
  183. /*!
  184. * Send GPIO pin config command to the radio and reads the answer into
  185. * @Si446xCmd union.
  186. *
  187. * @param GPIO0 GPIO0 configuration.
  188. * @param GPIO1 GPIO1 configuration.
  189. * @param GPIO2 GPIO2 configuration.
  190. * @param GPIO3 GPIO3 configuration.
  191. * @param NIRQ NIRQ configuration.
  192. * @param SDO SDO configuration.
  193. * @param GEN_CONFIG General pin configuration.
  194. */
  195. void si446x_gpio_pin_cfg(uint8_t GPIO0, uint8_t GPIO1, uint8_t GPIO2, uint8_t GPIO3, uint8_t NIRQ, uint8_t SDO, uint8_t GEN_CONFIG)
  196. {
  197. Pro2Cmd[0] = SI446X_CMD_ID_GPIO_PIN_CFG;
  198. Pro2Cmd[1] = GPIO0;
  199. Pro2Cmd[2] = GPIO1;
  200. Pro2Cmd[3] = GPIO2;
  201. Pro2Cmd[4] = GPIO3;
  202. Pro2Cmd[5] = NIRQ;
  203. Pro2Cmd[6] = SDO;
  204. Pro2Cmd[7] = GEN_CONFIG;
  205. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GPIO_PIN_CFG,
  206. Pro2Cmd,
  207. SI446X_CMD_REPLY_COUNT_GPIO_PIN_CFG,
  208. Pro2Cmd );
  209. Si446xCmd.GPIO_PIN_CFG.GPIO[0] = Pro2Cmd[0];
  210. Si446xCmd.GPIO_PIN_CFG.GPIO[1] = Pro2Cmd[1];
  211. Si446xCmd.GPIO_PIN_CFG.GPIO[2] = Pro2Cmd[2];
  212. Si446xCmd.GPIO_PIN_CFG.GPIO[3] = Pro2Cmd[3];
  213. Si446xCmd.GPIO_PIN_CFG.NIRQ = Pro2Cmd[4];
  214. Si446xCmd.GPIO_PIN_CFG.SDO = Pro2Cmd[5];
  215. Si446xCmd.GPIO_PIN_CFG.GEN_CONFIG = Pro2Cmd[6];
  216. }
  217. /*!
  218. * Send SET_PROPERTY command to the radio.
  219. *
  220. * @param GROUP Property group.
  221. * @param NUM_PROPS Number of property to be set. The properties must be in ascending order
  222. * in their sub-property aspect. Max. 12 properties can be set in one command.
  223. * @param START_PROP Start sub-property address.
  224. */
  225. #ifdef __C51__
  226. #pragma maxargs (13) /* allow 13 bytes for parameters */
  227. #endif
  228. void si446x_set_property( uint8_t GROUP, uint8_t NUM_PROPS, uint8_t START_PROP, ... )
  229. {
  230. va_list argList;
  231. uint8_t cmdIndex;
  232. Pro2Cmd[0] = SI446X_CMD_ID_SET_PROPERTY;
  233. Pro2Cmd[1] = GROUP;
  234. Pro2Cmd[2] = NUM_PROPS;
  235. Pro2Cmd[3] = START_PROP;
  236. va_start (argList, START_PROP);
  237. cmdIndex = 4;
  238. while(NUM_PROPS--)
  239. {
  240. Pro2Cmd[cmdIndex] = va_arg (argList,int);
  241. cmdIndex++;
  242. }
  243. va_end(argList);
  244. radio_comm_SendCmd( cmdIndex, Pro2Cmd );
  245. }
  246. /*!
  247. * Issue a change state command to the radio.
  248. *
  249. * @param NEXT_STATE1 Next state.
  250. */
  251. void si446x_change_state(uint8_t NEXT_STATE1)
  252. {
  253. Pro2Cmd[0] = SI446X_CMD_ID_CHANGE_STATE;
  254. Pro2Cmd[1] = NEXT_STATE1;
  255. radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_CHANGE_STATE, Pro2Cmd );
  256. }
  257. #ifdef RADIO_DRIVER_EXTENDED_SUPPORT
  258. /* Extended driver support functions */
  259. /*!
  260. * Sends NOP command to the radio. Can be used to maintain SPI communication.
  261. */
  262. void si446x_nop(void)
  263. {
  264. Pro2Cmd[0] = SI446X_CMD_ID_NOP;
  265. radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_NOP, Pro2Cmd );
  266. }
  267. /*!
  268. * Send the FIFO_INFO command to the radio. Optionally resets the TX/RX FIFO. Reads the radio response back
  269. * into @Si446xCmd.
  270. *
  271. * @param FIFO RX/TX FIFO reset flags.
  272. */
  273. void si446x_fifo_info(uint8_t FIFO)
  274. {
  275. Pro2Cmd[0] = SI446X_CMD_ID_FIFO_INFO;
  276. Pro2Cmd[1] = FIFO;
  277. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_FIFO_INFO,
  278. Pro2Cmd,
  279. SI446X_CMD_REPLY_COUNT_FIFO_INFO,
  280. Pro2Cmd );
  281. Si446xCmd.FIFO_INFO.RX_FIFO_COUNT = Pro2Cmd[0];
  282. Si446xCmd.FIFO_INFO.TX_FIFO_SPACE = Pro2Cmd[1];
  283. }
  284. /*!
  285. * The function can be used to load data into TX FIFO.
  286. *
  287. * @param numBytes Data length to be load.
  288. * @param pTxData Pointer to the data (uint8_t*).
  289. */
  290. void si446x_write_tx_fifo(uint8_t numBytes, uint8_t* pTxData)
  291. {
  292. radio_comm_WriteData( SI446X_CMD_ID_WRITE_TX_FIFO, 0, numBytes, pTxData );
  293. }
  294. /*!
  295. * Reads the RX FIFO content from the radio.
  296. *
  297. * @param numBytes Data length to be read.
  298. * @param pRxData Pointer to the buffer location.
  299. */
  300. void si446x_read_rx_fifo(uint8_t numBytes, uint8_t* pRxData)
  301. {
  302. radio_comm_ReadData( SI446X_CMD_ID_READ_RX_FIFO, 0, numBytes, pRxData );
  303. }
  304. /*!
  305. * Get property values from the radio. Reads them into Si446xCmd union.
  306. *
  307. * @param GROUP Property group number.
  308. * @param NUM_PROPS Number of properties to be read.
  309. * @param START_PROP Starting sub-property number.
  310. */
  311. void si446x_get_property(uint8_t GROUP, uint8_t NUM_PROPS, uint8_t START_PROP)
  312. {
  313. Pro2Cmd[0] = SI446X_CMD_ID_GET_PROPERTY;
  314. Pro2Cmd[1] = GROUP;
  315. Pro2Cmd[2] = NUM_PROPS;
  316. Pro2Cmd[3] = START_PROP;
  317. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_PROPERTY,
  318. Pro2Cmd,
  319. Pro2Cmd[2],
  320. Pro2Cmd );
  321. Si446xCmd.GET_PROPERTY.DATA[0 ] = Pro2Cmd[0];
  322. Si446xCmd.GET_PROPERTY.DATA[1 ] = Pro2Cmd[1];
  323. Si446xCmd.GET_PROPERTY.DATA[2 ] = Pro2Cmd[2];
  324. Si446xCmd.GET_PROPERTY.DATA[3 ] = Pro2Cmd[3];
  325. Si446xCmd.GET_PROPERTY.DATA[4 ] = Pro2Cmd[4];
  326. Si446xCmd.GET_PROPERTY.DATA[5 ] = Pro2Cmd[5];
  327. Si446xCmd.GET_PROPERTY.DATA[6 ] = Pro2Cmd[6];
  328. Si446xCmd.GET_PROPERTY.DATA[7 ] = Pro2Cmd[7];
  329. Si446xCmd.GET_PROPERTY.DATA[8 ] = Pro2Cmd[8];
  330. Si446xCmd.GET_PROPERTY.DATA[9 ] = Pro2Cmd[9];
  331. Si446xCmd.GET_PROPERTY.DATA[10] = Pro2Cmd[10];
  332. Si446xCmd.GET_PROPERTY.DATA[11] = Pro2Cmd[11];
  333. Si446xCmd.GET_PROPERTY.DATA[12] = Pro2Cmd[12];
  334. Si446xCmd.GET_PROPERTY.DATA[13] = Pro2Cmd[13];
  335. Si446xCmd.GET_PROPERTY.DATA[14] = Pro2Cmd[14];
  336. Si446xCmd.GET_PROPERTY.DATA[15] = Pro2Cmd[15];
  337. }
  338. #ifdef RADIO_DRIVER_FULL_SUPPORT
  339. /* Full driver support functions */
  340. /*!
  341. * Sends the FUNC_INFO command to the radio, then reads the resonse into @Si446xCmd union.
  342. */
  343. void si446x_func_info(void)
  344. {
  345. Pro2Cmd[0] = SI446X_CMD_ID_FUNC_INFO;
  346. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_FUNC_INFO,
  347. Pro2Cmd,
  348. SI446X_CMD_REPLY_COUNT_FUNC_INFO,
  349. Pro2Cmd );
  350. Si446xCmd.FUNC_INFO.REVEXT = Pro2Cmd[0];
  351. Si446xCmd.FUNC_INFO.REVBRANCH = Pro2Cmd[1];
  352. Si446xCmd.FUNC_INFO.REVINT = Pro2Cmd[2];
  353. Si446xCmd.FUNC_INFO.FUNC = Pro2Cmd[5];
  354. }
  355. /*!
  356. * Reads the Fast Response Registers starting with A register into @Si446xCmd union.
  357. *
  358. * @param respByteCount Number of Fast Response Registers to be read.
  359. */
  360. void si446x_frr_a_read(uint8_t respByteCount)
  361. {
  362. radio_comm_ReadData(SI446X_CMD_ID_FRR_A_READ,
  363. 0,
  364. respByteCount,
  365. Pro2Cmd);
  366. Si446xCmd.FRR_A_READ.FRR_A_VALUE = Pro2Cmd[0];
  367. Si446xCmd.FRR_A_READ.FRR_B_VALUE = Pro2Cmd[1];
  368. Si446xCmd.FRR_A_READ.FRR_C_VALUE = Pro2Cmd[2];
  369. Si446xCmd.FRR_A_READ.FRR_D_VALUE = Pro2Cmd[3];
  370. }
  371. /*!
  372. * Reads the Fast Response Registers starting with B register into @Si446xCmd union.
  373. *
  374. * @param respByteCount Number of Fast Response Registers to be read.
  375. */
  376. void si446x_frr_b_read(uint8_t respByteCount)
  377. {
  378. radio_comm_ReadData(SI446X_CMD_ID_FRR_B_READ,
  379. 0,
  380. respByteCount,
  381. Pro2Cmd);
  382. Si446xCmd.FRR_B_READ.FRR_B_VALUE = Pro2Cmd[0];
  383. Si446xCmd.FRR_B_READ.FRR_C_VALUE = Pro2Cmd[1];
  384. Si446xCmd.FRR_B_READ.FRR_D_VALUE = Pro2Cmd[2];
  385. Si446xCmd.FRR_B_READ.FRR_A_VALUE = Pro2Cmd[3];
  386. }
  387. /*!
  388. * Reads the Fast Response Registers starting with C register into @Si446xCmd union.
  389. *
  390. * @param respByteCount Number of Fast Response Registers to be read.
  391. */
  392. void si446x_frr_c_read(uint8_t respByteCount)
  393. {
  394. radio_comm_ReadData(SI446X_CMD_ID_FRR_C_READ,
  395. 0,
  396. respByteCount,
  397. Pro2Cmd);
  398. Si446xCmd.FRR_C_READ.FRR_C_VALUE = Pro2Cmd[0];
  399. Si446xCmd.FRR_C_READ.FRR_D_VALUE = Pro2Cmd[1];
  400. Si446xCmd.FRR_C_READ.FRR_A_VALUE = Pro2Cmd[2];
  401. Si446xCmd.FRR_C_READ.FRR_B_VALUE = Pro2Cmd[3];
  402. }
  403. /*!
  404. * Reads the Fast Response Registers starting with D register into @Si446xCmd union.
  405. *
  406. * @param respByteCount Number of Fast Response Registers to be read.
  407. */
  408. void si446x_frr_d_read(uint8_t respByteCount)
  409. {
  410. radio_comm_ReadData(SI446X_CMD_ID_FRR_D_READ,
  411. 0,
  412. respByteCount,
  413. Pro2Cmd);
  414. Si446xCmd.FRR_D_READ.FRR_D_VALUE = Pro2Cmd[0];
  415. Si446xCmd.FRR_D_READ.FRR_A_VALUE = Pro2Cmd[1];
  416. Si446xCmd.FRR_D_READ.FRR_B_VALUE = Pro2Cmd[2];
  417. Si446xCmd.FRR_D_READ.FRR_C_VALUE = Pro2Cmd[3];
  418. }
  419. /*!
  420. * Reads the ADC values from the radio into @Si446xCmd union.
  421. *
  422. * @param ADC_EN ADC enable parameter.
  423. */
  424. void si446x_get_adc_reading(uint8_t ADC_EN)
  425. {
  426. Pro2Cmd[0] = SI446X_CMD_ID_GET_ADC_READING;
  427. Pro2Cmd[1] = ADC_EN;
  428. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_ADC_READING,
  429. Pro2Cmd,
  430. SI446X_CMD_REPLY_COUNT_GET_ADC_READING,
  431. Pro2Cmd );
  432. Si446xCmd.GET_ADC_READING.GPIO_ADC = ((uint16_t)Pro2Cmd[0] << 8) & 0xFF00;
  433. Si446xCmd.GET_ADC_READING.GPIO_ADC |= (uint16_t)Pro2Cmd[1] & 0x00FF;
  434. Si446xCmd.GET_ADC_READING.BATTERY_ADC = ((uint16_t)Pro2Cmd[2] << 8) & 0xFF00;
  435. Si446xCmd.GET_ADC_READING.BATTERY_ADC |= (uint16_t)Pro2Cmd[3] & 0x00FF;
  436. Si446xCmd.GET_ADC_READING.TEMP_ADC = ((uint16_t)Pro2Cmd[4] << 8) & 0xFF00;
  437. Si446xCmd.GET_ADC_READING.TEMP_ADC |= (uint16_t)Pro2Cmd[5] & 0x00FF;
  438. }
  439. /*!
  440. * Receives information from the radio of the current packet. Optionally can be used to modify
  441. * the Packet Handler properties during packet reception.
  442. *
  443. * @param FIELD_NUMBER_MASK Packet Field number mask value.
  444. * @param LEN Length value.
  445. * @param DIFF_LEN Difference length.
  446. */
  447. void si446x_get_packet_info(uint8_t FIELD_NUMBER_MASK, uint16_t LEN, int16_t DIFF_LEN )
  448. {
  449. Pro2Cmd[0] = SI446X_CMD_ID_PACKET_INFO;
  450. Pro2Cmd[1] = FIELD_NUMBER_MASK;
  451. Pro2Cmd[2] = (uint8_t)(LEN >> 8);
  452. Pro2Cmd[3] = (uint8_t)(LEN);
  453. // the different of the byte, althrough it is signed, but to command hander
  454. // it can treat it as unsigned
  455. Pro2Cmd[4] = (uint8_t)((uint16_t)DIFF_LEN >> 8);
  456. Pro2Cmd[5] = (uint8_t)(DIFF_LEN);
  457. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_PACKET_INFO,
  458. Pro2Cmd,
  459. SI446X_CMD_REPLY_COUNT_PACKET_INFO,
  460. Pro2Cmd );
  461. Si446xCmd.PACKET_INFO.LENGTH = ((uint16_t)Pro2Cmd[0] << 8) & 0xFF00;
  462. Si446xCmd.PACKET_INFO.LENGTH |= (uint16_t)Pro2Cmd[1] & 0x00FF;
  463. }
  464. /*!
  465. * Gets the Packet Handler status flags. Optionally clears them.
  466. *
  467. * @param PH_CLR_PEND Flags to clear.
  468. */
  469. void si446x_get_ph_status(uint8_t PH_CLR_PEND)
  470. {
  471. Pro2Cmd[0] = SI446X_CMD_ID_GET_PH_STATUS;
  472. Pro2Cmd[1] = PH_CLR_PEND;
  473. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_PH_STATUS,
  474. Pro2Cmd,
  475. SI446X_CMD_REPLY_COUNT_GET_PH_STATUS,
  476. Pro2Cmd );
  477. Si446xCmd.GET_PH_STATUS.PH_PEND = Pro2Cmd[0];
  478. Si446xCmd.GET_PH_STATUS.PH_STATUS = Pro2Cmd[1];
  479. }
  480. /*!
  481. * Gets the Modem status flags. Optionally clears them.
  482. *
  483. * @param MODEM_CLR_PEND Flags to clear.
  484. */
  485. void si446x_get_modem_status( uint8_t MODEM_CLR_PEND )
  486. {
  487. Pro2Cmd[0] = SI446X_CMD_ID_GET_MODEM_STATUS;
  488. Pro2Cmd[1] = MODEM_CLR_PEND;
  489. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_MODEM_STATUS,
  490. Pro2Cmd,
  491. SI446X_CMD_REPLY_COUNT_GET_MODEM_STATUS,
  492. Pro2Cmd );
  493. Si446xCmd.GET_MODEM_STATUS.MODEM_PEND = Pro2Cmd[0];
  494. Si446xCmd.GET_MODEM_STATUS.MODEM_STATUS = Pro2Cmd[1];
  495. Si446xCmd.GET_MODEM_STATUS.CURR_RSSI = Pro2Cmd[2];
  496. Si446xCmd.GET_MODEM_STATUS.LATCH_RSSI = Pro2Cmd[3];
  497. Si446xCmd.GET_MODEM_STATUS.ANT1_RSSI = Pro2Cmd[4];
  498. Si446xCmd.GET_MODEM_STATUS.ANT2_RSSI = Pro2Cmd[5];
  499. Si446xCmd.GET_MODEM_STATUS.AFC_FREQ_OFFSET = ((uint16_t)Pro2Cmd[6] << 8) & 0xFF00;
  500. Si446xCmd.GET_MODEM_STATUS.AFC_FREQ_OFFSET |= (uint16_t)Pro2Cmd[7] & 0x00FF;
  501. }
  502. /*!
  503. * Gets the Chip status flags. Optionally clears them.
  504. *
  505. * @param CHIP_CLR_PEND Flags to clear.
  506. */
  507. void si446x_get_chip_status( uint8_t CHIP_CLR_PEND )
  508. {
  509. Pro2Cmd[0] = SI446X_CMD_ID_GET_CHIP_STATUS;
  510. Pro2Cmd[1] = CHIP_CLR_PEND;
  511. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_CHIP_STATUS,
  512. Pro2Cmd,
  513. SI446X_CMD_REPLY_COUNT_GET_CHIP_STATUS,
  514. Pro2Cmd );
  515. Si446xCmd.GET_CHIP_STATUS.CHIP_PEND = Pro2Cmd[0];
  516. Si446xCmd.GET_CHIP_STATUS.CHIP_STATUS = Pro2Cmd[1];
  517. Si446xCmd.GET_CHIP_STATUS.CMD_ERR_STATUS = Pro2Cmd[2];
  518. }
  519. /*!
  520. * Performs image rejection calibration. Completion can be monitored by polling CTS or waiting for CHIP_READY interrupt source.
  521. *
  522. * @param SEARCHING_STEP_SIZE
  523. * @param SEARCHING_RSSI_AVG
  524. * @param RX_CHAIN_SETTING1
  525. * @param RX_CHAIN_SETTING2
  526. */
  527. void si446x_ircal(uint8_t SEARCHING_STEP_SIZE, uint8_t SEARCHING_RSSI_AVG, uint8_t RX_CHAIN_SETTING1, uint8_t RX_CHAIN_SETTING2)
  528. {
  529. Pro2Cmd[0] = SI446X_CMD_ID_IRCAL;
  530. Pro2Cmd[1] = SEARCHING_STEP_SIZE;
  531. Pro2Cmd[2] = SEARCHING_RSSI_AVG;
  532. Pro2Cmd[3] = RX_CHAIN_SETTING1;
  533. Pro2Cmd[4] = RX_CHAIN_SETTING2;
  534. radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_IRCAL, Pro2Cmd);
  535. }
  536. /*!
  537. * Image rejection calibration. Forces a specific value for IR calibration, and reads back calibration values from previous calibrations
  538. *
  539. * @param IRCAL_AMP
  540. * @param IRCAL_PH
  541. */
  542. void si446x_ircal_manual(uint8_t IRCAL_AMP, uint8_t IRCAL_PH)
  543. {
  544. Pro2Cmd[0] = SI446X_CMD_ID_IRCAL_MANUAL;
  545. Pro2Cmd[1] = IRCAL_AMP;
  546. Pro2Cmd[2] = IRCAL_PH;
  547. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_IRCAL_MANUAL,
  548. Pro2Cmd,
  549. SI446X_CMD_REPLY_COUNT_IRCAL_MANUAL,
  550. Pro2Cmd );
  551. Si446xCmd.IRCAL_MANUAL.IRCAL_AMP_REPLY = Pro2Cmd[0];
  552. Si446xCmd.IRCAL_MANUAL.IRCAL_PH_REPLY = Pro2Cmd[1];
  553. }
  554. /*!
  555. * Requests the current state of the device and lists pending TX and RX requests
  556. */
  557. void si446x_request_device_state(void)
  558. {
  559. Pro2Cmd[0] = SI446X_CMD_ID_REQUEST_DEVICE_STATE;
  560. radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_REQUEST_DEVICE_STATE,
  561. Pro2Cmd,
  562. SI446X_CMD_REPLY_COUNT_REQUEST_DEVICE_STATE,
  563. Pro2Cmd );
  564. Si446xCmd.REQUEST_DEVICE_STATE.CURR_STATE = Pro2Cmd[0];
  565. Si446xCmd.REQUEST_DEVICE_STATE.CURRENT_CHANNEL = Pro2Cmd[1];
  566. }
  567. /*!
  568. * While in TX state this will hop to the frequency specified by the parameters
  569. *
  570. * @param INTE New INTE register value.
  571. * @param FRAC2 New FRAC2 register value.
  572. * @param FRAC1 New FRAC1 register value.
  573. * @param FRAC0 New FRAC0 register value.
  574. * @param VCO_CNT1 New VCO_CNT1 register value.
  575. * @param VCO_CNT0 New VCO_CNT0 register value.
  576. * @param PLL_SETTLE_TIME1 New PLL_SETTLE_TIME1 register value.
  577. * @param PLL_SETTLE_TIME0 New PLL_SETTLE_TIME0 register value.
  578. */
  579. void si446x_tx_hop(uint8_t INTE, uint8_t FRAC2, uint8_t FRAC1, uint8_t FRAC0, uint8_t VCO_CNT1, uint8_t VCO_CNT0, uint8_t PLL_SETTLE_TIME1, uint8_t PLL_SETTLE_TIME0)
  580. {
  581. Pro2Cmd[0] = SI446X_CMD_ID_TX_HOP;
  582. Pro2Cmd[1] = INTE;
  583. Pro2Cmd[2] = FRAC2;
  584. Pro2Cmd[3] = FRAC1;
  585. Pro2Cmd[4] = FRAC0;
  586. Pro2Cmd[5] = VCO_CNT1;
  587. Pro2Cmd[6] = VCO_CNT0;
  588. Pro2Cmd[7] = PLL_SETTLE_TIME1;
  589. Pro2Cmd[8] = PLL_SETTLE_TIME0;
  590. radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_TX_HOP, Pro2Cmd );
  591. }
  592. /*!
  593. * While in RX state this will hop to the frequency specified by the parameters and start searching for a preamble.
  594. *
  595. * @param INTE New INTE register value.
  596. * @param FRAC2 New FRAC2 register value.
  597. * @param FRAC1 New FRAC1 register value.
  598. * @param FRAC0 New FRAC0 register value.
  599. * @param VCO_CNT1 New VCO_CNT1 register value.
  600. * @param VCO_CNT0 New VCO_CNT0 register value.
  601. */
  602. void si446x_rx_hop(uint8_t INTE, uint8_t FRAC2, uint8_t FRAC1, uint8_t FRAC0, uint8_t VCO_CNT1, uint8_t VCO_CNT0)
  603. {
  604. Pro2Cmd[0] = SI446X_CMD_ID_RX_HOP;
  605. Pro2Cmd[1] = INTE;
  606. Pro2Cmd[2] = FRAC2;
  607. Pro2Cmd[3] = FRAC1;
  608. Pro2Cmd[4] = FRAC0;
  609. Pro2Cmd[5] = VCO_CNT1;
  610. Pro2Cmd[6] = VCO_CNT0;
  611. radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_RX_HOP, Pro2Cmd );
  612. }
  613. /*! Sends START_TX command ID to the radio with no input parameters
  614. *
  615. */
  616. void si446x_start_tx_fast( void )
  617. {
  618. Pro2Cmd[0] = SI446X_CMD_ID_START_TX;
  619. radio_comm_SendCmd( 1, Pro2Cmd );
  620. }
  621. /*!
  622. * Sends START_RX command ID to the radio with no input parameters
  623. *
  624. */
  625. void si446x_start_rx_fast( void )
  626. {
  627. Pro2Cmd[0] = SI446X_CMD_ID_START_RX;
  628. radio_comm_SendCmd( 1, Pro2Cmd );
  629. }
  630. /*!
  631. * Clear all Interrupt status/pending flags. Does NOT read back interrupt flags
  632. *
  633. */
  634. void si446x_get_int_status_fast_clear( void )
  635. {
  636. Pro2Cmd[0] = SI446X_CMD_ID_GET_INT_STATUS;
  637. radio_comm_SendCmd( 1, Pro2Cmd );
  638. }
  639. /*!
  640. * Clear and read all Interrupt status/pending flags
  641. *
  642. */
  643. void si446x_get_int_status_fast_clear_read(void)
  644. {
  645. Pro2Cmd[0] = SI446X_CMD_ID_GET_INT_STATUS;
  646. radio_comm_SendCmdGetResp( 1,
  647. Pro2Cmd,
  648. SI446X_CMD_REPLY_COUNT_GET_INT_STATUS,
  649. Pro2Cmd );
  650. Si446xCmd.GET_INT_STATUS.INT_PEND = Pro2Cmd[0];
  651. Si446xCmd.GET_INT_STATUS.INT_STATUS = Pro2Cmd[1];
  652. Si446xCmd.GET_INT_STATUS.PH_PEND = Pro2Cmd[2];
  653. Si446xCmd.GET_INT_STATUS.PH_STATUS = Pro2Cmd[3];
  654. Si446xCmd.GET_INT_STATUS.MODEM_PEND = Pro2Cmd[4];
  655. Si446xCmd.GET_INT_STATUS.MODEM_STATUS = Pro2Cmd[5];
  656. Si446xCmd.GET_INT_STATUS.CHIP_PEND = Pro2Cmd[6];
  657. Si446xCmd.GET_INT_STATUS.CHIP_STATUS = Pro2Cmd[7];
  658. }
  659. /*!
  660. * Reads back current GPIO pin configuration. Does NOT configure GPIO pins
  661. *
  662. */
  663. void si446x_gpio_pin_cfg_fast( void )
  664. {
  665. Pro2Cmd[0] = SI446X_CMD_ID_GPIO_PIN_CFG;
  666. radio_comm_SendCmdGetResp( 1,
  667. Pro2Cmd,
  668. SI446X_CMD_REPLY_COUNT_GPIO_PIN_CFG,
  669. Pro2Cmd );
  670. Si446xCmd.GPIO_PIN_CFG.GPIO[0] = Pro2Cmd[0];
  671. Si446xCmd.GPIO_PIN_CFG.GPIO[1] = Pro2Cmd[1];
  672. Si446xCmd.GPIO_PIN_CFG.GPIO[2] = Pro2Cmd[2];
  673. Si446xCmd.GPIO_PIN_CFG.GPIO[3] = Pro2Cmd[3];
  674. Si446xCmd.GPIO_PIN_CFG.NIRQ = Pro2Cmd[4];
  675. Si446xCmd.GPIO_PIN_CFG.SDO = Pro2Cmd[5];
  676. Si446xCmd.GPIO_PIN_CFG.GEN_CONFIG = Pro2Cmd[6];
  677. }
  678. /*!
  679. * Clear all Packet Handler status flags. Does NOT read back interrupt flags
  680. *
  681. */
  682. void si446x_get_ph_status_fast_clear( void )
  683. {
  684. Pro2Cmd[0] = SI446X_CMD_ID_GET_PH_STATUS;
  685. Pro2Cmd[1] = 0;
  686. radio_comm_SendCmd( 2, Pro2Cmd );
  687. }
  688. /*!
  689. * Clear and read all Packet Handler status flags.
  690. *
  691. */
  692. void si446x_get_ph_status_fast_clear_read(void)
  693. {
  694. Pro2Cmd[0] = SI446X_CMD_ID_GET_PH_STATUS;
  695. radio_comm_SendCmdGetResp( 1,
  696. Pro2Cmd,
  697. SI446X_CMD_REPLY_COUNT_GET_PH_STATUS,
  698. Pro2Cmd );
  699. Si446xCmd.GET_PH_STATUS.PH_PEND = Pro2Cmd[0];
  700. Si446xCmd.GET_PH_STATUS.PH_STATUS = Pro2Cmd[1];
  701. }
  702. /*!
  703. * Clear all Modem status flags. Does NOT read back interrupt flags
  704. *
  705. */
  706. void si446x_get_modem_status_fast_clear( void )
  707. {
  708. Pro2Cmd[0] = SI446X_CMD_ID_GET_MODEM_STATUS;
  709. Pro2Cmd[1] = 0;
  710. radio_comm_SendCmd( 2, Pro2Cmd );
  711. }
  712. /*!
  713. * Clear and read all Modem status flags.
  714. *
  715. */
  716. void si446x_get_modem_status_fast_clear_read( void )
  717. {
  718. Pro2Cmd[0] = SI446X_CMD_ID_GET_MODEM_STATUS;
  719. radio_comm_SendCmdGetResp( 1,
  720. Pro2Cmd,
  721. SI446X_CMD_REPLY_COUNT_GET_MODEM_STATUS,
  722. Pro2Cmd );
  723. Si446xCmd.GET_MODEM_STATUS.MODEM_PEND = Pro2Cmd[0];
  724. Si446xCmd.GET_MODEM_STATUS.MODEM_STATUS = Pro2Cmd[1];
  725. Si446xCmd.GET_MODEM_STATUS.CURR_RSSI = Pro2Cmd[2];
  726. Si446xCmd.GET_MODEM_STATUS.LATCH_RSSI = Pro2Cmd[3];
  727. Si446xCmd.GET_MODEM_STATUS.ANT1_RSSI = Pro2Cmd[4];
  728. Si446xCmd.GET_MODEM_STATUS.ANT2_RSSI = Pro2Cmd[5];
  729. Si446xCmd.GET_MODEM_STATUS.AFC_FREQ_OFFSET = ((uint16_t)Pro2Cmd[6] << 8) & 0xFF00;
  730. Si446xCmd.GET_MODEM_STATUS.AFC_FREQ_OFFSET |= (uint16_t)Pro2Cmd[7] & 0x00FF;
  731. }
  732. /*!
  733. * Clear all Chip status flags. Does NOT read back interrupt flags
  734. *
  735. */
  736. void si446x_get_chip_status_fast_clear( void )
  737. {
  738. Pro2Cmd[0] = SI446X_CMD_ID_GET_CHIP_STATUS;
  739. Pro2Cmd[1] = 0;
  740. radio_comm_SendCmd( 2, Pro2Cmd );
  741. }
  742. /*!
  743. * Clear and read all Chip status flags.
  744. *
  745. */
  746. void si446x_get_chip_status_fast_clear_read( void )
  747. {
  748. Pro2Cmd[0] = SI446X_CMD_ID_GET_CHIP_STATUS;
  749. radio_comm_SendCmdGetResp( 1,
  750. Pro2Cmd,
  751. SI446X_CMD_REPLY_COUNT_GET_CHIP_STATUS,
  752. Pro2Cmd );
  753. Si446xCmd.GET_CHIP_STATUS.CHIP_PEND = Pro2Cmd[0];
  754. Si446xCmd.GET_CHIP_STATUS.CHIP_STATUS = Pro2Cmd[1];
  755. Si446xCmd.GET_CHIP_STATUS.CMD_ERR_STATUS = Pro2Cmd[2];
  756. }
  757. /*!
  758. * Resets the RX/TX FIFO. Does not read back anything from TX/RX FIFO
  759. *
  760. */
  761. void si446x_fifo_info_fast_reset(uint8_t FIFO)
  762. {
  763. Pro2Cmd[0] = SI446X_CMD_ID_FIFO_INFO;
  764. Pro2Cmd[1] = FIFO;
  765. radio_comm_SendCmd( 2, Pro2Cmd );
  766. }
  767. /*!
  768. * Reads RX/TX FIFO count space. Does NOT reset RX/TX FIFO
  769. *
  770. */
  771. void si446x_fifo_info_fast_read(void)
  772. {
  773. Pro2Cmd[0] = SI446X_CMD_ID_FIFO_INFO;
  774. radio_comm_SendCmdGetResp( 1,
  775. Pro2Cmd,
  776. SI446X_CMD_REPLY_COUNT_FIFO_INFO,
  777. Pro2Cmd );
  778. Si446xCmd.FIFO_INFO.RX_FIFO_COUNT = Pro2Cmd[0];
  779. Si446xCmd.FIFO_INFO.TX_FIFO_SPACE = Pro2Cmd[1];
  780. }
  781. #endif /* RADIO_DRIVER_FULL_SUPPORT */
  782. #endif /* RADIO_DRIVER_EXTENDED_SUPPORT */