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
- Committer:
- tobyspark
- Date:
- 2014-07-09
- Revision:
- 78:7517f0060611
- Parent:
- 62:523de36d2f88
File content as of revision 78:7517f0060611:
// *SPARK D-FUSER // A project by Toby Harris // Copyright *spark audio-visual 2012 // // SPK_UTILS provides utility classes for the main SPK-DVIMXR codebase, most significantly the menu system. #include <string> #include <vector> #include <queue> class SPKIndexInRange { public: void operator = (int newIndex) { set(newIndex); } void operator ++ (int) { if (idx == max) idx = wrap ? min : max; else idx++; } void operator -- (int) { if (idx == min) idx = wrap ? max : min; else idx--; } void set (int newIndex) { if (newIndex > max) idx = max; else if (newIndex < min) idx = min; else idx = newIndex; } void set (int newMin, int newMax, int newIndex = 0, bool newWrap = false) { min = newMin; max = newMax; wrap = newWrap; set(newIndex); } void setMax(int newMax) { max = newMax; } SPKIndexInRange () { min = 0; max = 1; wrap = true; idx = 0; } SPKIndexInRange (int newMin, int newMax, int newIndex = 0, bool newWrap = false) { set(newMin, newMax, newIndex, newWrap); } int index() { return idx; } private: int idx; int min, max; bool wrap; }; class SPKMenu; class SPKMenuItem { public: enum itemType { changesToMenu, sendsCommand, hasHandler }; itemType type; string text; void (*handler)(int, bool); union { SPKMenu* menu; int32_t command[2]; void (*handler)(int, bool); } payload; SPKMenuItem(string title, SPKMenu* menu) { text = title; type = changesToMenu; payload.menu = menu; } SPKMenuItem(void (*menuItemHandler)(int, bool)) { text = "[has handler]"; type = hasHandler; payload.handler = menuItemHandler; } SPKMenuItem(string title, int32_t command) { text = title; type = sendsCommand; payload.command[0] = command; payload.command[1] = 0; } SPKMenuItem(string title, int32_t command1, int32_t command2) { text = title; type = sendsCommand; payload.command[0] = command1; payload.command[1] = command2; } }; class SPKMenu { public: SPKMenu() { selected.set(0, 0, 0, true); } std::string title; SPKMenu& operator = (const int &newIndex) { selected = newIndex; return *this; } void operator ++ () { selected++; } void operator -- () { selected--; } void addMenuItem (SPKMenuItem menuItem) { items.push_back(menuItem); selected.setMax(items.size()-1); } void clearMenuItems() { items.clear(); selected.setMax(0); } int selectedIndex() { return selected.index(); } std::string selectedString() { if (items.size() == 0) printf("SPKMenu no items"); return items[selected.index()].text; } SPKMenuItem selectedItem() { if (items.size() == 0) printf("SPKMenu no items"); return items[selected.index()]; } protected: SPKIndexInRange selected; std::vector<SPKMenuItem> items; }; class SPKSign { public: SPKSign(PinName signWrite, PinName signError) { writeDO = new DigitalOut(signWrite); errorDO = new DigitalOut(signError); } ~SPKSign() { delete writeDO; delete errorDO; } void serialWrite() { signWriteTimeout.detach(); signWriteTimeout.attach(this, &SPKSign::writeOff, 0.25); *writeDO = 1; } void serialError() { signErrorTimeout.detach(); signErrorTimeout.attach(this, &SPKSign::errorOff, 0.25); *errorDO = 1; } private: void writeOff() { *writeDO = 0; } void errorOff() { *errorDO = 0; } DigitalOut *writeDO; DigitalOut *errorDO; Timeout signWriteTimeout; Timeout signErrorTimeout; }; class SPKMessageHold { public: SPKMessageHold() { state = notHold; currentMessage = ""; savedMessage = ""; } void addMessage(string message) { addMessage(message, 0, 0); } void addMessage(string message, float maxSecs) { addMessage(message, 0.1, maxSecs); } void addMessage(string message, float minSecs, float maxSecs) { if (state == notHold) { if (maxSecs > 0.0f) { state = (minSecs > 0) ? holdWaitingForMin : holdMinPassed; savedMessage = currentMessage; currentMessage = message; maxTimeout.attach(this, &SPKMessageHold::handleTimeout, maxSecs); if (minSecs > 0) minTimeout.attach(this, &SPKMessageHold::handleTimeout, minSecs); } else { currentMessage = message; } } if (state == holdWaitingForMin) { if (maxSecs > 0.0f) enqueueMessage(message, minSecs, maxSecs); else savedMessage = message; } if (state == holdMinPassed) { if (maxSecs > 0.0f) { enqueueMessage(message, minSecs, maxSecs); dequeueMessage(); } else savedMessage = message; } } string message() { return currentMessage; } private: enum stateType { notHold, holdWaitingForMin, holdMinPassed }; struct messageType { string message; float minSecs; float maxSecs; }; void enqueueMessage(string message, float minSecs, float maxSecs) { messageType messageStruct = {message, minSecs, maxSecs}; enqueuedMessages.push(messageStruct); } void dequeueMessage() { currentMessage = enqueuedMessages.front().message; float minSecs = enqueuedMessages.front().minSecs; float maxSecs = enqueuedMessages.front().maxSecs; enqueuedMessages.pop(); maxTimeout.detach(); minTimeout.detach(); maxTimeout.attach(this, &SPKMessageHold::handleTimeout, maxSecs); if (minSecs > 0) minTimeout.attach(this, &SPKMessageHold::handleTimeout, minSecs); state = (minSecs > 0) ? holdWaitingForMin : holdMinPassed; } void handleTimeout() { if (enqueuedMessages.empty()) { if (state == holdWaitingForMin) { state = holdMinPassed; } else { currentMessage = savedMessage; state = notHold; } } else { dequeueMessage(); } } stateType state; string currentMessage; string savedMessage; queue< messageType >enqueuedMessages; Timeout minTimeout; Timeout maxTimeout; };