// work in progress
// COB 27th Sept
// sticky keys, possibly input pullup states - add pulldown resistors to inputs
// scope seems to max out at 50kHz, timers should be running much faster
// COB 28th setup
// setting timer1 overflow to too small an interval causes code to lock up
// for some reason key presses seem to reset the system
// this is part of the manage virtual oscillators function
// simplify to find bugs
// split 29th
// change to square wave output only
// 100kHz clock (/160 = 0xA0)
#define numKeyArrayOut 5
#define numKeyArrayIn 5
#define numtotalKeys 25
#define col_keyNum 0
#define col_divider 1
#define col_noteCounter 2
#define col_keyPressed 3
#define col_keyX_output 4
#define col_keyY_input 5
#define col_outputWfmCounter 6
#define numWfmSamples 15 // 16 samples -1 as first array element is zero
// key #, 100kHz clock divider, counter, pressed, keyboard x, keyboard y, waveform counter
int keyboard [25] [7] = {
{37, 227, 0, 0, 7, 2, 0},
{38, 215, 0, 0, 8, 2, 0},
{39, 202, 0, 0, 9, 2, 0},
{40, 191, 0, 0, 10, 2, 0},
{41, 180, 0, 0, 12, 2, 0},
{42, 170, 0, 0, 7, 3, 0},
{43, 161, 0, 0, 8, 3, 0},
{44, 152, 0, 0, 9, 3, 0},
{45, 143, 0, 0, 10, 3, 0},
{46, 135, 0, 0, 12, 3, 0},
{47, 128, 0, 0, 7, 4, 0},
{48, 120, 0, 0, 8, 4, 0},
{49, 114, 0, 0, 9, 4, 0},
{50, 107, 0, 0, 10, 4, 0},
{51, 101, 0, 0, 12, 4, 0},
{52, 96, 0, 0, 7, 5, 0},
{53, 90, 0, 0, 8, 5, 0},
{54, 85, 0, 0, 9, 5, 0},
{55, 80, 0, 0, 10, 5, 0},
{56, 76, 0, 0, 12, 5, 0},
{57, 72, 0, 0, 7, 6, 0},
{58, 68, 0, 0, 8, 6, 0},
{59, 64, 0, 0, 9, 6, 0},
{60, 60, 0, 0, 10, 6, 0},
{61, 57, 0, 0, 12, 6, 0},
};
int interruptCounter;
int oscUpdater;
// keyboard array
int keyArrayOut[numKeyArrayOut] = {7,8,9,10,12};
int keyArrayIn[numKeyArrayIn] = {2,3,4,5,6};
void setup() {
noInterrupts();
// key array outputs
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(12, OUTPUT);
// key array inputs
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
pinMode(5, INPUT);
pinMode(6, INPUT);
// debug led output
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Serial.begin(9600);
Serial.println("keyboard serial terminal ready");
printKeyboardArrayForDebug();
// TIMER 2
// set up for fast PWM at 50kHz
TCCR2A = 0x83;
TCCR2B = 0x01; // use 0x01 for no prescaler
TCCR1A = 0x00;
TCCR1B = 0x00;
TCCR1B |= B00001001; // prescaler/1, CTC mode, reset on OCR1A
OCR1A = 0x00A0; // tick every 160 counts = 100kHz
TIMSK1 |= B00000010; // enable interrupts on OCR1A overflow
interrupts(); // enable all interrupts
}
void loop() {
//digitalWrite(13, HIGH);
scanKeyArray();
manageVirtualOscillators();
//digitalWrite(13, LOW);
// output the simple square for 37 (A3)
//digitalWrite(13, simpleSquare[keyboard [0] [col_outputWfmCounter]]);
}
ISR(TIMER1_COMPA_vect)
{
// ripple through keyboard array and increment counters
/*
#define numKeyArrayOut 5
#define numKeyArrayIn 5
#define numtotalKeys 25
#define col_keyNum 0
#define col_divider 1
#define col_noteCounter 2
#define col_keyPressed 3
#define col_keyX_output 4
#define col_keyY_input 5
int keyboard [25] [6]
*/
for (interruptCounter=0; interruptCounter<numtotalKeys; interruptCounter++)
{
keyboard [interruptCounter][col_noteCounter] ++;
}
}
void manageVirtualOscillators (void)
{
for (oscUpdater = 0; oscUpdater < numtotalKeys; oscUpdater ++)
{
// has the virtual oscillator reached the divider limit?
if ( keyboard [interruptCounter][col_noteCounter] > keyboard [interruptCounter][col_divider] )
{
// reset the counter
keyboard [interruptCounter][col_noteCounter] = 0;
// check the waveform counter
if (keyboard [interruptCounter][col_outputWfmCounter] < numWfmSamples)
{
// increment if below maximum
keyboard [interruptCounter][col_outputWfmCounter] ++;
}
else
{
// rollover back to 0
keyboard [interruptCounter][col_outputWfmCounter] = 0;
}
}
}
}
void scanKeyArray (void)
{
int keyScan = 0;
int muxOutputPin = 0;
int muxInputPin = 0;
int muxInputState = LOW;
// scan all keys
for (keyScan = 0; keyScan < numtotalKeys; keyScan ++)
{
// set X column output
muxOutputPin = keyboard[keyScan][col_keyX_output];
digitalWrite(muxOutputPin, HIGH);
// read Y input
muxInputPin = keyboard[keyScan][col_keyY_input];
muxInputState = digitalRead(muxInputPin);
// evaluate input
if (muxInputState == HIGH)
{
// key pressed
Serial.print("output ");
Serial.print(muxOutputPin);
Serial.print(" is high & input ");
Serial.print(muxInputPin);
Serial.print(" is high = ");
Serial.print("keyboard key ");
Serial.print(keyboard[keyScan][col_keyNum]);
Serial.println(" pressed");
keyboard[keyScan][col_keyPressed] = 1;
}
else if (muxInputState == LOW)
{
if (keyboard[keyScan][col_keyPressed] == 1) // was pressed, now just released
{
keyboard[keyScan][col_keyPressed] = 0;
// set to 0 for now pending soft stop to waveform
}
else
{
//keyboard[keyScan][col_keyPressed] = 0; // still not pressed, reassert zero
// disabled for now pending soft stop to waveform
}
}
digitalWrite(keyboard[keyScan][col_keyX_output], LOW);
}
}
void printKeyboardArrayForDebug (void)
{
//int keyboard [25] [6]
int row, col;
for (row=0; row<25; row++)
{
for (col=0; col<6; col++)
{
Serial.print(keyboard[row][col]);
Serial.print(", ");
}
Serial.println();
}
}