Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

1484 lines
42KB

  1. /* USB EHCI Host for Teensy 3.6
  2. * Copyright 2017 Michael McElligott
  3. * Copyright 2017 Paul Stoffregen (paul@pjrc.com)
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the
  7. * "Software"), to deal in the Software without restriction, including
  8. * without limitation the rights to use, copy, modify, merge, publish,
  9. * distribute, sublicense, and/or sell copies of the Software, and to
  10. * permit persons to whom the Software is furnished to do so, subject to
  11. * the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included
  14. * in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  19. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  20. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  22. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. // https://forum.pjrc.com/threads/43110
  25. // https://github.com/PaulStoffregen/antplus
  26. #include <Arduino.h>
  27. #include "USBHost_t36.h" // Read this header first for key info
  28. #include "antplusdefs.h" // Ant internal defines, not for Arduino sketches
  29. #define ANTPLUS_VID 0x0FCF
  30. #define ANTPLUS_2_PID 0x1008
  31. #define ANTPLUS_M_PID 0x1009
  32. #define print USBHost::print_
  33. #define println USBHost::println_
  34. #define ENABLE_SERIALPRINTF 1
  35. #if ENABLE_SERIALPRINTF
  36. #undef printf
  37. #define printf(...) Serial.printf(__VA_ARGS__); Serial.write("\r\n")
  38. #else
  39. #undef printf
  40. #define printf(...)
  41. #endif
  42. void AntPlus::init()
  43. {
  44. contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t));
  45. contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t));
  46. contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t));
  47. driver_ready_for_device(this);
  48. callbackFunc = NULL;
  49. }
  50. bool AntPlus::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
  51. {
  52. if (type != 1) return false;
  53. println("AntPlus claim this=", (uint32_t)this, HEX);
  54. if (dev->idVendor != ANTPLUS_VID) return false;
  55. if (dev->idProduct != ANTPLUS_2_PID && dev->idProduct != ANTPLUS_M_PID) return false;
  56. println("found AntPlus, pid=", dev->idProduct, HEX);
  57. rxpipe = txpipe = NULL;
  58. const uint8_t *p = descriptors;
  59. const uint8_t *end = p + len;
  60. int descriptorLength = p[0];
  61. int descriptorType = p[1];
  62. if (descriptorLength < 9 || descriptorType != 4) return false;
  63. p += descriptorLength;
  64. while (p < end) {
  65. descriptorLength = p[0];
  66. if (p + descriptorLength > end) return false; // reject if beyond end of data
  67. descriptorType = p[1];
  68. if (descriptorType == 5) { // 5 = endpoint
  69. uint8_t epAddr = p[2];
  70. uint8_t epType = p[3] & 0x03;
  71. uint16_t epSize = p[4] | (p[5] << 8);
  72. if (epType == 2 && (epAddr & 0xF0) == 0x00) { // Bulk OUT
  73. txpipe = new_Pipe(dev, 2, epAddr, 0, epSize);
  74. } else if (epType == 2 && (epAddr & 0xF0) == 0x80) { // Bulk IN
  75. rxpipe = new_Pipe(dev, 2, epAddr & 0x0F, 1, epSize);
  76. }
  77. }
  78. p += descriptorLength;
  79. }
  80. if (rxpipe && txpipe) {
  81. rxpipe->callback_function = rx_callback;
  82. txpipe->callback_function = tx_callback;
  83. txhead = 0;
  84. txtail = 0;
  85. //rxhead = 0;
  86. //rxtail = 0;
  87. memset(txbuffer, 0, sizeof(txbuffer));
  88. first_update = true;
  89. txready = true;
  90. updatetimer.start(500000);
  91. queue_Data_Transfer(rxpipe, rxpacket, 64, this);
  92. rxlen = 0;
  93. do_polling = false;
  94. return true;
  95. }
  96. return false;
  97. }
  98. void AntPlus::disconnect()
  99. {
  100. updatetimer.stop();
  101. //txtimer.stop();
  102. }
  103. void AntPlus::rx_callback(const Transfer_t *transfer)
  104. {
  105. if (!transfer->driver) return;
  106. ((AntPlus *)(transfer->driver))->rx_data(transfer);
  107. }
  108. void AntPlus::tx_callback(const Transfer_t *transfer)
  109. {
  110. if (!transfer->driver) return;
  111. ((AntPlus *)(transfer->driver))->tx_data(transfer);
  112. }
  113. void AntPlus::rx_data(const Transfer_t *transfer)
  114. {
  115. uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);
  116. //println("ant rx, len=", len);
  117. //print_hexbytes(transfer->buffer, len);
  118. if (len < 1 || len > 64) {
  119. queue_Data_Transfer(rxpipe, rxpacket, 64, this);
  120. rxlen = 0;
  121. } else {
  122. rxlen = len; // signal arrival of data to Task()
  123. // TODO: should someday use EventResponder to call from yield()
  124. }
  125. }
  126. void AntPlus::tx_data(const Transfer_t *transfer)
  127. {
  128. uint8_t *p = (uint8_t *)transfer->buffer;
  129. //print("tx_data, len=", *(p-1));
  130. //print(", tail=", (p-1) - txbuffer);
  131. //println(", tail=", txtail);
  132. uint32_t tail = txtail;
  133. tail += *(p-1) + 1;
  134. txtail = tail;
  135. //println("new tail=", tail);
  136. txready = true;
  137. transmit();
  138. //txtimer.start(8000);
  139. // adjust tail...
  140. // start timer if more data to send
  141. }
  142. size_t AntPlus::write(const void *data, const size_t size)
  143. {
  144. //print("write ", size);
  145. //print(" bytes: ");
  146. //print_hexbytes(data, size);
  147. if (size > 64) return 0;
  148. uint32_t head = txhead;
  149. if (++head >= sizeof(txbuffer)) head = 0;
  150. uint32_t remain = sizeof(txbuffer) - head;
  151. if (remain < size + 1) {
  152. // not enough space at end of buffer
  153. txbuffer[head] = 0xFF;
  154. head = 0;
  155. }
  156. uint32_t avail;
  157. do {
  158. uint32_t tail = txtail;
  159. if (head > tail) {
  160. avail = sizeof(txbuffer) - head + tail;
  161. } else {
  162. avail = tail - head;
  163. }
  164. } while (avail < size + 1); // wait for space in buffer
  165. txbuffer[head] = size;
  166. memcpy(txbuffer + head + 1, data, size);
  167. txhead = head + size;
  168. //print("head=", txhead);
  169. //println(", tail=", txtail);
  170. //print_hexbytes(txbuffer, 60);
  171. NVIC_DISABLE_IRQ(IRQ_USBHS);
  172. transmit();
  173. NVIC_ENABLE_IRQ(IRQ_USBHS);
  174. return size;
  175. }
  176. void AntPlus::transmit()
  177. {
  178. if (!txready) return;
  179. uint32_t head = txhead;
  180. uint32_t tail = txtail;
  181. if (head == tail) {
  182. //println("no data to transmit");
  183. return; // no data to transit
  184. }
  185. if (++tail >= sizeof(txbuffer)) tail = 0;
  186. uint32_t size = txbuffer[tail];
  187. //print("tail=", tail);
  188. //println(", tx size=", size);
  189. if (size == 0xFF) {
  190. txtail = 0;
  191. tail = 0;
  192. size = txbuffer[0];
  193. //println("tx size=", size);
  194. }
  195. //txtail = tail + size;
  196. queue_Data_Transfer(txpipe, txbuffer + tail + 1, size, this);
  197. //txtimer.start(8000);
  198. txready = false;
  199. }
  200. void AntPlus::timer_event(USBDriverTimer *whichTimer)
  201. {
  202. if (whichTimer == &updatetimer) {
  203. updatetimer.start(250000);
  204. if (first_update) {
  205. ResetSystem();
  206. first_update = false;
  207. } else {
  208. do_polling = true;
  209. }
  210. //println("ant update timer");
  211. }
  212. /* else if (whichTimer == &txtimer) {
  213. println("ant tx timer");
  214. //txtimer.stop(); // TODO: why is this needed?
  215. txready = true;
  216. transmit();
  217. } */
  218. }
  219. void AntPlus::Task()
  220. {
  221. uint32_t len = rxlen;
  222. if (len) {
  223. handleMessages(rxpacket, len);
  224. NVIC_DISABLE_IRQ(IRQ_USBHS);
  225. queue_Data_Transfer(rxpipe, rxpacket, 64, this);
  226. rxlen = 0;
  227. NVIC_ENABLE_IRQ(IRQ_USBHS);
  228. }
  229. if (do_polling) {
  230. do_polling = false;
  231. for (int i = 0; i < PROFILE_TOTAL; i++) {
  232. TDCONFIG *cfg = &ant.dcfg[i];
  233. if (!(cfg->flags.profileValid)) continue;
  234. //printf("#### %i %i: %i %i %i ####", i, cfg->channel,
  235. // cfg->flags.channelStatus, cfg->flags.keyAccepted,
  236. // cfg->flags.chanIdOnce);
  237. if (cfg->flags.channelStatus) {
  238. RequestMessage(cfg->channel, MESG_CHANNEL_STATUS_ID);
  239. } else {
  240. AssignChannel(cfg->channel, cfg->channelType, cfg->networkNumber);
  241. RequestMessage(cfg->channel, MESG_CHANNEL_STATUS_ID);
  242. if (!cfg->flags.keyAccepted && !cfg->flags.chanIdOnce) {
  243. SetNetworkKey(cfg->networkNumber, getAntKey(ant.key));
  244. }
  245. }
  246. }
  247. }
  248. }
  249. enum _akeys {
  250. KEY_ANTSPORT,
  251. KEY_SUUNTO,
  252. KEY_GARMIN,
  253. KEY_ANTPLUS,
  254. KEY_TOTAL,
  255. KEY_DEFAULT = KEY_ANTSPORT
  256. };
  257. static const uint8_t antkeys[KEY_TOTAL][8] = {
  258. {0xB9,0xA5,0x21,0xFB,0xBD,0x72,0xC3,0x45}, // Ant+ sport key KEY_ANTSPORT
  259. {0xB9,0xAD,0x32,0x28,0x75,0x7E,0xC7,0x4D}, // Suunto KEY_SUUNTO
  260. {0xA8,0xA4,0x23,0xB9,0xF5,0x5E,0x63,0xC1}, // Garmin KEY_GARMIN
  261. {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // Ant+ key KEY_ANTPLUS (add your key here)
  262. //{0xFD,0x38,0xBE,0xA6,0x40,0x5D,0x26,0x99}
  263. };
  264. uint8_t AntPlus::calcMsgChecksum(const uint8_t *buffer, const uint8_t len)
  265. {
  266. uint8_t checksum = 0x00;
  267. for (uint8_t i = 0; i < len; i++)
  268. checksum ^= buffer[i];
  269. return checksum;
  270. }
  271. uint8_t * AntPlus::findStreamSync(uint8_t *stream, const size_t rlen, int *pos)
  272. {
  273. // find and sync with input stream
  274. *pos = 0;
  275. while (*pos < (int)rlen /*&& *pos < INPUTBUFFERSIZE-3*/){
  276. if (stream[*pos] == MESG_TX_SYNC)
  277. return stream + *pos;
  278. (*pos)++;
  279. }
  280. return NULL;
  281. }
  282. int AntPlus::msgCheckIntegrity(uint8_t *stream, const int len)
  283. {
  284. // min message length is 5
  285. if (len < 5) return 0;
  286. int crc = stream[STREAM_SYNC];
  287. crc ^= stream[STREAM_LENGTH];
  288. crc ^= stream[STREAM_MESSAGE];
  289. int mlen = 0;
  290. do{
  291. crc ^= stream[STREAM_DATA+mlen];
  292. } while (++mlen < stream[STREAM_LENGTH]);
  293. //printf("crc == 0x%X: msg crc = 0x%X\n", crc, stream[stream[STREAM_LENGTH] + 3]);
  294. return (crc == stream[stream[STREAM_LENGTH] + 3]);
  295. }
  296. int AntPlus::msgGetLength (uint8_t *stream)
  297. {
  298. // eg; {A4 1 6F 20 EA} = {SYNC DATALEN MSGID DATA CRC}
  299. return stream[STREAM_LENGTH] + 4;
  300. }
  301. int AntPlus::handleMessages(uint8_t *buffer, int tBytes)
  302. {
  303. int syncOffset = 0;
  304. //uint8_t buffer[ANTPLUS_MAXPACKETSIZE];
  305. uint8_t *stream = buffer;
  306. //int tBytes = antplus_read(ant, buffer, ant->ioVar.readBufferSize);
  307. //if (tBytes <= 0) return tBytes;
  308. //int tBytes = ANTPLUS_MAXPACKETSIZE;
  309. while (tBytes > 0){
  310. stream = findStreamSync(stream, tBytes, &syncOffset);
  311. if (stream == NULL){
  312. //printf("stream sync not found {size:%i}\n", tBytes);
  313. return 0;
  314. }
  315. tBytes -= syncOffset;
  316. if (!msgCheckIntegrity(stream, tBytes)){
  317. //printf("stream integrity failed {size:%i}\n", tBytes);
  318. return 0;
  319. }
  320. //we have a valid message
  321. //if (dispatchMessage(stream, tBytes) == -1){
  322. //printf("quiting..\n");
  323. //return 0;
  324. //}
  325. message_event(stream[STREAM_CHANNEL], stream[STREAM_MESSAGE],
  326. &stream[STREAM_DATA], (size_t)stream[STREAM_LENGTH]);
  327. int len = msgGetLength(stream);
  328. stream += len;
  329. tBytes -= len;
  330. }
  331. return 1;
  332. }
  333. // TODO: replace this with multiple Arduino style OnXYZ callbacks
  334. void AntPlus::setCallbackFunc(int (*func)(uint32_t msg, intptr_t *value1, uint32_t value2))
  335. {
  336. callbackFunc = func;
  337. }
  338. // TODO: replace this with multiple Arduino style OnXYZ callbacks
  339. void AntPlus::sendMessage(uint32_t msg, intptr_t *value1, uint32_t value2)
  340. {
  341. if (callbackFunc) (*callbackFunc)(msg, value1, value2);
  342. }
  343. void AntPlus::sendMessageChannelStatus(TDCONFIG *cfg, const uint32_t channelStatus)
  344. {
  345. cfg->flags.channelStatus = channelStatus;
  346. if (cfg->flags.channelStatus != cfg->flags.channelStatusOld) {
  347. uint32_t status = cfg->flags.channelStatus&0x0F;
  348. status |= ((cfg->channel&0x0F)<<4);
  349. sendMessage(ANTP_MSG_CHANNELSTATUS, NULL, status);
  350. cfg->flags.channelStatusOld = cfg->flags.channelStatus;
  351. }
  352. }
  353. void AntPlus::message_channel(const int chan, const int eventId,
  354. const uint8_t *payload, const size_t dataLength)
  355. {
  356. //printf(" $ chan event: chan:%i, msgId:0x%.2X, payload:%p, dataLen:%i, uPtr:%p", chan, eventId, payload, (int)dataLength, uPtr);
  357. //dump_hexbytes(payload, dataLength);
  358. TDCONFIG *cfg = &(ant.dcfg[chan]);
  359. switch (eventId){
  360. case EVENT_RX_SEARCH_TIMEOUT:
  361. printf(" $ event RX search timeout");
  362. break;
  363. case EVENT_RX_FAIL:
  364. //printf(" $ event RX fail");
  365. break;
  366. case EVENT_TX:
  367. //printf(" $ event TX");
  368. break;
  369. case EVENT_RX_BROADCAST:
  370. //printf(" $ event RX broadcast ");
  371. if (!cfg->flags.chanIdOnce) {
  372. cfg->flags.chanIdOnce = 1;
  373. RequestMessage(cfg->channel, MESG_CHANNEL_ID_ID);
  374. }
  375. //dump_hexbytes(payload, dataLength);
  376. dispatchPayload(cfg, payload, dataLength);
  377. break;
  378. }
  379. }
  380. void AntPlus::message_response(const int chan, const int msgId,
  381. const uint8_t *payload, const size_t dataLength)
  382. {
  383. //printf(" # response event: msgId:0x%.2X, payload:%p, dataLen:%i, uPtr:%p", msgId, payload, dataLength, uPtr);
  384. TDCONFIG *cfg = (TDCONFIG*)&(ant.dcfg[chan]);
  385. switch (msgId){
  386. case MESG_EVENT_ID:
  387. //printf(" * event");
  388. message_channel(chan, payload[STREAM_EVENT_EVENTID], payload, dataLength);
  389. break;
  390. case MESG_NETWORK_KEY_ID:
  391. printf("[%i] * network key accepted", chan);
  392. cfg->flags.keyAccepted = 1;
  393. if (cfg->transType == ANT_TRANSMISSION_MASTER)
  394. AssignChannel(cfg->channel, PARAMETER_TX_NOT_RX, cfg->networkNumber);
  395. else
  396. AssignChannel(cfg->channel, cfg->channelType, cfg->networkNumber);
  397. break;
  398. case MESG_ASSIGN_CHANNEL_ID:
  399. printf("[%i] * channel assign accepted", chan);
  400. SetChannelPeriod(cfg->channel, cfg->channelPeriod);
  401. break;
  402. case MESG_CHANNEL_MESG_PERIOD_ID:
  403. printf("[%i] * channel mesg period accepted", chan);
  404. SetChannelSearchTimeout(cfg->channel, cfg->searchTimeout);
  405. break;
  406. case MESG_CHANNEL_SEARCH_TIMEOUT_ID:
  407. printf("[%i] * search timeout period accepted", chan);
  408. SetChannelRFFreq(cfg->channel, cfg->RFFreq);
  409. break;
  410. case MESG_CHANNEL_RADIO_FREQ_ID:
  411. printf("[%i] * radio freq accepted", chan);
  412. SetSearchWaveform(cfg->channel, cfg->searchWaveform);
  413. break;
  414. case MESG_SEARCH_WAVEFORM_ID:
  415. printf("[%i] * search waveform accepted", chan);
  416. SetChannelId(cfg->channel, cfg->deviceNumber, cfg->deviceType, cfg->transType);
  417. break;
  418. case MESG_CHANNEL_ID_ID:
  419. printf("[%i] * set channel id accepted", chan);
  420. OpenChannel(cfg->channel);
  421. break;
  422. case MESG_OPEN_CHANNEL_ID:
  423. printf("[%i] * open channel accepted", chan);
  424. //cfg->flags.channelStatus = 1;
  425. RequestMessage(cfg->channel, MESG_CHANNEL_STATUS_ID);
  426. RequestMessage(cfg->channel, MESG_CAPABILITIES_ID);
  427. RequestMessage(cfg->channel, MESG_VERSION_ID);
  428. break;
  429. case MESG_UNASSIGN_CHANNEL_ID:
  430. printf("[%i] * channel Unassigned", chan);
  431. break;
  432. case MESG_CLOSE_CHANNEL_ID:
  433. printf("[%i] * channel CLOSED", chan);
  434. cfg->flags.keyAccepted = 0;
  435. sendMessageChannelStatus(cfg, ANT_CHANNEL_STATUS_UNASSIGNED);
  436. break;
  437. case CHANNEL_IN_WRONG_STATE:
  438. printf("[%i] * channel in wrong state", chan);
  439. break;
  440. case CHANNEL_NOT_OPENED:
  441. printf("[%i] * channel not opened", chan);
  442. break;
  443. case CHANNEL_ID_NOT_SET: //??
  444. printf("[%i] * channel ID not set", chan);
  445. break;
  446. case CLOSE_ALL_CHANNELS: // Start RX Scan mode
  447. printf("[%i] * close all channels", chan);
  448. break;
  449. case TRANSFER_IN_PROGRESS: // TO ack message ID
  450. printf("[%i] * tranfer in progress", chan);
  451. break;
  452. case TRANSFER_SEQUENCE_NUMBER_ERROR:
  453. printf("[%i] * transfer sequence number error", chan);
  454. break;
  455. case TRANSFER_IN_ERROR:
  456. printf("[%i] * transfer in error", chan);
  457. break;
  458. case INVALID_MESSAGE:
  459. printf("[%i] * invalid message", chan);
  460. break;
  461. case INVALID_NETWORK_NUMBER:
  462. printf("[%i] * invalid network number", chan);
  463. break;
  464. case INVALID_LIST_ID:
  465. printf("[%i] * invalid list ID", chan);
  466. break;
  467. case INVALID_SCAN_TX_CHANNEL:
  468. printf("[%i] * invalid Scanning transmit channel", chan);
  469. break;
  470. case INVALID_PARAMETER_PROVIDED:
  471. printf("[%i] * invalid parameter provided", chan);
  472. break;
  473. case EVENT_QUE_OVERFLOW:
  474. printf("[%i] * queue overflow", chan);
  475. break;
  476. default:
  477. printf("[i] #### unhandled response id %i", chan, msgId);
  478. ;
  479. };
  480. }
  481. void AntPlus::message_event(const int channel, const int msgId,
  482. const uint8_t *payload, const size_t dataLength)
  483. {
  484. //printf(" @ msg event cb: Chan:%i, Id:0x%.2X, payload:%p, len:%i, ptr:%p", channel, msgId, payload, (int)dataLength, uPtr);
  485. //dump_hexbytes(payload, dataLength);
  486. uint8_t chan = 0;
  487. if (channel >= 0 && channel < PROFILE_TOTAL) chan = channel;
  488. switch(msgId) {
  489. case MESG_BROADCAST_DATA_ID:
  490. //printf(" @ broadcast data \n");
  491. //dumpPayload(payload, dataLength);
  492. message_channel(chan, EVENT_RX_BROADCAST, payload, dataLength);
  493. break;
  494. case MESG_STARTUP_MESG_ID:
  495. // reason == ANT_STARTUP_RESET_xxxx
  496. //printf(" @ start up mesg reason: 0x%X", payload[STREAM_STARTUP_REASON]);
  497. //TDCONFIG *cfg = &(ant.dcfg[0]);
  498. //SetNetworkKey(cfg->networkNumber, getAntKey(cfg->keyIdx));
  499. SetNetworkKey(ant.dcfg[0].networkNumber, getAntKey(ant.key));
  500. break;
  501. case MESG_RESPONSE_EVENT_ID:
  502. message_response(payload[STREAM_EVENT_CHANNEL_ID],
  503. payload[STREAM_EVENT_RESPONSE_ID], payload, dataLength);
  504. break;
  505. case MESG_CHANNEL_STATUS_ID:
  506. //printf(" @ channel status for channel %i is %i",
  507. // payload[STREAM_CHANNEL_ID], payload[STREAM_CHANNEL_STATUS]);
  508. //TDCONFIG *cfg = (TDCONFIG*)&ant->dcfg[payload[STREAM_CHANNEL_ID]];
  509. sendMessageChannelStatus(&(ant.dcfg[payload[STREAM_CHANNEL_ID]]),
  510. payload[STREAM_CHANNELSTATUS_STATUS] & ANT_CHANNEL_STATUS_MASK);
  511. //if (cfg->flags.channelStatus != STATUS_TRACKING_CHANNEL)
  512. // printf("channel %i status: %s", payload[STREAM_CHANNEL_ID],
  513. // channelStatusStr[cfg->flags.channelStatus]);
  514. break;
  515. case MESG_CAPABILITIES_ID:
  516. //printf(" @ capabilities:");
  517. //printf(" Max ANT Channels: %i",payload[STREAM_CAP_MAXCHANNELS]);
  518. //printf(" Max ANT Networks: %i",payload[STREAM_CAP_MAXNETWORKS]);
  519. //printf(" Std. option: 0x%X",payload[STREAM_CAP_STDOPTIONS]);
  520. //printf(" Advanced: 0x%X",payload[STREAM_CAP_ADVANCED]);
  521. //printf(" Advanced2: 0x%X",payload[STREAM_CAP_ADVANCED2]);
  522. break;
  523. case MESG_CHANNEL_ID_ID:
  524. //TDCONFIG *cfg = (TDCONFIG*)&ant->dcfg[chan];
  525. ant.dcfg[chan].dev.deviceId = payload[STREAM_CHANNELID_DEVNO_LO] | (payload[STREAM_CHANNELID_DEVNO_HI] << 8);
  526. ant.dcfg[chan].dev.deviceType = payload[STREAM_CHANNELID_DEVTYPE];
  527. ant.dcfg[chan].dev.transType = payload[STREAM_CHANNELID_TRANTYPE];
  528. //printf(" @ CHANNEL ID: channel %i, deviceId:%i, deviceType:%i, transType:%i)", chan, cfg->dev.deviceId, cfg->dev.deviceType, cfg->dev.transType);
  529. sendMessage(ANTP_MSG_DEVICEID, (intptr_t *)&(ant.dcfg[chan].dev), chan);
  530. #if 0
  531. if (cfg->dev.scidDeviceType != cfg->deviceType){
  532. printf(" @ CHANNEL ID: this is not the device we're looking for");
  533. printf(" @ CHANNEL ID: expecting 0x%X but found 0x%X", cfg->deviceType, cfg->dev.scidDeviceType);
  534. //CloseChannel(cfg->channel);
  535. return;
  536. }
  537. #endif
  538. break;
  539. case MESG_VERSION_ID:
  540. //printf(" @ version: '%s'", (char*)&payload[STREAM_VERSION_STRING]);
  541. break;
  542. };
  543. }
  544. int AntPlus::ResetSystem()
  545. {
  546. //println("libantplus_ResetSystem");
  547. uint8_t msg[5];
  548. msg[0] = MESG_TX_SYNC; // sync
  549. msg[1] = 1; // length
  550. msg[2] = MESG_SYSTEM_RESET_ID; // msg id
  551. msg[3] = 0; // nop
  552. msg[4] = calcMsgChecksum(msg, 4);
  553. return write(msg, 5);
  554. }
  555. int AntPlus::RequestMessage(const int channel, const int message)
  556. {
  557. //println("libantplus_RequestMessage");
  558. uint8_t msg[6];
  559. msg[0] = MESG_TX_SYNC; // sync
  560. msg[1] = 2; // length
  561. msg[2] = MESG_REQUEST_ID; // msg id
  562. msg[3] = (uint8_t)channel;
  563. msg[4] = (uint8_t)message;
  564. msg[5] = calcMsgChecksum(msg, 5);
  565. return write(msg, 6);
  566. }
  567. int AntPlus::SetNetworkKey(const int netNumber, const uint8_t *key)
  568. {
  569. uint8_t msg[13];
  570. msg[0] = MESG_TX_SYNC;
  571. msg[1] = 9;
  572. msg[2] = MESG_NETWORK_KEY_ID;
  573. msg[3] = (uint8_t)netNumber;
  574. msg[4] = key[0];
  575. msg[5] = key[1];
  576. msg[6] = key[2];
  577. msg[7] = key[3];
  578. msg[8] = key[4];
  579. msg[9] = key[5];
  580. msg[10] = key[6];
  581. msg[11] = key[7];
  582. msg[12] = calcMsgChecksum(msg, 12); // xor checksum
  583. return write(msg, 13);
  584. }
  585. int AntPlus::SetChannelSearchTimeout(const int channel, const int searchTimeout)
  586. {
  587. uint8_t msg[6];
  588. msg[0] = MESG_TX_SYNC; // sync
  589. msg[1] = 2; // length
  590. msg[2] = MESG_CHANNEL_SEARCH_TIMEOUT_ID;
  591. msg[3] = (uint8_t)channel;
  592. msg[4] = (uint8_t)searchTimeout;
  593. msg[5] = calcMsgChecksum(msg, 5);
  594. return write(msg, 6);
  595. }
  596. int AntPlus::SetChannelPeriod(const int channel, const int period)
  597. {
  598. uint8_t msg[7];
  599. msg[0] = MESG_TX_SYNC; // sync
  600. msg[1] = 3; // length
  601. msg[2] = MESG_CHANNEL_MESG_PERIOD_ID;
  602. msg[3] = (uint8_t)channel;
  603. msg[4] = (uint8_t)(period & 0xFF);
  604. msg[5] = (uint8_t)(period >> 8);
  605. msg[6] = calcMsgChecksum(msg, 6);
  606. return write(msg, 7);
  607. }
  608. int AntPlus::SetChannelRFFreq(const int channel, const int freq)
  609. {
  610. uint8_t msg[6];
  611. msg[0] = MESG_TX_SYNC; // sync
  612. msg[1] = 2; // length
  613. msg[2] = MESG_CHANNEL_RADIO_FREQ_ID;
  614. msg[3] = (uint8_t)channel;
  615. msg[4] = (uint8_t)freq;
  616. msg[5] = calcMsgChecksum(msg, 5);
  617. return write(msg, 6);
  618. }
  619. int AntPlus::SetSearchWaveform(const int channel, const int wave)
  620. {
  621. uint8_t msg[7];
  622. msg[0] = MESG_TX_SYNC; // sync
  623. msg[1] = 3; // length
  624. msg[2] = MESG_SEARCH_WAVEFORM_ID; // msg id
  625. msg[3] = (uint8_t)channel;
  626. msg[4] = (uint8_t)wave & 0xFF;
  627. msg[5] = (uint8_t)wave >> 8;
  628. msg[6] = calcMsgChecksum(msg, 6);
  629. return write(msg, 7);
  630. }
  631. int AntPlus::OpenChannel(const int channel)
  632. {
  633. uint8_t msg[5];
  634. msg[0] = MESG_TX_SYNC; // sync
  635. msg[1] = 1; // length
  636. msg[2] = MESG_OPEN_CHANNEL_ID; // msg id
  637. msg[3] = (uint8_t)channel;
  638. msg[4] = calcMsgChecksum(msg, 4);
  639. return write(msg, 5);
  640. }
  641. int AntPlus::CloseChannel(const int channel)
  642. {
  643. uint8_t msg[5];
  644. msg[0] = MESG_TX_SYNC; // sync
  645. msg[1] = 1; // length
  646. msg[2] = MESG_CLOSE_CHANNEL_ID; // msg id
  647. msg[3] = (uint8_t)channel;
  648. msg[4] = calcMsgChecksum(msg, 4);
  649. return write(msg, 5);
  650. }
  651. int AntPlus::AssignChannel(const int channel, const int channelType, const int network)
  652. {
  653. uint8_t msg[7];
  654. msg[0] = MESG_TX_SYNC;
  655. msg[1] = 3;
  656. msg[2] = MESG_ASSIGN_CHANNEL_ID;
  657. msg[3] = (uint8_t)channel;
  658. msg[4] = (uint8_t)channelType;
  659. msg[5] = (uint8_t)network;
  660. msg[6] = calcMsgChecksum(msg, 6);
  661. return write(msg, 7);
  662. }
  663. int AntPlus::SetChannelId(const int channel, const int deviceNum, const int deviceType, const int transmissionType)
  664. {
  665. uint8_t msg[9];
  666. msg[0] = MESG_TX_SYNC;
  667. msg[1] = 5;
  668. msg[2] = MESG_CHANNEL_ID_ID;
  669. msg[3] = (uint8_t)channel;
  670. msg[4] = (uint8_t)(deviceNum & 0xFF);
  671. msg[5] = (uint8_t)(deviceNum >> 8);
  672. msg[6] = (uint8_t)deviceType;
  673. msg[7] = (uint8_t)transmissionType;
  674. msg[8] = calcMsgChecksum(msg, 8);
  675. return write(msg, 9);
  676. }
  677. int AntPlus::SendBurstTransferPacket(const int channelSeq, const uint8_t *data)
  678. {
  679. uint8_t msg[13];
  680. msg[0] = MESG_TX_SYNC;
  681. msg[1] = 9;
  682. msg[2] = MESG_BURST_DATA_ID;
  683. msg[3] = (uint8_t)channelSeq;
  684. msg[4] = data[0];
  685. msg[5] = data[1];
  686. msg[6] = data[2];
  687. msg[7] = data[3];
  688. msg[8] = data[4];
  689. msg[9] = data[5];
  690. msg[10] = data[6];
  691. msg[11] = data[7];
  692. msg[12] = calcMsgChecksum(msg, 12); // xor checksum
  693. return write(msg, 13);
  694. }
  695. int AntPlus::SendBurstTransfer(const int channel, const uint8_t *data, const int nunPackets)
  696. {
  697. int ret = 0;
  698. int seq = 0;
  699. for (int i = 0; i < nunPackets; i++) {
  700. if (i == nunPackets-1) seq |= 0x04;
  701. ret = SendBurstTransferPacket((seq<<5) | (channel&0x1F), data+(i<<3));
  702. seq = (seq+1)&0x03;
  703. }
  704. return ret;
  705. }
  706. int AntPlus::SendBroadcastData(const int channel, const uint8_t *data)
  707. {
  708. uint8_t msg[13];
  709. msg[0] = MESG_TX_SYNC;
  710. msg[1] = 9;
  711. msg[2] = MESG_BROADCAST_DATA_ID;
  712. msg[3] = (uint8_t)channel;
  713. msg[4] = data[0];
  714. msg[5] = data[1];
  715. msg[6] = data[2];
  716. msg[7] = data[3];
  717. msg[8] = data[4];
  718. msg[9] = data[5];
  719. msg[10] = data[6];
  720. msg[11] = data[7];
  721. msg[12] = calcMsgChecksum(msg, 12);
  722. return write(msg, 13);
  723. }
  724. int AntPlus::SendAcknowledgedData(const int channel, const uint8_t *data)
  725. {
  726. uint8_t msg[13];
  727. msg[0] = MESG_TX_SYNC;
  728. msg[1] = 9;
  729. msg[2] = MESG_ACKNOWLEDGED_DATA_ID;
  730. msg[3] = (uint8_t)channel;
  731. msg[4] = data[0];
  732. msg[5] = data[1];
  733. msg[6] = data[2];
  734. msg[7] = data[3];
  735. msg[8] = data[4];
  736. msg[9] = data[5];
  737. msg[10] = data[6];
  738. msg[11] = data[7];
  739. msg[12] = calcMsgChecksum(msg, 12);
  740. return write(msg, 13);
  741. }
  742. int AntPlus::SendExtAcknowledgedData(const int channel, const int devNum, const int devType, const int TranType, const uint8_t *data)
  743. {
  744. uint8_t msg[17];
  745. msg[0] = MESG_TX_SYNC;
  746. msg[1] = 13;
  747. msg[2] = MESG_EXT_ACKNOWLEDGED_DATA_ID;
  748. msg[3] = (uint8_t)channel;
  749. msg[4] = (uint8_t)(devNum & 0xFF);
  750. msg[5] = (uint8_t)(devNum >> 8);
  751. msg[6] = (uint8_t)devType;
  752. msg[7] = (uint8_t)TranType;
  753. msg[8] = data[0];
  754. msg[9] = data[1];
  755. msg[10] = data[2];
  756. msg[11] = data[3];
  757. msg[12] = data[4];
  758. msg[13] = data[5];
  759. msg[14] = data[6];
  760. msg[15] = data[7];
  761. msg[16] = calcMsgChecksum(msg, 16);
  762. return write(msg, 17);
  763. }
  764. int AntPlus::SendExtBroadcastData(const int channel, const int devNum, const int devType, const int TranType, const uint8_t *data)
  765. {
  766. uint8_t msg[17];
  767. msg[0] = MESG_TX_SYNC;
  768. msg[1] = 13;
  769. msg[2] = MESG_EXT_BROADCAST_DATA_ID;
  770. msg[3] = (uint8_t)channel;
  771. msg[4] = (uint8_t)(devNum & 0xFF);
  772. msg[5] = (uint8_t)(devNum >> 8);
  773. msg[6] = (uint8_t)devType;
  774. msg[7] = (uint8_t)TranType;
  775. msg[8] = data[0];
  776. msg[9] = data[1];
  777. msg[10] = data[2];
  778. msg[11] = data[3];
  779. msg[12] = data[4];
  780. msg[13] = data[5];
  781. msg[14] = data[6];
  782. msg[15] = data[7];
  783. msg[16] = calcMsgChecksum(msg, 16);
  784. return write(msg, 17);
  785. }
  786. int AntPlus::SendExtBurstTransferPacket(const int chanSeq, const int devNum, const int devType,
  787. const int TranType, const uint8_t *data)
  788. {
  789. uint8_t msg[17];
  790. msg[0] = MESG_TX_SYNC;
  791. msg[1] = 13;
  792. msg[2] = MESG_EXT_BROADCAST_DATA_ID;
  793. msg[3] = (uint8_t)chanSeq;
  794. msg[4] = (uint8_t)(devNum & 0xFF);
  795. msg[5] = (uint8_t)(devNum >> 8);
  796. msg[6] = (uint8_t)devType;
  797. msg[7] = (uint8_t)TranType;
  798. msg[8] = data[0];
  799. msg[9] = data[1];
  800. msg[10] = data[2];
  801. msg[11] = data[3];
  802. msg[12] = data[4];
  803. msg[13] = data[5];
  804. msg[14] = data[6];
  805. msg[15] = data[7];
  806. msg[16] = calcMsgChecksum(msg, 16);
  807. return write(msg, 17);
  808. }
  809. int AntPlus::SendExtBurstTransfer(const int channel, const int devNum, const int devType,
  810. const int tranType, const uint8_t *data, const int nunPackets)
  811. {
  812. int ret = 0;
  813. int seq = 0;
  814. for (int i = 0; i < nunPackets; i++){
  815. if (i == nunPackets-1) seq |= 0x04;
  816. ret = SendExtBurstTransferPacket((seq<<5) | (channel&0x1F),
  817. devNum, devType, tranType, data+(i<<3));
  818. seq = (seq+1)&0x03;
  819. }
  820. return ret;
  821. }
  822. void AntPlus::profileSetup_HRM(TDCONFIG *cfg, const uint32_t deviceId)
  823. {
  824. cfg->deviceNumber = deviceId; // 0
  825. cfg->deviceType = ANT_DEVICE_HRM;
  826. cfg->transType = ANT_TRANSMISSION_SLAVE;
  827. cfg->channelType = ANT_CHANNEL_TYPE_SLAVE;
  828. cfg->networkNumber = 0;
  829. cfg->channel = PROFILE_HRM;
  830. cfg->channelPeriod = ANT_PERIOD_HRM;
  831. cfg->RFFreq = ANT_FREQUENCY_SPORT;
  832. cfg->searchTimeout = 255;
  833. cfg->searchWaveform = 0x53;//316;//0x53;
  834. //cfg->keyIdx = KEY_ANTSPORT;
  835. cfg->flags.chanIdOnce = 0;
  836. cfg->flags.channelStatus = ANT_CHANNEL_STATUS_UNASSIGNED;
  837. cfg->flags.channelStatusOld = 0xFF;
  838. cfg->flags.keyAccepted = 0;
  839. cfg->flags.profileValid = 1;
  840. }
  841. void AntPlus::profileSetup_SPDCAD(TDCONFIG *cfg, const uint32_t deviceId)
  842. {
  843. cfg->deviceNumber = deviceId; // 0
  844. cfg->deviceType = ANT_DEVICE_SPDCAD;
  845. cfg->transType = ANT_TRANSMISSION_SLAVE; // 5
  846. cfg->channelType = ANT_CHANNEL_TYPE_SLAVE;
  847. cfg->networkNumber = 0;
  848. cfg->channel = PROFILE_SPDCAD;
  849. cfg->channelPeriod = ANT_PERIOD_SPDCAD;
  850. cfg->RFFreq = ANT_FREQUENCY_SPORT;
  851. cfg->searchTimeout = 255;
  852. cfg->searchWaveform = 0x53;
  853. //cfg->keyIdx = KEY_ANTSPORT;
  854. cfg->flags.chanIdOnce = 0;
  855. cfg->flags.channelStatus = ANT_CHANNEL_STATUS_UNASSIGNED;
  856. cfg->flags.channelStatusOld = 0xFF;
  857. cfg->flags.keyAccepted = 0;
  858. cfg->flags.profileValid = 1;
  859. }
  860. void AntPlus::profileSetup_POWER(TDCONFIG *cfg, const uint32_t deviceId)
  861. {
  862. cfg->deviceNumber = deviceId; // 0
  863. cfg->deviceType = ANT_DEVICE_POWER;
  864. cfg->transType = ANT_TRANSMISSION_SLAVE; // 5
  865. cfg->channelType = ANT_CHANNEL_TYPE_SLAVE;
  866. cfg->networkNumber = 0;
  867. cfg->channel = PROFILE_POWER;
  868. cfg->channelPeriod = ANT_PERIOD_POWER;
  869. cfg->RFFreq = ANT_FREQUENCY_SPORT;
  870. cfg->searchTimeout = 255;
  871. cfg->searchWaveform = 0x53;
  872. //cfg->keyIdx = KEY_ANTSPORT;
  873. cfg->flags.chanIdOnce = 0;
  874. cfg->flags.channelStatus = ANT_CHANNEL_STATUS_UNASSIGNED;
  875. cfg->flags.channelStatusOld = 0xFF;
  876. cfg->flags.keyAccepted = 0;
  877. cfg->flags.profileValid = 1;
  878. }
  879. void AntPlus::profileSetup_STRIDE(TDCONFIG *cfg, const uint32_t deviceId)
  880. {
  881. cfg->deviceNumber = deviceId; // 0
  882. cfg->deviceType = ANT_DEVICE_STRIDE;
  883. cfg->transType = ANT_TRANSMISSION_SLAVE; // 5
  884. cfg->channelType = ANT_CHANNEL_TYPE_SLAVE;
  885. cfg->networkNumber = 0;
  886. cfg->channel = PROFILE_STRIDE;
  887. cfg->channelPeriod = ANT_PERIOD_STRIDE;
  888. cfg->RFFreq = ANT_FREQUENCY_STRIDE;
  889. cfg->searchTimeout = 255;
  890. cfg->searchWaveform = 0x53;
  891. //cfg->keyIdx = KEY_ANTSPORT;
  892. cfg->flags.chanIdOnce = 0;
  893. cfg->flags.channelStatus = ANT_CHANNEL_STATUS_UNASSIGNED;
  894. cfg->flags.channelStatusOld = 0xFF;
  895. cfg->flags.keyAccepted = 0;
  896. cfg->flags.profileValid = 1;
  897. }
  898. void AntPlus::profileSetup_SPEED(TDCONFIG *cfg, const uint32_t deviceId)
  899. {
  900. cfg->deviceNumber = deviceId; // 0
  901. cfg->deviceType = ANT_DEVICE_SPEED;
  902. cfg->transType = ANT_TRANSMISSION_SLAVE; // 5
  903. cfg->channelType = ANT_CHANNEL_TYPE_SLAVE;
  904. cfg->networkNumber = 0;
  905. cfg->channel = PROFILE_SPEED;
  906. cfg->channelPeriod = ANT_PERIOD_SPEED;
  907. cfg->RFFreq = ANT_FREQUENCY_SPORT;
  908. cfg->searchTimeout = 255;
  909. cfg->searchWaveform = 0x53;
  910. //cfg->keyIdx = KEY_ANTSPORT;
  911. cfg->flags.chanIdOnce = 0;
  912. cfg->flags.channelStatus = ANT_CHANNEL_STATUS_UNASSIGNED;
  913. cfg->flags.channelStatusOld = 0xFF;
  914. cfg->flags.keyAccepted = 0;
  915. cfg->flags.profileValid = 1;
  916. }
  917. void AntPlus::profileSetup_CADENCE(TDCONFIG *cfg, const uint32_t deviceId)
  918. {
  919. cfg->deviceNumber = deviceId; // 0
  920. cfg->deviceType = ANT_DEVICE_CADENCE;
  921. cfg->transType = ANT_TRANSMISSION_SLAVE; // 5
  922. cfg->channelType = ANT_CHANNEL_TYPE_SLAVE;
  923. cfg->networkNumber = 0;
  924. cfg->channel = PROFILE_CADENCE;
  925. cfg->channelPeriod = ANT_PERIOD_CADENCE;
  926. cfg->RFFreq = ANT_FREQUENCY_SPORT;
  927. cfg->searchTimeout = 255;
  928. cfg->searchWaveform = 0x53;
  929. //cfg->keyIdx = KEY_ANTSPORT;
  930. cfg->flags.chanIdOnce = 0;
  931. cfg->flags.channelStatus = ANT_CHANNEL_STATUS_UNASSIGNED;
  932. cfg->flags.channelStatusOld = 0xFF;
  933. cfg->flags.keyAccepted = 0;
  934. cfg->flags.profileValid = 1;
  935. }
  936. #if 0
  937. /*
  938. uint64_t factory_passkey (uint64_t device_id, uint8_t *buffer)
  939. {
  940. uint64_t n = (((uint64_t)device_id ^ 0x7d215abb) << 32) + ((uint64_t)device_id ^ 0x42b93f06);
  941. for (uint8_t i = 0; i < 8; i++)
  942. buffer[i] = n >> (8*i)&0xFF;
  943. return n;
  944. }
  945. */
  946. int libantplus_Start ()
  947. {
  948. #if 0
  949. uint8_t buffer[8];
  950. factory_passkey(3825666043, buffer);
  951. dump_hexbytes(buffer, 8);
  952. #endif
  953. int ct = 0;
  954. uint32_t deviceId;
  955. for (int i = 0; i < PROFILE_TOTAL; i++){
  956. deviceId = 0;
  957. if (antplus_sendMessage(ANTP_MSG_PROFILE_SELECT, (intptr_t*)&deviceId, i) != 1)
  958. continue;
  959. ct++;
  960. //printf("enabling profile %i", i);
  961. switch (i){
  962. case PROFILE_HRM:
  963. profileSetup_HRM(&ant->dcfg[PROFILE_HRM], deviceId);
  964. libantplus_SetPayloadHandler(PROFILE_HRM, (void*)payload_HRM, (void*)NULL);
  965. break;
  966. case PROFILE_SPDCAD:
  967. profileSetup_SPDCAD(&ant->dcfg[PROFILE_SPDCAD], deviceId);
  968. libantplus_SetPayloadHandler(PROFILE_SPDCAD, (void*)payload_SPDCAD, (void*)NULL);
  969. break;
  970. case PROFILE_POWER:
  971. profileSetup_POWER(&ant->dcfg[PROFILE_POWER], deviceId);
  972. libantplus_SetPayloadHandler(PROFILE_POWER, (void*)payload_POWER, (void*)NULL);
  973. break;
  974. case PROFILE_STRIDE:
  975. profileSetup_STRIDE(&ant->dcfg[PROFILE_STRIDE], deviceId);
  976. libantplus_SetPayloadHandler(PROFILE_STRIDE, (void*)payload_STRIDE, (void*)NULL);
  977. break;
  978. case PROFILE_SPEED:
  979. profileSetup_SPEED(&ant->dcfg[PROFILE_SPEED], deviceId);
  980. libantplus_SetPayloadHandler(PROFILE_SPEED, (void*)payload_SPEED, (void*)NULL);
  981. break;
  982. case PROFILE_CADENCE:
  983. profileSetup_CADENCE(&ant->dcfg[PROFILE_CADENCE], deviceId);
  984. libantplus_SetPayloadHandler(PROFILE_CADENCE, (void*)payload_CADENCE, (void*)NULL);
  985. break;
  986. }
  987. }
  988. return ct;
  989. }
  990. TLIBANTPLUS *libantplus_Init (const uint8_t networkKey)
  991. {
  992. if (networkKey >= KEY_TOTAL){
  993. //printf("libantplus_Init(): invalid networkKey (%i)");
  994. //return NULL;
  995. ant->key = KEY_DEFAULT;
  996. }else{
  997. ant->key = networkKey;
  998. }
  999. libantplus_SetEventHandler(EVENTI_MESSAGE, (void*)message_event, (void*)ant);
  1000. return ant;
  1001. }
  1002. #endif
  1003. void AntPlus::begin(const uint8_t key)
  1004. {
  1005. ant.key = (key < KEY_TOTAL) ? key : 0;
  1006. int deviceId = 0; // TODO: user API to set this?
  1007. profileSetup_HRM(&ant.dcfg[PROFILE_HRM], deviceId);
  1008. profileSetup_SPDCAD(&ant.dcfg[PROFILE_SPDCAD], deviceId);
  1009. //profileSetup_POWER(&ant.dcfg[PROFILE_POWER], deviceId);
  1010. //profileSetup_STRIDE(&ant.dcfg[PROFILE_STRIDE], deviceId);
  1011. //profileSetup_SPEED(&ant.dcfg[PROFILE_SPEED], deviceId);
  1012. //profileSetup_CADENCE(&ant.dcfg[PROFILE_CADENCE], deviceId);
  1013. //ant.eventCb[EVENTI_MESSAGE].cbPtr = &message_event;
  1014. //SetEventHandler(EVENTI_MESSAGE, (void*)message_event, (void*)ant);
  1015. }
  1016. /*
  1017. int AntPlus::registerEventCallback(const int which, void *eventFunc, void *userPtr)
  1018. {
  1019. if (which < EVENTI_TOTAL) {
  1020. ant.eventCb[which].cbPtr = (int (*)(int, int, const uint8_t*, size_t, void*))eventFunc;
  1021. */
  1022. void AntPlus::dispatchPayload(TDCONFIG *cfg, const uint8_t *payload, const int len)
  1023. {
  1024. switch (cfg->channel) {
  1025. case PROFILE_HRM:
  1026. payload_HRM(cfg, payload, len);
  1027. break;
  1028. case PROFILE_SPDCAD:
  1029. payload_SPDCAD(cfg, payload, len);
  1030. break;
  1031. case PROFILE_POWER:
  1032. payload_POWER(cfg, payload, len);
  1033. break;
  1034. case PROFILE_STRIDE:
  1035. payload_STRIDE(cfg, payload, len);
  1036. break;
  1037. case PROFILE_SPEED:
  1038. payload_SPEED(cfg, payload, len);
  1039. break;
  1040. case PROFILE_CADENCE:
  1041. payload_CADENCE(cfg, payload, len);
  1042. break;
  1043. }
  1044. }
  1045. const uint8_t * AntPlus::getAntKey(const uint8_t keyIdx)
  1046. {
  1047. if (keyIdx >= KEY_TOTAL) return NULL;
  1048. return antkeys[keyIdx];
  1049. }
  1050. #define WHEEL_CIRCUMFERENCE 2122
  1051. typedef struct {
  1052. struct {
  1053. uint16_t time;
  1054. uint16_t interval;
  1055. uint8_t bpm; // heart rate in beats per minute
  1056. uint8_t sequence;
  1057. }current;
  1058. struct {
  1059. uint8_t bpm;
  1060. uint8_t sequence;
  1061. uint16_t time;
  1062. uint16_t interval;
  1063. }previous;
  1064. }payload_HRM_t;
  1065. typedef struct {
  1066. struct {
  1067. uint16_t cadenceTime;
  1068. uint16_t cadence;
  1069. uint16_t cadenceCt;
  1070. uint16_t speedTime;
  1071. uint16_t speed;
  1072. uint16_t speedCt;
  1073. uint32_t distance;
  1074. }current;
  1075. struct {
  1076. uint16_t cadenceTime;
  1077. uint16_t cadence;
  1078. uint16_t cadenceCt;
  1079. uint16_t speedTime;
  1080. uint16_t speed;
  1081. uint16_t speedCt;
  1082. uint32_t distance;
  1083. }previous;
  1084. uint16_t wheelCircumference; // default is WHEEL_CIRCUMFERENCE (2122cm)
  1085. uint8_t spdChange;
  1086. uint8_t cadChange;
  1087. }payload_SPDCAD_t;
  1088. typedef struct {
  1089. struct {
  1090. uint8_t sequence;
  1091. uint16_t pedalPowerContribution;
  1092. uint8_t pedalPower;
  1093. uint8_t instantCadence;
  1094. uint16_t sumPower;
  1095. uint16_t instantPower;
  1096. } current;
  1097. struct {
  1098. uint16_t stub;
  1099. } previous;
  1100. }payload_POWER_t;
  1101. typedef struct {
  1102. struct {
  1103. uint16_t speed;
  1104. uint16_t cadence;
  1105. uint8_t strides;
  1106. }current;
  1107. struct {
  1108. uint8_t strides;
  1109. uint16_t speed;
  1110. uint16_t cadence;
  1111. }previous;
  1112. }payload_STRIDE_t;
  1113. typedef struct {
  1114. struct {
  1115. uint16_t speedTime;
  1116. uint16_t speed;
  1117. uint16_t speedCt;
  1118. uint32_t distance;
  1119. }current;
  1120. struct {
  1121. uint16_t speedTime;
  1122. uint16_t speed;
  1123. uint16_t speedCt;
  1124. uint32_t distance;
  1125. }previous;
  1126. uint16_t wheelCircumference; // default is WHEEL_CIRCUMFERENCE (2122cm)
  1127. uint8_t spdChange;
  1128. }payload_SPEED_t;
  1129. typedef struct {
  1130. struct {
  1131. uint16_t cadenceTime;
  1132. uint16_t cadence;
  1133. uint16_t cadenceCt;
  1134. }current;
  1135. struct {
  1136. uint16_t cadenceTime;
  1137. uint16_t cadence;
  1138. uint16_t cadenceCt;
  1139. }previous;
  1140. uint8_t cadChange;
  1141. }payload_CADENCE_t;
  1142. typedef struct {
  1143. payload_HRM_t hrm;
  1144. payload_SPDCAD_t spdcad;
  1145. payload_POWER_t power;
  1146. payload_STRIDE_t stride;
  1147. payload_SPEED_t spd;
  1148. payload_CADENCE_t cad;
  1149. }payload_genstorage_t;
  1150. static payload_genstorage_t payload; // FIXME: should be in the AntPlus object
  1151. void AntPlus::payload_HRM(TDCONFIG *cfg, const uint8_t *data, const size_t dataLength)
  1152. {
  1153. payload_HRM_t *hrm = &payload.hrm;
  1154. hrm->current.bpm = data[STREAM_RXBROADCAST_DEV120_HR];
  1155. hrm->current.sequence = data[STREAM_RXBROADCAST_DEV120_SEQ];
  1156. //const int page = data[1]&0x0F;
  1157. if (hrm->previous.sequence != hrm->current.sequence || hrm->previous.bpm != hrm->current.bpm){
  1158. if (hrm->current.bpm){
  1159. hrm->current.time = (data[STREAM_RXBROADCAST_DEV120_BEATLO] + (data[STREAM_RXBROADCAST_DEV120_BEATHI] << 8));
  1160. hrm->current.interval = hrm->current.time - hrm->previous.time;
  1161. hrm->current.interval = (((int32_t)hrm->current.interval) * (int32_t)1000) / (int32_t)1024;
  1162. //printf("page %i", page);
  1163. sendMessage(ANTP_MSG_PROFILE_DATA, (intptr_t*)hrm, PROFILE_HRM);
  1164. hrm->previous.time = hrm->current.time;
  1165. hrm->previous.interval = hrm->current.interval;
  1166. hrm->previous.sequence = hrm->current.sequence;
  1167. hrm->previous.bpm = hrm->current.bpm;
  1168. }
  1169. }
  1170. //int page = data[1]&0x0F;
  1171. //printf("payload_HRM: page:%i, Sequence:%i, BPM:%i, %i %i", page, hrm->current.sequence, hrm->current.bpm, hrm->current.time, hrm->current.interval);
  1172. }
  1173. void AntPlus::payload_SPDCAD(TDCONFIG *cfg, const uint8_t *data, const size_t dataLength)
  1174. {
  1175. payload_SPDCAD_t *spdcad = &payload.spdcad;
  1176. spdcad->current.cadenceTime = data[1];
  1177. spdcad->current.cadenceTime |= (data[2] << 8);
  1178. spdcad->current.cadenceCt = data[3];
  1179. spdcad->current.cadenceCt |= (data[4] << 8);
  1180. spdcad->current.speedTime = data[5];
  1181. spdcad->current.speedTime |= (data[6] << 8);
  1182. spdcad->current.speedCt = data[7];
  1183. spdcad->current.speedCt |= (data[8] << 8);
  1184. spdcad->cadChange = (spdcad->current.cadenceTime != spdcad->previous.cadenceTime || spdcad->current.cadenceCt != spdcad->previous.cadenceCt);
  1185. spdcad->spdChange = (spdcad->current.speedTime != spdcad->previous.speedTime || spdcad->current.speedCt != spdcad->previous.speedCt);
  1186. if (spdcad->cadChange || spdcad->spdChange){
  1187. uint16_t cadence = (60 * (spdcad->current.cadenceCt - spdcad->previous.cadenceCt) * 1024) / (spdcad->current.cadenceTime - spdcad->previous.cadenceTime);
  1188. spdcad->current.cadence = cadence;
  1189. if (!spdcad->wheelCircumference) spdcad->wheelCircumference = WHEEL_CIRCUMFERENCE;
  1190. uint32_t speedRotationDelta = spdcad->current.speedCt - spdcad->previous.speedCt; // number wheel revolutions
  1191. float speedTimeDelta = (float)(spdcad->current.speedTime - spdcad->previous.speedTime) / 1024.0f; // time for above revolutions
  1192. float distance = (speedRotationDelta * (float)spdcad->wheelCircumference) / 1000.0f; // calculated distance (meters) travelled as per above
  1193. float speed = (distance / (speedTimeDelta / 3600.0f)) / 1000.0f; // its why we're here
  1194. spdcad->current.speed = speed * 100;
  1195. spdcad->current.distance += distance;
  1196. sendMessage(ANTP_MSG_PROFILE_DATA, (intptr_t*)spdcad, PROFILE_SPDCAD);
  1197. spdcad->previous.cadenceTime = spdcad->current.cadenceTime;
  1198. spdcad->previous.cadence = spdcad->current.cadence;
  1199. spdcad->previous.cadenceCt = spdcad->current.cadenceCt;
  1200. spdcad->previous.speedTime = spdcad->current.speedTime;
  1201. spdcad->previous.speedCt = spdcad->current.speedCt;
  1202. spdcad->previous.speed = spdcad->current.speed;
  1203. spdcad->previous.distance = spdcad->current.distance;
  1204. //printf("payload_SPDCAD: speed: %.2f, cadence: %i, total distance: %.2f", spdcad->current.speed/100.0f, spdcad->current.cadence, spdcad->current.distance/1000.0f);
  1205. }
  1206. }
  1207. void AntPlus::payload_POWER(TDCONFIG *cfg, const uint8_t *data, const size_t dataLength)
  1208. {
  1209. //printf("payload_POWER: len:%i", dataLength);
  1210. payload_POWER_t *pwr = &payload.power;
  1211. /*
  1212. uint8_t eventCount = data[2];
  1213. uint8_t pedalPowerContribution = ((data[3] != 0xFF) && (data[3]&0x80)) ; // left/right is defined if NOT 0xFF (= no Pedal Power) AND BIT 7 is set
  1214. uint8_t pedalPower = (data[3]&0x7F); // right pedalPower % - stored in bit 0-6
  1215. uint8_t instantCadence = data[4];
  1216. uint16_t sumPower = data[5] + (data[6]<<8);
  1217. uint16_t instantPower = data[7] + (data[8]<<8);
  1218. */
  1219. sendMessage(ANTP_MSG_PROFILE_DATA, (intptr_t*)pwr, PROFILE_POWER);
  1220. }
  1221. void AntPlus::payload_STRIDE(TDCONFIG *cfg, const uint8_t *data, const size_t dataLength)
  1222. {
  1223. //printf("payload_STRIDE: len:%i", dataLength);
  1224. payload_STRIDE_t *stride = &payload.stride;
  1225. int page = data[1];
  1226. if (page == 0){
  1227. stride->current.strides = data[7];
  1228. sendMessage(ANTP_MSG_PROFILE_DATA, (intptr_t*)stride, PROFILE_STRIDE);
  1229. stride->previous.strides = stride->current.strides;
  1230. }else if (page == 1){
  1231. stride->current.speed = ((float)(data[4]&0x0f) + (float)(data[5]/256.0f));
  1232. stride->current.cadence = ((float)data[3] + (float)((data[4] << 4) / 16.0f));
  1233. sendMessage(ANTP_MSG_PROFILE_DATA, (intptr_t*)stride, PROFILE_STRIDE);
  1234. stride->previous.speed = stride->current.speed;
  1235. stride->previous.cadence = stride->current.cadence;
  1236. }
  1237. }
  1238. void AntPlus::payload_SPEED(TDCONFIG *cfg, const uint8_t *data, const size_t dataLength)
  1239. {
  1240. //printf("payload_SPEED: len:%i", dataLength);
  1241. payload_SPEED_t *spd = &payload.spd;
  1242. spd->current.speedTime = data[5];
  1243. spd->current.speedTime |= (data[6] << 8);
  1244. spd->current.speedCt = data[7];
  1245. spd->current.speedCt |= (data[8] << 8);
  1246. spd->spdChange = (spd->current.speedTime != spd->previous.speedTime || spd->current.speedCt != spd->previous.speedCt);
  1247. if (spd->spdChange){
  1248. uint32_t speedRotationDelta = spd->current.speedCt - spd->previous.speedCt; // number wheel revolutions
  1249. float speedTimeDelta = (float)(spd->current.speedTime - spd->previous.speedTime) / 1024.0f; // time for above revolutions
  1250. if (!spd->wheelCircumference) spd->wheelCircumference = WHEEL_CIRCUMFERENCE;
  1251. float distance = (speedRotationDelta * (float)spd->wheelCircumference) / 1000.0f; // calculated distance (meters) travelled as per above
  1252. float speed = (distance / (speedTimeDelta / 3600.0f)) / 1000.0f; // its why we're here
  1253. spd->current.speed = speed * 100;
  1254. spd->current.distance += distance;
  1255. sendMessage(ANTP_MSG_PROFILE_DATA, (intptr_t*)spd, PROFILE_SPEED);
  1256. spd->previous.speedTime = spd->current.speedTime;
  1257. spd->previous.speedCt = spd->current.speedCt;
  1258. spd->previous.speed = spd->current.speed;
  1259. spd->previous.distance = spd->current.distance;
  1260. }
  1261. }
  1262. void AntPlus::payload_CADENCE(TDCONFIG *cfg, const uint8_t *data, const size_t dataLength)
  1263. {
  1264. //printf("payload_CADENCE: len:%i", dataLength);
  1265. payload_CADENCE_t *cad = &payload.cad;
  1266. cad->current.cadenceTime = data[5];
  1267. cad->current.cadenceTime |= (data[6] << 8);
  1268. cad->current.cadenceCt = data[7];
  1269. cad->current.cadenceCt |= (data[8] << 8);
  1270. cad->cadChange = (cad->current.cadenceTime != cad->previous.cadenceTime || cad->current.cadenceCt != cad->previous.cadenceCt);
  1271. if (cad->cadChange){
  1272. uint16_t cadence = (60 * (cad->current.cadenceCt - cad->previous.cadenceCt) * 1024) / (cad->current.cadenceTime - cad->previous.cadenceTime);
  1273. cad->current.cadence = cadence;
  1274. sendMessage(ANTP_MSG_PROFILE_DATA, (intptr_t*)cad, PROFILE_CADENCE);
  1275. cad->previous.cadenceTime = cad->current.cadenceTime;
  1276. cad->previous.cadence = cad->current.cadence;
  1277. cad->previous.cadenceCt = cad->current.cadenceCt;
  1278. }
  1279. }