📄 mp3srial.c
字号:
/******************************************************************************
Title: Frank's MP3 Player serial routines in C
Author: Frank Van Hooft
Date: 21 Aug 2004
This file contains various C routines that perform any functions related
to serial-type ports. This covers the ports:
UART0 (debug port)
UART1 (LCD display & pushbuttons)
TWI (also called I2C, for ST MP3 codec chip control)
SPI (used to send MP3 files to the codec chip)
USB (handled by the Cypress chip - we just control its reset)
Initialization routines for these ports are in mp3init.c or in the
assmbler (.s) files.
******************************************************************************/
/******************************************************************************
UART0 Port Handling Routines
This port is the debug RS232 port.
******************************************************************************/
void uart0_putwaitstr(u08 *c)
/* copies a string held in SRAM (data memory) to the UART0 *SLOWLY* */
/* by "owning" the UART and waiting until each char is sent before sending */
/* the next, bypassing the usual transmit queue. Very slow - use only for */
/* debug or in non-time-critical positions (eg initializations). */
{
while (*c) {
UART_TxCharWaitC(*c);
c++;
}
}
void uart0_putwaitPROGstr(u08 *c)
/* copies a string held in Flash (program memory) to the UART0 *SLOWLY* */
/* by "owning" the UART and waiting until each char is sent before sending */
/* the next, bypassing the usual transmit queue. Very slow - use only for */
/* debug or in non-time-critical positions (eg initializations). */
{
while (PRG_RDB(c)) {
UART_TxCharWaitC(PRG_RDB(c));
c++;
}
}
SIGNAL(SIG_UART0_RECV)
/* signal handler for receive complete interrupt from debug port */
/* This routine handles UART receive interrupts from UART 0 - the debug port */
// Used for debug purposes only
// Accepts single-character commands. They are:
//
// ? - help - print out this list of commands
// e - dump contents of Eeprom
// d - dump a bunch of Diskdrive information
// h - dump some debug information then Hang
// i - enable dumping of IR remote-control period values during training
// p - test IDE Ports bits where possible. Harddisk must be unplugged.
// t - test the harddisk interface. Harddisk must be plugged in.
// w - perform repeated writes to the harddisk.
// r - perform repeated reads from the harddisk.
{
switch (*AVR_UDR0) {
case '?':
PrintDebugCommands();
break;
case 'h':
DumpAndHang();
break;
case 'e':
DumpEEPROM();
break;
case 'd':
PrintDebugInfo();
break;
case 'i':
IRtrain_debug = 1;
uart0_putwaitPROGstr(PSTR("IR debug flag set. (Power-off to clear.)\r\n"));
break;
case 'p':
TestPortBits();
break;
case 't':
TestHarddisk();
break;
case 'w':
TestWriteHarddisk();
break;
case 'r':
TestReadHarddisk();
break;
default:
uart0_putwaitPROGstr(PSTR("\r\nUnknown command."));
PrintDebugCommands();
break;
}
}
// PrintDebugCommands
//
// Prints the list of debug commands to the debug port.
void PrintDebugCommands(void)
{
uart0_putwaitPROGstr(PSTR("\r\nDebug Port Commands are:\n\r\n"));
uart0_putwaitPROGstr(PSTR("? - print these commands\r\n"));
uart0_putwaitPROGstr(PSTR("e - dump contents of eeprom\r\n"));
uart0_putwaitPROGstr(PSTR("d - dump some diskdrive debug information\r\n"));
uart0_putwaitPROGstr(PSTR("h - dump some debug info (stack dump) then hang (processor stopped)\r\n"));
uart0_putwaitPROGstr(PSTR("i - enable dumping of IR remote-control period values during training\r\n"));
uart0_putwaitPROGstr(PSTR("p - test IDE Ports bits where possible. HARDDISK MUST BE UNPLUGGED.\r\n"));
uart0_putwaitPROGstr(PSTR("t - test the harddisk interface. Harddisk must be plugged in.\r\n"));
uart0_putwaitPROGstr(PSTR("w - Perform repeated writes to the harddisk.\r\n"));
uart0_putwaitPROGstr(PSTR("r - Perform repeated reads from the harddisk.\r\n"));
uart0_putwaitPROGstr(PSTR("\r\n"));
}
// DumpAndHang
//
// This routine prints out the debug port a bunch of debug information, then hangs (loops forever)
void DumpAndHang (void)
{
u08 *memptr, i;
// start of stack dump section
memptr = (u08*)(((*AVR_SPH)<<8) | *AVR_SPL); // copy stackpointer to memptr
uart0_putwaitPROGstr(PSTR("\n\rStack Pointer value: $"));
UART_PutHexWaitC(*AVR_SPH);
UART_PutHexWaitC(*AVR_SPL);
uart0_putwaitPROGstr(PSTR("\n\r"));
uart0_putwaitPROGstr(PSTR("Stack dump: $ "));
for (i=18; i; i--) {
UART_PutHexWaitC(*++memptr);
UART_TxCharWaitC(' ');
}
uart0_putwaitPROGstr(PSTR("\n\r"));
for (i=RAMEND-(u16)memptr; i; i--) {
UART_PutHexWaitC(*++memptr);
UART_TxCharWaitC(' ');
}
uart0_putwaitPROGstr(PSTR("\n\r"));
// End of stack dump code section
// first 2 bytes of 2nd line will be interrupt return address, in correct order (ie don't reverse bytes)
UART_TxCharWaitC(*AVR_UDR0); /* display received debug character on debug screen, clears interrupt */
uart0_putwaitPROGstr(PSTR("Player halted.\r\n"));
IDE_Standby(); /* allow the drive to auto power-down */
while (1);
}
/******************************************************************************
UART1 Port Handling Routines
This port is used for sending text to the LCD for display, as well as
for receiving button keypress information.
******************************************************************************/
SIGNAL(SIG_UART1_RECV)
/* signal handler for receive complete interrupt from pushbuttons port */
/* This routine handles UART receive interrupts from UART 1 - the pushbuttons port */
// It reads out the received character and places it in ButtonPress.
// Note that the new buttonpress will overwrite any old one that may be present.
// Most functions, if responding to a buttonpress, will then zero ButtonPress so they
// don't erroneously respond again. This routine only accepts the ASCII
// characters A-z; everything else is discarded (it's a junk filter).
//
// The time the NEXT button was depressed (pressed down) is recorded, for use
// by the CycleStepSize function (in mp3pc.c).
{
u08 rxchar;
rxchar = (*(volatile u08*)U1DR); // get the received character
if ( (rxchar >= 'A') && (rxchar <= 'z') ) {
// execute here if we have a valid new received character
ButtonPress = rxchar;
if (ButtonPress==BUT_NEXT_DN)
StepSizeStartTime = Tick100ms; // remember time that NEXT button was depressed
}
}
void uart1_putwaitstr(u08 *c)
/* copies a string held in SRAM (data memory) to the UART1 *SLOWLY* */
/* by "owning" the UART and waiting until each char is sent before sending */
/* the next, bypassing the usual transmit queue. Very slow - use only for */
/* debug or in non-time-critical positions (eg initializations). */
{
while (*c) {
UART1_TxCharWaitC(*c);
c++;
}
}
void uart1_putwaitPROGstr(u08 *c)
/* copies a string held in Flash (program memory) to the UART1 *SLOWLY* */
/* by "owning" the UART and waiting until each char is sent before sending */
/* the next, bypassing the usual transmit queue. Very slow - use only for */
/* debug or in non-time-critical positions (eg initializations). */
{
while (PRG_RDB(c)) {
UART1_TxCharWaitC(PRG_RDB(c));
c++;
}
}
void DisplayUART1rx (void)
/* This TEST routine pulls characters out of the UART1 receive port and */
/* sends them to the UART0, ie the debug port. */
/* Useful for seeing the pushbutton codes. */
{
if (!(*(volatile u08*)U1SR & 0x80))
return; /* exit if nothing received */
UART_TxCharWaitC(*(volatile u08*)U1DR); /* else read data register & give to uart0 */
return;
}
void HandleButtons (void)
/* This is a main loop routine that responds to any pushbutton presses. Normally the */
/* ButtonPress variable contains 0, meaning no button pressed. If a button is pressed then */
/* we respond accordingly, and clear ButtonPress afterwards. */
// Note that the IR remote control receiver can also write these values into ButtonPress,
// thereby emulating a pushbutton press and causing the player to behave accordingly.
{
switch (ButtonPress) {
case 0:
return; /* exit if no pushbutton pressed */
case BUT_ONOFF:
SwitchOff(); /* switch the player off - this routine never returns */
break;
case BUT_MODE:
PC_Flag_Mode = ~PC_Flag_Mode; // toggle value of playcontrol mode flag
DisplayRandomRpt(); // display update on lcd
if (PC_Flag_Mode) /* if random mode switched on then... */
InitRandomVariables(); // initialise the playcontrol random variables
else // else if random mode has just been switched off...
StepSize = 1; // then set Stepsize back to 1 (normal stepping through tracks)
break;
case BUT_STOP:
PC_Command = PC_Cmd_Stop; /* Tell PlayControl to stop */
break;
case BUT_PLAY:
PC_Command = PC_Cmd_Play; /* Tell PlayControl to play */
break;
case BUT_REPEAT:
PC_Flag_Repeat = ~PC_Flag_Repeat; // toggle value of PC_Flag_Repeat
DisplayRandomRpt(); // display update on lcd
break;
case BUT_PREVIOUS:
PC_Command = PC_Cmd_Prev; /* Tell PlayControl to go to the previous file */
break;
case BUT_NEXT_UP:
PC_Command = PC_Cmd_Next; /* Tell PlayControl to hop forward to the next file */
break;
case BUT_NEXT_DN:
CycleStepSize(); // CycleStepSize found in mp3pc.c
return; // Return, not break, to ensure ButtonPress not cleared in this case,
// as we need to keep re-executing this until a BUT_NEXT_UP occurs.
case BUT_MENUSEL:
MenuMain(); // Menu functions
break;
case BUT_UP:
PC_Command = PC_Cmd_Add10; // While playing, up button steps forward 10 songs
break;
case BUT_RIGHT:
PC_Command = PC_Cmd_Add100; // While playing, right button steps forward 100 songs
break;
case BUT_DOWN:
PC_Command = PC_Cmd_Bak10; // While playing, down button steps backward 10 songs
break;
case BUT_LEFT:
PC_Command = PC_Cmd_Bak100; // While playing, left button steps backward 100 songs
break;
default:
break; /* ignore received button character if we can't handle it */
}
ButtonPress = 0; // we're finished with this button push so delete it, otherwise
// we'd do it all over again. And again. And again...
}
/******************************************************************************
USB Port Handling Routines
******************************************************************************/
SIGNAL(SIG_INTERRUPT6)
// Interrupt service routine for USB connect detect interrupt.
// It shuts down this player, sets all the IDE port pins to inputs, takes the
// Cypress USB chip out of "disabled" state, and then waits.
// (Cypress part enabled by making PE2 an input; external pull-up resistor then
// pulls the enable line active high. Disable Cypress USB by driving PE2 output low.)
// Once the USB connector is removed it resets this player, to allow playing to
// start all over again (after a full reset of this AVR device)
// USB connector status can be read on Port E bit 6 - low means unplugged,
// high means USB connector plugged in.
// For IDE pinout, see header of file ide.s
{
*AVR_DDRA = 0x00;
*AVR_DDRB = *AVR_DDRB & 0x1F;
*AVR_DDRC = 0x00;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -