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

📄 control.c

📁 老外个人做的MP3/优盘。使用ATMEL MEGA系列的MCU
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ***********************************************************************
**
**  Copyright (C) 2002 	Romuald Bialy (MIS) <romek_b@o2.pl>.
**
**
**  Yampp-3/USB - Input control routines
**
**  File control.c
**
*************************************************************************
**
**   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.
**
*************************************************************************
**
**  Revision History
**
**  when         what  who      why
**
**  2002-09-01   1.0   MIS      initial public release
**  2002-09-25	 1.01  Jesper	solved problems with some IR standard detection
**  2002-10-24	 1.02  MIS	added checking for AUTOREPEAT definition.
**  2003-04-05	 1.10  MIS	added next function
				bugfix in IR codes setup procedures
**  2003-06-08	 1.11  MIS	added compatibility for some non standard RC-5 remotes.
**  2003-07-08	 1.30  MIS	added Sattelite support and Rotary Switch support.
**
*********************************************************************** */

#define _SFR_ASM_COMPAT 1
#include "yampp3_usb.h"


static u08 fn0[]  __attribute__ ((progmem)) = "PLAY";
static u08 fn1[]  __attribute__ ((progmem)) = "STOP";
static u08 fn2[]  __attribute__ ((progmem)) = "NEXT";
static u08 fn3[]  __attribute__ ((progmem)) = "PREV";
static u08 fn4[]  __attribute__ ((progmem)) = "NEXT PL";
static u08 fn5[]  __attribute__ ((progmem)) = "PREV PL";
static u08 fn6[]  __attribute__ ((progmem)) = "F.FWD";
static u08 fn7[]  __attribute__ ((progmem)) = "F.REW";
static u08 fn8[]  __attribute__ ((progmem)) = "BALANCE";
static u08 fn9[]  __attribute__ ((progmem)) = "LOUDNESS";
static u08 fn10[] __attribute__ ((progmem)) = "RANDOM";
static u08 fn11[] __attribute__ ((progmem)) = "REPEAT";
static u08 fn12[] __attribute__ ((progmem)) = "TIME";
static u08 fn13[] __attribute__ ((progmem)) = "INFO";
static u08 fn14[] __attribute__ ((progmem)) = "UP";
static u08 fn15[] __attribute__ ((progmem)) = "DOWN";
static u08 fn16[] __attribute__ ((progmem)) = "PLAYLIST";
static u08 fn17[] __attribute__ ((progmem)) = "MENU";
static u08 fn18[] __attribute__ ((progmem)) = "EQ ON/OF";

u08 *function_name[] = {(u08*)&fn0,(u08*)&fn1,(u08*)&fn2,(u08*)&fn3,(u08*)&fn4,(u08*)&fn5,(u08*)&fn6,
			(u08*)&fn7,(u08*)&fn8,(u08*)&fn9,(u08*)&fn10,(u08*)&fn11,(u08*)&fn12,
			(u08*)&fn13,(u08*)&fn14,(u08*)&fn15,(u08*)&fn16,(u08*)&fn17,(u08*)&fn18 };

#ifndef SATTELITE

#define IR_PORT		PORTE
#define IR_BIT		PE0
#define KBD_PIN		PIND
#define KBD_BIT		PD3

/*************************************************************************************
*			INFRARED REMOTE RECEPTION FUNCTIONS			     *
**************************************************************************************/

u08 rec80_active(void)
{
	register u08 i = F_CPU*40/7372800;

	while (i--)
		if (bit_is_clear(IR_PORT-2, IR_BIT))
		{
			delay10();
			if (bit_is_clear(IR_PORT-2, IR_BIT))
				return 1;
			else
				return 0;
		}
	return 0;
}

//-------------------------------------------------------------------------------------
/*
  if STD = 0
	The REC-80 format used by Panasonic is a space coded 48 bit code consisting 
	of a 32 bit group id, followed by a 16 bit commmand word.
	Leading this is a header consisting of a 10T signal and a 4T pause.
	All bits start with a pulse of length T. The length of the pause following
	indicates the bit value. A T pause for a 0-bit and a 3T pause for a 1-bit.

  if STD = 1
	The NEC format is a space coded 32 bit code consisting 
	of a 16 bit group id, followed by a 16 bit commmand word.
	Leading this is a header consisting of a 16T signal and a 8T pause.
	All bits start with a pulse of length T. The length of the pause following
	indicates the bit value. A T pause for a 0-bit and a 3T pause for a 1-bit.
	Modified REC80 format by Will Jenkins, wdj@cus.org.uk

  if STD = 2 or 3
	The SONY format is a pulse coded 15 or 12 bit code consisting 
	of a 6 bit device code, followed by a 6 or 9 bit commmand word.
	Leading this is a header consisting of a 4T signal pulse.
	All bits are composed of a pulse of either 1T or 2T in length followed by a
	1T pause. A 2T pulse indicates a 1 bit, and a 1T pulse is a 0 bit.

 if STD = 4
	The RC-5 format used by Philips is bi-phase coded 13 bit code consisting 
	of a 7 bit device code, followed by 6 bit commmand word. Highest two bits of
	device code is startbit and troggle bit. Troggle bit must be masked out 
	because	its change after any keypress.

*/

#ifdef AUTODETECT_STANDARD

u16 get_rec80(u08 std)
{
		u08 i, T2, T4, time, tmp = 0;
		union u16convert code;

		code.value = 0;
		timer0_source(CK256);				//update every 32us
		timer0_start();
		loop_until_bit_is_set(IR_PORT-2, IR_BIT);	// skip leading signal


	if(std < 2)
	{	
		timer0_start();

		while (bit_is_set(IR_PORT-2, IR_BIT))
		{
			T2 = inp(TCNT0);
			if (T2 >= F_CPU*140/7372800)		// max wait time
				return 0;
		}
	
		// measure time T

		timer0_start();
		loop_until_bit_is_set(IR_PORT-2, IR_BIT);
	
		T2 = inp(TCNT0);				// T is normally around 0E-10 hex = 15 -> 480 uS
		T2 = T2 * 2;
		// max time is 4T
		T4 = T2 * 2;
		
		for (i = 0; i < ((std == 0) ? 48 : 32); i++)
		{
			timer0_start();
			while(1)
			{
				time = inp(TCNT0);
				if (time > T4)
					return 0;
			
				// measure time on the lo flank
				if (bit_is_clear(IR_PORT-2, IR_BIT))
				{
					tmp <<= 1;
					if (time >= T2)
						tmp++;
					break;
				}
			}


			// save command data as we go
			if (std == 0)
			{
				if( i == 39)
					code.bytes.low = tmp;
				if( i == 47)
					code.bytes.high = tmp;
			}
			else
			{
				if( i == 15)
					code.bytes.high = tmp;
				if( i == 31)
					code.bytes.low = tmp;
			}

			// syncronize - wait for next hi flank
			loop_until_bit_is_set(IR_PORT - 2, IR_BIT);
		}
		return (code.value);
	}
	else if(std < 4)					// Format used by SONY remote controllers
	{
		if (inp(TCNT0) <= F_CPU*60/7372800) 
			return 0;				// is it the leading Signal ?			

		// now looking for the Data-bits
		for(i=0; i < ((std == 3) ? 11 : 14); i++)
		{
			tmp = 0x01;
			while (bit_is_set(IR_PORT-2, IR_BIT))
			{
				T2 = inp(TCNT0);
				if (T2 >= F_CPU*140/7372800)	// max wait time
					return 0;
			}
			timer0_start();
			while (bit_is_clear(IR_PORT-2, IR_BIT))
			{
				T2 = inp(TCNT0);
				if (T2 >= F_CPU*140/7372800)	// max wait time
					return 0;
			}
			if (inp(TCNT0) >= F_CPU*25/7372800)	// pulse longer than 1 ms? then logic "1"
				code.value += ((u16)tmp << i);	// the device code 
		}
		return (code.value);
	}

	else	// std=4 -> RC-5;

	{
		for(i=0; i<13; i++)
		{
			if(bit_is_clear(IR_PORT-2, IR_BIT) )
				T2 = 0;
			else
				T2 = 1;

			timer0_start();
			while(1)
			{
				time=inp(TCNT0);
				if(time > F_CPU*0x42/7372800)
					return 0;

				if(bit_is_clear(IR_PORT-2, IR_BIT) && (T2==1) )
				{
					tmp <<= 1;
					tmp++;
					break;
				}
				else if(bit_is_set(IR_PORT-2, IR_BIT) && (T2==0) )
				{
					tmp <<= 1;
					break;
				}
			}

			//save address data
			if(i == 6)
			{
				code.bytes.high = (tmp & 0x5f);		// save address and cut troggle bit
				if ((tmp & 0x10)) i++;			// for some non standard remotes
				tmp=0;
			}

			//delay
			timer0_start();
			while(1)
			{
				time=inp(TCNT0);
				if(time > F_CPU*0x21/7372800)
					break;
			}
		}
		code.bytes.low = tmp;
		return(code.value);
	}
}

//-------------------------------------------------------------------------------------
#else // PREDEFINED FUNCTIONS
//-------------------------------------------------------------------------------------

#if (REMOTE_STANDARD < 2)				// REC80, NEC80
u16 get_rec80(u08 std)
{
	u08 i, T2, T4, time, tmp = 0;
	union u16convert code;
	timer0_source(CK256);				//update every 32us
	timer0_start();
	loop_until_bit_is_set(IR_PORT-2, IR_BIT);	// skip leading signal
	timer0_start();

	while (bit_is_set(IR_PORT-2, IR_BIT))
	{
		T2 = inp(TCNT0);
		if (T2 >= F_CPU*140/7372800)		// max wait time
			return 0;
	}

	// measure time T

	timer0_start();
	loop_until_bit_is_set(IR_PORT-2, IR_BIT);
	
	T2 = inp(TCNT0);				// T is normally around 0E-10 hex = 15 -> 480 uS
	T2 = T2 * 2;
	// max time is 4T
	T4 = T2 * 2;
		
	for (i = 0; i < ((REMOTE_STANDARD == 0) ? 48 : 32); i++)
	{
		timer0_start();
		while(1)
		{
			time = inp(TCNT0);
			if (time > T4)
				return 0;
			
			// measure time on the lo flank
			if (bit_is_clear(IR_PORT-2, IR_BIT))
			{
				tmp <<= 1;
				if (time >= T2)
					tmp++;
				break;
			}
		}

		// save command data as we go
#if (REMOTE_STANDARD == 0)
		if( i == 39)
			code.bytes.low = tmp;
		if( i == 47)
			code.bytes.high = tmp;
#else
		if( i == 15)
			code.bytes.high = tmp;
		if( i == 31)
			code.bytes.low = tmp;
#endif
		// syncronize - wait for next hi flank
		loop_until_bit_is_set(IR_PORT - 2, IR_BIT);
	}
	return (code.value);
}
#endif

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

#if (REMOTE_STANDARD > 1 && REMOTE_STANDARD < 4)	// SONY
u16 get_rec80(u08 std)
{
	u08 i, T2, tmp = 1;
	union u16convert code;
	code.value = 0;
	timer0_source(CK256);				//update every 32us
	timer0_start();
	loop_until_bit_is_set(IR_PORT-2, IR_BIT);	// skip leading signal

	if (inp(TCNT0) <= F_CPU*60/7372800) 
		return 0;				// is it the leading Signal ?			

	// now looking for the Data-bits
	for(i=0; i < ((REMOTE_STANDARD == 3) ? 11 : 14); i++)
	{
		while (bit_is_set(IR_PORT-2, IR_BIT))
		{
			T2 = inp(TCNT0);
			if (T2 >= F_CPU*140/7372800)	// max wait time
				return 0;
		}
		timer0_start();
		while (bit_is_clear(IR_PORT-2, IR_BIT))
		{
			T2 = inp(TCNT0);
			if (T2 >= F_CPU*140/7372800)	// max wait time
				return 0;
		}
		if (inp(TCNT0) >= F_CPU*25/7372800)	// pulse longer than 1 ms? then logic "1"
			code.value += ((u16)tmp << i);	// the device code 
	}
	return (code.value);
}
#endif

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

#if (REMOTE_STANDARD == 4)				// RC-5
u16 get_rec80(u08 std)
{
	u08 i, T2, time, tmp = 0;
	union u16convert code;
	timer0_source(CK256);				//update every 32us
	timer0_start();
	loop_until_bit_is_set(IR_PORT-2, IR_BIT);	// skip leading signal

	for(i=0; i<13; i++)
	{
		if(bit_is_clear(IR_PORT-2, IR_BIT) )
			T2 = 0;
		else
			T2 = 1;

		timer0_start();
		while(1)
		{
			time=inp(TCNT0);
			if(time > F_CPU*0x42/7372800)
				return 0;

			if(bit_is_clear(IR_PORT-2, IR_BIT) && (T2==1) )
			{
				tmp <<= 1;
				tmp++;
				break;
			}
			else if(bit_is_set(IR_PORT-2, IR_BIT) && (T2==0) )
			{
				tmp <<= 1;
				break;
			}
		}

		//save address data
		if(i == 6)
		{
			code.bytes.high = (tmp & 0x5f);		// save address and cut troggle bit
			if ((tmp & 0x10)) i++;			// for some non standard remotes
			tmp=0;
		}

		//delay
		timer0_start();
		while(1)
		{
			time=inp(TCNT0);
			if(time > F_CPU*0x21/7372800)
				break;
		}
	}
	code.bytes.low = tmp;
	return(code.value);
}
#endif

//-------------------------------------------------------------------------------------
#endif // AUTODETECT_STANDARD


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

extern u08 nKeyTime;
u08 TableKbdShort[] = KBD_SHORT;	// Key definitions moved to "Constants.h" file !!!
u08 TableKbdLong[] = KBD_LONG;

event_e get_key_event(void)
{
	event_e event = EV_IDLE;
	static u08 keydown = 0;
	register u08 i;
	ramdisable();			// disable ExtRAM
	outp(0xff, PORTA-1);		// set port as output
	outp(0, PORTA);			// set all pins to 0
	delay10();			// allow time for port to activate

	if (keydown)			// if a key was pressed earlier
	{
		// see if it has been released
		if (bit_is_set(KBD_PIN, KBD_BIT))			// check bit
		{
			// 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 ? 
			{
				event = TableKbdLong[keydown];		// long keypress event
				if (event == EV_UP || event == EV_DOWN || 
				    event == EV_FFWD  || event == EV_FREW)
					nKeyTime = 0x86;		// 0.2 sec repeat time for volume and fast forward
				else
					nKeyTime = 0x82;		// 0.6 sec repeat time
			}	


	}
	else
	{	
		if (bit_is_clear(KBD_PIN, KBD_BIT))			// check if a key is down
		{
			// a key is active, check which one
			for (i = 0; i < 8; i++)
			{
				outp(~(1 << i), PORTA);			// write bit mask
				delay10();				// wait a while
				if (bit_is_clear(KBD_PIN, KBD_BIT)) 	// this bit ?
				{
					keydown = i + 1;		// store the key
					nKeyTime = 0;			// clear keypress timer
					break;				// and exit
				}
			}
		}
	}

⌨️ 快捷键说明

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