PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

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