123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- /*
- This software is subject to the license described in the License.txt file
- included with this software distribution. You may not use this file except in compliance
- with this license.
- Copyright (c) Dynastream Innovations Inc. 2012
- All rights reserved.
- */
- #include "StdAfx.h"
- #include "BikeSpeedSensor.h"
- /**************************************************************************
- * BikeSpeedSensor::ANT_eventNotification
- *
- * Process ANT channel event
- *
- * ucEventCode_: code of ANT channel event
- * pucEventBuffer_: pointer to buffer containing data received from ANT,
- * or a pointer to the transmit buffer in the case of an EVENT_TX
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpeedSensor::ANT_eventNotification(UCHAR ucEventCode_, UCHAR* pucEventBuffer_)
- {
- switch(ucEventCode_)
- {
- case EVENT_TX:
- HandleTransmit((UCHAR*) pucEventBuffer_);
- break;
- default:
- break;
- }
- }
- /**************************************************************************
- * BikeSpeedSensor::InitializeSim
- *
- * Initializes simulator variables
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpeedSensor::InitializeSim()
- {
- ulTimerInterval = 248; //30kph, 207cm wheel
- ulRunTime = 0;
- ulRunTime16000 = 0;
- ucReserved = BS_RESERVED;
- usEventCount = 0;
- ucWheelCircumference = System::Convert::ToByte(this->numericUpDown_Sim_WheelCircumference->Value); // Initial value set on UI
- ulMinSpeed = (ULONG) (System::Convert::ToDouble(this->numericUpDown_Sim_SpdMinOutput->Value) * 1000); // Initial value set on UI (km/h -> meter/h)
- ulCurSpeed = (ULONG) (System::Convert::ToDouble(this->numericUpDown_Sim_SpdCurOutput->Value) * 1000); // Initial value set on UI (km/h -> meter/h)
- ulMaxSpeed = (ULONG) (System::Convert::ToDouble(this->numericUpDown_Sim_SpdMaxOutput->Value) * 1000); // Initial value set on UI (km/h -> meter/h)
- ulElapsedTime2 = 0;
- usTime1024 = 0;
- ucMfgID = System::Convert::ToByte(this->textBox_ManfIDChange->Text); // Background data initially set on UI
- ucHwVersion = System::Convert::ToByte(this->textBox_HardwareVerChange->Text);
- ucSwVersion = System::Convert::ToByte(this->textBox_SoftwareVerChange->Text);
- ucModelNum = System::Convert::ToByte(this->textBox_ModelNumChange->Text);
- usSerialNum = System::Convert::ToUInt16(this->textBox_SerialNumChange->Text);
- ucSimDataType = SIM_FIXED; // Generate single fixed heart rate value by default
- bLegacy = FALSE; // Disable legacy mode by default
- bTxMinimum = FALSE; // Transmit full data set by default
- bSweepAscending = TRUE; // If sweeping, start with ascending values by default
- ucBackgroundCount = 0;
- ucNextBackgroundPage = BS_PAGE1; // By default, support all defined pages
- }
- /**************************************************************************
- * BikeSpeedSensor::HandleTransmit
- *
- * Encode data generated by simulator for transmission
- *
- * pucTxBuffer_: pointer to the transmit buffer
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpeedSensor::HandleTransmit(UCHAR* pucTxBuffer_)
- {
- static UCHAR ucMessageNum = 0; // Message count
- static UCHAR ucPageToggle = 0; // Page toggle tracker
- UCHAR ucPageNum = BS_PAGE0; // Page number
- // Send background pages every 65th message (not available in legacy sensors)
- if(!bLegacy)
- {
- if(ucMessageNum++ == BS_BACKGROUND_INTERVAL-1)
- {
- ucMessageNum = 0;
- switch(ucNextBackgroundPage)
- {
- case 1:
- ucPageNum = BS_PAGE1;
- ucNextBackgroundPage++;
- break;
- case 2:
- ucPageNum = BS_PAGE2;
- if(bTxMinimum)
- {
- // If using minimum data set, background pages are sent three times to ensure they are received by displays with lower message rate
- if(++ucBackgroundCount > 2)
- {
- ucBackgroundCount = 0;
- ucNextBackgroundPage ++;
- }
- }
- else
- {
- // Otherwise, send only once
- ucNextBackgroundPage++;
- }
- break;
- case 3:
- ucPageNum = BS_PAGE3;
- if(bTxMinimum)
- {
- // If using minimum data set, background pages are sent three times to ensure they are received by displays with lower message rate
- if(++ucBackgroundCount > 2)
- {
- ucBackgroundCount = 0;
- ucNextBackgroundPage = BS_PAGE2;
- }
- }
- else
- {
- // Otherwise, send only once
- ucNextBackgroundPage = BS_PAGE1;
- }
- break;
- default:
- break;
- }
- }
- }
- // Fill in common info
- if(!bLegacy)
- pucTxBuffer_[0] = ucPageNum;
- else
- pucTxBuffer_[0] = ucReserved; // Legacy sensors only, do not interpret at receiver, do not use as reference for new sensor designs
- pucTxBuffer_[4] = (UCHAR) (usTime1024 & 0xFF);
- pucTxBuffer_[5] = (UCHAR) (usTime1024 >> 8) & 0xFF;
- pucTxBuffer_[6] = (UCHAR) (usEventCount & 0xFF);
- pucTxBuffer_[7] = (UCHAR) (usEventCount >> 8) & 0xFF;
- // Page specific info
- switch(ucPageNum)
- {
- case BS_PAGE0:
- pucTxBuffer_[1] = ucReserved; // Reserved, do not interpret at the receiver
- pucTxBuffer_[2] = ucReserved; // Reserved, do not interpret at the receiver
- pucTxBuffer_[3] = ucReserved; // Reserved, do not interpret at the receiver
- break;
- case BS_PAGE1:
- pucTxBuffer_[1] = (ulElapsedTime2 & 0xFF); // Cumulative operating time, bits 0-7 (intervals of 2s)
- pucTxBuffer_[2] = (ulElapsedTime2 >> 8) & 0xFF; // Cumulative operating time, bits 8-15 (intervals of 2s)
- pucTxBuffer_[3] = (ulElapsedTime2 >> 16) & 0xFF; // Cumulative operating time, bits 16-23 (intervals of 2s)
- break;
- case BS_PAGE2:
- pucTxBuffer_[1] = ucMfgID; // Manufacturing ID
- pucTxBuffer_[2] = usSerialNum & 0x00FF; // Low byte of serial number
- pucTxBuffer_[3] = (usSerialNum & 0xFF00) >>8; // High byte of serial number
- break;
- case BS_PAGE3:
- pucTxBuffer_[1] = ucHwVersion; // Hardware version
- pucTxBuffer_[2] = ucSwVersion; // Software version
- pucTxBuffer_[3] = ucModelNum; // Model number
- break;
- default:
- break;
- }
- // Handle page toggle bit: toggle every four messages
- if(!bLegacy)
- {
- ucPageToggle += 0x20;
- pucTxBuffer_[0] += (ucPageToggle & BS_TOGGLE_MASK);
- }
- }
- /**************************************************************************
- * BikeSpeedSensor::onTimerTock
- *
- * Simulates a device event, updating simulator data based on this event
- * Modifications to the timer interval are applied immediately after this
- * at ANTChannel
- *
- * usEventTime_: current time (ms)
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpeedSensor::onTimerTock(USHORT eventTime)
- {
- ULONG tempOffset = 0; // Temporary variable to calculate sweeping intervals
- // Update event count
- ++usEventCount;
- // Update event time
- ulRunTime16000 += (ulTimerInterval << 4); // Multiply by 16 to convert from ms to 1/16000s
- usTime1024 = (USHORT) ((ulRunTime16000 << 3) / 125); // Convert to 1/1024s - multiply by 1024/16000
- ulRunTime += ulTimerInterval;
- while(ulRunTime/2000) // 2000 ms
- {
- ++ulElapsedTime2; // elapsed time is updated every 2 seconds
- ulRunTime -=2000;
- }
- switch(ucSimDataType)
- {
- case SIM_FIXED:
- // Speed value does not change
- break;
- case SIM_SWEEP:
- // Cadence sweeps between min and max
- // 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
- tempOffset = ulMaxSpeed-ulCurSpeed;
- tempOffset = ((tempOffset & 0x7000) >> 6) + ((tempOffset & 0xE00) >> 5) + ((tempOffset & 0x1C) >> 4)+0x7F;
- if(bSweepAscending)
- ulCurSpeed += tempOffset;
- else
- ulCurSpeed -= tempOffset;
- // Ensure next value is not less than min or more than max
- if(ulCurSpeed >= ulMaxSpeed)
- {
- ulCurSpeed = ulMaxSpeed;
- bSweepAscending = FALSE;
- }
- if(ulCurSpeed <= ulMinSpeed)
- {
- ulCurSpeed = ulMinSpeed;
- bSweepAscending = TRUE;
- }
- break;
- default:
- break;
- }
- // Update timer interval (in ms)
- if(ulCurSpeed)
- ulTimerInterval = (ULONG) 36000 * ucWheelCircumference/ulCurSpeed; // in ms (wheel circumference is in cm, speed in meter/h)
- else
- ulTimerInterval = 600000; // Stopping, set timer interval to a very large value
-
- // Update display
- UpdateDisplay();
- }
- /***************************************************************************
- * BikeSpeedSensor::UpdateDisplay
- *
- * Updates displayed simulator data on GUI
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpeedSensor::UpdateDisplay()
- {
- this->label_Trn_EventCountDisplay->Text = System::Convert::ToString(usEventCount); // Event count
- this->label_ElapsedSecsDisplay->Text = System::Convert::ToString((unsigned int)(ulElapsedTime2 & 0x00FFFFFF)*2); // Operating time (s)
- if(ucSimDataType == SIM_SWEEP) // Update only if it is changing
- this->numericUpDown_Sim_SpdCurOutput->Value = System::Convert::ToDecimal((double) ulCurSpeed/1000); // Current speed generated, meter/h -> km/h
- this->label_Trn_TimeDisplay->Text = System::Convert::ToString(usTime1024); // Time of last event (1/1024s)
- }
- /**************************************************************************
- * BikeSpeedSensor::radioButton_SimTypeChanged
- *
- * Select method to generate simulator data, from user input (GUI)
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpeedSensor::radioButton_SimTypeChanged (System::Object^ sender, System::EventArgs^ e)
- {
- this->numericUpDown_Sim_SpdCurOutput->Enabled = !this->numericUpDown_Sim_SpdCurOutput->Enabled;
- this->numericUpDown_Sim_SpdMinOutput->Enabled = !this->numericUpDown_Sim_SpdMinOutput->Enabled;
- this->numericUpDown_Sim_SpdMaxOutput->Enabled = !this->numericUpDown_Sim_SpdMaxOutput->Enabled;
- if(this->radioButton_Sim_Fixed->Checked)
- {
- ucSimDataType = SIM_FIXED;
- }
- else if(this->radioButton_Sim_Sweep->Checked)
- {
- bSweepAscending = TRUE;
- ucSimDataType = SIM_SWEEP;
- }
- }
- /**************************************************************************
- * BikeSpeedSensor::button_AdvancedUpdate_Click
- *
- * Validates and updates product information, from user input (GUI)
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpeedSensor::button_AdvancedUpdate_Click(System::Object^ sender, System::EventArgs^ e)
- {
- label_AdvancedError->Visible = false;
- label_AdvancedError->Text = "Error: ";
- //convert and catch failed conversions
- try{
- ucMfgID = System::Convert::ToByte(this->textBox_ManfIDChange->Text);
- }
- catch(...){
- label_AdvancedError->Text = System::String::Concat(label_AdvancedError->Text, " MFID");
- label_AdvancedError->Visible = true;
- }
- try{
- usSerialNum = System::Convert::ToUInt16(this->textBox_SerialNumChange->Text);
- }
- catch(...){
- label_AdvancedError->Text = System::String::Concat(label_AdvancedError->Text, " Ser#");
- label_AdvancedError->Visible = true;
- }
- try{
- ucHwVersion = System::Convert::ToByte(this->textBox_HardwareVerChange->Text);
- }
- catch(...){
- label_AdvancedError->Text = System::String::Concat(label_AdvancedError->Text, " HWVr");
- label_AdvancedError->Visible = true;
- }
- try{
- ucSwVersion = System::Convert::ToByte(this->textBox_SoftwareVerChange->Text);
- }
- catch(...){
- label_AdvancedError->Text = System::String::Concat(label_AdvancedError->Text, " SWVr");
- label_AdvancedError->Visible = true;
- }
- try{
- ucModelNum = System::Convert::ToByte(this->textBox_ModelNumChange->Text);
- }
- catch(...){
- label_AdvancedError->Text = System::String::Concat(label_AdvancedError->Text, " Mdl#");
- label_AdvancedError->Visible = true;
- }
- }
- /**************************************************************************
- * BikeSpeedSensor::button_UpdateTime_Click
- *
- * Validates and updates cumulative operating time, from user input (GUI)
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpeedSensor::button_UpdateTime_Click(System::Object^ sender, System::EventArgs^ e)
- {
- ULONG ulCumulativeTime = 0;
- label_AdvancedError->Visible = false;
- try
- {
- ulCumulativeTime = System::Convert::ToUInt32(this->textBox_ElpTimeChange->Text);
- if(ulCumulativeTime > 33554430) // Cumulative Operating Time rollover: 2 * 0xFFFFFF = 33554430 seconds
- throw "Cumulative operating time exceeds rollover value";
- ulElapsedTime2 = ulCumulativeTime >> 1; // Cumulative time is stored in intervals of 2 seconds
- // Update display (in seconds)
- label_ElapsedSecsDisplay->Text = ((ulElapsedTime2 & 0x00FFFFFF) << 1).ToString();
- }
- catch(...)
- {
- label_AdvancedError->Text = "Error: Time";
- label_AdvancedError->Visible = true;
- }
- }
- /**************************************************************************
- * BikeSpeedSensor::numericUpDown_Sim_SpdCurOutput_ValueChanged
- *
- * Validates and updates the current speed value, from user input (GUI)
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpeedSensor::numericUpDown_Sim_SpdCurOutput_ValueChanged(System::Object^ sender, System::EventArgs^ e)
- {
- // This value is raised whenever the value changes, even if internally
- // Only update the current value if set by the user
- if(this->numericUpDown_Sim_SpdCurOutput->Enabled)
- {
- ulCurSpeed = (ULONG) (System::Convert::ToDouble(this->numericUpDown_Sim_SpdCurOutput->Value) * 1000); // kn/h -> m/h
- ForceUpdate();
- }
- }
- /**************************************************************************
- * BikeSpeedSensor::numericUpDown_Sim_SpdMinMaxOutput_ValueChanged
- *
- * If the user has changed the min or max speed, validate that
- * minimum < current < maximum
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpeedSensor::numericUpDown_Sim_SpdMinMaxOutput_ValueChanged(System::Object^ sender, System::EventArgs^ e)
- {
- ULONG ulPrevSpeed = ulCurSpeed;
- // This event is raised whenever the min and max value change, even if internally
- // Check min<max if in min/max mode, and force min<cur<max
- if(this->numericUpDown_Sim_SpdMinOutput->Value < this->numericUpDown_Sim_SpdMaxOutput->Value)
- {
- ulMinSpeed = (ULONG) (System::Convert::ToDouble(this->numericUpDown_Sim_SpdMinOutput->Value) * 1000); // km/h -> meter/h
- ulMaxSpeed = (ULONG) (System::Convert::ToDouble(this->numericUpDown_Sim_SpdMaxOutput->Value) * 1000); // km/h -> meter/h
- if(ulCurSpeed > ulMaxSpeed)
- ulCurSpeed = ulMaxSpeed;
- else if(ulCurSpeed < ulMinSpeed)
- ulCurSpeed = ulMinSpeed;
- if(ulCurSpeed != ulPrevSpeed)
- {
- this->numericUpDown_Sim_SpdCurOutput->Value = System::Convert::ToDecimal((double) ulCurSpeed/1000); // meter/h -> km/h
- ForceUpdate();
- }
- }
- else
- {
- // If the values were invalid, set numeric values to last valid values
- this->numericUpDown_Sim_SpdMinOutput->Value = System::Convert::ToDecimal((double) ulMinSpeed/1000); // meter/h -> km/h
- this->numericUpDown_Sim_SpdMaxOutput->Value = System::Convert::ToDecimal((double) ulMaxSpeed/1000); // meter/h -> km/h
- }
-
- }
- /**************************************************************************
- * BikeSpeedSensor::checkBox_Legacy_CheckedChanged
- *
- * Enable simulation of legacy sensors for testing backward compatibility of receivers
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpeedSensor::checkBox_Legacy_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
- {
- // Enable simulation of legacy sensors for testing backward compatibility of receivers
- if(checkBox_Legacy->Checked)
- {
- 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);
- if( result == ::DialogResult::OK )
- {
- bLegacy = TRUE;
- // Generate random data for reserved field to simulate legacy receivers
- // This should not be interpreted by the receiver, and by no means should be used as a reference for new designs
- // This feature is avaialable only for testing backwards compatibility
- srand(ulElapsedTime2);
- ucReserved = (UCHAR) ((rand() % 240) + 16); // Generate a random number between 16 and 255
- checkBox_SendBasicPage->Checked = FALSE;
- checkBox_SendBasicPage->Enabled = FALSE;
- }
- else
- {
- bLegacy = FALSE;
- ucReserved = BS_RESERVED;
- checkBox_Legacy->Checked = FALSE;
- checkBox_SendBasicPage->Enabled = TRUE;
- }
- }
- else
- {
- bLegacy = FALSE;
- ucReserved = BS_RESERVED;
- checkBox_SendBasicPage->Enabled = TRUE;
- }
- }
- /**************************************************************************
- * BikeSpeedSensor::numericUpDown_Sim_WheelCircumference_ValueChanged
- *
- * Updates wheel circumference value, if updated (either by the user or internally)
- * Validation is already performed by the numericUpDown control
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpeedSensor::numericUpDown_Sim_WheelCircumference_ValueChanged(System::Object^ sender, System::EventArgs^ e)
- {
- ucWheelCircumference = System::Convert::ToByte(this->numericUpDown_Sim_WheelCircumference->Value);
- }
- /**************************************************************************
- * BikeSpeedSensor::checkBox_SendBasicPage_CheckedChanged
- *
- * Selects transmission of minimum data set
- * Minimum data set does not include Page 1
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpeedSensor::checkBox_SendBasicPage_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
- {
- if(checkBox_SendBasicPage->Checked)
- {
- bTxMinimum = TRUE;
- ucNextBackgroundPage = BS_PAGE2; // Page 1 is disabled
- ucBackgroundCount = 0; // Reset background page count
- }
- else
- {
- bTxMinimum = FALSE;
- ucNextBackgroundPage = BS_PAGE1; // Enable Page 1
- ucBackgroundCount = 0; // Reset background page count
- }
- }
- /**************************************************************************
- * BikeSpeedSensor::ForceUpdate
- *
- * Causes a timer event, to force the simulator to update all calculations
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpeedSensor::ForceUpdate()
- {
- timerHandle->Interval = 250;
- }
|