Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

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