MP3-capable chair with sensor-embedded weight scale.
Dependencies: ACM1602 SDFileSystem VS1053 mbed ClockControl PowerControl
main.cpp
- Committer:
- kayekss
- Date:
- 2014-03-26
- Revision:
- 0:d9789f57fd9d
- Child:
- 1:ef257d63d970
File content as of revision 0:d9789f57fd9d:
#include <stdio.h> #include "mbed.h" #include "defs.h" #include "HysteresisIn.h" #include "SDFileSystem.h" #include "VS1053.h" #include "ACM1602.h" // Pin settings for LPC1768(LPCXpresso) SDFileSystem sd(/*MOSI*/ xp11, /*MISO*/ xp12, /*SCK*/ xp13, /*CS*/ xp53, /*Mountpoint*/ "sd"); VS1053 mp3(/*MOSI*/ xp11, /*MISO*/ xp12, /*SCK*/ xp13, /*CS*/ xp52, /*BSYNC*/ xp51, /*DREQ*/ xp50, /*RST*/ xp49, /*SPI freq.*/ 6000000); HysteresisIn sens3(p17, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #3 (Outer) HysteresisIn sens2(p18, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #2 HysteresisIn sens1(p19, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #1 HysteresisIn sens0(p20, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #0 (Inner) ACM1602 lcd(/*SDA*/ xp9, /*SCL*/ xp10, /*Address*/ 0xa0); DigitalOut led(LED0); DigitalOut audioPower(xp38); Ticker tic; // Pin settings for LPC1114FN28 (SD card accessing does not work) // SDFileSystem sd(/*MOSI*/ dp2, /*MISO*/ dp1, /*SCK*/ dp6, /*CS*/ dp4, /*Mountpoint*/ "sd"); // VS1053 mp3(/*MOSI*/ dp2, /*MISO*/ dp1, /*SCK*/ dp6, // /*CS*/ dp14, /*BSYNC*/ dp17, /*DREQ*/ dp18, /*RST*/ dp25, /*SPI freq.*/ 4000000); // HysteresisIn sens3(dp9, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #3 (Outer) // HysteresisIn sens2(dp10, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #2 // HysteresisIn sens1(dp11, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #1 // HysteresisIn sens0(dp13, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #0 (Inner) // ACM1602 lcd(/*SDA*/ dp5, /*SCL*/ dp27, /*Address*/ 0xa0); // 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; /** Setup and initializations */ void setup(void) { // Initialize VS1053 mp3.hardwareReset(); mp3.clockUp(); wait(0.1); // Initialize power supply for audio amplifier circuit audioPower = 0; // Setup LCD lcd.init(); // Initialize LED led = 0; } /** 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 }; 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; } } } // 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 - 1], "rb"); if (fp) { // Power supply on audioPower = 1; led = 1; totalSizeSent = 0; state = (State) request; lcd.locate(15, 0); lcd.printf("*"); } else { lcd.locate(0, 1); lcd.printf("File Open Error "); } // Clear play request request = NONE; break; default: break; } break; case PLAYING1: case PLAYING2: case PLAYING3: case PLAYING4: if (request == NONE) { sizeRead = fread(buf, sizeof(uint8_t), BLOCK_SIZE, fp); if (sizeRead) { totalSizeSent += mp3.sendDataBlock(buf, sizeRead); } else { // Close the track fclose(fp); lcd.locate(15, 0); lcd.printf(" "); // Invoke play request again request = (Request) state; state = READY; } } 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; // Power supply off audioPower = 0; led = 0; } break; default: break; } } /** Print build timestamp (in JST) */ void printTimestamp() { time_t secBuild; struct tm *tmBuild; char sbuf[11]; secBuild = MBED_BUILD_TIMESTAMP + 9 * 60 * 60; tmBuild = localtime(&secBuild); strftime(sbuf, 11, "%Y-%m-%d", tmBuild); lcd.locate(0, 0); lcd.printf("Build %8s", sbuf); wait(0.0); strftime(sbuf, 11, "%H:%M:%S", tmBuild); lcd.locate(0, 1); lcd.printf(" T%8s", sbuf); wait(2.0); } /** Test files in the SD memory card */ uint8_t testFiles() { FILE *fpTest = NULL; bool sdTestResult = 0x00; 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 - 1], "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 "); wait(1.0); lcd.cls(); } else { lcd.printf("SD Test Fail "); } return sdTestResult; } /** Main routine */ int main(void) { setup(); // Print build timestamp printTimestamp(); // Test files: Enter an infinite loop on failure if (testFiles()) { while (1) { led = 1; wait(0.5); led = 0; wait(0.5); } } // Set Ticker interrupt routine tic.attach(&pollAndRequest, POLL_INTERVAL_SEC); // Main loop while (1) { controlTrack(); } }