Skip to content

feature/ND/230/Node-Event-Scheduler #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b69abb1
Add untested EventScheduler class
ShaneTWilliams Nov 10, 2019
fb6a923
Add untested Event class
ShaneTWilliams Nov 10, 2019
3f515a7
Fix small i2c interface error for compiling purposes
ShaneTWilliams Nov 10, 2019
b65b01e
Remove local variable `event` and operate on member array of events
ShaneTWilliams Nov 10, 2019
9ac9542
Add setter for m_num_calls_left
ShaneTWilliams Nov 10, 2019
8b5233b
Change EventScheduler::callFunctionAfter behaviour to be callFunction…
ShaneTWilliams Nov 10, 2019
6448937
Remove example test
ShaneTWilliams Nov 10, 2019
973919c
Add more descriptive comments to EventScheduler class
ShaneTWilliams Nov 10, 2019
22cd84a
Add more descriptive comments to Event class
ShaneTWilliams Nov 10, 2019
db41025
Update platformio.ini to include event scheduler
ShaneTWilliams Nov 10, 2019
4158cad
Change order of callFunctionEvery args
ShaneTWilliams Nov 10, 2019
ce5c537
Add comments and whitespace fixes
ShaneTWilliams Nov 10, 2019
83ccf5c
Add testing main for EventScheduler class
ShaneTWilliams Nov 10, 2019
0cc3318
Remove Testing as default env before PR
ShaneTWilliams Nov 10, 2019
5d4195c
Add newlines to end of files
ShaneTWilliams Nov 16, 2019
a350ef7
Move implementation of `Event` methods to header
ShaneTWilliams Nov 16, 2019
6ab8189
Rename `Event` method `callCallback` to `callback` :(
ShaneTWilliams Nov 16, 2019
74b5964
Change `Event` class to a struct and change m_events from an array to…
ShaneTWilliams Nov 22, 2019
155521e
Change eventId_t from int8_t to int16_t in case if more than 127 even…
ShaneTWilliams Nov 22, 2019
1f59a72
Add getter for m_MAX_NUM_EVENTS
ShaneTWilliams Nov 22, 2019
5b9b4c6
Add unit tests suggested in PR
ShaneTWilliams Nov 22, 2019
426c7d1
Add new comments to EventScheduler class
ShaneTWilliams Nov 22, 2019
ea74d95
Add better comments to `findFreeEventId`
ShaneTWilliams Nov 22, 2019
cf8ad37
Move EventScheduler from Node/Common to OnPod/Common
ShaneTWilliams Nov 22, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions OnPod/Common/EventScheduler/include/event.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef NODE_EVENT_H
#define NODE_EVENT_H

#include <stdint.h>

typedef int16_t eventId_t; // Should range from 0-127. -1 indicates error in finding free ID
typedef uint32_t timeMs_t; // Time in ms

enum class EventType
{
FINITE, // Repeat X number of times
FOREVER, // Repeat forever
};

enum class EventState
{
STARTED,
STOPPED,
};

struct Event
{
EventType type = EventType::FINITE;
EventState state = EventState::STOPPED;
void (*callback)(void) = nullptr;
timeMs_t delay_ms = 0;
timeMs_t last_time_called_ms = 0;
uint32_t num_calls_left = 0;
eventId_t id = 0;
};

#endif
45 changes: 45 additions & 0 deletions OnPod/Common/EventScheduler/include/event_scheduler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#ifndef NODE_EVENT_SCHEDULER_H
#define NODE_EVENT_SCHEDULER_H

#include <map>
#include <stdint.h>
#include "event.h"

class EventScheduler
{
private:
// Number of events that can be active at once
static const int16_t m_MAX_NUM_EVENTS = 50;
// Map to hold events and their ids
std::map<eventId_t, Event> m_events;

// Return a free event id
eventId_t findFreeEventId(void);

public:
int16_t getMaxNumEvents(void) { return m_MAX_NUM_EVENTS; };
// Check if any callbacks must be called and execute them.
// If the repeat limit is reached, reset the event object.
void updateEvents(timeMs_t current_time);

// Resumes the event's calls
void startEvent(eventId_t event_id);
// Pauses all the event's calls.
// If the event has a certain number of repeats, they will be preserved after starting again.
void stopEvent(eventId_t event_id);

// Call `callback` every `delay_ms` milliseconds, `repeat_count` times.
// Returns index of event in `m_event_list` or -1 if `m_event_list` is full.
eventId_t callFunctionEvery(timeMs_t delay_ms, void (*callback)(void),
timeMs_t current_time, uint32_t repeat_count);
// Call `callback` every `delay_ms` milliseconds, forever.
// Returns index of event in `m_event_list` or -1 if `m_event_list` is full.
eventId_t callFunctionEvery(timeMs_t delay_ms, void (*callback)(void),
timeMs_t current_time);
// Call `callback` after `delay_ms` milliseconds.
// Returns index of event in `m_event_list` or -1 if `m_event_list` is full.
eventId_t callFunctionAfter(timeMs_t delay_ms, void (*callback)(void),
timeMs_t current_time);
};

#endif
125 changes: 125 additions & 0 deletions OnPod/Common/EventScheduler/src/event_scheduler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#include <vector>
#include "event_scheduler.h"

void EventScheduler::updateEvents(timeMs_t current_time)
{
// Can't erase key/value pairs in the for loop
// Keep track of them in this vector then erase them afterwards
std::vector<eventId_t> events_to_erase;
// Iterate over map to find events that are due
for (auto& [id, event] : m_events)
{
if (event.state == EventState::STOPPED)
{
continue;
}

if (current_time - event.last_time_called_ms >= event.delay_ms)
{
event.callback();
event.last_time_called_ms = current_time;
if (event.type == EventType::FINITE)
{
event.num_calls_left--;
if (event.num_calls_left == 0)
{
// Add to temporary vector to be removed
events_to_erase.push_back(id);
}
}
}
}
// Remove key/value pairs that had expired
for (auto const id : events_to_erase)
{
m_events.erase(id);
}
}

eventId_t EventScheduler::findFreeEventId(void)
{
// If map is too damn big return error
if (m_events.size() >= m_MAX_NUM_EVENTS)
{
return -1;
}
// If empty use first id, 0
if (m_events.empty())
{
return 0;
}
// Check for gaps in the map
// Iterate and see if index_being_checked is available
eventId_t index_being_checked = 0;
for (auto event : m_events)
{
if (event.first == index_being_checked)
{
index_being_checked++;
}
else
{
return index_being_checked;
}
}
// If there were no gaps in the map then use the next index up
if (index_being_checked <= m_MAX_NUM_EVENTS)
{
return index_being_checked;
}
return -1;
}

void EventScheduler::startEvent(eventId_t id)
{
m_events[id].state = EventState::STARTED;
}

void EventScheduler::stopEvent(eventId_t id)
{
m_events[id].state = EventState::STOPPED;
}

eventId_t EventScheduler::callFunctionEvery(timeMs_t delay_ms, void (*callback)(void),
timeMs_t current_time, uint32_t repeat_count)
{
eventId_t id = findFreeEventId();
if (id == -1)
{
return id;
}
Event event;
event.type = EventType::FINITE;
event.state = EventState::STARTED;
event.delay_ms = delay_ms;
event.last_time_called_ms = current_time;
event.callback = callback;
event.num_calls_left = repeat_count;
m_events.insert({id, event});
return id;
}

eventId_t EventScheduler::callFunctionEvery(timeMs_t delay_ms, void (*callback)(void),
timeMs_t current_time)
{
eventId_t id = findFreeEventId();
if (id == -1)
{
return id;
}
Event event;
event.type = EventType::FOREVER;
event.state = EventState::STARTED;
event.delay_ms = delay_ms;
event.last_time_called_ms = current_time;
event.callback = callback;
event.num_calls_left = 0;
m_events.insert({id, event});
return id;
}

eventId_t EventScheduler::callFunctionAfter(timeMs_t delay_ms, void (*callback)(void),
timeMs_t current_time)
{
return callFunctionEvery(delay_ms, callback, current_time, 1);
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class I2CInterface
HAL_StatusTypeDef memRead(uint16_t devAddress, uint16_t memAddress,
uint16_t memAddressSize, uint32_t timeout);

HAL_StatusTypeDef isDeviceReady(uint16_t devAddress, uint32_t trials = 100, uint32_t timeout);
HAL_StatusTypeDef isDeviceReady(uint16_t devAddress, uint32_t trials, uint32_t timeout);

/*
Config methods for digital and analog noise filters
Expand Down
Loading