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
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 };
Generated on Tue Jul 12 2022 21:39:05 by 1.7.2