2020-11-11 20:20:21 -07:00
|
|
|
#include "pipe.h"
|
|
|
|
#include "fingering.h"
|
2020-11-24 21:33:55 -07:00
|
|
|
#include "tuning.h"
|
2020-11-11 20:20:21 -07:00
|
|
|
|
|
|
|
|
|
|
|
#define CLOSEDVAL 0x30
|
|
|
|
#define OPENVAL 0x70
|
|
|
|
#define GLISSANDO_STEPS (OPENVAL - CLOSEDVAL)
|
|
|
|
|
|
|
|
Pipe::Pipe() {
|
2020-11-24 21:33:55 -07:00
|
|
|
keysLast = 0;
|
2020-11-11 20:20:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Pipe::Init() {
|
2020-11-24 21:33:55 -07:00
|
|
|
// Capacative touch sensor
|
|
|
|
if (!capSensor.begin(0x5A)) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-11-11 20:20:21 -07:00
|
|
|
|
2020-11-24 21:33:55 -07:00
|
|
|
// Proximity sensor
|
|
|
|
if (paj7620Init()) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-11-11 20:20:21 -07:00
|
|
|
|
2020-11-24 21:33:55 -07:00
|
|
|
// Bag button
|
|
|
|
bagSensor.begin();
|
|
|
|
// This library takes the entire program out if you poll it 5-40 times without anything connected
|
|
|
|
bag_enabled = bagSensor.isConnected();
|
2020-11-11 20:20:21 -07:00
|
|
|
|
2020-11-24 21:33:55 -07:00
|
|
|
return true;
|
2020-11-11 20:20:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void Pipe::Update() {
|
2020-11-24 21:33:55 -07:00
|
|
|
uint8_t glissandoKeys = 0;
|
|
|
|
|
2020-11-25 17:13:54 -07:00
|
|
|
keysLast = keys;
|
|
|
|
keys = 0;
|
|
|
|
|
2020-11-24 21:33:55 -07:00
|
|
|
// Read the bag state, if there's a bag.
|
|
|
|
// if there isn't a bag, don't try, or this library will crash the program.
|
|
|
|
if (bag_enabled) {
|
|
|
|
bag = bagSensor.isPressed();
|
|
|
|
} else {
|
|
|
|
bag = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x6c is actually 8 bytes, but all 8 are always the same...
|
|
|
|
paj7620ReadReg(0x6c, 1, &kneeClosedness);
|
|
|
|
|
2020-11-25 21:53:45 -07:00
|
|
|
for (int i = 0; i < NUM_KEYS; ++i) {
|
2020-11-25 17:13:54 -07:00
|
|
|
uint16_t val = max(capSensor.filteredData(i), CLOSEDVAL);
|
2020-11-25 21:53:45 -07:00
|
|
|
keyOpen[i] = ((val - CLOSEDVAL) / float(GLISSANDO_STEPS));
|
2020-11-24 21:33:55 -07:00
|
|
|
|
|
|
|
// keys = all keys which are at least touched
|
|
|
|
// glissandoKeys = all keys which are fully closed
|
|
|
|
// The glissando operation computes the difference.
|
2020-11-25 21:53:45 -07:00
|
|
|
if (keyOpen[i] < 1.0) {
|
|
|
|
glissandoOpenness = max(glissandoOpenness, keyOpen[i]);
|
2020-11-24 21:33:55 -07:00
|
|
|
bitSet(keys, i);
|
2020-11-11 20:20:21 -07:00
|
|
|
}
|
2020-11-25 21:53:45 -07:00
|
|
|
if (keyOpen[i] == 0.0) {
|
2020-11-24 21:33:55 -07:00
|
|
|
bitSet(glissandoKeys, i);
|
2020-11-11 20:20:21 -07:00
|
|
|
}
|
2020-11-24 21:33:55 -07:00
|
|
|
}
|
2020-11-11 20:20:21 -07:00
|
|
|
|
2020-11-25 21:53:45 -07:00
|
|
|
// Compute glissando amount
|
|
|
|
glissandoOpenness = 0.0;
|
|
|
|
for (int i = 0; i < 8; ++i) {
|
|
|
|
glissandoOpenness = max(glissandoOpenness, keyOpen[i]);
|
|
|
|
}
|
|
|
|
|
2020-11-24 21:33:55 -07:00
|
|
|
// Look up notes in the big table
|
2020-11-25 17:13:54 -07:00
|
|
|
struct Fingering f = FingeredNote(keys);
|
|
|
|
struct Fingering gf = FingeredNote(glissandoKeys);
|
2020-11-11 20:20:21 -07:00
|
|
|
|
2020-11-24 21:33:55 -07:00
|
|
|
note = f.note;
|
|
|
|
glissandoNote = gf.note;
|
2020-11-11 20:20:21 -07:00
|
|
|
|
2020-11-24 21:33:55 -07:00
|
|
|
// Was the high bit set? That indicates "alternate fingering", which sounds different.
|
|
|
|
altFingering = f.alt;
|
2020-11-11 20:20:21 -07:00
|
|
|
|
2020-11-24 21:33:55 -07:00
|
|
|
// If the bag is squished, jump up an octave
|
|
|
|
// But only if the left thumb is down!
|
|
|
|
if (bag && (keys & bit(7))) {
|
|
|
|
note += NOTE_OCTAVE;
|
|
|
|
glissandoNote += NOTE_OCTAVE;
|
|
|
|
}
|
2020-11-11 20:20:21 -07:00
|
|
|
|
2020-11-24 21:33:55 -07:00
|
|
|
// All keys closed + knee = no sound
|
|
|
|
silent = ((kneeClosedness > 240) && (keys == 0xff));
|
2020-11-11 20:20:21 -07:00
|
|
|
}
|
2020-11-24 16:56:58 -07:00
|
|
|
|
|
|
|
bool Pipe::Pressed(uint8_t key) {
|
2020-11-24 21:33:55 -07:00
|
|
|
return bitRead(keys, key);
|
2020-11-24 16:56:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Pipe::JustPressed(uint8_t key) {
|
2020-11-24 21:33:55 -07:00
|
|
|
if (bitRead(keys, key)) {
|
|
|
|
return !bitRead(keysLast, key);
|
|
|
|
}
|
|
|
|
return false;
|
2020-11-24 16:56:58 -07:00
|
|
|
}
|
2020-11-25 17:13:54 -07:00
|
|
|
|
|
|
|
bool Pipe::typematicEvent(uint8_t key, uint16_t delay, uint16_t repeat) {
|
|
|
|
if (Pressed(key)) {
|
|
|
|
unsigned long now = millis();
|
|
|
|
|
|
|
|
if (JustPressed(key)) {
|
|
|
|
nextRepeat[key] = now + max(delay, repeat);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (now >= nextRepeat[key]) {
|
|
|
|
nextRepeat[key] = now + repeat;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Adjust Pipe::ReadAdjust(uint8_t keyUp, uint8_t keyDown, uint16_t delay, uint16_t repeat) {
|
|
|
|
bool eventUp = typematicEvent(keyUp, delay, repeat);
|
|
|
|
bool eventDown = typematicEvent(keyDown, delay, repeat);
|
|
|
|
|
|
|
|
if (Pressed(keyUp) && Pressed(keyDown)) {
|
|
|
|
unsigned long nr = max(nextRepeat[keyUp], nextRepeat[keyDown]);
|
|
|
|
|
|
|
|
nextRepeat[keyUp] = nr;
|
|
|
|
nextRepeat[keyDown] = nr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eventUp && eventDown) {
|
|
|
|
return ADJUST_BOTH;
|
|
|
|
} else if (eventUp) {
|
|
|
|
return ADJUST_UP;
|
|
|
|
} else if (eventDown) {
|
|
|
|
return ADJUST_DOWN;
|
|
|
|
}
|
|
|
|
return ADJUST_NONE;
|
|
|
|
}
|