Subversion Repositories Code-Repo

Rev

Blame | Last modification | View Log | RSS feed

#include <msp430.h>
#include <stdio.h>
#include <stdlib.h>

#include "hal_SPI.h"
#include "mmc.h"
#include "diskio.h"
#include "pff.h"
#include "player.h"
#include "adxl345.h"

/**
 * Takes an initialized DIR and returns the number of sub-dir and files
 */
FRESULT directory_info(char *path, int *dir_count, int *file_count) {
        FILINFO finfo;
        FRESULT result;
        DIR dir;

        *dir_count = 0;
        *file_count = 0;

        result = pf_opendir(&dir, path);
        if (result == FR_OK) {
                for (;;) {
                        result = pf_readdir(&dir, &finfo);
                        // Break upon end of list
                        if (result != FR_OK || finfo.fname[0] == 0) break;
                        // Increment the directory or file count
                        if (finfo.fattrib & AM_DIR) {
                                *dir_count = *dir_count + 1;
                        } else {
                                *file_count = *file_count + 1;
                        }
                }
        }

        return result;
}

static int file_count, dir_count;
static char filename[16];

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer

    /* --- Set Oscillator Settings (8Mhz) --------------- */
    // Set DCO to 5, MOD to 0
    DCOCTL = CALDCO_16MHZ;
    // Set RSEL to 13
        BCSCTL1 = CALBC1_16MHZ;
        // MCLK = DCO/1, SMCLK = MCLK/1
        BCSCTL2 = SELM_0 | DIVM_0 | DIVS_0;
        // LFXT1 = VLOCLK, 1pF termination
        BCSCTL3 = LFXT1S_2 | XCAP_0;
        // Disable oscillator fault interrupt
        IE1 &= ~OFIE;
        /* -------------------------------------------------- */

        /* --- Initialize I/O Ports ------------------------- */
        P2SEL = 0x0;    // P2SEL resets to 0xC0

        // SD Chip Select (idle high)
        MMC_CS_PxOUT |= MMC_CS;
        MMC_CS_PxDIR |= MMC_CS;

        // SD Card Detect (input)
        MMC_CD_PxDIR &= ~MMC_CD;

        // VS1053 Chip Select (idle high)
        VS10XX_CS_PxOUT |= VS10XX_CS;
        VS10XX_CS_PxDIR |= VS10XX_CS;

        // VS1053 Data/Command Select (idle high)
        VS10XX_DC_PxOUT |= VS10XX_DC;
        VS10XX_DC_PxDIR |= VS10XX_DC;

        // VS1053 DREQ Line (input)
        VS10XX_DREQ_PxDIR &= ~VS10XX_DREQ;

        // Accelerometer Chip Select (idle high)
        ADXL_CS_PxOUT |= ADXL_CS;
        ADXL_CS_PxDIR |= ADXL_CS;

        // Accelerometer Interrupt 1 (input)
        ADXL_INT1_PxDIR &= ~ADXL_INT1;
        ADXL_INT1_PxIES |= ADXL_INT1;   // Interrupt on High -> Low
        ADXL_INT1_PxIFG &= ~ADXL_INT1;  // Clear interrupt flag
        ADXL_INT1_PxIE  |= ADXL_INT1;   // Enable interrupt

        // Accelerometer Interrupt 2 (input)
        ADXL_INT2_PxDIR &= ~ADXL_INT2;
//      ADXL_INT2_PxIES |= ADXL_INT2;   // Interrupt on High -> Low
//      ADXL_INT2_PxIFG &= ~ADXL_INT2;  // Clear interrupt flag
//      ADXL_INT2_PxIE  |= ADXL_INT2;   // Enable interrupt

        // Reset (idle low)
        CHIP_RESET_PxOUT &= ~CHIP_RESET;
        CHIP_RESET_PxDIR |= CHIP_RESET;

        // Red LED (idle low)
        LED_RED_PxOUT &= ~LED_RED;
        LED_RED_PxDIR |= LED_RED;

        // Green LED (idle low)
        LED_GREEN_PxOUT &= ~LED_GREEN;
        LED_GREEN_PxDIR |= LED_GREEN;

        // Initialize port 3 even though it doesnt exist on the device
        P3DIR = 0xFF;
        P3OUT = 0x00;
        /* -------------------------------------------------- */

        unsigned char status = 1;
        int acc_x, acc_y, acc_z;
        FATFS fs;
        FRESULT result = FR_NOT_READY;

        // Init SPI Module
        halSPISetup();

//      __delay_cycles(32000000);

        // Attempt the startup procedure four times
        int i;
        for (i = 0; i < 4; i++) {

                // Initialize the accelerometer
                if (ADXLInit() == 0) {

                        // Sum the accelerometer values to seed the randomizer
                        ADXLRead(&acc_x, &acc_y, &acc_z);
                        srand(acc_x + acc_y + acc_z);

                        // Mount the SD card
                        result = pf_mount(&fs);
                        if (result == FR_OK) {

                                // Acquire the number of subdirectories and files in the root directory
                                result = directory_info("/", &dir_count, &file_count);

                                if (result == FR_OK && file_count > 0) {

                                        CHIP_RESET_HIGH();

                                        if (VS1053Init() == 0) {
                                                LED_GREEN_HIGH();
                                                __delay_cycles(1000000);
                                                LED_GREEN_LOW();

                                                // If everything went well, play the first track
                                                status = 0;
                                                VS1053PlayFile("track1.mp3");
                                                break;

                                        } else { // VS1053Init()
                                                continue;
                                        }

                                } else { // directory_info
                                        continue;
                                }

                        } else { // pf_mount()
                                continue;
                        }

                } else { // ADXLInit()
                        continue;
                }
        }

        // If everything is ok, enable accelerometer interrupts
        if (status == 0) {
                ADXLInitInterrupts();
        } else {
                // Otherwise turn off everything
                LED_RED_HIGH();
                void ADXLStandbyOn(void);
        }

        // Turn off all chips except the accelerometer
        CHIP_RESET_LOW();
        _BIS_SR(LPM4_bits + GIE);

}

#pragma vector=PORT1_VECTOR
__interrupt void Port1_Interrupt(void) {

        if (ADXL_INT1_PxIFG & ADXL_INT1) {
                LED_GREEN_HIGH();
                __delay_cycles(1000000);
                LED_GREEN_LOW();

                // Bring chips out of low-power state
                CHIP_RESET_HIGH();
                VSInitSoftware();

                // Play a random file
                int i = (rand() % file_count) + 1;
                snprintf(filename, 16, "track%d.mp3", i);
                VS1053PlayFile(filename);

                // Return chips to low-power state
                CHIP_RESET_LOW();

                // Clear the interrupt flag
                ADXL_INT1_PxIFG &= ~ADXL_INT1;
        }

//      if (ADXL_INT2_PxIFG & ADXL_INT2) {
//              LED_RED_HIGH();
//              __delay_cycles(2000000);
//              LED_RED_LOW();
//
//              // Clear the interrupt flag
//              ADXL_INT2_PxIFG &= ~ADXL_INT2;
//      }

        ADXLClearInterrupts();
}