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

📄 control.c

📁 老外个人做的MP3/优盘。使用ATMEL MEGA系列的MCU
💻 C
📖 第 1 页 / 共 2 页
字号:

	ramenable();							// enable ExtRAM
	return (event);
}

#ifdef ROTTARY_CONTROL

/****************************************************************************************
*			ROTARY SWITCH CONTROL FUNCTION					*
****************************************************************************************/
// Rotary switch connected to PD0 and PD1 after disconnecting MAX202 chip from PD0 line.
// This configuration uses UART Receive interrupt for rotary switch control. After
// UART detecting hi to low edge at RXD pin, start receiving data. After 200us from first
// edge (at 9600 baud UART speed) UART generate UART_RECEIV interrupt, but with framming
// error because not valid stop bit is received. UDR have received data. This data is
// used for magic debounce, and reading of UDR clearing interrupt flag. Next time, the
// uart interrupt is disabled because may generate several interrupts within continued
// low state at RXD pin. If main loop detect HI state at RXD, enable interrupt agin.


#define ROTARY_UP	EV_UP
#define ROTARY_DOWN	EV_DOWN
#define ROT_PORT	PORTD
#define ROT_PIN1	PD0
#define ROT_PIN2	PD1

u08 rotary_direction;

SIGNAL(SIG_UART0_RECV)					// rotary switch interrupt from uart :-) 
{
	if((inp(UDR0) & 0xf0) == 0)			// magic debounce and interrupt flag clearing
	{
		if (bit_is_set(ROT_PORT-2, ROT_PIN2))	// check second rotary pin (direction)
			rotary_direction = ROTARY_UP;
		else
			rotary_direction = ROTARY_DOWN;

		outp(0, UCSR0B);			// disable receiver interrupt
	}
}


void rotary_init(void)
{
		sbi(ROT_PORT, ROT_PIN1);
		sbi(ROT_PORT, ROT_PIN2);		// enable pullups
		cbi(ROT_PORT-1, ROT_PIN1);
		cbi(ROT_PORT-1, ROT_PIN2);		// rotary pins as inputs
		outp(0, UBRRH);
		outp(7 ,UBRR0);				// for 57600 baud speed - about 200us byte time
		outp(_BV(RXCIE) | _BV(RXEN) ,UCSR0B);	// enable receiver and receiver interrupt
}

u08 get_rotary_event()
{
	u08 event = EV_IDLE;

	if(bit_is_set(ROT_PORT-2, ROT_PIN1))
		outp(_BV(RXCIE) | _BV(RXEN) ,UCSR0B);	// re enable receiver and receiver interrupt

	if(rotary_direction)
	{
		event = rotary_direction;
		rotary_direction = 0;
		nKeyTime = 0;
	}
	return(event);
}
#endif // ROTTARY_CONTROL


#else // SATTELITE ON
/****************************************************************************************
*			SATTELITE COMMUNICATION FUNSTIONS				*
****************************************************************************************/

u08 linkholder;
u08 player_state = 0;
static u08 uart_chars1[]= SAT_CONTROL1;				// Tokens table for Sattelite control1
static u08 uart_chars2[]= SAT_CONTROL2;				// Tokens table for Sattelite control2

void Send_state(u08 state)
{
	uart_pc1(SAT_CMD_MARKER);
	uart_pc1(SAT_STATE);
	if(state != 0xff)
	{
		if((state & 0x0F))
		{
			player_state &= 0xF0;
			player_state |= (state & 0x0F);
		}
		if((state & 0xF0))
		{
			player_state &= 0x0F;
			if(state != STATE_RETURN)
				player_state |= (state & 0xF0);
		}
	}
	uart_pc1(player_state);
}

u08 Sattelite_init()
{
	u08 i = 0;
#ifdef LCD_NEGATIV
	i++;
#endif
#ifdef ALT_BAR_STYLE
	i+=2;
#endif
	uart_pc1(SAT_CMD_MARKER);
	uart_pc1(SAT_LCDTYPE);
	uart_pc1(LCD_TYPE);
	uart_pc1(LCD_LINE_LENGTH);
	uart_pc1(LCD_LINES);
	uart_pc1(GRAPHICS_LCD_CONTRAST);
	uart_pc1(i);
	uart_pc1(tolower(uart_chars1[EV_UP-1]));
	uart_pc1(tolower(uart_chars1[EV_DOWN-1]));
	uart_pc1(tolower(uart_chars1[EV_FFWD-1]));
	uart_pc1(tolower(uart_chars1[EV_FREW-1]));

	for(i=0; i<5; i++)
	{
		delayms(10);
		if(uart_haschar())
		{
			if(uart_getchar() == '+')
				return 0;
		}
	}
	return 1;
}

void Vlcd_clrscr(void)				// send clrscr command to Sattelite
{
	uart_pc1(SAT_CMD_MARKER);
	uart_pc1(SAT_CLRSCR);
	delayms(5);
}

void lcd_clrline(u08 line)
{
	uart_pc1(SAT_CMD_MARKER);
	uart_pc1(SAT_CLRLINE);
	uart_pc1(line);
}

void Vlcd_gotoxy(u08 x, u08 y)
{
	uart_pc1(SAT_CMD_MARKER);
	uart_pc1(SAT_GOTOXY);
	uart_pc1(x);
	uart_pc1(y);
}

void Vlcd_puts(char s[])			// print RAM string on Sattelite
{
	u08 linelen=LCD_LINE_LENGTH;
	while(*s && linelen--)
		uart_putchar(*s++);
}

void Vlcd_progputs(char s[])			// print ROM string on Sattelite
{
	u08 b, *p=s;
	while (p && (b = PRG_RDB(p++)))
		uart_putchar(b);
}

void Vlcd_bar(u08 val, u08 len)
{
	uart_pc1(SAT_CMD_MARKER);
	uart_pc1(SAT_BAR);
	uart_pc1(val);
	uart_pc1(len);
}

u08 Vlcd_logo(void)				// display startup logo on Sattelite LCD
{
	u08 i;
	uart_pc1(SAT_CMD_MARKER);
	uart_pc1(SAT_LOGO);
	for(i=0; i<5; i++)
	{
		delayms(10);
		if(uart_haschar())
			return(uart_getchar());
	}
	return 1;
}

void Vlcd_invert(void)				// start invert mode
{
	uart_pc1(SAT_CMD_MARKER);
	uart_pc1(SAT_INVERS);
}

void Vlcd_normal(void)				// end invert mode
{
	uart_pc1(SAT_CMD_MARKER);
	uart_pc1(SAT_NORMAL);
}

void Vlcd_wrdata(u08 data)
{
	uart_pc1(SAT_CMD_MARKER);
	uart_pc1(SAT_RAWDAT);
	uart_pc1(data);
}

u08 ir_active;
u16 ir_code;

u16 get_rec80(u08 std)
{
	static u08 old_std = 128;
	if(old_std != std)
	{
		uart_pc1(SAT_CMD_MARKER);
		uart_pc1(SAT_IRSTAND);
		uart_pc1(std);
		old_std = std;
		ir_code = 0;
	}

	ir_active = 0;
	return(ir_code);
}

u08 rec80_active(void)
{
	return(ir_active);
}

#endif // #ifdef SATTELITE

/****************************************************************************************
*			MAIN PLAYER CONTROL FUNSTIONS					*
****************************************************************************************/

extern u08 ir_standard;

#ifdef NUMERICAL_KEYS
 u08 number_key;
#endif

void control_handler(void)
{
	event_e event = EV_IDLE;
	u08 i;

#ifdef ENABLE_UART
	u08 c;

	static u08 uart_chars[]= UART_CHARS;				// Tokens table for UART control
	if (uart_haschar())						// Check UART event
	{		
		c = uart_getchar();					// get char

		for(i=0; i < sizeof(uart_chars); i++)
		{
			if(c == uart_chars[i])				// check tokens tabele
			{
				event = i+1;				// found
				break;
			}
		}
	}
#endif

#ifdef SATTELITE
	u08 c;
	extern void lcd_frame(void);
	extern u08 isPlaying;

	if (uart_haschar())						// Check UART event
	{		
		c = uart_getchar();					// get char

		if(c == '-')						// sattelite reinit request
		{
			Sattelite_init();
			Send_state(0xff);				// send last state
			if(isPlaying)
				lcd_frame();
			else
				event = EV_STOP;
		}

		else if(c == '$')					// sattelite STOP request
			event = EV_STOP;

		else if(c == 'Z')					// sattelite remote code present
		{
			ir_code = uart_getchar() * 256;			// function code H
			ir_code += uart_getchar();			// function code L
			ir_active = 1;
		}
		else if(c == 'z')					// sattelite remote code present
		{
			ir_code = 0;
			ir_active = 2;
		}

		else for(i=0; i < sizeof(uart_chars1); i++)		// sattelite standard events processing
		{
			if(c == uart_chars1[i] || c == uart_chars2[i])	// check tokens tabeles
			{
				event = i+1;				// found
				nKeyTime = 0;
				break;
			}
		}

	}
	extern u08 scroll_time;

	if(scroll_time % 10 == 0)
		linkholder = 0;

	if(scroll_time % 10 == 9 && !linkholder)			// send link-up holder command
	{
		uart_pc1(SAT_CMD_MARKER);
		uart_pc1(SAT_LINKHOLDER);
		linkholder = 1;
	}

#endif

	static event_e OldEvent = EV_IDLE;
	static u16 Lcod;

	if ((ir_standard != 255) && rec80_active())			// Check IR event
	{
		u16 code = get_rec80(ir_standard);
		if (!(Lcod == code && nKeyTime <= DOUBLE_TRAP))		// Trap for some IR transmitters that fast repeat
		{
#ifdef NUMERICAL_KEYS
			for (i = 0; i < (2 * (EV_LASTEVENT+10)); i+=2)
#else
			for (i = 0; i < (2 * EV_LASTEVENT); i+=2)	// search with all memorized codes
#endif
				if (eeprom_rw(EEPROM_RemCodes + i) == code) // if valid keycode found
				{
					OldEvent = i/2 + 1;		// Save event number
#ifdef ENABLE_AUTOREPEAT
RET_LAST:
#endif
					nKeyTime = 0;
					Lcod = code;			// For trap function
#ifdef NUMERICAL_KEYS
					if (OldEvent > EV_LASTEVENT)	// if numerical key pressed
					{
						number_key = OldEvent - EV_LASTEVENT - 1; // save number (0-9)
						OldEvent = EV_NUMBER;	// set event as EV_NUMBER,
					}				// number is stored in number_key variable
#endif
					event = OldEvent;
					break;
				}
#ifdef ENABLE_AUTOREPEAT
			if ((nKeyTime >= 2) && (OldEvent == EV_UP || OldEvent == EV_DOWN || 
						OldEvent == EV_FFWD  || OldEvent == EV_FREW))
				goto RET_LAST;				// Autorepeat feature on some keys
#endif
		}
	}
	else
	{
		if (nKeyTime > 10)
			OldEvent = EV_IDLE;
	}

#ifndef SATTELITE
	if (event == EV_IDLE)
		event = get_key_event();				// Check keyboard

 #ifdef ROTTARY_CONTROL							// local rotary switch
	if (event == EV_IDLE)
		event = get_rotary_event();				// Check Rotary Switch
 #endif
#endif // ifndef SATTELITE

	if (event != EV_IDLE)
		set_event(event);					// Add event to queue
}

/****************************************************************************************
*			SETUP REMOTE CODES FUNSTIONS					*
****************************************************************************************/


static u16 ee_adr;
extern u08 time_flag;

void get_rem_code(u08* name, u08 stand)
{
	u16 code;
	event_e event;
	do
	{
		code = eeprom_rw(ee_adr);				// Get old Key Code
		goto PRINT_CODE;

		while((event = get_event()) == EV_IDLE)
		{
			time_flag = 0;
			if (rec80_active())				// if IR active
			{
				if ((code = get_rec80(stand)))		// Get Code and validation
				{
PRINT_CODE:				lcd_clrline(1);
					uart_EOL();
					both_progputs(name);		// Print Event Name
					lprintf(": %04x",code);		// Print Key Code
#ifdef ENABLE_UART		
					uprintf(": %04x",code);
#endif
					eeprom_ww(ee_adr, code);	// Store Key Code to EEPROM
				}
			}
		}
		if (event == EV_STOP)					// If Clear
		{
			eeprom_ww(ee_adr, 0xffff);			// Clear Key Code
			break;
		}
	} while(event != EV_PLAY);
	ee_adr += 2;							// Next code address
	delayms(100);
	return;
}

#ifdef AUTODETECT_STANDARD
 static u08 ir0[]  __attribute__ ((progmem)) = "REC80 ";
 static u08 ir1[]  __attribute__ ((progmem)) = "NEC80 ";
 static u08 ir2[]  __attribute__ ((progmem)) = "SONY15";
 static u08 ir3[]  __attribute__ ((progmem)) = "SONY12";
 static u08 ir4[]  __attribute__ ((progmem)) = "RC-5  ";
 u08 *standard_name[] = { (u08*)&ir0, (u08*)&ir1, (u08*)&ir2, (u08*)&ir3, (u08*)&ir4 };
#endif

void setup_rem(void)
{
	u08 stand = 0;
	u08 i=4;
	ir_standard = 255;
	ee_adr = EEPROM_RemCodes;

	Send_state(STATE_IR_LEARN);

#ifdef AUTODETECT_STANDARD
	Vlcd_clrscr();
	uart_EOL();
	both_progputs(PSTR("Remote setup:\n"));
	both_progputs(PSTR("Standard 0 ?"));
	while(1)					// Recognize IR standard
	{
		time_flag = 0;
		if (rec80_active())
		{
			Vlcd_gotoxy(9,1);
			if (get_rec80(stand))		// If != 0  - found standard
			{
					uart_EOL();
					both_progputs(standard_name[stand]);
					delayms(3000);
					break;
			}
			else
			{
				if(--i == 0)
				{
					stand = (stand+1) % STANDARDS_COUNT;
					i=4;
					both_putchar(stand+'0');
				}
			}
		}
		if(get_event() == EV_STOP)
		{
			set_event(EV_STOP);
			return;
		}
	}
#endif
	Vlcd_clrscr();
	uart_EOL();
	both_progputs(PSTR("PLAY-Ok,STOP-Clear"));

	for(i=0; i < EV_LASTEVENT-4; i++)
		get_rem_code(function_name[i],stand);		// Learn Remote Events codes

	while(ee_adr++ < EV_LASTEVENT * 2 + EEPROM_RemCodes)	// fill rest function with 0xffff
			eeprom_wb(ee_adr, 0xff);

#ifdef NUMERICAL_KEYS
	static u08 num[]  __attribute__ ((progmem)) = {'0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0};
	ee_adr--;
	for(i=0; i<10; i++)
		get_rem_code((u08*)&num[2*i],stand);		// Learn Numerical keys codes
#endif

#ifdef AUTODETECT_STANDARD
	ir_standard = stand;
	eeprom_wb(EEPROM_IRSTAND,ir_standard);			// Store IR Standard into EEPROM
#endif
	both_progputs(PSTR("\rDone !"));
	Send_state(STATE_IR_ENDL);
}

⌨️ 快捷键说明

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