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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers spk_utils.h Source File

spk_utils.h

00001 // *SPARK D-FUSER
00002 // A project by Toby Harris
00003 // Copyright *spark audio-visual 2012
00004 //
00005 // SPK_UTILS provides utility classes for the main SPK-DVIMXR codebase, most significantly the menu system.
00006 
00007 #include <string>
00008 #include <vector>
00009 #include <queue>
00010 
00011 class SPKIndexInRange {
00012 public:
00013     void operator = (int newIndex) {
00014         set(newIndex);
00015     }
00016     
00017     void operator ++ (int) {
00018         if (idx == max) idx = wrap ? min : max;
00019         else idx++;
00020     }
00021     
00022     void operator -- (int) {
00023         if (idx == min) idx = wrap ? max : min;
00024         else idx--;
00025     }
00026     
00027     void set (int newIndex) {
00028         if (newIndex > max) idx = max;
00029         else if (newIndex < min) idx = min;
00030         else idx = newIndex;
00031     }
00032     
00033     void set (int newMin, int newMax, int newIndex = 0, bool newWrap = false) {
00034         min = newMin;
00035         max = newMax;
00036         wrap = newWrap;
00037         set(newIndex);
00038     }
00039     
00040     void setMax(int newMax) {
00041         max = newMax;
00042     }
00043     
00044     SPKIndexInRange () {
00045         min = 0;
00046         max = 1;
00047         wrap = true;
00048         idx = 0;
00049     }
00050     
00051     SPKIndexInRange (int newMin, int newMax, int newIndex = 0, bool newWrap = false) {
00052         set(newMin, newMax, newIndex, newWrap);
00053     }
00054     
00055     int index() {
00056         return idx;
00057     }
00058     
00059 private:
00060     int idx;
00061     int min, max;
00062     bool wrap;
00063 };
00064 
00065 class SPKMenu;
00066 
00067 class SPKMenuItem {
00068 public:
00069     enum itemType { changesToMenu, sendsCommand, hasHandler };
00070     itemType type;
00071     string text;
00072     void (*handler)(int, bool);
00073     union {
00074         SPKMenu* menu;
00075         int32_t command[2];
00076         void (*handler)(int, bool);
00077     } payload;
00078     
00079     SPKMenuItem(string title, SPKMenu* menu)
00080     {
00081         text = title;
00082         type = changesToMenu;
00083         payload.menu = menu;
00084     }
00085     
00086     SPKMenuItem(void (*menuItemHandler)(int, bool))
00087     {
00088         text = "[has handler]";
00089         type = hasHandler;
00090         payload.handler = menuItemHandler;
00091     }
00092     
00093     SPKMenuItem(string title, int32_t command)
00094     {
00095         text = title;
00096         type = sendsCommand;
00097         payload.command[0] = command;
00098         payload.command[1] = 0;
00099     }
00100     
00101     SPKMenuItem(string title, int32_t command1, int32_t command2)
00102     {
00103         text = title;
00104         type = sendsCommand;
00105         payload.command[0] = command1;
00106         payload.command[1] = command2;
00107     }
00108 };
00109 
00110 
00111 class SPKMenu {
00112 public:
00113     SPKMenu() {
00114         selected.set(0, 0, 0, true);
00115     }
00116     
00117     std::string title;
00118     
00119     SPKMenu& operator = (const int &newIndex) {
00120         selected = newIndex;
00121         return *this;
00122     }
00123     
00124     void operator ++ () {
00125         selected++;
00126     }
00127     
00128     void operator -- () {
00129         selected--;
00130     }
00131     
00132     void addMenuItem (SPKMenuItem menuItem) {
00133         items.push_back(menuItem);
00134         selected.setMax(items.size()-1);
00135     }
00136     
00137     void clearMenuItems() {
00138         items.clear();
00139         selected.setMax(0);
00140     }
00141     
00142     int selectedIndex() {
00143         return selected.index();
00144     }
00145     
00146     std::string  selectedString() {
00147     if (items.size() == 0) printf("SPKMenu no items");        
00148         return items[selected.index()].text;
00149     }
00150     
00151     SPKMenuItem selectedItem() {
00152     if (items.size() == 0) printf("SPKMenu no items");
00153         return items[selected.index()];
00154     }
00155         
00156 protected:
00157     SPKIndexInRange selected;
00158     std::vector<SPKMenuItem> items;
00159 };
00160 
00161 
00162 class SPKSign {
00163 public:
00164     SPKSign(PinName signWrite, PinName signError) {
00165         writeDO = new DigitalOut(signWrite);
00166         errorDO = new DigitalOut(signError);
00167     }
00168     
00169     ~SPKSign() {
00170         delete writeDO;
00171         delete errorDO;
00172     }
00173     
00174     void serialWrite() {
00175         signWriteTimeout.detach();
00176         signWriteTimeout.attach(this, &SPKSign::writeOff, 0.25);
00177         *writeDO = 1;
00178     }
00179     
00180     void serialError() {
00181         signErrorTimeout.detach();
00182         signErrorTimeout.attach(this, &SPKSign::errorOff, 0.25);
00183         *errorDO = 1;   
00184     }
00185 
00186 private:
00187     void writeOff() {
00188         *writeDO = 0;
00189     }
00190     
00191     void errorOff() {
00192         *errorDO = 0;
00193     }
00194     
00195     DigitalOut *writeDO;
00196     DigitalOut *errorDO;
00197     Timeout signWriteTimeout;
00198     Timeout signErrorTimeout;
00199 };
00200 
00201 class SPKMessageHold {
00202 public:
00203 
00204     SPKMessageHold() {
00205         state = notHold;
00206         currentMessage = "";
00207         savedMessage = "";
00208     }
00209     
00210     void addMessage(string message)
00211     {
00212         addMessage(message, 0, 0);
00213     }
00214     
00215     void addMessage(string message, float maxSecs)
00216     {
00217         addMessage(message, 0.1, maxSecs);
00218     }
00219     
00220     void addMessage(string message, float minSecs, float maxSecs) 
00221     {
00222         if (state == notHold)
00223         {
00224             if (maxSecs > 0.0f)
00225             {
00226                 state = (minSecs > 0) ? holdWaitingForMin : holdMinPassed;
00227                 savedMessage = currentMessage;
00228                 currentMessage = message;
00229                 
00230                 maxTimeout.attach(this, &SPKMessageHold::handleTimeout, maxSecs);
00231                 if (minSecs > 0) minTimeout.attach(this, &SPKMessageHold::handleTimeout, minSecs);
00232             }
00233             else
00234             {
00235                 currentMessage = message;
00236             }
00237         }
00238         if (state == holdWaitingForMin)
00239         {
00240             if (maxSecs > 0.0f)  enqueueMessage(message, minSecs, maxSecs);
00241             else                 savedMessage = message;
00242         }
00243         if (state == holdMinPassed)
00244         {
00245             if (maxSecs > 0.0f) { enqueueMessage(message, minSecs, maxSecs); dequeueMessage(); }
00246             else                savedMessage = message;
00247         }
00248     }
00249     
00250     string message() { return currentMessage; }
00251 
00252 private:
00253     enum stateType { notHold, holdWaitingForMin, holdMinPassed };
00254     struct messageType { string message; float minSecs; float maxSecs; };
00255 
00256     void enqueueMessage(string message, float minSecs, float maxSecs)
00257     {
00258         messageType messageStruct = {message, minSecs, maxSecs};
00259         enqueuedMessages.push(messageStruct);
00260     }
00261 
00262     void dequeueMessage()
00263     {
00264         currentMessage = enqueuedMessages.front().message;
00265         float minSecs = enqueuedMessages.front().minSecs;
00266         float maxSecs = enqueuedMessages.front().maxSecs;
00267         enqueuedMessages.pop();
00268         
00269         maxTimeout.detach();
00270         minTimeout.detach();
00271         maxTimeout.attach(this, &SPKMessageHold::handleTimeout, maxSecs);
00272         if (minSecs > 0) minTimeout.attach(this, &SPKMessageHold::handleTimeout, minSecs);
00273         state = (minSecs > 0) ? holdWaitingForMin : holdMinPassed;
00274     }
00275     
00276     void handleTimeout() 
00277     {
00278         if (enqueuedMessages.empty())
00279         {
00280             if (state == holdWaitingForMin)
00281             {
00282                 state = holdMinPassed;
00283             }
00284             else
00285             {
00286                 currentMessage = savedMessage;
00287                 state = notHold;
00288             }
00289         }
00290         else
00291         {
00292             dequeueMessage();
00293         }
00294     }
00295     
00296     stateType state;
00297     string currentMessage;
00298     string savedMessage;
00299     queue< messageType >enqueuedMessages;
00300     Timeout minTimeout;
00301     Timeout maxTimeout;
00302 };