diff --git a/final_project/sd_reader/comms.h b/final_project/sd_reader/comms.h index ad5c9e6..0df4d06 120000 --- a/final_project/sd_reader/comms.h +++ b/final_project/sd_reader/comms.h @@ -1 +1,81 @@ -../comms/comms.h \ No newline at end of file +#ifndef COMMS_H_ +#define COMMS_H_ + +#include +#include + + +/** + * Our format goes like this: + * + * 1 byte command, with data after + */ + + +typedef enum { + COMMS_CMD_CLR = 0U, //! Clears LCD and all file names + COMMS_CMD_NUM, //! sends the total number of songs to choose from + COMMS_CMD_QUERY_NUM, + COMMS_CMD_QUERY_NAME, //! Queries for the name of a given song ID + COMMS_CMD_REPLY_NAME, //! Responds with the name of the given song ID + COMMS_CMD_SELECT_FILE, //! selects a file from the given list to play, data is 1 byte for id + COMMS_CMD_PLAY, //! Starts playing file + COMMS_CMD_PAUSE //! pauses playing file +} comms_cmd_t; + +/** @brief Inline function to send commands and values. + */ +inline void comms_send(comms_cmd_t cmd) { + + while (! (UCSR0A & (1 << UDRE0))); + UDR0 = cmd; +} + +/** @brief Selects a file from the list on the DAC side. + * + * If another song is playing, this will stop + * that song from playing and select the new one. + */ +inline void comms_select_file(uint8_t id) { + comms_send(COMMS_CMD_SELECT_FILE); + comms_send((comms_cmd_t) id); +} + +/** @brief Queries for the name of the given song ID. + */ +inline void comms_query_name(uint8_t id) { + comms_send(COMMS_CMD_QUERY_NAME); + comms_send(id); +} + +/** @brief Repliers with the name of the requsted song ID + */ +inline void comms_reply_name(char* name) { + uint8_t len = strlen(name); + comms_send(COMMS_CMD_REPLY_NAME); + comms_send(len); + + for (uint8_t i = 0; i < len; i++) { + comms_send((uint8_t) name[i]); + } +} + +/** @brief Clears the LCD list of files. + */ +inline void comms_clear() { + comms_send(COMMS_CMD_CLR); +} + +/** @brief Starts playing song. + */ +inline void comms_play() { + comms_send(COMMS_CMD_PLAY); +} + +/** @brief Pauses playing song. + */ +inline void comms_pause() { + comms_send(COMMS_CMD_PLAY); +} + +#endif \ No newline at end of file diff --git a/final_project/sd_reader/main.c b/final_project/sd_reader/main.c index cc71de1..a727ecd 100644 --- a/final_project/sd_reader/main.c +++ b/final_project/sd_reader/main.c @@ -20,13 +20,15 @@ uint8_t cmd_state; // Song playing // TODO fix this atrocious naming -uint16_t song_buf[2][SONG_BUF_LEN]; //! Buffers to play song from +uint8_t song_buf[2][SONG_BUF_LEN]; //! Buffers to play song from uint8_t song_position; //! where we are in the buffers bool song_buf_select; //! which buffer we're using bool song_selected; //! Flag to say we just selected the song, read data in int8_t song_selection = -1; //! ID of selected song uint32_t song_len; uint32_t song_read_position; +bool send_number_of_songs = true; +uint8_t num_songs = 0; typedef struct { @@ -41,6 +43,7 @@ int main() gpio_init(); timer_init(); usart_init(); + sei(); // TODO set SPI to highest freq possible, might just need tweaking sd_raw_init(); @@ -101,9 +104,13 @@ int main() // Move on to reading next song song_id++; } + } - + + num_songs = song_id; + + // Print out all files/directories in top level while (1) { /// do stuff @@ -133,6 +140,10 @@ int main() // Wait for next loop to handle file info cmd_depth = 1; break; + case (COMMS_CMD_QUERY_NUM): + comms_send(COMMS_CMD_NUM); + comms_send(num_songs); + break; } } @@ -140,18 +151,17 @@ int main() if (cmd_depth == 1) { uint8_t song_id; - if (fifo_pop(&song_id) == FIFO_SUCCESS) { - switch (cmd_state) { - case (COMMS_CMD_SELECT_FILE): - // select proper song and begin reading in - song_selection = song_id; - song_selected = 1; - break; - case (COMMS_CMD_QUERY_NAME): - // Just going to hope we can bump the UART baudrate up high enough - comms_reply_name(songs[song_id].name); - break; - } + while (fifo_pop(&song_id) != FIFO_SUCCESS); + switch (cmd_state) { + case (COMMS_CMD_SELECT_FILE): + // select proper song and begin reading in + song_selection = song_id; + song_selected = 1; + break; + case (COMMS_CMD_QUERY_NAME): + // Just going to hope we can bump the UART baudrate up high enough + comms_reply_name(songs[song_id].name); + break; } } @@ -192,7 +202,7 @@ int main() // We are now at the actual data // divide by two to get uint16 - song_len = header.cksize / 2; + song_len = header.cksize; song_read_position = 0; } @@ -206,7 +216,7 @@ int main() // Read in file // 512 bytes to read, 256 samples - fat_read_file(songs[song_selection].fd, (uint8_t*) song_buf[read_song_buf], 512); + fat_read_file(songs[song_selection].fd, (uint8_t*) song_buf[read_song_buf], 256); song_read_position += 256; // If we selected the song, make sure we start playing from the right buffer diff --git a/final_project/sd_reader/main.h b/final_project/sd_reader/main.h index 9540d36..789f2ba 100644 --- a/final_project/sd_reader/main.h +++ b/final_project/sd_reader/main.h @@ -1,11 +1,15 @@ #ifndef MAIN_H_ #define MAIN_H_ +#define F_CPU 8000000UL + #include #include #include #include #include +#include +#include #include "fat.h" #include "fat_config.h" #include "partition.h" @@ -21,8 +25,9 @@ // Song playing -extern uint16_t song_buf[2][SONG_BUF_LEN]; //! Buffers to play song from +extern uint8_t song_buf[2][SONG_BUF_LEN]; //! Buffers to play song from extern uint8_t song_position; //! where we are in the buffers extern bool song_buf_select; //! which buffer we're using +extern bool send_number_of_songs; #endif \ No newline at end of file diff --git a/final_project/sd_reader/periph.c b/final_project/sd_reader/periph.c index e0a2f36..b263830 100644 --- a/final_project/sd_reader/periph.c +++ b/final_project/sd_reader/periph.c @@ -4,14 +4,15 @@ /** @brief intercepts incoming Serial commands */ ISR(USART_RX_vect) { + cli(); // Read byte into FIFO - fifo_push(UDR0); + uint8_t in_byte = UDR0; + fifo_push(in_byte); // Flag is cleared by reading data from UDR sei(); } - /** @brief Interrupt handler for actually playing music * * Will only be called if the TIFR OCF0A flag is high, using that as our play/pause flag @@ -29,19 +30,11 @@ ISR(TIMER0_COMPA_vect) { * * DAC12 and DAC13 are PB0 and PB1 */ - uint16_t in_data = song_buf[song_buf_select][song_position]; - // Split into 8 bit because we are using an 8 bit MCU, so code can be better - uint8_t data_lo = in_data; - uint8_t data_hi = in_data >> 8; - + uint8_t in_data = song_buf[song_buf_select][song_position]; // DAC0 -> DAC5 - PORTC = (data_lo >> 2) & 0x3F; // DAC6 -> DAC11 - PORTD &= 0x03; - PORTD |= data_hi << 2; - // DAC12 and DAC13 - PORTB &= 0xFC; // clear bits - PORTB |= data_hi >> 6; + PORTD &= in_data & 0xFC; + PORTB &= in_data & 0x03; // Go to next sample song_position++; @@ -66,7 +59,7 @@ void gpio_init() { void timer_init() { // Compare outputs should be default, nothing // Set to CTC, WGM = 0b010 - TCCR0A = (1 << OCIE0A); + TCCR0A = (1 << WGM01); // Set timer to use clock input w/o prescaling TCCR0B = 1; @@ -76,16 +69,21 @@ void timer_init() { OCR0A = 182; // Don't enable the interrupt yet + } void usart_init() { // set baudrate UBRR0L = UBRR_VALUE & 255; UBRR0H = UBRR_VALUE >> 8; + // Start it up + UCSR0B |= (1 << TXEN0) | (1 << RXEN0); // Set data info, no parity, 1 stop, 8-bit UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00); - // Start it up - UCSR0B |= (1 << TXEN0) | (1 << RXEN0); + + + // Enable interrupt + UCSR0B |= (1 << RXCIE0); } \ No newline at end of file