| 248 |
Kevin |
1 |
#include <msp430.h>
|
|
|
2 |
#include <stdio.h>
|
|
|
3 |
#include <stdlib.h>
|
|
|
4 |
|
|
|
5 |
#include "hal_SPI.h"
|
|
|
6 |
#include "mmc.h"
|
|
|
7 |
#include "diskio.h"
|
|
|
8 |
#include "pff.h"
|
|
|
9 |
#include "player.h"
|
|
|
10 |
#include "adxl345.h"
|
|
|
11 |
|
|
|
12 |
/**
|
|
|
13 |
* Takes an initialized DIR and returns the number of sub-dir and files
|
|
|
14 |
*/
|
|
|
15 |
FRESULT directory_info(char *path, int *dir_count, int *file_count) {
|
|
|
16 |
FILINFO finfo;
|
|
|
17 |
FRESULT result;
|
|
|
18 |
DIR dir;
|
|
|
19 |
|
|
|
20 |
*dir_count = 0;
|
|
|
21 |
*file_count = 0;
|
|
|
22 |
|
|
|
23 |
result = pf_opendir(&dir, path);
|
|
|
24 |
if (result == FR_OK) {
|
|
|
25 |
for (;;) {
|
|
|
26 |
result = pf_readdir(&dir, &finfo);
|
|
|
27 |
// Break upon end of list
|
|
|
28 |
if (result != FR_OK || finfo.fname[0] == 0) break;
|
|
|
29 |
// Increment the directory or file count
|
|
|
30 |
if (finfo.fattrib & AM_DIR) {
|
|
|
31 |
*dir_count = *dir_count + 1;
|
|
|
32 |
} else {
|
|
|
33 |
*file_count = *file_count + 1;
|
|
|
34 |
}
|
|
|
35 |
}
|
|
|
36 |
}
|
|
|
37 |
|
|
|
38 |
return result;
|
|
|
39 |
}
|
|
|
40 |
|
|
|
41 |
static int file_count, dir_count;
|
|
|
42 |
static char filename[16];
|
|
|
43 |
|
|
|
44 |
int main(void) {
|
|
|
45 |
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
|
|
|
46 |
|
|
|
47 |
/* --- Set Oscillator Settings (8Mhz) --------------- */
|
|
|
48 |
// Set DCO to 5, MOD to 0
|
|
|
49 |
DCOCTL = CALDCO_16MHZ;
|
|
|
50 |
// Set RSEL to 13
|
|
|
51 |
BCSCTL1 = CALBC1_16MHZ;
|
|
|
52 |
// MCLK = DCO/1, SMCLK = MCLK/1
|
|
|
53 |
BCSCTL2 = SELM_0 | DIVM_0 | DIVS_0;
|
|
|
54 |
// LFXT1 = VLOCLK, 1pF termination
|
|
|
55 |
BCSCTL3 = LFXT1S_2 | XCAP_0;
|
|
|
56 |
// Disable oscillator fault interrupt
|
|
|
57 |
IE1 &= ~OFIE;
|
|
|
58 |
/* -------------------------------------------------- */
|
|
|
59 |
|
|
|
60 |
/* --- Initialize I/O Ports ------------------------- */
|
|
|
61 |
P2SEL = 0x0; // P2SEL resets to 0xC0
|
|
|
62 |
|
| 251 |
Kevin |
63 |
// SPI Pins (idle low)
|
|
|
64 |
SPI_PxOUT &= ~(SPI_SIMO + SPI_SOMI + SPI_UCLK);
|
|
|
65 |
SPI_PxDIR |= SPI_SIMO + SPI_UCLK;
|
|
|
66 |
SPI_PxDIR &= ~SPI_SOMI;
|
|
|
67 |
SPI_PxREN |= SPI_SOMI;
|
|
|
68 |
|
| 248 |
Kevin |
69 |
// SD Chip Select (idle high)
|
|
|
70 |
MMC_CS_PxOUT |= MMC_CS;
|
|
|
71 |
MMC_CS_PxDIR |= MMC_CS;
|
|
|
72 |
|
|
|
73 |
// SD Card Detect (input)
|
|
|
74 |
MMC_CD_PxDIR &= ~MMC_CD;
|
|
|
75 |
|
|
|
76 |
// VS1053 Chip Select (idle high)
|
|
|
77 |
VS10XX_CS_PxOUT |= VS10XX_CS;
|
|
|
78 |
VS10XX_CS_PxDIR |= VS10XX_CS;
|
|
|
79 |
|
|
|
80 |
// VS1053 Data/Command Select (idle high)
|
|
|
81 |
VS10XX_DC_PxOUT |= VS10XX_DC;
|
|
|
82 |
VS10XX_DC_PxDIR |= VS10XX_DC;
|
|
|
83 |
|
|
|
84 |
// VS1053 DREQ Line (input)
|
|
|
85 |
VS10XX_DREQ_PxDIR &= ~VS10XX_DREQ;
|
|
|
86 |
|
|
|
87 |
// Accelerometer Chip Select (idle high)
|
|
|
88 |
ADXL_CS_PxOUT |= ADXL_CS;
|
|
|
89 |
ADXL_CS_PxDIR |= ADXL_CS;
|
|
|
90 |
|
|
|
91 |
// Accelerometer Interrupt 1 (input)
|
|
|
92 |
ADXL_INT1_PxDIR &= ~ADXL_INT1;
|
|
|
93 |
ADXL_INT1_PxIES |= ADXL_INT1; // Interrupt on High -> Low
|
|
|
94 |
ADXL_INT1_PxIFG &= ~ADXL_INT1; // Clear interrupt flag
|
|
|
95 |
|
|
|
96 |
// Accelerometer Interrupt 2 (input)
|
|
|
97 |
ADXL_INT2_PxDIR &= ~ADXL_INT2;
|
|
|
98 |
// ADXL_INT2_PxIES |= ADXL_INT2; // Interrupt on High -> Low
|
|
|
99 |
// ADXL_INT2_PxIFG &= ~ADXL_INT2; // Clear interrupt flag
|
|
|
100 |
// ADXL_INT2_PxIE |= ADXL_INT2; // Enable interrupt
|
|
|
101 |
|
|
|
102 |
// Reset (idle low)
|
|
|
103 |
CHIP_RESET_PxOUT &= ~CHIP_RESET;
|
|
|
104 |
CHIP_RESET_PxDIR |= CHIP_RESET;
|
|
|
105 |
|
|
|
106 |
// Red LED (idle low)
|
|
|
107 |
LED_RED_PxOUT &= ~LED_RED;
|
|
|
108 |
LED_RED_PxDIR |= LED_RED;
|
|
|
109 |
|
|
|
110 |
// Green LED (idle low)
|
|
|
111 |
LED_GREEN_PxOUT &= ~LED_GREEN;
|
|
|
112 |
LED_GREEN_PxDIR |= LED_GREEN;
|
|
|
113 |
|
|
|
114 |
// Initialize port 3 even though it doesnt exist on the device
|
|
|
115 |
P3DIR = 0xFF;
|
|
|
116 |
P3OUT = 0x00;
|
|
|
117 |
/* -------------------------------------------------- */
|
|
|
118 |
|
|
|
119 |
unsigned char status = 1;
|
|
|
120 |
int acc_x, acc_y, acc_z;
|
|
|
121 |
FATFS fs;
|
|
|
122 |
FRESULT result = FR_NOT_READY;
|
|
|
123 |
|
| 251 |
Kevin |
124 |
// Delay for a bit to ensure that SD card powers up
|
|
|
125 |
__delay_cycles(16000);
|
|
|
126 |
|
| 248 |
Kevin |
127 |
// Init SPI Module
|
|
|
128 |
halSPISetup();
|
|
|
129 |
|
|
|
130 |
// Attempt the startup procedure four times
|
|
|
131 |
int i;
|
|
|
132 |
for (i = 0; i < 4; i++) {
|
|
|
133 |
|
|
|
134 |
// Initialize the accelerometer
|
|
|
135 |
if (ADXLInit() == 0) {
|
|
|
136 |
|
|
|
137 |
// Sum the accelerometer values to seed the randomizer
|
|
|
138 |
ADXLRead(&acc_x, &acc_y, &acc_z);
|
|
|
139 |
srand(acc_x + acc_y + acc_z);
|
|
|
140 |
|
|
|
141 |
// Mount the SD card
|
|
|
142 |
result = pf_mount(&fs);
|
|
|
143 |
if (result == FR_OK) {
|
|
|
144 |
|
|
|
145 |
// Acquire the number of subdirectories and files in the root directory
|
|
|
146 |
result = directory_info("/", &dir_count, &file_count);
|
|
|
147 |
|
|
|
148 |
if (result == FR_OK && file_count > 0) {
|
|
|
149 |
|
|
|
150 |
CHIP_RESET_HIGH();
|
|
|
151 |
|
|
|
152 |
if (VS1053Init() == 0) {
|
|
|
153 |
LED_GREEN_HIGH();
|
|
|
154 |
__delay_cycles(1000000);
|
|
|
155 |
LED_GREEN_LOW();
|
|
|
156 |
|
|
|
157 |
// If everything went well, play the first track
|
|
|
158 |
status = 0;
|
|
|
159 |
VS1053PlayFile("track1.mp3");
|
|
|
160 |
break;
|
|
|
161 |
|
|
|
162 |
} else { // VS1053Init()
|
|
|
163 |
continue;
|
|
|
164 |
}
|
|
|
165 |
|
|
|
166 |
} else { // directory_info
|
|
|
167 |
continue;
|
|
|
168 |
}
|
|
|
169 |
|
|
|
170 |
} else { // pf_mount()
|
|
|
171 |
continue;
|
|
|
172 |
}
|
|
|
173 |
|
|
|
174 |
} else { // ADXLInit()
|
|
|
175 |
continue;
|
|
|
176 |
}
|
|
|
177 |
}
|
|
|
178 |
|
|
|
179 |
// If everything is ok, enable accelerometer interrupts
|
| 251 |
Kevin |
180 |
if (status != 0) {
|
| 248 |
Kevin |
181 |
// Otherwise turn off everything
|
|
|
182 |
LED_RED_HIGH();
|
|
|
183 |
void ADXLStandbyOn(void);
|
| 251 |
Kevin |
184 |
|
|
|
185 |
} else {
|
|
|
186 |
ADXL_INT1_PxIE |= ADXL_INT1; // Enable interrupt
|
|
|
187 |
ADXLInitInterrupts();
|
| 248 |
Kevin |
188 |
}
|
|
|
189 |
|
| 251 |
Kevin |
190 |
// LED_RED_HIGH();
|
| 248 |
Kevin |
191 |
// Turn off all chips except the accelerometer
|
|
|
192 |
CHIP_RESET_LOW();
|
|
|
193 |
_BIS_SR(LPM4_bits + GIE);
|
| 251 |
Kevin |
194 |
while(1);
|
| 248 |
Kevin |
195 |
}
|
|
|
196 |
|
|
|
197 |
#pragma vector=PORT1_VECTOR
|
|
|
198 |
__interrupt void Port1_Interrupt(void) {
|
|
|
199 |
|
|
|
200 |
if (ADXL_INT1_PxIFG & ADXL_INT1) {
|
|
|
201 |
LED_GREEN_HIGH();
|
|
|
202 |
|
|
|
203 |
// Bring chips out of low-power state
|
|
|
204 |
CHIP_RESET_HIGH();
|
|
|
205 |
VSInitSoftware();
|
|
|
206 |
|
|
|
207 |
// Play a random file
|
|
|
208 |
int i = (rand() % file_count) + 1;
|
|
|
209 |
snprintf(filename, 16, "track%d.mp3", i);
|
|
|
210 |
VS1053PlayFile(filename);
|
|
|
211 |
|
|
|
212 |
// Return chips to low-power state
|
|
|
213 |
CHIP_RESET_LOW();
|
|
|
214 |
|
| 251 |
Kevin |
215 |
// Clear the interrupts on the ADXL chip
|
|
|
216 |
ADXLClearInterrupts();
|
|
|
217 |
|
| 248 |
Kevin |
218 |
// Clear the interrupt flag
|
|
|
219 |
ADXL_INT1_PxIFG &= ~ADXL_INT1;
|
| 251 |
Kevin |
220 |
|
|
|
221 |
LED_GREEN_LOW();
|
| 248 |
Kevin |
222 |
}
|
|
|
223 |
|
|
|
224 |
// if (ADXL_INT2_PxIFG & ADXL_INT2) {
|
|
|
225 |
// LED_RED_HIGH();
|
|
|
226 |
// __delay_cycles(2000000);
|
|
|
227 |
// LED_RED_LOW();
|
|
|
228 |
//
|
|
|
229 |
// // Clear the interrupt flag
|
|
|
230 |
// ADXL_INT2_PxIFG &= ~ADXL_INT2;
|
|
|
231 |
// }
|
|
|
232 |
|
|
|
233 |
}
|