2
0

HRMDisplay.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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 "HRMDisplay.h"
  10. /**************************************************************************
  11. * HRMDisplay::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 HRMDisplay::ANT_eventNotification(UCHAR ucEventCode_, UCHAR* pucEventBuffer_)
  23. {
  24. switch(ucEventCode_)
  25. {
  26. case EVENT_RX_ACKNOWLEDGED:
  27. case EVENT_RX_BURST_PACKET: // intentional fall thru
  28. case EVENT_RX_BROADCAST:
  29. HandleReceive((UCHAR*) pucEventBuffer_);
  30. break;
  31. default:
  32. break;
  33. }
  34. }
  35. /**************************************************************************
  36. * HRMDisplay::InitializeSim
  37. *
  38. * Initializes simulator variables
  39. *
  40. * returns: N/A
  41. *
  42. **************************************************************************/
  43. void HRMDisplay::InitializeSim()
  44. {
  45. ucBPM = 0;
  46. ucEventCount = 0;
  47. ucPreviousEventCount = 0;
  48. usTime1024 = 0;
  49. usPreviousTime1024 = 0;
  50. ulElapsedTime2 = 0;
  51. ucStatePage = HRM_INIT_PAGE;
  52. ulAcumEventCount = 0;
  53. ulAcumTime1024 = 0;
  54. usR_RInterval1024 = 0;
  55. ucCalcBPM = 0;
  56. ucMfgID = 0;
  57. ucHwVersion = 0;
  58. ucSwVersion = 0;
  59. ucModelNum = 0;
  60. usSerialNum = 0;
  61. }
  62. /**************************************************************************
  63. * HRMDisplay::HandleReceive
  64. *
  65. * Decodes received data
  66. *
  67. * pucRxBuffer_: pointer to the buffer containing the received data
  68. *
  69. * returns: N/A
  70. *
  71. **************************************************************************/
  72. void HRMDisplay::HandleReceive(UCHAR* pucRxBuffer_)
  73. {
  74. static UCHAR ucNoEventCount = 0; // Successive transmissions with no new HR events
  75. UCHAR ucPageNum = 0;
  76. UCHAR ucEventDiff = 0;
  77. USHORT usTimeDiff1024 = 0;
  78. //Remove page toggle bit
  79. ucPageNum = pucRxBuffer_[0] & ~HRM_TOGGLE_MASK;
  80. //Removed, according to profile, bytes 4-7 should be decoded regardless of data page number
  81. //// Do not process undefined pages
  82. //if(!( ucPageNum == HRM_PAGE0 || ucPageNum == HRM_PAGE1
  83. // || ucPageNum == HRM_PAGE2 || ucPageNum == HRM_PAGE3
  84. // || ucPageNum == HRM_PAGE4))
  85. // return;
  86. // Monitor page toggle bit
  87. if(ucStatePage != HRM_EXT_PAGE)
  88. {
  89. if(ucStatePage == HRM_INIT_PAGE)
  90. {
  91. ucStatePage = (pucRxBuffer_[0] & HRM_TOGGLE_MASK) >>7;
  92. // Initialize previous values to correctly get the cumulative values
  93. ucPreviousEventCount = pucRxBuffer_[6];
  94. usPreviousTime1024 = pucRxBuffer_[4];
  95. usPreviousTime1024 += pucRxBuffer_[5]<<8;
  96. }
  97. else if(ucStatePage != ((pucRxBuffer_[0] & HRM_TOGGLE_MASK) >>7))
  98. {
  99. // First page toggle was seen, enable advanced data
  100. ucStatePage = HRM_EXT_PAGE;
  101. }
  102. }
  103. // Handle basic data
  104. ucEventCount = pucRxBuffer_[6];
  105. usTime1024 = pucRxBuffer_[4];
  106. usTime1024 += pucRxBuffer_[5]<<8;
  107. ucBPM = pucRxBuffer_[7];
  108. // Handle background data, if supported
  109. if(ucStatePage == HRM_EXT_PAGE)
  110. {
  111. switch(ucPageNum)
  112. {
  113. case HRM_PAGE1:
  114. ulElapsedTime2 = pucRxBuffer_[1];
  115. ulElapsedTime2 += pucRxBuffer_[2] << 8;
  116. ulElapsedTime2 += pucRxBuffer_[3] << 16;
  117. break;
  118. case HRM_PAGE2:
  119. ucMfgID = pucRxBuffer_[1];
  120. usSerialNum = pucRxBuffer_[2];
  121. usSerialNum += pucRxBuffer_[3] << 8;
  122. break;
  123. case HRM_PAGE3:
  124. ucHwVersion = pucRxBuffer_[1];
  125. ucSwVersion = pucRxBuffer_[2];
  126. ucModelNum = pucRxBuffer_[3];
  127. break;
  128. case HRM_PAGE4:
  129. usPreviousTime1024 = pucRxBuffer_[2];
  130. usPreviousTime1024 += pucRxBuffer_[3] << 8;
  131. break;
  132. default:
  133. break;
  134. }
  135. }
  136. // Only need to do calculations if dealing with a new event
  137. if(ucEventCount != ucPreviousEventCount)
  138. {
  139. ucNoEventCount = 0;
  140. // Update cumulative event count
  141. if(ucEventCount > ucPreviousEventCount)
  142. ucEventDiff = ucEventCount - ucPreviousEventCount;
  143. else
  144. ucEventDiff = (UCHAR) 0xFF - ucPreviousEventCount + ucEventCount + 1;
  145. ulAcumEventCount += ucEventDiff;
  146. // Update cumulative time
  147. if(usTime1024 > usPreviousTime1024)
  148. usTimeDiff1024 = usTime1024 - usPreviousTime1024;
  149. else
  150. usTimeDiff1024 = (USHORT) (0xFFFF - usPreviousTime1024 + usTime1024 + 1);
  151. ulAcumTime1024 += usTimeDiff1024;
  152. // Calculate R-R Interval
  153. if(ucEventDiff == 1)
  154. usR_RInterval1024 = usTimeDiff1024;
  155. // Calculate heart rate (from timing data), in bpm
  156. if(usTimeDiff1024 > 0)
  157. ucCalcBPM = (UCHAR) ( ((USHORT) ucEventDiff * 0xF000) / usTimeDiff1024 ); // 1 min = 0xF000 = 60 * 1024
  158. }
  159. else
  160. {
  161. ucNoEventCount++;
  162. if(ucNoEventCount >= MAX_NO_EVENTS)
  163. {
  164. ucCalcBPM = HRM_INVALID_BPM; // No new valid HR data has been received
  165. }
  166. }
  167. // Display data
  168. UpdateDisplay(ucPageNum);
  169. // Update previous time and event count
  170. if(ucPageNum != HRM_PAGE4)
  171. usPreviousTime1024 = usTime1024; // only if not previously obtained from HRM message
  172. ucPreviousEventCount = ucEventCount;
  173. }
  174. /**************************************************************************
  175. * HRMDisplay::UpdateDisplay
  176. *
  177. * Shows received decoded data on GUI
  178. *
  179. * ucPageNum_: received page
  180. *
  181. * returns: N/A
  182. *
  183. **************************************************************************/
  184. void HRMDisplay::UpdateDisplay(UCHAR ucPageNum_)
  185. {
  186. // Display basic data
  187. this->label_Trn_TimeDisplay->Text = usTime1024.ToString();
  188. this->label_Trn_EventCountDisplay->Text = ucEventCount.ToString();
  189. if(ucBPM)
  190. this->label_Trn_RawPulseDisplay->Text = ucBPM.ToString();
  191. else
  192. this->label_Trn_RawPulseDisplay->Text = "---"; // Invalid heart rate
  193. // Display background data, if available
  194. if(ucStatePage == HRM_EXT_PAGE)
  195. {
  196. this->label_Calc_waitToggle->Visible = false; // Page toggle was seen, so show in GUI
  197. switch(ucPageNum_)
  198. {
  199. case HRM_PAGE1:
  200. this->label_Glb_BattTimeDisplay->Text = (ulElapsedTime2*2).ToString();
  201. break;
  202. case HRM_PAGE2:
  203. this->label_Glb_ManfIDDisplay->Text = ucMfgID.ToString();
  204. this->label_Glb_SerialNumDisplay->Text = usSerialNum.ToString();
  205. break;
  206. case HRM_PAGE3:
  207. this->label_Glb_HardwareVerDisplay->Text = ucHwVersion.ToString();
  208. this->label_Glb_SoftwareVerDisplay->Text = ucSwVersion.ToString();
  209. this->label_Glb_ModelNumDisplay->Text = ucModelNum.ToString();
  210. break;
  211. case HRM_PAGE4:
  212. this->label_Trn_LastEventTimeDisplay->Text = usPreviousTime1024.ToString();
  213. break;
  214. default:
  215. break;
  216. }
  217. }
  218. // Display calculated data
  219. // Cumulative time (in s)
  220. this->label_Calc_ElapsedSecsDisplay->Text = System::Math::Round((DOUBLE) ulAcumTime1024/1024,3).ToString();
  221. // R-R interval (in ms)
  222. if(ucStatePage == HRM_EXT_PAGE)
  223. this->label_Calc_RRIntervalDisplay->Text = System::Math::Round(((DOUBLE) usR_RInterval1024*1000/1024),3).ToString(); // Convert to ms
  224. else
  225. this->label_Calc_RRIntervalDisplay->Text = "---";
  226. // Cumulative event count
  227. this->label_Calc_TotEventCountDisplay->Text = ulAcumEventCount.ToString();
  228. // Heart rate (from timing data)
  229. if(ucCalcBPM)
  230. {
  231. this->label_Calc_PulseDisplay->Text = ucCalcBPM.ToString();
  232. this->label_Calc_InstPulseDisplay->Text = ucBPM.ToString();
  233. }
  234. else
  235. {
  236. this->label_Calc_PulseDisplay->Text = "---"; // Invalid heart rate
  237. this->label_Calc_InstPulseDisplay->Text = "---";
  238. }
  239. }