PowerDecoder.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. ////////////////////////////////////////////////////////////////////////////////
  2. // Dynastream Innovations Inc.
  3. // Cochrane, AB, CANADA
  4. //
  5. // Copyright © 2014 Dynastream Innovations Inc.
  6. // All rights reserved. This software may not be reproduced by
  7. // any means without express written approval of Dynastream
  8. // Innovations Inc.
  9. // The software is being provided on an "as-is" basis and as an accommodation,
  10. // and therefore all warranties, representations, or guarantees of any kind
  11. // (whether express, implied or statutory) including, without limitation,
  12. // warranties of merchantability, non-infringement, or fitness for a particular
  13. // purpose, are specifically disclaimed.
  14. //
  15. ////////////////////////////////////////////////////////////////////////////////
  16. #include "string.h"
  17. #include "stdbool.h"
  18. #include "stdint.h"
  19. #include "stdlib.h"
  20. #include "math.h"
  21. #include "DecodeCrankTorque.h"
  22. #include "DecodeCrankTorqueFrequency.h"
  23. #include "DecodePowerOnly.h"
  24. #include "DecodeWheelTorque.h"
  25. #include "PowerDecoder.h"
  26. static PowerRecordReceiver prrPtr;
  27. static unsigned char ucPowerMeterChannel = 255;
  28. static unsigned char ucPowerMeterType = 255;
  29. static bool bResyncPowerChannel = true;
  30. static bool bResyncPowerOnlyChannel = true;
  31. static unsigned char ucPowerOnlyEventCount = 255;
  32. static double dPowerOnlyBundleRxTime = -1;
  33. static unsigned char ucNewPowerOnlyEventCount;
  34. void InitPowerDecoder(double dRecordInterval_, double dTimeBase_, double dReSyncInterval_, PowerRecordReceiver powerRecordReceiverPtr_)
  35. {
  36. prrPtr = powerRecordReceiverPtr_;
  37. DecodePowerOnly_Init(dRecordInterval_, dTimeBase_, dReSyncInterval_, prrPtr);
  38. DecodeCrankTorque_Init(dRecordInterval_, dTimeBase_, dReSyncInterval_, prrPtr);
  39. DecodeCrankTorqueFreq_Init(dRecordInterval_, dTimeBase_, dReSyncInterval_, prrPtr);
  40. DecodeWheelTorque_Init(dRecordInterval_, dTimeBase_, dReSyncInterval_, prrPtr);
  41. }
  42. // 16 = Power Only, 17 = Wheel Torque, 18 = Crank Torque, 32 = Crank Torque Frequency, 255 = Unknown
  43. void SetPowerMeterType(unsigned char ucPowerMeterType_)
  44. {
  45. ucPowerMeterType = ucPowerMeterType_;
  46. }
  47. void DecodePowerMessage(double dRxTime_, unsigned char messagePayload_[8])
  48. {
  49. // Initialize the received time for power only event count bundled messages or
  50. // if the received times differ greatly (we may have missed messages beyond the event count rollover)
  51. if (dPowerOnlyBundleRxTime < 0 || (dRxTime_ - dPowerOnlyBundleRxTime) > 30)
  52. dPowerOnlyBundleRxTime = dRxTime_;
  53. // do page decoding against the expected power pages.
  54. switch (messagePayload_[0])
  55. {
  56. case ANT_POWERONLY:
  57. ucNewPowerOnlyEventCount = messagePayload_[1];
  58. if (ucNewPowerOnlyEventCount != ucPowerOnlyEventCount)
  59. {
  60. ucPowerOnlyEventCount = ucNewPowerOnlyEventCount;
  61. dPowerOnlyBundleRxTime = dRxTime_;
  62. }
  63. // Don't grab the power decoding unless we're the
  64. // only power message type we've received so far.
  65. if (ucPowerMeterType == 255)
  66. {
  67. ucPowerMeterType = messagePayload_[0];
  68. DecodePowerOnly_Resync(dPowerOnlyBundleRxTime, messagePayload_);
  69. }
  70. if (bResyncPowerOnlyChannel)
  71. {
  72. DecodePowerOnly_Resync(dPowerOnlyBundleRxTime, messagePayload_);
  73. bResyncPowerOnlyChannel = false;
  74. }
  75. // For now we will only decode the power only page if it is the only bike power page we receive
  76. if (ucPowerMeterType == ANT_POWERONLY)
  77. DecodePowerOnly_Message(dPowerOnlyBundleRxTime, messagePayload_);
  78. break;
  79. case ANT_WHEELTORQUE:
  80. if (ucPowerMeterType != messagePayload_[0])
  81. {
  82. // set up the power only message in addition
  83. // to the crank torque data stream.
  84. DecodePowerOnly_Resync(dRxTime_, messagePayload_);
  85. bResyncPowerOnlyChannel = false;
  86. DecodeWheelTorque_Resync(dRxTime_, messagePayload_);
  87. bResyncPowerChannel = false;
  88. ucPowerMeterType = messagePayload_[0];
  89. }
  90. // This is resolved here in order to handle decoder specific
  91. // resync requirements when a new message is available.
  92. if (bResyncPowerChannel)
  93. {
  94. DecodeWheelTorque_Resync(dRxTime_, messagePayload_);
  95. bResyncPowerChannel = false;
  96. }
  97. DecodeWheelTorque_Message(dRxTime_, messagePayload_);
  98. break;
  99. case ANT_CRANKTORQUE:
  100. if (ucPowerMeterType != messagePayload_[0])
  101. {
  102. // set up the power only message in addition
  103. // to the crank torque data stream.
  104. DecodePowerOnly_Resync(dRxTime_, messagePayload_);
  105. bResyncPowerOnlyChannel = false;
  106. DecodeCrankTorque_Resync(dRxTime_, messagePayload_);
  107. bResyncPowerChannel = false;
  108. ucPowerMeterType = messagePayload_[0];
  109. }
  110. // This is resolved here in order to handle decoder specific
  111. // resync requirements when a new message is available.
  112. if (bResyncPowerChannel)
  113. {
  114. DecodeCrankTorque_Resync(dRxTime_, messagePayload_);
  115. bResyncPowerChannel = false;
  116. }
  117. DecodeCrankTorque_Message(dRxTime_, messagePayload_);
  118. break;
  119. case ANT_CRANKFREQ:
  120. if (ucPowerMeterType != messagePayload_[0])
  121. {
  122. // set up the power only message in addition
  123. // to the crank torque data stream.
  124. DecodePowerOnly_Resync(dRxTime_, messagePayload_);
  125. bResyncPowerOnlyChannel = false;
  126. DecodeCrankTorqueFreq_Resync(dRxTime_, messagePayload_);
  127. bResyncPowerChannel = false;
  128. ucPowerMeterType = messagePayload_[0];
  129. }
  130. // This is resolved here in order to handle decoder specific
  131. // resync requirements when a new message is available.
  132. if (bResyncPowerChannel)
  133. {
  134. DecodeCrankTorqueFreq_Resync(dRxTime_, messagePayload_);
  135. bResyncPowerChannel = false;
  136. }
  137. DecodeCrankTorqueFreq_Message(dRxTime_, messagePayload_);
  138. break;
  139. case ANT_TEPS:
  140. // This is an auxiliary message, not valid unless there is an actual power message
  141. // to match it to.
  142. // We still need to correct for Rx Time because we do not know which power only event count shared message comes first.
  143. ucNewPowerOnlyEventCount = messagePayload_[1];
  144. if (ucNewPowerOnlyEventCount != ucPowerOnlyEventCount)
  145. {
  146. ucPowerOnlyEventCount = ucNewPowerOnlyEventCount;
  147. dPowerOnlyBundleRxTime = dRxTime_;
  148. }
  149. break;
  150. case ANT_CALIBRATION_MESSAGE:
  151. switch (ucPowerMeterType)
  152. {
  153. case ANT_CRANKFREQ:
  154. // The only one that really matters is the crank torque frequency meter.
  155. DecodeCrankTorqueFreq_Calibration(dRxTime_, messagePayload_);
  156. break;
  157. default:
  158. break;
  159. }
  160. break;
  161. default:
  162. // Other pages are ignored in this example.
  163. break;
  164. }
  165. }