Pages: [1]   Go Down
Author Topic: Event system  (Read 10721 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
God Member
*****
Karma: 2
Posts: 596
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all,
As part of a bigger project, I've written a simple event dispatching system.

Its purpose is to decouple code generating an event (e.g. after debouncing a pushbutton the program "declares" that a key has been pressed) from the code that implements a response to that event (e.g. toggle a led or switch to a different menu page).

The system is composed of:
events
an event queue class
an event dispatcher class

Events are represented by an integer value. Each event has also an optional parameter, which is also an integer value. The parameter value is ignored by the system, and its meaning depends on what the user supplied code does with it.

Events are put into the system by inserting them into the event queue.

The dispatcher has to be set up so that a particular function will be called when a certain event (i.e. integer value) is extracted from the event queue.

Event codes are just integer values. For ease of use, though, some integer constants are already defined (e.g. EV_TIME, EV_SERIAL).

Since the event queue and event dispatcher are classes, multiple instances of them can be used in the same program (although I don't see advantages in doing so). One just has to be sure that each event dispatcher has its own event queue (i.e. two dispatchers cannot work on the same event queue).

So what does a sketch that uses the library look like ?
Let's make a very simple example.

Each second an event is generated.
The event handler prints the elapsed time (in seconds).

Code:
#include <Events.h>
#include <EventQueue.h>
#include <EventDispatcher.h>

// the event queue
EventQueue q;

// the event dispatcher
EventDispatcher disp(&q);

// time event handler
void timeHandler(int event, int param) {
    Serial.print("Time elapsed: ");
    Serial.println(millis() / 1000);
}

// this function generates an EV_TIME event
// each 1000 ms
void timeManager() {
    static unsigned long prevMillis = 0;
    unsigned long currMillis = millis();
    if (currMillis - prevMillis >= 1000) {
        prevMillis = currMillis;
        q.enqueueEvent(Events::EV_TIME, 0);    // param is not used here
    }
}

// program setup
void setup() {
    Serial.begin(115200);
    
    // make the dispatcher call timeHandler function
    // when an EV_TIME occurs
    disp.addEventListener(Events::EV_TIME, timeHandler);
}

// loop
void loop() {
    // call the event generating function
    timeManager();

    // get events from the queue and call the
    // registered function(s)
    disp.run();
}

Obviously the whole thing is overkill for such a trivial example.
It gets interesting if you have multiple event sources, though.

Let's expand the example by adding an "analog monitoring" function.

Analog channel 0 is continuously read. If its value changes by a specified amount, an event is generated. The event parameter is used to pass the current analog value to the event handler
The event handler simply prints the parameter value, but it could also easily map that value to 0.255 and call analogWrite(), thus linking e.g. a led intensity to a potentiometer position.

Code:
#include <Events.h>
#include <EventQueue.h>
#include <EventDispatcher.h>

// the event queue
EventQueue q;

// the event dispatcher
EventDispatcher disp(&q);

// use this analog channel
#define AN_CHAN 0

// generate an event when the analog
// channel value changes this much
// increase value for noisy sources
#define AN_DELTA 5

// time event handler
void timeHandler(int event, int param) {
    Serial.print("Time elapsed: ");
    Serial.println(millis() / 1000);
}

// analog event handler
void analogHandler(int event, int param) {
    Serial.print("Analog value: ");
    Serial.println(param);
}

// this function generates an EV_TIME event
// each 1000 ms
void timeManager() {
    static unsigned long prevMillis = 0;
    unsigned long currMillis;

    currMillis = millis();
    if (currMillis - prevMillis >= 1000) {
        prevMillis = currMillis;
        q.enqueueEvent(Events::EV_TIME, 0);    // param is not used here
    }
}

// this function generates an EV_ANALOG event
// whenever the analog channel AN_CHAN changes
void analogManager() {
    static int prevValue = 0;
    int currValue;

    currValue = analogRead(AN_CHAN);

    if (abs(currValue - prevValue) >= AN_DELTA) {
        prevValue = currValue;
        q.enqueueEvent(Events::EV_ANALOG0, currValue);    // use param to pass analog value to event handler
    }
}

// program setup
void setup() {
    Serial.begin(115200);
    
    disp.addEventListener(Events::EV_TIME, timeHandler);
    disp.addEventListener(Events::EV_ANALOG0, analogHandler);
}

// loop
void loop() {
    // call the event generating functions
    timeManager();
    analogManager();

    // get events from the queue and call the
    // registered function(s)
    disp.run();
}


Another area where this approach becomes useful (at least IMHO) is keyboard / keypad management. For this I've written a few other classes, that I'm planning to publish too.

PS: library code will follow soon.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 631
Posts: 50115
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
PS: library code will follow soon.

Looks pretty interesting. Do follow up with the library.
Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 596
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Events.h

Code:
/*
 * Events.h
 *
 * Part of Arduino Event System.
 *
 * Author: mromani@ottotecnica.com
 * Copyright (c) 2010 OTTOTECNICA Italy
 *
 * This library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser
 * General Public License along with this library; if not,
 * write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#ifndef Events_h
#define Events_h

#include <WProgram.h>

// Some common events.
// Codes 0..199 are available for
// user defined events.

class Events {

public:
    enum eventType {
        // no event occurred
        // param: none
        EV_NONE = 200,
        
        // a key was pressed
        // param: key code
        EV_KEY_PRESS,
        
        // a key was released
        // param: key code
        EV_KEY_RELEASE,
        
        // use this to notify a character
        // param: the character to be notified
        EV_CHAR,
        
        // generic time event
        // param: a time value (exact meaning is defined
        // by the code inserting this event into the queue)
        EV_TIME,
        
        // generic timer events
        // param: same as EV_TIME
        EV_TIMER0,
        EV_TIMER1,
        EV_TIMER2,
        EV_TIMER3,
        
        // analog read (last number = analog channel)
        // param: value read
        EV_ANALOG0,
        EV_ANALOG1,
        EV_ANALOG2,
        EV_ANALOG3,
        EV_ANALOG4,
        EV_ANALOG5,
        
        // menu events
        EV_MENU0,
        EV_MENU1,
        EV_MENU2,
        EV_MENU3,
        EV_MENU4,
        EV_MENU5,
        EV_MENU6,
        EV_MENU7,
        EV_MENU8,
        EV_MENU9,

        // serial event
        // example: a new char is available
        //          param: the return value of Serial.read()
        EV_SERIAL,
        
        // LCD screen needs to be refreshed
        EV_PAINT
    };
};

#endif
Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 596
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

EventQueue.h

Code:
/*
 * EventQueue.h
 *
 * Part of Arduino Event System.
 *
 * Author: mromani@ottotecnica.com
 * Copyright (c) 2010 OTTOTECNICA Italy
 *
 * This library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser
 * General Public License along with this library; if not,
 * write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#ifndef EventQueue_h
#define EventQueue_h

#include <WProgram.h>
#include <Events.h>

class EventQueue {

public:
    // Event queue size.
    // The maximum number of events
    // the queue can hold is EVQUEUE_SIZE - 1.
    // Increasing this number will consume 2 * sizeof(int)
    // bytes of RAM for each unit.
    static const int EVQUEUE_SIZE = 10;

    // Queue constructor
    EventQueue();

    // returns true if no events are in the queue
    boolean isEmpty();

    // returns true if no more events can be inserted into the queue
    boolean isFull();

    // actual number of events in queue
    int getNumEvents();

    // tries to insert an event into the queue;
    // returns true if successful, false if the
    // queue if full and the event cannot be inserted
    boolean enqueueEvent(int ev_code, int ev_param);

    // tries to extract an event from the queue;
    // returns true if successful, false if the
    // queue is empty (the parameteres are not touched
    // in this case)
    boolean dequeueEvent(int* ev_code, int* ev_param);

private:
    // each event is represented by an integer code
    int eventQueue[EVQUEUE_SIZE];

    // each event has a single integer parameter
    int eventParam[EVQUEUE_SIZE];

    // index of event queue head
    int eventQueueHead;

    // index of event queue tail
    int eventQueueTail;

    // actual number of events in queue
    int numEvents;

    // initialize event queue - to be called only by constructor
    void init();
};

#endif

EventQueue.cpp

Code:
/*
 * EventQueue.cpp
 *
 * Part of Arduino Event System.
 *
 * Author: mromani@ottotecnica.com
 * Copyright (c) 2010 OTTOTECNICA Italy
 *
 * This library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser
 * General Public License along with this library; if not,
 * write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#include "EventQueue.h"


EventQueue::EventQueue() {
    init();
}


void EventQueue::init() {
  int i;
  
  eventQueueHead = 0;
  eventQueueTail = EVQUEUE_SIZE - 1;
  numEvents = 0;
  
  for (i = 0; i < EVQUEUE_SIZE; i++) {
    eventQueue[i] = Events::EV_NONE;
    eventParam[i] = 0;
  }
}


boolean EventQueue::isEmpty() {
  return (numEvents == 0);
}


boolean EventQueue::isFull() {
  return (eventQueueHead == eventQueueTail);
}


int EventQueue::getNumEvents() {
  return numEvents;
}


boolean EventQueue::enqueueEvent(int ev_code, int ev_param) {

  if (isFull()) {
    // log the queue full error
    Serial.print(millis());
    Serial.println(" QUEUE FULL");
    return false;
  }

  // store the event
  eventQueue[eventQueueHead] = ev_code;
  eventParam[eventQueueHead] = ev_param;

  // update queue head value
  eventQueueHead = (eventQueueHead + 1) % EVQUEUE_SIZE;;

  // update number of events in queue
  numEvents++;

  return true;
}


boolean EventQueue::dequeueEvent(int* ev_code, int* ev_param) {
  int temp;
  boolean isEmpty;
  
  if (numEvents == 0) {
    return false;
  }

  eventQueueTail = (eventQueueTail + 1) % EVQUEUE_SIZE;

  // store event code and event parameter
  // into the user-supplied variables
  *ev_code = eventQueue[eventQueueTail];
  *ev_param = eventParam[eventQueueTail];

  // update number of events in queue
  numEvents--;

  return true;
}
Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 596
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

EventDispatcher.h

Code:
/*

 * EventDispatcher.h

 *

 * Part of Arduino Event System.
 *
 * Author: mromani@ottotecnica.com
 * Copyright (c) 2010 OTTOTECNICA Italy
 *
 * This library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser
 * General Public License along with this library; if not,
 * write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */



#ifndef EventDispatcher_h

#define EventDispatcher_h



#include <WProgram.h>

#include <Events.h>

#include <EventQueue.h>





typedef void (*EventListener)(int ev_code, int ev_param);





class EventDispatcher {



public:

    // maximum number of event/callback entries

    // can be changed to save memory or allow more events to be dispatched

    static const int MAX_LISTENERS = 20;

    

    enum OverwriteOption { ALWAYS_APPEND, OVERWRITE_EVENT };

    

    // the function f will be called when event ev_code will be dequeued

    // returns true if the listener is successfully installed,

    // false otherwise (e.g. the dispatch table is full)

    // Overwrite options:

    // ALWAYS_APPEND   = just add ev_code/f to the list

    // OVERWRITE_EVENT = if a listener with the same event is found, replace its function with f

    boolean addEventListener(int ev_code, EventListener f, OverwriteOption overwrite = ALWAYS_APPEND);

    

    // remove event listener

    // other listeners with the same function or ev_code will not be affected

    boolean removeEventListener(int ev_code, EventListener f);

    

    // enable or disable a listener

    // return true if the listener was successfully enabled or disabled,

    // false if the listener was not found

    boolean enableEventListener(int ev_code, EventListener f, boolean enable);

    

    boolean isEventListenerEnabled(int ev_code, EventListener f);

    

    // the default listener is a callback function that is called when

    // an event with no listener is dequeued

    boolean setDefaultListener(EventListener f);

    void removeDefaultListener();

    void enableDefaultListener(boolean enable);

    

    // this must be continuously called (in loop())

    void run();

    

    // get the current number of entries in the dispatch table

    int getNumEntries() { return numListeners; }

    

    // get a referenct to the underlying event queue

    EventQueue* getEventQueue() { return q; }



    // a dispatcher is used to process events of a particular queue

    EventDispatcher(EventQueue* evQueue);



private:

    // event queue to be managed

    EventQueue* q;

    

    // actual number of event listeners

    int numListeners;



    // pointers to callback functions

    EventListener callback[MAX_LISTENERS];

    

    // each listener observes a specific event type

    int eventCode[MAX_LISTENERS];

    

    // each listener can be enabled or disabled

    boolean enabled[MAX_LISTENERS];

    

    // callback function to be called for event types

    // which have no listener

    EventListener defaultCallback;

    

    // once set, the default callback function can be enabled or disabled

    boolean defaultCallbackEnabled;

    

    // returns the array index of the specified listener

    // or -1 if no such event/function couple is found

    int _searchEventListener(int ev_code, EventListener f);

    

    int _searchEventCode(int ev_code);

};



#endif


EventDispatcher.cpp

Code:
/*

 * EventDispatcher.cpp

 *

 * Part of Arduino Event System.
 *
 * Author: mromani@ottotecnica.com
 * Copyright (c) 2010 OTTOTECNICA Italy
 *
 * This library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser
 * General Public License along with this library; if not,
 * write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */


#include "EventDispatcher.h"





EventDispatcher::EventDispatcher(EventQueue* evQueue) {

    q = evQueue;

    numListeners = 0;

}





boolean EventDispatcher::addEventListener(int ev_code, EventListener f, OverwriteOption overwrite) {

    int k;

    

    // argument check

    if (f == 0) {

        return false;

    }

    

    if (overwrite == OVERWRITE_EVENT) {

        k = _searchEventCode(ev_code);

        if (k >= 0) {           // event code found

            callback[k] = f;    // replace function

            enabled[k] = true;  // it's an add(), so enable the listener

            return true;

        }

    }



    // APPEND or (OVERWRITE and NOT FOUND)

    

    // dispatch table is full

    if (numListeners == MAX_LISTENERS) {

        return false;

    }

    

    callback[numListeners] = f;

    eventCode[numListeners] = ev_code;

    enabled[numListeners] = true;

    

    numListeners++;

    

    return true;

}





boolean EventDispatcher::removeEventListener(int ev_code, EventListener f) {

    int i;

    int k;

    

    if (numListeners == 0) {

        return false;

    }

    

    k = _searchEventListener(ev_code, f);

    if (k < 0) {

        return false;

    }

    

    for (i = k; i < numListeners - 1; i++) {

        callback[i] = callback[i + 1];

        eventCode[i] = eventCode[i + 1];

        enabled[i] = enabled[i + 1];

    }

    

    numListeners--;

    

    return true;

}





boolean EventDispatcher::enableEventListener(int ev_code, EventListener f, boolean enable) {

    int k;



    if (numListeners == 0) {

        return false;

    }

    

    k = _searchEventListener(ev_code, f);

    if (k < 0) {

        return false;

    }

    

    enabled[k] = enable;

    

    return true;

}





boolean EventDispatcher::isEventListenerEnabled(int ev_code, EventListener f) {

    int k;



    if (numListeners == 0) {

        return false;

    }

    

    k = _searchEventListener(ev_code, f);

    if (k < 0) {

        return false;

    }

    

    return enabled[k];

}







void EventDispatcher::run() {

    int event;

    int param;

    int i;

    boolean handlerFound;

    

    handlerFound = false;



    if (q->dequeueEvent(&event, &param)) {

        for (i = 0; i < numListeners; i++) {

            if ((callback[i] != 0) && (eventCode[i] == event) && enabled[i]) {

                handlerFound = true;

                (*callback[i])(event, param);

            }

        }

        

        if (!handlerFound) {

            if ((defaultCallback != 0) && (defaultCallbackEnabled)) {

                (*defaultCallback)(event, param);

            }

        }

    }

}





boolean EventDispatcher::setDefaultListener(EventListener f) {

    if (f == 0) {

        return false;

    }

    

    defaultCallback = f;

    defaultCallbackEnabled = true;

    return true;

}





void EventDispatcher::removeDefaultListener() {

    defaultCallback = 0;

    defaultCallbackEnabled = false;

}





void EventDispatcher::enableDefaultListener(boolean enable) {

    defaultCallbackEnabled = enable;

}





int EventDispatcher::_searchEventListener(int ev_code, EventListener f) {

    int i;

    

    for (i = 0; i < numListeners; i++) {

        if ((eventCode[i] == ev_code) && (callback[i] == f)) {

            return i;

        }

    }

    

    return -1;

}





int EventDispatcher::_searchEventCode(int ev_code) {

    int i;

    

    for (i = 0; i < numListeners; i++) {

        if (eventCode[i] == ev_code) {

            return i;

        }

    }

    

    return -1;

}
Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 596
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In this final example I've added support for three buttons. The debouncing algorithm is compile-time configurable.

On the hardware side, I've got digital pins 5, 3, 4 connected to three pushbuttons (let's call them A, B and C). The buttons are active low.

When button B is pressed, the led on pin 13 is turned on.
When button C is pressed, the led is turned off.

Everything is also print()ed to the serial port so you can follow the events on the serial monitor.

This example also shows that the event dispatcher supports more than one event per handler.

Code:
#include <Events.h>
#include <EventQueue.h>
#include <EventDispatcher.h>

// the event queue
EventQueue q;

// the event dispatcher
EventDispatcher disp(&q);

// use this analog channel
#define AN_CHAN 0

// generate an event when the analog
// channel value changes this much
// increase value for noisy sources
#define AN_DELTA 5

// let's suppose we have three pushbuttons
// A, B and C connected to digital pins 5, 3, 4
#define NUM_KEYS 3
#define KEY_A 1
#define KEY_B 2
#define KEY_C 3
int kb_pins[NUM_KEYS] = { 5, 3, 4 };
int kb_keys[NUM_KEYS] = { KEY_A, KEY_B, KEY_C };
int kb_on[NUM_KEYS] = { 0, 0, 0 };
int kb_off[NUM_KEYS] = { 0, 0, 0 };
int kb_curr_state[NUM_KEYS] = { 0, 0, 0 };
int kb_prev_state[NUM_KEYS] = { 0, 0, 0 };
#define KB_SAMPLE_DELAY 20
#define KB_DEBOUNCE_COUNT 3

// led to be turned on or off
#define LED_PIN 13


// time event handler
void timeHandler(int event, int param) {
    Serial.print("Time elapsed: ");
    Serial.println(millis() / 1000);
}


// analog event handler
void analogHandler(int event, int param) {
    Serial.print("Analog value: ");
    Serial.println(param);
}


// keyboard event handler
void kbHandler(int event, int param) {
    switch(event) {
        case Events::EV_KEY_PRESS:
            Serial.print("key pressed: ");
            if (param == KEY_B) {
                digitalWrite(LED_PIN, 1);    // key B turns the led ON
            }
            break;
        
        case Events::EV_KEY_RELEASE:
            Serial.print("key released: ");
            if (param == KEY_C) {
                digitalWrite(LED_PIN, 0);    // key C turns the led OFF
            }
            break;
    }
    
    switch(param) {
        case KEY_A:
            Serial.print("A");
            break;
        
        case KEY_B:
            Serial.print("B");
            break;
        
        case KEY_C:
            Serial.print("C");
            break;
    }
    
    Serial.println();
}


// this function generates an EV_TIME event
// each 1000 ms
void timeManager() {
    static unsigned long prevMillis = 0;
    unsigned long currMillis;

    currMillis = millis();
    if (currMillis - prevMillis >= 1000) {
        prevMillis = currMillis;
        q.enqueueEvent(Events::EV_TIME, 0);    // param is not used here
    }
}


// this function generates an EV_ANALOG event
// whenever the analog channel AN_CHAN changes
void analogManager() {
    static int prevValue = 0;
    int currValue;

    currValue = analogRead(AN_CHAN);

    if (abs(currValue - prevValue) >= AN_DELTA) {
        prevValue = currValue;
        q.enqueueEvent(Events::EV_ANALOG0, currValue);    // use param to pass analog value to event handler
    }
}


// this function debounces the pushbutton pins
// and emits the "keyboard events"
void kbManager() {
    static unsigned long prevMillis = 0;
    unsigned long currMillis;
    int i;
    
    currMillis = millis();
    if (currMillis - prevMillis >= KB_SAMPLE_DELAY) {
        prevMillis = currMillis;
        for (i = 0; i < NUM_KEYS; i++) {
            if (!digitalRead(kb_pins[i])) {    // buttons are active low
                kb_on[i]++;
                kb_off[i] = 0;
            }
            else {
                kb_on[i] = 0;
                kb_off[i]++;
            }
            
            if (kb_on[i] >= KB_DEBOUNCE_COUNT) {
                kb_on[i] = 0;
                kb_off[i] = 0;
                kb_curr_state[i] = 1;
                if (kb_prev_state[i] == 0) {
                    // it was released and now it's pressed
                    kb_prev_state[i] = 1;
                    q.enqueueEvent(Events::EV_KEY_PRESS, kb_keys[i]);
                }
            }
            
            if (kb_off[i] >= KB_DEBOUNCE_COUNT) {
                kb_on[i] = 0;
                kb_off[i] = 0;
                kb_curr_state[i] = 0;
                if (kb_prev_state[i] == 1) {
                    // it was pressed and now it's released
                    kb_prev_state[i] = 0;
                    q.enqueueEvent(Events::EV_KEY_RELEASE, kb_keys[i]);
                }
            }
        }
    }
}


// program setup
void setup() {
    Serial.begin(115200);
    
    // call timeHandler for TIME events
    disp.addEventListener(Events::EV_TIME, timeHandler);
    
    // call analogHandler for ANALOG0 events
    disp.addEventListener(Events::EV_ANALOG0, analogHandler);
    
    // call kbHandler for _both_ KEY_PRESS and KEY_RELEASE events
    disp.addEventListener(Events::EV_KEY_PRESS, kbHandler);
    disp.addEventListener(Events::EV_KEY_RELEASE, kbHandler);
}


// loop
void loop() {
    // call the event generating functions
    timeManager();
    analogManager();
    kbManager();

    // get events from the queue and call the
    // registered function(s)
    disp.run();
}
Logged

Florida
Offline Offline
Sr. Member
****
Karma: 4
Posts: 431
hookedup!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for posting.   A well abstracted event mechanism sounds like a fine idea .. I'll play with it more when I get a chance.  

Just a note, that when compiled .. there are a couple of compile warnings .. the temp and isEmpty vars in EventQueue::dequeueEvent are not used. I removed them and got no warning / errors.  You may want to remove those vars in your next iteration.

Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 596
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you, I've deleted them.
But I didn't get any warnings in the output window of the arduino ide. Is there some config setting that I should change ?
Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 596
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I found an answer here:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1278712207/3

The -w switch passed to avr-g++ disables warnings. That thread has a workaround, which unfortunately didn't work at all for me.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 43
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you, I've deleted them.
Logged

Pages: [1]   Go Up
Jump to: