inital commit
Dependencies: mbed wave_player mbed-rtos 4DGL-uLCD-SE SDFileSystem2 PinDetect MMA8452
main.cpp@11:1a47726ac72a, 2021-12-15 (annotated)
- Committer:
- lfink6
- Date:
- Wed Dec 15 17:17:26 2021 +0000
- Revision:
- 11:1a47726ac72a
- Parent:
- 10:5bd6abd66d12
Rev final;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
lfink6 | 11:1a47726ac72a | 1 | /** |
lfink6 | 11:1a47726ac72a | 2 | * @file main.cpp |
lfink6 | 11:1a47726ac72a | 3 | * @authors Christopher Rothmann (chrisrothmann@gatech.edu) & Luke Fink (lfink6@gatech.edu) |
lfink6 | 11:1a47726ac72a | 4 | * @brief C++ Code to create an MP3 player from an mBED |
lfink6 | 11:1a47726ac72a | 5 | * @version 1.0 |
lfink6 | 11:1a47726ac72a | 6 | * @date 2021-12-13 |
lfink6 | 11:1a47726ac72a | 7 | * |
lfink6 | 11:1a47726ac72a | 8 | * @copyright Copyright (c) 2021 |
lfink6 | 11:1a47726ac72a | 9 | **/ |
lfink6 | 11:1a47726ac72a | 10 | |
lfink6 | 11:1a47726ac72a | 11 | |
lfink6 | 11:1a47726ac72a | 12 | // Define included libraries; all libraries below must be compiled together |
lfink6 | 11:1a47726ac72a | 13 | // Note: Some libraries have been updated to work with this code. Ensure all libraries |
lfink6 | 11:1a47726ac72a | 14 | // are the correct by using those included in this github |
4180_1 | 1:5b8e223e983d | 15 | #include "mbed.h" |
4180_1 | 2:c2afd0c426af | 16 | #include "rtos.h" |
4180_1 | 1:5b8e223e983d | 17 | #include "SDFileSystem.h" |
lfink6 | 3:8a1fd3450cb5 | 18 | #include "uLCD_4DGL.h" |
4180_1 | 1:5b8e223e983d | 19 | #include "wave_player.h" |
lfink6 | 11:1a47726ac72a | 20 | #include "MMA8452.h" |
lfink6 | 3:8a1fd3450cb5 | 21 | #include "PinDetect.h" |
lfink6 | 3:8a1fd3450cb5 | 22 | #include <string> |
lfink6 | 3:8a1fd3450cb5 | 23 | #include <vector> |
4180_1 | 1:5b8e223e983d | 24 | |
lfink6 | 11:1a47726ac72a | 25 | // Defining mBED inputs & outputs |
4180_1 | 1:5b8e223e983d | 26 | |
lfink6 | 11:1a47726ac72a | 27 | // mBED LED Outputs for Audiovisualizer/Testing & Diagnostics |
lfink6 | 11:1a47726ac72a | 28 | DigitalOut led1(LED1); |
lfink6 | 11:1a47726ac72a | 29 | DigitalOut led2(LED2); |
lfink6 | 11:1a47726ac72a | 30 | DigitalOut led3(LED3); |
lfink6 | 11:1a47726ac72a | 31 | DigitalOut led4(LED4); |
lfink6 | 3:8a1fd3450cb5 | 32 | |
lfink6 | 11:1a47726ac72a | 33 | // Pushbuttons for MP3 Player Controls |
lfink6 | 11:1a47726ac72a | 34 | PinDetect prev(p21); |
lfink6 | 11:1a47726ac72a | 35 | PinDetect next(p22); |
lfink6 | 11:1a47726ac72a | 36 | PinDetect shuffle(p23); |
lfink6 | 11:1a47726ac72a | 37 | PinDetect play(p24); |
4180_1 | 1:5b8e223e983d | 38 | |
lfink6 | 11:1a47726ac72a | 39 | // Serial & Analog Inputs & Ouputs for Data Communication |
lfink6 | 11:1a47726ac72a | 40 | RawSerial blueTooth(p28,p27); |
lfink6 | 11:1a47726ac72a | 41 | Serial pc(USBTX, USBRX); |
lfink6 | 11:1a47726ac72a | 42 | SDFileSystem sd(p5, p6, p7, p12, "sd"); |
lfink6 | 11:1a47726ac72a | 43 | uLCD_4DGL uLCD(p13,p14,p11); |
lfink6 | 11:1a47726ac72a | 44 | MMA8452 acc(p9, p10, 100000); |
4180_1 | 1:5b8e223e983d | 45 | AnalogOut DACout(p18); |
lfink6 | 11:1a47726ac72a | 46 | wave_player waver(&DACout); |
4180_1 | 1:5b8e223e983d | 47 | |
lfink6 | 11:1a47726ac72a | 48 | |
lfink6 | 11:1a47726ac72a | 49 | // Defining Internal Global Variables |
lfink6 | 6:6315ecdd0b47 | 50 | bool playing = false; |
lfink6 | 11:1a47726ac72a | 51 | int currentSong = 0; |
lfink6 | 11:1a47726ac72a | 52 | int songCount = 0; |
lfink6 | 11:1a47726ac72a | 53 | vector<string> songList; |
lfink6 | 11:1a47726ac72a | 54 | unsigned short max_range = 0xFFFF; |
lfink6 | 11:1a47726ac72a | 55 | |
lfink6 | 11:1a47726ac72a | 56 | // Defining Functions |
lfink6 | 3:8a1fd3450cb5 | 57 | |
lfink6 | 11:1a47726ac72a | 58 | /** |
lfink6 | 11:1a47726ac72a | 59 | * @brief Increments integer variable currentSong by one, while circling back to first song at end of list |
lfink6 | 11:1a47726ac72a | 60 | * @details Function is called both when "next song" pushbutton pressed or bluetooth command is sent; |
lfink6 | 11:1a47726ac72a | 61 | * LED1 switches value when called for diagnostics & testing |
lfink6 | 11:1a47726ac72a | 62 | **/ |
lfink6 | 11:1a47726ac72a | 63 | void nextSong() |
lfink6 | 3:8a1fd3450cb5 | 64 | { |
lfink6 | 11:1a47726ac72a | 65 | //led1 = !led1; |
lfink6 | 11:1a47726ac72a | 66 | if (currentSong == songCount - 1) |
lfink6 | 3:8a1fd3450cb5 | 67 | { |
lfink6 | 11:1a47726ac72a | 68 | currentSong = 0; |
lfink6 | 6:6315ecdd0b47 | 69 | } |
lfink6 | 6:6315ecdd0b47 | 70 | else |
lfink6 | 6:6315ecdd0b47 | 71 | { |
lfink6 | 11:1a47726ac72a | 72 | currentSong++; |
lfink6 | 6:6315ecdd0b47 | 73 | } |
lfink6 | 3:8a1fd3450cb5 | 74 | } |
lfink6 | 11:1a47726ac72a | 75 | |
lfink6 | 11:1a47726ac72a | 76 | /** |
lfink6 | 11:1a47726ac72a | 77 | * @brief Increments integer variable currentSong by minus one, while circling back to last song at zero |
lfink6 | 11:1a47726ac72a | 78 | * @details Function is called both when "previous song" pushbutton pressed or bluetooth command is sent; |
lfink6 | 11:1a47726ac72a | 79 | * LED2 switches value when called for diagnostics & testing |
lfink6 | 11:1a47726ac72a | 80 | **/ |
lfink6 | 11:1a47726ac72a | 81 | void prevSong() |
lfink6 | 3:8a1fd3450cb5 | 82 | { |
lfink6 | 11:1a47726ac72a | 83 | //led2 = !led2; |
lfink6 | 11:1a47726ac72a | 84 | if (currentSong == 0) |
lfink6 | 3:8a1fd3450cb5 | 85 | { |
lfink6 | 11:1a47726ac72a | 86 | currentSong = songCount - 1; |
lfink6 | 3:8a1fd3450cb5 | 87 | } |
lfink6 | 3:8a1fd3450cb5 | 88 | else |
lfink6 | 3:8a1fd3450cb5 | 89 | { |
lfink6 | 11:1a47726ac72a | 90 | currentSong--; |
lfink6 | 3:8a1fd3450cb5 | 91 | } |
lfink6 | 3:8a1fd3450cb5 | 92 | } |
lfink6 | 11:1a47726ac72a | 93 | |
lfink6 | 9:08886cc06a5d | 94 | |
lfink6 | 11:1a47726ac72a | 95 | /** |
lfink6 | 11:1a47726ac72a | 96 | * @brief Switches boolean variable playing |
lfink6 | 11:1a47726ac72a | 97 | * @details Function is called both when "pause/play" pushbutton pressed or bluetooth command is sent; |
lfink6 | 11:1a47726ac72a | 98 | * LED3 switches value when called for diagnostics & testing |
lfink6 | 11:1a47726ac72a | 99 | **/ |
lfink6 | 11:1a47726ac72a | 100 | void playSong() |
lfink6 | 3:8a1fd3450cb5 | 101 | { |
lfink6 | 11:1a47726ac72a | 102 | //led3 = !led3; |
lfink6 | 11:1a47726ac72a | 103 | playing = !playing; |
lfink6 | 3:8a1fd3450cb5 | 104 | } |
lfink6 | 3:8a1fd3450cb5 | 105 | |
lfink6 | 11:1a47726ac72a | 106 | /** |
lfink6 | 11:1a47726ac72a | 107 | * @brief Generates random integer within song list range to assign integer variable currentSong |
lfink6 | 11:1a47726ac72a | 108 | * @details Function is called both when "shuffle song" pushbutton pressed or bluetooth command is sent; |
lfink6 | 11:1a47726ac72a | 109 | * function seeds a true random value through the noise present on the 5th decimal place of an |
lfink6 | 11:1a47726ac72a | 110 | * accelerometer's input values; |
lfink6 | 11:1a47726ac72a | 111 | * LED4 switches value when called for diagnostics & testing |
lfink6 | 11:1a47726ac72a | 112 | **/ |
lfink6 | 11:1a47726ac72a | 113 | void shuffleSong() |
4180_1 | 1:5b8e223e983d | 114 | { |
lfink6 | 11:1a47726ac72a | 115 | //led4 = !led4; |
lfink6 | 11:1a47726ac72a | 116 | double x, y, z; |
lfink6 | 11:1a47726ac72a | 117 | acc.readXYZGravity(&x,&y,&z); |
lfink6 | 11:1a47726ac72a | 118 | currentSong = int(100000 * (x + y + z)) % songCount; |
lfink6 | 11:1a47726ac72a | 119 | } |
lfink6 | 11:1a47726ac72a | 120 | |
lfink6 | 11:1a47726ac72a | 121 | // Defining Threads |
lfink6 | 11:1a47726ac72a | 122 | |
lfink6 | 11:1a47726ac72a | 123 | /** |
lfink6 | 11:1a47726ac72a | 124 | * @brief Updates LCD screen according to user input & selections |
lfink6 | 11:1a47726ac72a | 125 | * @details First configures LCD screen layout & songlist, then continously checks for changes in global variables |
lfink6 | 11:1a47726ac72a | 126 | * integer currentSong & boolean playing to update LCD screen accordingly. No updates made if no changes found. |
lfink6 | 11:1a47726ac72a | 127 | * All LCD communications occur strictly in this thread. |
lfink6 | 11:1a47726ac72a | 128 | * @param *arguments Input arguments to thread used for RTOS thread library. Not needed to understand thread code. |
lfink6 | 11:1a47726ac72a | 129 | */ |
lfink6 | 11:1a47726ac72a | 130 | void LCDThread(void const *argument) |
lfink6 | 11:1a47726ac72a | 131 | { |
lfink6 | 11:1a47726ac72a | 132 | // Configure LCD screen |
lfink6 | 3:8a1fd3450cb5 | 133 | uLCD.cls(); |
lfink6 | 3:8a1fd3450cb5 | 134 | uLCD.baudrate(3000000); |
lfink6 | 3:8a1fd3450cb5 | 135 | uLCD.background_color(BLACK); |
lfink6 | 11:1a47726ac72a | 136 | uLCD.color(WHITE); |
lfink6 | 3:8a1fd3450cb5 | 137 | uLCD.text_width(1); |
lfink6 | 11:1a47726ac72a | 138 | uLCD.text_height(1); |
lfink6 | 11:1a47726ac72a | 139 | |
lfink6 | 11:1a47726ac72a | 140 | // Print Song List to LCD Screen |
lfink6 | 11:1a47726ac72a | 141 | uLCD.locate(0,0); |
lfink6 | 11:1a47726ac72a | 142 | uLCD.printf("Song List: "); |
lfink6 | 11:1a47726ac72a | 143 | uLCD.locate(0,1); |
lfink6 | 11:1a47726ac72a | 144 | uLCD.printf("->"); |
lfink6 | 11:1a47726ac72a | 145 | for(int i = 0; i < songCount; i++) |
lfink6 | 11:1a47726ac72a | 146 | { |
lfink6 | 11:1a47726ac72a | 147 | uLCD.locate(3,i+1); |
lfink6 | 11:1a47726ac72a | 148 | uLCD.printf("%s\n\r", songList[i].substr(0,songList[i].find(".wav"))); |
lfink6 | 11:1a47726ac72a | 149 | } |
lfink6 | 11:1a47726ac72a | 150 | |
lfink6 | 11:1a47726ac72a | 151 | // Print "NOW PLAYING: " & "STATUS: " feature; initialize to first song on SD card & paused |
lfink6 | 11:1a47726ac72a | 152 | uLCD.locate(0,12); |
lfink6 | 11:1a47726ac72a | 153 | uLCD.printf("NOW PLAYING:"); |
lfink6 | 11:1a47726ac72a | 154 | uLCD.locate(0,13); |
lfink6 | 11:1a47726ac72a | 155 | uLCD.printf("%s", songList[currentSong].substr(0,songList[currentSong].find(".wav"))); |
lfink6 | 11:1a47726ac72a | 156 | uLCD.locate(0,14); |
lfink6 | 11:1a47726ac72a | 157 | uLCD.printf("STATUS: PAUSED"); |
lfink6 | 11:1a47726ac72a | 158 | |
lfink6 | 11:1a47726ac72a | 159 | // Initialize internal thread variables to check for changes to external global variables |
lfink6 | 11:1a47726ac72a | 160 | bool prevPlayLCD = false; |
lfink6 | 11:1a47726ac72a | 161 | int previousSongLCD = 0; |
lfink6 | 11:1a47726ac72a | 162 | |
lfink6 | 11:1a47726ac72a | 163 | // Thread while loop to continously check for changes and update screen accordingly |
lfink6 | 11:1a47726ac72a | 164 | while (true) |
lfink6 | 11:1a47726ac72a | 165 | { |
lfink6 | 11:1a47726ac72a | 166 | // Check if new song has been selected |
lfink6 | 11:1a47726ac72a | 167 | if (previousSongLCD != currentSong) |
lfink6 | 11:1a47726ac72a | 168 | { |
lfink6 | 11:1a47726ac72a | 169 | // Update "NOW PLAYING: " feature |
lfink6 | 11:1a47726ac72a | 170 | uLCD.locate(0,12); |
lfink6 | 11:1a47726ac72a | 171 | uLCD.printf("NOW PLAYING:"); |
lfink6 | 11:1a47726ac72a | 172 | uLCD.locate(0,13); |
lfink6 | 11:1a47726ac72a | 173 | uLCD.printf("%s ", songList[currentSong].substr(0,songList[currentSong].find(".wav"))); |
lfink6 | 11:1a47726ac72a | 174 | // Update "->" feature |
lfink6 | 11:1a47726ac72a | 175 | uLCD.locate(0, previousSongLCD + 1); |
lfink6 | 11:1a47726ac72a | 176 | uLCD.printf(" "); |
lfink6 | 11:1a47726ac72a | 177 | uLCD.locate(0, currentSong + 1); |
lfink6 | 11:1a47726ac72a | 178 | uLCD.printf("->"); |
lfink6 | 11:1a47726ac72a | 179 | // Set internal change check to currentSong |
lfink6 | 11:1a47726ac72a | 180 | previousSongLCD = currentSong; |
lfink6 | 11:1a47726ac72a | 181 | } |
lfink6 | 11:1a47726ac72a | 182 | //Check if change to play/pause status |
lfink6 | 11:1a47726ac72a | 183 | if (prevPlayLCD != playing) |
lfink6 | 11:1a47726ac72a | 184 | { |
lfink6 | 11:1a47726ac72a | 185 | // Update "STATUS: " feature |
lfink6 | 11:1a47726ac72a | 186 | uLCD.locate(0,14); |
lfink6 | 11:1a47726ac72a | 187 | if (playing) |
lfink6 | 11:1a47726ac72a | 188 | { |
lfink6 | 11:1a47726ac72a | 189 | uLCD.printf("STATUS: PLAYING"); |
lfink6 | 11:1a47726ac72a | 190 | } |
lfink6 | 11:1a47726ac72a | 191 | else |
lfink6 | 11:1a47726ac72a | 192 | { |
lfink6 | 11:1a47726ac72a | 193 | uLCD.printf("STATUS: PAUSED "); |
lfink6 | 11:1a47726ac72a | 194 | } |
lfink6 | 11:1a47726ac72a | 195 | // Set internal change check to playing |
lfink6 | 11:1a47726ac72a | 196 | prevPlayLCD = playing; |
lfink6 | 11:1a47726ac72a | 197 | } |
lfink6 | 11:1a47726ac72a | 198 | Thread::wait(50); |
lfink6 | 3:8a1fd3450cb5 | 199 | } |
lfink6 | 11:1a47726ac72a | 200 | } |
lfink6 | 11:1a47726ac72a | 201 | |
lfink6 | 11:1a47726ac72a | 202 | /** |
lfink6 | 11:1a47726ac72a | 203 | * @brief Updates phone screen to latest currentSong playing, sends phone commands to mBED, all over BlueTooth |
lfink6 | 11:1a47726ac72a | 204 | * @details See commenting in thread for step-by-step approach |
lfink6 | 11:1a47726ac72a | 205 | * All BlueTooth communications occur strictly in this thread |
lfink6 | 11:1a47726ac72a | 206 | * BlueTooth Control Pad Module Controls: 1 = Pause/Play, 2 = Next Song, 3 = Previous Song, 4 = Shuffle Song |
lfink6 | 11:1a47726ac72a | 207 | * @param *arguments Input arguments to thread used for RTOS thread library. Not needed to understand thread code. |
lfink6 | 11:1a47726ac72a | 208 | */ |
lfink6 | 11:1a47726ac72a | 209 | void BluetoothThread(void const *argument) |
lfink6 | 11:1a47726ac72a | 210 | { |
lfink6 | 11:1a47726ac72a | 211 | // Initialize internal thread variable to check for changes to external global variables |
lfink6 | 11:1a47726ac72a | 212 | int previousSongBLE = 0; |
lfink6 | 11:1a47726ac72a | 213 | // Thread while look to continously check for BlueTooth commands and update currentSong on phone |
lfink6 | 11:1a47726ac72a | 214 | while (true) |
lfink6 | 11:1a47726ac72a | 215 | { |
lfink6 | 11:1a47726ac72a | 216 | // Update currentSong on phone |
lfink6 | 11:1a47726ac72a | 217 | if (blueTooth.writeable()) |
lfink6 | 11:1a47726ac72a | 218 | { |
lfink6 | 11:1a47726ac72a | 219 | // Check if new song has been selected |
lfink6 | 11:1a47726ac72a | 220 | if (previousSongBLE != currentSong) |
lfink6 | 11:1a47726ac72a | 221 | { |
lfink6 | 11:1a47726ac72a | 222 | // Send currentSong name over BlueTooth |
lfink6 | 11:1a47726ac72a | 223 | string str = "Current Song: "; |
lfink6 | 11:1a47726ac72a | 224 | for (int i = 0; i < 14; i++) |
lfink6 | 11:1a47726ac72a | 225 | { |
lfink6 | 11:1a47726ac72a | 226 | blueTooth.putc(str[i]); |
lfink6 | 11:1a47726ac72a | 227 | } |
lfink6 | 11:1a47726ac72a | 228 | for (int i = 0; i < songList[currentSong].size() - 4; i++) |
lfink6 | 11:1a47726ac72a | 229 | { |
lfink6 | 11:1a47726ac72a | 230 | blueTooth.putc(songList[currentSong][i]); |
lfink6 | 11:1a47726ac72a | 231 | } |
lfink6 | 11:1a47726ac72a | 232 | blueTooth.putc('\n'); |
lfink6 | 11:1a47726ac72a | 233 | previousSongBLE = currentSong; |
lfink6 | 11:1a47726ac72a | 234 | } |
lfink6 | 11:1a47726ac72a | 235 | |
lfink6 | 11:1a47726ac72a | 236 | } |
lfink6 | 11:1a47726ac72a | 237 | // Read in commands from BlueTooth module |
lfink6 | 11:1a47726ac72a | 238 | if (blueTooth.readable()) |
lfink6 | 11:1a47726ac72a | 239 | { |
lfink6 | 11:1a47726ac72a | 240 | // Check for '!B' to be compatible with "Control Pad" Module serial output |
lfink6 | 11:1a47726ac72a | 241 | if (blueTooth.getc()=='!') |
lfink6 | 11:1a47726ac72a | 242 | { |
lfink6 | 11:1a47726ac72a | 243 | if (blueTooth.getc()=='B') |
lfink6 | 11:1a47726ac72a | 244 | { |
lfink6 | 11:1a47726ac72a | 245 | // Check which command was hit |
lfink6 | 11:1a47726ac72a | 246 | char bnum = blueTooth.getc(); |
lfink6 | 11:1a47726ac72a | 247 | // Ensure mBED only updates on release, not hit |
lfink6 | 11:1a47726ac72a | 248 | char bhit = blueTooth.getc(); |
lfink6 | 11:1a47726ac72a | 249 | if (bhit == '0') |
lfink6 | 11:1a47726ac72a | 250 | { |
lfink6 | 11:1a47726ac72a | 251 | switch (bnum) |
lfink6 | 11:1a47726ac72a | 252 | { |
lfink6 | 11:1a47726ac72a | 253 | case '1': |
lfink6 | 11:1a47726ac72a | 254 | playSong(); |
lfink6 | 11:1a47726ac72a | 255 | break; |
lfink6 | 11:1a47726ac72a | 256 | |
lfink6 | 11:1a47726ac72a | 257 | case '2': |
lfink6 | 11:1a47726ac72a | 258 | nextSong(); |
lfink6 | 11:1a47726ac72a | 259 | break; |
lfink6 | 11:1a47726ac72a | 260 | |
lfink6 | 11:1a47726ac72a | 261 | case '3': |
lfink6 | 11:1a47726ac72a | 262 | prevSong(); |
lfink6 | 11:1a47726ac72a | 263 | break; |
lfink6 | 11:1a47726ac72a | 264 | |
lfink6 | 11:1a47726ac72a | 265 | case '4': |
lfink6 | 11:1a47726ac72a | 266 | shuffleSong(); |
lfink6 | 11:1a47726ac72a | 267 | break; |
lfink6 | 11:1a47726ac72a | 268 | |
lfink6 | 11:1a47726ac72a | 269 | default: |
lfink6 | 11:1a47726ac72a | 270 | break; |
lfink6 | 11:1a47726ac72a | 271 | } |
lfink6 | 11:1a47726ac72a | 272 | } |
lfink6 | 11:1a47726ac72a | 273 | } |
lfink6 | 11:1a47726ac72a | 274 | } |
lfink6 | 11:1a47726ac72a | 275 | } |
lfink6 | 11:1a47726ac72a | 276 | Thread::wait(50); |
lfink6 | 11:1a47726ac72a | 277 | } |
lfink6 | 11:1a47726ac72a | 278 | } |
lfink6 | 11:1a47726ac72a | 279 | |
lfink6 | 11:1a47726ac72a | 280 | /** |
lfink6 | 11:1a47726ac72a | 281 | * @brief Updates Mbed LEDs to show current volume level |
lfink6 | 11:1a47726ac72a | 282 | * @details Read and scales analogOut level, then sets leds to show the level in 4 tiers. |
lfink6 | 11:1a47726ac72a | 283 | * @param *arguments Input arguments to thread used for RTOS thread library. Not needed to understand thread code. |
lfink6 | 11:1a47726ac72a | 284 | */ |
lfink6 | 11:1a47726ac72a | 285 | void AudioVisualizerThread(void const *argument) |
lfink6 | 11:1a47726ac72a | 286 | { |
lfink6 | 11:1a47726ac72a | 287 | while(1) |
lfink6 | 11:1a47726ac72a | 288 | { |
lfink6 | 11:1a47726ac72a | 289 | if(playing) |
lfink6 | 11:1a47726ac72a | 290 | { |
lfink6 | 11:1a47726ac72a | 291 | float level = (DACout.read() - 0.25f) * 3.3f; |
lfink6 | 11:1a47726ac72a | 292 | if(level<0.825) |
lfink6 | 11:1a47726ac72a | 293 | { |
lfink6 | 11:1a47726ac72a | 294 | led1=true; |
lfink6 | 11:1a47726ac72a | 295 | led2=led3=led4=false; |
lfink6 | 11:1a47726ac72a | 296 | } |
lfink6 | 11:1a47726ac72a | 297 | else if(level>0.825&&level<1.65) |
lfink6 | 11:1a47726ac72a | 298 | { |
lfink6 | 11:1a47726ac72a | 299 | led1=led2=true; |
lfink6 | 11:1a47726ac72a | 300 | led3=led4=false; |
lfink6 | 11:1a47726ac72a | 301 | } |
lfink6 | 11:1a47726ac72a | 302 | else if(level>1.65&&level<2.47) |
lfink6 | 11:1a47726ac72a | 303 | { |
lfink6 | 11:1a47726ac72a | 304 | led1=led2=led3=true; |
lfink6 | 11:1a47726ac72a | 305 | led4=false; |
lfink6 | 11:1a47726ac72a | 306 | } |
lfink6 | 11:1a47726ac72a | 307 | else if(level>2.47) |
lfink6 | 11:1a47726ac72a | 308 | { |
lfink6 | 11:1a47726ac72a | 309 | led1=led2=led3=led4=true; |
lfink6 | 11:1a47726ac72a | 310 | } |
lfink6 | 11:1a47726ac72a | 311 | Thread::wait(50); |
lfink6 | 11:1a47726ac72a | 312 | } |
lfink6 | 11:1a47726ac72a | 313 | } |
lfink6 | 11:1a47726ac72a | 314 | } |
lfink6 | 11:1a47726ac72a | 315 | |
lfink6 | 11:1a47726ac72a | 316 | // Button Interupt Functions |
lfink6 | 11:1a47726ac72a | 317 | |
lfink6 | 11:1a47726ac72a | 318 | /** |
lfink6 | 11:1a47726ac72a | 319 | * @brief runs nextSong() function on pushbotton hit. Attached using PinDetect. |
lfink6 | 11:1a47726ac72a | 320 | **/ |
lfink6 | 11:1a47726ac72a | 321 | void nextInt() |
lfink6 | 11:1a47726ac72a | 322 | { |
lfink6 | 11:1a47726ac72a | 323 | nextSong(); |
lfink6 | 11:1a47726ac72a | 324 | } |
lfink6 | 11:1a47726ac72a | 325 | |
lfink6 | 11:1a47726ac72a | 326 | /** |
lfink6 | 11:1a47726ac72a | 327 | * @brief runs prevSong() function on pushbotton hit. Attached using PinDetect. |
lfink6 | 11:1a47726ac72a | 328 | **/ |
lfink6 | 11:1a47726ac72a | 329 | void prevInt() |
lfink6 | 11:1a47726ac72a | 330 | { |
lfink6 | 11:1a47726ac72a | 331 | prevSong(); |
lfink6 | 11:1a47726ac72a | 332 | } |
lfink6 | 11:1a47726ac72a | 333 | |
lfink6 | 11:1a47726ac72a | 334 | /** |
lfink6 | 11:1a47726ac72a | 335 | * @brief runs playSong() function on pushbotton hit. Attached using PinDetect. |
lfink6 | 11:1a47726ac72a | 336 | **/ |
lfink6 | 11:1a47726ac72a | 337 | void playInt() |
lfink6 | 11:1a47726ac72a | 338 | { |
lfink6 | 11:1a47726ac72a | 339 | playSong(); |
lfink6 | 11:1a47726ac72a | 340 | } |
lfink6 | 11:1a47726ac72a | 341 | |
lfink6 | 11:1a47726ac72a | 342 | /** |
lfink6 | 11:1a47726ac72a | 343 | * @brief runs shuffleSong() function on pushbotton hit. Attached using PinDetect. |
lfink6 | 11:1a47726ac72a | 344 | **/ |
lfink6 | 11:1a47726ac72a | 345 | void shuffleInt() |
lfink6 | 11:1a47726ac72a | 346 | { |
lfink6 | 11:1a47726ac72a | 347 | shuffleSong(); |
lfink6 | 11:1a47726ac72a | 348 | } |
lfink6 | 11:1a47726ac72a | 349 | |
lfink6 | 11:1a47726ac72a | 350 | /** |
lfink6 | 11:1a47726ac72a | 351 | * @brief Program main routine. |
lfink6 | 11:1a47726ac72a | 352 | * @return int No return expected. |
lfink6 | 11:1a47726ac72a | 353 | */ |
lfink6 | 11:1a47726ac72a | 354 | int main() |
lfink6 | 11:1a47726ac72a | 355 | { |
lfink6 | 11:1a47726ac72a | 356 | // Attach & configure interupts to pushbuttons |
lfink6 | 11:1a47726ac72a | 357 | next.mode(PullUp); |
lfink6 | 11:1a47726ac72a | 358 | prev.mode(PullUp); |
lfink6 | 11:1a47726ac72a | 359 | play.mode(PullUp); |
lfink6 | 11:1a47726ac72a | 360 | shuffle.mode(PullUp); |
lfink6 | 11:1a47726ac72a | 361 | next.attach_deasserted(&nextInt); |
lfink6 | 11:1a47726ac72a | 362 | prev.attach_deasserted(&prevInt); |
lfink6 | 11:1a47726ac72a | 363 | play.attach_deasserted(&playInt); |
lfink6 | 11:1a47726ac72a | 364 | shuffle.attach_deasserted(&shuffleInt); |
lfink6 | 11:1a47726ac72a | 365 | next.setSampleFrequency(); |
lfink6 | 11:1a47726ac72a | 366 | prev.setSampleFrequency(); |
lfink6 | 11:1a47726ac72a | 367 | play.setSampleFrequency(); |
lfink6 | 11:1a47726ac72a | 368 | shuffle.setSampleFrequency(); |
lfink6 | 11:1a47726ac72a | 369 | // Wait 10 milliseconds to ensure functions are attached |
lfink6 | 11:1a47726ac72a | 370 | Thread::wait(10); |
lfink6 | 3:8a1fd3450cb5 | 371 | |
lfink6 | 11:1a47726ac72a | 372 | // Extract file list from SD Card, place in vector<string> songList |
lfink6 | 3:8a1fd3450cb5 | 373 | DIR *dp; |
lfink6 | 3:8a1fd3450cb5 | 374 | struct dirent *dirp; |
lfink6 | 3:8a1fd3450cb5 | 375 | dp = opendir("/sd/myMusic"); |
lfink6 | 3:8a1fd3450cb5 | 376 | if(dp !=NULL) |
lfink6 | 3:8a1fd3450cb5 | 377 | { |
lfink6 | 3:8a1fd3450cb5 | 378 | while ((dirp = readdir(dp)) != NULL) { |
lfink6 | 3:8a1fd3450cb5 | 379 | songList.push_back(string(dirp->d_name)); |
lfink6 | 11:1a47726ac72a | 380 | songCount++; |
lfink6 | 3:8a1fd3450cb5 | 381 | } |
lfink6 | 3:8a1fd3450cb5 | 382 | } |
lfink6 | 11:1a47726ac72a | 383 | // Wait 10 miliseconds to ensure SD card communication complete |
lfink6 | 11:1a47726ac72a | 384 | Thread::wait(10); |
lfink6 | 3:8a1fd3450cb5 | 385 | |
lfink6 | 11:1a47726ac72a | 386 | // Start LCD & BlueTooth Thread |
lfink6 | 3:8a1fd3450cb5 | 387 | Thread thread1(LCDThread); |
lfink6 | 11:1a47726ac72a | 388 | Thread thread2(BluetoothThread); |
lfink6 | 11:1a47726ac72a | 389 | Thread thread3(AudioVisualizerThread); |
lfink6 | 11:1a47726ac72a | 390 | |
lfink6 | 11:1a47726ac72a | 391 | // Main while loop: |
lfink6 | 11:1a47726ac72a | 392 | // Main loop is now considered the Speaker Thread, playing/pausing current song |
lfink6 | 11:1a47726ac72a | 393 | // based on changes in global varaibles boolean playing & integer currentSong |
lfink6 | 11:1a47726ac72a | 394 | while (true) |
lfink6 | 11:1a47726ac72a | 395 | { |
lfink6 | 11:1a47726ac72a | 396 | // Read in selected file |
lfink6 | 11:1a47726ac72a | 397 | FILE *wave_file; |
lfink6 | 11:1a47726ac72a | 398 | string selectedSong= "/sd/myMusic/" + songList[currentSong]; |
lfink6 | 11:1a47726ac72a | 399 | const char* song = selectedSong.c_str(); |
lfink6 | 11:1a47726ac72a | 400 | wave_file=fopen(song,"r"); |
lfink6 | 11:1a47726ac72a | 401 | if(wave_file==NULL) |
lfink6 | 11:1a47726ac72a | 402 | { |
lfink6 | 11:1a47726ac72a | 403 | uLCD.locate(0,12); |
lfink6 | 11:1a47726ac72a | 404 | uLCD.printf("file open error!"); |
lfink6 | 11:1a47726ac72a | 405 | } |
lfink6 | 11:1a47726ac72a | 406 | // Wait 10 miliseconds to ensure file properly loaded |
lfink6 | 11:1a47726ac72a | 407 | Thread::wait(10); |
lfink6 | 11:1a47726ac72a | 408 | // Play file; stop/play feature built into waver library |
lfink6 | 11:1a47726ac72a | 409 | waver.play(wave_file); |
lfink6 | 11:1a47726ac72a | 410 | // Close file |
lfink6 | 11:1a47726ac72a | 411 | fclose(wave_file); |
lfink6 | 11:1a47726ac72a | 412 | // Reset playing variable so song does not repeat |
lfink6 | 11:1a47726ac72a | 413 | playing = false; |
lfink6 | 3:8a1fd3450cb5 | 414 | } |
4180_1 | 1:5b8e223e983d | 415 | } |