Microbug / MicroBitDAL_SB2_TEST

Fork of MicroBitDALImageRewrite by Joe Finney

Committer:
finneyj
Date:
Thu Apr 16 13:50:24 2015 +0000
Revision:
1:3e0360107f98
Child:
2:6597fe50dc94
Updates to include:; ;   - Asynchronous Scrolltext();   - First iteration of MessageBus implementation;   - Hardware configuration for SquareBoard protoype

Who changed what in which revision?

UserRevisionLine numberNew contents of line
finneyj 1:3e0360107f98 1 /**
finneyj 1:3e0360107f98 2 * Class definition for a MicroBitImage.
finneyj 1:3e0360107f98 3 *
finneyj 1:3e0360107f98 4 * An MicroBitImage is a simple bitmap representation of an image.
finneyj 1:3e0360107f98 5 */
finneyj 1:3e0360107f98 6
finneyj 1:3e0360107f98 7 #include "MicroBitMessageBus.h"
finneyj 1:3e0360107f98 8
finneyj 1:3e0360107f98 9 /**
finneyj 1:3e0360107f98 10 * Constructor.
finneyj 1:3e0360107f98 11 * Create a new Message Bus Listener.
finneyj 1:3e0360107f98 12 */
finneyj 1:3e0360107f98 13 MicroBitListener::MicroBitListener(int id, int value, void (*handler)(MicroBitEvent *))
finneyj 1:3e0360107f98 14 {
finneyj 1:3e0360107f98 15 this->id = id;
finneyj 1:3e0360107f98 16 this->value = value;
finneyj 1:3e0360107f98 17 this->cb = handler;
finneyj 1:3e0360107f98 18 this->next = NULL;
finneyj 1:3e0360107f98 19 }
finneyj 1:3e0360107f98 20
finneyj 1:3e0360107f98 21 /**
finneyj 1:3e0360107f98 22 * Constructor.
finneyj 1:3e0360107f98 23 * Create a new Message Bus.
finneyj 1:3e0360107f98 24 */
finneyj 1:3e0360107f98 25 MicroBitMessageBus::MicroBitMessageBus()
finneyj 1:3e0360107f98 26 {
finneyj 1:3e0360107f98 27 this->listeners = NULL;
finneyj 1:3e0360107f98 28 this->seq = 0;
finneyj 1:3e0360107f98 29 }
finneyj 1:3e0360107f98 30
finneyj 1:3e0360107f98 31 /**
finneyj 1:3e0360107f98 32 * Send the given event to all regstered recipients.
finneyj 1:3e0360107f98 33 *
finneyj 1:3e0360107f98 34 * @param The event to send. This structure is assumed to be heap allocated, and will
finneyj 1:3e0360107f98 35 * be automatically freed once all recipients have been notified.
finneyj 1:3e0360107f98 36 */
finneyj 1:3e0360107f98 37 void MicroBitMessageBus::send(MicroBitEvent *evt)
finneyj 1:3e0360107f98 38 {
finneyj 1:3e0360107f98 39 this->send(evt, NULL);
finneyj 1:3e0360107f98 40 }
finneyj 1:3e0360107f98 41
finneyj 1:3e0360107f98 42 /**
finneyj 1:3e0360107f98 43 * Send the given event to all regstered recipients, using a cached entry to minimize lookups.
finneyj 1:3e0360107f98 44 * This is particularly useful for optimizing sensors that frequently send to the same channel.
finneyj 1:3e0360107f98 45 *
finneyj 1:3e0360107f98 46 * @param evt The event to send. This structure is assumed to be heap allocated, and will
finneyj 1:3e0360107f98 47 * be automatically freed once all recipients have been notified.
finneyj 1:3e0360107f98 48 * @param c Cache entry to reduce lookups for commonly used channels.
finneyj 1:3e0360107f98 49 *
finneyj 1:3e0360107f98 50 * TODO: For now, this is unbuffered. We should consider scheduling events here, and operating
finneyj 1:3e0360107f98 51 * a different thread that empties the queue. This would perhaps provide greater opportunities
finneyj 1:3e0360107f98 52 * for aggregation.
finneyj 1:3e0360107f98 53 */
finneyj 1:3e0360107f98 54 void MicroBitMessageBus::send(MicroBitEvent *evt, MicroBitMessageBusCache *c)
finneyj 1:3e0360107f98 55 {
finneyj 1:3e0360107f98 56 MicroBitListener *l;
finneyj 1:3e0360107f98 57 MicroBitListener *start;
finneyj 1:3e0360107f98 58
finneyj 1:3e0360107f98 59 // Find the start of the sublist where we'll send this event.
finneyj 1:3e0360107f98 60 // Ideally, we'll have a valid, cached entry. Use it if we do.
finneyj 1:3e0360107f98 61 if ( c != NULL && c->seq == this->seq)
finneyj 1:3e0360107f98 62 {
finneyj 1:3e0360107f98 63 l = c->ptr;
finneyj 1:3e0360107f98 64 }
finneyj 1:3e0360107f98 65 else
finneyj 1:3e0360107f98 66 {
finneyj 1:3e0360107f98 67 l = listeners;
finneyj 1:3e0360107f98 68 while (l != NULL && l->id != evt->source)
finneyj 1:3e0360107f98 69 l = l->next;
finneyj 1:3e0360107f98 70 }
finneyj 1:3e0360107f98 71
finneyj 1:3e0360107f98 72 start = l;
finneyj 1:3e0360107f98 73
finneyj 1:3e0360107f98 74 // Now, send the event to all listeners registered for this event.
finneyj 1:3e0360107f98 75 while (l != NULL && l->id == evt->source)
finneyj 1:3e0360107f98 76 {
finneyj 1:3e0360107f98 77 if(l->value == MICROBIT_BUS_VALUE_ANY || l->value == evt->value)
finneyj 1:3e0360107f98 78 l->cb(evt);
finneyj 1:3e0360107f98 79
finneyj 1:3e0360107f98 80 l = l->next;
finneyj 1:3e0360107f98 81 }
finneyj 1:3e0360107f98 82
finneyj 1:3e0360107f98 83 // Next, send to any listeners registered for ALL event sources.
finneyj 1:3e0360107f98 84 l = listeners;
finneyj 1:3e0360107f98 85 while (l != NULL && l->id == MICROBIT_BUS_ID_ANY)
finneyj 1:3e0360107f98 86 {
finneyj 1:3e0360107f98 87 l->cb(evt);
finneyj 1:3e0360107f98 88 l = l->next;
finneyj 1:3e0360107f98 89 }
finneyj 1:3e0360107f98 90
finneyj 1:3e0360107f98 91 // Finally, if we were given a cached entry that's now invalid, update it.
finneyj 1:3e0360107f98 92 if ( c != NULL && c->seq != this->seq)
finneyj 1:3e0360107f98 93 {
finneyj 1:3e0360107f98 94 c->ptr = start;
finneyj 1:3e0360107f98 95 c->seq = this->seq;
finneyj 1:3e0360107f98 96 }
finneyj 1:3e0360107f98 97 }
finneyj 1:3e0360107f98 98
finneyj 1:3e0360107f98 99 /**
finneyj 1:3e0360107f98 100 * Register a listener function.
finneyj 1:3e0360107f98 101 *
finneyj 1:3e0360107f98 102 * @param id The source of messages to listen for. Events sent from any other IDs will be filtered.
finneyj 1:3e0360107f98 103 * Use MICROBIT_ID_ANY to receive events from all components.
finneyj 1:3e0360107f98 104 *
finneyj 1:3e0360107f98 105 * @param value The value of messages to listen for. Events with any other values will be filtered.
finneyj 1:3e0360107f98 106 * Use MICROBIT_VALUE_ANY to receive events of any value.
finneyj 1:3e0360107f98 107 *
finneyj 1:3e0360107f98 108 * @param hander The function to call when an event is received.
finneyj 1:3e0360107f98 109 *
finneyj 1:3e0360107f98 110 * TODO: We currently don't support C++ member functions as callbacks, which we should.
finneyj 1:3e0360107f98 111 */
finneyj 1:3e0360107f98 112
finneyj 1:3e0360107f98 113 void MicroBitMessageBus::listen(int id, int value, void (*handler)(MicroBitEvent *))
finneyj 1:3e0360107f98 114 {
finneyj 1:3e0360107f98 115 MicroBitListener *l, *p;
finneyj 1:3e0360107f98 116 MicroBitListener *newListener = new MicroBitListener(id, value, handler);
finneyj 1:3e0360107f98 117
finneyj 1:3e0360107f98 118 // Firstly, we treat a listener as an idempotent operation. Ensure we don't already have this handler
finneyj 1:3e0360107f98 119 // registered in a that will already capture these events. If we do, silently ignore.
finneyj 1:3e0360107f98 120 l = listeners;
finneyj 1:3e0360107f98 121
finneyj 1:3e0360107f98 122 while (l != NULL && l->id <= id)
finneyj 1:3e0360107f98 123 {
finneyj 1:3e0360107f98 124 if (l->cb == handler && (l->id == id || l->id == MICROBIT_BUS_ID_ANY) && (l->value == value || l->value == MICROBIT_BUS_VALUE_ANY))
finneyj 1:3e0360107f98 125 return;
finneyj 1:3e0360107f98 126
finneyj 1:3e0360107f98 127 l = l->next;
finneyj 1:3e0360107f98 128 }
finneyj 1:3e0360107f98 129
finneyj 1:3e0360107f98 130 // Maintain an ordered list of listeners.
finneyj 1:3e0360107f98 131 // Chain is held stictly in increasing order of ID (first level), then value code (second level).
finneyj 1:3e0360107f98 132 // Find the correct point in the chain for this event.
finneyj 1:3e0360107f98 133 // Adding a listener is a rare occurance, so we just walk the list.
finneyj 1:3e0360107f98 134 p = NULL;
finneyj 1:3e0360107f98 135 l = listeners;
finneyj 1:3e0360107f98 136
finneyj 1:3e0360107f98 137 while (l != NULL && l->id <= id && l->value <= value)
finneyj 1:3e0360107f98 138 {
finneyj 1:3e0360107f98 139 p=l;
finneyj 1:3e0360107f98 140 l = l->next;
finneyj 1:3e0360107f98 141 }
finneyj 1:3e0360107f98 142
finneyj 1:3e0360107f98 143 // Add the listener at this point in the chain.
finneyj 1:3e0360107f98 144 if (p == NULL)
finneyj 1:3e0360107f98 145 listeners = newListener;
finneyj 1:3e0360107f98 146 else
finneyj 1:3e0360107f98 147 {
finneyj 1:3e0360107f98 148 newListener->next = p->next;
finneyj 1:3e0360107f98 149 p->next = newListener;
finneyj 1:3e0360107f98 150 }
finneyj 1:3e0360107f98 151
finneyj 1:3e0360107f98 152 // Increase our sequence number and we're done.
finneyj 1:3e0360107f98 153 // This will lazily invalidate any cached entries to the listener list.
finneyj 1:3e0360107f98 154 this->seq++;
finneyj 1:3e0360107f98 155 }
finneyj 1:3e0360107f98 156