📄 mp3init.c
字号:
/******************************************************************************
Title: Frank's MP3 Player initialization routines in C
Author: Frank Van Hooft
Date: 21 Aug 2004
This file contains various C routines that perform initializations.
Also some diagnostic routines.
******************************************************************************/
void PC_init (void)
/* Initializes the PlayControl (PC) variables to their defaults. */
{
PC_Command = PC_Cmd_Idle; /* start up command is idle - hence no file playing */
PC_Flag_Mode = 0; /* Random mode is OFF - should never init to ON, else you'll also have to init the random variables */
PC_Flag_Repeat = ~0; /* Repeat mode is ON */
DisplayRandomRpt(); // display random & repeat modes on the LCD
PlayControlState = PC_St_Idle; /* PlayControl starts off in Idle state */
FileNumber = 1; /* by default, play 1st file in current directory */
StepSize = 1; // by default we step through tracks one at a time
}
void DisplayRandomRpt (void)
// Displays Random & Repeat status at the bottom of the LCD
{
ClearLCDlines(8, 1); // blank the bottom LCD display line
// display the Random portion
PositionLCDcursor(8, 1); // put cursor at start of bottom lcd line
uart1_putwaitPROGstr(PSTR("Random "));
if (PC_Flag_Mode == 0)
uart1_putwaitPROGstr(PSTR("Off"));
else
uart1_putwaitPROGstr(PSTR("On"));
// display the Repeat portion
PositionLCDcursor(8, 15); // put cursor partway into bottom lcd line
uart1_putwaitPROGstr(PSTR("Repeat "));
if (PC_Flag_Repeat == 0)
uart1_putwaitPROGstr(PSTR("Off"));
else
uart1_putwaitPROGstr(PSTR("On"));
}
void USB_init (void)
// Initialize the Cypress 7C68300A device. Bit of a misnomer; it really initialises itself.
// However it has a requirement that for its first 20 ms (minimum) after reset it has to have
// its ATA_ENABLE signal active (high) so that it can go through its internal initializations.
// After that time it can be disabled. So this routine sets its enable pin high (AVR Port E bit 2)
// waits for more than 20 ms, then sets it low to tell the Cypress part to get off the IDE bus.
// Then it waits a little longer to ensure it's complied, and returns.
// (In normal operation the Cypress part is kept disabled, ie told to stay off the IDE bus,
// until a USB cable is plugged in. In which case the AVR gets off the IDE bus and enables
// the Cypress part.)
//
// This routine also enables an interrupt on PortE bit 6, which is the USB cable detect line.
// Normally it's pulled low. If a USB cable is plugged in it goes high.
{
*AVR_DDRE = *AVR_DDRE | 0xFB; // set Port E bit 2 high - enable Cypress part
// (pin an input, pullup pulls it high )
*AVR_DDRE = *AVR_DDRE & 0x1F; /* ensure top 3 bits Port E are inputs */
Delayms(60); // 60 ms should be lots of time for the Cypress part
*AVR_PORTE = *AVR_PORTE & 0xFB; /* set bit 2 low - kick Cypress USB off the IDE bus */
*AVR_DDRE = *AVR_DDRE | 0x04; /* make the pin an output to drive the low */
Delayms(60); // Now we should be OK to use the IDE bus
*AVR_EICRB |= 0x30; // rising edge of ext int 6 will trigger int
*AVR_EIMSK |= 0x40; // set bit 6 in ext int mask, to enable interrupt
}
void LCD_init (void)
/* Sets the LCD display to a known initialized state */
{
UART1_TxCharWaitC(0x5c);
UART1_TxCharWaitC(0x40);
UART1_TxCharWaitC(32);
UART1_TxCharWaitC(0x30); /* clear display, use default font */
UART1_TxCharWaitC(0x5c);
UART1_TxCharWaitC(0x41);
UART1_TxCharWaitC(0x31); /* line wrap on, screen scroll off */
UART1_TxCharWaitC(0x5c);
UART1_TxCharWaitC(0x5b); /* display characters */
/* The following long list defines the strings the display will send when buttons pushed. */
/* Pretty simple - single characters A-L for the 12 buttons down, nothing for buttons up, */
/* nothing for autorepeat. */
uart1_putwaitPROGstr(PSTR("\\H0A ")); /* button 1 down sends A */
uart1_putwaitPROGstr(PSTR("\\H1B ")); /* button 2 down sends B */
uart1_putwaitPROGstr(PSTR("\\H2C ")); /* button 3 down sends C */
uart1_putwaitPROGstr(PSTR("\\H3D ")); /* button 4 down sends D */
uart1_putwaitPROGstr(PSTR("\\H4E ")); /* button 5 down sends E */
uart1_putwaitPROGstr(PSTR("\\H5F ")); /* button 6 down sends F */
uart1_putwaitPROGstr(PSTR("\\H6G ")); /* button 7 down sends G */
uart1_putwaitPROGstr(PSTR("\\H7H ")); /* button 8 down sends H */
uart1_putwaitPROGstr(PSTR("\\H8I ")); /* button 9 down sends I */
uart1_putwaitPROGstr(PSTR("\\H9J ")); /* button 10 down sends J */
uart1_putwaitPROGstr(PSTR("\\H:K ")); /* button 11 down sends K */
uart1_putwaitPROGstr(PSTR("\\H;L ")); /* button 12 down sends L */
uart1_putwaitPROGstr(PSTR("\\H@ ")); /* button 1 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HA ")); /* button 2 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HB ")); /* button 3 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HC ")); /* button 4 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HD ")); /* button 5 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HE ")); /* button 6 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HFg ")); /* button 7 up sends g */
uart1_putwaitPROGstr(PSTR("\\HG ")); /* button 8 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HH ")); /* button 9 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HI ")); /* button 10 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HJ ")); /* button 11 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HK ")); /* button 12 up sends nothing */
uart1_putwaitPROGstr(PSTR("\\HP ")); /* button 1 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\HQ ")); /* button 2 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\HR ")); /* button 3 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\HS ")); /* button 4 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\HT ")); /* button 5 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\HU ")); /* button 6 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\HV ")); /* button 7 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\HW ")); /* button 8 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\HX ")); /* button 9 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\HY ")); /* button 10 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\HZ ")); /* button 11 autorepeat sends nothing */
uart1_putwaitPROGstr(PSTR("\\H[ ")); /* button 12 autorepeat sends nothing */
}
void FSC_init(void)
/* Initializes any variables, ports. STA013 codec chip, for the FeedSTcodec routine */
{
int i;
u08 initaddr, initdata, ib, TWIWcode;
// Set the /SS pin (Port B bit 0) high, so that it cannot affect SPI port operation
*AVR_DDRB = *AVR_DDRB | 0x01; // make Port B bit 0 an output
*AVR_PORTB = *AVR_PORTB | 0x01; // and set it high
/* give the STA013 codec chip a solid reset pulse, then leave it out of reset */
/* Reset pin for STA013 is Port E bit 3 */
*AVR_DDRE = *AVR_DDRE | 0x08; /* make Port E bit 3 an output */
*AVR_DDRE = *AVR_DDRE & 0x1F; /* ensure top 3 bits Port E are inputs */
*AVR_PORTE = *AVR_PORTE & 0xF7; /* set bit 3 low - put STA013 in reset */
*AVR_PORTE = *AVR_PORTE & 0xF7;
*AVR_PORTE = *AVR_PORTE & 0xF7;
*AVR_PORTE = *AVR_PORTE & 0xF7;
*AVR_PORTE = *AVR_PORTE & 0xF7;
*AVR_PORTE = *AVR_PORTE & 0xF7;
*AVR_PORTE = *AVR_PORTE & 0xF7; /* repeat a few times, to ensure nice & */
*AVR_PORTE = *AVR_PORTE & 0xF7; /* long reset duration */
*AVR_PORTE = *AVR_PORTE | 0x08; /* then set the STA013 reset bit high */
for (i=0; i<30000; i++) /* need to delay a while after reset */
i = i + (*AVR_PINE & 0x00); /* so just waste some time */
// *TWI_TWSR = 0xF9; /* TWI clock prescaler (TWPS) value = 1 */
// *TWI_TWBR = 10; /* program TWI bus speed */
*TWI_TWSR = 0xF8; /* TWI clock prescaler (TWPS) value = 0 */
*TWI_TWBR = 40; /* program TWI bus speed */
// *TWI_TWCR = 0x04; /* switch on the TWI interface */
FeedSTcodec_Command = FSC_Cmd_Stop; /* default is for this routine to play */
/* send the STA013 initialization data to the STA013 via the TWI interface */
for (i=0; i<2*num_STA013_init_pairs;) /* loop through the init data pairs */
{
initaddr = PRG_RDB(&STA013_InitData[i++]); /* first byte in pair is address */
initdata = PRG_RDB(&STA013_InitData[i++]); /* second byte in pair is data */
TWIWcode = sta013_writeTWI(initaddr, initdata); /* give them to the STA013 */
if (initaddr == 16)
{
for (ib=0; ib<255; ib++) /* need to delay if we wrote to soft reset addr */
ib = ib + (*AVR_PINE & 0x00); /* so just waste some time! :-) */
}
if (TWIWcode != TWI_write_OK) StopOnError(TWIWcode); /* report TWI error if one occurred */
for (ib=0; ib<120; ib++) *AVR_PINE; /* short delay between writes out the TWI */
}
/* enable the AVR's SPI interface (used to send MP3 music data to the ST codec chip */
*AVR_DDRB = *AVR_DDRB | 0x06; /* set SCK & MOSI pins as outputs */
*AVR_SPCR = 0x59; /* SPI enabled, master, inv pol, clock = Fosc/16 */
// *AVR_SPCR = 0x5A; /* SPI enabled, master, inv pol, clock = Fosc/64 */
*AVR_SPDR = 0x00; /* give null byte to MP3 codec through SPI port */
/* (otherwise SPI port doesn't start-up right) */
}
void TimersInit (void)
/* Initializes any timers used by this application */
{
// timer/counter 0 is an 8-bit counter, run at full speed and used as part of the random-number
// generator required by the random play mode.
*AVR_TCCR0 = 0x01; /* start timer/counter 0 running normally at full speed */
// Timer/counter 1 is set up to generate an interrupt every 100ms. This is a simple timebase,
// incrementing the Tick100ms timebase keeper.
Tick100ms = 0;
*AVR_TCCR1A = 0; // automatically clear counter on output compare A match (CTC)
*AVR_TCCR1B = 0x0b; // counter prescaler = /64
*AVR_OCR1AH = 0x61;
*AVR_OCR1AL = 0xa8; // 16-bit output compare register A = 25,000
*AVR_TIMSK = *AVR_TIMSK | 0x10; // output compare 1A interrupt enabled
// Timer/counter 3 is used for input capture. It's used to measure the periods of the bitstream
// received from the IR receiver. With a prescaler value of /256, each increment of TCNT3 takes 16us.
*AVR_DDRE = *AVR_DDRE & 0x7f; // ensure the input capture 3 pin (PE7) is an input
*AVR_TCCR3A = 0;
*AVR_TCCR3B = 0x84; // prescaler = /256, noise canceller ON, capture on falling edge
*AVR_ETIMSK = *AVR_ETIMSK | 0x20; // enable input capture 3 interrupt
}
SIGNAL(SIG_OUTPUT_COMPARE1A)
// Executes in response to timer/counter 1 output compare A interrupt. This timer is set to interrupt
// every 100ms. It's used as a simple timebase - Tick100ms global variable is incremented. Any routine
// can read Tick100ms if they need to measure time.
{
Tick100ms++;
}
void IRInit (void)
// Simply checks through the IR sequence entries in the EEPROM, and if it sees a 0xff for a length, then it
// knows that entry is not present (0xff can only happen if the eeprom was erased or something similar)
// so it zeros that length. A zero length means "no entry". Length is the first byte of each 128-byte entry.
//
// And it writes the "ButtonPress" codes into the eeprom structures, so that the IR decoder is able to read
// them to know what a received IR code is supposed to do (they each emulate a pushbutton press).
{
u08 i;
u16 addr;
i = IR_numcodes; // number of IR sequence entries to check
addr = IRcode_Start; // eeprom address for start of first entry
while (i--) {
if ( EEPROM_ReadC(addr) == 0xff )
EEPROM_Write(addr, 0); // set length byte to zero if it's 0xff
addr += 128; // eeprom address of next length byte
}
IR_RX_period = 0; // indicate that no IR periods have been received by IC3 ISR
// clear the IR decode "count byte" variables; used to track where the IR decoder is for each of the period sequences
// zero means "at the beginning"
i = IR_numcodes;
while (i--)
IRdecode_cnt[i] = 0;
// Write the "ButtonPress" codes into the eeprom
EEPROM_Write(IRcode_pwr+1, BUT_ONOFF);
EEPROM_Write(IRcode_play+1, BUT_PLAY);
EEPROM_Write(IRcode_stop+1, BUT_STOP);
EEPROM_Write(IRcode_next+1, BUT_NEXT_UP);
EEPROM_Write(IRcode_back+1, BUT_PREVIOUS);
EEPROM_Write(IRcode_mode+1, BUT_MODE);
// By default, clear the training debug flag (so that IR receiver periods data is not dumped during
// normal operation). This flag can be set from the debug port menu.
IRtrain_debug = 0;
}
SIGNAL(SIG_INPUT_CAPTURE3)
// Executes in response to an input capture interrupt from timer/counter3. Which is the IR receiver.
// The "smarts" of the decoder are in IR_decode() routine, found in the mp3srial.c file.
{
*AVR_TCNT3H = 0;
*AVR_TCNT3L = 0; // zero counter register; ready for next period measurement
*AVR_TCCR3B = *AVR_TCCR3B ^ 0x40; // tell AVR to do next capture on the other edge (rising or falling - opposite of what we just triggered on)
*AVR_ETIFR = 0x20; // clear interrupt flag (was set due to capture edge being changed)
// *AVR_PORTB = *AVR_PORTB ^ 0x10; // debug only - toggle LED so we can see IRQ occurring
// Now read the period from ICR3. Store result in global variable IR_RX_period.
IR_RX_period = *AVR_ICR3L + (((u16)*AVR_ICR3H)<<8);
IR_decode(); // Should be in-line code ideally, for efficiency's sake.
// Was initially in main loop, but moved here to interrupt context
// because it missed periods when in main loop context.
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -