For the megasquirtavr we needed to schedule injection and ignition on/off (IO-port) events with little overhead, preferrably with great precision. Similar functionality is often needed in realtime microcontroller systems. Read about timed events and eventqueue here"

There are several choices for this:

The precisely timed interrupts are possible with timer interrupts found in several uCs (eg. atmeg128 has 2 8 bit and 2 16 bit timers). With timers a small footprint, efficient and precise timing is possible. (4usec is a practical target on the atmega128, but needs to keep other interrupt handlers small - or maybe allow nested interrupts).
We still need to take care about the mainloop, arrange it to execute more critical tasks in time (we can use a scheduler there), but mostly freed from the very time critical tasks it can focus on the main logic of the application and precalculate the time of events or fill in variables that are used from interrupt to calculate event times (like the phase, rpm and ignition advance and injector pulsewidth of an engine).

I believe that similar functionality is needed in lots of applications, so I explained it on this page. Also I'm lazy to explain the same thing in dozens of emails, I like to send just pointers instead ;=) It's a little bit more organized and linkable than a passingby message in a forum.
You can find the untested code here Some explanations (cut from an email message):


> you would like to explain to the rest of the group how your
> implementation of a heap based system works

First I answer the 'why'.

There are several ways to do timing. We can poll in a loop or
have a 10kHz interrupt, or we can separate these issues:
find out when the events are due and have a mechanism to execute them.
This easies programming. Obviously we will have more complex
functions (think of ion-sense) which we will not want to clutter
with doing a bit of (unrelated tweak) here and there. This
can help make the code readable and higher quality, with
less overhead and more time for higher level functions.
We still need to fit the overall functionality into the clocktics,
but not need to care with all little places of the code.

The eventqueue works this way:
we have the events in a heap semi-sorted according to their scheduled
time (type key_t). The heap is a packed binary-tree.   
The root index is 1 (HEAPROOT), the children have the indexes 2x and  2x+1
of their parent (with index == x) (see heap.c parent() and child() functions).

At the root is the smallest key (next to do) event.
This is what we need most (the next event to do). The parent's key is 
always smaller (or equal) than the children. This makes it possible
to do insertion and deletion in a very efficient, guaranteed logarithmic
(to the number of elements in the heap) time.

However, since 16 bit resolution overflows fast (4usec*65536 ~ 1/4sec)
we need a small trick: we use 2 heaps. If time is currently 45000,
the keys >45000 are inserted into the normal heap (hn), and 
smaller keys inserted into the overflow-heap (ho). This is necessary because
of the incontinuity (47000 is before 2000, although 2000 is smaller).
When the timer overflows, we consume the normal heap, and swap the 2 heaps.

 the draft untested code at
 http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/megasquirtavr/firmware/

 To start with, view
 eventqueue.c:
 SIGNAL (SIG_OUTPUT_COMPARE2)

 and heap.c:
 void heap_replace1st(uint16_t key, uint16_t val)

dispatcher.c:
void dispatcher(val_t)
If many types of events are to be handled, this should be implemented with
a hash or maybe tree. (not a big switch-case)

Note, that the dispatcher is configurable, it should fire or stop an injector like 4 sequential LOW-Z (PWM-ed) injbanks on
injector-event-scheduling
Or anything that is useful in your application. For port functions look at dispatcher.[ch] (Like address, mask and OR/AND/SET etc op )

Any comments, questions, improvements, warnings etc. are welcome.


Please send updates to this page or other documentation to cell at x-dsl.hu preferrably in html or diff form. Thanx.
genboard page