You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1518 lines
43KB

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