/*
https://github.com/schreibfaul1/ESP32-audioI2S/blob/master/examples/separate_audiotask/separate_audiotask.ino
board: ESP32 Devboard
This will not work with esp32 rev greater than 2.0.11
can't get dual core to work w/ 2 SPI devices so now will just use a pin to trigger a separate nano to start eye blink on radar signal.
switched to I2C led matrix instead of SPI.
Need to blend this with DualCore_HalloweenEyes_SD_I2s_debug.ino which has the basic funtionality working but missing triggers and radar.
radar rcwl-0516
*/
// libraries
#include "Audio.h"
#include "SD.h"
#include "FS.h"
#include "SPI.h"
#include <Adafruit_GFX.h>
#include <Wire.h>
#include "blinkImg.h"
#include "Adafruit_LEDBackpack.h"
// microSD Card Reader connections
#define SD_CS 5
#define SPI_MOSI 23
#define SPI_MISO 19
#define SPI_SCK 18
// I2S Connections Gain -> GND, VIN -> 3V3, SD is L-R Output Select (not used)
#define I2S_DOUT 22 //I2S DIN
#define I2S_BCLK 26
#define I2S_LRC 25
// Create Audio object
Audio audio;
// Radar Pin
#define RADAR_PIN 14
//Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
static const uint8_t matrixAddr = 0x70;
int8_t
eyeX = 3,
eyeY = 3, // Current eye position
newX = 3, newY = 3, // Next eye position
dX = 0, dY = 0; // Distance from prior to new position
uint8_t
blinkIndex[] = { 1, 2, 3, 4, 3, 2, 1 }, // Blink bitmap sequence
blinkCountdown = 100, // Countdown to next blink (in frames)
gazeCountdown = 75, // Countdown to next eye movement
gazeFrames = 50; // Duration of eye movement (smaller = faster)
bool radarDetected = false;
bool playFinished = true;
void radartask(void* parameter) {
for (;;) {
radarDetected = digitalRead(RADAR_PIN);
Serial.print("Radar: ");
Serial.println(radarDetected);
if (radarDetected && playFinished) {
playFinished = false; // prevent toggle of matrix until sound play is complete
//digitalWrite(MATRIX_TRIGGER, 1);
matrix.setBrightness(7);
}
// Draw eyeball in current state of blinkyness (no pupil). Note that
// only one eye needs to be drawn. Because the two eye matrices share
// the same address, the same data will be received by both.
matrix.clear();
matrix.drawBitmap(0, 0, blinkImg[(blinkCountdown < sizeof(blinkIndex)) ? /*Currently blinking? */ blinkIndex[blinkCountdown] /*Yes, look up bitmap # */ : 0 /* No, show bitmap 0 */], 8, 8, 1);
// Decrement blink counter. At end, set random time for next blink.
if (--blinkCountdown == 0) blinkCountdown = random(5, 180);
// Add a pupil (2x2 black square) atop the blinky eyeball bitmap.
// Periodically, the pupil moves to a new position...
// Serial.println(gazeCountdown);
if (--gazeCountdown <= gazeFrames) {
// Eyes are in motion - draw pupil at interim position
matrix.fillRect(
newX - (dX * gazeCountdown / gazeFrames),
newY - (dY * gazeCountdown / gazeFrames),
2, 2, 0);
if (gazeCountdown == 0) { // Last frame?
eyeX = newX;
eyeY = newY; // Yes. What's new is old, then...
do { // Pick random positions until one is within the eye circle
newX = random(7);
newY = random(7);
//Serial.println(newX);
dX = newX - 3;
dY = newY - 3;
} while ((dX * dX + dY * dY) >= 7); // Thank you Pythagoras
dX = newX - eyeX; // Horizontal distance to move
dY = newY - eyeY; // Vertical distance to move
gazeFrames = random(3, 15); // Duration of eye movement
gazeCountdown = random(gazeFrames, 120); // Count to end of next movement
}
} else {
// Not in motion yet -- draw pupil at current static position
matrix.fillRect(eyeX, eyeY, 2, 2, 0);
}
matrix.writeDisplay();
delay(40); // ~50 FPS
}
}
void radartaskinit() {
xTaskCreatePinnedToCore(
radartask, /* Function to implement the task */
"monitor radar", /* Name of the task */
5000, /* Stack size in words */
NULL, /* Task input parameter */
2 | portPRIVILEGE_BIT, /* Priority of the task */
NULL, /* Task handle. */
1 /* Core where the task should run */
);
}
void setup() {
Serial.begin(115200);
Serial.println("Setup started.");
// Options are: 240 (default), 160, 80, 40, 20 and 10 MHz
//setCpuFrequencyMhz(10);
//int cpuSpeed = getCpuFrequencyMhz();
//Serial.println("Running at " + String(cpuSpeed) + "MHz");
// Set microSD Card CS as OUTPUT and set HIGH
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
pinMode(RADAR_PIN, INPUT);
// Initialize SPI bus for microSD Card
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
// Start microSD Card
if (!SD.begin(SD_CS)) {
//if (!SD.begin()) {
Serial.println("Error accessing microSD card!");
while (true)
;
}
// Setup I2S
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
// Set Volume
audio.setVolume(15); //21 is max
// Initialize matrix:
Wire.begin(4, 15); //sda, scl
matrix.begin(matrixAddr);
matrix.setRotation(3);
matrix.setBrightness(7); // 0 to 15 range, 15 max
radartaskinit(); //start neopixel lightshow task
Serial.println("Setup completed.");
}
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
unsigned long interval = 1000;
int counter = 0;
bool startcount = false;
void loop() {
unsigned long currentMillis = millis();
audio.loop();
// play list of songs in parallel to the neopixel lightshow task
if (radarDetected && (audio.isRunning() != true)) {
Serial.println("sound start");
audio.connecttoFS(SD, "/HalloweenCompilation.mp3"); // test audio
playFinished = false;
// wait 30 sec to trigger sound complete
// start the counter
startcount = true;
}
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
// start 30 second counter when sound is triggered
if (startcount) {
counter++;
Serial.println(counter);
}
if (counter > 30) {
playFinished = true;
Serial.print("PlayFinished: ");
Serial.println(playFinished);
Serial.println("turn off Matrix");
//digitalWrite(MATRIX_TRIGGER, 0);
matrix.setBrightness(0);
startcount = false; // turn off counter until next trigger
counter = 0; // reset counter
}
}
}
void audio_id3data(const char* info) { //id3 metadata
Serial.print("id3data ");
Serial.println(info);
}