SDMSensor.cpp 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739
  1. /*
  2. This software is subject to the license described in the License.txt file
  3. included with this software distribution. You may not use this file except in compliance
  4. with this license.
  5. Copyright (c) Dynastream Innovations Inc. 2012
  6. All rights reserved.
  7. */
  8. #include "StdAfx.h"
  9. #include "SDMSensor.h"
  10. /**************************************************************************
  11. * SDMSensor::ANT_eventNotification
  12. *
  13. * Process ANT channel event
  14. *
  15. * ucEventCode_: code of ANT channel event
  16. * pucEventBuffer_: pointer to buffer containing data received from ANT,
  17. * or a pointer to the transmit buffer in the case of an EVENT_TX
  18. *
  19. * returns: N/A
  20. *
  21. **************************************************************************/
  22. void SDMSensor::ANT_eventNotification(UCHAR ucEventCode_, UCHAR* pucEventBuffer_)
  23. {
  24. switch(ucEventCode_)
  25. {
  26. case EVENT_TX:
  27. HandleTransmit((UCHAR*) pucEventBuffer_);
  28. UpdateDisplay();
  29. break;
  30. case EVENT_RX_ACKNOWLEDGED: // added for receiving request pages
  31. HandleReceive((UCHAR*) pucEventBuffer_);
  32. break;
  33. case EVENT_TRANSFER_TX_COMPLETED: // For sending ACK request replies
  34. ucAckRetryCount = 0; // Reset retransmission counter
  35. ucMsgExpectingAck = 0; // Clear pending msg code
  36. break;
  37. case EVENT_TRANSFER_TX_FAILED:
  38. case EVENT_ACK_TIMEOUT: // Intentional fall thru
  39. if(ucMsgExpectingAck)
  40. HandleRetransmit(); // resend if it failed
  41. break;
  42. default:
  43. break;
  44. }
  45. }
  46. /**************************************************************************
  47. * SDMSensor::InitializeSim
  48. *
  49. * Initializes simulator variables
  50. *
  51. * returns: N/A
  52. *
  53. **************************************************************************/
  54. void SDMSensor::InitializeSim()
  55. {
  56. // Time info
  57. ulTimerInterval = 667; //cadence of 90
  58. ulRunTime = 0;
  59. dwTimeLastEvent = GetTickCount(); // Initialize timers for latency calculation
  60. dwTimeLastTx = dwTimeLastEvent;
  61. // Common pages (data initialized on UI)
  62. commonPages->ulSerialNum = System::Convert::ToUInt32(this->textBox_SerialNum->Text);
  63. commonPages->usModelNum = System::Convert::ToUInt16(this->textBox_ModelNum->Text);
  64. commonPages->usMfgID = System::Convert::ToUInt16(this->textBox_MfgID->Text);
  65. commonPages->ucHwVersion = System::Convert::ToByte(this->textBox_HwVersion->Text);
  66. commonPages->ucSwVersion = System::Convert::ToByte(this->textBox_SwVersion->Text);
  67. // Options
  68. ucSimDataType = SIM_FIXED;
  69. bSweepAscending = TRUE;
  70. bTxCommon = TRUE; // Enable common pages (required on new designs)
  71. bTxPage2 = TRUE; // Enable page 2 and all fields by default
  72. bTxPage3 = FALSE; // Disable Page 3 by default
  73. bTxPage16 = TRUE; // Enable Request Pages by default
  74. bTxPage22 = TRUE; // Enable Request Pages by default
  75. bTxPage16Flag = FALSE; // This flag is raised when a request to send Page 16 data is received
  76. bTxPage22Flag = FALSE; // This flag is raised when a request to send Page 22 data is received
  77. ucRequestCount = 0;
  78. bP22Ignore = FALSE;
  79. ucMsgExpectingAck = 0;
  80. ucMaxAckRetries = 127; // 127 is the default max number of times to attempt to resend an ack message
  81. bUseTime = TRUE;
  82. bUseDistance = TRUE;
  83. bUseLatency = TRUE;
  84. bUseSpeed = TRUE;
  85. bUseCadence = TRUE;
  86. eUnit = SDM_SPM; // user input is cadence (rpm)
  87. // Simulator data
  88. ucStrideLength = System::Convert::ToByte(this->numericUpDown_Sim_StrideLength->Value);
  89. ucCalorieRate = System::Convert::ToByte(this->numericUpDown_Sim_BurnRate->Value);
  90. this->listBox_SimUnits->SelectedIndex = 3; // Use rpm by default
  91. this->listBox_SimUnits->SelectedIndexChanged += gcnew System::EventHandler(this, &SDMSensor::listBox_SimUnitsChanged);
  92. usMaxCadence16 = ConvertFromInput(this->numericUpDown_Sim_MaxOutput->Value); // Initial cadence value set on UI
  93. usMinCadence16 = ConvertFromInput(this->numericUpDown_Sim_MinOutput->Value); // Initial cadence value set on UI
  94. usCurCadence16 = ConvertFromInput(this->numericUpDown_Sim_CurOutput->Value); // Initial cadence value set on UI
  95. usMaxSpeed256 = CadenceToSpeed(usMaxCadence16);
  96. usMinSpeed256 = CadenceToSpeed(usMinCadence16);
  97. usCurSpeed256 = CadenceToSpeed(usCurCadence16);
  98. usCadence16 = usCurCadence16;
  99. usSpeed256 = usCurSpeed256;
  100. ucStrideCount = 0;
  101. ucCalorieCount = 0;
  102. ulTempCalories = 0;
  103. ulStridesAccum = 0;
  104. ulDistanceAccum = 0;
  105. usDistance16 = 0;
  106. usTime200 = 0;
  107. ucLatency32 = 0;
  108. // Initialize status flags
  109. sStatusFlags.ucLocation = (UCHAR) 0;
  110. sStatusFlags.ucBatteryStatus = (UCHAR) 0;
  111. sStatusFlags.ucHealth = (UCHAR) 0;
  112. sStatusFlags.ucUseState = (UCHAR) 1;
  113. this->listBox_P2Location->SelectedIndex = 0;
  114. this->listBox_P2Battery->SelectedIndex = 0;
  115. this->listBox_P2Health->SelectedIndex = 0;
  116. this->listBox_P2Use->SelectedIndex = 1;
  117. // Initialize capabilities flags
  118. sCapabFlags.ucCadence = (UCHAR) 1;
  119. sCapabFlags.ucCalories = (UCHAR) 0;
  120. sCapabFlags.ucDistance = (UCHAR) 1;
  121. sCapabFlags.ucLatency = (UCHAR) 1;
  122. sCapabFlags.ucSpeed = (UCHAR) 1;
  123. sCapabFlags.ucTime = (UCHAR) 1;
  124. ucCapabFlags = SDM_CAPAB_INITIAL; // initialize flags based on the values above, very important to do this
  125. this->label_P22Cadence->ForeColor = System::Drawing::Color::Green;
  126. this->label_P22Calories->ForeColor = System::Drawing::Color::Red;
  127. this->label_P22Distance->ForeColor = System::Drawing::Color::Green;
  128. this->label_P22Latency->ForeColor = System::Drawing::Color::Green;
  129. this->label_P22Speed->ForeColor = System::Drawing::Color::Green;
  130. this->label_P22Time->ForeColor = System::Drawing::Color::Green;
  131. }
  132. /**************************************************************************
  133. * SDMSensor::HandleTransmit
  134. *
  135. * Encode data generated by simulator for transmission
  136. *
  137. * pucTxBuffer_: pointer to the transmit buffer
  138. *
  139. * returns: N/A
  140. *
  141. **************************************************************************/
  142. void SDMSensor::HandleTransmit(UCHAR* pucTxBuffer_)
  143. {
  144. static UCHAR ucMessageCount = 0;
  145. static UCHAR ucExtMesgType = 0;
  146. UCHAR ucPageNum;
  147. // Update latency
  148. // Latency calculation is platform specific
  149. dwTimeLastTx = GetTickCount(); // Get current time for latency calculation
  150. ucLatency32 = (UCHAR) (((dwTimeLastTx - dwTimeLastEvent) << 2)/25); // Convert from ms to 1/32 seconds
  151. // Figure out what page to send
  152. ucPageNum = SDM_PAGE1;
  153. if(bTxPage2 || bTxPage3)
  154. {
  155. // Page 1 and 2 (or 3) alternate every 2 messages
  156. if(ucMessageCount & 0x02)
  157. if (bTxPage2)
  158. ucPageNum = SDM_PAGE2;
  159. else
  160. ucPageNum = SDM_PAGE3;
  161. }
  162. // Send common pages every 65th message,
  163. // Skip if we are sending request pages as this takes priority
  164. if(ucMessageCount++ >= (SDM_COMMON_INTERVAL - 1) && bTxCommon
  165. && (bTxPage16Flag == FALSE) && (bTxPage22Flag == FALSE))
  166. {
  167. // Always send two in a row
  168. if(ucExtMesgType++ & 0x02)
  169. ucPageNum = CommonData::PAGE81;
  170. else
  171. ucPageNum = CommonData::PAGE80;
  172. ucMessageCount = 0;
  173. }
  174. // Request pages only on request. This takes priority over all other messages.
  175. if (bTxPage16Flag == TRUE)
  176. {
  177. ucPageNum = SDM_PAGE16;
  178. ucRequestCount--; // subtract one from the resend count
  179. if (ucRequestCount == 0) // if count is zero, then reset
  180. bTxPage16Flag = FALSE;
  181. }
  182. if (bTxPage22Flag == TRUE)
  183. {
  184. ucPageNum = SDM_PAGE22;
  185. ucRequestCount--; // subtract one from the resend count
  186. if (ucRequestCount == 0) // if count is zero, then reset
  187. bTxPage22Flag = FALSE;
  188. }
  189. // Set page number
  190. pucTxBuffer_[0] = ucPageNum;
  191. // Encode each page
  192. switch(ucPageNum)
  193. {
  194. case SDM_PAGE1:
  195. pucTxBuffer_[1] = (usTime200 % 200) * bUseTime; // fractional time (1/200 seconds)
  196. pucTxBuffer_[2] = (UCHAR) (usTime200/200 * bUseTime); // time of last event (seconds)
  197. pucTxBuffer_[3] = (usDistance16 * bUseDistance >> 4) & 0xFF; // cumulative distance (meters)
  198. pucTxBuffer_[4] = (usDistance16 * bUseDistance << 4) & 0xF0; // fractional distance (1/16 meters)
  199. pucTxBuffer_[4] |= ((usSpeed256 * bUseSpeed >> 8) & 0x0F); // current speed (m/s) - if enabled
  200. pucTxBuffer_[5] = usSpeed256 * bUseSpeed & 0xFF; // fractional speed (1/256 m/s) - if enabled
  201. pucTxBuffer_[6] = ucStrideCount & 0xFF; // cumulative stride count (number of strides)
  202. pucTxBuffer_[7] = ucLatency32 * bUseLatency; // latency (1/32 seconds) - if enabled
  203. break;
  204. case SDM_PAGE2:
  205. pucTxBuffer_[1] = SDM_RESERVED;
  206. pucTxBuffer_[2] = SDM_RESERVED;
  207. pucTxBuffer_[3] = (usCadence16 * bUseCadence >> 4) & 0xFF; // current cadence (strides/min)
  208. pucTxBuffer_[4] = (usCadence16 * bUseCadence << 4) & 0xF0; // fractional cadence (1/16 strides/min)
  209. pucTxBuffer_[4] |= (usSpeed256 * bUseSpeed >> 8) & 0x0F; // current speed (m/s)
  210. pucTxBuffer_[5] = usSpeed256 * bUseSpeed & 0xFF; // fractional speed (1/256 m/s)
  211. pucTxBuffer_[6] = SDM_RESERVED;
  212. pucTxBuffer_[7] = ucStatusFlags; // SDM status flags
  213. break;
  214. case SDM_PAGE3:
  215. pucTxBuffer_[1] = SDM_RESERVED;
  216. pucTxBuffer_[2] = SDM_RESERVED;
  217. pucTxBuffer_[3] = (usCadence16 * bUseCadence >> 4) & 0xFF; // current cadence (strides/min)
  218. pucTxBuffer_[4] = (usCadence16 * bUseCadence << 4) & 0xF0; // fractional cadence (1/16 strides/min)
  219. pucTxBuffer_[4] |= (usSpeed256 * bUseSpeed >> 8) & 0x0F; // current speed (m/s)
  220. pucTxBuffer_[5] = usSpeed256 * bUseSpeed & 0xFF; // fractional speed (1/256 m/s)
  221. pucTxBuffer_[6] = ucCalorieCount & 0xFF; // cumulative calorie count
  222. pucTxBuffer_[7] = ucStatusFlags; // SDM status flags
  223. break;
  224. case SDM_PAGE16: // on request only
  225. pucTxBuffer_[1] = ulStridesAccum & 0xFF; // Bytes 1-3 = Stride Count
  226. pucTxBuffer_[2] = (ulStridesAccum >> 8) & 0xFF;
  227. pucTxBuffer_[3] = (ulStridesAccum >> 16) & 0xFF;
  228. pucTxBuffer_[4] = ulDistanceAccum & 0xFF; // Bytes 4-7 = Distance
  229. pucTxBuffer_[5] = (ulDistanceAccum >> 8) & 0xFF;
  230. pucTxBuffer_[6] = (ulDistanceAccum >> 16) & 0xFF;
  231. pucTxBuffer_[7] = (ulDistanceAccum >> 24) & 0xFF;
  232. break;
  233. case SDM_PAGE22: // on request only
  234. pucTxBuffer_[1] = ucCapabFlags; // Capabilities Byte
  235. pucTxBuffer_[2] = SDM_RESERVED; // Bytes 2-7 are reserved
  236. pucTxBuffer_[3] = SDM_RESERVED;
  237. pucTxBuffer_[4] = SDM_RESERVED;
  238. pucTxBuffer_[5] = SDM_RESERVED;
  239. pucTxBuffer_[6] = SDM_RESERVED;
  240. pucTxBuffer_[7] = SDM_RESERVED;
  241. break;
  242. case CommonData::PAGE80:
  243. case CommonData::PAGE81:
  244. try
  245. {
  246. commonPages->Encode(ucPageNum, pucTxBuffer_);
  247. }
  248. catch(CommonData::Error^ errorCommon)
  249. {
  250. }
  251. break;
  252. default:
  253. break;
  254. }
  255. }
  256. /**************************************************************************
  257. * SDMSensor::HandleReceive
  258. *
  259. * Decode incoming transmissions, specifically data requests
  260. *
  261. * returns: N/A
  262. *
  263. **************************************************************************/
  264. void SDMSensor::HandleReceive(UCHAR* pucRxBuffer_)
  265. {
  266. UCHAR ucPageNum = pucRxBuffer_[0];
  267. UCHAR ucRequestNum = pucRxBuffer_[6];
  268. BOOL bP22Skip = FALSE;
  269. // if all the flags are on AND we are chosing to ignore the request if this happens, set the flag
  270. if ((bP22Ignore == TRUE) && (ucCapabFlags == SDM_CAPAB_ALL))
  271. bP22Skip = TRUE;
  272. if(ucPageNum == SDM_PAGE70) // Only decode request pages
  273. {
  274. if ((ucRequestNum == SDM_PAGE16) && (bTxPage16 == TRUE)) // only process request if page is enabled
  275. {
  276. ucRequestCount = pucRxBuffer_[5]; // save the number of times to re-transmit
  277. if (ucRequestCount == 0x80) // 0x80 is a special case where we want to resend ack messages until a response is recieved
  278. {
  279. ucMaxAckRetries = 127; // reset to default in case this was changed
  280. SendAckRequestMsg(SDM_PAGE16); // will automatically attempt to re-send until ack
  281. }
  282. else if ((ucRequestCount & 0x80) == 0x80) // if MSB is set we want to use ACK response, the number in bits 0-6 becomes the maximum number of retries
  283. {
  284. ucMaxAckRetries = ucRequestCount &= ~0x80; // clear the MSB, save the remaining number as max retries
  285. SendAckRequestMsg(SDM_PAGE16);
  286. }
  287. else // must be a regular broadcast request
  288. {
  289. // set a flag that will insert the page into the regular broadcast stream
  290. bTxPage16Flag = TRUE;
  291. bTxPage22Flag = FALSE; // new requests will overwrite the last request
  292. }
  293. }
  294. if ((ucRequestNum == SDM_PAGE22) && (bTxPage22 == TRUE) && (bP22Skip == FALSE)) // only process request if page is enabled and we are not skipping
  295. {
  296. ucRequestCount = pucRxBuffer_[5]; // save the number of times to re-transmit
  297. if (ucRequestCount == 0x80) // 0x80 is a special case where we want to resend ack messages until a response is recieved
  298. {
  299. ucMaxAckRetries = 127; // reset to default in case this was changed
  300. SendAckRequestMsg(SDM_PAGE22); // will automatically attempt to re-send until ack
  301. }
  302. else if ((ucRequestCount & 0x80) == 0x80) // if MSB is set we want to use ACK response, the number in bits 0-6 becomes the maximum number of retries
  303. {
  304. ucMaxAckRetries = ucRequestCount &= ~0x80; // clear the MSB, save the remaining number as max retries
  305. SendAckRequestMsg(SDM_PAGE22);
  306. }
  307. else // must be a regular broadcast request
  308. {
  309. // set a flag that will insert the page into the regular broadcast stream
  310. bTxPage22Flag = TRUE;
  311. bTxPage16Flag = FALSE; // new requests will overwrite the last request
  312. }
  313. }
  314. }
  315. }
  316. /**************************************************************************
  317. * SDMSensor::HandleRetransmit
  318. *
  319. * Retransmits request message, up to the maximum retransmission number,
  320. * ucMaxAckRetries, which defaults to 127, but is modified on request
  321. *
  322. * returns: TRUE if message was retransmitted
  323. * FALSE if maximum number of retransmissions was reached
  324. *
  325. **************************************************************************/
  326. BOOL SDMSensor::HandleRetransmit()
  327. {
  328. BOOL bSuccess = TRUE;
  329. if(ucMsgExpectingAck) // Message still expecting an ack
  330. {
  331. if(ucAckRetryCount++ < ucMaxAckRetries)
  332. SendAckRequestMsg(ucMsgExpectingAck);
  333. else
  334. bSuccess = FALSE;
  335. }
  336. return bSuccess;
  337. }
  338. /**************************************************************************
  339. * SDMSensor::SendAckRequestMsg
  340. *
  341. * Reply to the request message using an acknoledged message
  342. *
  343. * ucMsgCode_: message ID of the calibration message to send
  344. * Supported messages:
  345. * - Page 16 Request (Distance and Strides)
  346. * - Page 22 Request (Capabilities)
  347. *
  348. * returns: N/A
  349. *
  350. **************************************************************************/
  351. void SDMSensor::SendAckRequestMsg(UCHAR ucMsgCode_)
  352. {
  353. UCHAR aucAckBuffer[8] = {0,0,0,0,0,0,0,0};
  354. switch(ucMsgCode_)
  355. {
  356. case SDM_PAGE16: // Page 16 Request (Distance and Strides)
  357. aucAckBuffer[0] = SDM_PAGE16;
  358. aucAckBuffer[1] = ulStridesAccum & 0xFF; // Bytes 1-3 = Stride Count
  359. aucAckBuffer[2] = (ulStridesAccum >> 8) & 0xFF;
  360. aucAckBuffer[3] = (ulStridesAccum >> 16) & 0xFF;
  361. aucAckBuffer[4] = ulDistanceAccum & 0xFF; // Bytes 4-7 = Distance
  362. aucAckBuffer[5] = (ulDistanceAccum >> 8) & 0xFF;
  363. aucAckBuffer[6] = (ulDistanceAccum >> 16) & 0xFF;
  364. aucAckBuffer[7] = (ulDistanceAccum >> 24) & 0xFF;
  365. break;
  366. case SDM_PAGE22: // Page 22 Request (Capabilities)
  367. aucAckBuffer[0] = SDM_PAGE22;
  368. aucAckBuffer[1] = ucCapabFlags; // Capabilities Byte
  369. aucAckBuffer[2] = SDM_RESERVED; // Bytes 2-7 are reserved
  370. aucAckBuffer[3] = SDM_RESERVED;
  371. aucAckBuffer[4] = SDM_RESERVED;
  372. aucAckBuffer[5] = SDM_RESERVED;
  373. aucAckBuffer[6] = SDM_RESERVED;
  374. aucAckBuffer[7] = SDM_RESERVED;
  375. break;
  376. default:
  377. return; // Do not transmit if unsupported message code
  378. }
  379. // Send acknowledged message
  380. if(!ucMsgExpectingAck) // If this message is not a retransmission
  381. {
  382. ucAckRetryCount = 0; // Reset retransmission counter
  383. ucMsgExpectingAck = ucMsgCode_; // Set code to message for which an ACK wil be expected
  384. }
  385. requestAckMsg(aucAckBuffer); // Send message
  386. }
  387. /**************************************************************************
  388. * SDMSensor::onTimerTock
  389. *
  390. * Simulates a device event, updating simulator data based on this event
  391. * Modifications to the timer interval are applied immediately after this
  392. * at ANTChannel
  393. *
  394. * usEventTime_: current time (ms)
  395. *
  396. * returns: N/A
  397. *
  398. **************************************************************************/
  399. void SDMSensor::onTimerTock(USHORT eventTime)
  400. {
  401. USHORT tempOffset = 0; // Temporary variable to calculate sweeping intervals
  402. dwTimeLastEvent = GetTickCount(); // Get current time in ms (since system started)
  403. // Update stride count (required)
  404. ucStrideCount++;
  405. // Update Accumulative stride count once every two steps
  406. ulStridesAccum++;
  407. if (ulStridesAccum == 16777216) // 16777215 = 0xFFFFFF
  408. ulStridesAccum = 0;
  409. // Update event time
  410. ulRunTime += ulTimerInterval;
  411. usTime200 = (USHORT) ((ulRunTime%256000)/5); // ms -> 1/200s, rollover at 256 seconds
  412. // Update speed
  413. switch(ucSimDataType)
  414. {
  415. case SIM_FIXED:
  416. // Speed and cadence values do not change
  417. break;
  418. case SIM_SWEEP:
  419. // Value sweeps between max and min
  420. // The jump offset is calculated versus position against the max so it won't get stuck on low values for a long time and won't speed through high values too fast
  421. // Calculate next speed value
  422. tempOffset = usMaxSpeed256-usCurSpeed256;
  423. tempOffset = ((tempOffset & 0x600) >> 6) + ((tempOffset & 0x100) >>5) + ((tempOffset & 0x80) >>4)+0xF;
  424. if(bSweepAscending)
  425. usCurSpeed256 += tempOffset;
  426. else
  427. usCurSpeed256 -= tempOffset;
  428. // Ensure value is more than min and less than max
  429. if(usCurSpeed256 >= usMaxSpeed256)
  430. {
  431. usCurSpeed256 = usMaxSpeed256;
  432. bSweepAscending = FALSE;
  433. }
  434. if(usCurSpeed256 <= usMinSpeed256)
  435. {
  436. usCurSpeed256 = usMinSpeed256;
  437. bSweepAscending = TRUE;
  438. }
  439. // Update cadence according to new speed
  440. usCurCadence16 = SpeedToCadence(usCurSpeed256);
  441. break;
  442. default:
  443. break;
  444. }
  445. usSpeed256 = usCurSpeed256;
  446. usCadence16 = usCurCadence16;
  447. // Calculate distance
  448. usDistance16 += ((USHORT) ucStrideLength * 16)/100; // Stride length cm -> 1/16m
  449. // Update Accumulative distance
  450. ulDistanceAccum += ((ULONG) ucStrideLength * 256)/100; // Stride length cm -> 1/256m
  451. // Update the Calorie count (burn rate (K-kcal/m) * distance (1/16m))
  452. ulTempCalories += (ULONG)(ucCalorieRate*((ucStrideLength * 16)/100)); // K-kcal
  453. ucCalorieCount = (UCHAR)((ulTempCalories/1000)/16); // convert to UCHAR and kcal
  454. // Update timer interval (in ms)
  455. if(usCadence16)
  456. ulTimerInterval = (ULONG) 960000/usCadence16; // 60 seconds/revolutions per minute (60 * 1000 * 16)
  457. else
  458. ulTimerInterval = 600000; // Cadence & speed = 0, so timer interval is set to a very large value
  459. }
  460. /***************************************************************************
  461. * SDMSensor::UpdateDisplay
  462. *
  463. * Updates displayed simulator data on GUI
  464. *
  465. * returns: N/A
  466. *
  467. **************************************************************************/
  468. void SDMSensor::UpdateDisplay()
  469. {
  470. this->label_TransStrideCountDisplay->Text = ucStrideCount.ToString(); // Display stride count (required)
  471. this->label_P1StrideCountDisplay->Text = ucStrideCount.ToString();
  472. if(bUseTime)
  473. this->label_Trn_TimeDisplay->Text = ((double)usTime200/200).ToString(); // Display time in seconds
  474. else
  475. this->label_Trn_TimeDisplay->Text = "--"; // Unused
  476. if(bUseSpeed)
  477. this->label_TransInstSpeedDisplay->Text = ((double)(usSpeed256 & 0xFFF)/256).ToString(); // Display speed in m/s
  478. else
  479. this->label_TransInstSpeedDisplay->Text = "--"; // Unused
  480. if(bUseCadence && (bTxPage2 || bTxPage3))
  481. this->label_TransCadenceDisplay->Text = ((double)usCadence16/16).ToString(); // Display cadence in rpm
  482. else
  483. this->label_TransCadenceDisplay->Text = "--"; // Unused
  484. if(bUseDistance)
  485. {
  486. this->label_TransDistDisplay->Text = ((double)(usDistance16 & 0xFFF)/16).ToString(); // Display distance in m
  487. this->label_P1TotDistDisplay->Text = ((double)(usDistance16 & 0xFFF)/16).ToString();
  488. }
  489. else
  490. {
  491. this->label_TransDistDisplay->Text = "--"; // Unused
  492. this->label_P1TotDistDisplay->Text = "--";
  493. }
  494. if(bUseLatency)
  495. this->label_TransLatencyDisplay->Text = System::Convert::ToString((double)ucLatency32*1000/32); // Display latency in ms
  496. else
  497. this->label_TransLatencyDisplay->Text = "--";
  498. if(ucSimDataType == SIM_SWEEP)
  499. {
  500. if(eUnit == SDM_SPM) // Show sweeping values
  501. this->numericUpDown_Sim_CurOutput->Value = ConvertToInput(usCurCadence16); // Cadence
  502. else
  503. this->numericUpDown_Sim_CurOutput->Value = ConvertToInput(usCurSpeed256 & 0xFFF); // Speed
  504. }
  505. if(bTxPage3) // calories
  506. {
  507. this->label_P3CalDisplay->Text = ucCalorieCount.ToString();
  508. this->label_TransCalDisplay->Text = ucCalorieCount.ToString();
  509. }
  510. else
  511. {
  512. this->label_P3CalDisplay->Text = "--";
  513. this->label_TransCalDisplay->Text = "--";
  514. }
  515. if(bTxPage16)
  516. {
  517. this->label_P16StridesDisplay->Text = ulStridesAccum.ToString(); //mask off the top byte
  518. this->label_P16DistanceDisplay->Text = ulDistanceAccum.ToString();
  519. }
  520. else
  521. {
  522. this->label_P16StridesDisplay->Text = "--";
  523. this->label_P16DistanceDisplay->Text = "--";
  524. }
  525. }
  526. /**************************************************************************
  527. * SDMSensor::button_UpdateCommon_Click
  528. *
  529. * Validates and updates product information, from user input (GUI)
  530. *
  531. * returns: N/A
  532. *
  533. **************************************************************************/
  534. System::Void SDMSensor::button_UpdateCommon_Click(System::Object^ sender, System::EventArgs^ e)
  535. {
  536. label_ErrorCommon->Visible = false;
  537. label_ErrorCommon->Text = "Error: ";
  538. // Convert and catch failed conversions
  539. try{
  540. commonPages->usMfgID = System::Convert::ToUInt16(this->textBox_MfgID->Text);
  541. }
  542. catch(...){
  543. label_ErrorCommon->Text = System::String::Concat(label_ErrorCommon->Text, " MFID");
  544. label_ErrorCommon->Visible = true;
  545. }
  546. try{
  547. if(!this->checkBox_InvalidSerial->Checked)
  548. commonPages->ulSerialNum = System::Convert::ToUInt32(this->textBox_SerialNum->Text);
  549. else
  550. commonPages->ulSerialNum = 0xFFFFFFFF;
  551. }
  552. catch(...){
  553. label_ErrorCommon->Text = System::String::Concat(label_ErrorCommon->Text, " Ser#");
  554. label_ErrorCommon->Visible = true;
  555. }
  556. try{
  557. commonPages->ucHwVersion = System::Convert::ToByte(this->textBox_HwVersion->Text);
  558. }
  559. catch(...){
  560. label_ErrorCommon->Text = System::String::Concat(label_ErrorCommon->Text, " HWVr");
  561. label_ErrorCommon->Visible = true;
  562. }
  563. try{
  564. commonPages->ucSwVersion = System::Convert::ToByte(this->textBox_SwVersion->Text);
  565. }
  566. catch(...){
  567. label_ErrorCommon->Text = System::String::Concat(label_ErrorCommon->Text, " SWVr");
  568. label_ErrorCommon->Visible = true;
  569. }
  570. try{
  571. commonPages->usModelNum = System::Convert::ToUInt16(this->textBox_ModelNum->Text);
  572. }
  573. catch(...){
  574. label_ErrorCommon->Text = System::String::Concat(label_ErrorCommon->Text, " Mdl#");
  575. label_ErrorCommon->Visible = true;
  576. }
  577. }
  578. /**************************************************************************
  579. * SDMSensor::checkBox_EnableCommon_CheckedChanged
  580. *
  581. * Enable/disable transmission of common pages
  582. *
  583. * returns: N/A
  584. *
  585. **************************************************************************/
  586. System::Void SDMSensor::checkBox_EnableCommon_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  587. {
  588. // Enable disabling common data pages for testing backward compatibility of receivers
  589. // Do NOT use as a reference for new designs
  590. if(!checkBox_EnableCommon->Checked)
  591. {
  592. System::Windows::Forms::DialogResult result = MessageBox::Show(L"This option is available for backward compatibility testing.\nIt should not be used as a reference in the development of new sensors.", L"Warning", MessageBoxButtons::OKCancel);
  593. if( result == ::DialogResult::OK )
  594. {
  595. bTxCommon = FALSE;
  596. }
  597. else
  598. {
  599. bTxCommon = TRUE;
  600. checkBox_EnableCommon->Checked = TRUE;
  601. }
  602. }
  603. else
  604. {
  605. // Reenable common pages
  606. bTxCommon = TRUE;
  607. }
  608. }
  609. /**************************************************************************
  610. * SDMSensor::listBox_SimUnitsChanged
  611. *
  612. * Select simulation units
  613. *
  614. * returns: N/A
  615. *
  616. **************************************************************************/
  617. System::Void SDMSensor::listBox_SimUnitsChanged(System::Object^ sender, System::EventArgs^ e)
  618. {
  619. System::Decimal decMaxValue;
  620. eUnit = (SDMUnit) this->listBox_SimUnits->SelectedIndex;
  621. // Remove limit, so that conversion can take place successfully (changed from 1000 to 2000)
  622. this->numericUpDown_Sim_MaxOutput->Maximum = 2000;
  623. this->numericUpDown_Sim_MinOutput->Maximum = 2000;
  624. this->numericUpDown_Sim_CurOutput->Maximum = 2000;
  625. // Disable boxes momentarily, to keep values from being checked and modified again as they change
  626. this->numericUpDown_Sim_CurOutput->Enabled = FALSE;
  627. this->numericUpDown_Sim_MaxOutput->Enabled = FALSE;
  628. this->numericUpDown_Sim_MinOutput->Enabled = FALSE;
  629. // Update input data
  630. if(eUnit == SDM_SPM)
  631. {
  632. // Selected cadence (switching from speed to cadence)
  633. // Latest speed and cadence values are maintained, just displayed in proper unit
  634. // Display values
  635. this->numericUpDown_Sim_MinOutput->Value = ConvertToInput(usMinCadence16);
  636. this->numericUpDown_Sim_CurOutput->Value = ConvertToInput(usCurCadence16);
  637. this->numericUpDown_Sim_MaxOutput->Value = ConvertToInput(usMaxCadence16);
  638. decMaxValue = ConvertToInput(SDM_MAX_CADENCE16);
  639. //MessageBox::Show("Current Cadence = " + usCurCadence16.ToString() + " Current dexMaxValue = " + decMaxValue.ToString(), "Speed to Cadence", MessageBoxButtons::OK,MessageBoxIcon::Error, MessageBoxDefaultButton::Button1);
  640. }
  641. else
  642. {
  643. // Selected a speed unit (switching between speed units or from cadence)
  644. // Latest speed value is maintained, just displayed in the selected unit
  645. this->numericUpDown_Sim_MinOutput->Value = ConvertToInput(usMinSpeed256);
  646. this->numericUpDown_Sim_CurOutput->Value = ConvertToInput(usCurSpeed256);
  647. this->numericUpDown_Sim_MaxOutput->Value = ConvertToInput(usMaxSpeed256);
  648. decMaxValue = ConvertToInput(SDM_MAX_SPEED256);
  649. //MessageBox::Show("Current Cadence = " + usCurCadence16.ToString() + " Current dexMaxValue = " + decMaxValue.ToString(), "Cadence to Speed", MessageBoxButtons::OK,MessageBoxIcon::Error, MessageBoxDefaultButton::Button1);
  650. }
  651. // Adjust maximum value of input boxes to prevent overflow of the speed/cadence fields
  652. this->numericUpDown_Sim_MaxOutput->Maximum = decMaxValue + (System::Decimal) 0.001;
  653. this->numericUpDown_Sim_MinOutput->Maximum = decMaxValue + (System::Decimal) 0.001;
  654. this->numericUpDown_Sim_CurOutput->Maximum = decMaxValue + (System::Decimal) 0.001;
  655. // Enable input boxes again so that they can be modified
  656. if(ucSimDataType == SIM_SWEEP)
  657. {
  658. this->numericUpDown_Sim_MaxOutput->Enabled = TRUE;
  659. this->numericUpDown_Sim_MinOutput->Enabled = TRUE;
  660. }
  661. else
  662. {
  663. this->numericUpDown_Sim_CurOutput->Enabled = TRUE;
  664. }
  665. }
  666. /**************************************************************************
  667. * SDMSensor::numericUpDown_Sim_CurOutput_ValueChanged
  668. *
  669. * Updates and converts units of the current speed or cadence value, when it changes
  670. *
  671. * returns: N/A
  672. *
  673. **************************************************************************/
  674. System::Void SDMSensor::numericUpDown_Sim_CurOutput_ValueChanged(System::Object^ sender, System::EventArgs^ e)
  675. {
  676. // Ignore changes when sweeping
  677. if(this->numericUpDown_Sim_CurOutput->Enabled)
  678. {
  679. if(eUnit == SDM_SPM)
  680. {
  681. // User input is cadence
  682. // Update cadence value
  683. usCurCadence16 = ConvertFromInput(this->numericUpDown_Sim_CurOutput->Value);
  684. // Update speed from cadence
  685. usCurSpeed256 = CadenceToSpeed(usCurCadence16);
  686. }
  687. else
  688. {
  689. // User input is speed
  690. // Update speed value
  691. usCurSpeed256 = ConvertFromInput(this->numericUpDown_Sim_CurOutput->Value);
  692. // Update cadence from speed
  693. usCurCadence16 = SpeedToCadence(usCurSpeed256);
  694. }
  695. ForceUpdate();
  696. }
  697. }
  698. /**************************************************************************
  699. * SDMSensor::numericUpDown_Sim_MinMaxOutput_ValueChanged
  700. *
  701. * If the user has changed the min or max speed, validate that
  702. * minimum < current < maximum
  703. *
  704. * returns: N/A
  705. *
  706. **************************************************************************/
  707. System::Void SDMSensor::numericUpDown_Sim_MinMaxOutput_ValueChanged(System::Object^ sender, System::EventArgs^ e)
  708. {
  709. USHORT usPrevCadence16 = usCurCadence16;
  710. USHORT usPrevSpeed256 = usCurSpeed256;
  711. // Check only if user changes values
  712. if(this->numericUpDown_Sim_MinOutput->Enabled && this->numericUpDown_Sim_MaxOutput->Enabled)
  713. {
  714. // Check min<max if in min/max mode, and force min<cur<max
  715. if(this->numericUpDown_Sim_MinOutput->Value < this->numericUpDown_Sim_MaxOutput->Value)
  716. {
  717. if(eUnit == SDM_SPM)
  718. {
  719. // User input is cadence
  720. usMinCadence16 = ConvertFromInput(this->numericUpDown_Sim_MinOutput->Value);
  721. usMaxCadence16 = ConvertFromInput(this->numericUpDown_Sim_MaxOutput->Value);
  722. if(usCurCadence16 > usMaxCadence16)
  723. usCurCadence16 = usMaxCadence16;
  724. else if(usCurCadence16 < usMinCadence16)
  725. usCurCadence16= usMinCadence16;
  726. // Update speed
  727. usMinSpeed256 = CadenceToSpeed(usMinCadence16);
  728. usMaxSpeed256 = CadenceToSpeed(usMaxCadence16);
  729. if(usCurCadence16 != usPrevCadence16)
  730. {
  731. this->numericUpDown_Sim_CurOutput->Value = ConvertToInput(usCurCadence16);
  732. usCurSpeed256 = CadenceToSpeed(usCurCadence16);
  733. ForceUpdate();
  734. }
  735. }
  736. else
  737. {
  738. // User input is speed
  739. usMinSpeed256 = ConvertFromInput(this->numericUpDown_Sim_MinOutput->Value);
  740. usMaxSpeed256 = ConvertFromInput(this->numericUpDown_Sim_MaxOutput->Value);
  741. if(usCurSpeed256 > usMaxSpeed256)
  742. usCurSpeed256 = usMaxSpeed256;
  743. else if(usCurSpeed256 < usMinSpeed256)
  744. usCurSpeed256 = usMinSpeed256;
  745. // Update cadence
  746. usMinCadence16 = SpeedToCadence(usMinSpeed256);
  747. usMaxCadence16 = SpeedToCadence(usMaxSpeed256);
  748. if(usCurSpeed256 != usPrevSpeed256)
  749. {
  750. this->numericUpDown_Sim_CurOutput->Value = ConvertToInput(usCurSpeed256);
  751. usCurCadence16 = SpeedToCadence(usCurSpeed256);
  752. ForceUpdate();
  753. }
  754. }
  755. }
  756. else
  757. {
  758. // If the values were invalid, set numeric values to last valid values
  759. if(eUnit == SDM_SPM)
  760. {
  761. // Cadence
  762. this->numericUpDown_Sim_MinOutput->Value = ConvertToInput(usMinCadence16);
  763. this->numericUpDown_Sim_MaxOutput->Value = ConvertToInput(usMaxCadence16);
  764. }
  765. else
  766. {
  767. // Speed
  768. this->numericUpDown_Sim_MinOutput->Value = ConvertToInput(usMinSpeed256);
  769. this->numericUpDown_Sim_MaxOutput->Value = ConvertToInput(usMaxSpeed256);
  770. }
  771. }
  772. }
  773. }
  774. /**************************************************************************
  775. * SDMSensor::checkBox_Sweeping_CheckedChanged
  776. *
  777. * Select method to generate simulator data, from user input (GUI)
  778. *
  779. * returns: N/A
  780. *
  781. **************************************************************************/
  782. System::Void SDMSensor::checkBox_Sweeping_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  783. {
  784. this->numericUpDown_Sim_CurOutput->Enabled = !this->numericUpDown_Sim_CurOutput->Enabled;
  785. this->numericUpDown_Sim_MinOutput->Enabled = !this->numericUpDown_Sim_MinOutput->Enabled;
  786. this->numericUpDown_Sim_MaxOutput->Enabled = !this->numericUpDown_Sim_MaxOutput->Enabled;
  787. // If we allow the units to be changed while the transmission is sweeping it gets really messy
  788. this->listBox_SimUnits->Enabled = !this->listBox_SimUnits->Enabled;
  789. if(this->checkBox_Sweeping->Checked)
  790. {
  791. ucSimDataType = SIM_SWEEP;
  792. bSweepAscending = TRUE;
  793. }
  794. else
  795. {
  796. ucSimDataType = SIM_FIXED;
  797. }
  798. }
  799. /**************************************************************************
  800. * SDMSensor::button_UpdateDistance_Click
  801. *
  802. * Validates and updates cumulative distance, from user input (GUI)
  803. *
  804. * returns: N/A
  805. *
  806. **************************************************************************/
  807. System::Void SDMSensor::button_UpdateDistance_Click(System::Object^ sender, System::EventArgs^ e)
  808. {
  809. this->label_P1UpdateError->Visible = false;
  810. //convert and catch failed conversions
  811. try{
  812. usDistance16 = 16 * (USHORT) System::Convert::ToByte(this->textBox_P1TotDistChange->Text);
  813. this->label_P1TotDistDisplay->Text = this->textBox_P1TotDistChange->Text;
  814. }
  815. catch(...){
  816. this->label_P1UpdateError->Text = "Error: Dist";
  817. this->label_P1UpdateError->Visible = true;
  818. }
  819. }
  820. /**************************************************************************
  821. * SDMSensor::button_UpdateStrides_Click
  822. *
  823. * Validates and updates cumulative distance, from user input (GUI)
  824. *
  825. * returns: N/A
  826. *
  827. **************************************************************************/
  828. System::Void SDMSensor::button_UpdateStrides_Click(System::Object^ sender, System::EventArgs^ e)
  829. {
  830. this->label_P1UpdateError->Visible = false;
  831. //convert and catch failed conversions
  832. try{
  833. ucStrideCount = System::Convert::ToByte(this->textBox_P1StrideCountChange->Text);
  834. this->label_P1StrideCountDisplay->Text = this->textBox_P1StrideCountChange->Text;
  835. }
  836. catch(...){
  837. this->label_P1UpdateError->Text = "Error: Stride";
  838. this->label_P1UpdateError->Visible = true;
  839. }
  840. }
  841. /**************************************************************************
  842. * SDMSensor::checkBox_P1InstSpeed_CheckedChanged
  843. *
  844. * Enable/disable transmission of speed (optional field), and synchronizes
  845. * option in Page 1, 2, and 3
  846. *
  847. * returns: N/A
  848. *
  849. **************************************************************************/
  850. System::Void SDMSensor::checkBox_P1InstSpeed_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  851. {
  852. // Synchronize the three pages' inst speed options to avoid confusion
  853. this->checkBox_P2InstSpeed->Checked = this->checkBox_P1InstSpeed->Checked;
  854. this->checkBox_P3InstSpeed->Checked = this->checkBox_P1InstSpeed->Checked;
  855. bUseSpeed = this->checkBox_P1InstSpeed->Checked;
  856. sCapabFlags.ucSpeed = (UCHAR) this->checkBox_P1InstSpeed->Checked;
  857. if (sCapabFlags.ucSpeed == 1) // if latency is selected
  858. {
  859. ucCapabFlags |= SDM_SPEED_MASK; // set the bit to 1
  860. this->label_P22Speed->ForeColor = System::Drawing::Color::Green;
  861. }
  862. else // distance not selected
  863. {
  864. ucCapabFlags &= ~SDM_SPEED_MASK; // set the bit to 0
  865. this->label_P22Speed->ForeColor = System::Drawing::Color::Red;
  866. }
  867. }
  868. /**************************************************************************
  869. * SDMSensor::checkBox_P2InstSpeed_CheckedChanged
  870. *
  871. * Enable/disable transmission of speed (optional field), and synchronizes
  872. * option in Page 1, 2, and 3
  873. *
  874. * returns: N/A
  875. *
  876. **************************************************************************/
  877. System::Void SDMSensor::checkBox_P2InstSpeed_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  878. {
  879. // Synchronize the three pages' inst speed options to avoid confusion
  880. this->checkBox_P1InstSpeed->Checked = this->checkBox_P2InstSpeed->Checked;
  881. this->checkBox_P3InstSpeed->Checked = this->checkBox_P2InstSpeed->Checked;
  882. bUseSpeed = this->checkBox_P2InstSpeed->Checked;
  883. sCapabFlags.ucSpeed = (UCHAR) this->checkBox_P2InstSpeed->Checked;
  884. if (sCapabFlags.ucSpeed == 1) // if latency is selected
  885. {
  886. ucCapabFlags |= SDM_SPEED_MASK; // set the bit to 1
  887. this->label_P22Speed->ForeColor = System::Drawing::Color::Green;
  888. }
  889. else // distance not selected
  890. {
  891. ucCapabFlags &= ~SDM_SPEED_MASK; // set the bit to 0
  892. this->label_P22Speed->ForeColor = System::Drawing::Color::Red;
  893. }
  894. }
  895. /**************************************************************************
  896. * SDMSensor::checkBox_P3InstSpeed_CheckedChanged
  897. *
  898. * Enable/disable transmission of speed (optional field), and synchronizes
  899. * option in Page 1, 2, and 3
  900. *
  901. * returns: N/A
  902. *
  903. **************************************************************************/
  904. System::Void SDMSensor::checkBox_P3InstSpeed_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  905. {
  906. // Synchronize the three pages' inst speed options to avoid confusion
  907. this->checkBox_P1InstSpeed->Checked = this->checkBox_P3InstSpeed->Checked;
  908. this->checkBox_P2InstSpeed->Checked = this->checkBox_P3InstSpeed->Checked;
  909. bUseSpeed = this->checkBox_P3InstSpeed->Checked;
  910. sCapabFlags.ucSpeed = (UCHAR) this->checkBox_P3InstSpeed->Checked;
  911. if (sCapabFlags.ucSpeed == 1) // if latency is selected
  912. {
  913. ucCapabFlags |= SDM_SPEED_MASK; // set the bit to 1
  914. this->label_P22Speed->ForeColor = System::Drawing::Color::Green;
  915. }
  916. else // distance not selected
  917. {
  918. ucCapabFlags &= ~SDM_SPEED_MASK; // set the bit to 0
  919. this->label_P22Speed->ForeColor = System::Drawing::Color::Red;
  920. }
  921. }
  922. /**************************************************************************
  923. * SDMSensor::checkBox_P1Time_CheckedChanged
  924. *
  925. * Enable/disable transmission of time in Page 1 (optional field)
  926. *
  927. * returns: N/A
  928. *
  929. **************************************************************************/
  930. System::Void SDMSensor::checkBox_P1Time_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  931. {
  932. bUseTime = !bUseTime;
  933. sCapabFlags.ucTime = (UCHAR) this->checkBox_P1Time->Checked;
  934. if (sCapabFlags.ucTime == 1) // if time is selected
  935. {
  936. ucCapabFlags |= SDM_TIME_MASK; // set the bit to 1
  937. this->label_P22Time->ForeColor = System::Drawing::Color::Green;
  938. }
  939. else // time not selected
  940. {
  941. ucCapabFlags &= ~SDM_TIME_MASK; // set the bit to 0
  942. this->label_P22Time->ForeColor = System::Drawing::Color::Red;
  943. }
  944. }
  945. /**************************************************************************
  946. * SDMSensor::checkBox_P1Latency_CheckedChanged
  947. *
  948. * Enable/disable transmission of latency in Page 1 (optional field)
  949. *
  950. * returns: N/A
  951. *
  952. **************************************************************************/
  953. System::Void SDMSensor::checkBox_P1Latency_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  954. {
  955. bUseLatency = !bUseLatency;
  956. sCapabFlags.ucLatency = (UCHAR) this->checkBox_P1Latency->Checked;
  957. if (sCapabFlags.ucLatency == 1) // if latency is selected
  958. {
  959. ucCapabFlags |= SDM_LATENCY_MASK; // set the bit to 1
  960. this->label_P22Latency->ForeColor = System::Drawing::Color::Green;
  961. }
  962. else // distance not selected
  963. {
  964. ucCapabFlags &= ~SDM_LATENCY_MASK; // set the bit to 0
  965. this->label_P22Latency->ForeColor = System::Drawing::Color::Red;
  966. }
  967. }
  968. /**************************************************************************
  969. * SDMSensor::checkBox_P1Distance_CheckedChanged
  970. *
  971. * Enable/disable transmission of distance in Page 1 (optional field)
  972. *
  973. * returns: N/A
  974. *
  975. **************************************************************************/
  976. System::Void SDMSensor::checkBox_P1Distance_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  977. {
  978. bUseDistance = !bUseDistance;
  979. sCapabFlags.ucDistance = (UCHAR) this->checkBox_P1Distance->Checked;
  980. if (sCapabFlags.ucDistance == 1) // if distance is selected
  981. {
  982. ucCapabFlags |= SDM_DISTANCE_MASK; // set the bit to 1
  983. this->label_P22Distance->ForeColor = System::Drawing::Color::Green;
  984. }
  985. else // distance not selected
  986. {
  987. ucCapabFlags &= ~SDM_DISTANCE_MASK; // set the bit to 0
  988. this->label_P22Distance->ForeColor = System::Drawing::Color::Red;
  989. }
  990. }
  991. /**************************************************************************
  992. * SDMSensor::checkBox_P2Cadence_CheckedChanged
  993. *
  994. * Enable/disable transmission of cadence in Page 2 (optional field)
  995. *
  996. * returns: N/A
  997. *
  998. **************************************************************************/
  999. System::Void SDMSensor::checkBox_P2Cadence_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  1000. {
  1001. this->checkBox_P3Cadence->Checked = this->checkBox_P2Cadence->Checked;
  1002. bUseCadence = this->checkBox_P2Cadence->Checked;
  1003. //bUseCadence = !bUseCadence;
  1004. sCapabFlags.ucCadence = (UCHAR) this->checkBox_P2Cadence->Checked;
  1005. if (sCapabFlags.ucCadence == 1) // if latency is selected
  1006. {
  1007. ucCapabFlags |= SDM_CADENCE_MASK; // set the bit to 1
  1008. this->label_P22Cadence->ForeColor = System::Drawing::Color::Green;
  1009. }
  1010. else // distance not selected
  1011. {
  1012. ucCapabFlags &= ~SDM_CADENCE_MASK; // set the bit to 0
  1013. this->label_P22Cadence->ForeColor = System::Drawing::Color::Red;
  1014. }
  1015. }
  1016. /**************************************************************************
  1017. * SDMSensor::checkBox_P3Cadence_CheckedChanged
  1018. *
  1019. * Enable/disable transmission of cadence in Page 3 (optional field)
  1020. *
  1021. * returns: N/A
  1022. *
  1023. **************************************************************************/
  1024. System::Void SDMSensor::checkBox_P3Cadence_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  1025. {
  1026. this->checkBox_P2Cadence->Checked = this->checkBox_P3Cadence->Checked;
  1027. bUseCadence = this->checkBox_P3Cadence->Checked;
  1028. //bUseCadence = !bUseCadence;
  1029. sCapabFlags.ucCadence = (UCHAR) this->checkBox_P3Cadence->Checked;
  1030. if (sCapabFlags.ucCadence == 1) // if latency is selected
  1031. {
  1032. ucCapabFlags |= SDM_CADENCE_MASK; // set the bit to 1
  1033. this->label_P22Cadence->ForeColor = System::Drawing::Color::Green;
  1034. }
  1035. else // distance not selected
  1036. {
  1037. ucCapabFlags &= ~SDM_CADENCE_MASK; // set the bit to 0
  1038. this->label_P22Cadence->ForeColor = System::Drawing::Color::Red;
  1039. }
  1040. }
  1041. /**************************************************************************
  1042. * SDMSensor::numericUpDown_Sim_StrideLength_ValueChanged
  1043. *
  1044. * Updates stride length when modified in UI
  1045. *
  1046. * returns: N/A
  1047. *
  1048. **************************************************************************/
  1049. System::Void SDMSensor::numericUpDown_Sim_StrideLength_ValueChanged(System::Object^ sender, System::EventArgs^ e)
  1050. {
  1051. ucStrideLength = System::Convert::ToByte(this->numericUpDown_Sim_StrideLength->Value);
  1052. usMaxSpeed256 = CadenceToSpeed(usMaxCadence16); // update the speed since it is based on stride length
  1053. usMinSpeed256 = CadenceToSpeed(usMinCadence16);
  1054. usCurSpeed256 = CadenceToSpeed(usCurCadence16);
  1055. }
  1056. /**************************************************************************
  1057. * SDMSensor::numericUpDown_Sim_BurnRate_ValueChanged
  1058. *
  1059. * Updates Calories Burn Rate when modified in UI
  1060. *
  1061. * returns: N/A
  1062. *
  1063. **************************************************************************/
  1064. System::Void SDMSensor::numericUpDown_Sim_BurnRate_ValueChanged(System::Object^ sender, System::EventArgs^ e)
  1065. {
  1066. ucCalorieRate = System::Convert::ToByte(this->numericUpDown_Sim_BurnRate->Value);
  1067. }
  1068. /**************************************************************************
  1069. * SDMSensor::listBox_P2Location_SelectedIndexChanged
  1070. *
  1071. * Updates location field in status flags
  1072. *
  1073. * returns: N/A
  1074. *
  1075. **************************************************************************/
  1076. System::Void SDMSensor::listBox_P2Location_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)
  1077. {
  1078. sStatusFlags.ucLocation = (UCHAR) this->listBox_P2Location->SelectedIndex;
  1079. ucStatusFlags &= ~SDM_LOCATION_MASK; // Clear previous status
  1080. ucStatusFlags |= (sStatusFlags.ucLocation << SDM_LOCATION_SHIFT); // Set updated status
  1081. }
  1082. /**************************************************************************
  1083. * SDMSensor::listBox_P2Battery_SelectedIndexChanged
  1084. *
  1085. * Updates battery status field in status flags
  1086. *
  1087. * returns: N/A
  1088. *
  1089. **************************************************************************/
  1090. System::Void SDMSensor::listBox_P2Battery_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)
  1091. {
  1092. sStatusFlags.ucBatteryStatus = (UCHAR) this->listBox_P2Battery->SelectedIndex;
  1093. ucStatusFlags &= ~SDM_BAT_MASK; // Clear previous status
  1094. ucStatusFlags |= (sStatusFlags.ucBatteryStatus << SDM_BAT_SHIFT); // Set updated status
  1095. }
  1096. /**************************************************************************
  1097. * SDMSensor::listBox_P2Health_SelectedIndexChanged
  1098. *
  1099. * Updates health field in status flags
  1100. *
  1101. * returns: N/A
  1102. *
  1103. **************************************************************************/
  1104. System::Void SDMSensor::listBox_P2Health_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)
  1105. {
  1106. sStatusFlags.ucHealth = (UCHAR) this->listBox_P2Health->SelectedIndex;
  1107. ucStatusFlags &= ~SDM_HEALTH_MASK; // Clear previous status
  1108. ucStatusFlags |= (sStatusFlags.ucHealth << SDM_HEALTH_SHIFT); // Set updated status
  1109. }
  1110. /**************************************************************************
  1111. * SDMSensor::listBox_P2Use_SelectedIndexChanged
  1112. *
  1113. * Updates use state field in status flags
  1114. *
  1115. * returns: N/A
  1116. *
  1117. **************************************************************************/
  1118. System::Void SDMSensor::listBox_P2Use_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)
  1119. {
  1120. sStatusFlags.ucUseState = (UCHAR) this->listBox_P2Use->SelectedIndex;
  1121. ucStatusFlags &= ~SDM_STATE_MASK; // Clear previous status
  1122. ucStatusFlags |= (sStatusFlags.ucUseState << SDM_STATE_SHIFT); // Set updated status
  1123. }
  1124. /**************************************************************************
  1125. * SDMSensor::listBox_P3Location_SelectedIndexChanged
  1126. *
  1127. * Updates location field in status flags
  1128. *
  1129. * returns: N/A
  1130. *
  1131. **************************************************************************/
  1132. System::Void SDMSensor::listBox_P3Location_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)
  1133. {
  1134. sStatusFlags.ucLocation = (UCHAR) this->listBox_P3Location->SelectedIndex;
  1135. ucStatusFlags &= ~SDM_LOCATION_MASK; // Clear previous status
  1136. ucStatusFlags |= (sStatusFlags.ucLocation << SDM_LOCATION_SHIFT); // Set updated status
  1137. }
  1138. /**************************************************************************
  1139. * SDMSensor::listBox_P3Battery_SelectedIndexChanged
  1140. *
  1141. * Updates battery status field in status flags
  1142. *
  1143. * returns: N/A
  1144. *
  1145. **************************************************************************/
  1146. System::Void SDMSensor::listBox_P3Battery_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)
  1147. {
  1148. sStatusFlags.ucBatteryStatus = (UCHAR) this->listBox_P3Battery->SelectedIndex;
  1149. ucStatusFlags &= ~SDM_BAT_MASK; // Clear previous status
  1150. ucStatusFlags |= (sStatusFlags.ucBatteryStatus << SDM_BAT_SHIFT); // Set updated status
  1151. }
  1152. /**************************************************************************
  1153. * SDMSensor::listBox_P3Health_SelectedIndexChanged
  1154. *
  1155. * Updates health field in status flags
  1156. *
  1157. * returns: N/A
  1158. *
  1159. **************************************************************************/
  1160. System::Void SDMSensor::listBox_P3Health_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)
  1161. {
  1162. sStatusFlags.ucHealth = (UCHAR) this->listBox_P3Health->SelectedIndex;
  1163. ucStatusFlags &= ~SDM_HEALTH_MASK; // Clear previous status
  1164. ucStatusFlags |= (sStatusFlags.ucHealth << SDM_HEALTH_SHIFT); // Set updated status
  1165. }
  1166. /**************************************************************************
  1167. * SDMSensor::listBox_P3Use_SelectedIndexChanged
  1168. *
  1169. * Updates use state field in status flags
  1170. *
  1171. * returns: N/A
  1172. *
  1173. **************************************************************************/
  1174. System::Void SDMSensor::listBox_P3Use_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)
  1175. {
  1176. sStatusFlags.ucUseState = (UCHAR) this->listBox_P3Use->SelectedIndex;
  1177. ucStatusFlags &= ~SDM_STATE_MASK; // Clear previous status
  1178. ucStatusFlags |= (sStatusFlags.ucUseState << SDM_STATE_SHIFT); // Set updated status
  1179. }
  1180. /**************************************************************************
  1181. * SDMSensor::ConvertFromInput
  1182. *
  1183. * Converts from user selected units for speed and cadence to units
  1184. * defined in the device profile
  1185. *
  1186. * decValue_: Value to convert
  1187. *
  1188. * returns: speed (1/256 s) or cadence (strides/min)
  1189. *
  1190. **************************************************************************/
  1191. USHORT SDMSensor::ConvertFromInput(System::Decimal decValue_)
  1192. {
  1193. USHORT usOutput;
  1194. switch(eUnit)
  1195. {
  1196. case SDM_MS:
  1197. usOutput = (USHORT) (256 * decValue_); // Convert speed from m/s to 1/256 m/s
  1198. break;
  1199. case SDM_KPH:
  1200. usOutput = (USHORT) (2560 * decValue_/36); // Convert speed from km/h to 1/256 m/s
  1201. break;
  1202. case SDM_MPH:
  1203. usOutput = (USHORT) (411991 * decValue_/3600); // Convert speed from mi/h to 1/256 m/s
  1204. break;
  1205. case SDM_SPM:
  1206. usOutput = (USHORT) (16 * decValue_); // Convert cadence from spm to 1/16 spm
  1207. break;
  1208. default:
  1209. usOutput = SDM_UNUSED;
  1210. break;
  1211. }
  1212. return usOutput;
  1213. }
  1214. /**************************************************************************
  1215. * SDMSensor::ConvertToInput
  1216. *
  1217. * Converts from units defined in device profile for speed and cadence
  1218. * to the user selected units for display purposes (on text box)
  1219. *
  1220. * usValue_: Value to convert
  1221. *
  1222. * returns: speed or cadence, in selected unit
  1223. *
  1224. **************************************************************************/
  1225. System::Decimal SDMSensor::ConvertToInput(USHORT usValue_)
  1226. {
  1227. System::Decimal decInput;
  1228. switch(eUnit)
  1229. {
  1230. case SDM_MS:
  1231. decInput = System::Convert::ToDecimal(usValue_ /256.0); // Convert speed from 1/256 m/s to m/s
  1232. break;
  1233. case SDM_KPH:
  1234. decInput = System::Convert::ToDecimal(usValue_ * 36/2560.0); // Convert speed from 1/256 m/s to km/h
  1235. break;
  1236. case SDM_MPH:
  1237. decInput = System::Convert::ToDecimal(usValue_ * 3600/411991.0); // Convert speed from 1/256 m/s to mi/h
  1238. break;
  1239. case SDM_SPM:
  1240. decInput = System::Convert::ToDecimal(usValue_/16.0); // Convert cadence from 1/16 spm to spm
  1241. break;
  1242. default:
  1243. decInput = System::Convert::ToDecimal(SDM_UNUSED);
  1244. break;
  1245. }
  1246. return decInput;
  1247. }
  1248. /**************************************************************************
  1249. * SDMSensor::CadenceToSpeed
  1250. *
  1251. * Converts from cadence to speed
  1252. *
  1253. * usCadence16_: Cadence (1/16 rpm)
  1254. *
  1255. * returns: Speed (1/256 m/s)
  1256. *
  1257. **************************************************************************/
  1258. USHORT SDMSensor::CadenceToSpeed(USHORT usCadence16_)
  1259. {
  1260. return (USHORT) (16 * (ULONG) ucStrideLength * (ULONG) usCadence16_ / (ULONG) 6000); // 1/16 spm -> 1/256 m/s (stride length is in cm)
  1261. }
  1262. /**************************************************************************
  1263. * SDMSensor::SpeedToCadence
  1264. *
  1265. * Converts from cadence to speed
  1266. *
  1267. * usCadence16_: Cadence (1/16 rpm)
  1268. *
  1269. * returns: Speed (1/256 m/s)
  1270. *
  1271. **************************************************************************/
  1272. USHORT SDMSensor::SpeedToCadence(USHORT usSpeed256_)
  1273. {
  1274. return (USHORT) ((ULONG) 6000 * usSpeed256_ / (16 * (ULONG) ucStrideLength)); // 1/256 m/s -> 1/16 spm (stride length is in cm)
  1275. }
  1276. /**************************************************************************
  1277. * SDMSensor::ForceUpdate
  1278. *
  1279. * Causes a timer event, to force the simulator to update all calculations
  1280. *
  1281. * returns: N/A
  1282. *
  1283. **************************************************************************/
  1284. void SDMSensor::ForceUpdate()
  1285. {
  1286. timerHandle->Interval = 250;
  1287. }
  1288. /**************************************************************************
  1289. * SDMSensor::checkBox_Page2_CheckedChanged
  1290. *
  1291. * Select whether to include Page 2 in transmission (Page 1 is always on)
  1292. *
  1293. * returns: N/A
  1294. *
  1295. **************************************************************************/
  1296. System::Void SDMSensor::checkBox_Page2_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  1297. {
  1298. if(this->checkBox_Page2->Checked) // If checked, Enable Page 2, Disable Page 3
  1299. {
  1300. Page2_Enable();
  1301. Page3_Disable();
  1302. this->checkBox_Page3->Checked = FALSE;
  1303. }
  1304. else // If not checked, Disable Page 2
  1305. {
  1306. Page2_Disable();
  1307. }
  1308. }
  1309. /**************************************************************************
  1310. * SDMSensor::checkBox_Page3_CheckedChanged
  1311. *
  1312. * Select whether to include Page 3 in transmission
  1313. *
  1314. * returns: N/A
  1315. *
  1316. **************************************************************************/
  1317. System::Void SDMSensor::checkBox_Page3_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  1318. {
  1319. // Calories capability dependent on whether Page 3 is on, so store that capability
  1320. sCapabFlags.ucCalories = (UCHAR) this->checkBox_Page3->Checked;
  1321. if(this->checkBox_Page3->Checked) // If checked, Enable Page 3, Disable Page 2
  1322. {
  1323. Page3_Enable();
  1324. Page2_Disable();
  1325. this->checkBox_Page2->Checked = FALSE;
  1326. ucCapabFlags |= SDM_CALORIES_MASK; // set the bit to 1
  1327. this->label_P22Calories->ForeColor = System::Drawing::Color::Green;
  1328. }
  1329. else // If not checked, Disable Page 3
  1330. {
  1331. Page3_Disable();
  1332. ucCapabFlags &= ~SDM_CALORIES_MASK; // set the bit to 0
  1333. this->label_P22Calories->ForeColor = System::Drawing::Color::Red;
  1334. }
  1335. }
  1336. /**************************************************************************
  1337. * SDMSensor::Page2_Enable
  1338. *
  1339. * Enables Page 2 GUI
  1340. *
  1341. * returns: N/A
  1342. *
  1343. **************************************************************************/
  1344. void SDMSensor::Page2_Enable()
  1345. {
  1346. this->listBox_P2Battery->Enabled = TRUE;
  1347. this->listBox_P2Health->Enabled = TRUE;
  1348. this->listBox_P2Location->Enabled = TRUE;
  1349. this->listBox_P2Use->Enabled = TRUE;
  1350. this->checkBox_P2Cadence->Enabled = TRUE;
  1351. this->checkBox_P2InstSpeed->Enabled = TRUE;
  1352. // synchronize Instant Speed and Flags in case anything was changed while the page was disabled
  1353. this->checkBox_P2InstSpeed->Checked = this->checkBox_P1InstSpeed->Checked;
  1354. this->listBox_P2Location->SelectedIndex = (int) sStatusFlags.ucLocation;
  1355. this->listBox_P2Battery->SelectedIndex = (int) sStatusFlags.ucBatteryStatus;
  1356. this->listBox_P2Health->SelectedIndex = (int) sStatusFlags.ucHealth;
  1357. this->listBox_P2Use->SelectedIndex = (int) sStatusFlags.ucUseState;
  1358. bTxPage2 = TRUE;
  1359. }
  1360. /**************************************************************************
  1361. * SDMSensor::Page2_Disable
  1362. *
  1363. * Disables Page 2 GUI
  1364. *
  1365. * returns: N/A
  1366. *
  1367. **************************************************************************/
  1368. void SDMSensor::Page2_Disable()
  1369. {
  1370. //this->label_TransCadence->ForeColor = System::Drawing::SystemColors::GrayText;
  1371. //this->label_TransCadenceDisplay->ForeColor = System::Drawing::SystemColors::GrayText;
  1372. this->listBox_P2Battery->Enabled = FALSE;
  1373. this->listBox_P2Health->Enabled = FALSE;
  1374. this->listBox_P2Location->Enabled = FALSE;
  1375. this->listBox_P2Use->Enabled = FALSE;
  1376. this->checkBox_P2Cadence->Enabled = FALSE;
  1377. this->checkBox_P2InstSpeed->Enabled = FALSE;
  1378. bTxPage2 = FALSE;
  1379. }
  1380. /**************************************************************************
  1381. * SDMSensor::Page3_Enable
  1382. *
  1383. * Enables Page 3 GUI
  1384. *
  1385. * returns: N/A
  1386. *
  1387. **************************************************************************/
  1388. void SDMSensor::Page3_Enable()
  1389. {
  1390. this->listBox_P3Battery->Enabled = TRUE;
  1391. this->listBox_P3Health->Enabled = TRUE;
  1392. this->listBox_P3Location->Enabled = TRUE;
  1393. this->listBox_P3Use->Enabled = TRUE;
  1394. this->checkBox_P3Cadence->Enabled = TRUE;
  1395. this->checkBox_P3InstSpeed->Enabled = TRUE;
  1396. this->textBox_P3Calories->Enabled = TRUE;
  1397. this->button_P3UpdateCalories->Enabled = TRUE;
  1398. this->label_P3CalDisplay->Enabled = TRUE;
  1399. // synchronize Instant Speed and Flags in case anything was changed while the page was disabled
  1400. this->checkBox_P3InstSpeed->Checked = this->checkBox_P1InstSpeed->Checked;
  1401. this->listBox_P3Location->SelectedIndex = (int) sStatusFlags.ucLocation;
  1402. this->listBox_P3Battery->SelectedIndex = (int) sStatusFlags.ucBatteryStatus;
  1403. this->listBox_P3Health->SelectedIndex = (int) sStatusFlags.ucHealth;
  1404. this->listBox_P3Use->SelectedIndex = (int) sStatusFlags.ucUseState;
  1405. bTxPage3 = TRUE;
  1406. }
  1407. /**************************************************************************
  1408. * SDMSensor::Page3_Disable
  1409. *
  1410. * Disables Page 3 GUI
  1411. *
  1412. * returns: N/A
  1413. *
  1414. **************************************************************************/
  1415. void SDMSensor::Page3_Disable()
  1416. {
  1417. this->listBox_P3Battery->Enabled = FALSE;
  1418. this->listBox_P3Health->Enabled = FALSE;
  1419. this->listBox_P3Location->Enabled = FALSE;
  1420. this->listBox_P3Use->Enabled = FALSE;
  1421. this->checkBox_P3Cadence->Enabled = FALSE;
  1422. this->checkBox_P3InstSpeed->Enabled = FALSE;
  1423. this->textBox_P3Calories->Enabled = FALSE;
  1424. this->button_P3UpdateCalories->Enabled = FALSE;
  1425. this->label_P3CalDisplay->Enabled = FALSE;
  1426. bTxPage3 = FALSE;
  1427. }
  1428. /**************************************************************************
  1429. * SDMSensor::checkBox_P22Enabled_CheckedChanged
  1430. *
  1431. * Select whether to allow Pagge 22 to be requestable
  1432. *
  1433. * returns: N/A
  1434. *
  1435. **************************************************************************/
  1436. System::Void SDMSensor::checkBox_P22Enabled_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  1437. {
  1438. if(this->checkBox_P22Enabled->Checked) // If checked, Enable
  1439. {
  1440. bTxPage22 = TRUE;
  1441. // disable UI
  1442. this->checkBox_P22Ignore->Enabled = TRUE;
  1443. this->groupBox_P22Supported->Enabled = TRUE;
  1444. }
  1445. else // If not checked, Disable
  1446. {
  1447. bTxPage22 = FALSE;
  1448. // enable UI
  1449. this->checkBox_P22Ignore->Enabled = FALSE;
  1450. this->groupBox_P22Supported->Enabled = FALSE;
  1451. }
  1452. }
  1453. /**************************************************************************
  1454. * SDMSensor::checkBox_P22Ignore_CheckedChanged
  1455. *
  1456. * The device profile allows for sensors to ignore a Page 22 (Capabilities) Request
  1457. * if the device supports all fields. This allows the user to either use this feature or not.
  1458. *
  1459. * returns: N/A
  1460. *
  1461. **************************************************************************/
  1462. System::Void SDMSensor::checkBox_P22Ignore_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  1463. {
  1464. if(this->checkBox_P22Ignore->Checked) // If checked, Enable
  1465. {
  1466. bP22Ignore = TRUE;
  1467. }
  1468. else // If not checked, Disable
  1469. {
  1470. bP22Ignore = FALSE;
  1471. }
  1472. }
  1473. /**************************************************************************
  1474. * SDMSensor::checkBox_P16Enabled_CheckedChanged
  1475. *
  1476. * Select whether to allow Pagge 16 to be requestable
  1477. *
  1478. * returns: N/A
  1479. *
  1480. **************************************************************************/
  1481. System::Void SDMSensor::checkBox_P16Enabled_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  1482. {
  1483. if(this->checkBox_P16Enabled->Checked) // If checked, Enable
  1484. {
  1485. bTxPage16 = TRUE;
  1486. // disable UI
  1487. this->label_P16Strides->Enabled = TRUE;
  1488. this->label_P16Distance->Enabled = TRUE;
  1489. this->label_P16StridesDisplay->Enabled = TRUE;
  1490. this->label_P16DistanceDisplay->Enabled = TRUE;
  1491. this->label_P16_UnitsDist->Enabled = TRUE;
  1492. this->button_P16UpdateStrides->Enabled = TRUE;
  1493. this->button_P16UpdateDistance->Enabled = TRUE;
  1494. this->textBox_P16StridesDisplayChange->Enabled = TRUE;
  1495. this->textBox_P16DistDisplayChange->Enabled = TRUE;
  1496. }
  1497. else // If not checked, Disable
  1498. {
  1499. bTxPage16 = FALSE;
  1500. // enable UI
  1501. this->label_P16Strides->Enabled = FALSE;
  1502. this->label_P16Distance->Enabled = FALSE;
  1503. this->label_P16StridesDisplay->Enabled = FALSE;
  1504. this->label_P16DistanceDisplay->Enabled = FALSE;
  1505. this->label_P16_UnitsDist->Enabled = FALSE;
  1506. this->button_P16UpdateStrides->Enabled = FALSE;
  1507. this->button_P16UpdateDistance->Enabled = FALSE;
  1508. this->textBox_P16StridesDisplayChange->Enabled = FALSE;
  1509. this->textBox_P16DistDisplayChange->Enabled = FALSE;
  1510. }
  1511. }
  1512. /**************************************************************************
  1513. * SDMSensor::button_P3UpdateCalories_Click
  1514. *
  1515. * Validates and updates cumulative Calories on Page 3, from user input (GUI)
  1516. *
  1517. * returns: N/A
  1518. *
  1519. **************************************************************************/
  1520. System::Void SDMSensor::button_P3UpdateCalories_Click(System::Object^ sender, System::EventArgs^ e)
  1521. {
  1522. //convert and catch failed conversions
  1523. try{
  1524. ucCalorieCount = System::Convert::ToByte(this->textBox_P3Calories->Text);
  1525. this->label_P3CalDisplay->Text = this->textBox_P3Calories->Text;
  1526. ulTempCalories = ucCalorieCount * 1000 * 16;
  1527. }
  1528. catch(...){
  1529. MessageBox::Show("Invalid Input. Please enter a value from 0 to 255.", "Error", MessageBoxButtons::OK,MessageBoxIcon::Error, MessageBoxDefaultButton::Button1);
  1530. }
  1531. }
  1532. /**************************************************************************
  1533. * SDMSensor::button_P16UpdateStrides_Click
  1534. *
  1535. * Validates and updates accumulated strides, from user input (GUI)
  1536. *
  1537. * returns: N/A
  1538. *
  1539. **************************************************************************/
  1540. System::Void SDMSensor::button_P16UpdateStrides_Click(System::Object^ sender, System::EventArgs^ e)
  1541. {
  1542. this->label_P16UpdateError->Visible = false;
  1543. //convert and catch failed conversions
  1544. try{
  1545. ulStridesAccum = System::Convert::ToUInt32(this->textBox_P16StridesDisplayChange->Text);
  1546. if (ulStridesAccum >= 16777216)
  1547. {
  1548. ulStridesAccum = 16777215;
  1549. this->label_P16StridesDisplay->Text = "16777215";
  1550. }
  1551. else
  1552. this->label_P16StridesDisplay->Text = this->textBox_P16StridesDisplayChange->Text;
  1553. }
  1554. catch(...){
  1555. this->label_P16UpdateError->Text = "Error: Stride";
  1556. this->label_P16UpdateError->Visible = true;
  1557. }
  1558. }
  1559. /**************************************************************************
  1560. * SDMSensor::button_P16UpdateDistance_Click
  1561. *
  1562. * Validates and updates accumlated distance, from user input (GUI)
  1563. *
  1564. * returns: N/A
  1565. *
  1566. **************************************************************************/
  1567. System::Void SDMSensor::button_P16UpdateDistance_Click(System::Object^ sender, System::EventArgs^ e)
  1568. {
  1569. this->label_P16UpdateError->Visible = false;
  1570. //convert and catch failed conversions
  1571. try{
  1572. ulDistanceAccum = System::Convert::ToUInt32(this->textBox_P16DistDisplayChange->Text);
  1573. this->label_P16DistanceDisplay->Text = this->textBox_P16DistDisplayChange->Text;
  1574. }
  1575. catch(...){
  1576. this->label_P16UpdateError->Text = "Error: Dist";
  1577. this->label_P16UpdateError->Visible = true;
  1578. }
  1579. }
  1580. System::Void SDMSensor::checkBox_InvalidSerial_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
  1581. {
  1582. if(this->checkBox_InvalidSerial->Checked)
  1583. this->textBox_SerialNum->Enabled = false;
  1584. else
  1585. this->textBox_SerialNum->Enabled = true;
  1586. }