Rev 248 | 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
// SPI Pins (idle low)
SPI_PxOUT &= ~(SPI_SIMO + SPI_SOMI + SPI_UCLK);
SPI_PxDIR |= SPI_SIMO + SPI_UCLK;
SPI_PxDIR &= ~SPI_SOMI;
SPI_PxREN |= SPI_SOMI;
// 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
// 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;
// Delay for a bit to ensure that SD card powers up
__delay_cycles(16000);
// Init SPI Module
halSPISetup();
// 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) {
// Otherwise turn off everything
LED_RED_HIGH();
void ADXLStandbyOn(void);
} else {
ADXL_INT1_PxIE |= ADXL_INT1; // Enable interrupt
ADXLInitInterrupts();
}
// LED_RED_HIGH();
// Turn off all chips except the accelerometer
CHIP_RESET_LOW();
_BIS_SR(LPM4_bits + GIE);
while(1);
}
#pragma vector=PORT1_VECTOR
__interrupt void Port1_Interrupt(void) {
if (ADXL_INT1_PxIFG & ADXL_INT1) {
LED_GREEN_HIGH();
// 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 interrupts on the ADXL chip
ADXLClearInterrupts();
// Clear the interrupt flag
ADXL_INT1_PxIFG &= ~ADXL_INT1;
LED_GREEN_LOW();
}
// if (ADXL_INT2_PxIFG & ADXL_INT2) {
// LED_RED_HIGH();
// __delay_cycles(2000000);
// LED_RED_LOW();
//
// // Clear the interrupt flag
// ADXL_INT2_PxIFG &= ~ADXL_INT2;
// }
}