MP3-capable chair with sensor-embedded weight scale.

Dependencies:   HysteresisIn LCD SDFileSystem VS1053 mbed

Files at this revision

API Documentation at this revision

Comitter:
kayekss
Date:
Fri Dec 20 21:35:07 2013 +0000
Commit message:
First commit

Changed in this revision

HysteresisIn.lib Show annotated file Show diff for this revision Revisions of this file
LCD.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
pinalias.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HysteresisIn.lib	Fri Dec 20 21:35:07 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/kayekss/code/HysteresisIn/#fe43537bd3d6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LCD.lib	Fri Dec 20 21:35:07 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/yamaguch/code/LCD/#b3def1d4f466
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Fri Dec 20 21:35:07 2013 +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	Fri Dec 20 21:35:07 2013 +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	Fri Dec 20 21:35:07 2013 +0000
@@ -0,0 +1,36 @@
+#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;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Dec 20 21:35:07 2013 +0000
@@ -0,0 +1,269 @@
+#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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Dec 20 21:35:07 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/f37f3b9c9f0b
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pinalias.h	Fri Dec 20 21:35:07 2013 +0000
@@ -0,0 +1,40 @@
+#ifndef PIN_ALIAS_H_
+#define PIN_ALIAS_H_
+
+// Pin aliases for KL25Z
+#define D100  PTC7
+#define D101  PTC0
+#define D102  PTC3
+#define D103  PTC4
+#define D104  PTC5
+#define D105  PTC6
+#define D106  PTC10
+#define D107  PTC11
+#define D108  PTC12
+#define D109  PTC13
+#define D110  PTC16
+#define D111  PTC17
+#define D112  PTA16
+#define D113  PTA17
+#define D114  PTE31
+#define D115  NC
+#define D116  PTD6
+#define D117  PTD7
+
+#define A10   PTC20
+#define A11   PTC21
+#define A12   PTC22
+#define A13   PTC23
+#define A14   PTC29
+#define A15   PTC30
+
+#define P0    PTB8
+#define P1    PTB9
+#define P2    PTB10
+#define P3    PTB11
+#define P4    PTE2
+#define P5    PTE3
+#define P6    PTE4
+#define P7    PTE5
+
+#endif