VS1053 audio player with lcd and rotary encoder

Dependencies:   LibMenu PinDetect SDFileSystem TextLCD VS1053lib mRotaryEncoder mbed

Files at this revision

API Documentation at this revision

Comitter:
ollie8
Date:
Tue Jun 18 17:01:22 2013 +0000
Parent:
0:389ef088650e
Child:
2:1c751f044ecd
Commit message:
Changed control to use interrupts. Added paused menu.

Changed in this revision

LibMenu.lib Show annotated file Show diff for this revision Revisions of this file
RPG.lib Show diff for this revision Revisions of this file
VS1053lib.lib Show annotated file Show diff for this revision Revisions of this file
mRotaryEncoder.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/LibMenu.lib	Wed May 29 13:15:22 2013 +0000
+++ b/LibMenu.lib	Tue Jun 18 17:01:22 2013 +0000
@@ -1,1 +1,1 @@
-LibMenu#3f4d33765f10
+http://mbed.org/users/ollie8/code/LibMenu/#7828182dbc9f
--- a/RPG.lib	Wed May 29 13:15:22 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/canderson199/code/RPG/#0b389c2c21b5
--- a/VS1053lib.lib	Wed May 29 13:15:22 2013 +0000
+++ b/VS1053lib.lib	Tue Jun 18 17:01:22 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/clemente/code/VS1053lib/#59076bd8a066
+http://mbed.org/users/clemente/code/VS1053lib/#59c27531f18e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mRotaryEncoder.lib	Tue Jun 18 17:01:22 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/charly/code/mRotaryEncoder/#75ddffaf3721
--- 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