VS1053 audio player with lcd and rotary encoder
Dependencies: LibMenu PinDetect SDFileSystem TextLCD VS1053lib mRotaryEncoder mbed
main.cpp@0:389ef088650e, 2013-05-29 (annotated)
- Committer:
- ollie8
- Date:
- Wed May 29 13:15:22 2013 +0000
- Revision:
- 0:389ef088650e
- Child:
- 1:0040f640281c
Check in of vs1053 player
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ollie8 | 0:389ef088650e | 1 | #include "mbed.h" |
ollie8 | 0:389ef088650e | 2 | #include "SDFileSystem.h" |
ollie8 | 0:389ef088650e | 3 | #include "VLSIcodec.h" |
ollie8 | 0:389ef088650e | 4 | #include "TextLCD.h" |
ollie8 | 0:389ef088650e | 5 | #include "RPG.h" |
ollie8 | 0:389ef088650e | 6 | #include "Menu.h" |
ollie8 | 0:389ef088650e | 7 | #include "PinDetect.h" |
ollie8 | 0:389ef088650e | 8 | |
ollie8 | 0:389ef088650e | 9 | enum PlayState { |
ollie8 | 0:389ef088650e | 10 | IDLE, |
ollie8 | 0:389ef088650e | 11 | CUED, |
ollie8 | 0:389ef088650e | 12 | PLAYING, |
ollie8 | 0:389ef088650e | 13 | PAUSED |
ollie8 | 0:389ef088650e | 14 | }; |
ollie8 | 0:389ef088650e | 15 | |
ollie8 | 0:389ef088650e | 16 | TextLCD lcd(p24, p25, p26, p27, p28, p29); |
ollie8 | 0:389ef088650e | 17 | SDFileSystem sd(p5, p6, p7, p8, "sd"); |
ollie8 | 0:389ef088650e | 18 | // PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dreq, PinName rst, PinName xdcs |
ollie8 | 0:389ef088650e | 19 | VS1053Codec vs1053(p11, p12, p13, p14, p15, p17, p16); |
ollie8 | 0:389ef088650e | 20 | RPG rpg(p21, p22, p23); |
ollie8 | 0:389ef088650e | 21 | Serial pc(USBTX, USBRX); |
ollie8 | 0:389ef088650e | 22 | Menu *current; |
ollie8 | 0:389ef088650e | 23 | PlayState state = IDLE; |
ollie8 | 0:389ef088650e | 24 | char* currentfile; |
ollie8 | 0:389ef088650e | 25 | PinDetect button(p23); |
ollie8 | 0:389ef088650e | 26 | |
ollie8 | 0:389ef088650e | 27 | void select(MenuItem *item) { |
ollie8 | 0:389ef088650e | 28 | lcd.cls(); |
ollie8 | 0:389ef088650e | 29 | lcd.printf(item->getName()); |
ollie8 | 0:389ef088650e | 30 | pc.printf("Selected - %s\n\r", item->getName()); |
ollie8 | 0:389ef088650e | 31 | } |
ollie8 | 0:389ef088650e | 32 | |
ollie8 | 0:389ef088650e | 33 | void cueItem(MenuItem *item) { |
ollie8 | 0:389ef088650e | 34 | currentfile = item->getName(); |
ollie8 | 0:389ef088650e | 35 | state = CUED; |
ollie8 | 0:389ef088650e | 36 | pc.printf("Cueing menu item - %s\n\r", item->getName()); |
ollie8 | 0:389ef088650e | 37 | } |
ollie8 | 0:389ef088650e | 38 | |
ollie8 | 0:389ef088650e | 39 | void setVolume(MenuItem *item) { |
ollie8 | 0:389ef088650e | 40 | |
ollie8 | 0:389ef088650e | 41 | } |
ollie8 | 0:389ef088650e | 42 | |
ollie8 | 0:389ef088650e | 43 | void setBass(MenuItem *item) { |
ollie8 | 0:389ef088650e | 44 | |
ollie8 | 0:389ef088650e | 45 | } |
ollie8 | 0:389ef088650e | 46 | |
ollie8 | 0:389ef088650e | 47 | void setTreble(MenuItem *item) { |
ollie8 | 0:389ef088650e | 48 | |
ollie8 | 0:389ef088650e | 49 | } |
ollie8 | 0:389ef088650e | 50 | |
ollie8 | 0:389ef088650e | 51 | void enterMenu(Menu *menu) { |
ollie8 | 0:389ef088650e | 52 | current = menu; |
ollie8 | 0:389ef088650e | 53 | pc.printf("Entered menu - %s\n\r", menu->getName()); |
ollie8 | 0:389ef088650e | 54 | menu->getItem(0).select(); |
ollie8 | 0:389ef088650e | 55 | } |
ollie8 | 0:389ef088650e | 56 | |
ollie8 | 0:389ef088650e | 57 | Menu root(&enterMenu, &select, "ROOT", 5); |
ollie8 | 0:389ef088650e | 58 | |
ollie8 | 0:389ef088650e | 59 | void buttonPress() { |
ollie8 | 0:389ef088650e | 60 | pc.printf("Button press"); |
ollie8 | 0:389ef088650e | 61 | switch (state) { |
ollie8 | 0:389ef088650e | 62 | case IDLE: |
ollie8 | 0:389ef088650e | 63 | current->selectedRow().enter(); |
ollie8 | 0:389ef088650e | 64 | break; |
ollie8 | 0:389ef088650e | 65 | case CUED: |
ollie8 | 0:389ef088650e | 66 | // do nothing until we start playing; |
ollie8 | 0:389ef088650e | 67 | break; |
ollie8 | 0:389ef088650e | 68 | case PLAYING: |
ollie8 | 0:389ef088650e | 69 | state = PAUSED; |
ollie8 | 0:389ef088650e | 70 | break; |
ollie8 | 0:389ef088650e | 71 | case PAUSED: |
ollie8 | 0:389ef088650e | 72 | state = PLAYING; |
ollie8 | 0:389ef088650e | 73 | break; |
ollie8 | 0:389ef088650e | 74 | } |
ollie8 | 0:389ef088650e | 75 | } |
ollie8 | 0:389ef088650e | 76 | |
ollie8 | 0:389ef088650e | 77 | void buttonHeld() { |
ollie8 | 0:389ef088650e | 78 | pc.printf("Button held"); |
ollie8 | 0:389ef088650e | 79 | state = IDLE; |
ollie8 | 0:389ef088650e | 80 | root.enter(); |
ollie8 | 0:389ef088650e | 81 | } |
ollie8 | 0:389ef088650e | 82 | |
ollie8 | 0:389ef088650e | 83 | void buildLibrary(Menu *libmenu) { |
ollie8 | 0:389ef088650e | 84 | DIR *d; |
ollie8 | 0:389ef088650e | 85 | struct dirent *p; |
ollie8 | 0:389ef088650e | 86 | d = opendir("/sd"); |
ollie8 | 0:389ef088650e | 87 | if (d != NULL) { |
ollie8 | 0:389ef088650e | 88 | while ((p = readdir(d)) != NULL) { |
ollie8 | 0:389ef088650e | 89 | pc.printf("Makning item\n\r"); |
ollie8 | 0:389ef088650e | 90 | char * name = p->d_name; |
ollie8 | 0:389ef088650e | 91 | if (sizeof(name) > 0) { |
ollie8 | 0:389ef088650e | 92 | MenuItem *item = new MenuItem(&cueItem, &select, name); |
ollie8 | 0:389ef088650e | 93 | pc.printf("Makning item done\n\r"); |
ollie8 | 0:389ef088650e | 94 | libmenu->addMenuItem(*item); |
ollie8 | 0:389ef088650e | 95 | pc.printf("Item added\n\r"); |
ollie8 | 0:389ef088650e | 96 | pc.printf(" - %s\n\r", name); |
ollie8 | 0:389ef088650e | 97 | } else { |
ollie8 | 0:389ef088650e | 98 | pc.printf("BLANK NAME"); |
ollie8 | 0:389ef088650e | 99 | } |
ollie8 | 0:389ef088650e | 100 | } |
ollie8 | 0:389ef088650e | 101 | } else { |
ollie8 | 0:389ef088650e | 102 | pc.printf("Could not open directory!\n"); |
ollie8 | 0:389ef088650e | 103 | } |
ollie8 | 0:389ef088650e | 104 | closedir(d); |
ollie8 | 0:389ef088650e | 105 | } |
ollie8 | 0:389ef088650e | 106 | |
ollie8 | 0:389ef088650e | 107 | void setupMenu() { |
ollie8 | 0:389ef088650e | 108 | pc.printf("Building menus...\n\r"); |
ollie8 | 0:389ef088650e | 109 | pc.printf("Menu size - %d\r\n", root.size()); |
ollie8 | 0:389ef088650e | 110 | Menu *library = new Menu(&enterMenu, &select, "Library", 6); |
ollie8 | 0:389ef088650e | 111 | root.addMenuItem(*library); |
ollie8 | 0:389ef088650e | 112 | buildLibrary(library); |
ollie8 | 0:389ef088650e | 113 | pc.printf("Menu size - %d\r\n", root.size()); |
ollie8 | 0:389ef088650e | 114 | Menu *settings = new Menu(&enterMenu, &select, "Settings", 3); |
ollie8 | 0:389ef088650e | 115 | root.addMenuItem(*settings); |
ollie8 | 0:389ef088650e | 116 | Menu *test = new Menu(&enterMenu, &select, "Test", 2); |
ollie8 | 0:389ef088650e | 117 | root.addMenuItem(*test); |
ollie8 | 0:389ef088650e | 118 | MenuItem *volume = new MenuItem(&setVolume, &select, "Volume"); |
ollie8 | 0:389ef088650e | 119 | settings->addMenuItem(*volume); |
ollie8 | 0:389ef088650e | 120 | MenuItem *bass = new MenuItem(&setBass, &select, "Bass"); |
ollie8 | 0:389ef088650e | 121 | settings->addMenuItem(*bass); |
ollie8 | 0:389ef088650e | 122 | MenuItem *treble = new MenuItem(&setTreble, &select, "Treble"); |
ollie8 | 0:389ef088650e | 123 | settings->addMenuItem(*treble); |
ollie8 | 0:389ef088650e | 124 | pc.printf("Menu size - %d\r\n", root.size()); |
ollie8 | 0:389ef088650e | 125 | root.enter(); |
ollie8 | 0:389ef088650e | 126 | pc.printf("Done.\n\r"); |
ollie8 | 0:389ef088650e | 127 | } |
ollie8 | 0:389ef088650e | 128 | |
ollie8 | 0:389ef088650e | 129 | void checkControl() { |
ollie8 | 0:389ef088650e | 130 | /* if (rpg.pb()) { |
ollie8 | 0:389ef088650e | 131 | wait(0.5); |
ollie8 | 0:389ef088650e | 132 | if (!rpg.pb()) { |
ollie8 | 0:389ef088650e | 133 | pc.printf("button press on\n\r"); |
ollie8 | 0:389ef088650e | 134 | current->selectedRow().enter(); |
ollie8 | 0:389ef088650e | 135 | } else { |
ollie8 | 0:389ef088650e | 136 | wait(1.0); |
ollie8 | 0:389ef088650e | 137 | if (rpg.pb()) { |
ollie8 | 0:389ef088650e | 138 | root.enter(); |
ollie8 | 0:389ef088650e | 139 | } |
ollie8 | 0:389ef088650e | 140 | } |
ollie8 | 0:389ef088650e | 141 | wait(0.4); |
ollie8 | 0:389ef088650e | 142 | } */ |
ollie8 | 0:389ef088650e | 143 | if (rpg.dir() > 0) { |
ollie8 | 0:389ef088650e | 144 | wait(0.001); |
ollie8 | 0:389ef088650e | 145 | pc.printf("forward\n\r"); |
ollie8 | 0:389ef088650e | 146 | current->up(); |
ollie8 | 0:389ef088650e | 147 | } else if (rpg.dir() < 0) { |
ollie8 | 0:389ef088650e | 148 | wait(0.001); |
ollie8 | 0:389ef088650e | 149 | pc.printf("back\n\r"); |
ollie8 | 0:389ef088650e | 150 | current->down(); |
ollie8 | 0:389ef088650e | 151 | } |
ollie8 | 0:389ef088650e | 152 | } |
ollie8 | 0:389ef088650e | 153 | |
ollie8 | 0:389ef088650e | 154 | void checkCued() { |
ollie8 | 0:389ef088650e | 155 | if (state == CUED) { |
ollie8 | 0:389ef088650e | 156 | pc.printf("Opening file %s\n\r", currentfile); |
ollie8 | 0:389ef088650e | 157 | unsigned char buff[32]; |
ollie8 | 0:389ef088650e | 158 | char abs[16]; |
ollie8 | 0:389ef088650e | 159 | strcpy(abs, "/sd/"); |
ollie8 | 0:389ef088650e | 160 | strcat(abs, currentfile); |
ollie8 | 0:389ef088650e | 161 | FILE *song = fopen(abs, "r"); |
ollie8 | 0:389ef088650e | 162 | if (song == NULL) { |
ollie8 | 0:389ef088650e | 163 | pc.printf("Cannot find file\n\r"); |
ollie8 | 0:389ef088650e | 164 | lcd.cls(); |
ollie8 | 0:389ef088650e | 165 | lcd.printf("File not found."); |
ollie8 | 0:389ef088650e | 166 | wait(1.5); |
ollie8 | 0:389ef088650e | 167 | root.enter(); |
ollie8 | 0:389ef088650e | 168 | } else { |
ollie8 | 0:389ef088650e | 169 | pc.printf("File open\n\r"); |
ollie8 | 0:389ef088650e | 170 | lcd.cls(); |
ollie8 | 0:389ef088650e | 171 | lcd.printf("Now playing:"); |
ollie8 | 0:389ef088650e | 172 | lcd.locate(0, 1); |
ollie8 | 0:389ef088650e | 173 | lcd.printf(currentfile); |
ollie8 | 0:389ef088650e | 174 | state = PLAYING; |
ollie8 | 0:389ef088650e | 175 | while(!feof(song)) { |
ollie8 | 0:389ef088650e | 176 | if (state == IDLE) { |
ollie8 | 0:389ef088650e | 177 | break; |
ollie8 | 0:389ef088650e | 178 | } else if (state == PLAYING) { |
ollie8 | 0:389ef088650e | 179 | if (vs1053.checkdreq()) { |
ollie8 | 0:389ef088650e | 180 | fread(&buff, 1, 32, song); |
ollie8 | 0:389ef088650e | 181 | //vs1053.testdreq(); |
ollie8 | 0:389ef088650e | 182 | for (int i = 0; i < 32; i++) { |
ollie8 | 0:389ef088650e | 183 | vs1053.writedata(buff[i]); |
ollie8 | 0:389ef088650e | 184 | } |
ollie8 | 0:389ef088650e | 185 | } else { |
ollie8 | 0:389ef088650e | 186 | // we have some free time so do something else |
ollie8 | 0:389ef088650e | 187 | } |
ollie8 | 0:389ef088650e | 188 | } |
ollie8 | 0:389ef088650e | 189 | } |
ollie8 | 0:389ef088650e | 190 | fclose(song); |
ollie8 | 0:389ef088650e | 191 | state = IDLE; |
ollie8 | 0:389ef088650e | 192 | root.enter(); |
ollie8 | 0:389ef088650e | 193 | } |
ollie8 | 0:389ef088650e | 194 | } |
ollie8 | 0:389ef088650e | 195 | } |
ollie8 | 0:389ef088650e | 196 | |
ollie8 | 0:389ef088650e | 197 | int main() { |
ollie8 | 0:389ef088650e | 198 | lcd.printf("Initialising..."); |
ollie8 | 0:389ef088650e | 199 | lcd.locate(0, 1); |
ollie8 | 0:389ef088650e | 200 | lcd.printf("O pod v0.1"); |
ollie8 | 0:389ef088650e | 201 | pc.printf("Starting...\n\r"); |
ollie8 | 0:389ef088650e | 202 | vs1053.init(); |
ollie8 | 0:389ef088650e | 203 | vs1053.loadpatch(); |
ollie8 | 0:389ef088650e | 204 | button.mode(PullUp); |
ollie8 | 0:389ef088650e | 205 | button.setAssertValue(0); |
ollie8 | 0:389ef088650e | 206 | button.attach_asserted(&buttonPress); |
ollie8 | 0:389ef088650e | 207 | button.attach_asserted_held(&buttonHeld); |
ollie8 | 0:389ef088650e | 208 | button.setSampleFrequency(); |
ollie8 | 0:389ef088650e | 209 | setupMenu(); |
ollie8 | 0:389ef088650e | 210 | while (1) { |
ollie8 | 0:389ef088650e | 211 | checkControl(); |
ollie8 | 0:389ef088650e | 212 | checkCued(); |
ollie8 | 0:389ef088650e | 213 | } |
ollie8 | 0:389ef088650e | 214 | } |