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
Diff: main.cpp
- Revision:
- 0:59b1d685427c
- Child:
- 1:f0cc153fe8d3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sat May 09 20:11:58 2015 +0000 @@ -0,0 +1,249 @@ +#include "mbed.h" +#include "DMX.h" +#include "spk_oled_ssd1305.h" +#include "spk_oled_gfx.h" + +#define kUSB_BAUD 57600 + +// MBED PINS + +#define kMBED_AIN_XFADE p20 +#define kMBED_AIN_FADEUP p19 +#define kMBED_DIN_TAP_L p24 +#define kMBED_DIN_TAP_R p23 +#define kMBED_ENC_SW p15 +#define kMBED_ENC_A p16 +#define kMBED_ENC_B p17 + +#define kMBED_RS232_TTLTX p13 +#define kMBED_RS232_TTLRX p14 + +#define kMBED_OLED_MOSI p5 +#define kMBED_OLED_SCK p7 +#define kMBED_OLED_CS p8 +#define kMBED_OLED_RES p9 +#define kMBED_OLED_DC p10 + +#define kMBED_DIN_ETHLO_DMXHI p30 +#define kMBED_DOUT_RS485_TXHI_RXLO p29 +#define kMBED_RS485_TTLTX p28 +#define kMBED_RS485_TTLRX p27 + +// DMX Fixtures + +#define kDMX_PARCAN_1 4 +#define kDMX_PARCAN_2 8 +#define kDMX_PARCAN_3 12 +#define kDMX_PARCAN_4 16 + +#define kDMX_PARCAN_R 0 +#define kDMX_PARCAN_G 1 +#define kDMX_PARCAN_B 2 +#define kDMX_PARCAN_LUMA 3 + +// MISC Defines + +#define kStringBufferLength 30 + +//// USB Serial + +Serial usbSerial(USBTX, USBRX); + +//// DMX + +DigitalIn rj45ModeDIN(kMBED_DIN_ETHLO_DMXHI); +DigitalOut dmxDirectionDOUT(kMBED_DOUT_RS485_TXHI_RXLO); +enum { rj45Ethernet = 0, rj45DMX = 1}; // These values from circuit + +DMX dmx(kMBED_RS485_TTLTX, kMBED_RS485_TTLRX); + +//// Display + +// SPKDisplay(PinName mosi, PinName clk, PinName cs, PinName dc, PinName res, Serial *debugSerial = NULL); +SPKDisplay screen(kMBED_OLED_MOSI, kMBED_OLED_SCK, kMBED_OLED_CS, kMBED_OLED_DC, kMBED_OLED_RES, NULL); + +//// mbed input + +DigitalIn button(kMBED_DIN_TAP_L); +bool buttonLastState; + +string usbSerialString; +bool newData = false; + +//// LAUREL VIOLIN DATA + +// [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. +int TA, TB; + +// [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 +float P1A, P1B, P2A, P2B, P3A, P3B, P4A, P4B; + +// [S: A] = signal strength. A is RMS of audio signal in the buffer. +float S1, S2, S3, S4; + +// [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) +float F1, F2, F3, F4; + +// [B: A, B, C, D] = raw bow data, A is sensor closest to frog, D closest to tip. +float B1, B2, B3, B4; + +// [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. +float EA, EB; +int EC; + +// TOBY VIOLIN EXTRAS + +float sMax = 0.2; +float sMultiplier = 255.0/sMax; + +void usbSerialReceive(void) +{ + char receivedChar; + + //if data is ready in the buffer + while (usbSerial.readable()) + { + receivedChar = usbSerial.getc(); + + // Is end of line? + if (receivedChar == '\n' || receivedChar == '\r') + { + // [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] + int scanCount; +// scanCount = sscanf( +// usbSerialString.c_str(), +// "[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]", +// &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 +// ); +// if (scanCount == 25) + scanCount = sscanf( + usbSerialString.c_str(), + "[S: %f, %f, %f, %f],[E: %f, %f, %d]", + &S1, &S2, &S3, &S4, &EA, &EB, &EC + ); + + if (scanCount == 7) + { + newData = true; + } + else + { + screen.textToBuffer("Read vars failed", 6); + } + + // Clear to start again + usbSerialString.clear(); + } + else + { + // Build string up + usbSerialString += receivedChar; + + screen.textToBuffer(usbSerialString.c_str(),4); + } + } +} + +//// M A I N +int main() { + + // Set display font + screen.fontStartCharacter = &characterBytesStartChar; + screen.fontEndCharacter = &characterBytesEndChar; + screen.fontCharacters = characterBytes; + + // Splash screen + screen.imageToBuffer(spkDisplayLogo); + screen.textToBuffer("SPK:DMXer",0); + screen.textToBuffer("FRATRES 2015",1); + screen.textToBuffer("SW v01",2); + screen.sendBuffer(); + + if (rj45ModeDIN == rj45DMX) screen.textToBuffer("RJ45: DMX Mode", 3); + else screen.textToBuffer("RJ45: Ethernet Mode", 3); + screen.sendBuffer(); + + dmxDirectionDOUT = 1; + dmx.start(); + +// unsigned char parCanData[4]; +// parCanData[kDMX_PARCAN_R] = 255; +// parCanData[kDMX_PARCAN_G] = 255; +// parCanData[kDMX_PARCAN_B] = 255; +// parCanData[kDMX_PARCAN_LUMA] = 0; +// dmx.put(parCanData, kDMX_PARCAN_1, 4); +// dmx.put(parCanData, kDMX_PARCAN_2, 4); +// dmx.put(parCanData, kDMX_PARCAN_3, 4); +// dmx.put(parCanData, kDMX_PARCAN_4, 4); + + dmx.put(kDMX_PARCAN_1+kDMX_PARCAN_R, 255); + dmx.put(kDMX_PARCAN_1+kDMX_PARCAN_G, 255); + dmx.put(kDMX_PARCAN_1+kDMX_PARCAN_B, 255); + dmx.put(kDMX_PARCAN_1+kDMX_PARCAN_LUMA, 0); + + dmx.put(kDMX_PARCAN_2+kDMX_PARCAN_R, 255); + dmx.put(kDMX_PARCAN_2+kDMX_PARCAN_G, 255); + dmx.put(kDMX_PARCAN_2+kDMX_PARCAN_B, 255); + dmx.put(kDMX_PARCAN_2+kDMX_PARCAN_LUMA, 0); + + dmx.put(kDMX_PARCAN_3+kDMX_PARCAN_R, 255); + dmx.put(kDMX_PARCAN_3+kDMX_PARCAN_G, 255); + dmx.put(kDMX_PARCAN_3+kDMX_PARCAN_B, 255); + dmx.put(kDMX_PARCAN_3+kDMX_PARCAN_LUMA, 0); + + dmx.put(kDMX_PARCAN_4+kDMX_PARCAN_R, 255); + dmx.put(kDMX_PARCAN_4+kDMX_PARCAN_G, 255); + dmx.put(kDMX_PARCAN_4+kDMX_PARCAN_B, 255); + dmx.put(kDMX_PARCAN_4+kDMX_PARCAN_LUMA, 0); + + //// Serial + usbSerial.baud(kUSB_BAUD); + usbSerial.attach(usbSerialReceive); + + //// TASK: Prime button change detection + buttonLastState = button; + + //// TASK: GO! + + // We've finished setting up, now loop this forever... + while (true) + { + if (newData) + { + char S1DMX = S1 * sMultiplier; + char S2DMX = S2 * sMultiplier; + char S3DMX = S3 * sMultiplier; + char S4DMX = S4 * sMultiplier; + dmx.put(kDMX_PARCAN_1+kDMX_PARCAN_LUMA, S1DMX); + dmx.put(kDMX_PARCAN_2+kDMX_PARCAN_LUMA, S2DMX); + dmx.put(kDMX_PARCAN_3+kDMX_PARCAN_LUMA, S3DMX); + dmx.put(kDMX_PARCAN_4+kDMX_PARCAN_LUMA, S4DMX); + + char dmxSummary[kStringBufferLength]; + snprintf(dmxSummary, kStringBufferLength, "S %03u %03u %03u %03u", S1DMX, S2DMX, S3DMX, S4DMX); + screen.textToBuffer(dmxSummary,6); + + newData = false; + } + + // Has the button changed? + if (button != buttonLastState) { + // If so, lets update the lastState variable and then send an OSC message + buttonLastState = button; + + if (button) screen.textToBuffer("Sent: /mbed/button 1",5); + else screen.textToBuffer("Sent: /mbed/button 0",5); + } + +// for (int i = 0; i<256; i++) +// { +// for (int j = 0; j<256; j++) +// { +// dmx.put(j, i); +// } +// wait(0.01); +// } + + screen.sendBuffer(); + } +}