#include #include #include "common.h" #include "ata.h" /* Use STA013 MP3 decoder connected to PORTB as follows: [STA013] [ATmega103] 3 SDA - PB3 4 SCL - PB4 5 SDI - PB2 6 SCKL - PB5 26 RESET - PB0 28 DATA_REQ - PF6 */ #include "sta013.h" /* Use external RAM as a 32K buffer connected to PORTA and PORTC */ #include "buf.h" /* CD poll/update routine see ATAPI stuff for details */ #include "iso9660.h" //states for CD state machine #define CD_REQUEST 0 //request the next sector #define CD_WAIT1 1 //wait to send the ATAPI command #define CD_WAIT2 2 //wait for sector to come back #define CD_READ 3 //read some of the sector data char cd_state = CD_REQUEST; int cd_ctr = 0; //how much of the sector have we read back //CD polling state machine control void pollCD() { //if an error occured, probably because CD has been ejected... if(CDerror) { clear(); //stop playing mp3count = 0; //init CD stuff again cur_mp3 = 0; initCD(); disp_file(); cd_state = CD_REQUEST; CDerror = FALSE; } //run the CD state machine switch (cd_state) { case CD_REQUEST: cd_ctr = 0; requestNextSector1(); cd_state = CD_WAIT1; break; case CD_WAIT1: if(requestNextSector2()) cd_state = CD_WAIT2; break; case CD_WAIT2: if(ATAPI_sect_ready()) cd_state = CD_READ; break; case CD_READ: if(!SAFE_TO_PRODUCE) { #ifdef DEBUG2 printf("buffer full\n\r"); #endif return; } cd_ctr += fetchSomeData(buf+producer+cd_ctr); if (cd_ctr >= BUF_BLOCK_SIZE) { cd_state = CD_REQUEST; MULTI_PRODUCE; #ifdef DEBUG2 printf("2K produced\n\r"); #endif } break; default: cd_state = CD_REQUEST; } } /* Use 6 push-buttons connected to PINF (analog) as follows: [button] [ATmega103] 0 vol+ - PF0 1 vol- - PF1 2 track+ - PF2 3 track- - PF3 4 stop - PF4 5 play/pause - PF5 */ #define BUTTONS_PIN PINF #define BUTTONS_INIT {} #define BUTTONS_IN (BUTTONS_PIN & 0x3f) #define NUM_BUTS 6 bit but_ready = FALSE; char but_status[6] = {0,0,0,0,0,0}; void pollButs() { char but,x,y; if(!but_ready) return; but_ready = FALSE; but = BUTTONS_IN; y = 1; for(x=0;x 0) // was pressed before but_status[x] = -1; else if (but_status[x] < 0) but_status[x]++; } else { // pressed if(but_status[x] >= 16) // held down extra long but_status[x] = 1; else but_status[x]++; } if (but_status[x] == 1) { // new press switch(x) { case 0: decVolume(); break; case 1: incVolume(); break; case 2: prevTrack(); break; case 3: nextTrack(); break; // case 4: STOP // case 5: PLAY/PAUSE default: #ifdef DEBUG printf("ERROR: unknown button %02X\n\r",x); #endif lcd_line2("unknown button"); // non-fatal } } y = y << 1; } } void playLoop() { int ctr; // counter for transfer of full block char *dptr; // data pointer within consume block disp_file(); //display track info on the LCD while (1) { // wait for data #ifdef DEBUG2 if (!SAFE_TO_CONSUME) printf("buffer empty\n\r"); #endif while (!SAFE_TO_CONSUME) { // potentially critical polling pollCD(); if (SAFE_TO_CONSUME) break; pollButs(); }; //debugging code to check buffering // if (!SAFE_TO_CONSUME) { // lcd_clear(); // lcd_putsf("oops"); // delay_ms(1000); // } // while (1) { // if (SAFE_TO_CONSUME) { // lcd_clear(); // lcd_putsf("ok"); // break; // } // pollCD(); // if (SAFE_TO_CONSUME) { // lcd_clear(); // lcd_putsf("ok"); // break; // } // pollButs(); // // } // perform block transfer dptr = buf+consumer; #ifdef DEBUG2 if (!(DATAREQ_IN)) printf("DATAREQ not ready\n\r"); #endif for(ctr = 0; ctr < BUF_BLOCK_SIZE;ctr+=4) { // wait for data_req while (!(DATAREQ_IN)) { // non-critical polling now pollCD(); if(DATAREQ_IN) break; pollButs(); }; // send a few bytes play(*(dptr++)); play(*(dptr++)); play(*(dptr++)); play(*(dptr++)); } // declare block consumed MULTI_CONSUME; #ifdef DEBUG2 printf("2K block cosumed\n\r"); #endif } } #ifdef DEBUG int serialCount = 0; //UART character-ready ISR interrupt [UART_RXC] void uart_rxc(void) { char c; if (SAFE_TO_PRODUCE) { c = UDR; buf[producer+serialCount] = c; serialCount++; if (serialCount == BUF_BLOCK_SIZE) { MULTI_PRODUCE; #ifdef DEBUG2 printf("2K block produced [serial]\n\r"); #endif serialCount = 0; } } } #endif // Timer 0 overflow ISR interrupt [TIM0_COMP] void tim0_comp(void) { but_ready = TRUE; sec++; //increment time of current track being played if(scroll_max) //if we are scrolling if((sec&15) == 0) //every half second { if(scroll_dir) //check direction { scroll += 2; if(scroll>scroll_max) //reverse when we get to the end { scroll = scroll_max; scroll_dir = 0; } } else { scroll -= 2; if(scroll==-2) //reverse when we get to the end { scroll = 0; scroll_dir = 1; } } } } void init() { int x; //we need to setup some CDROM control signals ASAP DDRB.7 = 1; //set DIOW to output DDRB.6 = 1; //set DIOR to output DDRB.0 = 1; //set RESET to output PORTB.0 = 1; //turn off RESET PORTB.7 = 1; //turn off DIOW PORTB.6 = 1; //turn off DIOR #ifdef DEBUG // set up serial port UCR = 0x98; // (with Rx int enable) // UCR = 0x18; // (no Rx int enable) UBRR = 12; // 19200bps //UBRR = 25; // 9600bps printf("UART initialized\n\r"); #endif // initialize LCD #ifdef DEBUG printf("Initializing LCD...\n\r"); #endif lcd_init(24); // initialize the LCD for 24 char wide lcd_clear(); // clear it lcd_putsf("MP3 CD SuperJukeBox V1.0"); lcd_putsf("EE 476 Final Project"); // enable external SRAM DDRA = 0xff; MCUCR = MCUCR | 0x80; #ifdef DEBUG printf("Validating SRAM...\n\r"); #endif for(x=0;x> 7); SCKR_OUT(HIGH); #asm("nop"); #asm("nop"); SCKR_OUT(LOW); SDI_OUT(data >> 6); SCKR_OUT(HIGH); #asm("nop"); #asm("nop"); SCKR_OUT(LOW); SDI_OUT(data >> 5); SCKR_OUT(HIGH); #asm("nop"); #asm("nop"); SCKR_OUT(LOW); SDI_OUT(data >> 4); SCKR_OUT(HIGH); #asm("nop"); #asm("nop"); SCKR_OUT(LOW); SDI_OUT(data >> 3); SCKR_OUT(HIGH); #asm("nop"); #asm("nop"); SCKR_OUT(LOW); SDI_OUT(data >> 2); SCKR_OUT(HIGH); #asm("nop"); #asm("nop"); SCKR_OUT(LOW); SDI_OUT(data >> 1); SCKR_OUT(HIGH); #asm("nop"); #asm("nop"); SCKR_OUT(LOW); SDI_OUT(data >> 0); SCKR_OUT(HIGH); #asm("nop"); #asm("nop"); SCKR_OUT(LOW); } data = bi2c_get(HEADH); printf("read HEADH = %02X\n\r",data); data = bi2c_get(HEADM); printf("read HEADM = %02X\n\r",data); data = bi2c_get(HEADL); printf("read HEADL = %02X\n\r",data); } #endif }