Uses *spark d-fuser controller hardware as a USB-DMX interface. Developed for visualising Laurel Pardue’s augmented violin with lights.
Dependencies: DMX mbed spk_oled_ssd1305
main.cpp
00001 #include "mbed.h" 00002 #include "DMX.h" 00003 #include "spk_oled_ssd1305.h" 00004 #include "spk_oled_gfx.h" 00005 00006 // https://developer.mbed.org/forum/mbed/post/4526/ 00007 // 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600 00008 #define kUSB_BAUD 57600 00009 00010 // MBED PINS 00011 00012 #define kMBED_AIN_XFADE p20 00013 #define kMBED_AIN_FADEUP p19 00014 #define kMBED_DIN_TAP_L p24 00015 #define kMBED_DIN_TAP_R p23 00016 #define kMBED_ENC_SW p15 00017 #define kMBED_ENC_A p16 00018 #define kMBED_ENC_B p17 00019 00020 #define kMBED_RS232_TTLTX p13 00021 #define kMBED_RS232_TTLRX p14 00022 00023 #define kMBED_OLED_MOSI p5 00024 #define kMBED_OLED_SCK p7 00025 #define kMBED_OLED_CS p8 00026 #define kMBED_OLED_RES p9 00027 #define kMBED_OLED_DC p10 00028 00029 #define kMBED_DIN_ETHLO_DMXHI p30 00030 #define kMBED_DOUT_RS485_TXHI_RXLO p29 00031 #define kMBED_RS485_TTLTX p28 00032 #define kMBED_RS485_TTLRX p27 00033 00034 // DMX Fixtures 00035 00036 #define kDMX_PARCAN_1 8 - 1 00037 #define kDMX_PARCAN_2 12 - 1 00038 #define kDMX_PARCAN_3 16 - 1 00039 #define kDMX_PARCAN_4 20 - 1 00040 00041 #define kDMX_PARCAN_LUMA 0 00042 #define kDMX_PARCAN_R 1 00043 #define kDMX_PARCAN_G 2 00044 #define kDMX_PARCAN_B 3 00045 00046 #define kDMX_SPOT_DIMMER 32 - 1 00047 00048 #define kDMX_PAN 36 - 1 00049 #define kDMX_TILT_MSB 37 - 1 00050 #define kDMX_TILT_LSB 38 - 1 00051 00052 #define kDMX_HAZER_HAZE 128 00053 #define kDMX_HAZER_FAN 129 00054 00055 // MISC Defines 00056 00057 #define kStringBufferLength 30 00058 #define kUSBSerialBufferLength 256 00059 00060 //// USB Serial 00061 00062 Serial usbSerial(USBTX, USBRX); 00063 00064 //// DMX 00065 00066 DigitalIn rj45ModeDIN(kMBED_DIN_ETHLO_DMXHI); 00067 DigitalOut dmxDirectionDOUT(kMBED_DOUT_RS485_TXHI_RXLO); 00068 enum { rj45Ethernet = 0, rj45DMX = 1}; // These values from circuit 00069 00070 DMX dmx(kMBED_RS485_TTLTX, kMBED_RS485_TTLRX); 00071 00072 //// Display 00073 00074 // SPKDisplay(PinName mosi, PinName clk, PinName cs, PinName dc, PinName res, Serial *debugSerial = NULL); 00075 SPKDisplay screen(kMBED_OLED_MOSI, kMBED_OLED_SCK, kMBED_OLED_CS, kMBED_OLED_DC, kMBED_OLED_RES, NULL); 00076 00077 //// mbed input 00078 00079 DigitalIn button(kMBED_DIN_TAP_L); 00080 DigitalIn buttonR(kMBED_DIN_TAP_R); 00081 bool buttonLastState; 00082 00083 char usbSerialBuffer[kUSBSerialBufferLength]; 00084 int usbSerialBufferPosition = 0; 00085 bool newStringData = false; 00086 bool newBowData = false; 00087 00088 //// LAUREL VIOLIN DATA 00089 00090 // [T: A, B] - T = timestamp. A is the time count (in minutes or something. Not presently very useful), B is sample count. I can change what is creating the stamp. Also, as I'm using sample count, this is only useful/changes when I record. 00091 int TA, TB; 00092 00093 // [P: A, B] - P = pitch. A is hardware estimate- i.e the pitch estimate that is determined solely from the fingerboard data. B is the combined hardware + audio data (more accurate, slightly slower). -1 = no data/not confident enough to estimate 00094 float P1A, P1B, P2A, P2B, P3A, P3B, P4A, P4B; 00095 00096 // [S: A] = signal strength. A is RMS of audio signal in the buffer. 00097 float S1, S2, S3, S4; 00098 00099 // [F: A, B, C, D] = finger on string raw data. generally ranges 1 (no contact) to like .4, 1 being no string down, .9 being low pitch near nut, .4 higher up in pitch closer to the bridge. A is G string (i think) 00100 float F1, F2, F3, F4; 00101 00102 // [B: A, B, C, D] = raw bow data, A is sensor closest to frog, D closest to tip. 00103 float B1, B2, B3, B4; 00104 00105 // [E: A, B, C] = bow Estimate. (currently broken) This should be A - pos estimate (0 to 1 normalized frog to tip), B- pressure (0 -400?) and C- on string/off (0, 1 if B is > 40) 0 for A/B means it isn't ready to estimate. -1 means bow off string. 00106 float EA, EB; 00107 int EC; 00108 00109 // TOBY VIOLIN EXTRAS 00110 00111 float sMaxFixed = 0.1; 00112 float sMultiplier = 255.0/sMaxFixed; 00113 00114 float eMaxFixed = 400; 00115 float eMultiplier = 255.0/eMaxFixed; 00116 00117 void testDMX() 00118 { 00119 static char state = 1; 00120 00121 if (state == 5) 00122 { 00123 dmx.put(kDMX_SPOT_DIMMER, 255); 00124 } 00125 else 00126 { 00127 dmx.put(kDMX_SPOT_DIMMER, 0); 00128 00129 int address; 00130 00131 switch (state) 00132 { 00133 case 1: address = kDMX_PARCAN_1; break; 00134 case 2: address = kDMX_PARCAN_2; break; 00135 case 3: address = kDMX_PARCAN_3; break; 00136 case 4: address = kDMX_PARCAN_4; break; 00137 } 00138 00139 unsigned char parCanData[4]; 00140 parCanData[kDMX_PARCAN_R] = 255; 00141 parCanData[kDMX_PARCAN_G] = 255; 00142 parCanData[kDMX_PARCAN_B] = 255; 00143 parCanData[kDMX_PARCAN_LUMA] = 0; 00144 dmx.put(parCanData, kDMX_PARCAN_1, 4); 00145 dmx.put(parCanData, kDMX_PARCAN_2, 4); 00146 dmx.put(parCanData, kDMX_PARCAN_3, 4); 00147 dmx.put(parCanData, kDMX_PARCAN_4, 4); 00148 00149 parCanData[kDMX_PARCAN_LUMA] = 255; 00150 dmx.put(parCanData, address, 4); 00151 } 00152 00153 if (++state > 5) state = 1; 00154 } 00155 00156 inline void processData() 00157 { 00158 float sMax = S1; 00159 if (sMax < S2) sMax = S2; 00160 if (sMax < S3) sMax = S3; 00161 if (sMax < S4) sMax = S4; 00162 00163 float threshold = sMax * 0.7; 00164 00165 if (S1 < threshold) S1 = 0; 00166 if (S2 < threshold) S2 = 0; 00167 if (S3 < threshold) S3 = 0; 00168 if (S4 < threshold) S4 = 0; 00169 } 00170 00171 void usbSerialReceive(void) 00172 { 00173 char receivedChar; 00174 00175 //if data is ready in the buffer 00176 while (usbSerial.readable()) 00177 { 00178 receivedChar = usbSerial.getc(); 00179 00180 // Is end of line? 00181 if (receivedChar == '\n' || receivedChar == '\r') 00182 { 00183 // [T: 352, 16896000],[P: 196, -1, 196, -1, 196, -1, 196, -1],[S: 0, 0, 0, 0],[F: 1, 1, 1, 1],[B: 0.5346, 0.5781, 0.9043, 0.9029],[E: 0, 0, 0] 00184 int scanCount; 00185 // scanCount = sscanf( 00186 // usbSerialString.c_str(), 00187 // "[T: %d, %d],[P: %f, %f, %f, %f, %f, %f, %f, %f],[S: %f, %f, %f, %f],[F: %f, %f, %f, %f],[B: %f, %f, %f, %f],[E: %f, %f, %d]", 00188 // &TA, &TB, &P1A, &P1B, &P2A, &P2B, &P3A, &P3B, &P4A, &P4B, &S1, &S2, &S3, &S4, &F1, &F2, &F3, &F4, &B1, &B2, &B3, &B4, &EA, &EB, &EC 00189 // ); 00190 // if (scanCount == 25) 00191 scanCount = sscanf( 00192 usbSerialBuffer, 00193 "[S: %f, %f, %f, %f],[E: %f, %f, %d]", 00194 &S1, &S2, &S3, &S4, &EA, &EB, &EC 00195 ); 00196 00197 if (scanCount == 7) 00198 { 00199 newStringData = true; 00200 newBowData = true; 00201 processData(); 00202 } 00203 else if (scanCount == 4) 00204 { 00205 newStringData = true; 00206 processData(); 00207 } 00208 else 00209 { 00210 screen.textToBuffer("Read vars failed", 6); 00211 } 00212 00213 // Clear to start again 00214 usbSerialBufferPosition = 0; 00215 } 00216 else if (usbSerialBufferPosition < kUSBSerialBufferLength) 00217 { 00218 // Build string up 00219 usbSerialBuffer[usbSerialBufferPosition++] = receivedChar; 00220 usbSerialBuffer[usbSerialBufferPosition] = 0; 00221 00222 screen.textToBuffer(usbSerialBuffer,4); 00223 } 00224 } 00225 } 00226 00227 //// M A I N 00228 int main() { 00229 00230 // Set display font 00231 screen.fontStartCharacter = &characterBytesStartChar; 00232 screen.fontEndCharacter = &characterBytesEndChar; 00233 screen.fontCharacters = characterBytes; 00234 00235 // Splash screen 00236 screen.imageToBuffer(spkDisplayLogo); 00237 screen.textToBuffer("SPK:DMXer",0); 00238 screen.textToBuffer("FRATRES 2015",1); 00239 screen.textToBuffer("SW v01",2); 00240 screen.sendBuffer(); 00241 00242 if (rj45ModeDIN == rj45DMX) screen.textToBuffer("RJ45: DMX Mode", 3); 00243 else screen.textToBuffer("RJ45: Ethernet Mode", 3); 00244 screen.sendBuffer(); 00245 00246 dmxDirectionDOUT = 1; 00247 dmx.start(); 00248 00249 dmx.put(kDMX_PARCAN_1+kDMX_PARCAN_R, 255); 00250 dmx.put(kDMX_PARCAN_1+kDMX_PARCAN_G, 255); 00251 dmx.put(kDMX_PARCAN_1+kDMX_PARCAN_B, 255); 00252 dmx.put(kDMX_PARCAN_1+kDMX_PARCAN_LUMA, 0); 00253 00254 dmx.put(kDMX_PARCAN_2+kDMX_PARCAN_R, 255); 00255 dmx.put(kDMX_PARCAN_2+kDMX_PARCAN_G, 255); 00256 dmx.put(kDMX_PARCAN_2+kDMX_PARCAN_B, 255); 00257 dmx.put(kDMX_PARCAN_2+kDMX_PARCAN_LUMA, 0); 00258 00259 dmx.put(kDMX_PARCAN_3+kDMX_PARCAN_R, 255); 00260 dmx.put(kDMX_PARCAN_3+kDMX_PARCAN_G, 255); 00261 dmx.put(kDMX_PARCAN_3+kDMX_PARCAN_B, 255); 00262 dmx.put(kDMX_PARCAN_3+kDMX_PARCAN_LUMA, 0); 00263 00264 dmx.put(kDMX_PARCAN_4+kDMX_PARCAN_R, 255); 00265 dmx.put(kDMX_PARCAN_4+kDMX_PARCAN_G, 255); 00266 dmx.put(kDMX_PARCAN_4+kDMX_PARCAN_B, 255); 00267 dmx.put(kDMX_PARCAN_4+kDMX_PARCAN_LUMA, 0); 00268 00269 dmx.put(kDMX_PAN, 50); 00270 00271 //// Serial 00272 usbSerial.baud(kUSB_BAUD); 00273 usbSerial.attach(usbSerialReceive); 00274 00275 //// TASK: Prime button change detection 00276 buttonLastState = button; 00277 00278 //// TASK: GO! 00279 00280 // We've finished setting up, now loop this forever... 00281 while (true) 00282 { 00283 if (newStringData) 00284 { 00285 char S1DMX = S1 * sMultiplier; 00286 char S2DMX = S2 * sMultiplier; 00287 char S3DMX = S3 * sMultiplier; 00288 char S4DMX = S4 * sMultiplier; 00289 00290 unsigned char parCanData[4]; 00291 parCanData[kDMX_PARCAN_R] = 255; 00292 parCanData[kDMX_PARCAN_G] = 255; 00293 parCanData[kDMX_PARCAN_B] = 255; 00294 00295 parCanData[kDMX_PARCAN_LUMA] = S1DMX; 00296 dmx.put(parCanData, kDMX_PARCAN_1, 4); 00297 00298 parCanData[kDMX_PARCAN_LUMA] = S2DMX; 00299 dmx.put(parCanData, kDMX_PARCAN_2, 4); 00300 00301 parCanData[kDMX_PARCAN_LUMA] = S3DMX; 00302 dmx.put(parCanData, kDMX_PARCAN_3, 4); 00303 00304 parCanData[kDMX_PARCAN_LUMA] = S4DMX; 00305 dmx.put(parCanData, kDMX_PARCAN_4, 4); 00306 00307 char dmxSummary[kStringBufferLength]; 00308 snprintf(dmxSummary, kStringBufferLength, "S %03u %03u %03u %03u", S1DMX, S2DMX, S3DMX, S4DMX); 00309 screen.textToBuffer(dmxSummary,6); 00310 00311 newStringData = false; 00312 } 00313 00314 if (newBowData) 00315 { 00316 // EA = Position, EB = Pressure, EC = On string 00317 if (EB < 0) EB = 0; 00318 char bowDMX = EB * eMultiplier; 00319 if (EC) 00320 { 00321 dmx.put(kDMX_SPOT_DIMMER, bowDMX); 00322 } 00323 else 00324 { 00325 dmx.put(kDMX_SPOT_DIMMER, 0); 00326 } 00327 00328 dmx.put(kDMX_TILT_MSB, 15 + EA * 50); 00329 } 00330 00331 // Has the button changed? 00332 if (button != buttonLastState) { 00333 // If so, lets update the lastState variable and then send an OSC message 00334 buttonLastState = button; 00335 00336 if (button) 00337 { 00338 testDMX(); 00339 screen.textToBuffer("Sent: /mbed/button 1",5); 00340 //dmx.put(kDMX_HAZER_HAZE, 128); 00341 //dmx.put(kDMX_HAZER_FAN, 255); 00342 } 00343 else 00344 { 00345 screen.textToBuffer("Sent: /mbed/button 0",5); 00346 dmx.put(kDMX_HAZER_HAZE, 0); 00347 dmx.put(kDMX_HAZER_FAN, 0); 00348 } 00349 } 00350 00351 screen.sendBuffer(); 00352 } 00353 }
Generated on Sat Jul 23 2022 07:05:31 by 1.7.2