MP3-capable chair with sensor-embedded weight scale.
Dependencies: HysteresisIn LCD SDFileSystem VS1053 mbed
main.cpp
- Committer:
- kayekss
- Date:
- 2013-12-20
- Revision:
- 0:0451ba2f1062
File content as of revision 0:0451ba2f1062:
#include <stdio.h> #include "mbed.h" #include "defs.h" #include "pinalias.h" #include "HysteresisIn.h" #include "SDFileSystem.h" #include "VS1053.h" #include "LCD.h" SDFileSystem sd(/*MOSI*/ D11, /*MISO*/ D12, /*SCK*/ D13, /*CS*/ D10, "sd"); VS1053 mp3(/*MOSI*/ D11, /*MISO*/ D12, /*SCK*/ D13, /*CS*/ D9, /*BSYNC*/ D8, /*DREQ*/ D7, /*RST*/ D6, /*SPI freq.*/ 6000000); HysteresisIn sens3(A3, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #3 (Outer) HysteresisIn sens2(A2, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #2 HysteresisIn sens1(A1, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #1 HysteresisIn sens0(A0, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #0 (Inner) LCD lcd(/*SDA*/ D107, /*SCL*/ D106, /*RESET*/ D105, /*Backlight*/ NC, /*Contrast*/ 40); BusOut led(/*Red*/ P3, /*Yellow*/ P4, /*Green*/ P5, /*Blue*/ P6, /*White*/ P7); Ticker tic; const char *fileNameList[] = { "", "/sd/Track1.mp3", "/sd/Track2.mp3", "/sd/Track3.mp3", "/sd/Track4.mp3" }; volatile State state = READY; volatile Request request = NONE; /** Setups and initializations */ void setup(void) { // Initialize VS1053 mp3.hardwareReset(); mp3.clockUp(); wait(0.1); // Setup LCD lcd.reset(); lcd.cls(); // Initialize LCD led = 0x00; } /** Read voltages from photo sensor pins and detect weightscale point code */ int readPhotoSensors(void) { uint8_t bitPattern; // Read all photo sensor inputs bitPattern = sens3.read() << 3 | sens2.read() << 2 | sens1.read() << 1 | sens0.read(); switch (bitPattern) { // 1 when open, 0 when shut // Higher bit is on outer side case 0xf: // 1111: no load return 0; case 0xe: // 1110: slight load return 1; case 0xc: // 1100 return 2; case 0x8: // 1000 return 3; case 0x0: // 0000: heavy load return 4; default: // Other than expectation: erroneous pattern return -1; } } /** Poll/sample weightscale inputs and issue requests */ void pollAndRequest() { const char* stateNameList[] = { "STOPPING", // -2 "CANCELING", // -1 "READY", // 0 "PLAYING1", // 1 "PLAYING2", // 2 "PLAYING3", // 3 "PLAYING4" // 4 }; const uint8_t ledPatternList[] = { 0x10, // -1 STOP_REQUEST W---- 0x00, // 0 NONE ----- 0x01, // 1 PLAY1_REQUEST ----R 0x02, // 2 PLAY2_REQUEST ---Y- 0x04, // 3 PLAY3_REQUEST --G-- 0x08 // 4 PLAY4_REQUEST -B--- }; int code; static int codePrev = 0; static uint8_t holdTimes = 0; // Get weightscale point code by reading photo sensors code = readPhotoSensors(); // Count the times that the given code persists if (code == codePrev && code != -1) { if (holdTimes < 99) { holdTimes++; } } else { holdTimes = 0; } lcd.locate(0, 0); lcd.printf("%-15s", stateNameList[state + 2]); lcd.locate(0, 1); lcd.printf("ps=%2d times=%2d", code, holdTimes); // Once the point is stable enough, make a request if (holdTimes == SETTLING_COUNT) { if (code == 0) { // Stable no load: stop request request = STOP_REQUEST; } else { // Certain stable load: play request 1..4 // Ignore cases while playing the same track if (state != code) { request = (Request) code; } } } // Set LED as the request led = ledPatternList[request + 1]; // Preserve this time's code codePrev = code; } /** Player control in accordance with requests */ void controlTrack() { static FILE *fp = NULL; size_t sizeRead = 0; uint8_t buf[BLOCK_SIZE]; static size_t totalSizeSent = 0; switch (state) { case READY: switch (request) { case STOP_REQUEST: // Clear stop request request = NONE; break; case PLAY1_REQUEST: case PLAY2_REQUEST: case PLAY3_REQUEST: case PLAY4_REQUEST: fp = fopen(fileNameList[request], "rb"); if (fp) { totalSizeSent = 0; state = (State) request; lcd.locate(15, 0); lcd.printf("*"); } // Clear play request request = NONE; break; default: break; } break; case PLAYING1: case PLAYING2: case PLAYING3: case PLAYING4: if (request == NONE) { if (feof(fp)) { // Close the track fclose(fp); lcd.locate(15, 0); lcd.printf(" "); // Invoke play request again request = (Request) state; state = READY; } else { sizeRead = fread(buf, sizeof(char), BLOCK_SIZE, fp); totalSizeSent += mp3.sendDataBlock(buf, sizeRead); } } else { // Cancel current track when something's requested fclose(fp); lcd.locate(15, 0); lcd.printf(" "); state = CANCELING; } break; case CANCELING: if (mp3.sendCancel()) { state = STOPPING; } break; case STOPPING: if (mp3.stop()) { state = READY; } if (request == STOP_REQUEST) { // Clear stop request request = NONE; } break; default: break; } } /** Main routine */ int main(void) { FILE *fpTest = NULL; time_t secBuild; struct tm *tmBuild; char sbuf[10]; bool sdTestResult = 0x00; setup(); // Print build timestamp (in JST) secBuild = MBED_BUILD_TIMESTAMP + 9 * 60 * 60; tmBuild = localtime(&secBuild); strftime(sbuf, 10, "%Y-%m-%d", tmBuild); lcd.locate(0, 0); lcd.printf("Build %8s", sbuf); wait(0.0); strftime(sbuf, 10, "%H:%M:%S", tmBuild); lcd.locate(0, 1); lcd.printf(" T%8s", sbuf); wait(2.0); // SD card test lcd.cls(); lcd.locate(0, 0); lcd.printf("No memory cards "); wait(0.0); lcd.locate(0, 0); lcd.printf("Track / / / Ok"); for (uint8_t i = 1; i <= 4; i++) { fpTest = fopen(fileNameList[i], "rb"); if (fpTest) { lcd.locate(2 * i + 4, 0); lcd.printf("%d", i); fclose(fpTest); } else { sdTestResult |= 0x01 << (i - 1); } } lcd.locate(0, 1); if (sdTestResult == 0x00) { lcd.printf("SD Test Pass "); } else { lcd.printf("SD Test Fail "); while (1) { led = sdTestResult; wait(0.5); led = 0x00; wait(0.5); } } wait(1.0); lcd.cls(); // Set Ticker interrupt routine tic.attach(&pollAndRequest, POLL_INTERVAL_SEC); // Main loop while (1) { controlTrack(); } }