⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp3init.c

📁 Frank s MP3 Player Source Files
💻 C
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************
    
    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 + -