mirror of
https://github.com/C0ntroller/keyboard.git
synced 2024-11-24 15:34:49 +01:00
Compare commits
No commits in common. "2cd7817d5c38348732ed8b2211cd223be1f953ce" and "ab48f69b6cfcd56185d8329057d13299c04cac99" have entirely different histories.
2cd7817d5c
...
ab48f69b6c
@ -12,4 +12,6 @@
|
|||||||
platform = teensy
|
platform = teensy
|
||||||
board = teensylc
|
board = teensylc
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
lib_deps =
|
||||||
|
thomasfredericks/Bounce2@^2.71
|
||||||
build_flags = -D USB_MIDI -D TEENSY_OPT_FASTEST
|
build_flags = -D USB_MIDI -D TEENSY_OPT_FASTEST
|
134
src/main.cpp
134
src/main.cpp
@ -1,38 +1,50 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <Bounce2.h>
|
||||||
|
|
||||||
#define MIDI_NAME {'P', 'i', 'n', 'g', 'b', 'o', 'a', 'r', 'd'}
|
#define MIDI_NAME {'P', 'i', 'n', 'g', 'b', 'o', 'a', 'r', 'd'}
|
||||||
#define MIDI_NAME_LEN 9
|
#define MIDI_NAME_LEN 9
|
||||||
|
|
||||||
#define KEY_GROUP_NUM 9
|
#define CHECK_PINS 9
|
||||||
#define KEY_PINS 6
|
#define KEY_PINS 6
|
||||||
#define NUMBER_OF_KEYS 49
|
#define BOUNCE_TIME 5
|
||||||
|
|
||||||
#define DEBOUNCE_TIMES 2
|
|
||||||
|
|
||||||
#define POWER_SUPPLY_CHECK_PIN 13
|
#define POWER_SUPPLY_CHECK_PIN 13
|
||||||
|
|
||||||
const uint8_t group_pins[KEY_GROUP_NUM] {14, 15, 16, 17, 18, 19, 20, 21, 22};
|
#define NUMBER_OF_KEYS 49
|
||||||
|
#define SELF_DRIVE_INTERVAL 100
|
||||||
|
|
||||||
|
Bounce check_pins[CHECK_PINS] {
|
||||||
|
{14, BOUNCE_TIME}, // not KEYS1..6
|
||||||
|
{15, BOUNCE_TIME}, // not KEYS7..12
|
||||||
|
{16, BOUNCE_TIME}, // not KEYS13..18
|
||||||
|
{17, BOUNCE_TIME}, // not KEYS19..24
|
||||||
|
{18, BOUNCE_TIME}, // not KEYS25..30
|
||||||
|
{19, BOUNCE_TIME}, // not KEYS31..36
|
||||||
|
{20, BOUNCE_TIME}, // not KEYS37..42
|
||||||
|
{21, BOUNCE_TIME}, // not KEYS43..48
|
||||||
|
{22, BOUNCE_TIME} // not KEYS49
|
||||||
|
};
|
||||||
|
|
||||||
// not KEY0%6..not KEY5%6
|
// not KEY0%6..not KEY5%6
|
||||||
const uint8_t key_pins[KEY_PINS] {2, 3, 4, 5, 6, 7};
|
const unsigned char key_pins[KEY_PINS] {2, 3, 4, 5, 6, 7};
|
||||||
// Array of pressed keys (initially all 0)
|
// Array of pressed keys (initially all 0)
|
||||||
uint8_t keys_pressed[NUMBER_OF_KEYS];
|
bool keys_pressed[NUMBER_OF_KEYS];
|
||||||
// K1, K2, K3, K4, K5, K12, K13, K14, K15
|
// K1, K2, K3, K4, K5, K12, K13, K14, K15
|
||||||
const uint8_t self_drive_pins[KEY_GROUP_NUM] {8, 9, 10, 11, 12, 26, 23, 24, 25};
|
const unsigned char self_drive_pins[CHECK_PINS] {8, 9, 10, 11, 12, 26, 23, 24, 25};
|
||||||
uint8_t current_self_drive_pin = 0;
|
volatile unsigned char curr_self_drive_pin = 0;
|
||||||
|
IntervalTimer self_drive_timer = IntervalTimer();
|
||||||
|
|
||||||
// Map the current array and pressed key to a MIDI note
|
// Map the current array and pressed key to a MIDI note
|
||||||
uint8_t mapToMidi(uint8_t active_key_group, uint8_t key) {
|
unsigned char mapToMidi(char curr_arr, char key) {
|
||||||
uint8_t offset = (active_key_group >> 1) * 12;
|
unsigned char offset = (curr_arr >> 1) * 12;
|
||||||
// case 3 and case 4 are swapped on purpose to reflect circuitry
|
// TODO: maybe we have to switch the notes and array offsets
|
||||||
// Uneven offset are the upper octave, even the lower
|
// Uneven offset are the upper octave, even the lower
|
||||||
if (active_key_group & 1) {
|
if (curr_arr & 1) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 0: return offset + 42; // F#2 + offset
|
case 0: return offset + 42; // F#2 + offset
|
||||||
case 1: return offset + 43; // G2 + offset
|
case 1: return offset + 43; // G2 + offset
|
||||||
case 2: return offset + 44; // G#2 + offset
|
case 2: return offset + 44; // G#2 + offset
|
||||||
case 4: return offset + 45; // A2 + offset
|
case 3: return offset + 45; // A2 + offset
|
||||||
case 3: return offset + 46; // A#2 + offset
|
case 4: return offset + 46; // A#2 + offset
|
||||||
case 5: return offset + 47; // B2 + offset
|
case 5: return offset + 47; // B2 + offset
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -40,8 +52,8 @@ uint8_t mapToMidi(uint8_t active_key_group, uint8_t key) {
|
|||||||
case 0: return offset + 36; // C2 + offset
|
case 0: return offset + 36; // C2 + offset
|
||||||
case 1: return offset + 37; // C#2 + offset
|
case 1: return offset + 37; // C#2 + offset
|
||||||
case 2: return offset + 38; // D2 + offset
|
case 2: return offset + 38; // D2 + offset
|
||||||
case 4: return offset + 39; // D#2 + offset
|
case 3: return offset + 39; // D#2 + offset
|
||||||
case 3: return offset + 40; // E2 + offset
|
case 4: return offset + 40; // E2 + offset
|
||||||
case 5: return offset + 41; // F2 + offset
|
case 5: return offset + 41; // F2 + offset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,19 +63,18 @@ uint8_t mapToMidi(uint8_t active_key_group, uint8_t key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if any of the array pins fell since last time
|
// Check if any of the array pins fell since last time
|
||||||
int8_t getActiveKeyGroup() {
|
char findCurrentArrPin() {
|
||||||
uint8_t active_groups = 0;
|
for (unsigned char i = 0; i < CHECK_PINS; i++) {
|
||||||
int8_t last_active_key_group = -1;
|
|
||||||
for (uint8_t i = 0; i < KEY_GROUP_NUM; i++) {
|
|
||||||
// Update status
|
// Update status
|
||||||
if (digitalReadFast(group_pins[i]) == LOW){
|
check_pins[i].update();
|
||||||
last_active_key_group = (int8_t) i;
|
// Check if the pin fell or is low
|
||||||
active_groups++;
|
// ! inverted
|
||||||
}
|
if (check_pins[i].fell()) return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active_groups==1){
|
// If none fell we should have enough time to see which one is low
|
||||||
return last_active_key_group;
|
for (unsigned char i = 0; i < CHECK_PINS; i++) {
|
||||||
|
if (check_pins[i].read() == LOW) return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default return
|
// Default return
|
||||||
@ -73,72 +84,75 @@ int8_t getActiveKeyGroup() {
|
|||||||
// Set the next self drive pin
|
// Set the next self drive pin
|
||||||
FASTRUN void nextSelfDrivePin() {
|
FASTRUN void nextSelfDrivePin() {
|
||||||
// Set the current pin to high
|
// Set the current pin to high
|
||||||
digitalWriteFast(self_drive_pins[current_self_drive_pin != 0 ? current_self_drive_pin - 1 : KEY_GROUP_NUM - 1], LOW);
|
digitalWriteFast(self_drive_pins[curr_self_drive_pin], HIGH);
|
||||||
digitalWriteFast(self_drive_pins[current_self_drive_pin], HIGH);
|
|
||||||
// Set the next pin
|
// Set the next pin
|
||||||
current_self_drive_pin = (current_self_drive_pin + 1) % KEY_GROUP_NUM;
|
curr_self_drive_pin = (curr_self_drive_pin + 1) % CHECK_PINS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interrupt for power supply check
|
||||||
|
FASTRUN void powerStateChanged() {
|
||||||
|
unsigned char state = digitalReadFast(POWER_SUPPLY_CHECK_PIN);
|
||||||
|
// ! inverted
|
||||||
|
if (state == LOW) {
|
||||||
|
curr_self_drive_pin = 0;
|
||||||
|
self_drive_timer.begin(nextSelfDrivePin, SELF_DRIVE_INTERVAL);
|
||||||
|
} else {
|
||||||
|
self_drive_timer.end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initial start function
|
// Initial start function
|
||||||
void setup() {
|
void setup() {
|
||||||
// Set all in- and outputs
|
// Set all in- and outputs
|
||||||
for (uint8_t i = 0; i < KEY_GROUP_NUM; i++) {
|
for (unsigned char i = 0; i < CHECK_PINS; i++) {
|
||||||
pinMode(group_pins[i], INPUT);
|
pinMode(check_pins[i].getPin(), INPUT);
|
||||||
pinMode(self_drive_pins[i], OUTPUT);
|
pinMode(self_drive_pins[i], INPUT);
|
||||||
}
|
}
|
||||||
for (uint8_t i = 0; i < KEY_PINS; i++) {
|
for (unsigned char i = 0; i < KEY_PINS; i++) {
|
||||||
pinMode(key_pins[i], INPUT);
|
pinMode(key_pins[i], INPUT);
|
||||||
}
|
}
|
||||||
pinMode(POWER_SUPPLY_CHECK_PIN, INPUT);
|
pinMode(POWER_SUPPLY_CHECK_PIN, INPUT);
|
||||||
|
// Manual call, so we can set the initial state
|
||||||
|
powerStateChanged();
|
||||||
|
// Setup interrupt for power supply
|
||||||
|
attachInterrupt(POWER_SUPPLY_CHECK_PIN, []() { while (true); }, CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
void loop() {
|
void loop() {
|
||||||
// Find active arr pin
|
// Find active arr pin
|
||||||
int8_t active_key_group = getActiveKeyGroup();
|
char curr_arr = findCurrentArrPin();
|
||||||
|
|
||||||
// If none is active, we do nothing, else we check the keys
|
// If none is active, we do nothing, else we check the keys
|
||||||
if (active_key_group >= 0) {
|
if (curr_arr >= 0) {
|
||||||
// Get all the key values ans send the MIDI message if needed
|
// Get all the key values ans send the MIDI message if needed
|
||||||
uint8_t value;
|
unsigned char value;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < KEY_PINS; i++) {
|
for (unsigned char i = 0; i < KEY_PINS; i++) {
|
||||||
// due to the circuitry, there is one phantom note above
|
|
||||||
// the highest key constantly 'playing'
|
|
||||||
// but we don't need to scan that far anyway
|
|
||||||
if (active_key_group == KEY_GROUP_NUM-1 && i>0){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value = digitalReadFast(key_pins[i]);
|
value = digitalReadFast(key_pins[i]);
|
||||||
// If the key is pressed, we send a MIDI message and set the entry in the array
|
// If the key is pressed, we send a MIDI message and set the entry in the array
|
||||||
// ! inverted
|
// ! inverted
|
||||||
if (value == LOW) {
|
if (value == LOW) {
|
||||||
// Check if the key is not already pressed
|
// Check if the key is not already pressed
|
||||||
if (keys_pressed[active_key_group * 6 + i] >= DEBOUNCE_TIMES) {
|
if (keys_pressed[curr_arr * 6 + i] == 0) {
|
||||||
// Send MIDI message
|
// Send MIDI message
|
||||||
usbMIDI.sendNoteOn(mapToMidi(active_key_group, i), 127, 1);
|
usbMIDI.sendNoteOn(mapToMidi(curr_arr, i), 127, 1);
|
||||||
|
// Set the entry in the array
|
||||||
|
keys_pressed[curr_arr * 6 + i] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the entry in the array
|
|
||||||
keys_pressed[active_key_group * 6 + i] += keys_pressed[active_key_group * 6 + i] < 0xFF ? 1 : 0;
|
|
||||||
} else {
|
} else {
|
||||||
// Check if the key is not already released
|
// Check if the key is not already released
|
||||||
if (keys_pressed[active_key_group * 6 + i] < DEBOUNCE_TIMES) {
|
if (keys_pressed[curr_arr * 6 + i] == 1) {
|
||||||
// Send MIDI message
|
// Send MIDI message
|
||||||
usbMIDI.sendNoteOff(mapToMidi(active_key_group, i), 0, 1);
|
usbMIDI.sendNoteOff(mapToMidi(curr_arr, i), 0, 1);
|
||||||
|
// Set the entry in the array
|
||||||
|
keys_pressed[curr_arr * 6 + i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the entry in the array
|
|
||||||
keys_pressed[active_key_group * 6 + i] = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MIDI Controllers should discard incoming MIDI messages.
|
// MIDI Controllers should discard incoming MIDI messages.
|
||||||
while (usbMIDI.read()) {}
|
while (usbMIDI.read()) {
|
||||||
|
|
||||||
// switch to next key group, if self powered
|
|
||||||
if (digitalReadFast(POWER_SUPPLY_CHECK_PIN) == LOW) {
|
|
||||||
nextSelfDrivePin();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user