The codebase to run the *spark d-fuser controller www.sparkav.co.uk/dvimixer
Dependencies: SPK-TVOne DMX DmxArtNet NetServicesMin OSC PinDetect mRotaryEncoder iniparser mbed spk_oled_ssd1305 filter
spk_utils.h@62:523de36d2f88, 2013-07-26 (annotated)
- Committer:
- tobyspark
- Date:
- Fri Jul 26 16:15:41 2013 +0000
- Revision:
- 62:523de36d2f88
- Parent:
- 57:14d37904c889
TVOne Status Line UX - instant and queuing behaviour, when you want which one.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tobyspark | 8:d46cc49f0f37 | 1 | // *SPARK D-FUSER |
tobyspark | 8:d46cc49f0f37 | 2 | // A project by Toby Harris |
tobyspark | 8:d46cc49f0f37 | 3 | // Copyright *spark audio-visual 2012 |
tobyspark | 8:d46cc49f0f37 | 4 | // |
tobyspark | 8:d46cc49f0f37 | 5 | // SPK_UTILS provides utility classes for the main SPK-DVIMXR codebase, most significantly the menu system. |
tobyspark | 8:d46cc49f0f37 | 6 | |
tobyspark | 0:87aab40d5806 | 7 | #include <string> |
tobyspark | 0:87aab40d5806 | 8 | #include <vector> |
tobyspark | 57:14d37904c889 | 9 | #include <queue> |
tobyspark | 0:87aab40d5806 | 10 | |
tobyspark | 0:87aab40d5806 | 11 | class SPKIndexInRange { |
tobyspark | 0:87aab40d5806 | 12 | public: |
tobyspark | 0:87aab40d5806 | 13 | void operator = (int newIndex) { |
tobyspark | 0:87aab40d5806 | 14 | set(newIndex); |
tobyspark | 0:87aab40d5806 | 15 | } |
tobyspark | 0:87aab40d5806 | 16 | |
tobyspark | 0:87aab40d5806 | 17 | void operator ++ (int) { |
tobyspark | 0:87aab40d5806 | 18 | if (idx == max) idx = wrap ? min : max; |
tobyspark | 0:87aab40d5806 | 19 | else idx++; |
tobyspark | 0:87aab40d5806 | 20 | } |
tobyspark | 0:87aab40d5806 | 21 | |
tobyspark | 0:87aab40d5806 | 22 | void operator -- (int) { |
tobyspark | 0:87aab40d5806 | 23 | if (idx == min) idx = wrap ? max : min; |
tobyspark | 0:87aab40d5806 | 24 | else idx--; |
tobyspark | 0:87aab40d5806 | 25 | } |
tobyspark | 0:87aab40d5806 | 26 | |
tobyspark | 0:87aab40d5806 | 27 | void set (int newIndex) { |
tobyspark | 0:87aab40d5806 | 28 | if (newIndex > max) idx = max; |
tobyspark | 0:87aab40d5806 | 29 | else if (newIndex < min) idx = min; |
tobyspark | 0:87aab40d5806 | 30 | else idx = newIndex; |
tobyspark | 0:87aab40d5806 | 31 | } |
tobyspark | 0:87aab40d5806 | 32 | |
tobyspark | 0:87aab40d5806 | 33 | void set (int newMin, int newMax, int newIndex = 0, bool newWrap = false) { |
tobyspark | 0:87aab40d5806 | 34 | min = newMin; |
tobyspark | 0:87aab40d5806 | 35 | max = newMax; |
tobyspark | 0:87aab40d5806 | 36 | wrap = newWrap; |
tobyspark | 0:87aab40d5806 | 37 | set(newIndex); |
tobyspark | 0:87aab40d5806 | 38 | } |
tobyspark | 0:87aab40d5806 | 39 | |
tobyspark | 0:87aab40d5806 | 40 | void setMax(int newMax) { |
tobyspark | 0:87aab40d5806 | 41 | max = newMax; |
tobyspark | 0:87aab40d5806 | 42 | } |
tobyspark | 0:87aab40d5806 | 43 | |
tobyspark | 0:87aab40d5806 | 44 | SPKIndexInRange () { |
tobyspark | 0:87aab40d5806 | 45 | min = 0; |
tobyspark | 0:87aab40d5806 | 46 | max = 1; |
tobyspark | 0:87aab40d5806 | 47 | wrap = true; |
tobyspark | 0:87aab40d5806 | 48 | idx = 0; |
tobyspark | 0:87aab40d5806 | 49 | } |
tobyspark | 0:87aab40d5806 | 50 | |
tobyspark | 0:87aab40d5806 | 51 | SPKIndexInRange (int newMin, int newMax, int newIndex = 0, bool newWrap = false) { |
tobyspark | 0:87aab40d5806 | 52 | set(newMin, newMax, newIndex, newWrap); |
tobyspark | 0:87aab40d5806 | 53 | } |
tobyspark | 0:87aab40d5806 | 54 | |
tobyspark | 0:87aab40d5806 | 55 | int index() { |
tobyspark | 0:87aab40d5806 | 56 | return idx; |
tobyspark | 0:87aab40d5806 | 57 | } |
tobyspark | 0:87aab40d5806 | 58 | |
tobyspark | 0:87aab40d5806 | 59 | private: |
tobyspark | 0:87aab40d5806 | 60 | int idx; |
tobyspark | 0:87aab40d5806 | 61 | int min, max; |
tobyspark | 0:87aab40d5806 | 62 | bool wrap; |
tobyspark | 0:87aab40d5806 | 63 | }; |
tobyspark | 0:87aab40d5806 | 64 | |
tobyspark | 23:909928cafb95 | 65 | class SPKMenu; |
tobyspark | 23:909928cafb95 | 66 | |
tobyspark | 23:909928cafb95 | 67 | class SPKMenuItem { |
tobyspark | 23:909928cafb95 | 68 | public: |
tobyspark | 49:16309f39cead | 69 | enum itemType { changesToMenu, sendsCommand, hasHandler }; |
tobyspark | 23:909928cafb95 | 70 | itemType type; |
tobyspark | 23:909928cafb95 | 71 | string text; |
tobyspark | 49:16309f39cead | 72 | void (*handler)(int, bool); |
tobyspark | 23:909928cafb95 | 73 | union { |
tobyspark | 23:909928cafb95 | 74 | SPKMenu* menu; |
tobyspark | 23:909928cafb95 | 75 | int32_t command[2]; |
tobyspark | 49:16309f39cead | 76 | void (*handler)(int, bool); |
tobyspark | 23:909928cafb95 | 77 | } payload; |
tobyspark | 23:909928cafb95 | 78 | |
tobyspark | 49:16309f39cead | 79 | SPKMenuItem(string title, SPKMenu* menu) |
tobyspark | 23:909928cafb95 | 80 | { |
tobyspark | 23:909928cafb95 | 81 | text = title; |
tobyspark | 23:909928cafb95 | 82 | type = changesToMenu; |
tobyspark | 23:909928cafb95 | 83 | payload.menu = menu; |
tobyspark | 23:909928cafb95 | 84 | } |
tobyspark | 23:909928cafb95 | 85 | |
tobyspark | 49:16309f39cead | 86 | SPKMenuItem(void (*menuItemHandler)(int, bool)) |
tobyspark | 49:16309f39cead | 87 | { |
tobyspark | 49:16309f39cead | 88 | text = "[has handler]"; |
tobyspark | 49:16309f39cead | 89 | type = hasHandler; |
tobyspark | 49:16309f39cead | 90 | payload.handler = menuItemHandler; |
tobyspark | 49:16309f39cead | 91 | } |
tobyspark | 49:16309f39cead | 92 | |
tobyspark | 23:909928cafb95 | 93 | SPKMenuItem(string title, int32_t command) |
tobyspark | 23:909928cafb95 | 94 | { |
tobyspark | 23:909928cafb95 | 95 | text = title; |
tobyspark | 23:909928cafb95 | 96 | type = sendsCommand; |
tobyspark | 23:909928cafb95 | 97 | payload.command[0] = command; |
tobyspark | 23:909928cafb95 | 98 | payload.command[1] = 0; |
tobyspark | 23:909928cafb95 | 99 | } |
tobyspark | 23:909928cafb95 | 100 | |
tobyspark | 23:909928cafb95 | 101 | SPKMenuItem(string title, int32_t command1, int32_t command2) |
tobyspark | 23:909928cafb95 | 102 | { |
tobyspark | 23:909928cafb95 | 103 | text = title; |
tobyspark | 23:909928cafb95 | 104 | type = sendsCommand; |
tobyspark | 23:909928cafb95 | 105 | payload.command[0] = command1; |
tobyspark | 23:909928cafb95 | 106 | payload.command[1] = command2; |
tobyspark | 23:909928cafb95 | 107 | } |
tobyspark | 23:909928cafb95 | 108 | }; |
tobyspark | 23:909928cafb95 | 109 | |
tobyspark | 23:909928cafb95 | 110 | |
tobyspark | 0:87aab40d5806 | 111 | class SPKMenu { |
tobyspark | 0:87aab40d5806 | 112 | public: |
tobyspark | 0:87aab40d5806 | 113 | SPKMenu() { |
tobyspark | 0:87aab40d5806 | 114 | selected.set(0, 0, 0, true); |
tobyspark | 0:87aab40d5806 | 115 | } |
tobyspark | 0:87aab40d5806 | 116 | |
tobyspark | 0:87aab40d5806 | 117 | std::string title; |
tobyspark | 0:87aab40d5806 | 118 | |
tobyspark | 5:f8b285ca41ba | 119 | SPKMenu& operator = (const int &newIndex) { |
tobyspark | 0:87aab40d5806 | 120 | selected = newIndex; |
tobyspark | 5:f8b285ca41ba | 121 | return *this; |
tobyspark | 0:87aab40d5806 | 122 | } |
tobyspark | 0:87aab40d5806 | 123 | |
tobyspark | 0:87aab40d5806 | 124 | void operator ++ () { |
tobyspark | 0:87aab40d5806 | 125 | selected++; |
tobyspark | 0:87aab40d5806 | 126 | } |
tobyspark | 0:87aab40d5806 | 127 | |
tobyspark | 0:87aab40d5806 | 128 | void operator -- () { |
tobyspark | 0:87aab40d5806 | 129 | selected--; |
tobyspark | 0:87aab40d5806 | 130 | } |
tobyspark | 0:87aab40d5806 | 131 | |
tobyspark | 23:909928cafb95 | 132 | void addMenuItem (SPKMenuItem menuItem) { |
tobyspark | 23:909928cafb95 | 133 | items.push_back(menuItem); |
tobyspark | 23:909928cafb95 | 134 | selected.setMax(items.size()-1); |
tobyspark | 23:909928cafb95 | 135 | } |
tobyspark | 23:909928cafb95 | 136 | |
tobyspark | 23:909928cafb95 | 137 | void clearMenuItems() { |
tobyspark | 23:909928cafb95 | 138 | items.clear(); |
tobyspark | 23:909928cafb95 | 139 | selected.setMax(0); |
tobyspark | 0:87aab40d5806 | 140 | } |
tobyspark | 0:87aab40d5806 | 141 | |
tobyspark | 0:87aab40d5806 | 142 | int selectedIndex() { |
tobyspark | 0:87aab40d5806 | 143 | return selected.index(); |
tobyspark | 0:87aab40d5806 | 144 | } |
tobyspark | 0:87aab40d5806 | 145 | |
tobyspark | 24:49c6624119ae | 146 | std::string selectedString() { |
tobyspark | 24:49c6624119ae | 147 | if (items.size() == 0) printf("SPKMenu no items"); |
tobyspark | 23:909928cafb95 | 148 | return items[selected.index()].text; |
tobyspark | 23:909928cafb95 | 149 | } |
tobyspark | 23:909928cafb95 | 150 | |
tobyspark | 23:909928cafb95 | 151 | SPKMenuItem selectedItem() { |
tobyspark | 24:49c6624119ae | 152 | if (items.size() == 0) printf("SPKMenu no items"); |
tobyspark | 23:909928cafb95 | 153 | return items[selected.index()]; |
tobyspark | 0:87aab40d5806 | 154 | } |
tobyspark | 0:87aab40d5806 | 155 | |
tobyspark | 0:87aab40d5806 | 156 | protected: |
tobyspark | 0:87aab40d5806 | 157 | SPKIndexInRange selected; |
tobyspark | 23:909928cafb95 | 158 | std::vector<SPKMenuItem> items; |
tobyspark | 0:87aab40d5806 | 159 | }; |
tobyspark | 0:87aab40d5806 | 160 | |
tobyspark | 0:87aab40d5806 | 161 | |
tobyspark | 0:87aab40d5806 | 162 | class SPKSign { |
tobyspark | 0:87aab40d5806 | 163 | public: |
tobyspark | 0:87aab40d5806 | 164 | SPKSign(PinName signWrite, PinName signError) { |
tobyspark | 0:87aab40d5806 | 165 | writeDO = new DigitalOut(signWrite); |
tobyspark | 0:87aab40d5806 | 166 | errorDO = new DigitalOut(signError); |
tobyspark | 0:87aab40d5806 | 167 | } |
tobyspark | 0:87aab40d5806 | 168 | |
tobyspark | 0:87aab40d5806 | 169 | ~SPKSign() { |
tobyspark | 0:87aab40d5806 | 170 | delete writeDO; |
tobyspark | 0:87aab40d5806 | 171 | delete errorDO; |
tobyspark | 0:87aab40d5806 | 172 | } |
tobyspark | 0:87aab40d5806 | 173 | |
tobyspark | 0:87aab40d5806 | 174 | void serialWrite() { |
tobyspark | 0:87aab40d5806 | 175 | signWriteTimeout.detach(); |
tobyspark | 0:87aab40d5806 | 176 | signWriteTimeout.attach(this, &SPKSign::writeOff, 0.25); |
tobyspark | 0:87aab40d5806 | 177 | *writeDO = 1; |
tobyspark | 0:87aab40d5806 | 178 | } |
tobyspark | 0:87aab40d5806 | 179 | |
tobyspark | 0:87aab40d5806 | 180 | void serialError() { |
tobyspark | 0:87aab40d5806 | 181 | signErrorTimeout.detach(); |
tobyspark | 0:87aab40d5806 | 182 | signErrorTimeout.attach(this, &SPKSign::errorOff, 0.25); |
tobyspark | 0:87aab40d5806 | 183 | *errorDO = 1; |
tobyspark | 0:87aab40d5806 | 184 | } |
tobyspark | 0:87aab40d5806 | 185 | |
tobyspark | 0:87aab40d5806 | 186 | private: |
tobyspark | 0:87aab40d5806 | 187 | void writeOff() { |
tobyspark | 0:87aab40d5806 | 188 | *writeDO = 0; |
tobyspark | 0:87aab40d5806 | 189 | } |
tobyspark | 0:87aab40d5806 | 190 | |
tobyspark | 0:87aab40d5806 | 191 | void errorOff() { |
tobyspark | 0:87aab40d5806 | 192 | *errorDO = 0; |
tobyspark | 0:87aab40d5806 | 193 | } |
tobyspark | 0:87aab40d5806 | 194 | |
tobyspark | 0:87aab40d5806 | 195 | DigitalOut *writeDO; |
tobyspark | 0:87aab40d5806 | 196 | DigitalOut *errorDO; |
tobyspark | 0:87aab40d5806 | 197 | Timeout signWriteTimeout; |
tobyspark | 0:87aab40d5806 | 198 | Timeout signErrorTimeout; |
tobyspark | 0:87aab40d5806 | 199 | }; |
tobyspark | 0:87aab40d5806 | 200 | |
tobyspark | 48:c0fedfa8c525 | 201 | class SPKMessageHold { |
tobyspark | 48:c0fedfa8c525 | 202 | public: |
tobyspark | 0:87aab40d5806 | 203 | |
tobyspark | 48:c0fedfa8c525 | 204 | SPKMessageHold() { |
tobyspark | 62:523de36d2f88 | 205 | state = notHold; |
tobyspark | 48:c0fedfa8c525 | 206 | currentMessage = ""; |
tobyspark | 57:14d37904c889 | 207 | savedMessage = ""; |
tobyspark | 48:c0fedfa8c525 | 208 | } |
tobyspark | 48:c0fedfa8c525 | 209 | |
tobyspark | 62:523de36d2f88 | 210 | void addMessage(string message) |
tobyspark | 62:523de36d2f88 | 211 | { |
tobyspark | 62:523de36d2f88 | 212 | addMessage(message, 0, 0); |
tobyspark | 62:523de36d2f88 | 213 | } |
tobyspark | 62:523de36d2f88 | 214 | |
tobyspark | 62:523de36d2f88 | 215 | void addMessage(string message, float maxSecs) |
tobyspark | 57:14d37904c889 | 216 | { |
tobyspark | 62:523de36d2f88 | 217 | addMessage(message, 0.1, maxSecs); |
tobyspark | 62:523de36d2f88 | 218 | } |
tobyspark | 62:523de36d2f88 | 219 | |
tobyspark | 62:523de36d2f88 | 220 | void addMessage(string message, float minSecs, float maxSecs) |
tobyspark | 62:523de36d2f88 | 221 | { |
tobyspark | 62:523de36d2f88 | 222 | if (state == notHold) |
tobyspark | 48:c0fedfa8c525 | 223 | { |
tobyspark | 62:523de36d2f88 | 224 | if (maxSecs > 0.0f) |
tobyspark | 57:14d37904c889 | 225 | { |
tobyspark | 62:523de36d2f88 | 226 | state = (minSecs > 0) ? holdWaitingForMin : holdMinPassed; |
tobyspark | 57:14d37904c889 | 227 | savedMessage = currentMessage; |
tobyspark | 57:14d37904c889 | 228 | currentMessage = message; |
tobyspark | 62:523de36d2f88 | 229 | |
tobyspark | 62:523de36d2f88 | 230 | maxTimeout.attach(this, &SPKMessageHold::handleTimeout, maxSecs); |
tobyspark | 62:523de36d2f88 | 231 | if (minSecs > 0) minTimeout.attach(this, &SPKMessageHold::handleTimeout, minSecs); |
tobyspark | 57:14d37904c889 | 232 | } |
tobyspark | 57:14d37904c889 | 233 | else |
tobyspark | 57:14d37904c889 | 234 | { |
tobyspark | 57:14d37904c889 | 235 | currentMessage = message; |
tobyspark | 57:14d37904c889 | 236 | } |
tobyspark | 48:c0fedfa8c525 | 237 | } |
tobyspark | 62:523de36d2f88 | 238 | if (state == holdWaitingForMin) |
tobyspark | 62:523de36d2f88 | 239 | { |
tobyspark | 62:523de36d2f88 | 240 | if (maxSecs > 0.0f) enqueueMessage(message, minSecs, maxSecs); |
tobyspark | 62:523de36d2f88 | 241 | else savedMessage = message; |
tobyspark | 62:523de36d2f88 | 242 | } |
tobyspark | 62:523de36d2f88 | 243 | if (state == holdMinPassed) |
tobyspark | 62:523de36d2f88 | 244 | { |
tobyspark | 62:523de36d2f88 | 245 | if (maxSecs > 0.0f) { enqueueMessage(message, minSecs, maxSecs); dequeueMessage(); } |
tobyspark | 62:523de36d2f88 | 246 | else savedMessage = message; |
tobyspark | 62:523de36d2f88 | 247 | } |
tobyspark | 48:c0fedfa8c525 | 248 | } |
tobyspark | 48:c0fedfa8c525 | 249 | |
tobyspark | 48:c0fedfa8c525 | 250 | string message() { return currentMessage; } |
tobyspark | 0:87aab40d5806 | 251 | |
tobyspark | 48:c0fedfa8c525 | 252 | private: |
tobyspark | 62:523de36d2f88 | 253 | enum stateType { notHold, holdWaitingForMin, holdMinPassed }; |
tobyspark | 62:523de36d2f88 | 254 | struct messageType { string message; float minSecs; float maxSecs; }; |
tobyspark | 62:523de36d2f88 | 255 | |
tobyspark | 62:523de36d2f88 | 256 | void enqueueMessage(string message, float minSecs, float maxSecs) |
tobyspark | 62:523de36d2f88 | 257 | { |
tobyspark | 62:523de36d2f88 | 258 | messageType messageStruct = {message, minSecs, maxSecs}; |
tobyspark | 62:523de36d2f88 | 259 | enqueuedMessages.push(messageStruct); |
tobyspark | 62:523de36d2f88 | 260 | } |
tobyspark | 62:523de36d2f88 | 261 | |
tobyspark | 62:523de36d2f88 | 262 | void dequeueMessage() |
tobyspark | 62:523de36d2f88 | 263 | { |
tobyspark | 62:523de36d2f88 | 264 | currentMessage = enqueuedMessages.front().message; |
tobyspark | 62:523de36d2f88 | 265 | float minSecs = enqueuedMessages.front().minSecs; |
tobyspark | 62:523de36d2f88 | 266 | float maxSecs = enqueuedMessages.front().maxSecs; |
tobyspark | 62:523de36d2f88 | 267 | enqueuedMessages.pop(); |
tobyspark | 62:523de36d2f88 | 268 | |
tobyspark | 62:523de36d2f88 | 269 | maxTimeout.detach(); |
tobyspark | 62:523de36d2f88 | 270 | minTimeout.detach(); |
tobyspark | 62:523de36d2f88 | 271 | maxTimeout.attach(this, &SPKMessageHold::handleTimeout, maxSecs); |
tobyspark | 62:523de36d2f88 | 272 | if (minSecs > 0) minTimeout.attach(this, &SPKMessageHold::handleTimeout, minSecs); |
tobyspark | 62:523de36d2f88 | 273 | state = (minSecs > 0) ? holdWaitingForMin : holdMinPassed; |
tobyspark | 62:523de36d2f88 | 274 | } |
tobyspark | 62:523de36d2f88 | 275 | |
tobyspark | 57:14d37904c889 | 276 | void handleTimeout() |
tobyspark | 57:14d37904c889 | 277 | { |
tobyspark | 57:14d37904c889 | 278 | if (enqueuedMessages.empty()) |
tobyspark | 57:14d37904c889 | 279 | { |
tobyspark | 62:523de36d2f88 | 280 | if (state == holdWaitingForMin) |
tobyspark | 62:523de36d2f88 | 281 | { |
tobyspark | 62:523de36d2f88 | 282 | state = holdMinPassed; |
tobyspark | 62:523de36d2f88 | 283 | } |
tobyspark | 62:523de36d2f88 | 284 | else |
tobyspark | 62:523de36d2f88 | 285 | { |
tobyspark | 62:523de36d2f88 | 286 | currentMessage = savedMessage; |
tobyspark | 62:523de36d2f88 | 287 | state = notHold; |
tobyspark | 62:523de36d2f88 | 288 | } |
tobyspark | 57:14d37904c889 | 289 | } |
tobyspark | 57:14d37904c889 | 290 | else |
tobyspark | 57:14d37904c889 | 291 | { |
tobyspark | 62:523de36d2f88 | 292 | dequeueMessage(); |
tobyspark | 57:14d37904c889 | 293 | } |
tobyspark | 48:c0fedfa8c525 | 294 | } |
tobyspark | 48:c0fedfa8c525 | 295 | |
tobyspark | 62:523de36d2f88 | 296 | stateType state; |
tobyspark | 48:c0fedfa8c525 | 297 | string currentMessage; |
tobyspark | 57:14d37904c889 | 298 | string savedMessage; |
tobyspark | 62:523de36d2f88 | 299 | queue< messageType >enqueuedMessages; |
tobyspark | 62:523de36d2f88 | 300 | Timeout minTimeout; |
tobyspark | 62:523de36d2f88 | 301 | Timeout maxTimeout; |
tobyspark | 48:c0fedfa8c525 | 302 | }; |