VS1053 audio player with lcd and rotary encoder
Dependencies: LibMenu PinDetect SDFileSystem TextLCD VS1053lib mRotaryEncoder mbed
main.cpp
- Committer:
- ollie8
- Date:
- 2013-12-26
- Revision:
- 3:b6bf1e6d9cde
- Parent:
- 2:1c751f044ecd
File content as of revision 3:b6bf1e6d9cde:
#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 }; void select(MenuNode *node); void enterMenu(Menu *menu); void enterPausedMenu(Menu *menu); 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; Menu root(&enterMenu, &select, "ROOT", 5); Menu pausedMenu(&enterPausedMenu, &select, "PAUSED", 2); void select(MenuNode *node) { lcd.cls(); lcd.printf(node->getName()); } void cueNode(MenuNode *node) { currentfile = node->getName(); state = CUED; } void setVolume(MenuNode *node) { } void setBass(MenuNode *node) { } void setTreble(MenuNode *node) { } void continuePlay(MenuNode *node) { state = PLAYING; } void enterMenu(Menu *menu) { current = menu; } void enterPausedMenu(Menu *menu) { current = menu; state = PAUSED; } void cancelPlay(MenuNode *node) { state = IDLE; root.enter(); } void buttonPress() { switch (state) { case IDLE: case PAUSED: current->getSelectedNode().enter(); break; case CUED: // do nothing until we start playing; break; case PLAYING: pausedMenu.enter(); break; } } 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) { char * name = p->d_name; if (sizeof(name) > 0) { MenuNode *node = new MenuNode(&cueNode, &select, name); library->addMenuNode(*node); } } } else { lcd.printf("Could not open root directory!\n"); } closedir(d); } void setupMenu() { pc.printf("Building menus...\n\r"); buildLibrary(); 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); 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(); if (state == PLAYING) { pc.printf("\r\n"); if (val > 1) { volume -= 0x05; vs1053.setvolume(volume, volume); rot.Set(0); } else if (val < -1) { volume += 0x05; vs1053.setvolume(volume, volume); rot.Set(0); } } else if (state == IDLE || state == PAUSED) { if (val > 1) { current->up(); rot.Set(0); } else if (val < -1) { 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) { unsigned char buff[BUFFER_SIZE]; char abs[16]; strcpy(abs, "/sd/"); strcat(abs, currentfile); FILE *song = fopen(abs, "r"); if (song == NULL) { lcd.cls(); lcd.printf("File not found."); wait(1.5); root.enter(); } else { char* playtime = (char*) malloc(6); drawNowPlaying("00:00"); state = PLAYING; while(!feof(song)) { if (state == IDLE) { 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.cancelplayback(); vs1053.resetplaytime(); state = IDLE; root.enter(); } } } int main() { pc.printf("Starting...\n\r"); lcd.printf("Initialising..."); lcd.locate(0, 1); lcd.printf("O pod v0.2"); wait(1.0); vs1053.init(); vs1053.loadpatch(); rot.Set(0); rot.attachSW(&buttonPress); rot.attachROT(&control); setupMenu(); while (1) { checkCued(); } }