Adafruit.Projects/Feather-M4-Express_NeoTrell...

250 lines
5.7 KiB
C++

// include NeoTrellis library
#include <Adafruit_NeoTrellis.h>
// include SPI, MP3 and SD libraries
#include <SPI.h>
#include <SD.h>
#include <Adafruit_VS1053.h>
// Declare NeoTrellis constants
Adafruit_NeoTrellis trellis;
#define NT_INTERRUPT 11 // Interrupt pin needs to be unused by MusicMaker
#define MAX_RIPPLES 16
#define FALLOFF_TIME 30
#define FALLOFF (0xFF/FALLOFF_TIME)
#define NUM_POINTS 8
#define RIPPLE_RATE .4
#define MATRIX_POINT(x,y) ((y)*4+(x))
// Declare MusicMaker constants
#define MM_RESET -1 // VS1053 reset pin (not used!)
#define MM_CS 6 // VS1053 chip select pin (output)
#define MM_DCS 10 // VS1053 Data/command select pin (output)
#define MM_DREQ 9 // VS1053 Data request, ideally an Interrupt pin
#define SD_CARDCS 5 // Card chip select pin
// Declare Sketch-specific global variables
const char *ClipNames[4][12] = {
{
"DOIT.mp3",
"MAKEIT.mp3",
"WORKIT.mp3",
"",
"HARDER.mp3",
"BETTER.mp3",
"FASTER.mp3",
"STRONGER.mp3",
},
{
"CRICK.mp3",
"FAIL.mp3",
"BITEASS.mp3",
"MARIO.mp3",
"PADUM.mp3",
"PHONE.mp3",
"WINNER.mp3",
"WRONG.mp3"
},
{
"WRONG.mp3"
},
{
"WRONG.mp3"
}
};
const char *TrackNames[4][12] = {
{
"AA000001.mp3",
"AA000002.mp3"
}
};
uint32_t colors[] = {
0xFF0000, 0x00FF00, 0x0000FF,
0xFF00FF, 0x00FFFF, 0xFFFFFF
};
union color {
struct {
uint8_t blue:8;
uint8_t green:8;
uint8_t red:8;
} bit;
uint32_t reg;
};
color matrix[4][4];
struct point {
float x;
float y;
};
struct ripple {
int8_t center;
uint32_t t;
color c;
point points[NUM_POINTS];
};
static struct ripple ripples[MAX_RIPPLES];
//define a callback for key presses
TrellisCallback blink(keyEvent evt){
for(int i=0; i<MAX_RIPPLES; i++){
if(ripples[i].center == -1){
//create a new ripple here
ripples[i].center = evt.bit.NUM;
ripples[i].t = 0;
for(int j=0; j<NUM_POINTS; j++){
ripples[i].points[j].x = NEO_TRELLIS_X(evt.bit.NUM);
ripples[i].points[j].y = NEO_TRELLIS_Y(evt.bit.NUM);
}
ripples[i].c.reg = colors[random(sizeof(colors)/sizeof(uint32_t))];
break;
}
}
return 0;
}
// Create new instance of VS1053_FilePlayer
Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(MM_RESET, MM_CS, MM_DCS, MM_DREQ, SD_CARDCS);
void setup() {
Serial.begin(115200);
// Check availability of hardwarecomponents
if (!musicPlayer.begin() or !SD.begin(SD_CARDCS) or !trellis.begin()) {
Serial.println(F("Failed to initialize all hardwarecomponents (VS1053, Trellis or SD card)"));
while(1);
}
/*
// Leaving this here for reference purposes
musicPlayer.sineTest(0x44, 500);
*/
// Set volume for left, right channels. lower numbers == louder volume!
musicPlayer.setVolume(25,25);
musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT); // DREQ int
// Play a file in the background, REQUIRES interrupts!
musicPlayer.startPlayingFile("/TRACKS/AA000002.mp3");
pinMode(NT_INTERRUPT, INPUT);
randomSeed(analogRead(0));
for(int i=0; i<MAX_RIPPLES; i++)
ripples[i].center = -1;
//activate all keys and set callbacks
for(int i=0; i<NEO_TRELLIS_NUM_KEYS; i++){
trellis.activateKey(i, SEESAW_KEYPAD_EDGE_RISING);
trellis.registerCallback(i, blink);
}
//do a little animation to show we're on
for(uint16_t i=0; i<trellis.pixels.numPixels(); i++) {
trellis.pixels.setPixelColor(i, 0x0000FF);
trellis.pixels.show();
delay(50);
}
for(uint16_t i=0; i<trellis.pixels.numPixels(); i++) {
trellis.pixels.setPixelColor(i, 0x000000);
trellis.pixels.show();
delay(50);
}
}
void loop() {
if (Serial.available()) {
char c = Serial.read();
// if we get an 's' on the serial console, stop!
if (c == 's') {
musicPlayer.stopPlaying();
}
// if we get an 'p' on the serial console, pause/unpause!
if (c == 'p') {
if (! musicPlayer.paused()) {
Serial.println("Paused");
musicPlayer.pausePlaying(true);
} else {
Serial.println("Resumed");
musicPlayer.pausePlaying(false);
}
}
}
if(!digitalRead(NT_INTERRUPT)){
trellis.read(false);
}
processRipples();
delay(25);
}
void processRipples(){
for(int x=0; x<4; x++){
for(int y=0; y<4; y++)
matrix[x][y].reg = 0;
}
bool update = false;
for(int i=0; i<MAX_RIPPLES; i++){
if(ripples[i].center > -1){
update = true;
//push all points out from the center
point *p = ripples[i].points;
p[0].x += RIPPLE_RATE;
p[1].x += RIPPLE_RATE/2;
p[1].y += RIPPLE_RATE/2;
p[2].y += RIPPLE_RATE;
p[3].x -= RIPPLE_RATE/2;
p[3].y += RIPPLE_RATE/2;
p[4].x -= RIPPLE_RATE;
p[5].x -= RIPPLE_RATE/2;
p[5].y -= RIPPLE_RATE/2;
p[6].y -= RIPPLE_RATE;
p[7].x += RIPPLE_RATE/2;
p[7].y -= RIPPLE_RATE/2;
for(int j=0; j<NUM_POINTS; j++){
int x = round(p[j].x);
int y = round(p[j].y);
if(x < 4 && x >= 0 && y < 4 && y >= 0){
byte red = min(255, matrix[x][y].bit.red + ripples[i].c.bit.red);
byte green = min(255, matrix[x][y].bit.green + ripples[i].c.bit.green);
byte blue = min(255, matrix[x][y].bit.blue + ripples[i].c.bit.blue);
matrix[x][y].bit.red = red;
matrix[x][y].bit.green = green;
matrix[x][y].bit.blue = blue;
}
}
ripples[i].t++;
if(ripples[i].t >= FALLOFF_TIME) ripples[i].center = -1;
}
}
if(update){
for(int x=0; x<4; x++){
for(int y=0; y<4; y++)
trellis.pixels.setPixelColor(MATRIX_POINT(x,y), matrix[x][y].reg);
}
trellis.pixels.show();
}
}