ChordJoy is a keyboard application that accepts chordal input from a set of digital ports, outputting letters and the chords that correspond to the piano keyboard keys the user has pressed.

Dependencies:   PinDetect_KL25Z mbed-rtos mbed

Fork of ChordJoy by Interactive Device Design

main.cpp

Committer:
andrewhead
Date:
2014-09-22
Revision:
3:ed89297af2ce
Parent:
2:49e2b1273f16
Child:
4:400a042e762a

File content as of revision 3:ed89297af2ce:

#include "mbed.h"
#include "rtos.h"


const int BUTTONS = 7;
const int BUZZERS = 3;
const int LETTERS = 27;

// Collection is the time that it takes after pressing one key and then reading
// all the keys to determine what the chord is.
const int COLLECTION_MS = 500;
Timer collectionTimer;

InterruptIn buttons [BUTTONS] = {
    InterruptIn(D2),
    InterruptIn(D4),
    InterruptIn(D5),
    InterruptIn(D8),
    InterruptIn(D9),
    InterruptIn(D10),
    InterruptIn(D11)
};
Serial pc(USBTX, USBRX);

// Note: there are only THREE PWMs on the board. So this is all we can use
// for this particular method of sound output. The pins chosen are important
// because the same PWM will map to multiple outputs. See the reference
// manual for Mbed for which pins map to distinct PWMs.
PwmOut buzzers [3] = {
    PwmOut(D0),
    PwmOut(D7),
    PwmOut(D3)
};

// Periods of notes in microseconds
int notePeriods [8] = {
    3818,   // C4
    3412,   // D4
    3030,   // E4
    2895,   // F4
    2551,   // G4
    2273,   // A4
    2024,   // B4
    10000000 // inaudible pitch
};
// Possible chords that can be played.
// Note that 7 is no button pressed, or a 'silent' pitch.
int chords [LETTERS][BUZZERS] = {
    {0, 7, 7}, // single notes
    {1, 7, 7},
    {2, 7, 7},
    {3, 7, 7},
    {4, 7, 7},
    {5, 7, 7},
    {6, 7, 7},
    {0, 2, 7}, // diads
    {0, 3, 7},
    {0, 4, 7},
    {0, 5, 7},
    {1, 3, 7},
    {1, 4, 7},
    {1, 5, 7},
    {1, 6, 7},
    {2, 4, 7},
    {2, 5, 7},
    {2, 6, 7},
    {3, 4, 7},
    {3, 5, 7},
    {4, 6, 7},
    {0, 2, 4}, // triads
    {0, 2, 5},
    {0, 3, 5},
    {1, 4, 6},
    {1, 3, 4},
    {1, 3, 6}
};

void playAllChords(void) {
    for (int i = 0; i < LETTERS; i++) {
        int *chord = chords[i];
        for (int j = 0; j < BUZZERS; j++) {
            int noteIndex = chord[j];
            if (noteIndex == 7) {
                buzzers[j] = 0;
            }
            else {
                buzzers[j] = .5f;
                int period = notePeriods[noteIndex];
                buzzers[j].period_us(period);
            }
        }
        wait_ms(10000);
    }
}

void setFlag() {
    collectionTimer.start();
}

void silenceBuzzers(void) {
    // Initialize all duty cycles to off, so we hear nothing.
    for (int i = 0; i < BUZZERS; i++) {
        buzzers[i] = 0.0f;
    }
}

void registerButtonInterrupts(void) {
    for (int i =  0; i < BUTTONS; i++) {
        buttons[i].rise(&setFlag);
    }   
}

int readChord(void) {
    /* Detect the current chord from the keys pressed. Return int index of chord.
       Return -1 if no chord can be found with the current keys.
       Note that we can only read as many keys as there are buzzers, so check
       on each key in an ascending order. */
    int firstThreeButtons[BUZZERS] = {7, 7, 7};
    int pressedCount = 0;
    for (int i = 0; i < BUTTONS; i++) {
        if (buttons[i].read() == 1) {
            firstThreeButtons[pressedCount] = i;
            pressedCount++;   
        }
        if (pressedCount >= BUZZERS) {
            break;
        }
    }
    int matchIndex = -1;
    for (int i = 0; i < LETTERS; i++) {
        bool chordMatches = true;
        for (int j = 0; j < BUZZERS; j++) {
            if (firstThreeButtons[j] != chords[i][j]) {
                chordMatches = false;
                break;            
            }
        }
        if (chordMatches == true) {
            matchIndex = i;
            break;
        }
    }
    pc.printf("Matched chord %d\n", matchIndex);
    return matchIndex;
}

void waitForChord(void) {
     /* This method should be run in the main loop so that it can print */
     while (true) {
        if (collectionTimer.read_ms() > COLLECTION_MS) {
            collectionTimer.stop();
            collectionTimer.reset();
            int chordIndex = readChord();
        }
        wait_ms(10);
    }   
}

int main() {
    silenceBuzzers();
    registerButtonInterrupts();
    waitForChord();
}