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

📄 yampp3.c

📁 Yet Another MP3 Player source code. It can be usefull as reference source for any project.
💻 C
📖 第 1 页 / 共 2 页
字号:
		{
			WDR;					// Enable time to push data

			nWrites = 0;			// This count prevents indefinite
			do						//  feed of data to VS1001 with no
			{						//  way to get control
									// Amount of rest of data bursts
				nBursts = (u08)(((pTemp = pPlayData) - pPlayBufStart) / 32);
				while (nBursts < BUFFER_SIZE / 32 &&// While we have data and 
					   bit_is_set(PINB, PB2))		//  DREQ is high
				{
					vs1001_send_32(pPlayData);		// Feed data to VS1001
					pPlayData += 32;				// Advance pointer
					nBursts++;
				}
				dwPlayed += pPlayData - pTemp;		// Count already pumped bytes
			} while(++nWrites < MAX_CONS_WRITES  &&	// We write not too many times
					nBursts == BUFFER_SIZE / 32  &&	//  and we didn't stop by DREQ
					RetrieveMP3Data());				//  and we read more data

			if (bBuf1Empty && bBuf2Empty)			// No more data to play
			{										// Try to autoplay next song
				bPlaying = false;
#ifdef ENABLE_CRC
				UART_Printfu16(crc);
#endif
				if (bRandom)
				{
					wSongNum = do_rand(wMaxSongs);
					event = EV_PLAY;
				}
				else
					event = EV_NEXT;
				continue;
			}
			
			if (nScrollUpd >= 5)	// Scroll song name every 500ms
			{
				lcd_gotoxy(0, 0);
				for (nTemp = 0; nTemp < 16; nTemp++)
					lcd_putchar(scroll_line[(scroll_pos + nTemp) % scroll_length]);
				scroll_pos++;
				nScrollUpd = 0;
			}

			if (nDispUpd >= 5)		// Update other display info every 500ms
			{
				dispbar();

				lcd_gotoxy(10,1);

				dst = timestr;
				
				if (tot_sw < 10)	// 0-9
				{
					src = timestr;
					wPlayTime = vs1001_read(VS1001_PLAYTIME);
					
					divt = udiv(wPlayTime, 3600);
					divt = udiv(divt.rem, 600);
					*src++ = '0' + (u08)divt.quot;
					divt = udiv(divt.rem, 60);
					*src++ = '0' + (u08)divt.quot;
					*src++ = ':';
					divt = udiv(divt.rem, 10);
					*src++ = '0' + (u08)divt.quot;
					*src++ = '0' + (u08)divt.rem;			
					*src = 0;
				}
				else if (tot_sw < 12)	// 10-11
				{
					*dst++ = '#';
					src = pTrack;
					while ((*dst = *src++)) dst++;
					while (dst < &timestr[5])
						*dst++ = ' ';
					dst = timestr;
				}
				else if (tot_sw < 14)	// 12-13
				{
					dst = randstr;
					//while (*dst++ = *src++);
				}
				else if (tot_sw < 16)	// 14-15
				{
					dst = loudstr;
					//while (*dst++ = *src++);
				}
	
				tot_sw += 2;
				
				if (tot_sw >= 16)
					tot_sw = 0;

//				lcd_puts(timestr);
				lcd_puts(dst);
				
				lcd_putchar(0);		// Volume indicator
				nDispUpd = 0;
				
			} // if update time display
		} // if (bPlaying)
	} // while (true)
}




// Auxillary functions definitions

// converts 16 bit unsigned integer to string
// str[] should be 6 bytes at least. Function can return value != str
// and you have to use it as a output value start
u08* unsigned2str(u16 track, u08 *str)
{
	register u08 i;
	udiv_t divt;

	for (i = 0; i < 5; i++) *str++ = ' ';
	*str = '\0';
	divt.quot = track;
	do {
		divt = udiv(divt.quot, 10u);
		*(--str) = '0' + (u08)divt.rem;
	} while (divt.quot);
	return str;
}


#ifdef ENABLE_SERIAL

typedef struct pairUART				// auxilliary structure for making
{									//  of pairs table for select operator
	u08 code, action;
} pairUART;

pairUART TableUART[] = { 
	{ 0, EV_IDLE }, 
	{ 'g', EV_PLAY },	 { 'G', EV_STOP }, 
	{ 'p', EV_PREV },	 { 'n', EV_NEXT }, 
	{ 'P', EV_PREV10 },  { 'N', EV_NEXT10 },
	{ 'V', EV_VOLUP },	 { 'v', EV_VOLDN },
	{ 'u', EV_NEUTRAL }, { 'm', EV_MUTE },
#ifdef ENABLE_NAV
	{ 'l', EV_NEXTL },	 { 'L', EV_PREVL },
#endif
	{ 'r', EV_RANDOM },	 { ' ', EV_PAUSE }
};


event_e get_char_event(void)
{
#ifdef HEXDUMP
	static u32 dwLbaSector = 0;
	static u32 dwTempAcc = 0;
#endif

	register u08 i;
	register u08 code = UART_ReceiveByte();

	for (i = 0; i < sizeof(TableUART) / sizeof(TableUART[0]); i++)
		if (TableUART[i].code == code)
			return TableUART[i].action;
#ifdef HEXDUMP
	if (code >= '0' && code <= '9')
		dwTempAcc = dwTempAcc * 10 + code - '0';
	if (code == 0x0d)		// Enter
	{
		sectordump(dwLbaSector = dwTempAcc);
		dwTempAcc = 0;
	}
	if (code == '+')
		sectordump(++dwLbaSector);
	if (code == '-')
		sectordump(--dwLbaSector);
#endif	// HEXDUMP

    return EV_IDLE;
}

#endif // ENABLE_SERIAL


// get a remote control event
typedef struct pairIR
{
	u16 code;
	u08 action;
} pairIR;

pairIR TableIR[] = { 
	{ 0, EV_IDLE },
	{ IR_PLAY, EV_PLAY },	  { IR_STOP, EV_STOP }, 
	{ IR_PREV, EV_PREV },	  { IR_NEXT, EV_NEXT }, 
	{ IR_PREV10, EV_PREV10 }, { IR_NEXT10, EV_NEXT10 },
	{ IR_VOLUP, EV_VOLUP },   { IR_VOLDN, EV_VOLDN },
#ifdef ENABLE_NAV
	{ IR_NEXTL, EV_NEXTL },	  { IR_PREVL, EV_PREVL },
#endif
	{ IR_RANDOM, EV_RANDOM }, { IR_PAUSE, EV_PAUSE }
};

event_e ir_event(void)
{
	register u08 i;
	u16 code = get_rec80();
	for (i = 0; i < sizeof(TableIR) / sizeof(TableIR[0]); i++)
		if (TableIR[i].code == code)
			return TableIR[i].action;

	return EV_IDLE;
}



// get a keyboard event - edhanced by MIS

u08 TableKbdShort[] = { EV_IDLE, EV_LOUDNESS, EV_PLAY, EV_PREV,   EV_NEXT,   EV_PREVL, EV_NEXTL, EV_VOLUP, EV_VOLDN };
u08 TableKbdLong[]  = { EV_IDLE, EV_RANDOM,   EV_STOP, EV_PREV10, EV_NEXT10, EV_PREVL, EV_NEXTL, EV_VOLUP, EV_VOLDN };

event_e get_key_event(void)
{
	static u08 keydown = 0;
	register u08 i;
	event_e event = EV_IDLE;

	cbi(MCUCR, SRE);		// disable ExtRAM

	outp(0xff, PORTA-1);	// set port as output
	outp(0, PORTA);			// set all pins to 0
	asm volatile("nop");	// allow time for port to activate

	if (keydown)			// if a key was pressed earlier
	{
		// see if it has been released
		if (bit_is_set(PIND, PD3))				// check bit
		{
			// no key is down, return last key seen
			if (nKeyTime < 8)					// max 0.8 sec for shortpress
				event = TableKbdShort[keydown];	// short keypress event
			keydown = 0;
		}
		else
			if ((nKeyTime & 0x7F) > 8)			// long keypress ? 
			{
				event = TableKbdLong[keydown];	// long keypress event
				nKeyTime = 0x83;				// 0.6 sec repeat time
			}

	}
	else
	{	
		if (bit_is_clear(PIND, PD3))	// check if a key is down
		{
			// a key is active, check which one
			for (i = 0; i < 8; i++)
			{
				outp(~(1 << i), PORTA);			// write bit mask
				asm volatile("nop");			// wait a while
				if (bit_is_clear(PIND, PD3)) 	// this bit ?
				{
					keydown = i + 1;	// store the key
					nKeyTime = 0;		// clear keypress timer
					break;				// and exit
				}
			}
		}
	}

	sbi(MCUCR, SRE);					// enable ExtRAM
	return event;
}



void send_sinewave_beeps(void)
{
	static u08 buf[] = { 0x53, 0xEF, 0x6E , 0x30, 0x45, 0x78, 0x69, 0x74 };
	register u08 i, j = 3;

	while (j-- != 0)
	{
		for (i = 0; i < 4; i++)
			vs1001_send_data(buf[i]);
		vs1001_nulls(4);
		delay10(10000);		// delay 100ms

		for (/*i = 4*/; i < 8; i++)
			vs1001_send_data(buf[i]);
		vs1001_nulls(4);
		delay10(10000);
	}	
}


void userchars(void)
{
#ifdef ENABLE_LCD
	static u08 data[] = { 0x10, 0x18, 0x1C, 0x1E, 0x1F };
	register u08 i = 0;
	
	lcd_command(0x48);		// start at 2'nd definable character
	while (i < 40)
		lcd_data(data[i++ >> 3]);	// eight times send each value
	// 2 more user definable characters possible
#endif
}


void setvolume(u08 v)
{
	register u08 i;

	vs1001_setvolume(v, v);
	eeprom_wb(EEPROM_VOLUME, v);

	lcd_command(0x40);

	for (i = 0; i < 8; i++)
	{
		if (v <= i * (VOL_STEP*(NUM_VOL_STEPS/8)))
			lcd_data((1 << ((10 - i) / 2)) - 1);	// Volume idicator mod
		else
			lcd_data(0x00);
	}
}


void dispbar(void)					// 10 bars of 5 steps each = 50 steps
{
	register u08 i, a, nSteps = (u08)((dwPlayed * LCD_STEPS) / dwFileSize);

	a = nSteps / 5;						// # of full bars

	lcd_gotoxy(0, 1);				

	for (i = 0; i < a; i++)
		lcd_putchar(5);

	if (a <= (LCD_STEPS / 5) - 1)	// jman to fix display overwrite
		lcd_putchar(1 + nSteps % 5);	
}


void eeprom_ww(u08 address, u16 value)
{
	union u16convert Data;
	Data.value = value;

	while (!eeprom_is_ready());
	eeprom_wb(address, Data.bytes.low);
	while (!eeprom_is_ready());
	eeprom_wb(address + 1, Data.bytes.high);
	while (!eeprom_is_ready());
}


bool RetrieveMP3Data(void)
{
// Buf1 Buf2 Action
//	E    E   Read full, return true
//	F    E   if (prep_read)
//	E    F		return true
//			 else
//			    read_info
//	F    F   prep_read
	u08 nRes;

	if (pPlayBufStart == BUFFER1P)	// Check that we exhausted buffer
	{
		if (pPlayData == BUFFER1P + BUFFER_SIZE)
			bBuf1Empty = true;
	}
	else							// pPlayBufStart == BUFFER2P
	{
		if (pPlayData == BUFFER2P + BUFFER_SIZE)
			bBuf2Empty = true;
	}

	if (bBuf1Empty  &&  bBuf2Empty)	// First case - both buffers empty
	{								//  unconditional read
		if (CheckAndAdvanceCluster())
		{
			ReadBuffer(BUF1);
			pPlayData = pPlayBufStart = BUFFER1P;
			return true;			// Need imeediate pump in
		}
		else
			return false;			// No more data for this file
	}

	if (!bBuf1Empty  &&  !bBuf2Empty)// Both buffers filled, refresh FAT cache 
		return CheckAndAdvanceCluster() == FAT_READ;

	if (bBuf1Empty)
	{
		if (pPlayBufStart == BUFFER1P)		// Need to switch buffer
			pPlayData = pPlayBufStart = BUFFER2P;
		nRes = CheckAndAdvanceCluster();
		if (nRes == NO_DATA)
			return false;
		if (nRes == DATA_EXIST)
			ReadBuffer(BUF1);
		return true;				// Was disk operation, need pump in
	}

	if (bBuf2Empty)
	{
		if (pPlayBufStart == BUFFER2P)		// Need to switch buffer
			pPlayData = pPlayBufStart = BUFFER1P;
		nRes = CheckAndAdvanceCluster();
		if (nRes == NO_DATA)
			return false;
		if (nRes == DATA_EXIST)
			ReadBuffer(BUF2);
		return true;				// Was disk operation, need pump in
	}
}


#ifdef HEXDUMP

void HexDump(u08 *buffer, u16 len)
{
    u16 i, j, k;

    EOL();
    for (i = 0, k = 0; i < len / 16; i++, k += 16)
    {
        UART_Printfu16(k);
        UART_SendByte(' ');
        for (j = 0; j < 16; j++)
        {
            UART_Printfu08(buffer[i * 16 + j]);	
            UART_SendByte(' ');
        }
        PRINT("    ");
        for(j =0 ; j < 16; j++)
        {
            if (buffer[i * 16 + j] >= 0x20)
                UART_SendByte(buffer[i * 16 + j]);
            else
                UART_SendByte('.');
        }
        EOL();
    }
}

void sectordump(u32 sector)
{
	if (ATA_ReadLBA0(sector, 1, TMP_SECTOR) == 0)
	{
		UART_Printfu32(sector);
		HexDump(TMP_SECTOR, BPS);
	}
	else
		PRINT("Dump failed\n");
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -