#ifndef CLOCK_H #define CLOCK_H /** * @brief Interuption appelée régulièrement par le microcontroleur * @see Clock::MS_PER_TICK */ extern "C" void SysTick_Handler(); /** * @brief This singleton class provides a high-level interface for timey-winey stuff in pseudo-real time. * @see getInstance */ class Clock { protected: /** * @brief This function is called every tick of the internal clock. */ virtual void everyTick(); /** * @brief This function is called approximatively every 5ms. * * Important note: if Clock::MS_PER_TICK is not a divisor of 5ms, the actual delay will be the closest superior multiple of * Clock::MS_PER_TICK, and the errors are NOT compensated for from one tick to the other * (i.e. if the delay between call N and call N+1 is 7ms, the delay between calls N+1 and N+2 will NOT be 3ms. * @see everyTick MS_PER_TICK */ virtual void every5ms(); /** * @brief This function is called approximatively every second. * * Important note: the same restrictions than every5ms apply here (but should be less noticeable). * @see every5ms everyTick MS_PER_TICK */ virtual void everySecond(); /** * @brief This function is called approximatively 100ms. * * Important note: the same restrictions than every5ms apply here (but should be less noticeable). * @see every5ms everyTick MS_PER_TICK */ virtual void every100ms(); public: /** * SysTick_Handler() is called at regular inteval by the microcontroler, but 'regular' might mean different things * depending on the hardware or the low-level configuration. This constant 'fixes' the Clock so we might use pseudo-real * time instead of cycles. */ static const unsigned long MS_PER_TICK = 5; /** * The duration of a match, in ms. */ static const unsigned long MATCH_DURATION_MS = 90*1000; /** * @return The global Clock instance. */ static Clock* getInstance(); /** * @return The time elapsed since the clock was initialised, in ms. */ unsigned long elapsedSinceStartup() const; /** * @brief Starts the match timer. Does nothing if already called before. */ void matchStart(); /** * @return The time elapsed since the match started, in ms, or 0 if the match hasn't started yet. */ unsigned long elapsedSinceMatchStart() const; /** * @brief Returns true if the match was declared as 'started'. * @see matchStart hasMatchEnded */ bool isMatchStarted() const; /** * @brief Returns true if the match has ended. * * A match is considered 'ended' if more than Clock::MATCH_DURATION_MS ms has gone by since the first call to matchStart(). * @see matchStart Clock::MATCH_DURATION_MS */ bool hasMatchEnded() const; /** * @brief Provides an active pause * * This functions 'waits' for the duration given in parameter. Note it CANNOT be more accurate than Clock::MS_PER_TICK. * In fact, it will always wait slightly more than the parameter, to something rounded up to the nearest multiple of Clock::MS_PER_TICK. * @param duration The delay to wait for, in ms * @return The actual wait, in ms * @see MS_PER_TICK */ static unsigned int delay(unsigned int duration); protected: Clock(); private: void tick(); friend void ::SysTick_Handler(); unsigned long m_tickCount; unsigned long m_last5msTick; unsigned long m_last100msTick; unsigned long m_last1sTick; unsigned long m_matchStartTime; bool m_matchStarted; }; #endif // CLOCK_H