123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- /*
- 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 "BikeSpdCadSensor.h"
- /**************************************************************************
- * BikeSpdCadSensor::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 BikeSpdCadSensor::ANT_eventNotification(UCHAR ucEventCode_, UCHAR* pucEventBuffer_)
- {
- switch(ucEventCode_)
- {
- case EVENT_TX:
- HandleTransmit((UCHAR*) pucEventBuffer_);
- break;
- default:
- break;
- }
- }
- /**************************************************************************
- * BikeSpdCadSensor::InitializeSim
- *
- * Initializes simulator variables
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpdCadSensor::InitializeSim()
- {
- // Simulation Timer
- ulRunTime16000 = 0;
- ulTimerInterval = 247; // First event, before cadence/speed events, to initialize sim data
- ulNextCadInterval = 667; //90 rpm
- ulNextSpdInterval = 248; //30kph, 207cm wheel
- // Cadence
- usCadEventCount = 0;
- usCadTime1024 = 0;
- ucCurCadence = (UCHAR)this->numericUpDown_Sim_CadCurOutput->Value; // Default current cadence is set on UI
- ucMinCadence = (UCHAR)this->numericUpDown_Sim_CadMinOutput->Value; // Default minimum cadence is set on UI
- ucMaxCadence = (UCHAR)this->numericUpDown_Sim_CadMaxOutput->Value; // Default maximum cadence is set on UI
- ucCadSimDataType = SIM_FIXED;
- bCadSweepAscending = TRUE;
-
- // Speed
- usSpdEventCount = 0;
- usSpdTime1024 = 0;
- ulCurSpeed = (ULONG) (System::Convert::ToDouble(this->numericUpDown_Sim_SpdCurOutput->Value) * 1000); // Initial value set on UI (km/h -> meter/h)
- ulMinSpeed = (ULONG) (System::Convert::ToDouble(this->numericUpDown_Sim_SpdMinOutput->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)
- ucWheelCircumference = System::Convert::ToByte(this->numericUpDown_Sim_WheelCircumference->Value); // Initial value set on UI
- ucSpdSimDataType = SIM_FIXED;
- bSpdSweepAscending = TRUE;
- }
- /**************************************************************************
- * BikeSpdCadSensor::HandleTransmit
- *
- * Encode data generated by simulator for transmission
- *
- * pucTxBuffer_: pointer to the transmit buffer
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpdCadSensor::HandleTransmit(UCHAR* pucTxBuffer_)
- {
- // Transmission is always the same page
- pucTxBuffer_[0] = (UCHAR) (usCadTime1024 & 0xFF);
- pucTxBuffer_[1] = (UCHAR) (usCadTime1024 >> 8) & 0xFF;
- pucTxBuffer_[2] = (UCHAR) (usCadEventCount & 0xFF);
- pucTxBuffer_[3] = (UCHAR) (usCadEventCount >> 8) & 0xFF;
- pucTxBuffer_[4] = (UCHAR) (usSpdTime1024 & 0xFF);
- pucTxBuffer_[5] = (UCHAR) (usSpdTime1024 >> 8) & 0xFF;
- pucTxBuffer_[6] = (UCHAR) (usSpdEventCount & 0xFF);
- pucTxBuffer_[7] = (UCHAR) (usSpdEventCount >> 8) & 0xFF;
- }
- /**************************************************************************
- * BikeSpdCadSensor::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 BikeSpdCadSensor::onTimerTock(USHORT eventTime)
- {
- // Update master time
- ulRunTime16000 += (ulTimerInterval << 4); // Multiply by 16 to convert from ms to 1/16000s
- // Handle event and calculate time until next cadence/speed event
- if(ulNextCadInterval < ulNextSpdInterval) // Cadence event
- {
- // Update event count
- ++usCadEventCount;
- // Update event time
- usCadTime1024 = (USHORT) ((ulRunTime16000 << 3) / 125); // Convert to 1/1024s - multiply by 1024/16000
-
- switch(ucCadSimDataType)
- {
- case SIM_FIXED:
- // 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
- ULONG tempOffset = ucMaxCadence-ucCurCadence;
- tempOffset = ((tempOffset & 0xC0) >> 6) + ((tempOffset & 0x20) >>5) + ((tempOffset & 0x10) >>4)+1;
- if(bCadSweepAscending)
- ucCurCadence += (UCHAR) tempOffset;
- else
- ucCurCadence -= (UCHAR) tempOffset;
- // Ensure next value is not less than min or more than max
- if(ucCurCadence >= ucMaxCadence)
- {
- ucCurCadence = ucMaxCadence;
- bCadSweepAscending = FALSE;
- }
- if(ucCurCadence <= ucMinCadence)
- {
- ucCurCadence = ucMinCadence;
- bCadSweepAscending = TRUE;
- }
- break;
- }
- default:
- break;
- }
- // Adjust speed interval with the time already elapsed in cadence event
- ulNextSpdInterval -= ulNextCadInterval;
- // Update cadence time interval (in ms)
- if(ucCurCadence)
- ulNextCadInterval = (ULONG) 60000/ucCurCadence; // 60 seconds/revolutions per minute
- else
- ulNextCadInterval = 600000; // coasting (no events, setting interval to a very large value)
- // Find out which event will occur next
- if(ulNextCadInterval < ulNextSpdInterval)
- ulTimerInterval = ulNextCadInterval;
- else
- ulTimerInterval = ulNextSpdInterval;
- }
- else // Speed event
- {
- // Update event count
- ++usSpdEventCount;
- // Update event time
- usSpdTime1024 = (USHORT) ((ulRunTime16000 << 3) / 125); // Convert to 1/1024s - multiply by 1024/16000
- switch(ucSpdSimDataType)
- {
- 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
- ULONG tempOffset = ulMaxSpeed-ulCurSpeed;
- tempOffset = ((tempOffset & 0x7000) >> 6) + ((tempOffset & 0xE00) >> 5) + ((tempOffset & 0x1C) >> 4)+0x7F;
- if(bSpdSweepAscending)
- ulCurSpeed += tempOffset;
- else
- ulCurSpeed -= tempOffset;
- // Ensure value is not less than min or more than max
- if(ulCurSpeed >= ulMaxSpeed)
- {
- ulCurSpeed = ulMaxSpeed;
- bSpdSweepAscending = FALSE;
- }
- if(ulCurSpeed <= ulMinSpeed)
- {
- ulCurSpeed = ulMinSpeed;
- bSpdSweepAscending = TRUE;
- }
- break;
- }
- default:
- break;
- }
- // Adjust cadence interval with the time already elapsed in speed event
- ulNextCadInterval -= ulNextSpdInterval;
- // Update speed time interval (in ms)
- if(ulCurSpeed)
- ulNextSpdInterval = (ULONG) 36000 * ucWheelCircumference/ulCurSpeed; // in ms (wheel circumference is in cm, speed in meter/h)
- else
- ulNextSpdInterval = 600000; // Stopping (no events, setting interval to a very large value)
- //Find out which event will occur next
- if(ulNextSpdInterval < ulNextCadInterval)
- ulTimerInterval = ulNextSpdInterval;
- else
- ulTimerInterval = ulNextCadInterval;
- }
- if(ulTimerInterval < 1) //this prevents timerInterval=0 if values are identical and could be used to prevent too short timer intervals
- ulTimerInterval = 1;
- UpdateDisplay();
- }
- /***************************************************************************
- * BikeSpdCadSensor::UpdateDisplay
- *
- * Updates displayed simulator data on GUI
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpdCadSensor::UpdateDisplay()
- {
- this->label_Trn_CadCountDisplay->Text = System::Convert::ToString(usCadEventCount); // Cadence event count
- this->label_Trn_CadenceTimeDisplay->Text = System::Convert::ToString(usCadTime1024); // Time of last cadence event (1/1024s)
- this->label_Trn_SpdCountDisplay->Text = System::Convert::ToString(usSpdEventCount); // Speed event cont
- this->label_Trn_SpeedTimeDisplay->Text = System::Convert::ToString(usSpdTime1024); // Time of last speed event (1/1024s)
- if(ucCadSimDataType == SIM_SWEEP) // Update only if it is changing
- this->numericUpDown_Sim_CadCurOutput->Value = ucCurCadence; // Current cadence generated by simulator (rpm)
- if(ucSpdSimDataType == SIM_SWEEP) // Update only if it is changing
- this->numericUpDown_Sim_SpdCurOutput->Value = System::Convert::ToDecimal((double) ulCurSpeed/1000); // Current speed generated, meters/h -> km/h
- }
- /**************************************************************************
- * BikeSpdCadSensor::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 BikeSpdCadSensor::numericUpDown_Sim_WheelCircumference_ValueChanged(System::Object^ sender, System::EventArgs^ e)
- {
- ucWheelCircumference = System::Convert::ToByte(this->numericUpDown_Sim_WheelCircumference->Value);
- }
- /**************************************************************************
- * BikeSpdCadSensor::checkBox_Sim_SpeedSweeping_CheckedChanged
- *
- * Select method to generate simulator data, from user input (GUI)
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpdCadSensor::checkBox_Sim_SpeedSweeping_CheckedChanged(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->checkBox_Sim_SpdSweeping->Checked)
- {
- bSpdSweepAscending = TRUE;
- ucSpdSimDataType = SIM_SWEEP;
- }
- else
- {
- ucSpdSimDataType = SIM_FIXED;
- }
- }
- /**************************************************************************
- * BikeSpdCadSensor::checkBox_Sim_CadenceSweeping_CheckedChanged
- *
- * Select method to generate simulator data, from user input (GUI)
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpdCadSensor::checkBox_Sim_CadenceSweeping_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
- {
- this->numericUpDown_Sim_CadCurOutput->Enabled = !this->numericUpDown_Sim_CadCurOutput->Enabled;
- this->numericUpDown_Sim_CadMinOutput->Enabled = !this->numericUpDown_Sim_CadMinOutput->Enabled;
- this->numericUpDown_Sim_CadMaxOutput->Enabled = !this->numericUpDown_Sim_CadMaxOutput->Enabled;
-
- if(this->checkBox_Sim_CadSweeping->Checked)
- {
- bCadSweepAscending = TRUE;
- ucCadSimDataType = SIM_SWEEP;
- }
- else
- {
- ucCadSimDataType = SIM_FIXED;
- }
- }
- /**************************************************************************
- * BikeSpdCadSensor::numericUpDown_Sim_SpdCurOutput_ValueChanged
- *
- * Validates and updates the current speed, from user input (GUI)
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpdCadSensor::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 pulse if set by the user
- if(this->numericUpDown_Sim_SpdCurOutput->Enabled)
- {
- ulCurSpeed = (ULONG) (System:: Convert::ToDouble(this->numericUpDown_Sim_SpdCurOutput->Value) * 1000); // km/h -> meter/h
- if(ulCurSpeed)
- ulNextSpdInterval = (ULONG) 36000 * ucWheelCircumference/ulCurSpeed; // in ms (wheel circumference is in cm, speed in meter/h)
- else
- ulNextSpdInterval = 600000; // Stopping (no speed events in a very long time, so display can interpret it as stopping)
- ForceUpdate();
- }
- }
- /**************************************************************************
- * BikeSpdCad::numericUpDown_Sim_SpdMinMaxOutput_ValueChanged
- *
- * If the user has changed the min or max speed, validate that
- * minimum < current < maximum
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpdCadSensor::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 -> meters/h
- ulMaxSpeed = (ULONG) (System::Convert::ToDouble(this->numericUpDown_Sim_SpdMaxOutput->Value) * 1000); // km/h -> meters/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); // meters/h -> km/h
- if(ulCurSpeed)
- ulNextSpdInterval = (ULONG) 36000 * ucWheelCircumference/ulCurSpeed; // in ms (wheel circumference is in cm, speed in meter/h)
- else
- ulNextSpdInterval = 600000; // Stopping (no speed events in a very long time, so display can interpret it as stopping)
- 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); // meters/h -> km/h
- this->numericUpDown_Sim_SpdMaxOutput->Value = System::Convert::ToDecimal((double) ulMaxSpeed/1000); // meters/h -> km/h
- }
- }
- /**************************************************************************
- * BikeSpdCadSensor::numericUpDown_Sim_CadCurOutput_ValueChanged
- *
- * Validates and updates the current cadence, from user input (GUI)
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpdCadSensor::numericUpDown_Sim_CadCurOutput_ValueChanged(System::Object^ sender, System::EventArgs^ e)
- {
- // This value is raised whenever the value changes, even if internally
- // Only update the current pulse if set by the user
- if(this->numericUpDown_Sim_CadCurOutput->Enabled)
- {
- ucCurCadence = System::Convert::ToByte(this->numericUpDown_Sim_CadCurOutput->Value);
- if(ucCurCadence)
- ulNextCadInterval = (ULONG) 60000/ucCurCadence; // 60 seconds/revolutions per minute
- else
- ulNextCadInterval = 600000; // Coasting (no cadence events in a very long time so that display can interpret as coasting)
- ForceUpdate();
- }
- }
- /**************************************************************************
- * BikeSpdCad::numericUpDown_Sim_CadMinMaxOutput_ValueChanged
- *
- * If the user has changed the min or max cadence, validate that
- * minimum < current < maximum
- *
- * returns: N/A
- *
- **************************************************************************/
- System::Void BikeSpdCadSensor::numericUpDown_Sim_CadMinMaxOutput_ValueChanged(System::Object^ sender, System::EventArgs^ e)
- {
- UCHAR ucPrevCadence = ucCurCadence;
- // 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_CadMinOutput->Value < this->numericUpDown_Sim_CadMaxOutput->Value)
- {
- ucMinCadence = (UCHAR) this->numericUpDown_Sim_CadMinOutput->Value;
- ucMaxCadence = (UCHAR) this->numericUpDown_Sim_CadMaxOutput->Value;
- if(ucCurCadence > ucMaxCadence)
- ucCurCadence = ucMaxCadence;
- else if(ucCurCadence < ucMinCadence)
- ucCurCadence = ucMinCadence;
- if(ucCurCadence != ucPrevCadence)
- {
- this->numericUpDown_Sim_CadCurOutput->Value = ucCurCadence;
- if(ucCurCadence)
- ulNextCadInterval = (ULONG) 60000/ucCurCadence; // 60 seconds/revolutions per minute
- else
- ulNextCadInterval = 600000; // Coasting (no cadence events in a very long time so that display can interpret as coasting)
- ForceUpdate();
- }
- }
- else
- {
- // If the values were invalid, set numeric values to last valid values
- this->numericUpDown_Sim_CadMinOutput->Value = ucMinCadence;
- this->numericUpDown_Sim_CadMaxOutput->Value = ucMaxCadence;
- }
- }
- /**************************************************************************
- * BikeSpdCad::ForceUpdate
- *
- * Causes a timer event, to force the simulator to update all calculations
- *
- * returns: N/A
- *
- **************************************************************************/
- void BikeSpdCadSensor::ForceUpdate()
- {
- timerHandle->Interval = 250;
- }
|