MP3-capable chair with sensor-embedded weight scale.

Dependencies:   ACM1602 SDFileSystem VS1053 mbed ClockControl PowerControl

Committer:
kayekss
Date:
Wed Mar 26 19:56:18 2014 +0000
Revision:
0:d9789f57fd9d
Child:
1:ef257d63d970
MP3-capable chair with sensor-embedded weight scale.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kayekss 0:d9789f57fd9d 1 #include <stdio.h>
kayekss 0:d9789f57fd9d 2 #include "mbed.h"
kayekss 0:d9789f57fd9d 3 #include "defs.h"
kayekss 0:d9789f57fd9d 4 #include "HysteresisIn.h"
kayekss 0:d9789f57fd9d 5 #include "SDFileSystem.h"
kayekss 0:d9789f57fd9d 6 #include "VS1053.h"
kayekss 0:d9789f57fd9d 7 #include "ACM1602.h"
kayekss 0:d9789f57fd9d 8
kayekss 0:d9789f57fd9d 9 // Pin settings for LPC1768(LPCXpresso)
kayekss 0:d9789f57fd9d 10 SDFileSystem sd(/*MOSI*/ xp11, /*MISO*/ xp12, /*SCK*/ xp13, /*CS*/ xp53, /*Mountpoint*/ "sd");
kayekss 0:d9789f57fd9d 11 VS1053 mp3(/*MOSI*/ xp11, /*MISO*/ xp12, /*SCK*/ xp13,
kayekss 0:d9789f57fd9d 12 /*CS*/ xp52, /*BSYNC*/ xp51, /*DREQ*/ xp50, /*RST*/ xp49, /*SPI freq.*/ 6000000);
kayekss 0:d9789f57fd9d 13 HysteresisIn sens3(p17, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #3 (Outer)
kayekss 0:d9789f57fd9d 14 HysteresisIn sens2(p18, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #2
kayekss 0:d9789f57fd9d 15 HysteresisIn sens1(p19, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #1
kayekss 0:d9789f57fd9d 16 HysteresisIn sens0(p20, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #0 (Inner)
kayekss 0:d9789f57fd9d 17 ACM1602 lcd(/*SDA*/ xp9, /*SCL*/ xp10, /*Address*/ 0xa0);
kayekss 0:d9789f57fd9d 18 DigitalOut led(LED0);
kayekss 0:d9789f57fd9d 19 DigitalOut audioPower(xp38);
kayekss 0:d9789f57fd9d 20 Ticker tic;
kayekss 0:d9789f57fd9d 21
kayekss 0:d9789f57fd9d 22 // Pin settings for LPC1114FN28 (SD card accessing does not work)
kayekss 0:d9789f57fd9d 23 // SDFileSystem sd(/*MOSI*/ dp2, /*MISO*/ dp1, /*SCK*/ dp6, /*CS*/ dp4, /*Mountpoint*/ "sd");
kayekss 0:d9789f57fd9d 24 // VS1053 mp3(/*MOSI*/ dp2, /*MISO*/ dp1, /*SCK*/ dp6,
kayekss 0:d9789f57fd9d 25 // /*CS*/ dp14, /*BSYNC*/ dp17, /*DREQ*/ dp18, /*RST*/ dp25, /*SPI freq.*/ 4000000);
kayekss 0:d9789f57fd9d 26 // HysteresisIn sens3(dp9, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #3 (Outer)
kayekss 0:d9789f57fd9d 27 // HysteresisIn sens2(dp10, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #2
kayekss 0:d9789f57fd9d 28 // HysteresisIn sens1(dp11, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #1
kayekss 0:d9789f57fd9d 29 // HysteresisIn sens0(dp13, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #0 (Inner)
kayekss 0:d9789f57fd9d 30 // ACM1602 lcd(/*SDA*/ dp5, /*SCL*/ dp27, /*Address*/ 0xa0);
kayekss 0:d9789f57fd9d 31 // Ticker tic;
kayekss 0:d9789f57fd9d 32
kayekss 0:d9789f57fd9d 33 const char *fileNameList[] = {
kayekss 0:d9789f57fd9d 34 "/sd/Track1.mp3",
kayekss 0:d9789f57fd9d 35 "/sd/Track2.mp3",
kayekss 0:d9789f57fd9d 36 "/sd/Track3.mp3",
kayekss 0:d9789f57fd9d 37 "/sd/Track4.mp3"
kayekss 0:d9789f57fd9d 38 };
kayekss 0:d9789f57fd9d 39
kayekss 0:d9789f57fd9d 40 volatile State state = READY;
kayekss 0:d9789f57fd9d 41 volatile Request request = NONE;
kayekss 0:d9789f57fd9d 42
kayekss 0:d9789f57fd9d 43 /** Setup and initializations */
kayekss 0:d9789f57fd9d 44 void setup(void) {
kayekss 0:d9789f57fd9d 45 // Initialize VS1053
kayekss 0:d9789f57fd9d 46 mp3.hardwareReset();
kayekss 0:d9789f57fd9d 47 mp3.clockUp();
kayekss 0:d9789f57fd9d 48 wait(0.1);
kayekss 0:d9789f57fd9d 49
kayekss 0:d9789f57fd9d 50 // Initialize power supply for audio amplifier circuit
kayekss 0:d9789f57fd9d 51 audioPower = 0;
kayekss 0:d9789f57fd9d 52
kayekss 0:d9789f57fd9d 53 // Setup LCD
kayekss 0:d9789f57fd9d 54 lcd.init();
kayekss 0:d9789f57fd9d 55
kayekss 0:d9789f57fd9d 56 // Initialize LED
kayekss 0:d9789f57fd9d 57 led = 0;
kayekss 0:d9789f57fd9d 58 }
kayekss 0:d9789f57fd9d 59
kayekss 0:d9789f57fd9d 60 /** Read voltages from photo sensor pins and detect weightscale point code */
kayekss 0:d9789f57fd9d 61 int readPhotoSensors(void) {
kayekss 0:d9789f57fd9d 62 uint8_t bitPattern;
kayekss 0:d9789f57fd9d 63
kayekss 0:d9789f57fd9d 64 // Read all photo sensor inputs
kayekss 0:d9789f57fd9d 65 bitPattern = (sens3.read() << 3)
kayekss 0:d9789f57fd9d 66 | (sens2.read() << 2)
kayekss 0:d9789f57fd9d 67 | (sens1.read() << 1)
kayekss 0:d9789f57fd9d 68 | sens0.read();
kayekss 0:d9789f57fd9d 69
kayekss 0:d9789f57fd9d 70 switch (bitPattern) {
kayekss 0:d9789f57fd9d 71 // 1 when open, 0 when shut
kayekss 0:d9789f57fd9d 72 // Higher bit is on outer side
kayekss 0:d9789f57fd9d 73 case 0xf: // 1111: no load
kayekss 0:d9789f57fd9d 74 return 0;
kayekss 0:d9789f57fd9d 75 case 0xe: // 1110: slight load
kayekss 0:d9789f57fd9d 76 return 1;
kayekss 0:d9789f57fd9d 77 case 0xc: // 1100
kayekss 0:d9789f57fd9d 78 return 2;
kayekss 0:d9789f57fd9d 79 case 0x8: // 1000
kayekss 0:d9789f57fd9d 80 return 3;
kayekss 0:d9789f57fd9d 81 case 0x0: // 0000: heavy load
kayekss 0:d9789f57fd9d 82 return 4;
kayekss 0:d9789f57fd9d 83 default: // Other than expectation: erroneous pattern
kayekss 0:d9789f57fd9d 84 return -1;
kayekss 0:d9789f57fd9d 85 }
kayekss 0:d9789f57fd9d 86 }
kayekss 0:d9789f57fd9d 87
kayekss 0:d9789f57fd9d 88 /** Poll/sample weightscale inputs and issue requests */
kayekss 0:d9789f57fd9d 89 void pollAndRequest() {
kayekss 0:d9789f57fd9d 90 const char* stateNameList[] = {
kayekss 0:d9789f57fd9d 91 "STOPPING", // -2
kayekss 0:d9789f57fd9d 92 "CANCELING", // -1
kayekss 0:d9789f57fd9d 93 "READY", // 0
kayekss 0:d9789f57fd9d 94 "PLAYING1", // 1
kayekss 0:d9789f57fd9d 95 "PLAYING2", // 2
kayekss 0:d9789f57fd9d 96 "PLAYING3", // 3
kayekss 0:d9789f57fd9d 97 "PLAYING4" // 4
kayekss 0:d9789f57fd9d 98 };
kayekss 0:d9789f57fd9d 99 int code;
kayekss 0:d9789f57fd9d 100 static int codePrev = 0;
kayekss 0:d9789f57fd9d 101 static uint8_t holdTimes = 0;
kayekss 0:d9789f57fd9d 102
kayekss 0:d9789f57fd9d 103 // Get weightscale point code by reading photo sensors
kayekss 0:d9789f57fd9d 104 code = readPhotoSensors();
kayekss 0:d9789f57fd9d 105
kayekss 0:d9789f57fd9d 106 // Count the times that the given code persists
kayekss 0:d9789f57fd9d 107 if (code == codePrev && code != -1) {
kayekss 0:d9789f57fd9d 108 if (holdTimes < 99) {
kayekss 0:d9789f57fd9d 109 holdTimes++;
kayekss 0:d9789f57fd9d 110 }
kayekss 0:d9789f57fd9d 111 } else {
kayekss 0:d9789f57fd9d 112 holdTimes = 0;
kayekss 0:d9789f57fd9d 113 }
kayekss 0:d9789f57fd9d 114 lcd.locate(0, 0);
kayekss 0:d9789f57fd9d 115 lcd.printf("%-15s", stateNameList[state + 2]);
kayekss 0:d9789f57fd9d 116 lcd.locate(0, 1);
kayekss 0:d9789f57fd9d 117 lcd.printf("ps=%2d times=%2d", code, holdTimes);
kayekss 0:d9789f57fd9d 118
kayekss 0:d9789f57fd9d 119 // Once the point is stable enough, make a request
kayekss 0:d9789f57fd9d 120 if (holdTimes == SETTLING_COUNT) {
kayekss 0:d9789f57fd9d 121 if (code == 0) {
kayekss 0:d9789f57fd9d 122 // Stable no load: stop request
kayekss 0:d9789f57fd9d 123 request = STOP_REQUEST;
kayekss 0:d9789f57fd9d 124 } else {
kayekss 0:d9789f57fd9d 125 // Certain stable load: play request 1..4
kayekss 0:d9789f57fd9d 126 // Ignore cases while playing the same track
kayekss 0:d9789f57fd9d 127 if (state != code) {
kayekss 0:d9789f57fd9d 128 request = (Request) code;
kayekss 0:d9789f57fd9d 129 }
kayekss 0:d9789f57fd9d 130 }
kayekss 0:d9789f57fd9d 131 }
kayekss 0:d9789f57fd9d 132
kayekss 0:d9789f57fd9d 133 // Preserve this time's code
kayekss 0:d9789f57fd9d 134 codePrev = code;
kayekss 0:d9789f57fd9d 135 }
kayekss 0:d9789f57fd9d 136
kayekss 0:d9789f57fd9d 137 /** Player control in accordance with requests */
kayekss 0:d9789f57fd9d 138 void controlTrack() {
kayekss 0:d9789f57fd9d 139 static FILE *fp = NULL;
kayekss 0:d9789f57fd9d 140 size_t sizeRead = 0;
kayekss 0:d9789f57fd9d 141 uint8_t buf[BLOCK_SIZE];
kayekss 0:d9789f57fd9d 142 static size_t totalSizeSent = 0;
kayekss 0:d9789f57fd9d 143
kayekss 0:d9789f57fd9d 144 switch (state) {
kayekss 0:d9789f57fd9d 145 case READY:
kayekss 0:d9789f57fd9d 146 switch (request) {
kayekss 0:d9789f57fd9d 147 case STOP_REQUEST:
kayekss 0:d9789f57fd9d 148 // Clear stop request
kayekss 0:d9789f57fd9d 149 request = NONE;
kayekss 0:d9789f57fd9d 150 break;
kayekss 0:d9789f57fd9d 151 case PLAY1_REQUEST: case PLAY2_REQUEST: case PLAY3_REQUEST: case PLAY4_REQUEST:
kayekss 0:d9789f57fd9d 152 fp = fopen(fileNameList[request - 1], "rb");
kayekss 0:d9789f57fd9d 153 if (fp) {
kayekss 0:d9789f57fd9d 154 // Power supply on
kayekss 0:d9789f57fd9d 155 audioPower = 1;
kayekss 0:d9789f57fd9d 156 led = 1;
kayekss 0:d9789f57fd9d 157
kayekss 0:d9789f57fd9d 158 totalSizeSent = 0;
kayekss 0:d9789f57fd9d 159 state = (State) request;
kayekss 0:d9789f57fd9d 160 lcd.locate(15, 0);
kayekss 0:d9789f57fd9d 161 lcd.printf("*");
kayekss 0:d9789f57fd9d 162 } else {
kayekss 0:d9789f57fd9d 163 lcd.locate(0, 1);
kayekss 0:d9789f57fd9d 164 lcd.printf("File Open Error ");
kayekss 0:d9789f57fd9d 165 }
kayekss 0:d9789f57fd9d 166 // Clear play request
kayekss 0:d9789f57fd9d 167 request = NONE;
kayekss 0:d9789f57fd9d 168 break;
kayekss 0:d9789f57fd9d 169 default:
kayekss 0:d9789f57fd9d 170 break;
kayekss 0:d9789f57fd9d 171 }
kayekss 0:d9789f57fd9d 172 break;
kayekss 0:d9789f57fd9d 173 case PLAYING1: case PLAYING2: case PLAYING3: case PLAYING4:
kayekss 0:d9789f57fd9d 174 if (request == NONE) {
kayekss 0:d9789f57fd9d 175 sizeRead = fread(buf, sizeof(uint8_t), BLOCK_SIZE, fp);
kayekss 0:d9789f57fd9d 176 if (sizeRead) {
kayekss 0:d9789f57fd9d 177 totalSizeSent += mp3.sendDataBlock(buf, sizeRead);
kayekss 0:d9789f57fd9d 178 } else {
kayekss 0:d9789f57fd9d 179 // Close the track
kayekss 0:d9789f57fd9d 180 fclose(fp);
kayekss 0:d9789f57fd9d 181 lcd.locate(15, 0);
kayekss 0:d9789f57fd9d 182 lcd.printf(" ");
kayekss 0:d9789f57fd9d 183
kayekss 0:d9789f57fd9d 184 // Invoke play request again
kayekss 0:d9789f57fd9d 185 request = (Request) state;
kayekss 0:d9789f57fd9d 186 state = READY;
kayekss 0:d9789f57fd9d 187 }
kayekss 0:d9789f57fd9d 188 } else {
kayekss 0:d9789f57fd9d 189 // Cancel current track when something's requested
kayekss 0:d9789f57fd9d 190 fclose(fp);
kayekss 0:d9789f57fd9d 191 lcd.locate(15, 0);
kayekss 0:d9789f57fd9d 192 lcd.printf(" ");
kayekss 0:d9789f57fd9d 193 state = CANCELING;
kayekss 0:d9789f57fd9d 194 }
kayekss 0:d9789f57fd9d 195 break;
kayekss 0:d9789f57fd9d 196 case CANCELING:
kayekss 0:d9789f57fd9d 197 if (mp3.sendCancel()) {
kayekss 0:d9789f57fd9d 198 state = STOPPING;
kayekss 0:d9789f57fd9d 199 }
kayekss 0:d9789f57fd9d 200 break;
kayekss 0:d9789f57fd9d 201 case STOPPING:
kayekss 0:d9789f57fd9d 202 if (mp3.stop()) {
kayekss 0:d9789f57fd9d 203 state = READY;
kayekss 0:d9789f57fd9d 204 }
kayekss 0:d9789f57fd9d 205 if (request == STOP_REQUEST) {
kayekss 0:d9789f57fd9d 206 // Clear stop request
kayekss 0:d9789f57fd9d 207 request = NONE;
kayekss 0:d9789f57fd9d 208
kayekss 0:d9789f57fd9d 209 // Power supply off
kayekss 0:d9789f57fd9d 210 audioPower = 0;
kayekss 0:d9789f57fd9d 211 led = 0;
kayekss 0:d9789f57fd9d 212 }
kayekss 0:d9789f57fd9d 213 break;
kayekss 0:d9789f57fd9d 214 default:
kayekss 0:d9789f57fd9d 215 break;
kayekss 0:d9789f57fd9d 216 }
kayekss 0:d9789f57fd9d 217 }
kayekss 0:d9789f57fd9d 218
kayekss 0:d9789f57fd9d 219 /** Print build timestamp (in JST) */
kayekss 0:d9789f57fd9d 220 void printTimestamp() {
kayekss 0:d9789f57fd9d 221 time_t secBuild;
kayekss 0:d9789f57fd9d 222 struct tm *tmBuild;
kayekss 0:d9789f57fd9d 223 char sbuf[11];
kayekss 0:d9789f57fd9d 224
kayekss 0:d9789f57fd9d 225 secBuild = MBED_BUILD_TIMESTAMP + 9 * 60 * 60;
kayekss 0:d9789f57fd9d 226 tmBuild = localtime(&secBuild);
kayekss 0:d9789f57fd9d 227
kayekss 0:d9789f57fd9d 228 strftime(sbuf, 11, "%Y-%m-%d", tmBuild);
kayekss 0:d9789f57fd9d 229 lcd.locate(0, 0);
kayekss 0:d9789f57fd9d 230 lcd.printf("Build %8s", sbuf);
kayekss 0:d9789f57fd9d 231 wait(0.0);
kayekss 0:d9789f57fd9d 232 strftime(sbuf, 11, "%H:%M:%S", tmBuild);
kayekss 0:d9789f57fd9d 233 lcd.locate(0, 1);
kayekss 0:d9789f57fd9d 234 lcd.printf(" T%8s", sbuf);
kayekss 0:d9789f57fd9d 235 wait(2.0);
kayekss 0:d9789f57fd9d 236 }
kayekss 0:d9789f57fd9d 237
kayekss 0:d9789f57fd9d 238 /** Test files in the SD memory card */
kayekss 0:d9789f57fd9d 239 uint8_t testFiles() {
kayekss 0:d9789f57fd9d 240 FILE *fpTest = NULL;
kayekss 0:d9789f57fd9d 241 bool sdTestResult = 0x00;
kayekss 0:d9789f57fd9d 242
kayekss 0:d9789f57fd9d 243 lcd.cls();
kayekss 0:d9789f57fd9d 244 lcd.locate(0, 0);
kayekss 0:d9789f57fd9d 245 lcd.printf("No memory cards ");
kayekss 0:d9789f57fd9d 246 wait(0.0);
kayekss 0:d9789f57fd9d 247 lcd.locate(0, 0);
kayekss 0:d9789f57fd9d 248 lcd.printf("Track / / / Ok");
kayekss 0:d9789f57fd9d 249 for (uint8_t i = 1; i <= 4; i++) {
kayekss 0:d9789f57fd9d 250 fpTest = fopen(fileNameList[i - 1], "rb");
kayekss 0:d9789f57fd9d 251 if (fpTest) {
kayekss 0:d9789f57fd9d 252 lcd.locate(2 * i + 4, 0);
kayekss 0:d9789f57fd9d 253 lcd.printf("%d", i);
kayekss 0:d9789f57fd9d 254 fclose(fpTest);
kayekss 0:d9789f57fd9d 255 } else {
kayekss 0:d9789f57fd9d 256 sdTestResult |= 0x01 << (i - 1);
kayekss 0:d9789f57fd9d 257 }
kayekss 0:d9789f57fd9d 258 }
kayekss 0:d9789f57fd9d 259 lcd.locate(0, 1);
kayekss 0:d9789f57fd9d 260 if (sdTestResult == 0x00) {
kayekss 0:d9789f57fd9d 261 lcd.printf("SD Test Pass ");
kayekss 0:d9789f57fd9d 262 wait(1.0);
kayekss 0:d9789f57fd9d 263 lcd.cls();
kayekss 0:d9789f57fd9d 264 } else {
kayekss 0:d9789f57fd9d 265 lcd.printf("SD Test Fail ");
kayekss 0:d9789f57fd9d 266 }
kayekss 0:d9789f57fd9d 267 return sdTestResult;
kayekss 0:d9789f57fd9d 268 }
kayekss 0:d9789f57fd9d 269
kayekss 0:d9789f57fd9d 270 /** Main routine */
kayekss 0:d9789f57fd9d 271 int main(void) {
kayekss 0:d9789f57fd9d 272 setup();
kayekss 0:d9789f57fd9d 273
kayekss 0:d9789f57fd9d 274 // Print build timestamp
kayekss 0:d9789f57fd9d 275 printTimestamp();
kayekss 0:d9789f57fd9d 276
kayekss 0:d9789f57fd9d 277 // Test files: Enter an infinite loop on failure
kayekss 0:d9789f57fd9d 278 if (testFiles()) {
kayekss 0:d9789f57fd9d 279 while (1) {
kayekss 0:d9789f57fd9d 280 led = 1;
kayekss 0:d9789f57fd9d 281 wait(0.5);
kayekss 0:d9789f57fd9d 282 led = 0;
kayekss 0:d9789f57fd9d 283 wait(0.5);
kayekss 0:d9789f57fd9d 284 }
kayekss 0:d9789f57fd9d 285 }
kayekss 0:d9789f57fd9d 286
kayekss 0:d9789f57fd9d 287 // Set Ticker interrupt routine
kayekss 0:d9789f57fd9d 288 tic.attach(&pollAndRequest, POLL_INTERVAL_SEC);
kayekss 0:d9789f57fd9d 289
kayekss 0:d9789f57fd9d 290 // Main loop
kayekss 0:d9789f57fd9d 291 while (1) {
kayekss 0:d9789f57fd9d 292 controlTrack();
kayekss 0:d9789f57fd9d 293 }
kayekss 0:d9789f57fd9d 294 }