VS1053 audio player with lcd and rotary encoder

Dependencies:   LibMenu PinDetect SDFileSystem TextLCD VS1053lib mRotaryEncoder mbed

Revision:
1:0040f640281c
Parent:
0:389ef088650e
Child:
2:1c751f044ecd
--- a/main.cpp	Wed May 29 13:15:22 2013 +0000
+++ b/main.cpp	Tue Jun 18 17:01:22 2013 +0000
@@ -2,9 +2,11 @@
 #include "SDFileSystem.h"
 #include "VLSIcodec.h"
 #include "TextLCD.h"
-#include "RPG.h"
 #include "Menu.h"
-#include "PinDetect.h"
+#include "mRotaryEncoder.h"
+
+#define BUFFER_SIZE 512
+#define MAX_BUF_WRITE 32
 
 enum PlayState {
     IDLE,
@@ -17,59 +19,71 @@
 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);
-RPG rpg(p21, p22, p23);
+mRotaryEncoder rot(p21, p22, p23);
 Serial pc(USBTX, USBRX);
 Menu *current;
 PlayState state = IDLE;
 char* currentfile;
-PinDetect  button(p23);
+char* lastPlaytime = (char*) malloc(6);
+unsigned char volume = 0x00;
 
-void select(MenuItem *item) {
+void select(MenuNode *node) {
     lcd.cls();
-    lcd.printf(item->getName());
-    pc.printf("Selected - %s\n\r", item->getName());
+    lcd.printf(node->getName());
+    pc.printf("Selected - %s\n\r", node->getName());
 }
 
-void cueItem(MenuItem *item) {
-    currentfile = item->getName();
+void cueNode(MenuNode *node) {
+    currentfile = node->getName();
     state = CUED;
-    pc.printf("Cueing menu item - %s\n\r", item->getName());
+    pc.printf("Cueing menu node - %s\n\r", node->getName());
 }
 
-void setVolume(MenuItem *item) {
+void setVolume(MenuNode *node) {
 
 }
 
-void setBass(MenuItem *item) {
+void setBass(MenuNode *node) {
  
 }
 
-void setTreble(MenuItem *item) {
+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->getItem(0).select();
 }
 
 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->selectedRow().enter();
+            current->getSelectedNode().enter();
         break;
         case CUED:
             // do nothing until we start playing;
             break;
         case PLAYING:
             state = PAUSED;
+            pausedMenu.enter();
         break;
         case PAUSED:
-            state = PLAYING;
+            current->getSelectedNode().enter();
         break;
     }
 }
@@ -80,19 +94,27 @@
     root.enter();
 }
 
-void buildLibrary(Menu *libmenu) {
+void buildLibrary() {
     DIR *d;
     struct dirent *p;
     d = opendir("/sd");
     if (d != NULL) {
+        int dircount = 0;
         while ((p = readdir(d)) != NULL) {
-            pc.printf("Makning item\n\r");
+            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) {
-                MenuItem *item = new MenuItem(&cueItem, &select, name);
-                pc.printf("Makning item done\n\r");
-                libmenu->addMenuItem(*item);
-                pc.printf("Item added\n\r");
+                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");            
@@ -107,54 +129,72 @@
 void setupMenu() {
     pc.printf("Building menus...\n\r");
     pc.printf("Menu size - %d\r\n", root.size());
-    Menu *library = new Menu(&enterMenu, &select, "Library", 6);
-    root.addMenuItem(*library);
-    buildLibrary(library);
+    buildLibrary();
     pc.printf("Menu size - %d\r\n", root.size());
     Menu *settings = new Menu(&enterMenu, &select, "Settings", 3);
-    root.addMenuItem(*settings);
+    root.addMenuNode(*settings);
     Menu *test = new Menu(&enterMenu, &select, "Test", 2);
-    root.addMenuItem(*test);
-    MenuItem *volume = new MenuItem(&setVolume, &select, "Volume");
-    settings->addMenuItem(*volume);
-    MenuItem *bass = new MenuItem(&setBass, &select, "Bass");
-    settings->addMenuItem(*bass);
-    MenuItem *treble = new MenuItem(&setTreble, &select, "Treble");
-    settings->addMenuItem(*treble);
+    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 checkControl() {
-/*    if (rpg.pb()) {
-        wait(0.5);
-        if (!rpg.pb()) {
-            pc.printf("button press on\n\r");
-            current->selectedRow().enter();        
-        } else {
-            wait(1.0);
-            if (rpg.pb()) {
-                root.enter();            
-            }
+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);
         }
-        wait(0.4);
-    } */
-    if (rpg.dir() > 0) {
-        wait(0.001);
-        pc.printf("forward\n\r");
-        current->up();      
-    } else if (rpg.dir() < 0) {
-        wait(0.001);
-        pc.printf("back\n\r");
-        current->down();
+        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[32];
+        unsigned char buff[BUFFER_SIZE];
         char abs[16];
         strcpy(abs, "/sd/");
         strcat(abs, currentfile);
@@ -166,28 +206,36 @@
             wait(1.5);
             root.enter();
         } else {
+            char* playtime = (char*) malloc(6);
             pc.printf("File open\n\r");
-            lcd.cls();
-            lcd.printf("Now playing:");
-            lcd.locate(0, 1);
-            lcd.printf(currentfile);
+            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) {
-                    if (vs1053.checkdreq()) {
-                        fread(&buff, 1, 32, song);
-                        //vs1053.testdreq();
-                        for (int i = 0; i < 32; i++) {
-                            vs1053.writedata(buff[i]);
+                    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;
+                                }
+                            }
                         }
-                    } else {
-                        // we have some free time so do something else
                     }
                 }
             }
             fclose(song);
+            vs1053.resetplaytime();
             state = IDLE;
             root.enter();
         }
@@ -198,17 +246,16 @@
     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();
-    button.mode(PullUp);
-    button.setAssertValue(0);
-    button.attach_asserted(&buttonPress);
-    button.attach_asserted_held(&buttonHeld);
-    button.setSampleFrequency();
+    rot.Set(0);
+    rot.attachSW(&buttonPress);
+    //rot.attachSWHeld(&buttonHeld);
+    rot.attachROT(&control);
     setupMenu();
     while (1) {
-        checkControl();
         checkCued();
     }
 }
\ No newline at end of file