blinkenlights working w sonar

This commit is contained in:
2016-05-12 01:32:35 +02:00
parent 11764cbd7a
commit d01e40e174
48 changed files with 4627 additions and 952 deletions
+159
View File
@@ -0,0 +1,159 @@
#include "event_handler.h"
#include "com/debug.h"
typedef struct {
uint32_t handler_id;
uint32_t chained_handler; // if not 0, that handler is removed together with this handler.
EventType type; // event type
EventHandlerCallback handler; // returns True if event was handled.
bool used; // this slot is currently used
void *user_data;
} EventHandlerSlot;
#define EH_SLOT_COUNT 6
static EventHandlerSlot eh_slots[EH_SLOT_COUNT];
static uint32_t next_slot_pid = 1; // 0 is reserved
/** Get a valid free PID for a new handler slot. */
static uint32_t make_pid(void)
{
uint32_t pid = next_slot_pid++;
// make sure no task is given PID 0
if (next_slot_pid == 0) {
next_slot_pid++;
}
return pid;
}
/**
* @brief Register an event handler for event type
* @param type : handled event type
* @param handler : the handler func
* @return handler ID. Can be used to remove the handler.
*/
uint32_t register_event_handler(EventType type, EventHandlerCallback handler, void *user_data)
{
for (int i = 0; i < EH_SLOT_COUNT; i++) {
if (eh_slots[i].used) continue;
// Free slot found
EventHandlerSlot *slot = &eh_slots[i];
slot->handler = handler;
slot->type = type;
slot->handler_id = make_pid();
slot->used = true;
slot->chained_handler = 0;
slot->user_data = user_data;
return slot->handler_id;
}
error("Failed to register event handler for type %d", type);
return 0; // fail
}
/** Chain for common destruction */
bool chain_event_handler(uint32_t from, uint32_t to, bool reci)
{
uint8_t cnt = 0;
for (int i = 0; i < EH_SLOT_COUNT; i++) {
EventHandlerSlot *slot = &eh_slots[i];
if (!slot->used) continue;
if (slot->handler_id == from) {
slot->chained_handler = to;
cnt++;
}
// link back in two-handler reciprocal link
if (reci && slot->handler_id == to) {
slot->chained_handler = from;
cnt++;
}
if (cnt == (reci ? 2 : 1)) {
return true;
}
}
return false;
}
/**
* @brief check if exists
*/
bool event_handler_exists(uint32_t handler_id)
{
for (int i = 0; i < EH_SLOT_COUNT; i++) {
EventHandlerSlot *slot = &eh_slots[i];
if (!slot->used) continue;
if (slot->handler_id == handler_id) {
return true;
}
}
return false;
}
/**
* @brief Remove event handler by handler ID
* @param handler_id : handler ID, obtained when registering or in the callback.
* @return number of removed handlers
*/
int remove_event_handler(uint32_t handler_id)
{
int cnt = 0;
while (handler_id != 0) { // outer loop because of chained handlers
bool suc = false;
for (int i = 0; i < EH_SLOT_COUNT; i++) {
if (!eh_slots[i].used) {
continue; // skip empty slot
}
// Free slot found
EventHandlerSlot *slot = &eh_slots[i];
if (slot->handler_id == handler_id) {
slot->used = false;
slot->user_data = NULL;
suc = true;
cnt++;
handler_id = slot->chained_handler; // continue with the chained handler.
break;
}
}
if (!suc) break;
}
return cnt;
}
/** Handle an event */
void run_event_handler(Event *evt)
{
bool handled = false;
for (int i = 0; i < EH_SLOT_COUNT; i++) {
EventHandlerSlot *slot = &eh_slots[i];
if (!slot->used) continue; // unused
if (slot->type != evt->type) continue; // wrong type
handled = slot->handler(slot->handler_id, evt, &slot->user_data);
if (handled) break;
}
if (!handled) {
warn("Unhandled event, type %d", evt->type);
}
}
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include "main.h"
#include "event_queue.h"
typedef bool (*EventHandlerCallback) (uint32_t hdlr_id, Event *evt, void **user_data);
/**
* @brief Register an event handler for event type
* @param type : handled event type
* @param handler : the handler func
* @return handler ID. Can be used to remove the handler.
*/
uint32_t register_event_handler(EventType type, EventHandlerCallback handler, void *user_data);
/**
* @brief Remove event handler by handler ID
* @param handler_id : handler ID, obtained when registering or in the callback.
* @return number of removed handlers
*/
int remove_event_handler(uint32_t handler_id);
/**
* @brief Handle an event
* @param event : pointer to the event to handle
*/
void run_event_handler(Event *event);
/**
* @brief Check if hansler exists
* @param handler_id : handler
* @return exists
*/
bool event_handler_exists(uint32_t handler_id);
/**
* @brief Create a link between two handlers (one direction).
*
* If handler A is linked to handler B, and handler A is removed,
* both handlers will perish.
*
* Make a circle if you need to chain more than two handlers.
*
* @param from : handler A
* @param to : handler B
* @param reciprocal : link also from B to A
* @return
*/
bool chain_event_handler(uint32_t from, uint32_t to, bool reciprocal);
+66
View File
@@ -0,0 +1,66 @@
#include "event_queue.h"
#include "com/debug.h"
/** Task queue */
static CircBuf *tq;
/** Event queue */
static CircBuf *eq;
void queues_init(size_t tq_size, size_t eq_size)
{
tq = cbuf_create(tq_size, sizeof(QueuedTask));
eq = cbuf_create(eq_size, sizeof(Event));
}
bool tq_post(void (*handler)(void*), void *arg)
{
QueuedTask task;
task.handler = handler;
task.arg = arg;
bool suc = cbuf_append(tq, &task);
if (!suc) error("TQ overflow");
return suc;
}
bool eq_post(const Event *event)
{
bool suc = cbuf_append(eq, event);
if (!suc) {
error("EQ overflow, evt %d", event->type);
}
return suc;
}
bool tq_poll_one(void)
{
QueuedTask task;
// serve all tasks
bool suc = cbuf_pop(tq, &task);
if (suc) {
task.handler(task.arg);
}
return suc;
}
void tq_poll(void)
{
// serve all tasks
while (tq_poll_one());
}
bool eq_take(Event *dest)
{
bool suc = cbuf_pop(eq, dest);
return suc;
}
+75
View File
@@ -0,0 +1,75 @@
#pragma once
#include "main.h"
#include "utils/circbuf.h"
#define TASK_QUEUE_SIZE 64
#define EVENT_QUEUE_SIZE 64
/** Application events */
typedef enum {
EVENT_ONE // placeholder
} EventType;
/** Event Queue entry */
typedef struct {
EventType type;
void *data;
} Event;
typedef struct {
void (*handler)(void*);
void* arg;
} QueuedTask;
/**
* @brief Set up the task and event queues
* @param tq_size : number of slots in the task queue
* @param eq_size : number of slots in the event queue
*/
void queues_init(size_t tq_size, size_t eq_size);
/**
* @brief Post a task on the task queue, with arg.
*
* @see tq_post()
*
* @param handler : task function
* @param arg : argument for the handler
* @return success
*/
bool tq_post(void (*handler)(void *), void *arg);
/**
* @brief Post an event on the event queue
* @param event : pointer to an event to post; will be copied.
* @return success
*/
bool eq_post(const Event *event);
/**
* @brief Run all pending tasks on the task queue
*/
void tq_poll(void);
/**
* @brief Run one pending task on the task queue
* @return true if a task was run.
*/
bool tq_poll_one(void);
/**
* @brief Take one event off the event queue.
* @param dest : pointer to a destination event variable.
* @return success
*/
bool eq_take(Event *dest);