From 9218e647e0868ae68608aab18b53c6c417fe5240 Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Thu, 10 Mar 2016 17:01:17 +0000 Subject: [PATCH] microbit: Refactor of periodc timer callbacks - Factored periodic timer funcitonality out of fiber scheduler and into a new SystemTimer module module. - Enapsulated "ticks" variable within SystemTimer module, with accessor funciton. - Added accessor/mutator functions to get and set the tick period. - Added a class wrapper to permit periodic callbacks to both C and C++ functions. - Updated all references in microbit-dal to use this refactored API. --- inc/MicroBit.h | 1 + inc/MicroBitConfig.h | 4 +- inc/MicroBitFiber.h | 38 +-------- inc/MicroBitSystemTimer.h | 97 +++++++++++++++++++++++ source/CMakeLists.txt | 1 + source/MicroBit.cpp | 12 ++- source/MicroBitButton.cpp | 10 +-- source/MicroBitDisplay.cpp | 17 ++-- source/MicroBitEvent.cpp | 4 +- source/MicroBitFiber.cpp | 101 +----------------------- source/MicroBitMessageBus.cpp | 2 +- source/MicroBitSystemTimer.cpp | 138 +++++++++++++++++++++++++++++++++ source/MicroBitThermometer.cpp | 6 +- 13 files changed, 269 insertions(+), 162 deletions(-) create mode 100644 inc/MicroBitSystemTimer.h create mode 100644 source/MicroBitSystemTimer.cpp diff --git a/inc/MicroBit.h b/inc/MicroBit.h index d4f3a57..25d806a 100644 --- a/inc/MicroBit.h +++ b/inc/MicroBit.h @@ -7,6 +7,7 @@ #include "MicroBitHeapAllocator.h" #include "MicroBitPanic.h" #include "ErrorNo.h" +#include "MicroBitSystemTimer.h" #include "Matrix4.h" #include "MicroBitCompat.h" #include "MicroBitComponent.h" diff --git a/inc/MicroBitConfig.h b/inc/MicroBitConfig.h index cc9afd4..9446238 100644 --- a/inc/MicroBitConfig.h +++ b/inc/MicroBitConfig.h @@ -88,8 +88,8 @@ // Scheduling quantum (milliseconds) // Also used to drive the micro:bit runtime system ticker. -#ifndef FIBER_TICK_PERIOD_MS -#define FIBER_TICK_PERIOD_MS 6 +#ifndef SYSTEM_TICK_PERIOD_MS +#define SYSTEM_TICK_PERIOD_MS 6 #endif // diff --git a/inc/MicroBitFiber.h b/inc/MicroBitFiber.h index a8c0432..233058c 100644 --- a/inc/MicroBitFiber.h +++ b/inc/MicroBitFiber.h @@ -79,21 +79,6 @@ extern Fiber *currentFiber; */ void scheduler_init(MicroBitMessageBus *_messageBus); -/* - * Reconfigures the system wide timer to the given period in milliseconds. - * - * @param speedMs the new period of the timer in milliseconds - * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if speedMs < 1 - * - * @note this will also modify the value that is added to ticks in MiroBitFiber:scheduler_tick() - */ -int scheduler_set_tick_period(int speedMs); - -/* - * Returns the currently used tick speed in milliseconds - */ -int scheduler_get_tick_period(); - /** * Determines if the fiber scheduler is operational. * @return 1 if the fber scheduler is running, 0 otherwise. @@ -163,7 +148,7 @@ void schedule(); void fiber_sleep(unsigned long t); /** - * Timer callback. Called from interrupt context, once every FIBER_TICK_PERIOD_MS milliseconds. + * Timer callback. Called from interrupt context, once every SYSTEM_TICK_PERIOD_MS milliseconds by default. * Simply checks to determine if any fibers blocked on the sleep queue need to be woken up * and made runnable. */ @@ -265,21 +250,6 @@ void idle(); */ void idle_task(); -/** - * add a component to the array of system components which invocate the systemTick member function during a systemTick - * - * @param component The component to add. - * @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported. - */ -int fiber_add_system_component(MicroBitComponent *component); - -/** - * remove a component from the array of system components - * @param component The component to remove. - * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previous added. - */ -int fiber_remove_system_component(MicroBitComponent *component); - /** * add a component to the array of of idle thread components. * isIdleCallbackNeeded is polled during a systemTick to determine if the idle thread should jump to the front of the queue @@ -313,10 +283,4 @@ extern "C" void save_context(Cortex_M0_TCB *tcb, uint32_t stack); extern "C" void save_register_context(Cortex_M0_TCB *tcb); extern "C" void restore_register_context(Cortex_M0_TCB *tcb); -/** - * Time since power on. Measured in milliseconds. - * When stored as an unsigned long, this gives us approx 50 days between rollover, which is ample. :-) - */ -extern unsigned long ticks; - #endif diff --git a/inc/MicroBitSystemTimer.h b/inc/MicroBitSystemTimer.h new file mode 100644 index 0000000..22b743e --- /dev/null +++ b/inc/MicroBitSystemTimer.h @@ -0,0 +1,97 @@ +/** + * Definitions for the MicroBit system timer. + * + * This module provides: + * + * 1) a concept of global system time since power up + * 2) a simple periodic multiplexing API for the underlying mbed implementation. + * + * The latter is useful to avoid costs associated with multiple mbed Ticker instances + * in microbit-dal components, as each incurs a significant additional RAM overhead (circa 80 bytes). + */ + +#ifndef MICROBIT_SYSTEM_TIMER_H +#define MICROBIT_SYSTEM_TIMER_H + +#include "mbed.h" +#include "MicroBitConfig.h" +#include "MicroBitComponent.h" + +/** + * Initialises the system wide timer. + * This must be called before any components register to receive periodic periodic callbacks. + * + * @param timer_period The initial period between interrupts, in millseconds. + * @return MICROBIT_OK on success. + */ +int system_timer_init(int period); + +/* + * Reconfigures the system wide timer to the given period in milliseconds. + * + * @param period the new period of the timer in milliseconds + * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if period < 1 + */ +int system_timer_set_period(int period); + +/* + * Provides the current tick period in milliseconds + * @return the current tick period in milliseconds + */ +int system_timer_get_period(); + +/* + * Determines the time since the device was powered on. + * @return the current time since poweron in milliseconds + */ +unsigned long system_timer_current_time(); + +/** + * Timer callback. Called from interrupt context, once per period. + * Simply checks to determine if any fibers blocked on the sleep queue need to be woken up + * and made runnable. + */ +void system_timer_tick(); + +/** + * add a component to the array of system components. This component will then receive + * period callbacks, once every tick period. + * + * @param component The component to add. + * @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported. + */ +int system_timer_add_component(MicroBitComponent *component); + +/** + * remove a component from the array of system components. this component will no longer receive + * period callbacks. + * @param component The component to remove. + * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previous added. + */ +int system_timer_remove_component(MicroBitComponent *component); + +/** + * A simple C/C++ wrapper to allow periodic callbacks to standard C functions transparently. + */ +class MicroBitSystemTimerCallback : MicroBitComponent +{ + void (*fn)(void); + + /** + * Creates an object that receives periodic callbacks from the system timer, + * and, in turn, calls a plain C function as provided as a parameter. + */ + public: + MicroBitSystemTimerCallback(void (*function)(void)) + { + fn = function; + system_timer_add_component(this); + } + + void systemTick() + { + fn(); + } +}; + +#endif diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 3084b16..01dfe76 100755 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -16,6 +16,7 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES "MicroBitCompass.cpp" "MicroBitEvent.cpp" "MicroBitFiber.cpp" + "MicroBitSystemTimer.cpp" "ManagedString.cpp" "Matrix4.cpp" "MicroBitAccelerometer.cpp" diff --git a/source/MicroBit.cpp b/source/MicroBit.cpp index 2a0acc3..ab48f64 100644 --- a/source/MicroBit.cpp +++ b/source/MicroBit.cpp @@ -112,8 +112,12 @@ void MicroBit::init() // Bring up the heap allocator, and reclaim as much memory from SoftDevice as possible. microbit_heap_init(); - // Bring up fiber scheduler. Wait a little while for state to stabilise. + // Bring up the system timer. + system_timer_init(SYSTEM_TICK_PERIOD_MS); + + // Bring up fiber scheduler. scheduler_init(&messageBus); + // Load any stored calibration data from persistent storage. MicroBitStorage s = MicroBitStorage(); MicroBitConfigurationBlock *b = s.getConfigurationBlock(); @@ -536,7 +540,7 @@ void MicroBit::seedRandom(uint32_t seed) */ int MicroBit::addSystemComponent(MicroBitComponent *component) { - return fiber_add_system_component(component); + return system_timer_add_component(component); } /** @@ -547,7 +551,7 @@ int MicroBit::addSystemComponent(MicroBitComponent *component) */ int MicroBit::removeSystemComponent(MicroBitComponent *component) { - return fiber_remove_system_component(component); + return system_timer_remove_component(component); } /** @@ -581,7 +585,7 @@ int MicroBit::removeIdleComponent(MicroBitComponent *component) */ unsigned long MicroBit::systemTime() { - return ticks; + return system_timer_current_time(); } diff --git a/source/MicroBitButton.cpp b/source/MicroBitButton.cpp index 4fc137c..e9eb655 100644 --- a/source/MicroBitButton.cpp +++ b/source/MicroBitButton.cpp @@ -28,7 +28,7 @@ MicroBitButton::MicroBitButton(uint16_t id, PinName name, MicroBitButtonEventCon this->eventConfiguration = eventConfiguration; this->downStartTime = 0; this->sigma = 0; - fiber_add_system_component(this); + system_timer_add_component(this); } /** @@ -84,7 +84,7 @@ void MicroBitButton::systemTick() MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_DOWN); //Record the time the button was pressed. - downStartTime=ticks; + downStartTime = system_timer_current_time(); } // Check to see if we have on->off state change. @@ -96,7 +96,7 @@ void MicroBitButton::systemTick() if (eventConfiguration == MICROBIT_BUTTON_ALL_EVENTS) { //determine if this is a long click or a normal click and send event - if((ticks - downStartTime) >= MICROBIT_BUTTON_LONG_CLICK_TIME) + if((system_timer_current_time() - downStartTime) >= MICROBIT_BUTTON_LONG_CLICK_TIME) MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_LONG_CLICK); else MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_CLICK); @@ -104,7 +104,7 @@ void MicroBitButton::systemTick() } //if button is pressed and the hold triggered event state is not triggered AND we are greater than the button debounce value - if((status & MICROBIT_BUTTON_STATE) && !(status & MICROBIT_BUTTON_STATE_HOLD_TRIGGERED) && (ticks - downStartTime) >= MICROBIT_BUTTON_HOLD_TIME) + if((status & MICROBIT_BUTTON_STATE) && !(status & MICROBIT_BUTTON_STATE_HOLD_TRIGGERED) && (system_timer_current_time() - downStartTime) >= MICROBIT_BUTTON_HOLD_TIME) { //set the hold triggered event flag status |= MICROBIT_BUTTON_STATE_HOLD_TRIGGERED; @@ -128,5 +128,5 @@ int MicroBitButton::isPressed() */ MicroBitButton::~MicroBitButton() { - fiber_remove_system_component(this); + system_timer_remove_component(this); } diff --git a/source/MicroBitDisplay.cpp b/source/MicroBitDisplay.cpp index cc8cae0..59be541 100644 --- a/source/MicroBitDisplay.cpp +++ b/source/MicroBitDisplay.cpp @@ -50,7 +50,7 @@ MicroBitDisplay::MicroBitDisplay(uint16_t id, uint8_t x, uint8_t y) : if (!this->defaultDisplay) this->defaultDisplay = this; - fiber_add_system_component(this); + system_timer_add_component(this); status |= MICROBIT_COMPONENT_RUNNING; } @@ -153,7 +153,7 @@ void MicroBitDisplay::render() //timer does not have enough resolution for brightness of 1. 23.53 us if(brightness != MICROBIT_DISPLAY_MAXIMUM_BRIGHTNESS && brightness > MICROBIT_DISPLAY_MINIMUM_BRIGHTNESS) - renderTimer.attach_us(this, &MicroBitDisplay::renderFinish, (((brightness * 950) / (MICROBIT_DISPLAY_MAXIMUM_BRIGHTNESS)) * scheduler_get_tick_period())); + renderTimer.attach_us(this, &MicroBitDisplay::renderFinish, (((brightness * 950) / (MICROBIT_DISPLAY_MAXIMUM_BRIGHTNESS)) * system_timer_get_period())); //this will take around 23us to execute if(brightness <= MICROBIT_DISPLAY_MINIMUM_BRIGHTNESS) @@ -247,7 +247,7 @@ MicroBitDisplay::animationUpdate() if (animationMode == ANIMATION_MODE_NONE) return; - animationTick += FIBER_TICK_PERIOD_MS; + animationTick += system_timer_get_period(); if(animationTick >= animationDelay) { @@ -939,17 +939,12 @@ void MicroBitDisplay::setDisplayMode(DisplayMode mode) if(mode == DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE) { //to reduce the artifacts on the display - increase the tick - if(scheduler_get_tick_period() != MICROBIT_LIGHT_SENSOR_TICK_PERIOD) - scheduler_set_tick_period(MICROBIT_LIGHT_SENSOR_TICK_PERIOD); + if(system_timer_get_period() != MICROBIT_LIGHT_SENSOR_TICK_PERIOD) + system_timer_set_period(MICROBIT_LIGHT_SENSOR_TICK_PERIOD); } if(this->mode == DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE && mode != DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE) { - - //if we previously were in light sense mode - return to our default. - if(scheduler_get_tick_period() != FIBER_TICK_PERIOD_MS) - scheduler_set_tick_period(FIBER_TICK_PERIOD_MS); - delete this->lightSensor; this->lightSensor = NULL; @@ -1216,5 +1211,5 @@ int MicroBitDisplay::readLightLevel() */ MicroBitDisplay::~MicroBitDisplay() { - fiber_remove_system_component(this); + system_timer_remove_component(this); } diff --git a/source/MicroBitEvent.cpp b/source/MicroBitEvent.cpp index d9c0d04..d37505d 100644 --- a/source/MicroBitEvent.cpp +++ b/source/MicroBitEvent.cpp @@ -21,7 +21,7 @@ MicroBitEvent::MicroBitEvent(uint16_t source, uint16_t value, MicroBitEventLaunc { this->source = source; this->value = value; - this->timestamp = ticks; + this->timestamp = system_timer_current_time(); if(mode != CREATE_ONLY) this->fire(mode); @@ -34,7 +34,7 @@ MicroBitEvent::MicroBitEvent() { this->source = 0; this->value = 0; - this->timestamp = ticks; + this->timestamp = system_timer_current_time(); } /** diff --git a/source/MicroBitFiber.cpp b/source/MicroBitFiber.cpp index 1f4387f..9e65af5 100644 --- a/source/MicroBitFiber.cpp +++ b/source/MicroBitFiber.cpp @@ -25,13 +25,6 @@ static Fiber *sleepQueue = NULL; // The list of blocked fibers static Fiber *waitQueue = NULL; // The list of blocked fibers waiting on an event. static Fiber *fiberPool = NULL; // Pool of unused fibers, just waiting for a job to do. -/* - * Time since power on. Measured in milliseconds. - * When stored as an unsigned long, this gives us approx 50 days between rollover, which is ample. :-) - */ -unsigned long ticks = 0; -static unsigned int tickPeriod = FIBER_TICK_PERIOD_MS; - /* * Scheduler wide flags */ @@ -43,15 +36,9 @@ static uint8_t fiber_flags = 0; */ static MicroBitMessageBus *messageBus = NULL; -// Array of components which are iterated during a system tick -static MicroBitComponent* systemTickComponents[MICROBIT_SYSTEM_COMPONENTS]; - // Array of components which are iterated during idle thread execution, isIdleCallbackNeeded is polled during a systemTick. static MicroBitComponent* idleThreadComponents[MICROBIT_IDLE_COMPONENTS]; -// Periodic callback interrupt -static Ticker fiberSchedulerTicker; - /** * Utility function to add the currenty running fiber to the given queue. * Perform a simple add at the head, to avoid complexity, @@ -190,39 +177,11 @@ void scheduler_init(MicroBitMessageBus *_messageBus) } // register a period callback to drive the scheduler and any other registered components. - fiberSchedulerTicker.attach_us(scheduler_tick, tickPeriod * 1000); + new MicroBitSystemTimerCallback(scheduler_tick); fiber_flags |= MICROBIT_SCHEDULER_RUNNING; } -/* - * Reconfigures the system wide timer to the given period in milliseconds. - * - * @param speedMs the new period of the timer in milliseconds - * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if speedMs < 1 - * - * @note this will also modify the value that is added to ticks in MiroBitFiber:scheduler_tick() - */ -int scheduler_set_tick_period(int speedMs) -{ - if(speedMs < 1) - return MICROBIT_INVALID_PARAMETER; - - tickPeriod = speedMs; - fiberSchedulerTicker.detach(); - fiberSchedulerTicker.attach_us(scheduler_tick, tickPeriod * 1000); - - return MICROBIT_OK; -} - -/* - * Returns the currently used tick speed in milliseconds - */ -int scheduler_get_tick_period() -{ - return tickPeriod; -} - /** * Determines if the fiber scheduler is operational. * @return 1 if the fber scheduler is running, 0 otherwise. @@ -236,7 +195,7 @@ int fiber_scheduler_running() } /** - * Timer callback. Called from interrupt context, once every FIBER_TICK_PERIOD_MS milliseconds, by default. + * Timer callback. Called from interrupt context, once every SYSTEM_TICK_PERIOD_MS milliseconds, by default. * Simply checks to determine if any fibers blocked on the sleep queue need to be woken up * and made runnable. */ @@ -245,15 +204,12 @@ void scheduler_tick() Fiber *f = sleepQueue; Fiber *t; - // increment our real-time counter. - ticks += scheduler_get_tick_period(); - // Check the sleep queue, and wake up any fibers as necessary. while (f != NULL) { t = f->next; - if (ticks >= f->context) + if (system_timer_current_time() >= f->context) { // Wakey wakey! dequeue_fiber(f); @@ -262,11 +218,6 @@ void scheduler_tick() f = t; } - - // Update any components registered for a callback - for(int i = 0; i < MICROBIT_SYSTEM_COMPONENTS; i++) - if(systemTickComponents[i] != NULL) - systemTickComponents[i]->systemTick(); } /** @@ -355,7 +306,7 @@ void fiber_sleep(unsigned long t) } // Calculate and store the time we want to wake up. - f->context = ticks + t; + f->context = system_timer_current_time() + t; // Remove fiber from the run queue dequeue_fiber(f); @@ -785,50 +736,6 @@ void schedule() } } - -/** - * Add a component to to the collection of those invoked when the scheduler's periodic timer is triggered. - * The given component is called on each interrupt, within interrupt context. - * - * @param component The component to add. - * @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported. - * @note this will be converted into a dynamic list of components - */ -int fiber_add_system_component(MicroBitComponent *component) -{ - int i = 0; - - while(systemTickComponents[i] != NULL && i < MICROBIT_SYSTEM_COMPONENTS) - i++; - - if(i == MICROBIT_SYSTEM_COMPONENTS) - return MICROBIT_NO_RESOURCES; - - systemTickComponents[i] = component; - return MICROBIT_OK; -} - -/** - * remove a component from the array of components - * @param component The component to remove. - * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMTER is returned if the given component has not been previous added. - * @note this will be converted into a dynamic list of components - */ -int fiber_remove_system_component(MicroBitComponent *component) -{ - int i = 0; - - while(systemTickComponents[i] != component && i < MICROBIT_SYSTEM_COMPONENTS) - i++; - - if(i == MICROBIT_SYSTEM_COMPONENTS) - return MICROBIT_INVALID_PARAMETER; - - systemTickComponents[i] = NULL; - - return MICROBIT_OK; -} - /** * add a component to the array of components which invocate the systemTick member function during a systemTick * @param component The component to add. diff --git a/source/MicroBitMessageBus.cpp b/source/MicroBitMessageBus.cpp index 86a3bdc..b222ee7 100644 --- a/source/MicroBitMessageBus.cpp +++ b/source/MicroBitMessageBus.cpp @@ -265,7 +265,7 @@ int MicroBitMessageBus::isIdleCallbackNeeded() * * Example: * @code - * MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_DOWN,ticks,CREATE_ONLY); + * MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_DOWN,CREATE_ONLY); * evt.fire(); * * //OR YOU CAN DO THIS... diff --git a/source/MicroBitSystemTimer.cpp b/source/MicroBitSystemTimer.cpp new file mode 100644 index 0000000..60a261c --- /dev/null +++ b/source/MicroBitSystemTimer.cpp @@ -0,0 +1,138 @@ +/** + * Definitions for the MicroBit system timer. + * + * This module provides: + * + * 1) a concept of global system time since power up + * 2) a simple periodic multiplexing API for the underlying mbed implementation. + * + * The latter is useful to avoid costs associated with multiple mbed Ticker instances + * in microbit-dal components, as each incurs a significant additional RAM overhead (circa 80 bytes). + */ + +#include "MicroBit.h" + +/* + * Time since power on. Measured in milliseconds. + * When stored as an unsigned long, this gives us approx 50 days between rollover, which is ample. :-) + */ +static unsigned long ticks = 0; +static unsigned int tick_period = 0; + +// Array of components which are iterated during a system tick +static MicroBitComponent* systemTickComponents[MICROBIT_SYSTEM_COMPONENTS]; + +// Periodic callback interrupt +static Ticker timer; + + +/** + * Initialises the system wide timer. + * This must be called before any components register to receive periodic periodic callbacks. + * + * @param timer_period The initial period between interrupts, in millseconds. + * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if period is illegal. + */ +int system_timer_init(int period) +{ + return system_timer_set_period(period); +} + +/* + * Reconfigures the system wide timer to the given period in milliseconds. + * + * @param period the new period of the timer in milliseconds + * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if period < 1 + */ +int system_timer_set_period(int period) +{ + if (period < 1) + return MICROBIT_INVALID_PARAMETER; + + // If a timer is already running, ensure it is disabled before reconfiguring. + if (tick_period) + timer.detach(); + + // register a period callback to drive the scheduler and any other registered components. + tick_period = period; + timer.attach_us(system_timer_tick, period * 1000); + + return MICROBIT_OK; +} + +/* + * Provides the current tick period in milliseconds + * @return the current tick period in milliseconds + */ +int system_timer_get_period() +{ + return tick_period; +} + +/* + * Determines the time since the device was powered on. + * @return the current time since poweron in milliseconds + */ +unsigned long system_timer_current_time() +{ + return ticks; +} + +/** + * Timer callback. Called from interrupt context, once per period. + * Simply checks to determine if any fibers blocked on the sleep queue need to be woken up + * and made runnable. + */ +void system_timer_tick() +{ + // increment our real-time counter. + ticks += system_timer_get_period(); + + // Update any components registered for a callback + for(int i = 0; i < MICROBIT_SYSTEM_COMPONENTS; i++) + if(systemTickComponents[i] != NULL) + systemTickComponents[i]->systemTick(); +} + +/** + * Add a component to the array of system components. This component will then receive + * period callbacks, once every tick period. + * + * @param component The component to add. + * @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported. + */ +int system_timer_add_component(MicroBitComponent *component) +{ + int i = 0; + + while(systemTickComponents[i] != NULL && i < MICROBIT_SYSTEM_COMPONENTS) + i++; + + if(i == MICROBIT_SYSTEM_COMPONENTS) + return MICROBIT_NO_RESOURCES; + + systemTickComponents[i] = component; + return MICROBIT_OK; +} + +/** + * remove a component from the array of system components. this component will no longer receive + * period callbacks. + * @param component The component to remove. + * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previous added. + */ +int system_timer_remove_component(MicroBitComponent *component) +{ + int i = 0; + + while(systemTickComponents[i] != component && i < MICROBIT_SYSTEM_COMPONENTS) + i++; + + if(i == MICROBIT_SYSTEM_COMPONENTS) + return MICROBIT_INVALID_PARAMETER; + + systemTickComponents[i] = NULL; + + return MICROBIT_OK; +} + diff --git a/source/MicroBitThermometer.cpp b/source/MicroBitThermometer.cpp index e5db65d..02918e7 100644 --- a/source/MicroBitThermometer.cpp +++ b/source/MicroBitThermometer.cpp @@ -98,12 +98,12 @@ void MicroBitThermometer::idleTick() } /** - * Determines if we're due to take another temeoratur reading + * Determines if we're due to take another temperature reading * @return 1 if we're due to take a temperature reading, 0 otherwise. */ int MicroBitThermometer::isSampleNeeded() { - return ticks >= sampleTime; + return system_timer_current_time() >= sampleTime; } /** @@ -167,7 +167,7 @@ void MicroBitThermometer::updateTemperature() temperature = processorTemperature / 4; // Schedule our next sample. - sampleTime = ticks + samplePeriod; + sampleTime = system_timer_current_time() + samplePeriod; // Send an event to indicate that we'e updated our temperature. MicroBitEvent e(id, MICROBIT_THERMOMETER_EVT_UPDATE);