MP3-capable chair with sensor-embedded weight scale.

Dependencies:   HysteresisIn LCD SDFileSystem VS1053 mbed

Committer:
kayekss
Date:
Fri Dec 20 21:35:07 2013 +0000
Revision:
0:0451ba2f1062
First commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kayekss 0:0451ba2f1062 1 #include <stdio.h>
kayekss 0:0451ba2f1062 2 #include "mbed.h"
kayekss 0:0451ba2f1062 3 #include "defs.h"
kayekss 0:0451ba2f1062 4 #include "pinalias.h"
kayekss 0:0451ba2f1062 5 #include "HysteresisIn.h"
kayekss 0:0451ba2f1062 6 #include "SDFileSystem.h"
kayekss 0:0451ba2f1062 7 #include "VS1053.h"
kayekss 0:0451ba2f1062 8 #include "LCD.h"
kayekss 0:0451ba2f1062 9
kayekss 0:0451ba2f1062 10 SDFileSystem sd(/*MOSI*/ D11, /*MISO*/ D12, /*SCK*/ D13, /*CS*/ D10, "sd");
kayekss 0:0451ba2f1062 11 VS1053 mp3(/*MOSI*/ D11, /*MISO*/ D12, /*SCK*/ D13,
kayekss 0:0451ba2f1062 12 /*CS*/ D9, /*BSYNC*/ D8, /*DREQ*/ D7, /*RST*/ D6, /*SPI freq.*/ 6000000);
kayekss 0:0451ba2f1062 13 HysteresisIn sens3(A3, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #3 (Outer)
kayekss 0:0451ba2f1062 14 HysteresisIn sens2(A2, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #2
kayekss 0:0451ba2f1062 15 HysteresisIn sens1(A1, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #1
kayekss 0:0451ba2f1062 16 HysteresisIn sens0(A0, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #0 (Inner)
kayekss 0:0451ba2f1062 17 LCD lcd(/*SDA*/ D107, /*SCL*/ D106, /*RESET*/ D105, /*Backlight*/ NC,
kayekss 0:0451ba2f1062 18 /*Contrast*/ 40);
kayekss 0:0451ba2f1062 19 BusOut led(/*Red*/ P3, /*Yellow*/ P4, /*Green*/ P5, /*Blue*/ P6, /*White*/ P7);
kayekss 0:0451ba2f1062 20 Ticker tic;
kayekss 0:0451ba2f1062 21
kayekss 0:0451ba2f1062 22 const char *fileNameList[] = {
kayekss 0:0451ba2f1062 23 "",
kayekss 0:0451ba2f1062 24 "/sd/Track1.mp3",
kayekss 0:0451ba2f1062 25 "/sd/Track2.mp3",
kayekss 0:0451ba2f1062 26 "/sd/Track3.mp3",
kayekss 0:0451ba2f1062 27 "/sd/Track4.mp3"
kayekss 0:0451ba2f1062 28 };
kayekss 0:0451ba2f1062 29
kayekss 0:0451ba2f1062 30 volatile State state = READY;
kayekss 0:0451ba2f1062 31 volatile Request request = NONE;
kayekss 0:0451ba2f1062 32
kayekss 0:0451ba2f1062 33 /** Setups and initializations */
kayekss 0:0451ba2f1062 34 void setup(void) {
kayekss 0:0451ba2f1062 35 // Initialize VS1053
kayekss 0:0451ba2f1062 36 mp3.hardwareReset();
kayekss 0:0451ba2f1062 37 mp3.clockUp();
kayekss 0:0451ba2f1062 38 wait(0.1);
kayekss 0:0451ba2f1062 39
kayekss 0:0451ba2f1062 40 // Setup LCD
kayekss 0:0451ba2f1062 41 lcd.reset();
kayekss 0:0451ba2f1062 42 lcd.cls();
kayekss 0:0451ba2f1062 43
kayekss 0:0451ba2f1062 44 // Initialize LCD
kayekss 0:0451ba2f1062 45 led = 0x00;
kayekss 0:0451ba2f1062 46 }
kayekss 0:0451ba2f1062 47
kayekss 0:0451ba2f1062 48 /** Read voltages from photo sensor pins and detect weightscale point code */
kayekss 0:0451ba2f1062 49 int readPhotoSensors(void) {
kayekss 0:0451ba2f1062 50 uint8_t bitPattern;
kayekss 0:0451ba2f1062 51
kayekss 0:0451ba2f1062 52 // Read all photo sensor inputs
kayekss 0:0451ba2f1062 53 bitPattern = sens3.read() << 3
kayekss 0:0451ba2f1062 54 | sens2.read() << 2
kayekss 0:0451ba2f1062 55 | sens1.read() << 1
kayekss 0:0451ba2f1062 56 | sens0.read();
kayekss 0:0451ba2f1062 57
kayekss 0:0451ba2f1062 58 switch (bitPattern) {
kayekss 0:0451ba2f1062 59 // 1 when open, 0 when shut
kayekss 0:0451ba2f1062 60 // Higher bit is on outer side
kayekss 0:0451ba2f1062 61 case 0xf: // 1111: no load
kayekss 0:0451ba2f1062 62 return 0;
kayekss 0:0451ba2f1062 63 case 0xe: // 1110: slight load
kayekss 0:0451ba2f1062 64 return 1;
kayekss 0:0451ba2f1062 65 case 0xc: // 1100
kayekss 0:0451ba2f1062 66 return 2;
kayekss 0:0451ba2f1062 67 case 0x8: // 1000
kayekss 0:0451ba2f1062 68 return 3;
kayekss 0:0451ba2f1062 69 case 0x0: // 0000: heavy load
kayekss 0:0451ba2f1062 70 return 4;
kayekss 0:0451ba2f1062 71 default: // Other than expectation: erroneous pattern
kayekss 0:0451ba2f1062 72 return -1;
kayekss 0:0451ba2f1062 73 }
kayekss 0:0451ba2f1062 74 }
kayekss 0:0451ba2f1062 75
kayekss 0:0451ba2f1062 76 /** Poll/sample weightscale inputs and issue requests */
kayekss 0:0451ba2f1062 77 void pollAndRequest() {
kayekss 0:0451ba2f1062 78 const char* stateNameList[] = {
kayekss 0:0451ba2f1062 79 "STOPPING", // -2
kayekss 0:0451ba2f1062 80 "CANCELING", // -1
kayekss 0:0451ba2f1062 81 "READY", // 0
kayekss 0:0451ba2f1062 82 "PLAYING1", // 1
kayekss 0:0451ba2f1062 83 "PLAYING2", // 2
kayekss 0:0451ba2f1062 84 "PLAYING3", // 3
kayekss 0:0451ba2f1062 85 "PLAYING4" // 4
kayekss 0:0451ba2f1062 86 };
kayekss 0:0451ba2f1062 87 const uint8_t ledPatternList[] = {
kayekss 0:0451ba2f1062 88 0x10, // -1 STOP_REQUEST W----
kayekss 0:0451ba2f1062 89 0x00, // 0 NONE -----
kayekss 0:0451ba2f1062 90 0x01, // 1 PLAY1_REQUEST ----R
kayekss 0:0451ba2f1062 91 0x02, // 2 PLAY2_REQUEST ---Y-
kayekss 0:0451ba2f1062 92 0x04, // 3 PLAY3_REQUEST --G--
kayekss 0:0451ba2f1062 93 0x08 // 4 PLAY4_REQUEST -B---
kayekss 0:0451ba2f1062 94 };
kayekss 0:0451ba2f1062 95 int code;
kayekss 0:0451ba2f1062 96 static int codePrev = 0;
kayekss 0:0451ba2f1062 97 static uint8_t holdTimes = 0;
kayekss 0:0451ba2f1062 98
kayekss 0:0451ba2f1062 99 // Get weightscale point code by reading photo sensors
kayekss 0:0451ba2f1062 100 code = readPhotoSensors();
kayekss 0:0451ba2f1062 101
kayekss 0:0451ba2f1062 102 // Count the times that the given code persists
kayekss 0:0451ba2f1062 103 if (code == codePrev && code != -1) {
kayekss 0:0451ba2f1062 104 if (holdTimes < 99) {
kayekss 0:0451ba2f1062 105 holdTimes++;
kayekss 0:0451ba2f1062 106 }
kayekss 0:0451ba2f1062 107 } else {
kayekss 0:0451ba2f1062 108 holdTimes = 0;
kayekss 0:0451ba2f1062 109 }
kayekss 0:0451ba2f1062 110 lcd.locate(0, 0);
kayekss 0:0451ba2f1062 111 lcd.printf("%-15s", stateNameList[state + 2]);
kayekss 0:0451ba2f1062 112 lcd.locate(0, 1);
kayekss 0:0451ba2f1062 113 lcd.printf("ps=%2d times=%2d", code, holdTimes);
kayekss 0:0451ba2f1062 114
kayekss 0:0451ba2f1062 115 // Once the point is stable enough, make a request
kayekss 0:0451ba2f1062 116 if (holdTimes == SETTLING_COUNT) {
kayekss 0:0451ba2f1062 117 if (code == 0) {
kayekss 0:0451ba2f1062 118 // Stable no load: stop request
kayekss 0:0451ba2f1062 119 request = STOP_REQUEST;
kayekss 0:0451ba2f1062 120 } else {
kayekss 0:0451ba2f1062 121 // Certain stable load: play request 1..4
kayekss 0:0451ba2f1062 122 // Ignore cases while playing the same track
kayekss 0:0451ba2f1062 123 if (state != code) {
kayekss 0:0451ba2f1062 124 request = (Request) code;
kayekss 0:0451ba2f1062 125 }
kayekss 0:0451ba2f1062 126 }
kayekss 0:0451ba2f1062 127 }
kayekss 0:0451ba2f1062 128
kayekss 0:0451ba2f1062 129 // Set LED as the request
kayekss 0:0451ba2f1062 130 led = ledPatternList[request + 1];
kayekss 0:0451ba2f1062 131
kayekss 0:0451ba2f1062 132 // Preserve this time's code
kayekss 0:0451ba2f1062 133 codePrev = code;
kayekss 0:0451ba2f1062 134 }
kayekss 0:0451ba2f1062 135
kayekss 0:0451ba2f1062 136 /** Player control in accordance with requests */
kayekss 0:0451ba2f1062 137 void controlTrack() {
kayekss 0:0451ba2f1062 138 static FILE *fp = NULL;
kayekss 0:0451ba2f1062 139 size_t sizeRead = 0;
kayekss 0:0451ba2f1062 140 uint8_t buf[BLOCK_SIZE];
kayekss 0:0451ba2f1062 141 static size_t totalSizeSent = 0;
kayekss 0:0451ba2f1062 142
kayekss 0:0451ba2f1062 143 switch (state) {
kayekss 0:0451ba2f1062 144 case READY:
kayekss 0:0451ba2f1062 145 switch (request) {
kayekss 0:0451ba2f1062 146 case STOP_REQUEST:
kayekss 0:0451ba2f1062 147 // Clear stop request
kayekss 0:0451ba2f1062 148 request = NONE;
kayekss 0:0451ba2f1062 149 break;
kayekss 0:0451ba2f1062 150 case PLAY1_REQUEST: case PLAY2_REQUEST: case PLAY3_REQUEST: case PLAY4_REQUEST:
kayekss 0:0451ba2f1062 151 fp = fopen(fileNameList[request], "rb");
kayekss 0:0451ba2f1062 152 if (fp) {
kayekss 0:0451ba2f1062 153 totalSizeSent = 0;
kayekss 0:0451ba2f1062 154 state = (State) request;
kayekss 0:0451ba2f1062 155 lcd.locate(15, 0);
kayekss 0:0451ba2f1062 156 lcd.printf("*");
kayekss 0:0451ba2f1062 157 }
kayekss 0:0451ba2f1062 158 // Clear play request
kayekss 0:0451ba2f1062 159 request = NONE;
kayekss 0:0451ba2f1062 160 break;
kayekss 0:0451ba2f1062 161 default:
kayekss 0:0451ba2f1062 162 break;
kayekss 0:0451ba2f1062 163 }
kayekss 0:0451ba2f1062 164 break;
kayekss 0:0451ba2f1062 165 case PLAYING1: case PLAYING2: case PLAYING3: case PLAYING4:
kayekss 0:0451ba2f1062 166 if (request == NONE) {
kayekss 0:0451ba2f1062 167 if (feof(fp)) {
kayekss 0:0451ba2f1062 168 // Close the track
kayekss 0:0451ba2f1062 169 fclose(fp);
kayekss 0:0451ba2f1062 170 lcd.locate(15, 0);
kayekss 0:0451ba2f1062 171 lcd.printf(" ");
kayekss 0:0451ba2f1062 172
kayekss 0:0451ba2f1062 173 // Invoke play request again
kayekss 0:0451ba2f1062 174 request = (Request) state;
kayekss 0:0451ba2f1062 175 state = READY;
kayekss 0:0451ba2f1062 176 } else {
kayekss 0:0451ba2f1062 177 sizeRead = fread(buf, sizeof(char), BLOCK_SIZE, fp);
kayekss 0:0451ba2f1062 178 totalSizeSent += mp3.sendDataBlock(buf, sizeRead);
kayekss 0:0451ba2f1062 179 }
kayekss 0:0451ba2f1062 180 } else {
kayekss 0:0451ba2f1062 181 // Cancel current track when something's requested
kayekss 0:0451ba2f1062 182 fclose(fp);
kayekss 0:0451ba2f1062 183 lcd.locate(15, 0);
kayekss 0:0451ba2f1062 184 lcd.printf(" ");
kayekss 0:0451ba2f1062 185 state = CANCELING;
kayekss 0:0451ba2f1062 186 }
kayekss 0:0451ba2f1062 187 break;
kayekss 0:0451ba2f1062 188 case CANCELING:
kayekss 0:0451ba2f1062 189 if (mp3.sendCancel()) {
kayekss 0:0451ba2f1062 190 state = STOPPING;
kayekss 0:0451ba2f1062 191 }
kayekss 0:0451ba2f1062 192 break;
kayekss 0:0451ba2f1062 193 case STOPPING:
kayekss 0:0451ba2f1062 194 if (mp3.stop()) {
kayekss 0:0451ba2f1062 195 state = READY;
kayekss 0:0451ba2f1062 196 }
kayekss 0:0451ba2f1062 197 if (request == STOP_REQUEST) {
kayekss 0:0451ba2f1062 198 // Clear stop request
kayekss 0:0451ba2f1062 199 request = NONE;
kayekss 0:0451ba2f1062 200 }
kayekss 0:0451ba2f1062 201 break;
kayekss 0:0451ba2f1062 202 default:
kayekss 0:0451ba2f1062 203 break;
kayekss 0:0451ba2f1062 204 }
kayekss 0:0451ba2f1062 205 }
kayekss 0:0451ba2f1062 206
kayekss 0:0451ba2f1062 207 /** Main routine */
kayekss 0:0451ba2f1062 208 int main(void) {
kayekss 0:0451ba2f1062 209 FILE *fpTest = NULL;
kayekss 0:0451ba2f1062 210 time_t secBuild;
kayekss 0:0451ba2f1062 211 struct tm *tmBuild;
kayekss 0:0451ba2f1062 212 char sbuf[10];
kayekss 0:0451ba2f1062 213 bool sdTestResult = 0x00;
kayekss 0:0451ba2f1062 214
kayekss 0:0451ba2f1062 215 setup();
kayekss 0:0451ba2f1062 216
kayekss 0:0451ba2f1062 217 // Print build timestamp (in JST)
kayekss 0:0451ba2f1062 218 secBuild = MBED_BUILD_TIMESTAMP + 9 * 60 * 60;
kayekss 0:0451ba2f1062 219 tmBuild = localtime(&secBuild);
kayekss 0:0451ba2f1062 220
kayekss 0:0451ba2f1062 221 strftime(sbuf, 10, "%Y-%m-%d", tmBuild);
kayekss 0:0451ba2f1062 222 lcd.locate(0, 0);
kayekss 0:0451ba2f1062 223 lcd.printf("Build %8s", sbuf);
kayekss 0:0451ba2f1062 224 wait(0.0);
kayekss 0:0451ba2f1062 225 strftime(sbuf, 10, "%H:%M:%S", tmBuild);
kayekss 0:0451ba2f1062 226 lcd.locate(0, 1);
kayekss 0:0451ba2f1062 227 lcd.printf(" T%8s", sbuf);
kayekss 0:0451ba2f1062 228 wait(2.0);
kayekss 0:0451ba2f1062 229
kayekss 0:0451ba2f1062 230 // SD card test
kayekss 0:0451ba2f1062 231 lcd.cls();
kayekss 0:0451ba2f1062 232 lcd.locate(0, 0);
kayekss 0:0451ba2f1062 233 lcd.printf("No memory cards ");
kayekss 0:0451ba2f1062 234 wait(0.0);
kayekss 0:0451ba2f1062 235 lcd.locate(0, 0);
kayekss 0:0451ba2f1062 236 lcd.printf("Track / / / Ok");
kayekss 0:0451ba2f1062 237 for (uint8_t i = 1; i <= 4; i++) {
kayekss 0:0451ba2f1062 238 fpTest = fopen(fileNameList[i], "rb");
kayekss 0:0451ba2f1062 239 if (fpTest) {
kayekss 0:0451ba2f1062 240 lcd.locate(2 * i + 4, 0);
kayekss 0:0451ba2f1062 241 lcd.printf("%d", i);
kayekss 0:0451ba2f1062 242 fclose(fpTest);
kayekss 0:0451ba2f1062 243 } else {
kayekss 0:0451ba2f1062 244 sdTestResult |= 0x01 << (i - 1);
kayekss 0:0451ba2f1062 245 }
kayekss 0:0451ba2f1062 246 }
kayekss 0:0451ba2f1062 247 lcd.locate(0, 1);
kayekss 0:0451ba2f1062 248 if (sdTestResult == 0x00) {
kayekss 0:0451ba2f1062 249 lcd.printf("SD Test Pass ");
kayekss 0:0451ba2f1062 250 } else {
kayekss 0:0451ba2f1062 251 lcd.printf("SD Test Fail ");
kayekss 0:0451ba2f1062 252 while (1) {
kayekss 0:0451ba2f1062 253 led = sdTestResult;
kayekss 0:0451ba2f1062 254 wait(0.5);
kayekss 0:0451ba2f1062 255 led = 0x00;
kayekss 0:0451ba2f1062 256 wait(0.5);
kayekss 0:0451ba2f1062 257 }
kayekss 0:0451ba2f1062 258 }
kayekss 0:0451ba2f1062 259 wait(1.0);
kayekss 0:0451ba2f1062 260 lcd.cls();
kayekss 0:0451ba2f1062 261
kayekss 0:0451ba2f1062 262 // Set Ticker interrupt routine
kayekss 0:0451ba2f1062 263 tic.attach(&pollAndRequest, POLL_INTERVAL_SEC);
kayekss 0:0451ba2f1062 264
kayekss 0:0451ba2f1062 265 // Main loop
kayekss 0:0451ba2f1062 266 while (1) {
kayekss 0:0451ba2f1062 267 controlTrack();
kayekss 0:0451ba2f1062 268 }
kayekss 0:0451ba2f1062 269 }