Skip to content

Commit b1c9995

Browse files
Merge pull request #850 from adafruit/philb-branch
Incorporate voice changer into M4_Eyes (off by default, performance r…
2 parents 0e1eaf4 + a24493b commit b1c9995

6 files changed

Lines changed: 457 additions & 8 deletions

File tree

M4_Eyes/M4_Eyes.ino

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ float iris_prev[IRIS_LEVELS] = { 0 };
6969
float iris_next[IRIS_LEVELS] = { 0 };
7070
uint16_t iris_frame = 0;
7171

72+
#if NUM_EYES > 1
73+
uint32_t priorButtonState;
74+
#endif
75+
7276
// Callback invoked after each SPI DMA transfer - sets a flag indicating
7377
// the next line of graphics can be issued as soon as its ready.
7478
static void dma_callback(Adafruit_ZeroDMA *dma) {
@@ -150,7 +154,7 @@ void setup() {
150154
seesaw.analogWrite(SEESAW_BACKLIGHT_PIN, 0);
151155
// Configure Seesaw pins 9,10,11 as inputs
152156
seesaw.pinModeBulk(0b111000000000, INPUT_PULLUP);
153-
uint32_t initialButtonState = seesaw.digitalReadBulk(0b111000000000);
157+
priorButtonState = seesaw.digitalReadBulk(0b111000000000);
154158
#endif
155159

156160
if(i == 1) fatal("Flash init fail", 100);
@@ -273,11 +277,11 @@ void setup() {
273277
// of the nose booper when doing this...it self-calibrates on startup.
274278
char *filename = "config.eye";
275279
#if NUM_EYES > 1 // Only available on MONSTER M4SK
276-
if(!(initialButtonState & 0b001000000000)) {
280+
if(!(priorButtonState & 0b001000000000)) {
277281
filename = "config1.eye";
278-
} else if(!(initialButtonState & 0b010000000000)) {
282+
} else if(!(priorButtonState & 0b010000000000)) {
279283
filename = "config2.eye";
280-
} else if(!(initialButtonState & 0b100000000000)) {
284+
} else if(!(priorButtonState & 0b100000000000)) {
281285
filename = "config3.eye";
282286
}
283287
#endif
@@ -414,6 +418,18 @@ void setup() {
414418
eye[e].eyeY = eyeOldY;
415419
}
416420

421+
#if defined(ADAFRUIT_MONSTER_M4SK_EXPRESS)
422+
if(voiceOn) {
423+
if(!voiceSetup()) {
424+
Serial.println("Voice init fail, continuing without");
425+
voiceOn = false;
426+
} else {
427+
currentPitch = voicePitch(currentPitch);
428+
digitalWrite(20, HIGH); // Speaker on
429+
}
430+
}
431+
#endif
432+
417433
user_setup();
418434

419435
lastLightReadTime = micros() + 2000000; // Delay initial light reading
@@ -901,6 +917,27 @@ void loop() {
901917
irisValue = irisMin + (sum * irisRange); // 0.0-1.0 -> iris min/max
902918
if((++iris_frame) >= (1 << IRIS_LEVELS)) iris_frame = 0;
903919
}
920+
#if defined(ADAFRUIT_MONSTER_M4SK_EXPRESS)
921+
if(voiceOn) {
922+
// Read buttons, change pitch
923+
uint32_t buttonState = seesaw.digitalReadBulk(0b111000000000); // Bits CLEAR if currently pressed
924+
uint32_t changedState = ~(buttonState ^ priorButtonState); // Bits CLEAR if changed from before
925+
uint32_t newlyPressed = ~(buttonState | changedState); // Bits SET if newly pressed
926+
if( newlyPressed & 0b001000000000) { // Seesaw pin 9 (inner)
927+
currentPitch *= 1.05;
928+
} else if(newlyPressed & 0b010000000000) { // Seesaw pin 10 (middle)
929+
currentPitch = defaultPitch;
930+
} else if(newlyPressed & 0b100000000000) { // Seesaw pin 11 (outer)
931+
currentPitch *= 0.95;
932+
}
933+
if(newlyPressed) {
934+
currentPitch = voicePitch(currentPitch);
935+
Serial.print("Voice pitch: ");
936+
Serial.println(currentPitch);
937+
}
938+
priorButtonState = buttonState;
939+
}
940+
#endif // ADAFRUIT_MONSTER_M4SK_EXPRESS
904941
user_loop();
905942
}
906943
} // end first-column check

M4_Eyes/file.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ void loadConfig(char *filename) {
372372
eye[e].rotation &= 3;
373373
}
374374
#endif
375+
#if defined(ADAFRUIT_MONSTER_M4SK_EXPRESS)
376+
v = doc["voice"];
377+
if(v.is<bool>()) voiceOn = v.as<bool>();
378+
currentPitch = defaultPitch = doc["pitch"] | defaultPitch;
379+
#endif // ADAFRUIT_MONSTER_M4SK_EXPRESS
375380
}
376381
file.close();
377382
} else {

M4_Eyes/globals.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ GLOBAL_VAR int8_t blinkPin GLOBAL_INIT(-1); // Manual both-eyes bl
8484
#endif
8585
GLOBAL_VAR uint32_t boopThreshold GLOBAL_INIT(17500);
8686

87+
#if defined(ADAFRUIT_MONSTER_M4SK_EXPRESS)
88+
GLOBAL_VAR bool voiceOn GLOBAL_INIT(false);
89+
GLOBAL_VAR float currentPitch GLOBAL_INIT(1.0);
90+
GLOBAL_VAR float defaultPitch GLOBAL_INIT(1.0);
91+
#endif
8792

8893
// EYE-RELATED STRUCTURES --------------------------------------------------
8994

@@ -207,6 +212,14 @@ extern uint32_t availableRAM(void);
207212
extern uint32_t availableNVM(void);
208213
extern uint8_t *writeDataToFlash(uint8_t *src, uint32_t len);
209214

215+
// Functions in pdmvoice.cpp
216+
#if defined(ADAFRUIT_MONSTER_M4SK_EXPRESS)
217+
extern bool voiceSetup(void);
218+
extern float voicePitch(float p);
219+
extern void voiceGain(float g);
220+
extern volatile uint16_t voiceLastReading;
221+
#endif // ADAFRUIT_MONSTER_M4SK_EXPRESS
222+
210223
// Functions in tablegen.cpp
211224
extern void calcDisplacement(void);
212225
extern void calcMap(void);

0 commit comments

Comments
 (0)