VS1053 audio player with lcd and rotary encoder
Dependencies: LibMenu PinDetect SDFileSystem TextLCD VS1053lib mRotaryEncoder mbed
main.cpp
- Committer:
- ollie8
- Date:
- 2013-06-18
- Revision:
- 1:0040f640281c
- Parent:
- 0:389ef088650e
- Child:
- 2:1c751f044ecd
File content as of revision 1:0040f640281c:
#include "mbed.h" #include "SDFileSystem.h" #include "VLSIcodec.h" #include "TextLCD.h" #include "Menu.h" #include "mRotaryEncoder.h" #define BUFFER_SIZE 512 #define MAX_BUF_WRITE 32 enum PlayState { IDLE, CUED, PLAYING, PAUSED }; TextLCD lcd(p24, p25, p26, p27, p28, p29); SDFileSystem sd(p5, p6, p7, p8, "sd"); // PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dreq, PinName rst, PinName xdcs VS1053Codec vs1053(p11, p12, p13, p14, p15, p17, p16); mRotaryEncoder rot(p21, p22, p23); Serial pc(USBTX, USBRX); Menu *current; PlayState state = IDLE; char* currentfile; char* lastPlaytime = (char*) malloc(6); unsigned char volume = 0x00; void select(MenuNode *node) { lcd.cls(); lcd.printf(node->getName()); pc.printf("Selected - %s\n\r", node->getName()); } void cueNode(MenuNode *node) { currentfile = node->getName(); state = CUED; pc.printf("Cueing menu node - %s\n\r", node->getName()); } void setVolume(MenuNode *node) { } void setBass(MenuNode *node) { } void setTreble(MenuNode *node) { } void continuePlay(MenuNode *node) { state = PLAYING; } void enterMenu(Menu *menu) { current = menu; pc.printf("Entered menu - %s\n\r", menu->getName()); } Menu root(&enterMenu, &select, "ROOT", 5); Menu pausedMenu(&enterMenu, &select, "PAUSED", 2); void cancelPlay(MenuNode *node) { state = IDLE; root.enter(); } void buttonPress() { pc.printf("Button press"); switch (state) { case IDLE: current->getSelectedNode().enter(); break; case CUED: // do nothing until we start playing; break; case PLAYING: state = PAUSED; pausedMenu.enter(); break; case PAUSED: current->getSelectedNode().enter(); break; } } void buttonHeld() { pc.printf("Button held"); state = IDLE; root.enter(); } void buildLibrary() { DIR *d; struct dirent *p; d = opendir("/sd"); if (d != NULL) { int dircount = 0; while ((p = readdir(d)) != NULL) { dircount++; } closedir(d); Menu *library = new Menu(&enterMenu, &select, "Library", dircount); root.addMenuNode(*library); d = opendir("/sd"); while ((p = readdir(d)) != NULL) { pc.printf("Makning node\n\r"); char * name = p->d_name; if (sizeof(name) > 0) { MenuNode *node = new MenuNode(&cueNode, &select, name); pc.printf("Makning node done\n\r"); library->addMenuNode(*node); pc.printf("Node added\n\r"); pc.printf(" - %s\n\r", name); } else { pc.printf("BLANK NAME"); } } } else { pc.printf("Could not open directory!\n"); } closedir(d); } void setupMenu() { pc.printf("Building menus...\n\r"); pc.printf("Menu size - %d\r\n", root.size()); buildLibrary(); pc.printf("Menu size - %d\r\n", root.size()); Menu *settings = new Menu(&enterMenu, &select, "Settings", 3); root.addMenuNode(*settings); Menu *test = new Menu(&enterMenu, &select, "Test", 2); root.addMenuNode(*test); MenuNode *volume = new MenuNode(&setVolume, &select, "Volume"); settings->addMenuNode(*volume); MenuNode *bass = new MenuNode(&setBass, &select, "Bass"); settings->addMenuNode(*bass); MenuNode *treble = new MenuNode(&setTreble, &select, "Treble"); settings->addMenuNode(*treble); pc.printf("Menu size - %d\r\n", root.size()); MenuNode *contPlay = new MenuNode(&continuePlay, &select, "Continue"); MenuNode *cancPlay = new MenuNode(&cancelPlay, &select, "Cancel"); pausedMenu.addMenuNode(*contPlay); pausedMenu.addMenuNode(*cancPlay); root.enter(); pc.printf("Done.\n\r"); } void control() { int val = rot.Get(); pc.printf("Enc val - %d", val); if (state == PLAYING) { pc.printf("\r\n"); if (val > 1) { pc.printf("Going up...\r\n"); volume -= 0x05; rot.Set(0); } else if (val < -1) { pc.printf("Going down...\r\n"); volume += 0x05; rot.Set(0); } pc.printf("Setting volume - %d", volume); vs1053.setvolume(volume, volume); } else if (state == IDLE || state == PAUSED) { if (val > 1) { pc.printf("forward\n\r"); current->up(); rot.Set(0); } else if (val < -1) { pc.printf("back\n\r"); current->down(); rot.Set(0); } } } void drawNowPlaying(char* playtime) { if (strcmp(playtime, lastPlaytime) != 0) { lcd.cls(); lcd.printf("Playing:"); lcd.locate(11, 0); lcd.printf(playtime); lcd.locate(0, 1); lcd.printf(currentfile); strcpy(lastPlaytime, playtime); } } void checkCued() { if (state == CUED) { pc.printf("Opening file %s\n\r", currentfile); unsigned char buff[BUFFER_SIZE]; char abs[16]; strcpy(abs, "/sd/"); strcat(abs, currentfile); FILE *song = fopen(abs, "r"); if (song == NULL) { pc.printf("Cannot find file\n\r"); lcd.cls(); lcd.printf("File not found."); wait(1.5); root.enter(); } else { char* playtime = (char*) malloc(6); pc.printf("File open\n\r"); drawNowPlaying("00:00"); state = PLAYING; while(!feof(song)) { if (state == IDLE) { // empty the buffer on the VS1053 then break out of the loop // TODO add cancel play methos to vs1053 lib break; } else if (state == PLAYING) { fread(&buff, 1, BUFFER_SIZE, song); int i= 0; while (i < BUFFER_SIZE) { vs1053.writedata(buff[i++]); if (i % MAX_BUF_WRITE == 0) { bool checkPlaytime = true; while (!vs1053.checkdreq()) { if (checkPlaytime) { vs1053.getplaytime(playtime); playtime[5] = NULL; drawNowPlaying(playtime); checkPlaytime = false; } } } } } } fclose(song); vs1053.resetplaytime(); state = IDLE; root.enter(); } } } int main() { lcd.printf("Initialising..."); lcd.locate(0, 1); lcd.printf("O pod v0.1"); wait(1.0); pc.printf("Starting...\n\r"); vs1053.init(); vs1053.loadpatch(); rot.Set(0); rot.attachSW(&buttonPress); //rot.attachSWHeld(&buttonHeld); rot.attachROT(&control); setupMenu(); while (1) { checkCued(); } }