📄 control.c
字号:
/* ***********************************************************************
**
** 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 + -