MP3-capable chair with sensor-embedded weight scale.

Dependencies:   ACM1602 SDFileSystem VS1053 mbed ClockControl PowerControl

Files at this revision

API Documentation at this revision

Comitter:
kayekss
Date:
Wed Mar 26 19:56:18 2014 +0000
Child:
1:ef257d63d970
Commit message:
MP3-capable chair with sensor-embedded weight scale.

Changed in this revision

ACM1602.lib Show annotated file Show diff for this revision Revisions of this file
HysteresisIn.lib Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
VS1053.lib Show annotated file Show diff for this revision Revisions of this file
defs.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ACM1602.lib	Wed Mar 26 19:56:18 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/kayekss/code/ACM1602/#f81621685b23
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HysteresisIn.lib	Wed Mar 26 19:56:18 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/kayekss/code/HysteresisIn/#fe43537bd3d6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Wed Mar 26 19:56:18 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/SDFileSystem/#c8f66dc765d4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VS1053.lib	Wed Mar 26 19:56:18 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/kayekss/code/VS1053/#1f57fbd3aeb5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/defs.h	Wed Mar 26 19:56:18 2014 +0000
@@ -0,0 +1,77 @@
+#ifndef ISU_PROJECT_DEFS_H_
+#define ISU_PROJECT_DEFS_H_
+
+// Input thresholds
+#define HIGH_TO_LOW        0.25
+#define LOW_TO_HIGH        0.75
+
+// Delay count until settling
+#define SETTLING_COUNT        5
+
+// Polling interval (second)
+#define POLL_INTERVAL_SEC  0.50
+
+// Block size of read/write (byte)
+#define BLOCK_SIZE         1024
+
+typedef enum {
+    CANCELING = -1,
+    STOPPING  = -2,
+    READY     =  0,
+    PLAYING1  =  1,
+    PLAYING2  =  2,
+    PLAYING3  =  3,
+    PLAYING4  =  4
+} State;
+
+typedef enum {
+    STOP_REQUEST  = -1,
+    NONE          =  0,
+    PLAY1_REQUEST =  1,
+    PLAY2_REQUEST =  2,
+    PLAY3_REQUEST =  3,
+    PLAY4_REQUEST =  4
+} Request;
+
+PinName const xp5  = P0_9;   // SPI1 + MOSI
+PinName const xp6  = P0_8;   //      | MISO
+PinName const xp7  = P0_7;   //      | SCK
+PinName const xp8  = P0_6;   //      | SSEL#
+PinName const xp9  = P0_0;   // UART3+ Tx     I2C1 + SDA
+PinName const xp10 = P0_1;   //      | Rx          | SCL
+PinName const xp11 = P0_18;  //               SPI0 + MOSI
+PinName const xp12 = P0_17;  //                    | MISO
+PinName const xp13 = P0_15;  // UART1+ Tx          | SCK
+PinName const xp14 = P0_16;  //      | Rx          | SSEL#
+PinName const xp15 = P0_23;  // AnalogIn
+PinName const xp16 = P0_24;  // AnalogIn
+PinName const xp17 = P0_25;  // AnalogIn
+PinName const xp18 = P0_26;  // AnalogIn  AnalogOut
+PinName const xp19 = P1_30;  // AnalogIn
+PinName const xp20 = P1_31;  // AnalogIn
+PinName const xp21 = P0_2;
+PinName const xp22 = P0_3;
+PinName const xp23 = P0_21;
+PinName const xp24 = P0_22;
+PinName const xp25 = P0_27;  // **Open drain
+PinName const xp26 = P0_28;  // **Open drain
+PinName const xp27 = P2_13;
+PinName const xp53 = P2_12;
+PinName const xp52 = P2_11;
+PinName const xp51 = P2_10;
+PinName const xp50 = P2_8;
+PinName const xp49 = P2_7;
+PinName const xp48 = P2_6;
+PinName const xp47 = P2_5;   // PwmOut
+PinName const xp46 = P2_4;   // PwmOut
+PinName const xp45 = P2_3;   // PwmOut
+PinName const xp44 = P2_2;   // PwmOut
+PinName const xp43 = P2_1;   // PwmOut
+PinName const xp42 = P2_0;   // PwmOut
+PinName const xp41 = P0_11;  // UART2+ Rx     I2C2 + SCL
+PinName const xp40 = P0_10;  //      | Tx          | SDA
+PinName const xp39 = P0_5;   // CAN  + TD
+PinName const xp38 = P0_4;   //      | RD
+PinName const LED0 = P0_22;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Mar 26 19:56:18 2014 +0000
@@ -0,0 +1,294 @@
+#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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Mar 26 19:56:18 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/7d30d6019079
\ No newline at end of file