finished messing with timer :) (for now)
main.c is now out of the timer business (except for "ticking" cycles... since there really is no other way to guarantee something runs exactly once per scan cycle)partial-rewrite
parent
7371362576
commit
0b6103d6c3
|
@ -10,9 +10,9 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ uint8_t timer__schedule__milliseconds ( uint16_t milliseconds,
|
|||
// ----------------------------------------------------------------------------
|
||||
// private
|
||||
|
||||
void timer___increment_cycles (void);
|
||||
void timer___tick_cycles (void);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -189,13 +189,14 @@ void timer___increment_cycles (void);
|
|||
// ----------------------------------------------------------------------------
|
||||
// private
|
||||
|
||||
// === timer___increment_cycles() ===
|
||||
/** functions/timer___increment_cycles/description
|
||||
// === timer___tick_cycles() ===
|
||||
/** functions/timer___tick_cycles/description
|
||||
* Increment the counter for the number of cycles, and perform scheduled tasks
|
||||
*
|
||||
* Meant to be used only by `main()`
|
||||
*
|
||||
* Notes:
|
||||
* - See "./event-list.h" regarding the function name.
|
||||
* - The corresponding real-time function (dealing with milliseconds instead of
|
||||
* cycles) will be in an interrupt vector, and not explicitly called anywhere
|
||||
* in the code.
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/** description
|
||||
* Implements the non device specific functionality of
|
||||
* ".../firmware/lib/timer", and all the functions defined in "./common.h"
|
||||
*/
|
||||
|
||||
|
||||
#include "./common.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t timer__init(void) {
|
||||
_cycles_scheduled = list__new();
|
||||
_milliseconds_scheduled = list__new();
|
||||
_milliseconds_to_schedule = list__new();
|
||||
|
||||
if ( !_cycles_scheduled ||
|
||||
!_milliseconds_scheduled ||
|
||||
!_milliseconds_to_schedule ) {
|
||||
|
||||
list__free(_cycles_scheduled);
|
||||
list__free(_milliseconds_scheduled);
|
||||
list__free(_milliseconds_to_schedule);
|
||||
|
||||
return 1; // error
|
||||
}
|
||||
|
||||
return _device__init();
|
||||
}
|
||||
|
||||
uint16_t timer__get_cycles(void) {
|
||||
return _cycles;
|
||||
}
|
||||
|
||||
uint16_t timer__get_milliseconds(void) {
|
||||
return _milliseconds;
|
||||
}
|
||||
|
||||
uint8_t timer__schedule_cycles(uint16_t cycles, void(*function)(void)) {
|
||||
// - there is the possibility that this function could be called by an
|
||||
// event executing within an interrupt vector. if that happens, and the
|
||||
// interrupt originally interrupted this same function, it wouldn't be
|
||||
// safe to operate on `_cycles_scheduled`
|
||||
if (lock) return 1; // error
|
||||
lock = true;
|
||||
|
||||
uint8_t ret = _event_list__append(_cycles_scheduled, cycles, function);
|
||||
|
||||
lock = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t timer__schedule_milliseconds( uint16_t milliseconds,
|
||||
void(*function)(void) ) {
|
||||
// - even though the only other place `...to_schedule` should be referenced
|
||||
// is within an interrupt vector (which this function can't interrupt),
|
||||
// we have to be careful: what if this function is interrupted, and an
|
||||
// event executes that calls this function? this function would
|
||||
// essentially be interrupting itself. we must avoid that.
|
||||
if (_milliseconds_to_schedule_lock) return 1; // error
|
||||
_milliseconds_to_schedule_lock = true;
|
||||
|
||||
uint8_t ret = _event_list__append( _milliseconds_to_schedule,
|
||||
milliseconds,
|
||||
function );
|
||||
|
||||
_milliseconds_to_schedule_lock = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void timer___increment_cycles (void) {
|
||||
_cycles++;
|
||||
_event_list__update(_cycles_scheduled);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t _event_list__append( list__list_t * list,
|
||||
uint16_t ticks,
|
||||
void(*function)(void) ) {
|
||||
if (!function) return 0; // success: there is no function to add
|
||||
|
||||
_event_t * event = list__insert(list, -1, malloc(sizeof(_event_t)) );
|
||||
if (!event) return 1; // error
|
||||
|
||||
event->ticks = ticks;
|
||||
event->function = function;
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
void _event_list__update(list__list_t * list) {
|
||||
for (_event_t * event = list->head; event;) {
|
||||
if (event->ticks == 0) {
|
||||
(*event->function)();
|
||||
event = list__pop_node_next(list, event);
|
||||
} else {
|
||||
event->ticks--;
|
||||
event = event->_private.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _event_list__move(list__list_t * to, list__list_t * from) {
|
||||
if (from->length == 0) return; // nothing to move
|
||||
|
||||
((_event_t *)to->tail)->_private.next = from->head;
|
||||
to->tail = from->tail;
|
||||
to->length += from->length;
|
||||
|
||||
from->head = NULL;
|
||||
from->tail = NULL;
|
||||
from->length = 0;
|
||||
}
|
||||
|
|
@ -1,218 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/** description
|
||||
* A central place for all `#include`s and common definitions relevant to this
|
||||
* timer library
|
||||
*
|
||||
* Prefix: `_`
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ERGODOX_FIRMWARE__LIB__TIMER__COMMON__H
|
||||
#define ERGODOX_FIRMWARE__LIB__TIMER__COMMON__H
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "../../../firmware/lib/data-types/list.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
list__node_t _private; // "subclass" `list__node_t`
|
||||
uint16_t ticks; // cycles or milliseconds
|
||||
void(*function)(void);
|
||||
} _event_t;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint16_t _cycles;
|
||||
list__list_t * _cycles_scheduled;
|
||||
list__list_t * _cycles_to_schedule;
|
||||
list__list_t * _cycles_to_schedule_lock;
|
||||
|
||||
volatile uint16_t _milliseconds;
|
||||
list__list_t * _milliseconds_scheduled;
|
||||
list__list_t * _milliseconds_to_schedule;
|
||||
bool _milliseconds_to_schedule_lock;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t _device__init (void);
|
||||
|
||||
uint8_t _event_list__append ( list__list_t * list,
|
||||
uint16_t ticks,
|
||||
void(*function)(void) );
|
||||
void _event_list__update (list__list_t * list);
|
||||
void _event_list__move (list__list_t * to, list__list_t * from);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif // ERGODOX_FIRMWARE__LIB__TIMER__COMMON__H
|
||||
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// === Documentation ==========================================================
|
||||
// ============================================================================
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// typedefs -------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// === _event_t ===
|
||||
/** typedefs/_event_t/description
|
||||
* A struct to represent a scheduled event
|
||||
*
|
||||
* Members:
|
||||
* - `_private`: The C way of "subclassing" another type
|
||||
* - `ticks`: The number of cycles or milliseconds in which the given event
|
||||
* should run
|
||||
* - `function`: A pointer to the function to run
|
||||
*/
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// variables ------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// === _cycles ===
|
||||
/** variables/_cycles/description
|
||||
* The number of scan cycles since the timer was initialized (mod 2^16)
|
||||
*/
|
||||
|
||||
// === _cycles_scheduled ===
|
||||
/** variables/_cycles_scheduled/description
|
||||
* A list of scheduled events, to be run in a given number of cycles
|
||||
*
|
||||
* Meant to be used only by `timer___increment_cycles()` (after initialization)
|
||||
*/
|
||||
|
||||
// === _cycles_to_schedule ===
|
||||
//
|
||||
/** variables/_cycles_to_schedule/description
|
||||
* A list of events to schedule
|
||||
*
|
||||
* Meant to be used only by `timer__schedule_cycles()` and
|
||||
* `timer___increment_cycles()` (after initialization)
|
||||
*
|
||||
* `timer___increment_cycles()` will move the events in this list to
|
||||
* `_cycles_scheduled` the next time it runs and the latter list is not locked.
|
||||
*
|
||||
* The reason for having both `_cycles_scheduled` and `_cycles_to_schedule` is
|
||||
* that this allows us to only reference `_cycles_scheduled` from place, which
|
||||
* in turn allows us not to have to worry about whether that function will have
|
||||
* access to it when it runs.
|
||||
*/
|
||||
|
||||
// === _cycles_to_schedule_lock ===
|
||||
//
|
||||
/** variables/_milliseconds_to_schedule_lock/description
|
||||
* A lock for `_milliseconds_to_schedule`
|
||||
*
|
||||
* To make sure that if `timer__schedule_milliseconds()` is interrupted by the
|
||||
* interrupt vector that may touch `_milliseconds_to_schedule`, the interrupt
|
||||
* leaves the variable alone until the function is done with it.
|
||||
*/
|
||||
|
||||
// === _milliseconds ===
|
||||
/** variables/_milliseconds/description
|
||||
* The number of milliseconds since the timer was initialized (mod 2^16)
|
||||
*/
|
||||
|
||||
// === _milliseconds_scheduled ===
|
||||
/** variables/_milliseconds_scheduled/description
|
||||
* A list of scheduled events, to be run in a given number of milliseconds
|
||||
*
|
||||
* Meant to be used only in the interrupt vector responsible for updating
|
||||
* `_milliseconds` (after initialization)
|
||||
*/
|
||||
|
||||
// === _milliseconds_to_schedule ===
|
||||
/** variables/_milliseconds_to_schedule/description
|
||||
* A list of events to schedule
|
||||
*
|
||||
* Meant to be used only by `timer__schedule_milliseconds()` and the interrupt
|
||||
* vector that updates `_milliseconds` (after initialization)
|
||||
*
|
||||
* The responsible interrupt vector will move the events in this list to
|
||||
* `_milliseconds_scheduled` the next time it runs and the latter list is not
|
||||
* locked.
|
||||
*
|
||||
* The reason for having both `_milliseconds_scheduled` and
|
||||
* `_milliseconds_to_schedule` is that this way only the events that have not
|
||||
* yet been scheduled are effected if `timer__schedule_milliseconds()` is
|
||||
* interrupted by the interrupt vector. In this case, time for these
|
||||
* unscheduled events will not start being counted until they are scheduled,
|
||||
* hopefully on the interrupt vector's next run. If, on the other hand, there
|
||||
* were only one list and the function was interrupted, every event in the list
|
||||
* would be inaccessible to the interrupt vector, and we would not be able to
|
||||
* count time for *any* of them during that run.
|
||||
*/
|
||||
|
||||
// === _milliseconds_to_schedule_lock ===
|
||||
/** variables/_milliseconds_to_schedule_lock/description
|
||||
* A lock for `_milliseconds_to_schedule`
|
||||
*
|
||||
* To make sure that if `timer__schedule_milliseconds()` is interrupted by the
|
||||
* interrupt vector that may touch `_milliseconds_to_schedule`, the interrupt
|
||||
* leaves the variable alone until the function is done with it.
|
||||
*/
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// functions ------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// === _device__init() ===
|
||||
/** functions/_device__init/description
|
||||
* Initialize the device specific portions of the timer
|
||||
*
|
||||
* Meant to be called only by `timer__init()`
|
||||
*
|
||||
* Returns:
|
||||
* - success: `0`
|
||||
* - failure: [other]
|
||||
*/
|
||||
|
||||
// === _event_list__append() ===
|
||||
/** functions/_event_list__append/description
|
||||
* Append an event with the given attributes to `list`
|
||||
*
|
||||
* Arguments:
|
||||
* - `list`: The list to add the new event to
|
||||
* - `ticks`: The number of ticks to assign to the event
|
||||
* - `function`: A pointer to the function to assign to the event
|
||||
*
|
||||
* Returns:
|
||||
* - success: `0`
|
||||
* - failure: [other]
|
||||
*/
|
||||
|
||||
// === _event_list__update() ===
|
||||
/** functions/_event_list__update/description
|
||||
* Decrement the `ticks` of every event in `list` by `1`, and run any event
|
||||
* with `ticks == 0`
|
||||
*
|
||||
* Arguments:
|
||||
* - `list`: The list to update
|
||||
*/
|
||||
|
||||
// === _event_list__move() ===
|
||||
/** functions/_event_list__move/description
|
||||
* Move all events in `from` to `to`, and clear `to`
|
||||
*
|
||||
* Arguments:
|
||||
* - `to`: The list into which to move all elements
|
||||
* - `from`: The list to move all elements from
|
||||
*/
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/** description
|
||||
* Timer interface for device functions
|
||||
*
|
||||
* Prefix: `timer___device__`
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ERGODOX_FIRMWARE__LIB__TIMER__DEVICE__H
|
||||
#define ERGODOX_FIRMWARE__LIB__TIMER__DEVICE__H
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private
|
||||
|
||||
void timer___device__init (void);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif // ERGODOX_FIRMWARE__LIB__TIMER__DEVICE__H
|
||||
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// === documentation ==========================================================
|
||||
// ============================================================================
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// functions ------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// === timer___device__init() ===
|
||||
/** functions/timer___device__init/description
|
||||
* Initialize the device specific portions of the timer
|
||||
*/
|
||||
|
|
@ -5,16 +5,22 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/** description
|
||||
* Implements the device specific functionality of ".../firmware/lib/timer" for
|
||||
* the ATMega32U4
|
||||
* Implements the timer interface defined in ".../firmware/lib/timer.h" for the
|
||||
* ATMega32U4
|
||||
*
|
||||
* See the accompanying '.md' file for further documentation.
|
||||
*
|
||||
* Notes:
|
||||
* - Not all of this code is device-specific, but the parts that aren't are
|
||||
* trivial enough that it's not worth separating them.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include "../common.h"
|
||||
#include "../../../../firmware/lib/data-types/list.h"
|
||||
#include "../event-list.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -24,7 +30,44 @@
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t _device__init(void) {
|
||||
/** variables/_cycles/description
|
||||
* The number of scan cycles since the timer was initialized (mod 2^16)
|
||||
*/
|
||||
static uint16_t _cycles;
|
||||
|
||||
/** variables/_cycles__scheduled/description
|
||||
* A list of scheduled events, to be run in a given number of cycles
|
||||
*
|
||||
* After initialization, this should *only* be used as an argument to an
|
||||
* `event_list__...()` function.
|
||||
*/
|
||||
static list__list_t * _cycles__scheduled;
|
||||
|
||||
/** variables/_milliseconds/description
|
||||
* The number of milliseconds since the timer was initialized (mod 2^16)
|
||||
*/
|
||||
static volatile uint16_t _milliseconds;
|
||||
|
||||
/** variables/_milliseconds__scheduled/description
|
||||
* A list of scheduled events, to be run in a given number of milliseconds
|
||||
*
|
||||
* After initialization, this should *only* be used as an argument to an
|
||||
* `event_list__...()` function.
|
||||
*/
|
||||
static list__list_t * _milliseconds__scheduled;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t timer__init(void) {
|
||||
_cycles__scheduled = list__new();
|
||||
_milliseconds__scheduled = list__new();
|
||||
|
||||
if (!_cycles__scheduled || !_milliseconds__scheduled) {
|
||||
list__free(_cycles__scheduled);
|
||||
list__free(_milliseconds__scheduled);
|
||||
return 1; // error
|
||||
}
|
||||
|
||||
OCR0A = 250; // (ticks per millisecond)
|
||||
TCCR0A = 0b00000010; // (configure Timer/Counter 0)
|
||||
TCCR0B = 0b00000011; // (configure Timer/Counter 0)
|
||||
|
@ -34,17 +77,36 @@ uint8_t _device__init(void) {
|
|||
return 0; // success
|
||||
}
|
||||
|
||||
uint16_t timer__get_cycles(void) {
|
||||
return _cycles;
|
||||
}
|
||||
|
||||
uint16_t timer__get_milliseconds(void) {
|
||||
return _milliseconds;
|
||||
}
|
||||
|
||||
uint8_t timer__schedule_cycles(uint16_t cycles, void(*function)(void)) {
|
||||
return event_list__append(_cycles__scheduled, cycles, function);
|
||||
}
|
||||
|
||||
uint8_t timer__schedule_milliseconds( uint16_t milliseconds,
|
||||
void(*function)(void) ) {
|
||||
return event_list__append( _milliseconds__scheduled,
|
||||
milliseconds,
|
||||
function );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void timer___tick_cycles (void) {
|
||||
_cycles++;
|
||||
event_list__tick(_cycles__scheduled);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ISR(TIMER0_COMPA_vect) {
|
||||
_milliseconds++;
|
||||
|
||||
// if possible, move all events from `...to_schedule` into `...scheduled`
|
||||
// - interrupts are disabled here, so it's safe to operate on the list
|
||||
// without locking it, as long as it's not already locked
|
||||
if (!_milliseconds_to_schedule_lock)
|
||||
_event_list__move(_milliseconds_scheduled, _milliseconds_to_schedule);
|
||||
|
||||
_event_list__update(_milliseconds_scheduled);
|
||||
event_list__tick(_milliseconds__scheduled);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/** description
|
||||
* Event-list interface, to handle lists of scheduled events
|
||||
*
|
||||
* Prefix: `event_list__`
|
||||
*
|
||||
* Meant to be used only within ".../firmware/lib/timer"
|
||||
*
|
||||
*
|
||||
* Usage notes:
|
||||
*
|
||||
* - A "tick" is an ill-defined unit of time. It may represent any occurrence,
|
||||
* even a randomly timed one; but it makes the most sense for it to count
|
||||
* something that occurs predictably, like the passing of a millisecond, or
|
||||
* the completion of a scan cycle.
|
||||
*
|
||||
* - To "tick" (as a verb) is to denote the passage of a "tick" of time by
|
||||
* performing the actions corresponding thereto.
|
||||
*
|
||||
* - All functions declared here should be safe for use within interrupt
|
||||
* routines, as long as you pay attention to the warnings below.
|
||||
*
|
||||
*
|
||||
* Warnings:
|
||||
*
|
||||
* - Any list passed as an argument to one of these functions must not be used
|
||||
* *anywhere* except as an argument to one of these functions.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ERGODOX_FIRMWARE__LIB__TIMER__EVENT_LIST__H
|
||||
#define ERGODOX_FIRMWARE__LIB__TIMER__EVENT_LIST__H
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../../../firmware/lib/data-types/list.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t event_list__append ( list__list_t * list,
|
||||
uint16_t ticks,
|
||||
void(*function)(void) );
|
||||
void event_list__tick (list__list_t * list);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif // ERGODOX_FIRMWARE__LIB__TIMER__EVENT_LIST__H
|
||||
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// === Documentation ==========================================================
|
||||
// ============================================================================
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// functions ------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// === event_list__append() ===
|
||||
/** functions/event_list__append/description
|
||||
* Append an event with the given attributes to `list`
|
||||
*
|
||||
* Arguments:
|
||||
* - `list`: The list to add the new event to
|
||||
* - `ticks`: The number of ticks to assign to the event
|
||||
* - `function`: A function pointer to assign to the event
|
||||
*
|
||||
* Returns:
|
||||
* - success: `0`
|
||||
* - failure: [other]
|
||||
*/
|
||||
|
||||
// === event_list__tick() ===
|
||||
/** functions/event_list__tick/description
|
||||
* Perform any actions that should occur every "tick", and run functions as
|
||||
* scheduled
|
||||
*
|
||||
* Arguments:
|
||||
* - `list`: The list to "tick"
|
||||
*/
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/** description
|
||||
* Implements the event-list interface defined in "../event-list.h" for the
|
||||
* ATMega32U4 (though, the code should be the same for anything in the AVR
|
||||
* family)
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <util/atomic.h>
|
||||
#include "../../../../firmware/lib/data-types/list.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
list__node_t _private; // "subclass" `list__node_t`
|
||||
uint16_t ticks; // our unit of time
|
||||
void(*function)(void);
|
||||
} event_t;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t event_list__append( list__list_t * list,
|
||||
uint16_t ticks,
|
||||
void(*function)(void) ) {
|
||||
if (!function || !list) return 0; // success: nothing to do
|
||||
|
||||
event_t * event = malloc(sizeof(event_t));
|
||||
if (!event) return 1; // error
|
||||
|
||||
event->ticks = ticks;
|
||||
event->function = function;
|
||||
|
||||
ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
|
||||
list__insert(list, -1, event);
|
||||
}
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
void event_list__tick(list__list_t * list) {
|
||||
if (!list) return;
|
||||
|
||||
ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
|
||||
for (event_t * event = list->head; event;) {
|
||||
if (event->ticks == 0) {
|
||||
NONATOMIC_BLOCK( NONATOMIC_RESTORESTATE ) {
|
||||
(*event->function)();
|
||||
}
|
||||
event = list__pop_node_next(list, event);
|
||||
} else {
|
||||
event->ticks--;
|
||||
event = event->_private.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,6 @@
|
|||
#
|
||||
|
||||
|
||||
SRC += $(wildcard $(CURDIR)/*.c)
|
||||
SRC += $(wildcard $(CURDIR)/device/$(MCU).c)
|
||||
SRC += $(wildcard $(CURDIR)/event-list/$(MCU).c)
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ int main(void) {
|
|||
#undef off
|
||||
}
|
||||
|
||||
timer___increment_cycles();
|
||||
timer___tick_cycles();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue