Compare commits

..

No commits in common. "d563a4d497d99024b3a0e1cf7b9add83dab4d821" and "a2469f83c79801df17e011ca729b21bb84163cc6" have entirely different histories.

4 changed files with 64 additions and 44 deletions

View File

@ -51,6 +51,7 @@ void doPlay(bool forceDisplayUpdate) {
updateDisplay = true; updateDisplay = true;
} }
#if 0
if (updateDisplay) { if (updateDisplay) {
// Look up the note name // Look up the note name
const char *noteName = NoteName(pipe.CurrentNote); const char *noteName = NoteName(pipe.CurrentNote);
@ -68,4 +69,5 @@ void doPlay(bool forceDisplayUpdate) {
display.display(); display.display();
last_note = pipe.CurrentNote; last_note = pipe.CurrentNote;
} }
#endif
} }

View File

@ -17,7 +17,15 @@ bool Pipe::Init() {
return false; return false;
} }
// Knee sensor
if (!kneeSensor.begin()) {
return false;
}
// Bag button // 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();
return true; return true;
} }
@ -29,31 +37,29 @@ void Pipe::Update() {
Keys = 0; Keys = 0;
// Read the bag state, if there's a bag. // 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) { if (bag_enabled) {
// XXX: re-enable the bag sensor at some point Bag = bagSensor.isPressed();
//Bag = bagSensor.isPressed();
} else { } else {
Bag = false; Bag = false;
} }
for (int i = 0; i < NUM_KEYS; ++i) { // 0x6c is actually 8 bytes, but all 8 are always the same...
int key = KeySensor[i]; KneeClosedness = 255 - kneeSensor.readRange();
if (key == -1) {
continue;
}
for (int i = 0; i < NUM_KEYS; ++i) {
uint16_t sensorReading = capSensor.filteredData(i); uint16_t sensorReading = capSensor.filteredData(i);
uint16_t val = OPENVAL - min(max(sensorReading, CLOSEDVAL), OPENVAL); uint16_t val = OPENVAL - min(max(sensorReading, CLOSEDVAL), OPENVAL);
KeyPressure[key] = val / float(GLISSANDO_STEPS); KeyPressure[i] = val / float(GLISSANDO_STEPS);
// keys = all keys which are at least touched // keys = all keys which are at least touched
// glissandoKeys = all keys which are fully closed // glissandoKeys = all keys which are fully closed
// The glissando operation computes the difference. // The glissando operation computes the difference.
if (KeyPressure[key] > 0.0) { if (KeyPressure[i] > 0.0) {
bitSet(Keys, key); bitSet(Keys, i);
} }
if (KeyPressure[key] == 1.0) { if (KeyPressure[i] == 1.0) {
bitSet(glissandoKeys, key); bitSet(glissandoKeys, i);
} }
} }
@ -75,9 +81,6 @@ void Pipe::Update() {
// Was the high bit set? That indicates "alternate fingering", which sounds different. // Was the high bit set? That indicates "alternate fingering", which sounds different.
AltFingering = f.alt; AltFingering = f.alt;
// All keys closed + knee = no sound
Silent = ((KeyPressure[11] > 0) && (CurrentNote == NOTE_D4));
// If the bag is squished, jump up an octave // If the bag is squished, jump up an octave
// But only if the left thumb is down! // But only if the left thumb is down!
if (Bag && (Keys & bit(7))) { if (Bag && (Keys & bit(7))) {
@ -85,6 +88,8 @@ void Pipe::Update() {
GlissandoNote += NOTE_OCTAVE; GlissandoNote += NOTE_OCTAVE;
} }
// All keys closed + knee = no sound
Silent = ((KneeClosedness > 240) && (Keys == 0xff));
} }
bool Pipe::Pressed(uint8_t key) { bool Pipe::Pressed(uint8_t key) {

8
pipe.h
View File

@ -8,9 +8,6 @@
#define NUM_KEYS 12 #define NUM_KEYS 12
// A mapping of MPR121 input to pipe key
const int KeySensor[NUM_KEYS] = { 11, -1, 0, 1, 2, 3, 4, 5, 6, 7, -1, -1 };
enum Adjust { enum Adjust {
ADJUST_DOWN = -1, ADJUST_DOWN = -1,
ADJUST_NONE = 0, ADJUST_NONE = 0,
@ -20,6 +17,9 @@ enum Adjust {
class Pipe { class Pipe {
public: public:
// kneeClosedness indicates how "closed" the knee sensor is. 0 = wide open.
uint8_t KneeClosedness;
// keys are which keys are being pressed. // keys are which keys are being pressed.
uint16_t Keys; uint16_t Keys;
uint16_t KeysLast; uint16_t KeysLast;
@ -70,6 +70,8 @@ class Pipe {
private: private:
Adafruit_MPR121 capSensor; Adafruit_MPR121 capSensor;
Adafruit_VL6180X kneeSensor;
QwiicButton bagSensor;
bool bag_enabled; bool bag_enabled;
unsigned long nextRepeat[NUM_KEYS]; unsigned long nextRepeat[NUM_KEYS];
bool typematicEvent(uint8_t key, uint16_t delay, uint16_t repeat); bool typematicEvent(uint8_t key, uint16_t delay, uint16_t repeat);

View File

@ -11,14 +11,15 @@
const char *buildDate = __DATE__; const char *buildDate = __DATE__;
#if defined(ADAFRUIT_TRELLIS_MAdafruit_SSD1306EXPRESS)
#include <Adafruit_NeoTrellisM4.h> #include <Adafruit_NeoTrellisM4.h>
Adafruit_NeoTrellisM4 trellis = Adafruit_NeoTrellisM4(); Adafruit_NeoTrellisM4 trellis; // = Adafruit_NeoTrellisM4();
#endif
Pipe pipe; Pipe pipe;
Tuning tuning = Tuning(NOTE_D4, PITCH_CONCERT_D4, TUNINGSYSTEM_JUST); Tuning tuning = Tuning(NOTE_D4, PITCH_CONCERT_D4, TUNINGSYSTEM_JUST);
Adafruit_SSD1306 display(128, 32, &Wire, -1);
Adafruit_SSD1306 display(128, 32, &Wire, -1);
// Settings // Settings
#define VOLUME_INITIAL 0.8 #define VOLUME_INITIAL 0.8
@ -39,7 +40,13 @@ AudioMixer4 mixL;
AudioMixer4 mixR; AudioMixer4 mixR;
AudioSynthNoiseWhite noise; AudioSynthNoiseWhite noise;
#if defined(ADAFRUIT_TRELLIS_M4_EXPRESS)
AudioOutputAnalogStereo out1; AudioOutputAnalogStereo out1;
#else
AudioOutputI2S out1;
#endif
AudioControlSGTL5000 sgtl5000;
AudioConnection FMVoicePatchCords[] = { AudioConnection FMVoicePatchCords[] = {
{noise, 0, mixL, 3}, {noise, 0, mixL, 3},
@ -73,18 +80,15 @@ AudioConnection FMVoicePatchCords[] = {
FMVoiceWiring(Regulators[2]), FMVoiceWiring(Regulators[2]),
}; };
void blink(int count, bool forever) { void blink(bool forever) {
for (;;) { for (;;) {
for (int i = 0; i < count; i++) {
digitalWrite(LED_BUILTIN, true); digitalWrite(LED_BUILTIN, true);
delay(200); delay(200);
digitalWrite(LED_BUILTIN, false); digitalWrite(LED_BUILTIN, false);
delay(200); delay(200);
}
if (!forever) { if (!forever) {
return; return;
} }
delay(1200);
} }
} }
@ -135,30 +139,34 @@ void setup() {
// Initialize display // Initialize display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) {
blink(2, true); blink(true);
} }
digitalWrite(LED_BUILTIN, false); digitalWrite(LED_BUILTIN, false);
diag("Hello!"); diag("Hello!");
#if defined(ADAFRUIT_TRELLIS_M4_EXPRESS)
diag("Trellis..."); diag("Trellis...");
trellis.begin(); trellis.begin();
#endif
diag("Pipe..."); diag("Pipe...");
while (!pipe.Init()) { while (!pipe.Init()) {
diag("Pipe connected?"); diag("Pipe connected?");
blink(3, false); blink(false);
} }
diag("Audio..."); diag("Audio...");
AudioMemory(120); AudioMemory(120);
AudioProcessorUsageMaxReset(); AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset(); AudioMemoryUsageMaxReset();
sgtl5000.enable();
sgtl5000.volume(volume[4]);
diag("Synth..."); diag("Synth...");
loadPatch(0); loadPatch(0);
loadPatch(1); loadPatch(1);
loadPatch(2); loadPatch(2);
noise.amplitude(0.0); noise.amplitude(1.0);
diag("Mixer..."); diag("Mixer...");
// Turn on all mixer channels // Turn on all mixer channels
@ -208,20 +216,23 @@ void loop() {
static bool upSetting = true; // GET IT? static bool upSetting = true; // GET IT?
pipe.Update(); pipe.Update();
#if defined(ADAFRUIT_TRELLIS_M4_EXPRESS)
trellis.tick(); trellis.tick();
#endif
if (trellis.justPressed(0)) { // If we're infinitely (for the sensor) off the knee,
upSetting = !upSetting; // we might be in setup mode.
} if (pipe.KneeClosedness == 0) {
// We only enter into setup mode if no keys are pressed.
if (upSetting) { // This hopefully avoids accidentally entering setup while playing.
trellis.setPixelColor(0, 0x200000); // Like say you're playing a jaunty tune and suddenly there's an earthquake.
// You ought to be able to finish the tune off before your pipe goes into setup mode.
if (upSetting || (pipe.Keys == 0)) {
doSetup(); doSetup();
upSetting = true;
return; return;
} }
for (int i = 0; i < 12; i += 1) {
trellis.setPixelColor(i, 0xffffff * pipe.KeyPressure[i]);
} }
doPlay(upSetting); doPlay(upSetting);