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

📄 yampp3_usb.c

📁 老外个人做的MP3/优盘。使用ATMEL MEGA系列的MCU
💻 C
📖 第 1 页 / 共 5 页
字号:
		j=8;
		while(j--)
		{
			for (i = 0; i < 8; i++)
			{
				if (i >= j)
					lcd_data1f();
				else
					lcd_data00();
			}
		}

//		if(!info_flag)
//			lcd_clrline(LCD_LINES - 1);
//		else
			Vlcd_gotoxy(0, LCD_LINES - 1);

  #if (LCD_LINE_LENGTH > 16)
		Vlcd_progputs(PSTR("Volume "));
  #else
		Vlcd_progputs(PSTR("Vol"));
  #endif
		for (i=0; i < 8; i++)			// write volume bar
		{
			if(MIN_VOLUME - v >= i * (VOL_STEP*(NUM_VOL_STEPS/8)))
				Vlcd_putchar(i);
			else
				Vlcd_putchar(' ');
		}
		if (v < 20) Vlcd_putchar(' ');
		if (v > 1)
			Vlcd_putchar('-');
		else
			Vlcd_putchar(' ');
		lprintf("%udB",v/2);
	}

 #else //GRAPH_LCD

	status_display();				// update status bar on Graphisc LCD

	Vlcd_gotoxy(10+7*(LCD_TYPE == 8)-1*(v>19),LCD_TYPE-2);
	if (v > 1)
		Vlcd_putchar('-');
	else
		Vlcd_putchar(' ');
	lprintf("%udB",v/2);			// Volume Level

 #endif // GRAPH_LCD
#endif // SATTELITE


#ifdef VOL_UP_RAMP
	if(!volume_ramp)
#endif
		eeprom_wb(EEPROM_VOLUME,v);		// only after ramp ends (EEPROM write cycles save)

	time_flag = 5;					// prevent display overvriting for 2 second
	info_flag = 1;					// allow scroll data
}


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


void setbalance(s08 b)
{
	vs1001_setvolume(volume,b);
	eeprom_wb(EEPROM_BALANCE,b);
#ifdef GRAPH_LCD
	status_display();				// update status bar on Graphisc LCD
	u08 i = b;
#if(LCD_TYPE == 7)
	Vlcd_gotoxy(10,5);
#else
	Vlcd_gotoxy(17,6);
#endif
	Vlcd_putchar(' ');
	if(b <= 0)
	{
		Vlcd_putchar('<');
		i = 0-b;
	}
	else
		Vlcd_putchar('-');

	lprintf("%u",i/4);
	Vlcd_putchar( (b >= 0) ? '>':'-');

#else  //GRAPH_LCD

	u08 i = b;
	lcd_clrline(LCD_LINES - 1);
	Vlcd_progputs(PSTR("Balance "));
	if(b <= 0)
	{
		Vlcd_putchar(0x7f);
		i = 0-b;
	}
	else
		Vlcd_putchar('-');

	lprintf("-%u-",i/4);
	Vlcd_putchar( (b >= 0) ? 0x7e:'-');

#endif //GRAPH_LCD

	info_flag = 2;					// allow scroll data, balance mode
	time_flag = 5;					// prevent display overvriting for 2 second

}

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

void eeprom_ww(u16 address, u16 value)			// write word to eeprom
{
	asm volatile("call eeprom_write_byte");
	asm volatile("subi r24,lo8(-(1))");
	asm volatile("sbci r25,hi8(-(1))");
	asm volatile("mov r22,r23");
	asm volatile("call eeprom_write_byte");
}


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

// Random stuff, maximum 32768 songs on the disk!

static u32 seed = 1;

// Init randomize table
void InitRnd(void)
{
	memset(RANDOM_TAB,0,4096);		// clear random table
}

u16 randcalc(u16 max)							// assembler optimized randomizer function
{
//  return ((seed = seed * 1103515245L + 12345) % max);	// get new song number

	asm volatile ("push r24");
	asm volatile ("push r25");
	asm volatile ("lds r22,seed");
	asm volatile ("lds r23,(seed)+1");
	asm volatile ("lds r24,(seed)+2");
	asm volatile ("lds r25,(seed)+3");
	asm volatile ("ldi r18,lo8(1103515245)");
	asm volatile ("ldi r19,hi8(1103515245)");
	asm volatile ("ldi r20,hlo8(1103515245)");
	asm volatile ("ldi r21,hhi8(1103515245)");
	asm volatile ("call __mulsi3");
	asm volatile ("subi r22,lo8(-(12345))");
	asm volatile ("sbci r23,hi8(-(12345))");
	asm volatile ("sbci r24,hlo8(-(12345))");
	asm volatile ("sbci r25,hhi8(-(12345))");
	asm volatile ("sts seed,r22");
	asm volatile ("sts (seed)+1,r23");
	asm volatile ("sts (seed)+2,r24");
	asm volatile ("sts (seed)+3,r25");
	asm volatile ("pop r19");
	asm volatile ("pop r18");
	asm volatile ("clr r20");
	asm volatile ("clr r21");
	asm volatile ("call __udivmodsi4");
	asm volatile ("mov r25,r23");
	asm volatile ("mov r24,r22");
	return max;						// return result from R24:R25
}

u08 tabval(u16 num, u08 fn)					// check random tabele for song status
{								// and mark as played if necessary
	u16 index = 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 &= 0x7fff;						// limit for lower RAM usage
	for(num = 0; num < max; num++)
		if(tabval(num,0) == 0)
			break;
	if (num == max)
		num = -1;
	else
	{
		do
		{
//			WDR;
			num = randcalc(max);
		} while (tabval(num,0) != 0);			// check this song not be played piervously
		tabval(num,1);					// mark as just played
	}
	return num;
}


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

u08 format_new_disk(void)
{
	YADL_ROOT_SECTOR *pBoot;					// Boot Sector struct
	IDENTIFY_DATA *pID;	
	u08 i,c;
	u32 sectors;

	i = firmware_scan_tag[0];					// for compiler warning supression
	
	// first get some drive data
	IdentifyDrive(buffer1);
	
	// flip and save the ModelNumber data
	pID = (IDENTIFY_DATA *) buffer1;
	strncpy(buffer1,(u08*)pID->ModelNumber,sizeof(pID->ModelNumber));
	for (i=0;i<sizeof(pID->ModelNumber);i+=2)
	{
		c = buffer1[i];
		buffer1[i] = buffer1[i+1];
		buffer1[i+1] = c;
	}
	buffer1[sizeof(pID->ModelNumber)] = 0;				// terminate entry
	
	// get max sectors (disk size)
	sectors = pID->UserAddressableSectors;
	
	// clear buffer
	pBoot = (YADL_ROOT_SECTOR *) buffer2;				// use temp buffer for room
	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_DISK;

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

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

	// copy the ModelNumber result from Identify Drive
	strncpy(pBoot->disk_info, buffer1, YADL_LEN_DISK_INFO);	

// section 2
	
	strncpy_P(pBoot->build_timestamp, date_txt, YADL_LEN_BUILD_TIMESTAMP);
	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 (ATA_Write(0,1,(u08*) pBoot));
}


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


u32 songbase_start;			// first songbase sector
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

u32 MyCluster;				// current cluster number
u32 MySector;				// current sector number
u16 SectorsLd;				// sectors in cluster counter

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


//
// return the next FAT in a chain
//
u32 next_fat(u32 current_fat)
{
	u16 fat_offset;
	u32 fat_sector;
	static u32 fat_in_cache = -1;
	
	fat_sector = fat_start + current_fat / (SECTORSIZE / sizeof(CLUSTER));
	fat_offset = current_fat % (SECTORSIZE / sizeof(CLUSTER));
	
	if (fat_sector != fat_in_cache)
	{
		while(ATA_Read(fat_sector,1,(u08*)FAT_CACHE))
		    	ATA_SW_Reset2();
		fat_in_cache = fat_sector;
	}
	if(BackStepPos < MAX_REV_STEPS)
		Rev_Table[++BackStepPos] = ((CLUSTER*)FAT_CACHE)[fat_offset];
	return ((CLUSTER*)FAT_CACHE)[fat_offset];
}

void init_load_sectors(u32 cluster)
{
	MyCluster = cluster;
	MySector = sector_cluster_offset + YADL_SECTORS_PER_CLUSTER * MyCluster;
	SectorsLd = 0;
}


//
// load a bufferfull of data
//
void load_sectors(u08 *buffer)
{
	while(ATA_Read( MySector, BUFFERSIZE / SECTORSIZE, buffer))
	    	ATA_SW_Reset2();
	MySector += BUFFERSIZE / SECTORSIZE;
	SectorsLd += BUFFERSIZE / SECTORSIZE;
	if (SectorsLd == YADL_SECTORS_PER_CLUSTER)
		init_load_sectors(next_fat(MyCluster));
}

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

static char firmver_txt[] __attribute__ ((progmem)) = "Firmware version";

void init_stuff(void)
{
	u08 update = 0;
	YADL_ROOT_SECTOR *pRoot;				// Boot Sector struct
	pRoot = (YADL_ROOT_SECTOR *) buffer1;			// Allocate room from the temp buffer
	while(ATA_Read(0,1,buffer1))				// read root sector
		ATA_SW_Reset2();

	if(pRoot->id[0] != 'Y' || pRoot->id[1] != 'A' || 
	   pRoot->id[2] != 'D' || pRoot->id[3] != 'L')		// YADL signature not found
	{
		event_e event = EV_IDLE;
		Vlcd_clrscr();
		both_progputs(PSTR("Found not YADL\nor new disk !!\n"));
#if (LCD_LINES == 2)
		delayms(5000);
		Vlcd_clrscr();
#endif
		both_progputs(PSTR("Press PLAY to\nformat the disk."));
		uart_EOL();
		while((event = get_event()) != EV_PLAY);	// wait for PLAY key
		Vlcd_clrscr();
		both_progputs(PSTR("All data be lost\nAre you sure ?\n"));

		while((event = get_event()) == EV_PLAY);	// wait for release key

		while((event = get_event()) != EV_PLAY);	// wait for accept by PLAY key

#if (LCD_LINES == 2)
		Vlcd_clrscr();
#endif
		both_progputs(PSTR("Format"));
		register u08 i = format_new_disk();
		both_progputs((i) ? PSTR(" ERROR !") : PSTR("ing OK."));

		wdt_enable(0x07);
		while(1);					// reset player by watchdog
	}

	if(pRoot->firmware_version_major != YAMPP_FIRMWARE_VERSION_MAJOR)
	{
		pRoot->firmware_version_major = YAMPP_FIRMWARE_VERSION_MAJOR;
		update = 1;
	}
	if(pRoot->firmware_version_minor != YAMPP_FIRMWARE_VERSION_MINOR)
	{
		pRoot->firmware_version_minor = YAMPP_FIRMWARE_VERSION_MINOR;
		update = 1;
	}
	if(strcmp_P(pRoot->build_timestamp, date_txt))
	{
		strcpy_P(pRoot->build_timestamp, date_txt);
		update = 1;
	}
	if (update)
	{
		while(ATA_Write(0,1,(u08*) pRoot))
		    	ATA_SW_Reset2();
		Vlcd_clrscr();
		both_progputs((u08*)&firmver_txt);
		both_progputs(PSTR("\ninfo updated.\n"));
		delayms(4000);
	}

	sector_cluster_offset = pRoot->sector_cluster_offset;
	songbase_start 	= pRoot->songbase_start;			// SECTOR !!
	songbase_qty	= pRoot->songbase_qty;
	playlist_start 	= sector_cluster_offset + YADL_SECTORS_PER_CLUSTER * pRoot->playlist_start;	// SECTOR !!!
	playlist_qty 	= pRoot->playlist_qty;		
	fat_start 	= pRoot->fat_start;


	// VS1001 User Software Loader
	//
	u32 app_start = pRoot->wasteland_start;
	vs1001_fw = 0;
	u16 *pData;
	pData = (u16*) buffer1;
	while(ATA_Read(app_start,1,buffer1))			// read first free sector
		ATA_SW_Reset2();

	if(*pData++ != 0x4679 || *pData++ != 0x776D)		// Firmware signature ('yFmw') not found
		return;						// exit

	u16 DataLen = *pData++;					// length of firmware in words (firmware only)
	vs1001_fw = *pData++;					// address to enter into VS1001 register A1ADDR
								// for application running.
	vs1001_write(7,vs1001_fw + 0x4000);			// write to VS1001 register WRAMADDR
	while(DataLen--)					// data length in words
	{
		if (pData == (u16*)(buffer1+512))
		{
			app_start++;
			while(ATA_Read(app_start,1,buffer1)) 	// read next sector with application datas
				ATA_SW_Reset2();
			pData = (u16*) buffer1;			// new start address
		}
		vs1001_write(6,*pData++);			// write firmware word to vs1001
	}
}


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

u16 curPlaylist = 0;
u16 curIndex = 0;
u16 selected_Playlist;


#ifdef SATTELITE

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

YADL_PLAY_LIST_ENTRY *get_pl_entry(u16 index)
{
	static u32 nLastSector = -1;
	u32 nCurSector;
	
	//
	// find (and load) correct playlist sector
	//

	nCurSector =  playlist_start + (index >> 3);	// 64 bytes per one playlist entry
	if (nCurSector != nLastSector)
	{
		while(ATA_Read(nCurSector,1,(u08*)PL_CACHE))
			ATA_SW_Reset2();
		nLastSector = nCurSector;	
	}
	return &((YADL_PLAY_LIST_ENTRY *)PL_CACHE)[index % 8];
}

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

YADL_SONG_BASE_ENTRY *get_song_entry(u16 index)
{
	static u32 nLastSector = -1;
	u32 nCurSector;
	
	nCurSector = songbase_start + (index >> 2);
	if (nCurSector != nLastSector)
	{
		while(ATA_Read(nCurSector,1,(u08*)SE_CACHE))
			ATA_SW_Reset2();
		nLastSector = nCurSector;
	}
	return &((YADL_SONG_BASE_ENTRY *)SE_CACHE)[index % 4];
}

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

u16 get_offset_entry(u16 index, u16 Playlist)
{
	static u32 nLastSector = -1;
	YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(Playlist);
	FOFFSET offset = pListEntry->offset;

	// first compute desired start sector
	u32 nCurSector = playlist_start + (offset / SECTORSIZE) + (index * sizeof(u16) / SECTORSIZE);

	offset = offset % SECTORSIZE;		 // cut offset to rest inside one sector

⌨️ 快捷键说明

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