Add 'Feather-M4-Express_NeoTrellis_Music-Maker-FeatherWing-w-Amp.ino'
This commit is contained in:
parent
52b7eec571
commit
82f1cc07d8
243
Feather-M4-Express_NeoTrellis_Music-Maker-FeatherWing-w-Amp.ino
Normal file
243
Feather-M4-Express_NeoTrellis_Music-Maker-FeatherWing-w-Amp.ino
Normal file
@ -0,0 +1,243 @@
|
||||
// include NeoTrellis library
|
||||
#include <Adafruit_NeoTrellis.h>
|
||||
// include SPI, MP3 and SD libraries
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
#include <Adafruit_VS1053.h>
|
||||
|
||||
// Set up NeoTrellis
|
||||
Adafruit_NeoTrellis trellis;
|
||||
#define INT_PIN 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))
|
||||
|
||||
// Set up MusicMaker
|
||||
#define VS1053_RESET -1 // VS1053 reset pin (not used!)
|
||||
#define VS1053_CS 6 // VS1053 chip select pin (output)
|
||||
#define VS1053_DCS 10 // VS1053 Data/command select pin (output)
|
||||
#define CARDCS 5 // Card chip select pin
|
||||
#define VS1053_DREQ 9 // VS1053 Data request, ideally an Interrupt pin
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Adafruit_VS1053_FilePlayer musicPlayer =
|
||||
Adafruit_VS1053_FilePlayer(VS1053_RESET, VS1053_CS, VS1053_DCS, VS1053_DREQ, CARDCS);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Wait for serial port to be opened, remove this line for 'standalone' operation
|
||||
while (!Serial) { delay(1); }
|
||||
delay(500);
|
||||
Serial.println("\n\nAdafruit VS1053 Feather Test");
|
||||
|
||||
if (! musicPlayer.begin()) { // initialise the music player
|
||||
Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
|
||||
while (1);
|
||||
}
|
||||
|
||||
Serial.println(F("VS1053 found"));
|
||||
|
||||
musicPlayer.sineTest(0x44, 500); // Make a tone to indicate VS1053 is working
|
||||
|
||||
if (!SD.begin(CARDCS)) {
|
||||
Serial.println(F("SD failed, or not present"));
|
||||
while (1); // don't do anything more
|
||||
}
|
||||
Serial.println("SD OK!");
|
||||
|
||||
// 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!
|
||||
/* Serial.println(F("Playing full track 001"));
|
||||
musicPlayer.playFullFile("/track001.mp3");
|
||||
*/
|
||||
Serial.println(F("Playing track 002"));
|
||||
musicPlayer.startPlayingFile("/track002.mp3");
|
||||
|
||||
pinMode(INT_PIN, INPUT);
|
||||
randomSeed(analogRead(0));
|
||||
|
||||
if(!trellis.begin()){
|
||||
Serial.println("could not start trellis");
|
||||
while(1);
|
||||
}
|
||||
else{
|
||||
Serial.println("trellis started");
|
||||
}
|
||||
|
||||
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() {
|
||||
Serial.print(".");
|
||||
// File is playing in the background
|
||||
if (musicPlayer.stopped()) {
|
||||
Serial.println("Done playing music");
|
||||
while (1) {
|
||||
delay(10); // we're done! do nothing...
|
||||
}
|
||||
}
|
||||
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(INT_PIN)){
|
||||
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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user