📄 mp3srial.c
字号:
*AVR_DDRD = *AVR_DDRD & 0x7F;
*AVR_DDRF = *AVR_DDRF & 0xE1; /* All IDE pins are now inputs - bus is free */
*AVR_DDRE = *AVR_DDRE & 0xFB; /* Now safe to enable Cypress USB chip */
/* (pullup on enable line now pulls it high) */
*AVR_PORTE = *AVR_PORTE & 0xF7; /* ST MP3 codec reset (ie sound stopped) */
/* put an appropriate message on the LCD display */
LCD_init(); /* clear the display */
UART1_TxCharWaitC(0x5c);
UART1_TxCharWaitC(0x42);
UART1_TxCharWaitC(0x20);
UART1_TxCharWaitC(0x21); /* put cursor on start of 2nd row */
uart1_putwaitPROGstr(PSTR(" USB Port In Use")); /* write message on that row */
UART1_TxCharWaitC(0x5c);
UART1_TxCharWaitC(0x42);
UART1_TxCharWaitC(0x20);
UART1_TxCharWaitC(0x23); /* put cursor on start of 4th row */
uart1_putwaitPROGstr(PSTR(" Player restarts after USB cable unplugged."));
/* send a message out the debug port */
uart0_putwaitPROGstr(PSTR("\r\n\n\nUSB port in use.\r\n"));
uart0_putwaitPROGstr(PSTR("Player restarts when USB unplugged.\r\n\n"));
// Zero the directory cluster number in eeprom as the current directory may have been deleted.
// This will trigger a return to the root directory, recount of files, etc at power-up
EEPROM_Write (DIRcluster0, 0);
EEPROM_Write (DIRcluster1, 0);
EEPROM_Write (DIRcluster2, 0);
EEPROM_Write (DIRcluster3, 0);
while (*AVR_PINE & 0x40); /* wait until USB cable unplugged */
/* send a message out the debug port */
uart0_putwaitPROGstr(PSTR("USB port unplugged. Restarting player.\r\n\n"));
Delayms(100); /* ensure USB chip finished doing its thing */
ResetAVR(); /* reset the player */
}
/******************************************************************************
TWI (I2C) Port Handling Routines
This port used for sending initial configuration data to the STA013 codec
Routine is slow - it waits for TWI status bits; it does not return to main
loop while executing. So be aware that if you use this routine whilst
a track is playing,
******************************************************************************/
u08 sta013_writeTWI (u08 waddr, u08 wdata)
/* Writes a single byte to the TWI interface of the ST codec chip */
/* We're passed in the address and the byte to write to that address */
/* Returns an error code if a problem occurs. */
/* The basic 5-step sequence of events is: */
/* 1. Start condition */
/* 2. Send the TWI address of the sta013 indicating a write, ie 0x86 */
/* 3. Send the address of the sta013 register we want to write to, ie waddr */
/* 4. Send the data byte to the sta013, ie wdata */
/* 5. Stop condition */
{
/* print the codec write data values to the screen - debug only */
// UART_TxCharWaitC('\r');
// UART_TxCharWaitC('\n');
// UART_PutHexWaitC(waddr);
// UART_TxCharWaitC(' ');
// UART_PutHexWaitC(wdata);
// UART_TxCharWaitC(' ');
/* end debug printing section */
*TWI_TWCR = 0xA4; /* initiate start condition */
while ((*TWI_TWCR & 0x80) != 0x80); /* wait until high bit set indicating start has been sent */
if ((*TWI_TWSR & 0xF8) != 0x08) return TWI_write_start_fail; /* report error if start condition failed */
*TWI_TWDR = 0x86;
*TWI_TWCR = 0x84; /* inform sta013 we want to write to it */
while ((*TWI_TWCR & 0x80) != 0x80); /* wait until high bit set indicating 0x86 has been sent */
if ((*TWI_TWSR & 0xF8) != 0x18) return TWI_write_0x86_fail; /* report error if writing 0x86 failed */
*TWI_TWDR = waddr;
*TWI_TWCR = 0x84; /* give sta013 the internal address we want to write to */
while ((*TWI_TWCR & 0x80) != 0x80); /* wait until high bit set indicating waddr has been sent */
if ((*TWI_TWSR & 0xF8) != 0x28) return TWI_write_waddr_fail; /* report error if writing waddr failed */
*TWI_TWDR = wdata;
*TWI_TWCR = 0x84; /* give sta013 the internal address we want to write to */
while ((*TWI_TWCR & 0x80) != 0x80); /* wait until high bit set indicating wdata has been sent */
if ((*TWI_TWSR & 0xF8) != 0x28) return TWI_write_wdata_fail; /* report error if writing waddr failed */
*TWI_TWCR = 0x94; /* transmit stop condition */
return TWI_write_OK;
}
/******************************************************************************
SPI Port Handling Routines
This port used for sending MP3 files to the STA013 codec
******************************************************************************/
void FeedSTcodec(void)
/* This routine reads data out of the MP3 Data queue and feeds it to the ST MP3 codec chip. */
/* The ST MP3 codec data request line is on Port E bit 5. High means it wants data. */
/* This function also monitors its command byte (FeedSTcodec_Command) so that it will not feed */
/* the codec chip any data if the user command is STOP. */
{
u08 mp3data;
if (FeedSTcodec_Command == FSC_Cmd_Stop) /* exit if we're told to stop */
return;
/* debug only */
// for (mp3data=0; mp3data<100; mp3data++)
// Q_read_C ((u08*)&MP3DATAQ[0]);
/* end debug section */
// debug only - return if data q empty
// if (Q_CheckEmptyC((u08*)&MP3DATAQ[0]) == Q_empty) return;
// end debug
while (*AVR_PINE & 0x20) { /* while MP3 codec wants data ... */
mp3data = Q_read_C ((u08*)&MP3DATAQ[0]); /* try to read a byte from the data queue */
if (ReadQstatus != Q_OK) return; /* exit if queue read returned q empty */
while (!(*AVR_SPSR & 0x80)); /* wait until SPI port ready for new byte */
*AVR_SPDR = mp3data; /* give byte to MP3 codec through SPI port */
}
}
/******************************************************************************
Other Routines
Not directly affecting the various serial ports, but related to or called
by those routines.
******************************************************************************/
void SwitchOff (void)
/* This routine is called by HandleButtons when the On/Off button is pressed, ie the
user is switching the unit off. This routine does a bunch of calls to shut the player
down, then goes into a loop when it sits waiting for the On/Off button to be pressed
again, waiting for the unit to be switched on. */
{
*AVR_PORTE = *AVR_PORTE & 0xF7; /* put STA013 codec in reset */
UART1_TxCharWaitC(0x5c);
UART1_TxCharWaitC(0x40);
UART1_TxCharWaitC(32);
UART1_TxCharWaitC(0x30); /* clear lcd display */
LED_OFF();
LCD_LIGHT_OFF(); // turn off LED & LCD backlight
IDE_Standby(); /* allow the drive to auto power-down */
ButtonPress = 0; // clear out the previous ON/OFF button press
while (ButtonPress != BUT_ONOFF)
IR_CheckTimeout(); // wait until on/off button pressed (on) again
// either by pushbutton or IR remote control
ResetAVR();
}
void PrintStackPointer (void)
// As you might guess from the function name, this routine prints the value of the
// stack pointer out the debug port (using slow 'wait' routines).
{
u08 *memptr, i;
memptr = (u08*)(((*AVR_SPH)<<8) | *AVR_SPL); // copy stackpointer to memptr
uart0_putwaitPROGstr(PSTR("Stack Pointer value: $"));
UART_PutHexWaitC(*AVR_SPH);
UART_PutHexWaitC(*AVR_SPL);
uart0_putwaitPROGstr(PSTR("\n\r"));
uart0_putwaitPROGstr(PSTR("Stack dump: $ "));
for (i=RAMEND-(u16)memptr; i; i--) {
UART_PutHexWaitC(*++memptr);
UART_TxCharWaitC(' ');
}
uart0_putwaitPROGstr(PSTR("\n\r"));
}
void PrintDebugInfo (void)
// Prints a bunch of disk-related debug info out the debug port, slowly.
// ie it uses the xxWaitxx functions, to avoid overflowing the uart tx q.
{
u08 linecnt, i, j;
u16 temp;
uart0_putwaitPROGstr(PSTR("\r\nDISKDRIVE DEBUG INFORMATION\r\n")); /* debug port message */
uart0_putwaitPROGstr(PSTR("Findfile current directory cluster: $"));
UART_PutHexWaitC((u08)(FINDFILE_CLUS>>24));
UART_PutHexWaitC((u08)(FINDFILE_CLUS>>16));
UART_PutHexWaitC((u08)(FINDFILE_CLUS>>8));
UART_PutHexWaitC((u08) FINDFILE_CLUS);
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("Findfile current offset into this cluster: $"));
UART_PutHexWaitC((u08)(FINDFILE_OFSET>>8));
UART_PutHexWaitC((u08) FINDFILE_OFSET);
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("Streamfile State: $"));
UART_PutHexWaitC(STREAMFILE_ST);
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("CalcNextCluster State: $"));
UART_PutHexWaitC(CALNXCL_ST);
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("CalcNextCluster sector it's seeking to: $"));
UART_PutHexWaitC((u08)(CALNXCL_SN>>24));
UART_PutHexWaitC((u08)(CALNXCL_SN>>16));
UART_PutHexWaitC((u08)(CALNXCL_SN>>8));
UART_PutHexWaitC((u08) CALNXCL_SN);
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("SeekSector State: $"));
UART_PutHexWaitC(SEEKSECT_ST);
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("Drive status register: $"));
UART_PutHexWaitC(IDE_read8_C(0x7f));
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("Drive error register: $"));
UART_PutHexWaitC(IDE_read8_C(0x4f));
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("Sectors per cluster: $"));
UART_PutHexWaitC(SEC_PER_CLUS);
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("FAT start sector: $"));
UART_PutHexWaitC((u08)(FAT_START_SEC>>8));
UART_PutHexWaitC((u08) FAT_START_SEC);
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("DIR start sector: $"));
UART_PutHexWaitC((u08)(DIR_START_SEC>>24));
UART_PutHexWaitC((u08)(DIR_START_SEC>>16));
UART_PutHexWaitC((u08)(DIR_START_SEC>>8));
UART_PutHexWaitC((u08) DIR_START_SEC);
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("FeedSTcodec_Command: $"));
UART_PutHexWaitC(FeedSTcodec_Command);
uart0_putwaitPROGstr(PSTR("\r\n"));
uart0_putwaitPROGstr(PSTR("File Number: $"));
UART_PutHexWaitC((u08)(FileNumber>>8));
UART_PutHexWaitC((u08) FileNumber);
uart0_putwaitPROGstr(PSTR("\r\n"));
// print out a bunch of Boot Sector Boot Paramer Block Data
while ( SeekSectorC(63, 1) != SeekSect_Done); // seek drive to start of BPB sector
// Drive is seeked to that sector. Now do a bunch of reads from the drive's data register
// and print out the results on the debug port.
uart0_putwaitPROGstr(PSTR("\r\nDump of the drive's Boot Parameter Block:\r\n"));
while ( IDE_read8_C(0x7f) & 0x80 ); // wait until drive says it's not busy (wait for top bit to clear)
linecnt = 16;
while (linecnt--) {
// print 4 bytes separated by spaces, 4 times (separated by 2 spaces)
i = 4;
while (i--) { // outer loop
j = 2;
while (j--) { // inner loop
temp = IDE_read16_C(0x47); // get 16-bit word from drive data register
UART_PutHexWaitC( (u08)temp ); // print low byte to debug port
uart0_putwaitPROGstr(PSTR(" ")); // followed by a space
UART_PutHexWaitC( (u08)(temp>>8) ); // print high byte to debug port
uart0_putwaitPROGstr(PSTR(" ")); // followed by a space
}
uart0_putwaitPROGstr(PSTR(" ")); // extra space between groups of 4 bytes
}
uart0_putwaitPROGstr(PSTR("\r\n")); // end of line CR/LF
}
uart0_putwaitPROGstr(PSTR("\r\n")); // extra CR/LF at end of BPB data dump
DumpDirectory(); // dump some data out of the current directory
IDE_Standby(); /* allow the drive to auto power-down */
}
// DumpDirectory
//
// This routine prints to the debug port the first directory record in the current directory
// Use only when debugging - because it takes over the diskdrive it'll disrupt anything currently playing.
u08 DumpDirectory (void)
{
u08 linecnt, i, j;
// Ensure StreamFileC stopped
STREAMFILE_CMD = StreamFile_Cmd_Stop; // command StreamFileC to STOP
StreamFileC();
while (STREAMFILE_ST!=StreamFile_St_Idle) StreamFileC(); // wait until StreamFileC idle
// Ensure MP3dataQ empty
Q_clear_C((u08*)&MP3DATAQ[0]);
// Command StreamFileC to stream current directory into the MP3dataQ
STREAMFILE_FILESZ = 0xFFFFFFF; // huge "file size"
STREAMFILE_CLUS = CURRENT_DIRCL; // cluster number for start of current directory
STREAMFILE_QPOINTER = &MP3DATAQ[0]; // point StreamFile to the MP3 Data queue
STREAMFILE_CMD = StreamFile_Cmd_Stream; // command StreamFileC to start streaming
StreamFileC();
StreamFileC();
// Wait until 32 bytes in queue. If StreamFileC goes idle, return.
while ( Q_HowMuchDataC((u08*)&MP3DATAQ[0]) < 32 ) {
StreamFileC();
if ( (STREAMFILE_ST==StreamFile_St_Idle) && (Q_HowMuchDataC((u08*)&MP3DATAQ[0])<32) )
return 1;
}
// We now have 32 bytes in the queue; a directory entry's worth. Read them out of
// the queue, printing them to the debug port. Each line prints 16 bytes.
uart0_putwaitPROGstr(PSTR("\r\nFirst 32-byte record in current directory:\r\n"));
linecnt = 2;
while (linecnt--) {
// print 4 bytes separated by spaces, 4 times (separated by 2 spaces)
i = 4;
while (i--) { // outer loop
j = 4;
while (j--) { // inner loop
UART_PutHexWaitC( Q_read_C((u08*)&MP3DATAQ[0]) ); // print byte to debug port
uart0_putwaitPROGstr(PSTR(" ")); // followed by a space
}
uart0_putwaitPROGstr(PSTR(" ")); // extra space between groups of 4 bytes
}
uart0_putwaitPROGstr(PSTR("\r\n")); // end of line CR/LF
}
uart0_putwaitPROGstr(PSTR("\r\n")); // extra CR/LF at end of directory data dump
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -