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

📄 yampp3.c

📁 fat文件系统的源码 老外写的FAT32文件系统 还是有用的
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
  Copyright (C) 2001 Jesper Hansen <jesperh@telia.com>.

  Rewritten by: Nikolai Vorontsov <nickviz@mail.be>

  Rewritten by:	Romuald Bialy (aka MIS) <romek_b@o2.pl>

  This file is part of the yampp system.

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation, 
  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

/*
	PIN assignements
	
	PA0-PA7		data bus 0..7 + Address 0..7
	PC0-PC7		address 8..15	
	
	PB0		T0	DIOW		ATA out
	PB1		T1	DIOR		ATA out
	PB2		AIN0	DREQ		VS1001 in		
	PB3		AIN1	BSYNC		VS1001 out
	PB4		SS	MP3		VS1001 out
	PB5		MOSI	SO		VS1001 out
	PB6		MISO 	SI		VS1001 in
	PB7		SCK	SCK		VS1001 out

	PD0		RxD	RS-232		UART in
	PD1		TxD	RS-232		UART out
	PD2		INT0	IR_INPUT	IR in
	PD3		INT1	KEY_INPUT	KEY in
	PD4		T0		
	PD5		T1	LCD_ENABLE	LCD out
	PD6		WR	WR		RAM out
	PD7		RD	RD		RAM out
*/


#include <stdlib.h>
#include <io.h>
#include <progmem.h>
#include <eeprom.h>
#include <sig-avr.h>
#include <interrupt.h>
#include <wdt.h>
#include <string.h>

#include "Constants.h"
#include "types.h"
#include "mem.h"
#include "delay.h"
#include "ata_if.h"
#include "fat.h"
#include "vs1001.h"
#include "remote.h"
#include "uart.h"
#include "lcd.h"


// Amount of small steps in LCD play position bar
#ifdef PROGRESBAR_II
 #if (LCD_LINES == 2)
  #define LCD_STEPS ((LCD_LINE_LENGTH - 7 - 2*(LCD_LINE_LENGTH != 16)) * 5)
 #else
  #define LCD_STEPS ((LCD_LINE_LENGTH - 6) * 5)
 #endif
#else //PROGRESBAR_II
 #if (LCD_LINES == 2)
  #define LCD_STEPS ((LCD_LINE_LENGTH - 6) * 5)
 #else
  #define LCD_STEPS ((LCD_LINE_LENGTH - 5) * 5)
 #endif
#endif //PROGRESBAR_II

// Amount of buffers writed before relinquish control
#define MAX_CONS_WRITES 100


#define	EV_IDLE		0
#define	EV_PLAY		1
#define	EV_STOP		2
#define	EV_NEXT		3
#define	EV_PREV		4
#define	EV_NEXT10	5
#define	EV_PREV10	6
#define	EV_VOLUP	7
#define	EV_VOLDN	8
#define	EV_NEXTD	9
#define	EV_PREVD	10
#define	EV_FFWD		11
#define	EV_FREW		12
#define	EV_LOUDNESS	13
#define	EV_RANDOM	14
#define	EV_REMAIN	15
#define	EV_NEXTL	16
#define	EV_PREVL	17
#define	EV_NUMBER	18
#define	EV_PAUSE	19

// Auxilliary functions declarations
void sectordump(u32 sector);
u08* unsigned2str(u16 track, u08 *str);
u08 get_char_event(void);
u08 ir_event(void);
u08 get_key_event(void);
void setvolume(u08 v);
void dispbar(void);
u16 Numb2Int(void);
void BadHeadStrip(void);
u08 get_char_event(void);
void send_sinewave_beeps(void);

#ifdef PROGRESBAR_II
 void lcd_frame(void);
#else
 #define lcd_frame()
#endif


// Global variables
u08 scroll_length;
u08 scroll_pos;
char *scroll_line;
u08 LastEvent		= EV_IDLE;

#if (LCD_LINES == 4) && (defined DIR_SCROLL)
 u08 dir_scroll_length;
 u08 dir_scroll_pos;
 char *dir_scroll_line;
#endif

bool bPlaying;				// Current state - play/stop
u08 *pPlayData;				// Pointer to current position in currently used buffer
u08 *pUpdBuf;				// Pointer to buffer need updating

u32 dwPlayed;				// Amount of already played blocks (32 bytes)
u16 wBackStepPos;			// Actual position in backstep tabele
u16 wSongNum;				// Current playing song
u16 wMaxSongs = 1;			// Maximum available songs

#define TI1_H	(((u16)-(F_CPU / 2560)) >> 8)
#define TI1_L	(((u16)-(F_CPU / 2560)) & 0xff )

volatile u08 nDispUpd = 0;			// Counter for display update loop
volatile u08 nKeyTime = 0;			// Counter for keypress time check - Added by MIS

#ifdef OLD_VS1001
 volatile u16 wPlayT = 0;			// Play Time counter for older VS1001 chips
#endif

SIGNAL(SIG_OVERFLOW1)				// Timer1 overflow every 100 mS
{
	nDispUpd++;
	nKeyTime++;
#ifdef OLD_VS1001
	wPlayT++;
#endif
	outp(TI1_H, TCNT1H);			// Reload timer
	outp(TI1_L, TCNT1L);
}

#ifndef SETUP_REMOTE_CODES

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

static u32 seed = 1;
static u16 wFirstInDir = 0;

// Init randomize table
void InitRnd(void)
{
u16 Temp;
	for (Temp = 0; Temp < (wMaxSongs >> 3); Temp++)
		RANDOM_TAB[Temp] = 0;					// one bit in table represent one song
	RANDOM_TAB[Temp] = (0xff << (wMaxSongs % 8));			// last byte.
}

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)");
#ifdef YAMPP3USB
	asm volatile ("call __mulsi3");
#else
	asm volatile ("rcall __mulsi3");
#endif
	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");
#ifdef YAMPP3USB
	asm volatile ("call __udivmodsi4");
#else
	asm volatile ("rcall __udivmodsi4");
#endif
	asm volatile ("mov r25,r23");
	asm volatile ("mov r24,r22");
	return max;
}

u08 tabval(u16 num, u08 fn)					// check random tabele for song status
{									// and mark as played if necessary
	u16 index = (num + wFirstInDir) >> 3;
	u08 offset = 1 << ((num  + wFirstInDir) % 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;
	for(num = 0; num < max; num++)
		if(tabval(num,0) == 0)
			break;
	if (num == max)
	{
		InitRnd();
		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;
}

// This function return number of songs in current direcrory and sets first song number variable
u16 checkdir(void)
{
	register u16 Temp;
	for (Temp = 0; Temp < nLastPosD; Temp++)				// search dir tabele
	{
		if (DirsTable[Temp].song_num <= wSongNum)
			wFirstInDir = DirsTable[Temp].song_num;			// update first song number in current dir
		else
			break;							// found end of current dir
	}
	if (Temp == nLastPosD)							// if this is last dir on CD
		return (wMaxSongs - wFirstInDir);
	return (DirsTable[Temp].song_num - wFirstInDir);
}

#if (LCD_LINES == 4)
void printsp(void)
{
	register u08 i = (LCD_LINE_LENGTH - 11);
	while(i--) lcd_putchar(' ');
}
#endif

void load_buffers(void)
{
	ReadBuffer(BUFFER1P);			// Load buffer1
	ReadBuffer(BUFFER2P);			// Load buffer2
	pUpdBuf = 0;				// Mark as just loaded
	pPlayData = BUFFER1P;			// Start playing from buffer1
#ifdef OLD_VS1001
	BadHeadStrip();
#endif				
}



u08 *randstr  = "Rand*";
u08 *loudstr  = "Loud*";
u08 randmod[] = "-+*";
u08 trackstr[6], *pTrack, timestr[6], tot_sw = 0;

#ifdef ENABLE_NUMERIC
u08 number[6], *pNum = number;
#endif

#endif // #ifndef SETUP_REMOTE_CODES
//----------------------------------------------------------------------------
// Main part
//----------------------------------------------------------------------------
int main(void)
{
#ifndef SETUP_REMOTE_CODES
	bool bRandom, bLoudness;				// Modificators
	bool bFfwdMute = false;					// Search mute flag
	u08 nVolume = 0;					// Current volume level
	u16 wPlayTime;						// Current play time
#ifdef REMAIN_TIME
	u16 wSongTime = 0;					// Song time for remain calculation
	u08 bTimeMode = 0;					// Remain time modificator
#endif
	u16 wAddTime = 0;					// Fix play time for search
	u08 nWrites, i;						// Buffering variables
	u08 event = EV_STOP;					// Current event
	u08 *src, *dst; 					// Temporary variables
	u16 nTemp;
	udiv_t divt;
#endif // #ifndef SETUP_REMOTE_CODES
//----------------------------------------------------------------------------
// B - Port
//----------------------------------------------------------------------------
	outp(0x57, PORTB);
	outp(0xBB, DDRB);

//----------------------------------------------------------------------------
// D - Port
//----------------------------------------------------------------------------
	outp (0xDC ,PORTD);
#ifdef ENABLE_RST_OUT
	outp (0xF0 ,DDRD);
#else
	outp (0xE0 ,DDRD);
#endif

#ifdef YAMPP3USB
#define SRW	SRW10
	cbi(DDRD, PD5);		// PD5 is input in yampp-3/USB

//----------------------------------------------------------------------------
// E - Port
//----------------------------------------------------------------------------
	cbi(DDRE, PE0);		// PE0 is IR input
	sbi(PORTE, PE0);	// activate pullup
	sbi(DDRE, PE1);		// set ALE pin as output
	cbi(PORTE, PE1);	// and set it low (inactive)
	sbi(DDRE, PE2);		// PE2 is LCD_ENABLE
	cbi(PORTE, PE2);	// and set it low (inactive)
#endif

//----------------------------------------------------------------------------
// Timer 1
//----------------------------------------------------------------------------
	// setup timer1 for a 100mS periodic interrupt
	outp(0, TCCR1A);
	outp(4, TCCR1B);			// Prescaler /256  tPeriod = 32 uS
	outp(TI1_H, TCNT1H);			// Load counter value hi
	outp(TI1_L, TCNT1L);			// Load counter value lo

//----------------------------------------------------------------------------
// Initialization
//----------------------------------------------------------------------------

	outp((1<<SRE)|(1<<SRW), MCUCR);		// enable external SRAM and wait states 

	delay10(1000);
   	lcd_init(0, LCD_FUNCTION_DEFAULT);

	outp((1<<MSTR) | (1<<SPE), SPCR);	// SPI 2 MHz clock
	inp(SPSR);				// clear SPI status
#if (LCD_LINE_LENGTH == 16)
	lcd_puts_p(PSTR(" Hi, MP3 world!\n yampp-3 player"));
#endif
#if (LCD_LINE_LENGTH == 20)
	lcd_puts_p(PSTR("   Hi, MP3 world!\nyampp-3 player Alive"));
#endif
#if (LCD_LINE_LENGTH == 24)
	lcd_puts_p(PSTR("     Hi, MP3 world!\n yampp-3 player Alive !"));
#endif

	UART_Init();				// Init RS-232 link

#ifdef ENABLE_RST_OUT
	cbi(PORTD,PD4);				// activate reset signal to VS1001 and CD-ROM
	delay10(1000);
	sbi(PORTD,PD4);				// deactivate reset signal to VS1001 and CD-ROM
#endif
	// Say hello to UART
 	PRINT_p(PSTR("\n\nyampp-3 "__DATE__" "__TIME__"\nATA checking..."));

#ifdef ENABLE_WATCHDOG
	wdt_enable(0x07);
#endif

	delay10(10000);
	vs1001_setcomp(F_VS1001);		// set frequency of vs1001 clock
	vs1001_reset(false);			// Init VS1001

#ifdef SETUP_REMOTE_CODES
	setvolume(6);
	send_sinewave_beeps();			// Send three sinewave beeps to indicate
	remote_setup();				// Enter remote setup procedure
	while(1) WDR;

#else // SETUP_REMOTE_CODES	-	for get full code space

	ATA_Init();				// Init and wait for drive
	ATA_SW_Reset();				// Reset drive
	PRINT_p(PSTR("done.\n"));

	if ((nTemp = init_fat()))				// Read disk structure
	{
		lcd_clrscr();
		lcd_puts_p(PSTR("Wrong cluster\nsize "));	// Error info, recompile code
		lcd_puts(unsigned2str((nTemp>>1), trackstr));	// Show cluster size for this disk
		lcd_putchar('k');
		while (true) WDR;				// Lock player
	}

	PRINT_p(PSTR("Scanning..."));
//	wMaxSongs = dirlist(DIRLIST_VERBOSE);
	wMaxSongs = dirlist(DIRLIST_SCAN);

	PRINT(unsigned2str(wMaxSongs , trackstr));		// jman number of songs in decimal
	PRINT_p(PSTR(" entries\n"));

	seed = 1 + inp(TCNT1L);					// Init randomizer from timer 
								// (ATA init gives us random delay)
	InitRnd();						// Init randomizer tabele

	if ((nVolume = eeprom_rb(EEPROM_VOLUME)) > MIN_VOLUME)	// Load and set initial volume
		nVolume = MIN_VOLUME / 2;			// set volume to 1/2 scale after eeprom erase

	setvolume(nVolume);

#ifdef PWR_BEEPS
	send_sinewave_beeps();					// Send three sinewave beeps to indicate
#endif								// we're starting up okay

	// load bAutoPlay and position settings
	bRandom		= eeprom_rb(EEPROM_RANDOM) % 3;		//  Load random setting
	wSongNum	= eeprom_rw(EEPROM_SONGPOS);		//  Load position setting
	bLoudness	= eeprom_rb(EEPROM_LOUDNESS);	

	// set initial status in the strings
	*(loudstr+4) = bLoudness ? '+' : '-';
	*(randstr+4) = randmod[bRandom];
	if (eeprom_rb(EEPROM_AUTOPLAY))				// Load autoplay status
		event = EV_PLAY;

//----------------------------------------------------------------------------
// start things rolling
//----------------------------------------------------------------------------
	sbi(TIMSK, TOIE1);	 			// Enable timer1 interrupt
	while (true)					// Main loop
	{
		WDR;					// Give watchdog full time
		if (UART_HasChar())			// Check all input controls
			event = get_char_event();

		if (rec80_active())
			event = ir_event();
		else
			if (nKeyTime > 16)
				LastEvent = EV_IDLE;

		if (event == EV_IDLE)
			event = get_key_event();
			
		if (bPlaying && event == EV_PLAY)	// second play press does pause
			event = EV_PAUSE;

		switch (event)				// According input control
		{
			case EV_IDLE:
				break;

			case EV_PREVD:			// Switch to previous start dir
				checkdir();
				wSongNum = ((wFirstInDir) ? wFirstInDir : wMaxSongs) -1;
				checkdir();
				wSongNum = wFirstInDir;
				goto PLAY;

⌨️ 快捷键说明

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