Skip to content

Instantly share code, notes, and snippets.

@yrrah
Last active December 16, 2015 09:49

Revisions

  1. yrrah revised this gist Apr 25, 2013. 1 changed file with 463 additions and 444 deletions.
    907 changes: 463 additions & 444 deletions gistfile1.c
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,7 @@
    #include <TimerOne.h>
    #include <DmxSimple.h>
    #include <TinyXML.h>

    #define DEBUG 1
    #define MIDI_BAUDRATE 31250
    #define COMPILE_MIDI_IN 1 // Set this setting to 1 to use the MIDI input.
    @@ -101,87 +101,79 @@ int clockChan = -1;
    int clockNote = -1;
    int clockVelocity = -1;

    int curRow=0;
    int curCol=0;
    int curRow = 0;
    int curCol = 0;

    int files = 0;
    int CB = INIT_WAIT;

    void XML_callback( uint8_t statusflags, char* tagName, uint16_t tagNameLen, char* data, uint16_t dataLen )
    {
    void XML_callback(uint8_t statusflags, char* tagName, uint16_t tagNameLen, char* data, uint16_t dataLen) {
    char ns[] = "num-scenes";
    char fn[] = "filename";
    char ct[] = "clockType";
    char cc[] = "clockChan";
    char cn[] = "clockNote";
    char cv[] = "clockVelocity";
    if (statusflags & STATUS_ATTR_TEXT)
    {
    if(!strcmp(ns, tagName)){
    numScenes = asciiHexToInt(data, 2);

    Serial.print("numScenes: ");
    Serial.println(numScenes);

    fileNames = (char**) malloc(numScenes * sizeof (char*));
    }
    if(!strcmp(fn, tagName)){
    Serial.print("Filename: ");
    fileNames[files] = (char*) malloc((strlen(data)+1)*sizeof(char));
    strcpy(fileNames[files],data);
    Serial.println(fileNames[files]);
    if(numScenes == ++files){
    XMLdone = true;
    if (statusflags & STATUS_ATTR_TEXT) {
    if (!strcmp(ns, tagName)) {
    numScenes = asciiHexToInt(data, 2);

    Serial.print("numScenes: ");
    Serial.println(numScenes);

    fileNames = (char**) malloc(numScenes * sizeof (char*));
    }
    if (!strcmp(fn, tagName)) {
    Serial.print("Filename: ");
    fileNames[files] = (char*) malloc((strlen(data) + 1) * sizeof (char));
    strcpy(fileNames[files], data);
    Serial.println(fileNames[files]);
    if (numScenes == ++files) {
    XMLdone = true;
    }
    }
    if (!strcmp(ct, tagName)) {
    Serial.print("Clock MIDI Message Type: ");
    clockType = asciiHexToInt(data, 2);
    Serial.println(clockType);
    }
    if (!strcmp(cc, tagName)) {
    Serial.print("Clock MIDI Channel: ");
    clockChan = asciiHexToInt(data, 2);
    Serial.println(clockChan);
    }
    if (!strcmp(cn, tagName)) {
    Serial.print("Clock MIDI Note: ");
    clockNote = asciiHexToInt(data, 2);
    Serial.println(clockNote);
    }
    if (!strcmp(cv, tagName)) {
    Serial.print("Clock MIDI Velocity: ");
    clockVelocity = asciiHexToInt(data, 2);
    Serial.println(clockVelocity);
    }

    }
    if(!strcmp(ct, tagName)){
    Serial.print("Clock MIDI Message Type: ");
    clockType = asciiHexToInt(data, 2);
    Serial.println(clockType);
    }
    if(!strcmp(cc, tagName)){
    Serial.print("Clock MIDI Channel: ");
    clockChan = asciiHexToInt(data, 2);
    Serial.println(clockChan);
    }
    if(!strcmp(cn, tagName)){
    Serial.print("Clock MIDI Note: ");
    clockNote = asciiHexToInt(data, 2);
    Serial.println(clockNote);
    }
    if(!strcmp(cv, tagName)){
    Serial.print("Clock MIDI Velocity: ");
    clockVelocity = asciiHexToInt(data, 2);
    Serial.println(clockVelocity);
    }

    }
    }

    static void readXML() {
    TinyXML xml;
    uint8_t buffer[100];
    uint16_t buflen = 100;

    static void readXML(){
    TinyXML xml;
    uint8_t buffer[100];
    uint16_t buflen = 100;

    xml.init((uint8_t*)&buffer,buflen,&XML_callback);

    while(myFile.available()&&!XMLdone){

    char c = myFile.read();
    xml.processChar(c);


    }


    }
    xml.init((uint8_t*) & buffer, buflen, &XML_callback);

    while (myFile.available() && !XMLdone) {

    char c = myFile.read();
    xml.processChar(c);


    }


    }

    void loadFrame(int FrameID) {
    int i;
    int chan, val, upVal;
    @@ -207,7 +199,7 @@ void loadFrame(int FrameID) {
    //read and execute DMX instructions
    in = myFile.read();
    while (myFile.available() && in != '%' && in != '#') {

    switch (in) {
    case 'S':
    case 'P':
    @@ -261,30 +253,30 @@ void loadFrame(int FrameID) {
    case 'F':
    switch (in2) {
    case 'U'://FU = Fade Up
    fades[chan][0] = 1;
    DmxSimple.write(chan, val);
    break;
    fades[chan][0] = 1;
    DmxSimple.write(chan, val);
    break;
    case 'D'://FD = Fade Down
    fades[chan][0] = 2;
    DmxSimple.write(chan, upVal);
    fades[chan][0] = 2;
    DmxSimple.write(chan, upVal);
    break;
    }
    fades[chan][1] = val;
    fades[chan][2] = upVal;
    fades[chan][1] = val;
    fades[chan][2] = upVal;
    break;
    case 'M':
    /* Serial.print(val);
    Serial.print(" ");
    Serial.println(upVal);
    */ switch (in2) {
    /* Serial.print(val);
    Serial.print(" ");
    Serial.println(upVal);
    */ switch (in2) {
    case '1'://M1 = MIDI Note
    out = (int) ((global_note / 127)*(upVal - val) + val);
    break;
    case '2'://M2 = MIDI Velocity
    out = (int) ((global_velocity / 127)*(upVal - val) + val);
    break;
    }
    // Serial.println(float2s(out, 5));
    // Serial.println(float2s(out, 5));
    DmxSimple.write(chan, out);
    break;
    }
    @@ -313,160 +305,158 @@ void loadScene(char* fileName) {

    int i;
    int looplength;
    // open the file. note that only one file can be open at a time,

    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    myFile.close();
    myFile.close();
    myFile = SD.open(fileName, FILE_READ);
    if (!myFile) {
    // if the file didn't open, print an error:
    #ifdef DEBUG
    Serial.print("error opening scene: ");
    Serial.println(fileName);
    Serial.println(fileName);
    #endif
    } else {
    Serial.print("Opening Scene: ");
    Serial.println(fileName);
    //free the memory for the old case array if it exists
    if (fgcount != 0) {
    for (i = 0; i < fgcount; i++)
    free(caseArray[i]);
    free(caseArray);
    }

    myFile.readBytes(temp, 2);
    fgcount = asciiHexToInt(temp, 2);

    myFile.readBytes(temp, 2);
    looplength = asciiHexToInt(temp, 2);

    myFile.readBytes(temp, 2);
    maxChannel = asciiHexToInt(temp, 2);

    fades = (int**) malloc(maxChannel * sizeof (int*));

    for (i = 0; i < maxChannel; i++) {
    fades[i] = (int*) malloc(3 * sizeof (int));
    fades[i][0] = 0;
    }

    #ifdef DEBUG
    Serial.print("fgcount ");
    Serial.println(fgcount);
    Serial.print("looplength ");
    Serial.println(looplength);
    Serial.print("maxChannel ");
    Serial.println(maxChannel);
    #endif

    caseInfo = (int**) malloc(fgcount * sizeof (int*));

    for (i = 0; i < fgcount; i++) {
    caseInfo[i] = (int*) malloc(3 * sizeof (int));

    while (myFile.read() != '#');

    myFile.readBytes(temp, 2);
    caseInfo[i][FG_LENGTH] = asciiHexToInt(temp, 2);
    caseInfo[i][FG_ADDR] = myFile.position();
    caseInfo[i][CURRENT_F] = 0;

    #ifdef DEBUG
    Serial.flush();
    Serial.print("------ Case Info ");
    Serial.print(i);
    Serial.println(" -------");
    Serial.print("FG Length: ");
    Serial.println(caseInfo[i][FG_LENGTH]);
    Serial.print("FG Address: ");
    Serial.println(caseInfo[i][FG_ADDR]);
    Serial.print("Current Frame: ");
    Serial.println(caseInfo[i][CURRENT_F]);
    #endif
    }else{
    Serial.print("Opening Scene: ");
    Serial.println(fileName);
    //free the memory for the old case array if it exists
    if (fgcount != 0) {
    for (i = 0; i < fgcount; i++)
    free(caseArray[i]);
    free(caseArray);
    }

    myFile.readBytes(temp, 2);
    fgcount = asciiHexToInt(temp, 2);

    myFile.readBytes(temp, 2);
    looplength = asciiHexToInt(temp, 2);

    myFile.readBytes(temp, 2);
    maxChannel = asciiHexToInt(temp, 2);

    fades = (int**) malloc(maxChannel * sizeof (int*));

    for (i = 0; i < maxChannel; i++) {
    fades[i] = (int*) malloc(3 * sizeof (int));
    fades[i][0] = 0;
    }

    #ifdef DEBUG
    Serial.print("fgcount ");
    Serial.println(fgcount);
    Serial.print("looplength ");
    Serial.println(looplength);
    Serial.print("maxChannel ");
    Serial.println(maxChannel);
    #endif

    caseInfo = (int**) malloc(fgcount * sizeof (int*));

    for (i = 0; i < fgcount; i++) {
    caseInfo[i] = (int*) malloc(3 * sizeof (int));

    while (myFile.read() != '#');

    myFile.readBytes(temp, 2);
    caseInfo[i][FG_LENGTH] = asciiHexToInt(temp, 2);
    caseInfo[i][FG_ADDR] = myFile.position();
    caseInfo[i][CURRENT_F] = 0;

    #ifdef DEBUG
    Serial.flush();
    Serial.print("------ Case Info ");
    Serial.print(i);
    Serial.println(" -------");
    Serial.print("FG Length: ");
    Serial.println(caseInfo[i][FG_LENGTH]);
    Serial.print("FG Address: ");
    Serial.println(caseInfo[i][FG_ADDR]);
    Serial.print("Current Frame: ");
    Serial.println(caseInfo[i][CURRENT_F]);
    #endif

    }

    while (myFile.read() != '$');

    myFile.readBytes(temp, 2);
    caseCount = asciiHexToInt(temp, 2);
    int fg = 0;


    caseArray = (int**) malloc(caseCount * sizeof (int*));
    for (i = 0; i < caseCount; i++) {
    caseArray[i] = (int*) malloc(6 * sizeof (int));

    char c = myFile.read();
    if(c == '$'){
    fg++;
    }

    caseArray[i][FRAME_GROUP] = fg;
    //MIDI Listen Channel
    myFile.readBytes(temp, 2);
    caseArray[i][LISTEN_CHAN] = asciiHexToInt(temp, 2);
    //MIDI low case value
    myFile.readBytes(temp, 2);
    caseArray[i][CASE_VAL_L] = asciiHexToInt(temp, 2);
    //MIDI high case value
    myFile.readBytes(temp, 2);
    caseArray[i][CASE_VAL_H] = asciiHexToInt(temp, 2);
    //MIDI varible (pitch,velocity,etc)
    myFile.readBytes(temp, 1);
    caseArray[i][MIDI_VAR] = asciiHexToInt(temp, 1);
    //MIDI message type (note on, note off, etc)
    myFile.readBytes(temp, 1);
    caseArray[i][MSG_TYPE] = asciiHexToInt(temp, 1);

    #ifdef DEBUG
    Serial.flush();
    Serial.print("------ Case Array Index ");
    Serial.print(i);
    Serial.println(" -------");
    Serial.print("Frame Group ");
    Serial.println(caseArray[i][FRAME_GROUP]);
    Serial.print("MIDI Listen Channel ");
    Serial.println(caseArray[i][LISTEN_CHAN]);
    Serial.print("MIDI low case value ");
    Serial.println(caseArray[i][CASE_VAL_L]);
    Serial.print("MIDI high case value ");
    Serial.println(caseArray[i][CASE_VAL_H]);
    Serial.print("MIDI varible ");
    Serial.println(caseArray[i][MIDI_VAR]);
    Serial.print("MIDI message type ");
    Serial.println(caseArray[i][MSG_TYPE]);
    Serial.flush();
    #endif

    }
    }

    }

    while (myFile.read() != '$');

    myFile.readBytes(temp, 2);
    caseCount = asciiHexToInt(temp, 2);
    int fg = 0;


    caseArray = (int**) malloc(caseCount * sizeof (int*));
    for (i = 0; i < caseCount; i++) {
    caseArray[i] = (int*) malloc(6 * sizeof (int));

    char c = myFile.read();
    if (c == '$') {
    fg++;
    }

    caseArray[i][FRAME_GROUP] = fg;
    //MIDI Listen Channel
    myFile.readBytes(temp, 2);
    caseArray[i][LISTEN_CHAN] = asciiHexToInt(temp, 2);
    //MIDI low case value
    myFile.readBytes(temp, 2);
    caseArray[i][CASE_VAL_L] = asciiHexToInt(temp, 2);
    //MIDI high case value
    myFile.readBytes(temp, 2);
    caseArray[i][CASE_VAL_H] = asciiHexToInt(temp, 2);
    //MIDI varible (pitch,velocity,etc)
    myFile.readBytes(temp, 1);
    caseArray[i][MIDI_VAR] = asciiHexToInt(temp, 1);
    //MIDI message type (note on, note off, etc)
    myFile.readBytes(temp, 1);
    caseArray[i][MSG_TYPE] = asciiHexToInt(temp, 1);

    #ifdef DEBUG
    Serial.flush();
    Serial.print("------ Case Array Index ");
    Serial.print(i);
    Serial.println(" -------");
    Serial.print("Frame Group ");
    Serial.println(caseArray[i][FRAME_GROUP]);
    Serial.print("MIDI Listen Channel ");
    Serial.println(caseArray[i][LISTEN_CHAN]);
    Serial.print("MIDI low case value ");
    Serial.println(caseArray[i][CASE_VAL_L]);
    Serial.print("MIDI high case value ");
    Serial.println(caseArray[i][CASE_VAL_H]);
    Serial.print("MIDI varible ");
    Serial.println(caseArray[i][MIDI_VAR]);
    Serial.print("MIDI message type ");
    Serial.println(caseArray[i][MSG_TYPE]);
    Serial.flush();
    #endif

    }
    }
    }

    void count() {
    milliSec++;
    // Serial.println(milliSec);
    step = 255/period;
    if(step==0)step = 1;

    if(S1_count--==0){
    S1_EN = 1;
    }
    if(S2_count--==0){
    S2_EN = 1;
    }
    if(S3_count--==0){
    S3_EN = 1;
    }
    if(S4_count--==0){
    S4_EN = 1;
    }
    if(CB--==0){
    buttonled(curRow,curCol);
    }
    }

    // Serial.println(milliSec);
    step = 255 / period;
    if (step == 0)step = 1;

    if (S1_count-- == 0) {
    S1_EN = 1;
    }
    if (S2_count-- == 0) {
    S2_EN = 1;
    }
    if (S3_count-- == 0) {
    S3_EN = 1;
    }
    if (S4_count-- == 0) {
    S4_EN = 1;
    }
    if (CB-- == 0) {
    buttonled(curRow, curCol);
    }
    }

    int asciiHexToInt(char* a, int length) {
    //converts acii representation of hex eg 'ff' to 0xFF
    @@ -500,21 +490,21 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    int i;

    //MIDI Clock Signal
    if ( ((midiType==clockType)||(clockType==-1)) && ((midiChan==clockChan)||(clockChan==-1))
    && ((note==clockNote)||(clockNote==-1)) && ((velocity==clockVelocity)||(clockVelocity==-1))){
    if (((midiType == clockType) || (clockType == -1)) && ((midiChan == clockChan) || (clockChan == -1))
    && ((note == clockNote) || (clockNote == -1)) && ((velocity == clockVelocity) || (clockVelocity == -1))) {

    #ifdef DEBUG

    Serial.print("Clock... Period: ");
    Serial.println(period);
    Serial.println(period);
    #endif

    period = milliSec;
    period = milliSec;
    milliSec = 0;

    }

    #ifdef DEBUG
    #ifdef DEBUG
    Serial.print("Type: ");
    Serial.print(midiType);
    Serial.print(" Chan: ");
    @@ -523,7 +513,7 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    Serial.print(note);
    Serial.print(" velocity: ");
    Serial.println(velocity);
    #endif
    #endif
    //loop through all cases
    for (int i = 0; i < caseCount; i++) {

    @@ -553,210 +543,238 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    return 0;
    }

    void blackout(){
    digitalWrite(ledground1, HIGH);
    digitalWrite(ledground2, HIGH);
    digitalWrite(ledground3, HIGH);
    digitalWrite(ledground4, HIGH);
    digitalWrite(redled, LOW);
    digitalWrite(greenled, LOW);
    digitalWrite(blueled, LOW);
    digitalWrite(whiteredled, LOW);
    digitalWrite(whitegreenled, LOW);
    digitalWrite(whiteblueled, LOW);
    void blackout() {
    digitalWrite(ledground1, HIGH);
    digitalWrite(ledground2, HIGH);
    digitalWrite(ledground3, HIGH);
    digitalWrite(ledground4, HIGH);
    digitalWrite(redled, LOW);
    digitalWrite(greenled, LOW);
    digitalWrite(blueled, LOW);
    digitalWrite(whiteredled, LOW);
    digitalWrite(whitegreenled, LOW);
    digitalWrite(whiteblueled, LOW);
    }

    void down1()
    {
    if(S1_EN){
    S1_EN = 0; S1_P=1;
    S1_count = SW_DELAY;
    }
    void down1() {
    if (S1_EN) {
    S1_EN = 0;
    S1_P = 1;
    S1_count = SW_DELAY;
    }
    }
    void down2()
    {
    if(S2_EN){
    S2_EN = 0; S2_P=1;
    S2_count = SW_DELAY;
    }

    void down2() {
    if (S2_EN) {
    S2_EN = 0;
    S2_P = 1;
    S2_count = SW_DELAY;
    }
    }

    void down3()
    {
    if(S3_EN){
    S3_EN = 0; S3_P=1;
    S3_count = SW_DELAY;
    }
    void down3() {
    if (S3_EN) {
    S3_EN = 0;
    S3_P = 1;
    S3_count = SW_DELAY;
    }
    }

    void down4()
    {
    if(S4_EN){
    S4_EN = 0; S4_P=1;
    S4_count = 50;
    }
    void down4() {
    if (S4_EN) {
    S4_EN = 0;
    S4_P = 1;
    S4_count = 50;
    }
    }

    void buttonled(int row,int collumn){
    blackout();
    switch (row){
    case 0:
    digitalWrite(ledground1,LOW);
    break;

    case 1:
    digitalWrite(ledground2,LOW);
    break;
    case 2:
    digitalWrite(ledground3,LOW);
    break;

    case 3:
    digitalWrite(ledground4,LOW);
    break;
    }
    switch(collumn){
    case -1:
    digitalWrite(whiteredled,HIGH);
    break;
    case 0:
    digitalWrite(whiteredled,HIGH);
    digitalWrite(whitegreenled,HIGH);
    digitalWrite(whiteblueled,HIGH);
    break;
    case 1:
    digitalWrite(blueled,HIGH);
    digitalWrite(whiteblueled,HIGH);
    break;
    case 2:
    digitalWrite(greenled,HIGH);
    digitalWrite(whitegreenled,HIGH);
    break;
    case 3:
    digitalWrite(redled,HIGH);
    digitalWrite(whiteredled,HIGH);
    break;
    }
    void buttonled(int row, int collumn) {

    blackout();
    switch (row) {
    case 0:
    digitalWrite(ledground1, LOW);
    break;

    case 1:
    digitalWrite(ledground2, LOW);
    break;

    case 2:
    digitalWrite(ledground3, LOW);
    break;

    case 3:
    digitalWrite(ledground4, LOW);
    break;
    }
    switch (collumn) {

    case -1:
    digitalWrite(whiteredled, HIGH);
    break;

    case 0:
    digitalWrite(whiteredled, HIGH);
    digitalWrite(whitegreenled, HIGH);
    digitalWrite(whiteblueled, HIGH);
    break;

    case 1:
    digitalWrite(blueled, HIGH);
    digitalWrite(whiteblueled, HIGH);

    break;

    case 2:
    digitalWrite(greenled, HIGH);
    digitalWrite(whitegreenled, HIGH);
    break;

    case 3:
    digitalWrite(redled, HIGH);
    digitalWrite(whiteredled, HIGH);

    break;

    }
    }

    void loop() {
    boolean dmx = 0;
    int i;
    int newScene = 0;
    boolean pressed = 0;

    if(S1_P){
    S1_P = 0;
    pressed = 1;
    if(++S1_n>3||S1_n>=numScenes){S1_n = 0;}
    newScene = S1_n;
    Serial.println(newScene);
    if(newScene<numScenes){

    selectedScene = newScene;
    buttonled(0,S1_n);
    curRow=0;curCol=S1_n;
    }else{S1_n=0; buttonled(0,-1);CB = CB_COUNT;}

    }else if(S2_P){
    S2_P = 0;
    if(++S2_n>3||4+S2_n>=numScenes){S2_n = 0;}
    newScene = 4+S2_n;
    if(newScene<numScenes){
    pressed = 1;
    selectedScene = newScene;
    buttonled(1,S2_n);
    curRow=1;curCol=S2_n;
    }else{S2_n=0; buttonled(1,-1);CB = CB_COUNT;}


    }else if(S3_P){
    S3_P = 0;
    if(++S3_n>3||8+S3_n>=numScenes){S3_n = 0;}
    newScene = 8+S3_n;
    if(newScene<numScenes){
    pressed = 1;
    selectedScene = newScene;
    buttonled(2,S3_n);
    curRow=2;curCol=S3_n;
    }else{S3_n=0; buttonled(2,-1);CB = CB_COUNT;}

    }else if(S4_P){
    S4_P = 0;
    if(++S4_n>3||12+S4_n>=numScenes){S4_n = 0;}
    newScene = 12+S4_n;
    if(newScene<numScenes){
    pressed = 1;
    selectedScene = newScene;
    buttonled(3,S4_n);
    curRow=3;curCol=S4_n;
    }else{S4_n=0; buttonled(3,-1);CB = CB_COUNT;
    }

    }else{
    pressed = 0;
    }
    if(pressed){
    Serial.print("New scene selected: [");
    Serial.print(selectedScene);
    Serial.print("]");
    Serial.println(fileNames[selectedScene]);
    loadScene(fileNames[selectedScene]);
    }




    if (S1_P) {
    S1_P = 0;
    pressed = 1;
    if (++S1_n > 3 || S1_n >= numScenes) {
    S1_n = 0;
    }
    newScene = S1_n;
    Serial.println(newScene);
    if (newScene < numScenes) {

    selectedScene = newScene;
    buttonled(0, S1_n);
    curRow = 0;
    curCol = S1_n;
    } else {
    S1_n = 0;
    buttonled(0, -1);
    CB = CB_COUNT;
    }

    } else if (S2_P) {
    S2_P = 0;
    if (++S2_n > 3 || 4 + S2_n >= numScenes) {
    S2_n = 0;
    }
    newScene = 4 + S2_n;
    if (newScene < numScenes) {
    pressed = 1;
    selectedScene = newScene;
    buttonled(1, S2_n);
    curRow = 1;
    curCol = S2_n;
    } else {
    S2_n = 0;
    buttonled(1, -1);
    CB = CB_COUNT;
    }


    } else if (S3_P) {
    S3_P = 0;
    if (++S3_n > 3 || 8 + S3_n >= numScenes) {
    S3_n = 0;
    }
    newScene = 8 + S3_n;
    if (newScene < numScenes) {
    pressed = 1;
    selectedScene = newScene;
    buttonled(2, S3_n);
    curRow = 2;
    curCol = S3_n;
    } else {
    S3_n = 0;
    buttonled(2, -1);
    CB = CB_COUNT;
    }

    } else if (S4_P) {
    S4_P = 0;
    if (++S4_n > 3 || 12 + S4_n >= numScenes) {
    S4_n = 0;
    }
    newScene = 12 + S4_n;
    if (newScene < numScenes) {
    pressed = 1;
    selectedScene = newScene;
    buttonled(3, S4_n);
    curRow = 3;
    curCol = S4_n;
    } else {
    S4_n = 0;
    buttonled(3, -1);
    CB = CB_COUNT;
    }

    } else {
    pressed = 0;
    }
    if (pressed) {
    Serial.print("New scene selected: [");
    Serial.print(selectedScene);
    Serial.print("]");
    Serial.println(fileNames[selectedScene]);
    loadScene(fileNames[selectedScene]);
    }





    if (usbMIDI.read())
    dmx = handleMIDI(usbMIDI.getType(), usbMIDI.getChannel(), usbMIDI.getData1(), usbMIDI.getData2());
    else if (MIDI.read())
    handleMIDI(MIDI.getType(), MIDI.getChannel(), MIDI.getData1(), MIDI.getData2());

    if (step){
    for (i = 0; i < maxChannel; i++) {
    if(fades[i][0] == 1){//fade up
    fades[i][1] = fades[i][1] + step;//increase fade
    if(fades[i][1]<fades[i][2]){//if val < max
    DmxSimple.write(i, fades[i][1]);
    /* Serial.print(i);
    Serial.print(" fade up ");
    Serial.print(period);
    Serial.print(" x ");
    Serial.println(fades[i][1]);
    */ }else{
    fades[i][0] = 0;//disable fade
    DmxSimple.write(i, 0);
    }
    }else if(fades[i][0] == 2){//fade down
    fades[i][2] = fades[i][2] - step;//decrease fade
    if(fades[i][2]>fades[i][1]){//if val > min
    DmxSimple.write(i, fades[i][2]);
    /* Serial.print(i);
    Serial.print(" fade dn ");
    Serial.print(period);
    Serial.print(" x ");
    Serial.println(fades[i][2]);
    */ }else{
    fades[i][0] = 0;//disable fade
    DmxSimple.write(i, 0);
    }
    }else{
    // DmxSimple.write(i, 0);
    }
    }
    step=0;
    }
    if (step) {
    for (i = 0; i < maxChannel; i++) {
    if (fades[i][0] == 1) {//fade up
    fades[i][1] = fades[i][1] + step; //increase fade
    if (fades[i][1] < fades[i][2]) {//if val < max
    DmxSimple.write(i, fades[i][1]);
    /* Serial.print(i);
    Serial.print(" fade up ");
    Serial.print(period);
    Serial.print(" x ");
    Serial.println(fades[i][1]);
    */ } else {
    fades[i][0] = 0; //disable fade
    DmxSimple.write(i, 0);
    }
    } else if (fades[i][0] == 2) {//fade down
    fades[i][2] = fades[i][2] - step; //decrease fade
    if (fades[i][2] > fades[i][1]) {//if val > min
    DmxSimple.write(i, fades[i][2]);
    /* Serial.print(i);
    Serial.print(" fade dn ");
    Serial.print(period);
    Serial.print(" x ");
    Serial.println(fades[i][2]);
    */ } else {
    fades[i][0] = 0; //disable fade
    DmxSimple.write(i, 0);
    }
    } else {
    // DmxSimple.write(i, 0);
    }
    }
    step = 0;
    }
    }

    char * float2s(double f, unsigned int digits) {
    @@ -797,31 +815,32 @@ char * float2s(double f, unsigned int digits) {

    return s;
    }

    void setup() {
    DmxSimple.usePin(7);
    DmxSimple.maxChannel(8);
    MIDI.begin(MIDI_CHANNEL_OMNI);
    pinMode(redled, OUTPUT);
    pinMode(greenled, OUTPUT);
    pinMode(blueled, OUTPUT);
    pinMode(whiteredled, OUTPUT);
    pinMode(whitegreenled, OUTPUT);
    pinMode(whiteblueled, OUTPUT);
    pinMode(ledground1, OUTPUT);
    pinMode(ledground2, OUTPUT);
    pinMode(ledground3, OUTPUT);
    pinMode(ledground4, OUTPUT);
    pinMode(switchground1, INPUT_PULLUP);
    pinMode(switchground2, INPUT_PULLUP);
    pinMode(switchground3, INPUT_PULLUP);
    pinMode(switchground4, INPUT_PULLUP);
    pinMode(switch1, OUTPUT);
    pinMode(switch2, OUTPUT);
    pinMode(switch3, OUTPUT);
    pinMode(switch4, OUTPUT);

    MIDI.begin(MIDI_CHANNEL_OMNI);

    pinMode(redled, OUTPUT);
    pinMode(greenled, OUTPUT);
    pinMode(blueled, OUTPUT);
    pinMode(whiteredled, OUTPUT);
    pinMode(whitegreenled, OUTPUT);
    pinMode(whiteblueled, OUTPUT);
    pinMode(ledground1, OUTPUT);
    pinMode(ledground2, OUTPUT);
    pinMode(ledground3, OUTPUT);
    pinMode(ledground4, OUTPUT);
    pinMode(switchground1, INPUT_PULLUP);
    pinMode(switchground2, INPUT_PULLUP);
    pinMode(switchground3, INPUT_PULLUP);
    pinMode(switchground4, INPUT_PULLUP);
    pinMode(switch1, OUTPUT);
    pinMode(switch2, OUTPUT);
    pinMode(switch3, OUTPUT);
    pinMode(switch4, OUTPUT);


    Timer1.initialize(10000); //in microseconds (1000000us = 1s)
    Timer1.attachInterrupt(count); //runs every millisecond
    @@ -843,27 +862,27 @@ void setup() {
    #endif
    return;
    }
    myFile = SD.open("config.xml", FILE_READ);

    myFile = SD.open("config.xml", FILE_READ);
    if (!myFile) {
    // if the file didn't open, print an error:
    #ifdef DEBUG
    Serial.println("error opening config file");
    #endif
    }else{
    #ifdef DEBUG
    Serial.println("initialization done.");
    #endif
    readXML();
    if(numScenes>0)
    loadScene(fileNames[0]);
    else
    Serial.println("No scenes to load!");
    }
    attachInterrupt(switchground1, down1,FALLING);
    attachInterrupt(switchground2, down2,FALLING);
    attachInterrupt(switchground3, down3,FALLING);
    attachInterrupt(switchground4, down4,FALLING);
    } else {

    #ifdef DEBUG
    Serial.println("initialization done.");
    #endif
    readXML();
    if (numScenes > 0)
    loadScene(fileNames[0]);
    else
    Serial.println("No scenes to load!");
    }
    attachInterrupt(switchground1, down1, FALLING);
    attachInterrupt(switchground2, down2, FALLING);
    attachInterrupt(switchground3, down3, FALLING);
    attachInterrupt(switchground4, down4, FALLING);

    }
  2. yrrah revised this gist Apr 25, 2013. 1 changed file with 323 additions and 192 deletions.
    515 changes: 323 additions & 192 deletions gistfile1.c
    Original file line number Diff line number Diff line change
    @@ -3,9 +3,12 @@
    #include <TimerOne.h>
    #include <DmxSimple.h>
    #include <TinyXML.h>
    #include <string.h>


    #define DEBUG 1
    #define MIDI_BAUDRATE 31250
    #define COMPILE_MIDI_IN 1 // Set this setting to 1 to use the MIDI input.
    #define COMPILE_MIDI_OUT 0 // Set this setting to 1 to use the MIDI output.
    #define COMPILE_MIDI_THRU 0 // Set this setting to 1 to use the MIDI Soft Thru feature
    #define USE_SERIAL_PORT Serial
    #define USE_RUNNING_STATUS 0
    #define USE_1BYTE_PARSING 1
    @@ -37,8 +40,8 @@
    #define greenled 11 //hole 18
    #define redled 12 // this goes to hole 19 on the ribbon cable

    #define whitegreenled 13 //hole 15
    #define whiteblueled 14
    #define whitegreenled 14 //hole 15
    #define whiteblueled 13
    #define whiteredled 15 //hole 16

    #define switchground1 18 //hole 1
    @@ -51,6 +54,9 @@
    #define switch3 39 //hole 9
    #define switch4 40 //hole 10

    #define SW_DELAY 60 //milliseconds
    #define CB_COUNT 50
    #define INIT_WAIT 200

    File myFile;
    volatile int milliSec = 0;
    @@ -64,128 +70,91 @@ int maxChannel = 20;
    double global_note, global_velocity;
    volatile int period = 0;
    int step = 1;
    int counte = 0;
    boolean XMLdone = 0;
    int numScenes = 0;
    char** fileNames;
    int selectedScene = 0;

    int switches[4]={switch1,switch2,switch3,switch4};
    int switchgrounds[4]={switchground1,switchground2,switchground3,switchground4};
    int row;
    int collumn;
    int i=1;
    int j=1;
    int buttonpress;

    void buttonled(int row,int collumn){
    switch (row){
    case 0:
    digitalWrite(ledground1,LOW);
    break;
    boolean S1_EN = 0;
    boolean S2_EN = 0;
    boolean S3_EN = 0;
    boolean S4_EN = 0;

    case 1:
    digitalWrite(ledground2,LOW);
    break;

    case 2:
    digitalWrite(ledground3,LOW);
    break;
    boolean S1_P = 0;
    boolean S2_P = 0;
    boolean S3_P = 0;
    boolean S4_P = 0;

    case 3:
    digitalWrite(ledground4,LOW);
    break;
    }

    switch(collumn){
    case 0:
    digitalWrite(redled,HIGH);
    break;
    int S1_count = INIT_WAIT;
    int S2_count = INIT_WAIT;
    int S3_count = INIT_WAIT;
    int S4_count = INIT_WAIT;

    case 1:
    digitalWrite(greenled,HIGH);
    break;

    case 2:
    digitalWrite(blueled,HIGH);
    break;

    case 3:
    digitalWrite(whiteredled,HIGH);
    digitalWrite(whitegreenled,HIGH);
    digitalWrite(whiteblueled,HIGH);
    break;

    }
    delay (50);
    blackout();
    }
    int S1_n = 0;
    int S2_n = 0;
    int S3_n = 0;
    int S4_n = 0;

    void ledtest(){
    int clockType = -1;
    int clockChan = -1;
    int clockNote = -1;
    int clockVelocity = -1;

    for (int i=0; i<4; i++){
    for (int j=0; j<4; j++){
    buttonled(i,j);
    delay (50);
    blackout();
    delay(50);
    }
    }
    }

    void lightbutton(){

    for (int i=0; i<4; i++){
    for (int j=0; j<4; j++){
    digitalWrite(switchgrounds[i],LOW);
    if (digitalRead(switches[j])==LOW){
    buttonpress=4*i+j;
    buttonled(i,j);
    Serial.println(buttonpress);
    }
    digitalWrite(switchgrounds[i],HIGH);
    }
    }}
    int curRow=0;
    int curCol=0;

    void blackout(){
    digitalWrite(ledground1, HIGH);
    digitalWrite(ledground2, HIGH);
    digitalWrite(ledground3, HIGH);
    digitalWrite(ledground4, HIGH);
    digitalWrite(redled, LOW);
    digitalWrite(greenled, LOW);
    digitalWrite(blueled, LOW);
    digitalWrite(whiteredled, LOW);
    digitalWrite(whitegreenled, LOW);
    digitalWrite(whiteblueled, LOW);
    }
    int files = 0;
    int CB = INIT_WAIT;

    void XML_callback( uint8_t statusflags, char* tagName, uint16_t tagNameLen, char* data, uint16_t dataLen )
    {
    {
    char ns[] = "num-scenes";
    char fn[] = "filename";
    int i = 0;
    char ct[] = "clockType";
    char cc[] = "clockChan";
    char cn[] = "clockNote";
    char cv[] = "clockVelocity";
    if (statusflags & STATUS_ATTR_TEXT)
    {
    /* Serial.print("Attribute:");
    Serial.print(tagName);
    Serial.print(" text:");
    Serial.println(data);*/

    {
    if(!strcmp(ns, tagName)){
    numScenes = asciiHexToInt(data, 1);
    numScenes = asciiHexToInt(data, 2);

    Serial.print("numScenes: ");
    Serial.println(numScenes);

    fileNames = (char**) malloc(numScenes * sizeof (char*));
    }
    if(!strcmp(fn, tagName)){
    Serial.print("Filename: ");
    fileNames[i] = (char*) malloc((strlen(data)+1)*sizeof(char));
    strcpy(fileNames[i],data);
    Serial.println(data);
    if(numScenes == ++i){
    fileNames[files] = (char*) malloc((strlen(data)+1)*sizeof(char));
    strcpy(fileNames[files],data);
    Serial.println(fileNames[files]);
    if(numScenes == ++files){
    XMLdone = true;
    }
    }
    }
    if(!strcmp(ct, tagName)){
    Serial.print("Clock MIDI Message Type: ");
    clockType = asciiHexToInt(data, 2);
    Serial.println(clockType);
    }
    if(!strcmp(cc, tagName)){
    Serial.print("Clock MIDI Channel: ");
    clockChan = asciiHexToInt(data, 2);
    Serial.println(clockChan);
    }
    if(!strcmp(cn, tagName)){
    Serial.print("Clock MIDI Note: ");
    clockNote = asciiHexToInt(data, 2);
    Serial.println(clockNote);
    }
    if(!strcmp(cv, tagName)){
    Serial.print("Clock MIDI Velocity: ");
    clockVelocity = asciiHexToInt(data, 2);
    Serial.println(clockVelocity);
    }

    }
    }

    @@ -204,7 +173,7 @@ uint16_t buflen = 100;


    }


    }

    @@ -213,13 +182,6 @@ uint16_t buflen = 100;










    void loadFrame(int FrameID) {
    int i;
    int chan, val, upVal;
    @@ -363,7 +325,8 @@ void loadScene(char* fileName) {
    Serial.println(fileName);
    #endif
    }else{

    Serial.print("Opening Scene: ");
    Serial.println(fileName);
    //free the memory for the old case array if it exists
    if (fgcount != 0) {
    for (i = 0; i < fgcount; i++)
    @@ -388,11 +351,11 @@ void loadScene(char* fileName) {
    }

    #ifdef DEBUG
    Serial.print("fgcount: ");
    Serial.print("fgcount ");
    Serial.println(fgcount);
    Serial.print("looplength: ");
    Serial.print("looplength ");
    Serial.println(looplength);
    Serial.print("maxChannel: ");
    Serial.print("maxChannel ");
    Serial.println(maxChannel);
    #endif

    @@ -485,47 +448,25 @@ void count() {
    // Serial.println(milliSec);
    step = 255/period;
    if(step==0)step = 1;
    }


    char * float2s(double f, unsigned int digits) {
    int index = 0;
    static char s[16]; // buffer to build string representation
    // handle sign
    if (f < 0.0) {
    s[index++] = '-';
    f = -f;
    }
    // handle infinite values
    if (isinf(f)) {
    strcpy(&s[index], "INF");
    return s;
    }
    // handle Not a Number
    if (isnan(f)) {
    strcpy(&s[index], "NaN");
    return s;
    }

    // max digits
    if (digits > 9) digits = 9;
    long multiplier = pow(10, digits); // fix int => long

    int exponent = int(log10(f));
    double g = f / pow(10, exponent);
    if ((g < 1.0) && (g != 0.0)) {
    g *= 10;
    exponent--;
    }
    if(S1_count--==0){
    S1_EN = 1;
    }
    if(S2_count--==0){
    S2_EN = 1;
    }
    if(S3_count--==0){
    S3_EN = 1;
    }
    if(S4_count--==0){
    S4_EN = 1;
    }
    if(CB--==0){
    buttonled(curRow,curCol);
    }
    }

    long whole = long(g); // single digit
    long part = long((g - whole) * multiplier); // # digits
    char format[16];
    sprintf(format, "%%ld.%%0%dld E%%+d", digits);
    sprintf(&s[index], format, whole, part, exponent);

    return s;
    }

    int asciiHexToInt(char* a, int length) {
    //converts acii representation of hex eg 'ff' to 0xFF
    @@ -559,14 +500,18 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    int i;

    //MIDI Clock Signal
    if (midiType == 1 && midiChan == 1 && note == 12/*C1*/ && velocity == 10) {
    if ( ((midiType==clockType)||(clockType==-1)) && ((midiChan==clockChan)||(clockChan==-1))
    && ((note==clockNote)||(clockNote==-1)) && ((velocity==clockVelocity)||(clockVelocity==-1))){

    #ifdef DEBUG
    Serial.print("Clock... Period: ");

    Serial.print("Clock... Period: ");
    Serial.println(period);
    #endif
    period = milliSec;

    period = milliSec;
    milliSec = 0;
    }

    #ifdef DEBUG
    @@ -608,13 +553,170 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    return 0;
    }

    void blackout(){
    digitalWrite(ledground1, HIGH);
    digitalWrite(ledground2, HIGH);
    digitalWrite(ledground3, HIGH);
    digitalWrite(ledground4, HIGH);
    digitalWrite(redled, LOW);
    digitalWrite(greenled, LOW);
    digitalWrite(blueled, LOW);
    digitalWrite(whiteredled, LOW);
    digitalWrite(whitegreenled, LOW);
    digitalWrite(whiteblueled, LOW);
    }

    void down1()
    {
    if(S1_EN){
    S1_EN = 0; S1_P=1;
    S1_count = SW_DELAY;
    }
    }
    void down2()
    {
    if(S2_EN){
    S2_EN = 0; S2_P=1;
    S2_count = SW_DELAY;
    }
    }

    void down3()
    {
    if(S3_EN){
    S3_EN = 0; S3_P=1;
    S3_count = SW_DELAY;
    }
    }

    void down4()
    {
    if(S4_EN){
    S4_EN = 0; S4_P=1;
    S4_count = 50;
    }
    }

    void buttonled(int row,int collumn){

    blackout();
    switch (row){
    case 0:
    digitalWrite(ledground1,LOW);
    break;

    case 1:
    digitalWrite(ledground2,LOW);
    break;

    case 2:
    digitalWrite(ledground3,LOW);
    break;

    case 3:
    digitalWrite(ledground4,LOW);
    break;
    }
    switch(collumn){

    case -1:
    digitalWrite(whiteredled,HIGH);
    break;

    case 0:
    digitalWrite(whiteredled,HIGH);
    digitalWrite(whitegreenled,HIGH);
    digitalWrite(whiteblueled,HIGH);
    break;

    case 1:
    digitalWrite(blueled,HIGH);
    digitalWrite(whiteblueled,HIGH);

    break;

    case 2:
    digitalWrite(greenled,HIGH);
    digitalWrite(whitegreenled,HIGH);
    break;

    case 3:
    digitalWrite(redled,HIGH);
    digitalWrite(whiteredled,HIGH);

    break;

    }
    }

    void loop() {
    boolean dmx = 0;
    int i;
    int newScene = 0;
    boolean pressed = 0;

    // lightbutton();
    //faderpots();
    //ledtest();
    if(S1_P){
    S1_P = 0;
    pressed = 1;
    if(++S1_n>3||S1_n>=numScenes){S1_n = 0;}
    newScene = S1_n;
    Serial.println(newScene);
    if(newScene<numScenes){

    selectedScene = newScene;
    buttonled(0,S1_n);
    curRow=0;curCol=S1_n;
    }else{S1_n=0; buttonled(0,-1);CB = CB_COUNT;}

    }else if(S2_P){
    S2_P = 0;
    if(++S2_n>3||4+S2_n>=numScenes){S2_n = 0;}
    newScene = 4+S2_n;
    if(newScene<numScenes){
    pressed = 1;
    selectedScene = newScene;
    buttonled(1,S2_n);
    curRow=1;curCol=S2_n;
    }else{S2_n=0; buttonled(1,-1);CB = CB_COUNT;}


    }else if(S3_P){
    S3_P = 0;
    if(++S3_n>3||8+S3_n>=numScenes){S3_n = 0;}
    newScene = 8+S3_n;
    if(newScene<numScenes){
    pressed = 1;
    selectedScene = newScene;
    buttonled(2,S3_n);
    curRow=2;curCol=S3_n;
    }else{S3_n=0; buttonled(2,-1);CB = CB_COUNT;}

    }else if(S4_P){
    S4_P = 0;
    if(++S4_n>3||12+S4_n>=numScenes){S4_n = 0;}
    newScene = 12+S4_n;
    if(newScene<numScenes){
    pressed = 1;
    selectedScene = newScene;
    buttonled(3,S4_n);
    curRow=3;curCol=S4_n;
    }else{S4_n=0; buttonled(3,-1);CB = CB_COUNT;
    }

    }else{
    pressed = 0;
    }
    if(pressed){
    Serial.print("New scene selected: [");
    Serial.print(selectedScene);
    Serial.print("]");
    Serial.println(fileNames[selectedScene]);
    loadScene(fileNames[selectedScene]);
    }





    if (usbMIDI.read())
    dmx = handleMIDI(usbMIDI.getType(), usbMIDI.getChannel(), usbMIDI.getData1(), usbMIDI.getData2());
    @@ -627,25 +729,25 @@ void loop() {
    fades[i][1] = fades[i][1] + step;//increase fade
    if(fades[i][1]<fades[i][2]){//if val < max
    DmxSimple.write(i, fades[i][1]);
    Serial.print(i);
    /* Serial.print(i);
    Serial.print(" fade up ");
    Serial.print(period);
    Serial.print(" x ");
    Serial.println(fades[i][1]);
    }else{
    */ }else{
    fades[i][0] = 0;//disable fade
    DmxSimple.write(i, 0);
    }
    }else if(fades[i][0] == 2){//fade down
    fades[i][2] = fades[i][2] - step;//decrease fade
    if(fades[i][2]>fades[i][1]){//if val > min
    DmxSimple.write(i, fades[i][2]);
    Serial.print(i);
    /* Serial.print(i);
    Serial.print(" fade dn ");
    Serial.print(period);
    Serial.print(" x ");
    Serial.println(fades[i][2]);
    }else{
    */ }else{
    fades[i][0] = 0;//disable fade
    DmxSimple.write(i, 0);
    }
    @@ -657,15 +759,51 @@ void loop() {
    }
    }

    char * float2s(double f, unsigned int digits) {
    int index = 0;
    static char s[16]; // buffer to build string representation
    // handle sign
    if (f < 0.0) {
    s[index++] = '-';
    f = -f;
    }
    // handle infinite values
    if (isinf(f)) {
    strcpy(&s[index], "INF");
    return s;
    }
    // handle Not a Number
    if (isnan(f)) {
    strcpy(&s[index], "NaN");
    return s;
    }

    void my_int1() { Serial.println("interrupt #1"); }
    void my_int2() { Serial.println("interrupt #2"); }
    void my_int3() { Serial.println("interrupt #3"); }
    void my_int4() { Serial.println("interrupt #4"); }
    // max digits
    if (digits > 9) digits = 9;
    long multiplier = pow(10, digits); // fix int => long

    int exponent = int(log10(f));
    double g = f / pow(10, exponent);
    if ((g < 1.0) && (g != 0.0)) {
    g *= 10;
    exponent--;
    }

    long whole = long(g); // single digit
    long part = long((g - whole) * multiplier); // # digits
    char format[16];
    sprintf(format, "%%ld.%%0%dld E%%+d", digits);
    sprintf(&s[index], format, whole, part, exponent);

    return s;
    }
    void setup() {

    /* pinMode(redled, OUTPUT);
    DmxSimple.usePin(7);
    DmxSimple.maxChannel(8);

    MIDI.begin(MIDI_CHANNEL_OMNI);

    pinMode(redled, OUTPUT);
    pinMode(greenled, OUTPUT);
    pinMode(blueled, OUTPUT);
    pinMode(whiteredled, OUTPUT);
    @@ -674,29 +812,16 @@ void setup() {
    pinMode(ledground1, OUTPUT);
    pinMode(ledground2, OUTPUT);
    pinMode(ledground3, OUTPUT);
    pinMode(ledground4, OUTPUT);*/
    pinMode(switchground1, INPUT);
    pinMode(switchground2, INPUT);
    pinMode(switchground3, INPUT);
    pinMode(switchground4, INPUT);
    // pinMode(switch1, OUTPUT);
    // pinMode(switch2, OUTPUT);
    // pinMode(switch3, OUTPUT);
    // pinMode(switch4, OUTPUT);
    // digitalWrite(switch1,HIGH);
    // digitalWrite(switch2,HIGH);
    // digitalWrite(switch3,HIGH);
    // digitalWrite(switch4,HIGH);

    attachInterrupt(7, my_int1, RISING);
    attachInterrupt(6, my_int2, RISING);
    attachInterrupt(1, my_int3, RISING);
    attachInterrupt(0, my_int4, RISING);
    pinMode(ledground4, OUTPUT);
    pinMode(switchground1, INPUT_PULLUP);
    pinMode(switchground2, INPUT_PULLUP);
    pinMode(switchground3, INPUT_PULLUP);
    pinMode(switchground4, INPUT_PULLUP);
    pinMode(switch1, OUTPUT);
    pinMode(switch2, OUTPUT);
    pinMode(switch3, OUTPUT);
    pinMode(switch4, OUTPUT);

    DmxSimple.usePin(7);
    DmxSimple.maxChannel(8);
    //pinMode(3, OUTPUT);
    MIDI.begin(MIDI_CHANNEL_OMNI);

    Timer1.initialize(10000); //in microseconds (1000000us = 1s)
    Timer1.attachInterrupt(count); //runs every millisecond
    @@ -726,13 +851,19 @@ void setup() {
    Serial.println("error opening config file");
    #endif
    }else{

    #ifdef DEBUG
    Serial.println("initialization done.");
    #endif
    readXML();
    readXML();
    if(numScenes>0)
    loadScene(fileNames[0]);
    else
    Serial.println("No scenes to load!");
    }
    }
    attachInterrupt(switchground1, down1,FALLING);
    attachInterrupt(switchground2, down2,FALLING);
    attachInterrupt(switchground3, down3,FALLING);
    attachInterrupt(switchground4, down4,FALLING);

    }
  3. yrrah revised this gist Apr 24, 2013. 1 changed file with 303 additions and 83 deletions.
    386 changes: 303 additions & 83 deletions gistfile1.c
    Original file line number Diff line number Diff line change
    @@ -2,12 +2,10 @@
    #include <MIDI.h>
    #include <TimerOne.h>
    #include <DmxSimple.h>

    #include <TinyXML.h>
    #include <string.h>

    #define DEBUG 1
    #define MIDI_BAUDRATE 31250
    #define COMPILE_MIDI_IN 1 // Set this setting to 1 to use the MIDI input.
    #define COMPILE_MIDI_OUT 0 // Set this setting to 1 to use the MIDI output.
    #define COMPILE_MIDI_THRU 0 // Set this setting to 1 to use the MIDI Soft Thru feature
    #define USE_SERIAL_PORT Serial
    #define USE_RUNNING_STATUS 0
    #define USE_1BYTE_PARSING 1
    @@ -30,6 +28,30 @@
    #define POT4 44
    #define FADER 45

    #define ledground1 8 //hole 2
    #define ledground2 5 //hole 4
    #define ledground3 24 //hole 13
    #define ledground4 16 //hole 11

    #define blueled 10 //hole 17
    #define greenled 11 //hole 18
    #define redled 12 // this goes to hole 19 on the ribbon cable

    #define whitegreenled 13 //hole 15
    #define whiteblueled 14
    #define whiteredled 15 //hole 16

    #define switchground1 18 //hole 1
    #define switchground2 19 //hole 3
    #define switchground3 0 //hole 14
    #define switchground4 1 //hole 12

    #define switch1 26 //hole 7
    #define switch2 38 //hole 8
    #define switch3 39 //hole 9
    #define switch4 40 //hole 10


    File myFile;
    volatile int milliSec = 0;
    char* temp = "";
    @@ -42,6 +64,162 @@ int maxChannel = 20;
    double global_note, global_velocity;
    volatile int period = 0;
    int step = 1;
    boolean XMLdone = 0;
    int numScenes = 0;
    char** fileNames;

    int switches[4]={switch1,switch2,switch3,switch4};
    int switchgrounds[4]={switchground1,switchground2,switchground3,switchground4};
    int row;
    int collumn;
    int i=1;
    int j=1;
    int buttonpress;

    void buttonled(int row,int collumn){
    switch (row){
    case 0:
    digitalWrite(ledground1,LOW);
    break;

    case 1:
    digitalWrite(ledground2,LOW);
    break;

    case 2:
    digitalWrite(ledground3,LOW);
    break;

    case 3:
    digitalWrite(ledground4,LOW);
    break;
    }

    switch(collumn){
    case 0:
    digitalWrite(redled,HIGH);
    break;

    case 1:
    digitalWrite(greenled,HIGH);
    break;

    case 2:
    digitalWrite(blueled,HIGH);
    break;

    case 3:
    digitalWrite(whiteredled,HIGH);
    digitalWrite(whitegreenled,HIGH);
    digitalWrite(whiteblueled,HIGH);
    break;

    }
    delay (50);
    blackout();
    }

    void ledtest(){

    for (int i=0; i<4; i++){
    for (int j=0; j<4; j++){
    buttonled(i,j);
    delay (50);
    blackout();
    delay(50);
    }
    }
    }

    void lightbutton(){

    for (int i=0; i<4; i++){
    for (int j=0; j<4; j++){
    digitalWrite(switchgrounds[i],LOW);
    if (digitalRead(switches[j])==LOW){
    buttonpress=4*i+j;
    buttonled(i,j);
    Serial.println(buttonpress);
    }
    digitalWrite(switchgrounds[i],HIGH);
    }
    }}

    void blackout(){
    digitalWrite(ledground1, HIGH);
    digitalWrite(ledground2, HIGH);
    digitalWrite(ledground3, HIGH);
    digitalWrite(ledground4, HIGH);
    digitalWrite(redled, LOW);
    digitalWrite(greenled, LOW);
    digitalWrite(blueled, LOW);
    digitalWrite(whiteredled, LOW);
    digitalWrite(whitegreenled, LOW);
    digitalWrite(whiteblueled, LOW);
    }

    void XML_callback( uint8_t statusflags, char* tagName, uint16_t tagNameLen, char* data, uint16_t dataLen )
    {
    char ns[] = "num-scenes";
    char fn[] = "filename";
    int i = 0;
    if (statusflags & STATUS_ATTR_TEXT)
    {
    /* Serial.print("Attribute:");
    Serial.print(tagName);
    Serial.print(" text:");
    Serial.println(data);*/

    if(!strcmp(ns, tagName)){
    numScenes = asciiHexToInt(data, 1);
    Serial.print("numScenes: ");
    Serial.println(numScenes);

    fileNames = (char**) malloc(numScenes * sizeof (char*));
    }
    if(!strcmp(fn, tagName)){
    Serial.print("Filename: ");
    fileNames[i] = (char*) malloc((strlen(data)+1)*sizeof(char));
    strcpy(fileNames[i],data);
    Serial.println(data);
    if(numScenes == ++i){
    XMLdone = true;
    }
    }
    }
    }


    static void readXML(){
    TinyXML xml;
    uint8_t buffer[100];
    uint16_t buflen = 100;

    xml.init((uint8_t*)&buffer,buflen,&XML_callback);

    while(myFile.available()&&!XMLdone){

    char c = myFile.read();
    xml.processChar(c);


    }


    }













    void loadFrame(int FrameID) {
    int i;
    int chan, val, upVal;
    @@ -210,11 +388,11 @@ void loadScene(char* fileName) {
    }

    #ifdef DEBUG
    Serial.print("fgcount ");
    Serial.print("fgcount: ");
    Serial.println(fgcount);
    Serial.print("looplength ");
    Serial.print("looplength: ");
    Serial.println(looplength);
    Serial.print("maxChannel ");
    Serial.print("maxChannel: ");
    Serial.println(maxChannel);
    #endif

    @@ -309,47 +487,44 @@ void count() {
    if(step==0)step = 1;
    }

    void setup() {
    DmxSimple.usePin(7);
    DmxSimple.maxChannel(8);
    //pinMode(3, OUTPUT);
    //MIDI.begin(MIDI_CHANNEL_OMNI);

    Timer1.initialize(10000); //in microseconds (1000000us = 1s)
    Timer1.attachInterrupt(count); //runs every millisecond
    Timer1.start();

    #ifdef DEBUG
    char * float2s(double f, unsigned int digits) {
    int index = 0;
    static char s[16]; // buffer to build string representation
    // handle sign
    if (f < 0.0) {
    s[index++] = '-';
    f = -f;
    }
    // handle infinite values
    if (isinf(f)) {
    strcpy(&s[index], "INF");
    return s;
    }
    // handle Not a Number
    if (isnan(f)) {
    strcpy(&s[index], "NaN");
    return s;
    }

    Serial.print("Initializing SD card...");
    #endif
    // On the Ethernet Shield, CS is pin 4. It's set as an output by default.*/
    // Note that even if it's not used as the CS pin, the hardware SS pin
    // (10 on most Arduino boards, 53 on the Mega) must be left as an output
    // or the SD library functions will not work.
    pinMode(20, OUTPUT);
    // max digits
    if (digits > 9) digits = 9;
    long multiplier = pow(10, digits); // fix int => long

    if (!SD.begin(20)) {
    #ifdef DEBUG
    Serial.println("initialization failed!");
    #endif
    return;
    int exponent = int(log10(f));
    double g = f / pow(10, exponent);
    if ((g < 1.0) && (g != 0.0)) {
    g *= 10;
    exponent--;
    }

    myFile = SD.open("config.xml", FILE_READ);
    if (!myFile) {
    // if the file didn't open, print an error:
    #ifdef DEBUG
    Serial.println("error opening config file");
    #endif
    }else{

    #ifdef DEBUG
    Serial.println("initialization done.");
    #endif

    loadScene("TestTwo.scn");
    }

    long whole = long(g); // single digit
    long part = long((g - whole) * multiplier); // # digits
    char format[16];
    sprintf(format, "%%ld.%%0%dld E%%+d", digits);
    sprintf(&s[index], format, whole, part, exponent);

    return s;
    }

    int asciiHexToInt(char* a, int length) {
    @@ -384,7 +559,7 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    int i;

    //MIDI Clock Signal
    if (midiType == NoteOn && midiChan == 1 && note == 12/*C1*/ && velocity == 10) {
    if (midiType == 1 && midiChan == 1 && note == 12/*C1*/ && velocity == 10) {
    #ifdef DEBUG
    Serial.print("Clock... Period: ");
    Serial.println(period);
    @@ -436,6 +611,10 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    void loop() {
    boolean dmx = 0;
    int i;

    // lightbutton();
    //faderpots();
    //ledtest();

    if (usbMIDI.read())
    dmx = handleMIDI(usbMIDI.getType(), usbMIDI.getChannel(), usbMIDI.getData1(), usbMIDI.getData2());
    @@ -448,25 +627,25 @@ void loop() {
    fades[i][1] = fades[i][1] + step;//increase fade
    if(fades[i][1]<fades[i][2]){//if val < max
    DmxSimple.write(i, fades[i][1]);
    /* Serial.print(i);
    Serial.print(i);
    Serial.print(" fade up ");
    Serial.print(period);
    Serial.print(" x ");
    Serial.println(fades[i][1]);
    */ }else{
    }else{
    fades[i][0] = 0;//disable fade
    DmxSimple.write(i, 0);
    }
    }else if(fades[i][0] == 2){//fade down
    fades[i][2] = fades[i][2] - step;//decrease fade
    if(fades[i][2]>fades[i][1]){//if val > min
    DmxSimple.write(i, fades[i][2]);
    /* Serial.print(i);
    Serial.print(i);
    Serial.print(" fade dn ");
    Serial.print(period);
    Serial.print(" x ");
    Serial.println(fades[i][2]);
    */ }else{
    }else{
    fades[i][0] = 0;//disable fade
    DmxSimple.write(i, 0);
    }
    @@ -478,41 +657,82 @@ void loop() {
    }
    }

    char * float2s(double f, unsigned int digits) {
    int index = 0;
    static char s[16]; // buffer to build string representation
    // handle sign
    if (f < 0.0) {
    s[index++] = '-';
    f = -f;
    }
    // handle infinite values
    if (isinf(f)) {
    strcpy(&s[index], "INF");
    return s;
    }
    // handle Not a Number
    if (isnan(f)) {
    strcpy(&s[index], "NaN");
    return s;
    }

    // max digits
    if (digits > 9) digits = 9;
    long multiplier = pow(10, digits); // fix int => long
    void my_int1() { Serial.println("interrupt #1"); }
    void my_int2() { Serial.println("interrupt #2"); }
    void my_int3() { Serial.println("interrupt #3"); }
    void my_int4() { Serial.println("interrupt #4"); }

    int exponent = int(log10(f));
    double g = f / pow(10, exponent);
    if ((g < 1.0) && (g != 0.0)) {
    g *= 10;
    exponent--;
    }
    void setup() {

    /* pinMode(redled, OUTPUT);
    pinMode(greenled, OUTPUT);
    pinMode(blueled, OUTPUT);
    pinMode(whiteredled, OUTPUT);
    pinMode(whitegreenled, OUTPUT);
    pinMode(whiteblueled, OUTPUT);
    pinMode(ledground1, OUTPUT);
    pinMode(ledground2, OUTPUT);
    pinMode(ledground3, OUTPUT);
    pinMode(ledground4, OUTPUT);*/
    pinMode(switchground1, INPUT);
    pinMode(switchground2, INPUT);
    pinMode(switchground3, INPUT);
    pinMode(switchground4, INPUT);
    // pinMode(switch1, OUTPUT);
    // pinMode(switch2, OUTPUT);
    // pinMode(switch3, OUTPUT);
    // pinMode(switch4, OUTPUT);
    // digitalWrite(switch1,HIGH);
    // digitalWrite(switch2,HIGH);
    // digitalWrite(switch3,HIGH);
    // digitalWrite(switch4,HIGH);

    attachInterrupt(7, my_int1, RISING);
    attachInterrupt(6, my_int2, RISING);
    attachInterrupt(1, my_int3, RISING);
    attachInterrupt(0, my_int4, RISING);

    DmxSimple.usePin(7);
    DmxSimple.maxChannel(8);
    //pinMode(3, OUTPUT);
    MIDI.begin(MIDI_CHANNEL_OMNI);

    long whole = long(g); // single digit
    long part = long((g - whole) * multiplier); // # digits
    char format[16];
    sprintf(format, "%%ld.%%0%dld E%%+d", digits);
    sprintf(&s[index], format, whole, part, exponent);
    Timer1.initialize(10000); //in microseconds (1000000us = 1s)
    Timer1.attachInterrupt(count); //runs every millisecond
    Timer1.start();

    return s;
    #ifdef DEBUG

    Serial.print("Initializing SD card...");
    #endif
    // On the Ethernet Shield, CS is pin 4. It's set as an output by default.*/
    // Note that even if it's not used as the CS pin, the hardware SS pin
    // (10 on most Arduino boards, 53 on the Mega) must be left as an output
    // or the SD library functions will not work.
    pinMode(20, OUTPUT);

    if (!SD.begin(20)) {
    #ifdef DEBUG
    Serial.println("initialization failed!");
    #endif
    return;
    }

    myFile = SD.open("config.xml", FILE_READ);
    if (!myFile) {
    // if the file didn't open, print an error:
    #ifdef DEBUG
    Serial.println("error opening config file");
    #endif
    }else{
    #ifdef DEBUG
    Serial.println("initialization done.");
    #endif
    readXML();
    if(numScenes>0)
    loadScene(fileNames[0]);
    else
    Serial.println("No scenes to load!");
    }
    }
  4. yrrah revised this gist Apr 22, 2013. 1 changed file with 95 additions and 30 deletions.
    125 changes: 95 additions & 30 deletions gistfile1.c
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,9 @@
    #include <SD.h>
    #include <MIDI.h>
    #include <TimerOne.h>
    #include <DmxSimple.h> //limited to 64 channels in DmxSimple.h to save memory
    #include <DmxSimple.h>

    //define DEBUG 1
    #define DEBUG 1
    #define MIDI_BAUDRATE 31250
    #define COMPILE_MIDI_IN 1 // Set this setting to 1 to use the MIDI input.
    #define COMPILE_MIDI_OUT 0 // Set this setting to 1 to use the MIDI output.
    @@ -34,12 +34,14 @@ File myFile;
    volatile int milliSec = 0;
    char* temp = "";
    int** caseArray;
    int caseCount;
    int** caseInfo;
    int fgcount = 0; //number of frame groups & corresponding cases
    int** fades;
    int fgcount; //number of frame groups & corresponding cases
    int maxChannel = 20;
    double global_note, global_velocity;
    int period = 0;

    volatile int period = 0;
    int step = 1;
    void loadFrame(int FrameID) {
    int i;
    int chan, val, upVal;
    @@ -49,15 +51,15 @@ void loadFrame(int FrameID) {
    Serial.print("Load Frame Group:");
    Serial.print(FrameID);
    Serial.print(" Frame:");
    Serial.println(caseArray[FrameID][CURRENT_F]);
    Serial.println(caseInfo[FrameID][CURRENT_F]);
    #endif

    //seek to location of frame group on SD card
    myFile.seek(caseArray[FrameID][FG_ADDR]);
    myFile.seek(caseInfo[FrameID][FG_ADDR]);

    //find location of frame
    i = 0;
    while (i <= caseArray[FrameID][CURRENT_F]) {
    while (i <= caseInfo[FrameID][CURRENT_F]) {
    while (myFile.read() != '%');
    i++;
    }
    @@ -119,31 +121,38 @@ void loadFrame(int FrameID) {
    case 'F':
    switch (in2) {
    case 'U'://FU = Fade Up
    fades[chan][0] = 1;
    DmxSimple.write(chan, val);
    break;
    case 'D'://FD = Fade Down
    fades[chan][0] = 2;
    DmxSimple.write(chan, upVal);
    break;
    }
    fades[chan][1] = val;
    fades[chan][2] = upVal;
    break;
    case 'M':
    Serial.print(val);
    /* Serial.print(val);
    Serial.print(" ");
    Serial.println(upVal);
    switch (in2) {
    */ switch (in2) {
    case '1'://M1 = MIDI Note
    out = (int) ((global_note / 127)*(upVal - val) + val);
    break;
    case '2'://M2 = MIDI Velocity
    out = (int) ((global_velocity / 127)*(upVal - val) + val);
    break;
    }
    Serial.println(float2s(out, 5));
    // Serial.println(float2s(out, 5));
    DmxSimple.write(chan, out);
    break;
    }
    break;
    default:
    #ifdef DEBUG
    Serial.println("DMX Instuction Type not implemented yet");
    Serial.print(caseArray[FrameID][CURRENT_F]);
    Serial.print(caseInfo[FrameID][CURRENT_F]);
    Serial.print(" ");
    Serial.print(FrameID);
    Serial.print(" ");
    @@ -156,8 +165,8 @@ void loadFrame(int FrameID) {
    }

    //increment frame counter
    if (++caseArray[FrameID][CURRENT_F] >= caseArray[FrameID][FG_LENGTH])
    caseArray[FrameID][CURRENT_F] = 0;
    if (++caseInfo[FrameID][CURRENT_F] >= caseInfo[FrameID][FG_LENGTH])
    caseInfo[FrameID][CURRENT_F] = 0;
    }

    void loadScene(char* fileName) {
    @@ -172,7 +181,8 @@ void loadScene(char* fileName) {
    if (!myFile) {
    // if the file didn't open, print an error:
    #ifdef DEBUG
    Serial.println("error opening scene");
    Serial.print("error opening scene: ");
    Serial.println(fileName);
    #endif
    }else{

    @@ -191,6 +201,13 @@ void loadScene(char* fileName) {

    myFile.readBytes(temp, 2);
    maxChannel = asciiHexToInt(temp, 2);

    fades = (int**) malloc(maxChannel * sizeof (int*));

    for (i = 0; i < maxChannel; i++) {
    fades[i] = (int*) malloc(3 * sizeof (int));
    fades[i][0] = 0;
    }

    #ifdef DEBUG
    Serial.print("fgcount ");
    @@ -214,16 +231,24 @@ void loadScene(char* fileName) {
    caseInfo[i][CURRENT_F] = 0;

    #ifdef DEBUG
    Serial.print("FG located at ");
    Serial.println(caseArray[i][5]);
    Serial.flush();
    Serial.print("------ Case Info ");
    Serial.print(i);
    Serial.println(" -------");
    Serial.print("FG Length: ");
    Serial.println(caseInfo[i][FG_LENGTH]);
    Serial.print("FG Address: ");
    Serial.println(caseInfo[i][FG_ADDR]);
    Serial.print("Current Frame: ");
    Serial.println(caseInfo[i][CURRENT_F]);
    #endif

    }

    while (myFile.read() != '$');

    myFile.readBytes(temp, 2);
    int caseCount = asciiHexToInt(temp, 2);
    caseCount = asciiHexToInt(temp, 2);
    int fg = 0;


    @@ -250,14 +275,16 @@ void loadScene(char* fileName) {
    myFile.readBytes(temp, 1);
    caseArray[i][MIDI_VAR] = asciiHexToInt(temp, 1);
    //MIDI message type (note on, note off, etc)
    myFile.readBytes(temp, 2);
    caseArray[i][MSG_TYPE] = asciiHexToInt(temp, 2);
    myFile.readBytes(temp, 1);
    caseArray[i][MSG_TYPE] = asciiHexToInt(temp, 1);

    #ifdef DEBUG
    Serial.flush();
    Serial.print("------ Case Array Index ");
    Serial.print(i);
    Serial.println(" -------");
    Serial.print("Frame Group ");
    Serial.println(caseArray[i][FRAME_GROUP]);
    Serial.print("MIDI Listen Channel ");
    Serial.println(caseArray[i][LISTEN_CHAN]);
    Serial.print("MIDI low case value ");
    @@ -277,6 +304,9 @@ void loadScene(char* fileName) {

    void count() {
    milliSec++;
    // Serial.println(milliSec);
    step = 255/period;
    if(step==0)step = 1;
    }

    void setup() {
    @@ -318,7 +348,7 @@ void setup() {
    Serial.println("initialization done.");
    #endif

    loadScene("qq.scn");
    loadScene("TestTwo.scn");
    }
    }

    @@ -354,12 +384,17 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    int i;

    //MIDI Clock Signal
    if (midiType == NoteOn && midiChan == 1 && note == 12/*C1*/ && velocity == 14) {
    if (midiType == NoteOn && midiChan == 1 && note == 12/*C1*/ && velocity == 10) {
    #ifdef DEBUG
    Serial.print("Clock... Period: ");
    Serial.println(period);
    #endif
    period = milliSec;
    milliSec = 0;

    }

    //#ifdef DEBUG
    #ifdef DEBUG
    Serial.print("Type: ");
    Serial.print(midiType);
    Serial.print(" Chan: ");
    @@ -368,9 +403,9 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    Serial.print(note);
    Serial.print(" velocity: ");
    Serial.println(velocity);
    //#endif
    #endif
    //loop through all cases
    for (int i = 0; i < fgcount; i++) {
    for (int i = 0; i < caseCount; i++) {

    //check to see if correct message type (Note on, Note off, etc)
    if (caseArray[i][MSG_TYPE] == midiType
    @@ -390,7 +425,7 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    //do comparison and load frame if true
    if (midiValue >= caseArray[i][CASE_VAL_L]
    && midiValue <= caseArray[i][CASE_VAL_H]) {
    loadFrame(i);
    loadFrame(caseArray[i][FRAME_GROUP]);
    return 1;
    }
    }
    @@ -406,11 +441,41 @@ void loop() {
    dmx = handleMIDI(usbMIDI.getType(), usbMIDI.getChannel(), usbMIDI.getData1(), usbMIDI.getData2());
    else if (MIDI.read())
    handleMIDI(MIDI.getType(), MIDI.getChannel(), MIDI.getData1(), MIDI.getData2());
    else return;

    if (!dmx)
    for (i = 0; i < maxChannel; i++)
    DmxSimple.write(i, 0);
    if (step){
    for (i = 0; i < maxChannel; i++) {
    if(fades[i][0] == 1){//fade up
    fades[i][1] = fades[i][1] + step;//increase fade
    if(fades[i][1]<fades[i][2]){//if val < max
    DmxSimple.write(i, fades[i][1]);
    /* Serial.print(i);
    Serial.print(" fade up ");
    Serial.print(period);
    Serial.print(" x ");
    Serial.println(fades[i][1]);
    */ }else{
    fades[i][0] = 0;//disable fade
    DmxSimple.write(i, 0);
    }
    }else if(fades[i][0] == 2){//fade down
    fades[i][2] = fades[i][2] - step;//decrease fade
    if(fades[i][2]>fades[i][1]){//if val > min
    DmxSimple.write(i, fades[i][2]);
    /* Serial.print(i);
    Serial.print(" fade dn ");
    Serial.print(period);
    Serial.print(" x ");
    Serial.println(fades[i][2]);
    */ }else{
    fades[i][0] = 0;//disable fade
    DmxSimple.write(i, 0);
    }
    }else{
    // DmxSimple.write(i, 0);
    }
    }
    step=0;
    }
    }

    char * float2s(double f, unsigned int digits) {
  5. yrrah revised this gist Apr 21, 2013. 1 changed file with 389 additions and 376 deletions.
    765 changes: 389 additions & 376 deletions gistfile1.c
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,8 @@
    #include <SD.h>
    //#include <MIDI.h>
    #include <MIDI.h>
    #include <TimerOne.h>
    #include <DmxSimple.h> //limited to 64 channels in DmxSimple.h to save memory

    //define DEBUG 1
    #define MIDI_BAUDRATE 31250
    #define COMPILE_MIDI_IN 1 // Set this setting to 1 to use the MIDI input.
    @@ -12,14 +13,15 @@
    #define USE_1BYTE_PARSING 1
    #define USE_CALLBACKS 0
    #define MIDI_SYSEX_ARRAY_SIZE 64
    #define LISTEN_CHAN 0
    #define CASE_VAL_L 1
    #define CASE_VAL_H 2
    #define MIDI_VAR 3
    #define MSG_TYPE 4
    #define FG_ADDR 5
    #define FG_LENGTH 6
    #define CURRENT_F 7
    #define FRAME_GROUP 0
    #define LISTEN_CHAN 1
    #define CASE_VAL_L 2
    #define CASE_VAL_H 3
    #define MIDI_VAR 4
    #define MSG_TYPE 5
    #define FG_ADDR 1
    #define FG_LENGTH 0
    #define CURRENT_F 2
    #define PITCH 0
    #define VELOCITY 1
    #define POT1 41
    @@ -29,412 +31,423 @@
    #define FADER 45

    File myFile;
    volatile int milliSec = 0;
    char* temp = "";
    int** caseArray;
    int fgcount=0; //number of frame groups & corresponding cases
    int maxChannel=20;
    int** caseInfo;
    int fgcount = 0; //number of frame groups & corresponding cases
    int maxChannel = 20;
    double global_note, global_velocity;
    int period = 0;

    void loadFrame(int FrameID) {
    int i;
    int chan, val, upVal;
    char in, in2;

    #ifdef DEBUG
    Serial.print("Load Frame Group:");
    Serial.print(FrameID);
    Serial.print(" Frame:");
    Serial.println(caseArray[FrameID][CURRENT_F]);
    #endif

    //seek to location of frame group on SD card
    myFile.seek(caseArray[FrameID][FG_ADDR]);

    //find location of frame
    i = 0;
    while (i <= caseArray[FrameID][CURRENT_F]) {
    while (myFile.read() != '%');
    i++;
    }

    //read and execute DMX instructions
    in = myFile.read();
    while (myFile.available() && in != '%' && in != '#') {

    switch (in) {
    case 'S':
    case 'P':
    case 'F':
    case 'M':
    in2 = myFile.read();
    myFile.readBytes(temp, 2);
    chan = asciiHexToInt(temp, 2);
    myFile.readBytes(temp, 2);
    val = asciiHexToInt(temp, 2);
    myFile.readBytes(temp, 2);
    upVal = asciiHexToInt(temp, 2);

    #ifdef DEBUG
    Serial.flush();
    Serial.print("DMX Instruction: chan ");
    Serial.print(chan, HEX);
    Serial.print(", ");
    Serial.print(val, HEX);
    Serial.print(", ");
    Serial.println(upVal, HEX);
    #endif

    double potValue;
    int out;
    switch (in) {
    case 'S'://ST = Static
    DmxSimple.write(chan, val);
    break;
    case 'P':
    switch (in2) {
    case '1'://P1 = Potentiometer 1
    potValue = analogRead(POT1);
    break;
    case '2'://P1 = Potentiometer 2
    potValue = analogRead(POT2);
    break;
    case '3'://P1 = Potentiometer 3
    potValue = analogRead(POT3);
    break;
    case '4'://P1 = Potentiometer 4
    potValue = analogRead(POT4);
    break;
    case '5'://P1 = Fader / Slider
    potValue = analogRead(FADER);
    break;
    }
    out = (int) ((potValue / 1023)*(upVal - val) + val);
    DmxSimple.write(chan, out);
    break;
    case 'F':
    switch (in2) {
    case 'U'://FU = Fade Up
    case 'D'://FD = Fade Down
    break;
    }
    break;
    case 'M':
    Serial.print(val);
    Serial.print(" ");
    Serial.println(upVal);
    switch (in2) {
    case '1'://M1 = MIDI Note
    out = (int) ((global_note / 127)*(upVal - val) + val);
    break;
    case '2'://M2 = MIDI Velocity
    out = (int) ((global_velocity / 127)*(upVal - val) + val);
    break;
    }
    Serial.println(float2s(out, 5));
    DmxSimple.write(chan, out);
    break;
    }
    break;
    default:
    #ifdef DEBUG
    Serial.println("DMX Instuction Type not implemented yet");
    Serial.print(caseArray[FrameID][CURRENT_F]);
    Serial.print(" ");
    Serial.print(FrameID);
    Serial.print(" ");
    Serial.print(in);
    Serial.println(in2);
    #endif
    break;
    }
    in = myFile.read();
    }

    //increment frame counter
    if (++caseArray[FrameID][CURRENT_F] >= caseArray[FrameID][FG_LENGTH])
    caseArray[FrameID][CURRENT_F] = 0;
    }

    void loadScene(char* fileName) {

    void loadFrame(int FrameID){
    int i;
    int chan, val, upVal;
    char in,in2;
    int i;
    int looplength;

    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    myFile.close();
    myFile = SD.open(fileName, FILE_READ);
    if (!myFile) {
    // if the file didn't open, print an error:
    #ifdef DEBUG
    Serial.println("error opening scene");
    #endif
    }else{

    //free the memory for the old case array if it exists
    if (fgcount != 0) {
    for (i = 0; i < fgcount; i++)
    free(caseArray[i]);
    free(caseArray);
    }

    myFile.readBytes(temp, 2);
    fgcount = asciiHexToInt(temp, 2);

    myFile.readBytes(temp, 2);
    looplength = asciiHexToInt(temp, 2);

    myFile.readBytes(temp, 2);
    maxChannel = asciiHexToInt(temp, 2);

    #ifdef DEBUG
    Serial.print("Load Frame Group:");
    Serial.print(FrameID);
    Serial.print(" Frame:");
    Serial.println(caseArray[FrameID][CURRENT_F]);
    Serial.print("fgcount ");
    Serial.println(fgcount);
    Serial.print("looplength ");
    Serial.println(looplength);
    Serial.print("maxChannel ");
    Serial.println(maxChannel);
    #endif

    caseInfo = (int**) malloc(fgcount * sizeof (int*));

    //seek to location of frame group on SD card
    myFile.seek(caseArray[FrameID][FG_ADDR]);

    //find location of frame
    i=0;
    while(i<=caseArray[FrameID][CURRENT_F]){
    while(myFile.read()!='%');
    i++;
    }

    //read and execute DMX instructions
    in = myFile.read();
    while(myFile.available()&&in!='%'&&in!='#'){

    switch(in){
    case 'S':
    case 'P':
    case 'F':
    case 'M':
    in2 = myFile.read();
    myFile.readBytes(temp,2);
    chan = asciiHexToInt(temp,2);
    myFile.readBytes(temp,2);
    val = asciiHexToInt(temp,2);
    myFile.readBytes(temp,2);
    upVal = asciiHexToInt(temp,2);

    #ifdef DEBUG
    Serial.flush();
    Serial.print("DMX Instruction: chan ");
    Serial.print(chan,HEX);
    Serial.print(", ");
    Serial.print(val,HEX);
    Serial.print(", ");
    Serial.println(upVal,HEX);
    #endif

    double potValue;
    int out;
    switch(in){
    case 'S'://ST = Static
    DmxSimple.write(chan,val);
    break;
    case 'P':
    switch(in2){
    case '1'://P1 = Potentiometer 1
    potValue = analogRead(POT1);
    break;
    case '2'://P1 = Potentiometer 2
    potValue = analogRead(POT2);
    break;
    case '3'://P1 = Potentiometer 3
    potValue = analogRead(POT3);
    break;
    case '4'://P1 = Potentiometer 4
    potValue = analogRead(POT4);
    break;
    case '5'://P1 = Fader / Slider
    potValue = analogRead(FADER);
    break;
    }
    out = (int)((potValue/1023)*(upVal-val) + val);
    DmxSimple.write(chan,out);
    break;
    case 'F':
    switch(in2){
    case 'U'://FU = Fade Up
    case 'D'://FD = Fade Down
    break;
    }
    break;
    case 'M':
    Serial.print(val);
    Serial.print(" ");
    Serial.println(upVal);
    switch(in2){
    case '1'://M1 = MIDI Note
    out = (int)((global_note/127)*(upVal-val) + val);
    break;
    case '2'://M2 = MIDI Velocity
    out = (int)((global_velocity/127)*(upVal-val) + val);
    break;
    }
    Serial.println(float2s(out,5));
    DmxSimple.write(chan,out);
    break;
    }
    break;
    default:
    #ifdef DEBUG
    Serial.println("DMX Instuction Type not implemented yet");
    Serial.print(caseArray[FrameID][CURRENT_F]);
    Serial.print(" ");
    Serial.print(FrameID);
    Serial.print(" ");
    Serial.print(in);
    Serial.println(in2);
    #endif
    break;
    }
    in = myFile.read();
    }

    //increment frame counter
    if(++caseArray[FrameID][CURRENT_F]>=caseArray[FrameID][FG_LENGTH])
    caseArray[FrameID][CURRENT_F]=0;
    }
    for (i = 0; i < fgcount; i++) {
    caseInfo[i] = (int*) malloc(3 * sizeof (int));

    void loadCase(){
    int i;

    caseArray = (int**) malloc(fgcount*sizeof(int*));
    for (i = 0; i < fgcount; i++){
    caseArray[i] = (int*) malloc(8*sizeof(int));
    while (myFile.read() != '#');

    myFile.readBytes(temp, 2);
    caseInfo[i][FG_LENGTH] = asciiHexToInt(temp, 2);
    caseInfo[i][FG_ADDR] = myFile.position();
    caseInfo[i][CURRENT_F] = 0;

    #ifdef DEBUG
    Serial.print("FG located at ");
    Serial.println(caseArray[i][5]);
    #endif

    }

    while (myFile.read() != '$');

    myFile.readBytes(temp, 2);
    int caseCount = asciiHexToInt(temp, 2);
    int fg = 0;


    caseArray = (int**) malloc(caseCount * sizeof (int*));
    for (i = 0; i < caseCount; i++) {
    caseArray[i] = (int*) malloc(6 * sizeof (int));

    //MIDI Listen Channel
    myFile.readBytes(temp,2);
    caseArray[i][LISTEN_CHAN] = asciiHexToInt(temp,2);
    //MIDI low case value
    myFile.readBytes(temp,2);
    caseArray[i][CASE_VAL_L] = asciiHexToInt(temp,2);
    //MIDI high case value
    myFile.readBytes(temp,2);
    caseArray[i][CASE_VAL_H] = asciiHexToInt(temp,2);
    //MIDI varible (pitch,velocity,etc)
    myFile.readBytes(temp,1);
    caseArray[i][MIDI_VAR] = asciiHexToInt(temp,1);
    //MIDI message type (note on, note off, etc)
    myFile.readBytes(temp,2);
    caseArray[i][MSG_TYPE] = asciiHexToInt(temp,2);
    //FG address
    //caseArray[i][FG_ADDR] gets set in loadScene()
    //caseArray[i][FG_LENGTH] gets set in loadScene()
    caseArray[i][CURRENT_F] = 0;

    #ifdef DEBUG
    char c = myFile.read();
    if(c == '$'){
    fg++;
    }

    caseArray[i][FRAME_GROUP] = fg;
    //MIDI Listen Channel
    myFile.readBytes(temp, 2);
    caseArray[i][LISTEN_CHAN] = asciiHexToInt(temp, 2);
    //MIDI low case value
    myFile.readBytes(temp, 2);
    caseArray[i][CASE_VAL_L] = asciiHexToInt(temp, 2);
    //MIDI high case value
    myFile.readBytes(temp, 2);
    caseArray[i][CASE_VAL_H] = asciiHexToInt(temp, 2);
    //MIDI varible (pitch,velocity,etc)
    myFile.readBytes(temp, 1);
    caseArray[i][MIDI_VAR] = asciiHexToInt(temp, 1);
    //MIDI message type (note on, note off, etc)
    myFile.readBytes(temp, 2);
    caseArray[i][MSG_TYPE] = asciiHexToInt(temp, 2);

    #ifdef DEBUG
    Serial.flush();
    Serial.print("------ Case Array Index ");
    Serial.print(i);
    Serial.println(" -------");
    Serial.print("MIDI Listen Channel ");
    Serial.println(caseArray[i][0]);
    Serial.println(caseArray[i][LISTEN_CHAN]);
    Serial.print("MIDI low case value ");
    Serial.println(caseArray[i][1]);
    Serial.println(caseArray[i][CASE_VAL_L]);
    Serial.print("MIDI high case value ");
    Serial.println(caseArray[i][2]);
    Serial.println(caseArray[i][CASE_VAL_H]);
    Serial.print("MIDI varible ");
    Serial.println(caseArray[i][3]);
    Serial.println(caseArray[i][MIDI_VAR]);
    Serial.print("MIDI message type ");
    Serial.println(caseArray[i][4]);
    Serial.println(caseArray[i][MSG_TYPE]);
    Serial.flush();
    #endif
    }
    }

    void loadScene(){

    int i;
    int looplength;

    //free the memory for the old case array if it exists
    if(fgcount!=0){
    for (i = 0; i < fgcount; i++)
    free(caseArray[i]);
    free(caseArray);
    }

    myFile.readBytes(temp,2);
    fgcount = asciiHexToInt(temp,2);

    myFile.readBytes(temp,2);
    looplength = asciiHexToInt(temp,2);

    myFile.readBytes(temp,2);
    maxChannel = asciiHexToInt(temp,2);

    #ifdef DEBUG
    Serial.print("fgcount ");
    Serial.println(fgcount);
    Serial.print("looplength ");
    Serial.println(looplength);
    Serial.print("maxChannel ");
    Serial.println(maxChannel);
    #endif

    //create new case array
    loadCase();

    //set FG addresses in case array
    i = 0;
    for(i = 0; i<fgcount; i++){
    while(myFile.read()!='#');

    myFile.readBytes(temp,2);
    caseArray[i][FG_LENGTH] = asciiHexToInt(temp,2);
    caseArray[i][FG_ADDR] = myFile.position();

    #ifdef DEBUG
    Serial.print("FG located at ");
    Serial.println(caseArray[i][5]);
    #endif

    }
    }
    }

    void setup(){
    void count() {
    milliSec++;
    }

    void setup() {
    DmxSimple.usePin(7);
    DmxSimple.maxChannel(8);
    //pinMode(3, OUTPUT);
    // MIDI.begin(MIDI_CHANNEL_OMNI);
    //pinMode(3, OUTPUT);
    //MIDI.begin(MIDI_CHANNEL_OMNI);

    Timer1.initialize(10000); //in microseconds (1000000us = 1s)
    Timer1.attachInterrupt(count); //runs every millisecond
    Timer1.start();

    #ifdef DEBUG

    Serial.print("Initializing SD card...");
    Serial.print("Initializing SD card...");
    #endif
    // On the Ethernet Shield, CS is pin 4. It's set as an output by default.*/
    // Note that even if it's not used as the CS pin, the hardware SS pin
    // (10 on most Arduino boards, 53 on the Mega) must be left as an output
    // or the SD library functions will not work.
    pinMode(20, OUTPUT);
    if (!SD.begin(20)) {
    // On the Ethernet Shield, CS is pin 4. It's set as an output by default.*/
    // Note that even if it's not used as the CS pin, the hardware SS pin
    // (10 on most Arduino boards, 53 on the Mega) must be left as an output
    // or the SD library functions will not work.
    pinMode(20, OUTPUT);

    if (!SD.begin(20)) {
    #ifdef DEBUG
    Serial.println("initialization failed!");
    #endif
    return;
    }
    Serial.println("initialization failed!");
    #endif
    return;
    }

    myFile = SD.open("config.xml", FILE_READ);
    if (!myFile) {
    // if the file didn't open, print an error:
    #ifdef DEBUG
    Serial.println("initialization done.");
    #endif
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    myFile = SD.open("qq.scn", FILE_READ);
    if (!myFile) {
    // if the file didn't open, print an error:
    #ifdef DEBUG
    Serial.println("error opening scene");
    #endif
    }

    loadScene();

    //myFile.close();
    }

    int asciiHexToInt(char* a, int length){
    //converts acii representation of hex eg 'ff' to 0xFF
    int val;
    int in;
    int out=0;

    for(int i=length-1;i>=0;i--){

    in = a[i];

    if(in>='A'&&in<='F'){
    val = in-55;
    }
    else if(in>='a'&&in<='f'){
    val = in-87;
    }
    else if(in>='0'&in<='9'){
    val = in-48;
    }
    else return -1;

    out += val * (int)ceil((pow(16,length-1-i)));
    }
    return out;
    Serial.println("error opening config file");
    #endif
    }else{

    #ifdef DEBUG
    Serial.println("initialization done.");
    #endif

    loadScene("qq.scn");
    }
    }

    void loop(){
    boolean dmx=0;
    int i;

    if(usbMIDI.read())
    dmx = handleMIDI(usbMIDI.getType(), usbMIDI.getChannel(),usbMIDI.getData1(),usbMIDI.getData2());
    // else if(MIDI.read())
    // handleMIDI(MIDI.getType(), MIDI.getChannel(),MIDI.getData1(),MIDI.getData2());
    else return;

    if(!dmx)
    for(i=0; i<maxChannel; i++)
    DmxSimple.write(i,0);

    int asciiHexToInt(char* a, int length) {
    //converts acii representation of hex eg 'ff' to 0xFF
    int val;
    int in;
    int out = 0;

    for (int i = length - 1; i >= 0; i--) {

    in = a[i];

    if (in >= 'A' && in <= 'F') {
    val = in - 55;
    } else if (in >= 'a' && in <= 'f') {
    val = in - 87;
    } else if (in >= '0' & in <= '9') {
    val = in - 48;
    } else return -1;

    out += val * (int) ceil((pow(16, length - 1 - i)));
    }
    return out;
    }

    boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {

    global_note = note;
    global_velocity = velocity;

    int midiValue=0;
    int i;

    switch (midiType) {
    case 0:// NoteOff // Note Off
    midiType = 0x80;
    break;
    case 1:// NoteOn // Note On
    midiType = 0x90;
    break;
    default:// InvalidType // For notifying errors
    midiType = 0;
    break;
    }

    //#ifdef DEBUG
    boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {

    global_note = note;
    global_velocity = velocity;

    int midiValue = 0;
    int i;

    //MIDI Clock Signal
    if (midiType == NoteOn && midiChan == 1 && note == 12/*C1*/ && velocity == 14) {
    period = milliSec;
    milliSec = 0;
    }

    //#ifdef DEBUG
    Serial.print("Type: ");
    Serial.print(midiType);
    Serial.print(" Chan: ");
    Serial.print(midiChan);
    Serial.print(" note: ");
    Serial.print(note);
    Serial.print(" velocity: ");
    Serial.println(velocity);
    //#endif
    //loop through all cases
    for(int i=0; i<fgcount; i++){

    //check to see if correct message type (Note on, Note off, etc)
    if(caseArray[i][MSG_TYPE]==midiType
    && caseArray[i][LISTEN_CHAN]==midiChan)
    {

    //get relevant incoming midi data
    switch(caseArray[i][MIDI_VAR]){

    case PITCH:
    midiValue=note;
    break;
    case VELOCITY:
    midiValue=velocity;
    break;
    }

    //do comparison and load frame if true
    if(midiValue>=caseArray[i][CASE_VAL_L]
    && midiValue<=caseArray[i][CASE_VAL_H])
    {
    loadFrame(i);
    return 1;
    }
    }
    }
    return 0;
    Serial.print(midiType);
    Serial.print(" Chan: ");
    Serial.print(midiChan);
    Serial.print(" note: ");
    Serial.print(note);
    Serial.print(" velocity: ");
    Serial.println(velocity);
    //#endif
    //loop through all cases
    for (int i = 0; i < fgcount; i++) {

    //check to see if correct message type (Note on, Note off, etc)
    if (caseArray[i][MSG_TYPE] == midiType
    && caseArray[i][LISTEN_CHAN] == midiChan) {

    //get relevant incoming midi data
    switch (caseArray[i][MIDI_VAR]) {

    case PITCH:
    midiValue = note;
    break;
    case VELOCITY:
    midiValue = velocity;
    break;
    }

    //do comparison and load frame if true
    if (midiValue >= caseArray[i][CASE_VAL_L]
    && midiValue <= caseArray[i][CASE_VAL_H]) {
    loadFrame(i);
    return 1;
    }
    }
    }
    return 0;
    }

    char * float2s(double f, unsigned int digits){
    int index = 0;
    static char s[16]; // buffer to build string representation
    // handle sign
    if (f < 0.0)
    {
    s[index++] = '-';
    f = -f;
    }
    // handle infinite values
    if (isinf(f))
    {
    strcpy(&s[index], "INF");
    return s;
    }
    // handle Not a Number
    if (isnan(f))
    {
    strcpy(&s[index], "NaN");
    void loop() {
    boolean dmx = 0;
    int i;

    if (usbMIDI.read())
    dmx = handleMIDI(usbMIDI.getType(), usbMIDI.getChannel(), usbMIDI.getData1(), usbMIDI.getData2());
    else if (MIDI.read())
    handleMIDI(MIDI.getType(), MIDI.getChannel(), MIDI.getData1(), MIDI.getData2());
    else return;

    if (!dmx)
    for (i = 0; i < maxChannel; i++)
    DmxSimple.write(i, 0);
    }

    char * float2s(double f, unsigned int digits) {
    int index = 0;
    static char s[16]; // buffer to build string representation
    // handle sign
    if (f < 0.0) {
    s[index++] = '-';
    f = -f;
    }
    // handle infinite values
    if (isinf(f)) {
    strcpy(&s[index], "INF");
    return s;
    }
    // handle Not a Number
    if (isnan(f)) {
    strcpy(&s[index], "NaN");
    return s;
    }

    // max digits
    if (digits > 9) digits = 9;
    long multiplier = pow(10, digits); // fix int => long

    int exponent = int(log10(f));
    double g = f / pow(10, exponent);
    if ((g < 1.0) && (g != 0.0)) {
    g *= 10;
    exponent--;
    }

    long whole = long(g); // single digit
    long part = long((g - whole) * multiplier); // # digits
    char format[16];
    sprintf(format, "%%ld.%%0%dld E%%+d", digits);
    sprintf(&s[index], format, whole, part, exponent);

    return s;
    }

    // max digits
    if (digits > 9) digits = 9;
    long multiplier = pow(10, digits); // fix int => long

    int exponent = int(log10(f));
    double g = f / pow(10, exponent);
    if ((g < 1.0) && (g != 0.0))
    {
    g *= 10;
    exponent--;
    }

    long whole = long(g); // single digit
    long part = long((g-whole)*multiplier); // # digits
    char format[16];
    sprintf(format, "%%ld.%%0%dld E%%+d", digits);
    sprintf(&s[index], format, whole, part, exponent);

    return s;
    }
  6. yrrah revised this gist Apr 21, 2013. 1 changed file with 151 additions and 49 deletions.
    200 changes: 151 additions & 49 deletions gistfile1.c
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,8 @@
    #include <SD.h>
    #include <MIDI.h>
    //#include <MIDI.h>
    #include <DmxSimple.h> //limited to 64 channels in DmxSimple.h to save memory

    #define DEBUG 1
    //define DEBUG 1
    #define MIDI_BAUDRATE 31250
    #define COMPILE_MIDI_IN 1 // Set this setting to 1 to use the MIDI input.
    #define COMPILE_MIDI_OUT 0 // Set this setting to 1 to use the MIDI output.
    @@ -22,18 +22,23 @@
    #define CURRENT_F 7
    #define PITCH 0
    #define VELOCITY 1
    #define NOTE_ON 'n'
    #define POT1 41
    #define POT2 42
    #define POT3 43
    #define POT4 44
    #define FADER 45

    File myFile;
    char* temp = "";
    int** caseArray;
    int fgcount=0; //number of frame groups & corresponding cases
    int fgcount=0; //number of frame groups & corresponding cases
    int maxChannel=20;
    double global_note, global_velocity;

    void loadFrame(int FrameID){
    int i;
    int chan, val;
    char in;
    int chan, val, upVal;
    char in,in2;

    #ifdef DEBUG
    Serial.print("Load Frame Group:");
    @@ -56,42 +61,100 @@ void loadFrame(int FrameID){
    in = myFile.read();
    while(myFile.available()&&in!='%'&&in!='#'){

    if(in=='S'){
    //static instruction
    myFile.readBytes(temp,2);
    chan = asciiHexToInt(temp,2);
    myFile.readBytes(temp,2);
    val = asciiHexToInt(temp,2);
    DmxSimple.write(chan,val);


    #ifdef DEBUG
    Serial.flush();
    Serial.print("DMX Instruction: chan ");
    Serial.print(chan,HEX);
    Serial.print(", ");
    Serial.println(val,HEX);
    #endif
    }else{

    #ifdef DEBUG
    switch(in){
    case 'S':
    case 'P':
    case 'F':
    case 'M':
    in2 = myFile.read();
    myFile.readBytes(temp,2);
    chan = asciiHexToInt(temp,2);
    myFile.readBytes(temp,2);
    val = asciiHexToInt(temp,2);
    myFile.readBytes(temp,2);
    upVal = asciiHexToInt(temp,2);

    #ifdef DEBUG
    Serial.flush();
    Serial.print("DMX Instruction: chan ");
    Serial.print(chan,HEX);
    Serial.print(", ");
    Serial.print(val,HEX);
    Serial.print(", ");
    Serial.println(upVal,HEX);
    #endif

    double potValue;
    int out;
    switch(in){
    case 'S'://ST = Static
    DmxSimple.write(chan,val);
    break;
    case 'P':
    switch(in2){
    case '1'://P1 = Potentiometer 1
    potValue = analogRead(POT1);
    break;
    case '2'://P1 = Potentiometer 2
    potValue = analogRead(POT2);
    break;
    case '3'://P1 = Potentiometer 3
    potValue = analogRead(POT3);
    break;
    case '4'://P1 = Potentiometer 4
    potValue = analogRead(POT4);
    break;
    case '5'://P1 = Fader / Slider
    potValue = analogRead(FADER);
    break;
    }
    out = (int)((potValue/1023)*(upVal-val) + val);
    DmxSimple.write(chan,out);
    break;
    case 'F':
    switch(in2){
    case 'U'://FU = Fade Up
    case 'D'://FD = Fade Down
    break;
    }
    break;
    case 'M':
    Serial.print(val);
    Serial.print(" ");
    Serial.println(upVal);
    switch(in2){
    case '1'://M1 = MIDI Note
    out = (int)((global_note/127)*(upVal-val) + val);
    break;
    case '2'://M2 = MIDI Velocity
    out = (int)((global_velocity/127)*(upVal-val) + val);
    break;
    }
    Serial.println(float2s(out,5));
    DmxSimple.write(chan,out);
    break;
    }
    break;
    default:
    #ifdef DEBUG
    Serial.println("DMX Instuction Type not implemented yet");
    Serial.print(caseArray[FrameID][CURRENT_F]);
    Serial.print(" ");
    Serial.println(FrameID);
    #endif
    }
    in = myFile.read();
    Serial.print(FrameID);
    Serial.print(" ");
    Serial.print(in);
    Serial.println(in2);
    #endif
    break;
    }
    in = myFile.read();
    }

    //increment frame counter
    if(++caseArray[FrameID][CURRENT_F]>=caseArray[FrameID][FG_LENGTH])
    caseArray[FrameID][CURRENT_F]=0;
    }




    void loadCase(){
    int i;

    @@ -188,8 +251,7 @@ void loadScene(){
    }
    }

    void setup()
    {
    void setup(){
    DmxSimple.usePin(7);
    DmxSimple.maxChannel(8);
    //pinMode(3, OUTPUT);
    @@ -217,11 +279,11 @@ Serial.println("initialization done.");
    #endif
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    myFile = SD.open("1.scn", FILE_READ);
    myFile = SD.open("qq.scn", FILE_READ);
    if (!myFile) {
    // if the file didn't open, print an error:
    #ifdef DEBUG
    Serial.println("error opening test.txt");
    Serial.println("error opening scene");
    #endif
    }

    @@ -230,7 +292,6 @@ Serial.println("initialization done.");
    //myFile.close();
    }


    int asciiHexToInt(char* a, int length){
    //converts acii representation of hex eg 'ff' to 0xFF
    int val;
    @@ -257,18 +318,14 @@ int asciiHexToInt(char* a, int length){
    return out;
    }




    void loop()
    {
    void loop(){
    boolean dmx=0;
    int i;

    if(usbMIDI.read())
    dmx = handleMIDI(usbMIDI.getType(), usbMIDI.getChannel(),usbMIDI.getData1(),usbMIDI.getData2());
    else if(MIDI.read())
    handleMIDI(MIDI.getType(), MIDI.getChannel(),MIDI.getData1(),MIDI.getData2());
    // else if(MIDI.read())
    // handleMIDI(MIDI.getType(), MIDI.getChannel(),MIDI.getData1(),MIDI.getData2());
    else return;

    if(!dmx)
    @@ -280,10 +337,12 @@ int i;

    boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {

    global_note = note;
    global_velocity = velocity;

    int midiValue=0;
    int i;


    switch (midiType) {
    case 0:// NoteOff // Note Off
    midiType = 0x80;
    @@ -296,7 +355,7 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    break;
    }

    #ifdef DEBUG
    //#ifdef DEBUG
    Serial.print("Type: ");
    Serial.print(midiType);
    Serial.print(" Chan: ");
    @@ -305,7 +364,7 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    Serial.print(note);
    Serial.print(" velocity: ");
    Serial.println(velocity);
    #endif
    //#endif
    //loop through all cases
    for(int i=0; i<fgcount; i++){

    @@ -318,7 +377,7 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    switch(caseArray[i][MIDI_VAR]){

    case PITCH:
    midiValue=note;
    midiValue=note;
    break;
    case VELOCITY:
    midiValue=velocity;
    @@ -335,4 +394,47 @@ boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {
    }
    }
    return 0;
    }
    }

    char * float2s(double f, unsigned int digits){
    int index = 0;
    static char s[16]; // buffer to build string representation
    // handle sign
    if (f < 0.0)
    {
    s[index++] = '-';
    f = -f;
    }
    // handle infinite values
    if (isinf(f))
    {
    strcpy(&s[index], "INF");
    return s;
    }
    // handle Not a Number
    if (isnan(f))
    {
    strcpy(&s[index], "NaN");
    return s;
    }

    // max digits
    if (digits > 9) digits = 9;
    long multiplier = pow(10, digits); // fix int => long

    int exponent = int(log10(f));
    double g = f / pow(10, exponent);
    if ((g < 1.0) && (g != 0.0))
    {
    g *= 10;
    exponent--;
    }

    long whole = long(g); // single digit
    long part = long((g-whole)*multiplier); // # digits
    char format[16];
    sprintf(format, "%%ld.%%0%dld E%%+d", digits);
    sprintf(&s[index], format, whole, part, exponent);

    return s;
    }
  7. yrrah created this gist Apr 18, 2013.
    338 changes: 338 additions & 0 deletions gistfile1.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,338 @@
    #include <SD.h>
    #include <MIDI.h>
    #include <DmxSimple.h> //limited to 64 channels in DmxSimple.h to save memory

    #define DEBUG 1
    #define MIDI_BAUDRATE 31250
    #define COMPILE_MIDI_IN 1 // Set this setting to 1 to use the MIDI input.
    #define COMPILE_MIDI_OUT 0 // Set this setting to 1 to use the MIDI output.
    #define COMPILE_MIDI_THRU 0 // Set this setting to 1 to use the MIDI Soft Thru feature
    #define USE_SERIAL_PORT Serial
    #define USE_RUNNING_STATUS 0
    #define USE_1BYTE_PARSING 1
    #define USE_CALLBACKS 0
    #define MIDI_SYSEX_ARRAY_SIZE 64
    #define LISTEN_CHAN 0
    #define CASE_VAL_L 1
    #define CASE_VAL_H 2
    #define MIDI_VAR 3
    #define MSG_TYPE 4
    #define FG_ADDR 5
    #define FG_LENGTH 6
    #define CURRENT_F 7
    #define PITCH 0
    #define VELOCITY 1
    #define NOTE_ON 'n'

    File myFile;
    char* temp = "";
    int** caseArray;
    int fgcount=0; //number of frame groups & corresponding cases
    int maxChannel=20;

    void loadFrame(int FrameID){
    int i;
    int chan, val;
    char in;

    #ifdef DEBUG
    Serial.print("Load Frame Group:");
    Serial.print(FrameID);
    Serial.print(" Frame:");
    Serial.println(caseArray[FrameID][CURRENT_F]);
    #endif

    //seek to location of frame group on SD card
    myFile.seek(caseArray[FrameID][FG_ADDR]);

    //find location of frame
    i=0;
    while(i<=caseArray[FrameID][CURRENT_F]){
    while(myFile.read()!='%');
    i++;
    }

    //read and execute DMX instructions
    in = myFile.read();
    while(myFile.available()&&in!='%'&&in!='#'){

    if(in=='S'){
    //static instruction
    myFile.readBytes(temp,2);
    chan = asciiHexToInt(temp,2);
    myFile.readBytes(temp,2);
    val = asciiHexToInt(temp,2);
    DmxSimple.write(chan,val);


    #ifdef DEBUG
    Serial.flush();
    Serial.print("DMX Instruction: chan ");
    Serial.print(chan,HEX);
    Serial.print(", ");
    Serial.println(val,HEX);
    #endif
    }else{

    #ifdef DEBUG
    Serial.println("DMX Instuction Type not implemented yet");
    Serial.print(caseArray[FrameID][CURRENT_F]);
    Serial.print(" ");
    Serial.println(FrameID);
    #endif
    }
    in = myFile.read();
    }

    //increment frame counter
    if(++caseArray[FrameID][CURRENT_F]>=caseArray[FrameID][FG_LENGTH])
    caseArray[FrameID][CURRENT_F]=0;
    }




    void loadCase(){
    int i;

    caseArray = (int**) malloc(fgcount*sizeof(int*));
    for (i = 0; i < fgcount; i++){
    caseArray[i] = (int*) malloc(8*sizeof(int));

    //MIDI Listen Channel
    myFile.readBytes(temp,2);
    caseArray[i][LISTEN_CHAN] = asciiHexToInt(temp,2);
    //MIDI low case value
    myFile.readBytes(temp,2);
    caseArray[i][CASE_VAL_L] = asciiHexToInt(temp,2);
    //MIDI high case value
    myFile.readBytes(temp,2);
    caseArray[i][CASE_VAL_H] = asciiHexToInt(temp,2);
    //MIDI varible (pitch,velocity,etc)
    myFile.readBytes(temp,1);
    caseArray[i][MIDI_VAR] = asciiHexToInt(temp,1);
    //MIDI message type (note on, note off, etc)
    myFile.readBytes(temp,2);
    caseArray[i][MSG_TYPE] = asciiHexToInt(temp,2);
    //FG address
    //caseArray[i][FG_ADDR] gets set in loadScene()
    //caseArray[i][FG_LENGTH] gets set in loadScene()
    caseArray[i][CURRENT_F] = 0;

    #ifdef DEBUG
    Serial.flush();
    Serial.print("------ Case Array Index ");
    Serial.print(i);
    Serial.println(" -------");
    Serial.print("MIDI Listen Channel ");
    Serial.println(caseArray[i][0]);
    Serial.print("MIDI low case value ");
    Serial.println(caseArray[i][1]);
    Serial.print("MIDI high case value ");
    Serial.println(caseArray[i][2]);
    Serial.print("MIDI varible ");
    Serial.println(caseArray[i][3]);
    Serial.print("MIDI message type ");
    Serial.println(caseArray[i][4]);
    Serial.flush();
    #endif
    }
    }

    void loadScene(){

    int i;
    int looplength;

    //free the memory for the old case array if it exists
    if(fgcount!=0){
    for (i = 0; i < fgcount; i++)
    free(caseArray[i]);
    free(caseArray);
    }

    myFile.readBytes(temp,2);
    fgcount = asciiHexToInt(temp,2);

    myFile.readBytes(temp,2);
    looplength = asciiHexToInt(temp,2);

    myFile.readBytes(temp,2);
    maxChannel = asciiHexToInt(temp,2);

    #ifdef DEBUG
    Serial.print("fgcount ");
    Serial.println(fgcount);
    Serial.print("looplength ");
    Serial.println(looplength);
    Serial.print("maxChannel ");
    Serial.println(maxChannel);
    #endif

    //create new case array
    loadCase();

    //set FG addresses in case array
    i = 0;
    for(i = 0; i<fgcount; i++){
    while(myFile.read()!='#');

    myFile.readBytes(temp,2);
    caseArray[i][FG_LENGTH] = asciiHexToInt(temp,2);
    caseArray[i][FG_ADDR] = myFile.position();

    #ifdef DEBUG
    Serial.print("FG located at ");
    Serial.println(caseArray[i][5]);
    #endif
    }
    }

    void setup()
    {
    DmxSimple.usePin(7);
    DmxSimple.maxChannel(8);
    //pinMode(3, OUTPUT);
    // MIDI.begin(MIDI_CHANNEL_OMNI);


    #ifdef DEBUG

    Serial.print("Initializing SD card...");
    #endif
    // On the Ethernet Shield, CS is pin 4. It's set as an output by default.*/
    // Note that even if it's not used as the CS pin, the hardware SS pin
    // (10 on most Arduino boards, 53 on the Mega) must be left as an output
    // or the SD library functions will not work.
    pinMode(20, OUTPUT);

    if (!SD.begin(20)) {
    #ifdef DEBUG
    Serial.println("initialization failed!");
    #endif
    return;
    }
    #ifdef DEBUG
    Serial.println("initialization done.");
    #endif
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    myFile = SD.open("1.scn", FILE_READ);
    if (!myFile) {
    // if the file didn't open, print an error:
    #ifdef DEBUG
    Serial.println("error opening test.txt");
    #endif
    }

    loadScene();

    //myFile.close();
    }


    int asciiHexToInt(char* a, int length){
    //converts acii representation of hex eg 'ff' to 0xFF
    int val;
    int in;
    int out=0;

    for(int i=length-1;i>=0;i--){

    in = a[i];

    if(in>='A'&&in<='F'){
    val = in-55;
    }
    else if(in>='a'&&in<='f'){
    val = in-87;
    }
    else if(in>='0'&in<='9'){
    val = in-48;
    }
    else return -1;

    out += val * (int)ceil((pow(16,length-1-i)));
    }
    return out;
    }




    void loop()
    {
    boolean dmx=0;
    int i;

    if(usbMIDI.read())
    dmx = handleMIDI(usbMIDI.getType(), usbMIDI.getChannel(),usbMIDI.getData1(),usbMIDI.getData2());
    else if(MIDI.read())
    handleMIDI(MIDI.getType(), MIDI.getChannel(),MIDI.getData1(),MIDI.getData2());
    else return;

    if(!dmx)
    for(i=0; i<maxChannel; i++)
    DmxSimple.write(i,0);


    }

    boolean handleMIDI(int midiType, int midiChan, int note, int velocity) {

    int midiValue=0;
    int i;


    switch (midiType) {
    case 0:// NoteOff // Note Off
    midiType = 0x80;
    break;
    case 1:// NoteOn // Note On
    midiType = 0x90;
    break;
    default:// InvalidType // For notifying errors
    midiType = 0;
    break;
    }

    #ifdef DEBUG
    Serial.print("Type: ");
    Serial.print(midiType);
    Serial.print(" Chan: ");
    Serial.print(midiChan);
    Serial.print(" note: ");
    Serial.print(note);
    Serial.print(" velocity: ");
    Serial.println(velocity);
    #endif
    //loop through all cases
    for(int i=0; i<fgcount; i++){

    //check to see if correct message type (Note on, Note off, etc)
    if(caseArray[i][MSG_TYPE]==midiType
    && caseArray[i][LISTEN_CHAN]==midiChan)
    {

    //get relevant incoming midi data
    switch(caseArray[i][MIDI_VAR]){

    case PITCH:
    midiValue=note;
    break;
    case VELOCITY:
    midiValue=velocity;
    break;
    }

    //do comparison and load frame if true
    if(midiValue>=caseArray[i][CASE_VAL_L]
    && midiValue<=caseArray[i][CASE_VAL_H])
    {
    loadFrame(i);
    return 1;
    }
    }
    }
    return 0;
    }