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

📄 yampp7_usb.c

📁 使用AVR单片机M162制做的MP3,这是整机的代码.可做参考.
💻 C
📖 第 1 页 / 共 5 页
字号:


void lcd_clrline(u08 line)		// clear single line of LCD
{
	register u08 i = 15;
	lcd_gotoxy(4,line);
	while(i--)
		lcd_putchar(' ');
	lcd_gotoxy(4,line);		// goto begin of line
}


void lcd_clricon(u08 objc)
{
	lcd_color(colors[objc], colors[objc+16]);
	lcd_clrline(ICONS_YPOS+2);
	lcd_clrline(ICONS_YPOS);
}

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

#define IMAGES_COUNT	6

u08 icon_cache[6];		// max 6 avaliable icons at the same time

void clr_icon_cache(void)
{
	memset(icon_cache, 255, 6);
}

void lcd_image(u08 number)
{
	u08 i;

	clr_icon_cache();
	number *= 32;
	lcd_window(0,0,127,127);
	wdt_reset();
	cbi(PORTB,LCD_CS);
	lcd_wrcmd(LCD_CMD_RAMWR);
	sbi(PORTB,LCD_CS);

	u16 j;
	for(i=0; i<32; i++)
	{
		pump_audio();
#if (CLKDIV > 0)
	set_cpu_speed(CLKDIV>>1);		// Cpu speed * 2
#endif
		CARD_Read(lcd_data_start + number);		// read sector
		number++;
		cbi(PORTB,LCD_CS);
		for(j=0; j<512; j++)
			lcd_wrdata(SectorBuffer[j]);
		sbi(PORTB,LCD_CS);
	}
	pump_audio();
}


void lcd_icon(u08 number, u08 xpos)
{

	if(icon_cache[xpos] != number)
	{
		icon_cache[xpos] = number;
		xpos = xpos*18 + 5;
		lcd_window(xpos,ICONS_YPOS,xpos+15,ICONS_YPOS+15);

		// read data, 256 bytes/icon, starting after last image
		CARD_Read(lcd_data_start + number/2 + (32*IMAGES_COUNT));		// read sector

		cbi(PORTB,LCD_CS);
		lcd_wrcmd(LCD_CMD_RAMWR);

		u08 *p = (number % 2) ? SectorBuffer+256 : SectorBuffer;
		u08 i = 0;
		while (--i)
			lcd_wrdata(*p++);

		sbi(PORTB,LCD_CS);
		pump_audio();
	}
}

//--------------------------------------------------------------------------
void status_display(void)
{
	u08 i,j,v;
	lcd_icon(bRandom ? 2:1 ,0);		// icon 1 or 2 - random status
	lcd_icon(Repeat + 3 ,1);		// icon 3 to 6 - repeat status
	lcd_icon(bLoudness + 13 ,2);		// icon 13 to 25 - loudness status

	if ((keylock & 1) == 1)
		lcd_icon(7 ,3);			// icon 7 - keys locked
	else
	{
		if (autolock)
		{
			i = keylock_time*8 / AUTOLOCK_TIME;
			lcd_icon(26 + ((i>7) ? 7:i) ,3);	// icons 26 to 33 - autolock timer ON - animation
		}
		else
			lcd_icon(8 ,3);		// icon 8 - keys UnLocked
	}

	if(!IsCharging())
		lcd_icon((lobatt > 1) ? 10:9 ,4); // icon 9 or 10 - batt full, empty

	lcd_color(colors[BALANCE_INDICATOR], colors[BALANCE_INDICATOR+16]);
	if(info_flag == 1)
	{
		lcd_gotoxy(97,ICONS_YPOS);
		i = balance;
		if(balance <= 0)
		{
			lcd_putchar(31);
			i = 0-balance;
		}
		else
			lcd_putchar(' ');

		printf("%u",i/6);
		lcd_putchar( (balance >= 0) ? 30 : ' ');
	}
	else 
	{
		if (volume < MIN_VOLUME)
		{
			lcd_window(95,ICONS_YPOS, 122,ICONS_YPOS+15);
			cbi(PORTB,LCD_CS);
			lcd_wrcmd(LCD_CMD_RAMWR);
			for (i=0; i<16; i++)
			{
				v = 28*(16-i) / 16;
				for(j=0; j<28; j++)
				{
					if(j>v && MIN_VOLUME - volume >= j * VOL_STEP * NUM_VOL_STEPS / 28)
						lcd_wrdata(colors[VOLUME_BAR+1]);
					else
						lcd_wrdata(colors[VOLUME_BAR]);
				}
			}
			sbi(PORTB,LCD_CS);
		}
	}

}
//--------------------------------------------------------------------------

void eeprom_update(void)
{
	union u16convert Data;
	// save current settings to EEPROM
	Data.value = curPlaylist;
	eeprom_wb(EEPROM_PLAYLIST, Data.bytes.low);
	eeprom_wb(EEPROM_PLAYLIST + 1, Data.bytes.high);
	Data.value = curIndex;					// save song number within current playlist
	eeprom_wb(EEPROM_SONGPOS, Data.bytes.low);
	eeprom_wb(EEPROM_SONGPOS + 1, Data.bytes.high);
	eeprom_wb(EEPROM_VOLUME,volume);
	eeprom_wb(EEPROM_BALANCE,balance);
	eeprom_wb(EEPROM_REPEAT,Repeat);
	eeprom_wb(EEPROM_RANDOM,bRandom);
	eeprom_wb(EEPROM_TIME,timemode);
	eeprom_wb(EEPROM_LOUDNESS, bLoudness);
	eeprom_wb(EEPROM_AUTOLOCK,autolock);
	eeprom_wb(EEPROM_BACKLIGHT,light_mode);		// save backlight mode
}

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

void PowerOff(void)
{
	beep(SINE_500,150);
	backlight_on();

	if(CARD_SW_Reset2())
		lcd_image(4);

	u08 i = POWER_OFF_BAR_LEN;
	union u16convert Data;
	while(i-=2)
	{
		lcd_gotoxy(POWER_OFF_BAR_XPOS, POWER_OFF_BAR_YPOS);
		Data.bytes.high = colors[POWER_OFF_BAR];
		Data.bytes.low  = colors[POWER_OFF_BAR+1];
		lcd_bar((POWER_OFF_BAR_LEN + 2)<<8 | i, Data.value);
		delayms(10);
	}
	eeprom_update();
	sbi(ACSR,ACD);				// Disable Analog Comparator
	sbi(GIMSK,INT2);			// enable external interrupt 2 on falling edge
	wdt_disable();				// disable the watchdog
	TCCR0 = 0;				// Disable Timer 0
	sbi(DDRB,  LED_PIN);
	cbi(PORTB, LED_PIN);			// Backlight off
	cbi(PORTB, RESET_PIN);			// keep VS1001 reset
	lcd_off();
	cbi(CHARGE_PORT,CHARGE_PIN);		// disable pullup on charge input
	cbi(CHARGE_DDR,CHARGE_PIN);		// and switch to input for no current draw in sleep mode

#ifdef MMC_CARD
	MMC_Off();
//	sbi(MMC_PORT,MMC_CS);			// MMC CS HIGH
//	sbi(MMC_DDR,MMC_CS);
#endif
	PORTA = 0;
	DDRA = 0xff;				// PORTA Output and LOW
	PORTC = 0x80;				// Deselect CF Card
	cbi(PORTB, PB2);			// FTDI reset
#ifndef FIXED_RESET
	PORTD = 0x32;				// WR and RD low to avoid powering FTDI chip via WR and RD signals
#else
	PORTD = 0xB2;				// RD high and and WR low to avoid powering FTDI chip via WR and RD signals,
#endif						// but need to modyfi the board. High RD is for solving problems
						// with accidentaly CF card "True IDE Mode" entering after card insert.
	sei();					// global interrupt enable
	DDRD = 0xC0;				// WR and RD as output
sldo:
	MCUCR = 0x30;				// enable deep sleep mode and disable EXT RAM
	TCCR1B = 0;				// stop timer1
	asm volatile("sleep");			// Enter to Sleep mode
	asm volatile("nop");

// *********************************** 

	// wakeup going here
	MCUCR = 0x20;				// enable idle mode
	TCCR1B = 4;				// start timer1
	sleepcount = 0;
	while(sleepcount < 10)
	{
		asm volatile("sleep");		// Enter to idle mode
		asm volatile("nop");
		if bit_is_set(PINE,BUTTON_1)	// Play key pressed ?
			goto sldo;		// No, go to deep sleep again
	}
	PORTD = 0xFF;				// WR and RD high to avoid CF garbage
	wdt_enable(1);
	while (1);				// reset player by watchdog
}

/******************************************************************************
*				KEYBOARD CONTROL FUNCTION					*
******************************************************************************/

//
// button handling
//

//------------------------------------------------------------------------------------------
// Keyboard layout (while playing)
//
//		 			BUTTON_1	BUTTON_2	BUTTON_3	BUTTON_4	
u08 TableKbdShort[] = { EV_IDLE,	EV_PLAY,	EV_STOP, 	EV_NEXT,  	EV_PREV };
u08 TableKbdLong[]  = { EV_IDLE, 	EV_FFWD,	EV_MENU, 	EV_UP, 		EV_DOWN };

// Keyboard layout (On Stop)
//	 				BUTTON_1	BUTTON_2	BUTTON_3	BUTTON_4	
//			ShortPress:	PLAY		STOP	 	MBASS	  	RANDOM
//			LongPress: 	PWR.OFF 	MENU		AU.LOCK,	LCD Contrast


void check_keylock(void)
{
	if (bit_is_clear(PIND,BUTTON_3) && bit_is_clear(PIND,BUTTON_4))
	{						// if both top buttons down
		wdt_disable();				// disable watchdog for prevent from bootloader entering
		keylock |= 2;				// mark as pressed

		if (nKeyTime == 2)			// if pressed by 0.3 second
			backlight_on();			

		if (nKeyTime == 10)			// if pressed by 1 second
		{
			nKeyTime++;
			keylock_time = 0;
			keylock ^= 1;			// flip keylock status (bit 0)
		}
		return;
	}
	else
	{
		// both top buttons released and change occur
		if (keylock > 1 && bit_is_set(PIND,BUTTON_3) && bit_is_set(PIND,BUTTON_4))
		{
			nKeyTime = 0;			// clear key timer
			keylock &= 1;			// clear marker
			wdt_enable(6);			// enable watchdog
			if(keylock)
				backlight_off();	// Backlight off in locked state
		}

		if (keylock)
			nKeyTime = 0;
	}
}

void get_key(void)
{
	static u08 keydown = 0;
	u08 keyflag;
	event_e event = EV_IDLE;

	if (keydown)					// if a key was pressed earlier
	{
		// see if it has been released
		
		if (bit_is_set(PINE,BUTTON_1) &&			// if key up
		    bit_is_set(PIND,BUTTON_2) &&			// if key up
		    bit_is_set(PIND,BUTTON_3) &&			// if key up
		    bit_is_set(PIND,BUTTON_4) )			// if key up
		{
			// no key is down, return last key seen
			if (nKeyTime < 8 && nKeyTime > 0)		// max 0.8 sec for shortpress
				event = TableKbdShort[keydown];	// short keypress event
			keydown = 0;
		}
		else
			if ((nKeyTime & 0x7F) >= 8)			// long keypress ? 
			{
				light_time = BACKLIGHT_TIME;
				event = TableKbdLong[keydown];		// long keypress event
				if (event == EV_UP || event == EV_DOWN || event == EV_FFWD)
					nKeyTime = 0x86;		// 0.2 sec repeat time for volume
				else
					nKeyTime = 0x80;		// as long repeat as possible
			}	
	}
	else
	{	
		keyflag = 0;
		if (bit_is_clear(PINE,BUTTON_1))			// if key 1 down
			keyflag = 1;					// store it
		if (bit_is_clear(PIND,BUTTON_2))			// if key 2 down
			keyflag = 2;					// store it
		if (bit_is_clear(PIND,BUTTON_3))			// if key 3 down
			keyflag = 3;					// store it
		if (bit_is_clear(PIND,BUTTON_4))			// if key 4 down
			keyflag = 4;					// store it

		if (keyflag && nKeyTime > 0)
		{
			keydown = keyflag;				// store it
			keylock_time = 0;
			backlight_on();
		}

		if (keyflag == 0)
			nKeyTime = 0;					// clear keypress timer
	}	

	if (event != EV_IDLE)
		set_event(event);
}

/******************************************************************
*			RANDOM STUFF				  *
******************************************************************/

// Random stuff, maximum 512 songs
u08 RANDOM_TAB[64];				// "True Random" table, maximum 512 songs

// Init randomizer table
void InitRnd(void)
{
	memset(RANDOM_TAB,0,sizeof(RANDOM_TAB)); // one bit in table represent one song
}

u08 tabval(u16 num, u08 fn)				// check random tabele for song status
{							// and mark as played if necessary
	u08 index = (u08)(num >> 3);
	u08 offset = 1 << (num % 8);
	if(fn)
		RANDOM_TAB[index] |= offset;		// if fn=1 mark as played

	return (RANDOM_TAB[index] & offset);		// return status
}

// new random procedure
u16 do_rand(u16 max)					// returned random value from 0 to max - 1
{
	u16 num;
	max &= 0x01ff;					// limit to 512 songs to lower RAM usage
	for(num = 0; num < max; num++)			// check if all songs in playlist has been played
		if(tabval(num,0) == 0)			// this one not be played yet
			break;				// break loop
	if (num == max)					// if all has been played
		num = -1;				// no more songs in current playlist
	else
	{
		do
		{
			wdt_reset();			// kick the dog
			num = (TCNT1 + TCNT0 + SectorBuffer[32]) % max;	// get a random number
		} while (tabval(num,0) != 0);		// loop if this song has already been played
		tabval(num,1);				// else, mark as played
	}
	return num;					// return song # to play
}


/************************************************************************
*				FORMAT NEW DISK				*
*************************************************************************/

u08 format_new_disk(void)
{
	YADL_ROOT_SECTOR *pBoot;					// Boot Sector struct
	u32 sectors;

#ifndef MMC_CARD

	IDENTIFY_DATA *pID;	
	u08 i,c;
	u08 tmpSectorBuffer[sizeof(pID->ModelNumber)];

	// first get some drive data
	CARD_Identify();
	
	// flip and save the ModelNumber data
	pID = (IDENTIFY_DATA *) SectorBuffer;
	strncpy(tmpSectorBuffer,(u08*)pID->ModelNumber,sizeof(pID->ModelNumber));
	for (i=0;i<sizeof(pID->ModelNumber);i+=2)
	{
		c = tmpSectorBuffer[i];
		tmpSectorBuffer[i] = tmpSectorBuffer[i+1];
		tmpSectorBuffer[i+1] = c;
	}
	tmpSectorBuffer[sizeof(pID->ModelNumber)] = 0;			// terminate entry
	
	// get max sectors (disk size)
	sectors = pID->UserAddressableSectors;

#else

	u08 tmpSectorBuffer[8];
	MMC_Name();
	strncpy(tmpSectorBuffer, SectorBuffer, 7);
	tmpSectorBuffer[7] = 0;						// terminate entry
	sectors = MMC_Capacity();

#endif

	// clear buffer
	pBoot = (YADL_ROOT_SECTOR *) SectorBuffer;		// use temp buffer for room
	strcpy_P(pBoot->model,firmware_scan_tag);		// for compiler warning supression...
								// I don't know why, but it decrease code size too
	memset(pBoot,0,512);				

// section 1
	strncpy(pBoot->id,"YADL",4);
	pBoot->disk_size = sectors;
	pBoot->unmount_state = YADL_STATE_NEW;
	pBoot->media_type = YADL_MEDIA_FLASH;

	pBoot->disk_version_major = DISK_LAYOUT_VERSION_MAJOR;
	pBoot->disk_version_minor = DISK_LAYOUT_VERSION_MINOR;

	strcpy_P(pBoot->model,model_txt);	// yampp model name

	// copy the ModelNumber result from Identify Drive
	strcpy(pBoot->disk_info,tmpSectorBuffer);	

// section 2
	
	strcpy_P(pBoot->build_timestamp,date_txt);
	pBoot->build_timestamp[YADL_LEN_BUILD_TIMESTAMP-1] = 0;	// make sure it's terminated

	pBoot->firmware_version_major = YAMPP_FIRMWARE_VERSION_MAJOR;
	pBoot->firmware_version_minor = YAMPP_FIRMWARE_VERSION_MINOR;
	
// section 3	
// section 4
// section 5

	// write the sector
	// and return result
	
	return CARD_Write(YADL_SEC_ROOT);
}



//////////////////////////////////

u32 songbase_start;
u16 songbase_qty;			// number of songs
u32 fat_start;				// first fat sector
u32 sector_cluster_offset;		// add to cluster -> sector conversions
u32 playlist_start;			// first playlist sector
u16 playlist_qty;			// number of playlists

/////////////////////////////////

⌨️ 快捷键说明

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