ant_bsc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /**
  2. * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "sdk_common.h"
  41. #if NRF_MODULE_ENABLED(ANT_BSC)
  42. #include "nrf_assert.h"
  43. #include "nrf_error.h"
  44. #include "app_error.h"
  45. #include "ant_interface.h"
  46. #include "ant_bsc.h"
  47. #include "ant_bsc_utils.h"
  48. #define NRF_LOG_MODULE_NAME ant_bsc
  49. #if ANT_BSC_LOG_ENABLED
  50. #define NRF_LOG_LEVEL ANT_BSC_LOG_LEVEL
  51. #define NRF_LOG_INFO_COLOR ANT_BSC_INFO_COLOR
  52. #else // ANT_BSC_LOG_ENABLED
  53. #define NRF_LOG_LEVEL 0
  54. #endif // ANT_BSC_LOG_ENABLED
  55. #include "nrf_log.h"
  56. NRF_LOG_MODULE_REGISTER();
  57. #define MAIN_DATA_INTERVAL 4 /**< The number of background data pages sent between main data pages.*/
  58. #define BACKGROUND_DATA_INTERVAL 64 /**< The number of main data pages sent between background data page.
  59. Background data page is sent every 65th message. */
  60. #define TX_TOGGLE_DIVISOR 4 /**< The number of messages between changing state of toggle bit. */
  61. /**@brief BSC message data layout structure. */
  62. typedef struct
  63. {
  64. ant_bsc_page_t page_number : 7;
  65. uint8_t toggle_bit : 1;
  66. uint8_t page_payload[7];
  67. }ant_bsc_single_message_layout_t;
  68. typedef struct
  69. {
  70. uint8_t page_payload[8];
  71. }ant_bsc_combined_message_layout_t;
  72. typedef union
  73. {
  74. ant_bsc_single_message_layout_t speed_or_cadence;
  75. ant_bsc_combined_message_layout_t combined;
  76. }ant_bsc_message_layout_t;
  77. /**@brief Function for initializing the ANT BSC profile instance.
  78. *
  79. * @param[in] p_profile Pointer to the profile instance.
  80. * @param[in] p_channel_config Pointer to the ANT channel configuration structure.
  81. *
  82. * @retval NRF_SUCCESS If initialization was successful. Otherwise, an error code is returned.
  83. */
  84. static ret_code_t ant_bsc_init(ant_bsc_profile_t * p_profile,
  85. ant_channel_config_t const * p_channel_config)
  86. {
  87. p_profile->channel_number = p_channel_config->channel_number;
  88. p_profile->page_0 = DEFAULT_ANT_BSC_PAGE0();
  89. p_profile->page_1 = DEFAULT_ANT_BSC_PAGE1();
  90. p_profile->page_2 = DEFAULT_ANT_BSC_PAGE2();
  91. p_profile->page_3 = DEFAULT_ANT_BSC_PAGE3();
  92. p_profile->page_4 = DEFAULT_ANT_BSC_PAGE4();
  93. p_profile->page_5 = DEFAULT_ANT_BSC_PAGE5();
  94. p_profile->page_comb_0 = DEFAULT_ANT_BSC_COMBINED_PAGE0();
  95. NRF_LOG_INFO("ANT BSC channel %u init", p_profile->channel_number);
  96. return ant_channel_init(p_channel_config);
  97. }
  98. ret_code_t ant_bsc_disp_init(ant_bsc_profile_t * p_profile,
  99. ant_channel_config_t const * p_channel_config,
  100. ant_bsc_disp_config_t const * p_disp_config)
  101. {
  102. ASSERT(p_profile != NULL);
  103. ASSERT(p_channel_config != NULL);
  104. ASSERT(p_disp_config->evt_handler != NULL);
  105. p_profile->evt_handler = p_disp_config->evt_handler;
  106. p_profile->_cb.p_disp_cb = p_disp_config->p_cb;
  107. p_profile->_cb.p_disp_cb->device_type = p_channel_config->device_type;
  108. return ant_bsc_init(p_profile, p_channel_config);
  109. }
  110. ret_code_t ant_bsc_sens_init(ant_bsc_profile_t * p_profile,
  111. ant_channel_config_t const * p_channel_config,
  112. ant_bsc_sens_config_t const * p_sens_config)
  113. {
  114. ASSERT(p_profile != NULL);
  115. ASSERT(p_channel_config != NULL);
  116. ASSERT(p_sens_config != NULL);
  117. ASSERT(p_sens_config->p_cb != NULL);
  118. ASSERT(p_sens_config->evt_handler != NULL);
  119. ASSERT((p_sens_config->main_page_number == ANT_BSC_PAGE_0)
  120. || (p_sens_config->main_page_number == ANT_BSC_PAGE_5)
  121. || (p_sens_config->main_page_number == ANT_BSC_COMB_PAGE_0));
  122. p_profile->evt_handler = p_sens_config->evt_handler;
  123. p_profile->_cb.p_sens_cb = p_sens_config->p_cb;
  124. p_profile->_cb.p_sens_cb->page_1_present = p_sens_config->page_1_present;
  125. p_profile->_cb.p_sens_cb->page_4_present = p_sens_config->page_4_present;
  126. p_profile->_cb.p_sens_cb->main_page_number = p_sens_config->main_page_number;
  127. p_profile->_cb.p_sens_cb->bkgd_page_number =
  128. p_sens_config->page_1_present ? ANT_BSC_PAGE_1 : ANT_BSC_PAGE_2;
  129. p_profile->_cb.p_sens_cb->message_counter = 0;
  130. p_profile->_cb.p_sens_cb->toggle_bit = true;
  131. p_profile->_cb.p_sens_cb->device_type = p_channel_config->device_type; /* Device type is set up in channel config */
  132. return ant_bsc_init(p_profile, p_channel_config);
  133. }
  134. /**@brief Function for setting the next background page number.
  135. *
  136. * @param[in] p_profile Pointer to the profile instance.
  137. *
  138. */
  139. __STATIC_INLINE void next_bkgd_page_number_set(ant_bsc_profile_t * p_profile)
  140. {
  141. /* Determine the last background page*/
  142. ant_bsc_page_t last_bkgd_page =
  143. p_profile->_cb.p_sens_cb->page_4_present ? ANT_BSC_PAGE_4 : ANT_BSC_PAGE_3;
  144. /* Switch the background page according to user settings */
  145. ++(p_profile->_cb.p_sens_cb->bkgd_page_number);
  146. if (p_profile->_cb.p_sens_cb->bkgd_page_number > last_bkgd_page)
  147. {
  148. p_profile->_cb.p_sens_cb->bkgd_page_number =
  149. p_profile->_cb.p_sens_cb->page_1_present ? ANT_BSC_PAGE_1 : ANT_BSC_PAGE_2;
  150. }
  151. }
  152. /**@brief Function for getting next page number to send.
  153. *
  154. * @param[in] p_profile Pointer to the profile instance.
  155. *
  156. * @return Next page number.
  157. */
  158. static ant_bsc_page_t next_page_number_get(ant_bsc_profile_t * p_profile)
  159. {
  160. ant_bsc_page_t page_number;
  161. /* This is a single speed or cadence sensor - switch data page */
  162. if (p_profile->_cb.p_sens_cb->message_counter < (BACKGROUND_DATA_INTERVAL))
  163. {
  164. /* Return main page */
  165. page_number = p_profile->_cb.p_sens_cb->main_page_number;
  166. }
  167. else
  168. {
  169. /* Return background page */
  170. page_number = p_profile->_cb.p_sens_cb->bkgd_page_number;
  171. }
  172. /* Set page toggle bit */
  173. if ((p_profile->_cb.p_sens_cb->message_counter % TX_TOGGLE_DIVISOR) == 0)
  174. {
  175. p_profile->_cb.p_sens_cb->toggle_bit ^= 1;
  176. }
  177. /* Update message counter, wrap when counter equals 64 + 4 */
  178. ++(p_profile->_cb.p_sens_cb->message_counter);
  179. if (p_profile->_cb.p_sens_cb->message_counter == (BACKGROUND_DATA_INTERVAL + MAIN_DATA_INTERVAL))
  180. {
  181. p_profile->_cb.p_sens_cb->message_counter = 0;
  182. /* Set new background data page number */
  183. next_bkgd_page_number_set(p_profile);
  184. }
  185. return page_number;
  186. }
  187. /**@brief Function for encoding BSC message.
  188. *
  189. * @param[in] p_profile Pointer to the profile instance.
  190. * @param[out] p_message_payload Pointer to the message payload structure.
  191. *
  192. * @note Assume to be called each time when Tx window will occur.
  193. */
  194. static void sens_message_encode(ant_bsc_profile_t * p_profile, uint8_t * p_message_payload)
  195. {
  196. ant_bsc_message_layout_t * p_bsc_message_payload = (ant_bsc_message_layout_t *)p_message_payload;
  197. ant_bsc_evt_t bsc_sens_event;
  198. if (p_profile->_cb.p_sens_cb->device_type == BSC_COMBINED_DEVICE_TYPE)
  199. {
  200. NRF_LOG_INFO("BSC TX Page: \"Combined Speed & Cadence Page\"");
  201. ant_bsc_combined_page_0_encode(p_bsc_message_payload->combined.page_payload,
  202. &(p_profile->page_comb_0));
  203. bsc_sens_event = (ant_bsc_evt_t) ANT_BSC_COMB_PAGE_0_UPDATED;
  204. }
  205. else
  206. {
  207. p_bsc_message_payload->speed_or_cadence.page_number = next_page_number_get(p_profile);
  208. p_bsc_message_payload->speed_or_cadence.toggle_bit = p_profile->_cb.p_sens_cb->toggle_bit;
  209. NRF_LOG_INFO("BSC TX Page number: %u",
  210. p_bsc_message_payload->speed_or_cadence.page_number);
  211. ant_bsc_page_0_encode(p_bsc_message_payload->speed_or_cadence.page_payload,
  212. &(p_profile->page_0));
  213. bsc_sens_event = (ant_bsc_evt_t) p_bsc_message_payload->speed_or_cadence.page_number;
  214. switch (p_bsc_message_payload->speed_or_cadence.page_number)
  215. {
  216. case ANT_BSC_PAGE_0:
  217. // No implementation needed
  218. break;
  219. case ANT_BSC_PAGE_1:
  220. ant_bsc_page_1_encode(p_bsc_message_payload->speed_or_cadence.page_payload,
  221. &(p_profile->page_1));
  222. break;
  223. case ANT_BSC_PAGE_2:
  224. ant_bsc_page_2_encode(p_bsc_message_payload->speed_or_cadence.page_payload,
  225. &(p_profile->page_2));
  226. break;
  227. case ANT_BSC_PAGE_3:
  228. ant_bsc_page_3_encode(p_bsc_message_payload->speed_or_cadence.page_payload,
  229. &(p_profile->page_3));
  230. break;
  231. case ANT_BSC_PAGE_4:
  232. ant_bsc_page_4_encode(p_bsc_message_payload->speed_or_cadence.page_payload,
  233. &(p_profile->page_4));
  234. break;
  235. case ANT_BSC_PAGE_5:
  236. ant_bsc_page_5_encode(p_bsc_message_payload->speed_or_cadence.page_payload,
  237. &(p_profile->page_5));
  238. break;
  239. default:
  240. // No implementation needed
  241. break;
  242. }
  243. }
  244. p_profile->evt_handler(p_profile, bsc_sens_event);
  245. }
  246. /**@brief Function for setting payload for ANT message and sending it.
  247. *
  248. * @param[in] p_profile Pointer to the profile instance.
  249. */
  250. static void ant_message_send(ant_bsc_profile_t * p_profile)
  251. {
  252. uint8_t p_message_payload[ANT_STANDARD_DATA_PAYLOAD_SIZE];
  253. uint32_t err_code;
  254. sens_message_encode(p_profile, p_message_payload);
  255. err_code = sd_ant_broadcast_message_tx(p_profile->channel_number,
  256. sizeof(p_message_payload),
  257. p_message_payload);
  258. APP_ERROR_CHECK(err_code);
  259. }
  260. void ant_bsc_sens_evt_handler(ant_evt_t * p_ant_evt, void * p_context)
  261. {
  262. ant_bsc_profile_t * p_profile = (ant_bsc_profile_t *)p_context;
  263. if (p_ant_evt->channel == p_profile->channel_number)
  264. {
  265. switch (p_ant_evt->event)
  266. {
  267. case EVENT_TX:
  268. ant_message_send(p_profile);
  269. break;
  270. default:
  271. break;
  272. }
  273. }
  274. }
  275. ret_code_t ant_bsc_disp_open(ant_bsc_profile_t * p_profile)
  276. {
  277. ASSERT(p_profile != NULL);
  278. NRF_LOG_INFO("ANT BSC channel %u open", p_profile->channel_number);
  279. return sd_ant_channel_open(p_profile->channel_number);
  280. }
  281. ret_code_t ant_bsc_sens_open(ant_bsc_profile_t * p_profile)
  282. {
  283. ASSERT(p_profile != NULL);
  284. // Fill tx buffer for the first frame
  285. ant_message_send(p_profile);
  286. NRF_LOG_INFO("ANT BSC channel %u open", p_profile->channel_number);
  287. return sd_ant_channel_open(p_profile->channel_number);
  288. }
  289. /**@brief Function for decoding BSC message.
  290. *
  291. * @param[in,out] p_profile Pointer to the profile instance.
  292. * @param[in] p_message_payload Pointer to the message payload structure.
  293. *
  294. * @note Assume to be call each time when Rx window will occur.
  295. */
  296. static void disp_message_decode(ant_bsc_profile_t * p_profile, uint8_t * p_message_payload)
  297. {
  298. const ant_bsc_message_layout_t * p_bsc_message_payload =
  299. (ant_bsc_message_layout_t *)p_message_payload;
  300. ant_bsc_evt_t bsc_disp_event;
  301. if (p_profile->_cb.p_disp_cb->device_type == BSC_COMBINED_DEVICE_TYPE)
  302. {
  303. NRF_LOG_INFO("BSC RX Page Number: \"Combined Speed & Cadence Page\"");
  304. ant_bsc_combined_page_0_decode(p_bsc_message_payload->combined.page_payload,
  305. &(p_profile->page_comb_0));
  306. bsc_disp_event = (ant_bsc_evt_t) ANT_BSC_COMB_PAGE_0_UPDATED;
  307. }
  308. else
  309. {
  310. NRF_LOG_INFO("BSC RX Page Number: %u",
  311. p_bsc_message_payload->speed_or_cadence.page_number);
  312. ant_bsc_page_0_decode(p_bsc_message_payload->speed_or_cadence.page_payload,
  313. &(p_profile->page_0)); // Page 0 is present in each message
  314. bsc_disp_event = (ant_bsc_evt_t) p_bsc_message_payload->speed_or_cadence.page_number;
  315. switch (p_bsc_message_payload->speed_or_cadence.page_number)
  316. {
  317. case ANT_BSC_PAGE_0:
  318. // No implementation needed
  319. break;
  320. case ANT_BSC_PAGE_1:
  321. ant_bsc_page_1_decode(p_bsc_message_payload->speed_or_cadence.page_payload,
  322. &(p_profile->page_1));
  323. break;
  324. case ANT_BSC_PAGE_2:
  325. ant_bsc_page_2_decode(p_bsc_message_payload->speed_or_cadence.page_payload,
  326. &(p_profile->page_2));
  327. break;
  328. case ANT_BSC_PAGE_3:
  329. ant_bsc_page_3_decode(p_bsc_message_payload->speed_or_cadence.page_payload,
  330. &(p_profile->page_3));
  331. break;
  332. case ANT_BSC_PAGE_4:
  333. ant_bsc_page_4_decode(p_bsc_message_payload->speed_or_cadence.page_payload,
  334. &(p_profile->page_4));
  335. break;
  336. case ANT_BSC_PAGE_5:
  337. ant_bsc_page_5_decode(p_bsc_message_payload->speed_or_cadence.page_payload,
  338. &(p_profile->page_5));
  339. break;
  340. default:
  341. // No implementation needed
  342. break;
  343. }
  344. }
  345. p_profile->evt_handler(p_profile, bsc_disp_event);
  346. }
  347. void ant_bsc_disp_evt_handler(ant_evt_t * p_ant_evt, void * p_context)
  348. {
  349. ant_bsc_profile_t * p_profile = (ant_bsc_profile_t *)p_context;
  350. if (p_ant_evt->channel == p_profile->channel_number)
  351. {
  352. switch (p_ant_evt->event)
  353. {
  354. case EVENT_RX:
  355. if (p_ant_evt->message.ANT_MESSAGE_ucMesgID == MESG_BROADCAST_DATA_ID
  356. || p_ant_evt->message.ANT_MESSAGE_ucMesgID == MESG_ACKNOWLEDGED_DATA_ID
  357. || p_ant_evt->message.ANT_MESSAGE_ucMesgID == MESG_BURST_DATA_ID)
  358. {
  359. disp_message_decode(p_profile, p_ant_evt->message.ANT_MESSAGE_aucPayload);
  360. }
  361. break;
  362. default:
  363. break;
  364. }
  365. }
  366. }
  367. #endif // NRF_MODULE_ENABLED(ANT_BSC)