11#if 0 // Change to 1 to enable this code (must enable ONE user*.cpp only!)
22
3- // WIP DO NOT USE
4-
53#include "globals.h"
64#include <Servo.h>
75
86// Servo stuff
97Servo myservo;
108#define SERVO_MOUTH_OPEN 0
119#define SERVO_MOUTH_CLOSED 180
12- // TO DO: move servo when sound is playing.
13- // At end of WAV, move mouth to closed position.
10+ #define SERVO_PIN 3
11+
12+ #define BUTTON_PIN 2
1413
1514// WAV player stuff
16- #define WAV_BUFFER_SIZE 256
15+ #define WAV_BUFFER_SIZE 256
1716static uint8_t wavBuf[2][WAV_BUFFER_SIZE];
1817static File wavFile;
1918static bool playing = false;
@@ -22,6 +21,7 @@ static uint8_t activeBuf;
2221static uint16_t bufIdx, bufEnd, nextBufEnd;
2322static bool startWav(char *filename);
2423static void wavOutCallback(void);
24+ static uint32_t wavEventTime; // WAV start or end time, in ms
2525static const char *wav_path = "fizzgig";
2626static struct wavlist { // Linked list of WAV filenames
2727 char *filename;
@@ -58,23 +58,35 @@ void user_setup(void) {
5858 wavListPtr->next = wavListStart; // Point last item's next to list head (list is looped)
5959 wavListPtr = wavListStart; // Update list pointer to head
6060 }
61- myservo.attach(3);
6261}
6362
6463void user_loop(void) {
65- if(!playing && wavListPtr) {
66- pinMode(2, INPUT_PULLUP);
64+ if(playing) {
65+ // While WAV is playing, wiggle servo between middle and open-mouth positions:
66+ uint32_t elapsed = millis() - wavEventTime; // Time since audio start
67+ uint16_t frac = elapsed % 500; // 0 to 499 = 0.5 sec
68+ float n = 1.0 - ((float)abs(250 - frac) / 500.0); // Ramp 0.5, 1.0, 0.5 in 0.5 sec
69+ myservo.write((int)((float)SERVO_MOUTH_CLOSED + (float)(SERVO_MOUTH_OPEN - SERVO_MOUTH_CLOSED) * n));
70+ // BUTTON_PIN button is ignored while sound is playing.
71+ } else if(wavListPtr) {
72+ // Not currently playing WAV. Check for button press on pin BUTTON_PIN.
73+ pinMode(BUTTON_PIN, INPUT_PULLUP);
6774 delayMicroseconds(20); // Avoid boop code interference
68- if(!digitalRead(2 )) {
75+ if(!digitalRead(BUTTON_PIN )) {
6976 arcada.chdir(wav_path);
7077 startWav(wavListPtr->filename);
7178 wavListPtr = wavListPtr->next; // Will loop around from end to start of list
7279 }
80+ pinMode(BUTTON_PIN, INPUT);
81+ if(myservo.attached()) { // If servo still active (from recent WAV playing)
82+ myservo.write(SERVO_MOUTH_CLOSED); // Make sure it's in closed position
83+ // If it's been more than 1 sec since audio stopped,
84+ // deactivate the servo to reduce power, heat & noise.
85+ if((millis() - wavEventTime) > 1000) {
86+ myservo.detach();
87+ }
88+ }
7389 }
74-
75- // 'pos' will be determined periodically, maybe not every frame. TBD.
76- // needs to go to a closed position when WAV is finished.
77- // myservo.write(pos);
7890}
7991
8092static uint16_t readWaveData(uint8_t *dst) {
@@ -146,10 +158,12 @@ static bool startWav(char *filename) {
146158 analogWrite(A0, 128);
147159 analogWrite(A1, 128);
148160 arcada.enableSpeaker(true);
149- bufIdx = 0;
150- playing = true;
161+ wavEventTime = millis(); // WAV starting time
162+ bufIdx = 0;
163+ playing = true;
151164 arcada.timerCallback(buf.fmt.sampleRate, wavOutCallback);
152- nextBufEnd = readWaveData(wavBuf[1]);
165+ nextBufEnd = readWaveData(wavBuf[1]);
166+ myservo.attach(SERVO_PIN);
153167 }
154168 return true;
155169 } else {
@@ -175,7 +189,8 @@ static void wavOutCallback(void) {
175189 if(nextBufEnd <= 0) {
176190 arcada.timerStop();
177191 arcada.enableSpeaker(false);
178- playing = false;
192+ playing = false;
193+ wavEventTime = millis(); // Same var now holds WAV end time
179194 return;
180195 }
181196 bufIdx = 0;
0 commit comments