MP3-capable chair with sensor-embedded weight scale.
Dependencies: ACM1602 SDFileSystem VS1053 mbed ClockControl PowerControl
main.cpp
- Committer:
- kayekss
- Date:
- 2014-03-29
- Revision:
- 2:844bedc9dc63
- Parent:
- 1:ef257d63d970
- Child:
- 3:64f0ba828a2e
File content as of revision 2:844bedc9dc63:
#include <stdio.h> #include "mbed.h" #include "defs.h" #include "HysteresisIn.h" #include "SDFileSystem.h" #include "VS1053.h" #include "ACM1602.h" #include "ClockControl.h" #include "EthernetPowerControl.h" #include "PowerControl.h" // Pin settings for mbed LPC1768 SDFileSystem sd(/*MOSI*/ p11, /*MISO*/ p12, /*SCK*/ p13, /*CS*/ p21, /*Mountpoint*/ "sd"); VS1053 mp3(/*MOSI*/ p11, /*MISO*/ p12, /*SCK*/ p13, /*CS*/ p22, /*BSYNC*/ p23, /*DREQ*/ p24, /*RST*/ p25, /*SPI freq.*/ 4000000); HysteresisIn sens3(p17, H_TO_L_THRES, L_TO_H_THRES, 1); // Photo sensor #3 (Outer) HysteresisIn sens2(p18, H_TO_L_THRES, L_TO_H_THRES, 1); // Photo sensor #2 HysteresisIn sens1(p19, H_TO_L_THRES, L_TO_H_THRES, 1); // Photo sensor #1 HysteresisIn sens0(p20, H_TO_L_THRES, L_TO_H_THRES, 1); // Photo sensor #0 (Inner) ACM1602 lcd(/*SDA*/ p9, /*SCL*/ p10, /*Address*/ 0xa0); DigitalOut audioPower(p30); DigitalIn test3(p17); DigitalIn test2(p18); DigitalIn test1(p19); DigitalIn test0(p20); DigitalIn inputSelector(p8); // Set unused pins to input when using the LPCXpresso board BusIn __dummy(xp21, xp22, xp23, xp24, xp49, xp50, xp51, xp52, xp53); Ticker tic; bool inputFrom; size_t totalSizeSent; 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) { // Reduce system clock frequency to 48 MHz setSystemFrequency(0x3, 0x1, 6, 1); // Power down Ethernet PHY PHY_PowerDown(); // Set pull-up mode inputSelector.mode(PullUp); test3.mode(PullUp); test2.mode(PullUp); test1.mode(PullUp); test0.mode(PullUp); wait(0.1); // Initialize VS1053 mp3.hardwareReset(); mp3.clockUp(); wait(0.1); // Initialize power supply for audio amplifier circuit audioPower = 0; // Setup LCD lcd.init(); // Read input selector inputFrom = inputSelector; } /** Read voltages from photo sensor pins and detect weightscale point code */ int readPhotoSensors(void) { uint8_t bitPattern; // Read all photo sensor inputs if (inputFrom) { bitPattern = (test3 << 3) | (test2 << 2) | (test1 << 1) | test0; } else { 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; } // Print status to LCD: // current state, photo sensor inputs, hold count, // file size sent to VS1053 lcd.locate(0, 0); lcd.printf("%-9s in=%2d", stateNameList[state + 2], code); lcd.locate(0, 1); lcd.printf("x%2d ", holdTimes); switch (state) { case PLAYING1: case PLAYING2: case PLAYING3: case PLAYING4: if (totalSizeSent >= 1000000) { lcd.printf("%9.2f MB", totalSizeSent / 1048576.0); } else if (totalSizeSent >= 1000) { lcd.printf("%9.2f KB", totalSizeSent / 1024.0); } else { lcd.printf("%6d bytes", totalSizeSent); } break; default: lcd.printf(" <No File>"); break; } // 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]; 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) { clearerr(fp); // Power supply on audioPower = 1; totalSizeSent = 0; state = (State) request; } // Clear play request request = NONE; break; default: break; } break; case PLAYING1: case PLAYING2: case PLAYING3: case PLAYING4: if (request == NONE) { // Continue playback if (feof(fp)) { // Close when the track reaches the end fclose(fp); fp = NULL; // 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); fp = NULL; 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; } 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) {} } // Set Ticker interrupt routine tic.attach(&pollAndRequest, POLL_INTERVAL_SEC); // Main loop while (1) { controlTrack(); } }