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

📄 yampp7_usb.c

📁 DIY自己的MP3的参考价值极高的代码。含有详细的解释
💻 C
📖 第 1 页 / 共 5 页
字号:
void idle(void)
{
static	u08 iconflash = 1;

	wdt_reset();						// reset the watchdog
	usb_handler();
	if(usb_link == 0)					// usb link disables other control
	{
		set_cpu_speed(CLKDIV);				// CPU clock = XTAL / M162CLKDIV
		if (isPlaying) 					// only during playing
			check_keylock();
		else
			keylock = 0;

		if (!keylock)					// if keylock active
			get_key();				// check keyboard
	}
	else
		return;

	u08 charging = IsCharging();				// check charging status

	if (isPlaying)
	{
		sleepcount = 0;					// power off blocking
		feed_audio_data();
		if (vol_decrease && (time_flag == 4))		// If fast forward volume downed
		{
			vs1001_setvolume(volume,balance);	// Restore volume
			vol_decrease = 0;
		}

//------------------------ LCD VISUALISATION ----------------------------

		if (scroll_flag >= SCROLL_SPEED && info_flag < 3)
		{
			u08 nTemp;

			scroll_flag = 0;

			//
			// scrolling artist

			if (scroll_length > 15)
			{
				lcd_color(colors[ARTIST_NAME], colors[ARTIST_NAME+16]);
				lcd_gotoxy(4, ARTIST_NAME_YPOS);
				for (nTemp = 0; nTemp <  15; nTemp++)
#ifdef ALTERNATE_SCROLL
					lcd_putchar(artistname[scroll_pos + nTemp]);

				if (scroll_pos + 15 == scroll_length)
					scroll_dir -= 2;
				if (scroll_pos == 0)
					scroll_dir++;

				scroll_pos += ((signed char)scroll_dir / (10/SCROLL_SPEED));

#else //ALTERNATE_SCROLL
					lcd_putchar(artistname[(scroll_pos + nTemp) % scroll_length]);
#endif
				feed_audio_data();
			}

			//
			// scrolling name

			if (scroll_length_2 > 15)
			{
				lcd_color(colors[SONG_NAME], colors[SONG_NAME+16]);
				lcd_gotoxy(4, SONG_NAME_YPOS);
				for (nTemp = 0; nTemp < 15; nTemp++)
#ifdef ALTERNATE_SCROLL
					lcd_putchar(titlename[scroll_pos_2 + nTemp]);

				if (scroll_pos_2 + 15 == scroll_length_2)
					scroll_dir_2 -= 2;
				if (scroll_pos_2 == 0)
					scroll_dir_2++;

				scroll_pos_2 += ((signed char)scroll_dir_2 / (10/SCROLL_SPEED));
#else //ALTERNATE_SCROLL
					lcd_putchar(titlename[(scroll_pos_2 + nTemp) % scroll_length_2]);
#endif
				feed_audio_data();
			}

#ifndef ALTERNATE_SCROLL
			scroll_pos++;
			scroll_pos_2++;
#endif
		}

		if (time_flag >= 5 && info_flag < 3)
		{
			if(bLoudness)
				vs1001_write(0x0D,bLoudness);			// Rewrite loudness settings
										// if VS1001 do selfreset
			//
			// display bar function

			register u08 nSteps = (u08)((fileplayed * (PROGRESS_BAR_LEN+2)) / filesize);
			lcd_gotoxy(PROGRESS_BAR_XPOS, PROGRESS_BAR_YPOS);
			union u16convert Data;
			Data.bytes.high = colors[PROGRESS_BAR];
			Data.bytes.low  = colors[PROGRESS_BAR+1];
			lcd_bar((PROGRESS_BAR_LEN<<8) | nSteps, Data.value);

			//
			// printing song time 

			lcd_color(colors[SONG_TIME], colors[SONG_TIME+16]);
			lcd_gotoxy(SONG_TIME_XPOS, SONG_TIME_YPOS);	// time display position
			u16 wPlayTime = vs1001_read(VS1001_PLAYTIME) + addtime;

			if (timemode == 1)
			{
				wPlayTime = songtime - wPlayTime;		// calculate time remain
				if ((s16)wPlayTime < 0)
					wPlayTime = 0;
			}
			printf("%3u:%02u", wPlayTime / 60, wPlayTime % 60); 	// print time on LCD
			if (timemode == 1)
			{
				lcd_gotoxy(SONG_TIME_XPOS + 8*(wPlayTime < 600), SONG_TIME_YPOS);
				lcd_putchar('-');
			}

			if(info_flag < 2)
			{
				status_display();
				if (charging)					// charging in progress ?
				{
					lobatt = 0;
					lobatt_time = 0;
					iconflash = !iconflash;
					if (iconflash)
						lcd_icon(11,4);			// battery charging icon 1
					else
						lcd_icon(12,4);			// battery charging icon 2
				}
			}

			if (!info_flag)
				time_flag = 0;
		}

		if((time_flag > 30) && (menu_event != EV_IDLE))		// display overvrite timer ends
		{
			info_flag = 0;					// enable status updating
			menu_event = EV_IDLE;
			Playlist_name();				// show Playlist name
		}

//------------------------ LCD VISUALISATION END -------------------------

	}//if (isPlaying)
	else
	{
		if (charging)					// charging in progress ?
		{
			sleepcount = 0;				// power off blocking
			lobatt = 0;				// clear low battery status
			lobatt_time = 0;			// clear low battery timer
			if(!info_flag)				// not in menu
			{
				if (time_flag % 10 == 4)
				{
					lcd_gotoxy(BATTCHARGE_TEXT_XPOS, BATTCHARGE_TEXT_YPOS);
					lcd_color(colors[BATTCHARGE_TEXT], colors[BATTCHARGE_TEXT+16]);
					_p_puts(Charge_txt);
					lcd_icon(11,4);			// battery charging icon 1
				}

				if (time_flag % 10 == 9)
					lcd_icon(12,4);			// battery charging icon 2
			}
		}

		if (!menu_event)
		{
			MCUCR = 0xA0;				// choose idle mode
			asm volatile ("sleep");			// go to sleep
			asm volatile ("nop");
			wdt_reset();				// reset the watchdog
		}

		if (sleepcount > DEEP_SLEEP_TIMEOUT)
			PowerOff();				// Go to power off procedure and off player

		if (! CARD_SW_Reset2())				// if card removed
			PowerOff();				// power off

		if (time_flag >= 30)
		{
			if (menu_event || (lobatt_time < 50 && !charging))	
				set_event(EV_STOP);		// if auto menu exit or end of battery charge
			else
				status_display();

			menu_event = EV_IDLE;
			time_flag = 0;
		}
	} 

	BatteryMeasure();
	
	if (lobatt == 2)
	{
		u16 off_time = lobatt_time;
		if ((off_time % 600) == 10)			//beeps in one minute interval
		{
			beep(SINE_2000,80);
			lcd_clricon(LOBAT_ALERT);
			_p_puts(Lobatt_txt);
			info_flag = 2;				//denny status line displaying
		}
		if ((off_time % 600) == 50)
		{
			info_flag = 0;				//allow status line displaying
			lcd_clricon(LOBAT_ALERT);
			clr_icon_cache();
		}
		if (off_time > 6050)				//and power off after 10 minutes
		{
			send_sinewave_beeps();
			PowerOff();
		}
	}
}

void play_song(void)
{
	YADL_SONG_BASE_ENTRY *pEntry = get_song_entry(get_offset_entry(curIndex));

	if(pEntry->state != YADL_STATE_READY)			// check for valid song entry
	{
		lcd_color(colors[LOBATT_TEXT], colors[LOBATT_TEXT+16]);
		lcd_clrline(BATTCHARGE_TEXT_YPOS);
		_p_puts(BaseErr_txt);
		beep(SINE_500,500);
		delayms(2000);
		send_sinewave_beeps();
		set_event(EV_STOP);
		return;
	}

	addtime = 0;
	bitrate = ((pEntry->bitrate) & 0x7fff);			// get bitrate and mask VBR signature (MSB)
	strcpy(artistname, pEntry->artist);
	scroll_length = strlen(artistname);
#ifndef ALTERNATE_SCROLL
	if (scroll_length > 16)
	{
		strcat(artistname, " >> ");			// add ' >> ' sign
		scroll_length += 4;		
	}
#endif

	//
	// calc number of VS1001 blocks
	//
	filesize = pEntry->length / 32;

	fileplayed = 0;
	ClusterCount = 0;					// Reset Cluster counter

	//
	// preload buffers
	//
	init_load_sectors(pEntry->start);
	outptr = SectorBuffer;

	//
	// start playing the song
	//

	isPlaying = 1;
	vs1001_reset();
	LoudSet();
	if (!info_flag)
		Playlist_name();
}

void next_playlist(void)
{
	YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(curPlaylist);

	if(pListEntry->next_playlist != (u16)-1)		// check for next playlist number
		curPlaylist = pListEntry->next_playlist;
	else
		curPlaylist++;

	if((curPlaylist == (u16)-1) || (curPlaylist >= playlist_qty))
		curPlaylist = 0;

	pListEntry = get_pl_entry(curPlaylist);
	InitRnd();							// init randomizer table

	curIndex = (bRandom) ? do_rand(pListEntry->entry_qty) : 0;
}

void prev_playlist(void)
{
	if(--curPlaylist == (u16)-1)					// playlist down
		curPlaylist = playlist_qty - 1;				// go to last playlist
	YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(curPlaylist);	// update playlist data
	InitRnd();

	curIndex = (bRandom) ? do_rand(pListEntry->entry_qty) : pListEntry->entry_qty-1;
}

void next_song(u08 mode)
{
	YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(curPlaylist);

	if (Repeat == 3 && mode == 0)				// repeat one song
		goto GO_PLAY;


	if (mode == 2)
	{
#ifdef NEW_PREW
		if(ClusterCount)
			goto GO_PLAY;
		else
#endif
			curIndex = (bRandom) ? do_rand(pListEntry->entry_qty) : curIndex-1;
	}
	else
		curIndex = (bRandom) ? do_rand(pListEntry->entry_qty) : curIndex+1;

	if (curIndex < (pListEntry->entry_qty))			// if not End of playlist
		goto GO_PLAY;
	else
	{
		InitRnd();					// init randomizer table
		if(Repeat == 2)					// repeat playlist
		{
			if (bRandom)
				curIndex = do_rand(pListEntry->entry_qty);
			else
				curIndex = 0;
			goto GO_PLAY;
		}

		if(Repeat == 0)
		{
			set_event(EV_STOP);			// normal play, stop after end of playlist
			return;
		}

		if(Repeat == 1 || Repeat == 3)			// normal play and repeat one song, next playlist after end of playlist
		{						// fixed by Roger Nilson
			if (mode == 2)
				prev_playlist();
			else
				next_playlist();
GO_PLAY:		play_song();
		}
	}
}

//----------------------------------------------------------------------------

void set_contrast(void)
{
	event_e event = EV_IDLE;
	u08 contrast = eeprom_rb(EEPROM_LCD_CONTRAST);
	lcd_image(5);						// Contrast menu image
	info_flag = 3;
	union u16convert Data;
	goto SETC;

	while(1)
	{
  		wdt_reset();					// reset the watchdog
		time_flag = 0;
		sleepcount = 0;					// power off blocking
		event = get_event();
		switch(event)
		{
			default:
			case EV_IDLE: 
				break;

			case EV_UP:
			case EV_NEXT:
				if (contrast < 0x40)
					contrast++;
				goto SETC;

			case EV_DOWN:
			case EV_PREV:
				if (contrast > 0x10)
					contrast--;
SETC:
				lcd_gotoxy(CONTRAST_BAR_XPOS, CONTRAST_BAR_YPOS);
				Data.bytes.high = colors[CONTRAST_BAR];
				Data.bytes.low  = colors[CONTRAST_BAR+1];
				lcd_bar(0x60<<8 | (2*(contrast-0x10)), Data.value);
				lcd_contrast(contrast);
				break;

			case EV_STOP:
				eeprom_wb(EEPROM_LCD_CONTRAST,contrast);
				set_event(EV_STOP);
				return;
		}
		event = EV_IDLE;
	}
}

void set_cpu_speed(u08 speed)
{
	asm volatile("ldi r25, 128");
	asm volatile("cli");
	asm volatile("sts 0x61, r25");
	asm volatile("sts 0x61, r24");
	asm volatile("sei");
}

//----------------------------------------------------------------------------
// Main part
//----------------------------------------------------------------------------
int main(void) 
{
 
 //------------------------------
 // Initialize 
 //------------------------------

//////////////////////////////////////////////////////////////////
// B - Port
//////////////////////////////////////////////////////////////////

	PORTB = 0x0A;
	DDRB = 0xff;

//	cbi(PORTB,LED_PIN);
//	sbi(DDRB, LED_PIN);		// pin PB0 is output for LED or backlight
//	sbi(PORTB,RESET_PIN);		// RESET- hi
//	sbi(DDRB, RESET_PIN);		// pin PB1 is output, RESET- 

	// PB2 is BSYNC pin to VS1001
	// PB3 is MP3 signal to VS1001 and battery monitor input
	// PB4 is SCE signal for LCD dosplay
	// PB5 (MOSI) is used for SPI
	// PB6 (MISO) is used for SPI
	// PB7 (SCK) is used for SPI
	
//////////////////////////////////////////////////////////////////
// D - Port
//////////////////////////////////////////////////////////////////

	PORTD = 0xFF;			// activate pullups
	DDRD  = 0xC0;
	// pin PD0 is DREQ input
	// pin PD1, PD4 and PD5 is keyboard input, enable pullup
	// PD2 and PD3 are RXF and TXE input pins from FTDI
	// PD6 and PD7 are WR and RD signals for CF and FTDI chip.

//////////////////////////////////////////////////////////////////
// E - Port
//////////////////////////////////////////////////////////////////

	sbi(PORTE,BUTTON_1);			// pin PE0 is keyboard input, enable pullup

#ifndef PCB_REV_D
	cbi(CHARGE_DDR,CHARGE_PIN);		// set pin as input
	sbi(CHARGE_PORT,CHARGE_PIN);		// activate pullup
#endif

	EMCUCR = 0;
	set_cpu_speed(CLKDIV);			// CPU clock = XTAL / M162CLKDIV
						// eg about 4-8MHz

	OCR0 = 0;				// PWM duty = 0%
	TCCR0 = (1<<WGM00) | (1<<COM01) | (1<<CS01) | (1<<CS00);	// Timer 0 normal PWM mode, CLK/64

	MCUCR = (1<<SRE);			// enable external SRAM 

	delayms(50);
	usb_init();
	wdt_enable(7);

	//
	// setup timer1 for a 100mS periodic interrupt
	//	
	TCCR1A = 0;
	TCCR1B = 4;				// prescaler /256  tPeriod = 32 uS
	TCNT1 = (u16)-(F_CPU / 2560);		// load counter value

	sbi(TIMSK, TOIE1);	 		// enable timer1 interrupt

	// setup some buffers

⌨️ 快捷键说明

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