📄 ir.c
字号:
/* For the new style of IR handling (i.e. via 4438) */
/************************************************************************
* Local variables. *
************************************************************************/
PRIVATE unsigned short dataIR; /* System/customer IR code */
PRIVATE char cntIRbits = 0; /* Number of IR sys/cust. bits */
PRIVATE volatile char stateIR = IR_IDLE; /* IR state machine state */
PRIVATE char trigger_edge;
PRIVATE unsigned int prevIRtime = 0; /* Last time IR intr. happens */
#ifdef IR_NEC
PRIVATE unsigned int wrongIRwidth = 0;
PRIVATE unsigned int intIRtime = 0;
#endif
#ifdef IR_SANYO
PRIVATE unsigned short IR_sanyo_codebar;/* Sanyo IR only */
#endif /* IR_SAYNO */
#ifdef IRREP
PRIVATE unsigned char previous_data; /* Record the previous ID code */
#endif
/************************************************************************
* Local routines *
************************************************************************/
PRIVATE void IR_core_NEC(unsigned int, int);
PRIVATE void IR_core_Philips(unsigned int, int);
void ir_init()
{
CPRINTF(("EauxIR_ir_init....\n"));
sysIRcode = IR_syscode[0]; /* Initialize IR system code */
#ifdef DANCER
sysDANCERcode = T_DANCER_syscode[0]; /* Initialize IR system code */
#endif
CLEAR_IRXOR; /* Clear IR XOR (EAUX11 is active high!! */
#ifdef IR_SANYO
IR_sanyo_codebar = (~sysIRcode) & 0x1fff;
#endif /* IR_SANYO */
#ifdef NETWORK
#ifdef EAUX_ENABLE_C2PO
if (boot_nic) { //use ethernet
ENABLE_EAUX3(2); /* toggle dbg interrupt pin */
EAUX_init_irq_ctl(1, 1, 1, 8, 0x80);
}
#endif
#ifdef WILDCAT /* AUX5 as PCMCIA interrupt */
EAUX_init_irq_ctl(1, EAUX_FALLING_EDGE, 1, 4, 0x40);
#endif
#endif
#if defined(BD_BAHAMAS) && defined(DVD_MODEM)
Init4210IrqCtl( 1, 1, 4 ); /*falling-edge, aux4, eaux mode enabled*/
#else
EAUX_init_ir(1, EAUX_FALLING_EDGE, 1); /* Start 4438 IR */
#endif
EAUX_INIT_16550(1, EAUX_RISING_EDGE); /* On, Rising edge */
trigger_edge = 0;
mvd[riface_clear_dbgirq] = 0; /* Clear debug_irq */
#ifndef NETWORK
enable_int(debug);
#endif
}
#if (IR_NEC || IR_SANYO)
PRIVATE void IR_core_NEC(width, overflow)
unsigned int width;
int overflow;
{
#define LEADER_MIN ir_tbl[0]
#define LEADER_MAX ir_tbl[1]
#define DATA_1_MIN ir_tbl[2]
#define DATA_1_MAX ir_tbl[3]
#define DATA_0_MIN ir_tbl[4]
#define DATA_0_MAX ir_tbl[5]
#ifdef IRREP
#define REPEAT_MIN ir_tbl[6]
#define REPEAT_MAX ir_tbl[7]
#endif /* IRREP */
#ifdef DANCER
#define LEADER_DANCER_MIN ir_tbl[IRTBL_INDX_LAST+1]
#define LEADER_DANCER_MAX ir_tbl[IRTBL_INDX_LAST+2]
#define DATA_1_DANCER_MIN ir_tbl[IRTBL_INDX_LAST+3]
#define DATA_1_DANCER_MAX ir_tbl[IRTBL_INDX_LAST+4]
#define DATA_0_DANCER_MIN ir_tbl[IRTBL_INDX_LAST+5]
#define DATA_0_DANCER_MAX ir_tbl[IRTBL_INDX_LAST+6]
#endif
unsigned int *ir_tbl;
unsigned char data, check;
int reset;
ir_tbl = IR_table;
/*
* If 4438's clock overflows, then reset. The only exception is
* when REP is considered!!
*/
reset = overflow;
if (stateIR == IR_CUSTOM) {
dataIR <<= 1;
if ((width >= DATA_1_MIN) && (width <= DATA_1_MAX)) {
dataIR |= 0x1;
} else if ((width < DATA_0_MIN) || (width > DATA_1_MAX)) {
#ifdef IR_NEC
reset = 1;
#endif /* IR_NEC */
#ifdef IR_SANYO
reset = 1; /* we do not care about repeat key for Sanyo yet */
#endif /* IR_SANYO */
}
cntIRbits++;
#ifdef IR_NEC
/* First 16 bits are syscode */
#if defined(_KB_VIALTA_) || defined(_KB_VIALTA_02_)
if (cntIRbits == 16) {
int k;
for ( k =0; k < T_IR_syscode_SZ >> 2; k ++)
if (dataIR == IR_syscode[k]) break;
if (k == T_IR_syscode_SZ >> 2) reset = 1;
else code_set = k;
}
#else
if ((cntIRbits == 16) && (dataIR != sysIRcode)) reset = 1;
#endif
#if 0
if (cntIRbits == 24) {
data = dataIR & 0xff;
/* reverse data bits to fit look up table */
mvd[riface_reflect] = data;
data = mvd[riface_reflect];
#ifdef IRREP
previous_data = data;
#endif
codeIR = data | 0x100; /* Indicate a new code */
} else if (cntIRbits == 32) reset = 1;
#else
if (cntIRbits == 32)
{
data = (dataIR >> 8) & 0xff;
check = (~data) & 0xff;
if((dataIR & 0xff)== check) /*do the double check */
{
mvd[riface_reflect] = data;
data = mvd[riface_reflect];
#ifdef IRREP
previous_data = data;
#endif
codeIR = data | 0x100; /* Indicate a new code */
}
reset = 1;
}
#endif
#endif /* IR_NEC */
#ifdef IR_SANYO
if (cntIRbits == 13) {
dataIR &= 0x1fff;
if (dataIR != sysIRcode) reset = 1;
dataIR = 0;
} else if (cntIRbits == 26) {
unsigned short tmp = (~sysIRcode) & 0x1fff;
if (dataIR != tmp) reset = 1;
dataIR = 0;
} else if (cntIRbits == 34) {
data = dataIR;
mvd[riface_reflect] = data;
data = mvd[riface_reflect];
codeIR = data;
dataIR = 0;
} else if (cntIRbits == 42) {
data = dataIR;
mvd[riface_reflect] = data;
data = ~(mvd[riface_reflect]);
if (data == codeIR) {
codeIR = data | 0x100;
} else codeIR = 0;
reset = 1;
}
#endif /* IR_SANYO */
}
#ifdef DANCER
else if (stateIR == DANCER_CUSTOM)
{
dataIR <<= 1;
if ((width >= DATA_1_DANCER_MIN) && (width <= DATA_1_DANCER_MAX)) {
dataIR |= 0x1;
}
else if ((width < DATA_1_DANCER_MIN) || (width > DATA_0_DANCER_MAX)) {
reset = 1;
}
cntIRbits++;
if ((cntIRbits == 15) && ((dataIR & 0x7f) != sysDANCERcode)) reset = 1;
if (cntIRbits == 16)
{
int i;
int parity;
int one_num = 0;
parity = dataIR & 0x1;
data = dataIR >> 8;
for (i=0;i<8;i++)
{
if ((data & 0x1) == 1)
one_num ++;
data >>= 1;
}
if (!(one_num & 1) && !parity)
reset = 1;
else if ((one_num & 1) && parity)
reset = 1;
else
{
data = dataIR >> 8;
codeIR = data | 0x1100; /* Indicate a new code */
}
} else if (cntIRbits == 17) reset = 1;
}
#endif
else {
if ((width >= LEADER_MIN) && (width <= LEADER_MAX)) {
stateIR = IR_CUSTOM;
dataIR = cntIRbits = 0;
#ifdef DANCER
} else if ((width >= LEADER_DANCER_MIN) &&
(width <= LEADER_DANCER_MAX))
{
stateIR = DANCER_CUSTOM;
dataIR = cntIRbits = 0;
#endif
#ifdef IRREP
} else if ((width >= REPEAT_MIN) && (width <= REPEAT_MAX)) {
/* if the width is 2.25 ms, it is repeat code leader */
if (repeat_IRkey_allowed(previous_data))
codeIR = previous_data | 0x100; /* Indicate a new code */
#endif
} else reset = 1;
}
if (reset) {
/* Reset all, start from the very beginning */
#ifdef NETWORK
if (netmode && dataIR && cntIRbits >= 32) {
extern int stream_playing;
fan_dataIR[nKeyEnd] = dataIR;
nKeyEnd ++;
if(nKeyEnd >= 100) nKeyEnd = 0;
ir_keypressed = 1;
if (stream_playing && dataIR==0xf807)
stopTime = RISC_linear_time+6;
}
#endif
dataIR = 0;
stateIR = IR_IDLE;
}
}
#endif /* IR_NEC || IR_SANYO */
#ifdef IR_PHILIPS
PRIVATE unsigned int data_half = 0; /* Mark whether or nor have half_bit
data before edge of intr. coming*/
PRIVATE void IR_core_Philips(width, overflow)
unsigned int width;
int overflow;
{
unsigned int *ir_tbl;
int reset;
int is_half_bit;
int is_full_bit;
#define HALFBIT_MIN ir_tbl[0]
#define HALFBIT_MAX ir_tbl[1]
#define ONEBIT_MIN ir_tbl[2]
#define ONEBIT_MAX ir_tbl[3]
ir_tbl = IR_table;
reset = overflow; /* If 3881's clock overflows, then reset */
is_half_bit = (width >= HALFBIT_MIN) && (width <= HALFBIT_MAX);
is_full_bit = (width >= ONEBIT_MIN) && (width <= ONEBIT_MAX);
if (stateIR == IR_IDLE) {
/* We shall get a rising edge, since the first bit is fixed */
dataIR = 0;
cntIRbits = 0;
stateIR = IR_CUSTOM;
if (is_half_bit) data_half = 0;
else if (is_full_bit) data_half = 1;
else {
stateIR = IR_IDLE;
}
} else {
if (data_half) {
/*
* We were in half bit position, so this edge shall either
* conclude the previous cycle or go the the half position
* of the next bit. Record the last bit.
*/
dataIR <<= 1;
if (!trigger_edge) dataIR |= 1;
cntIRbits++;
if (is_half_bit) data_half = 0;
else if (!is_full_bit) reset = 1;
} else {
/*
* We started at a sampling cycle, so we shall only get half bit,
* otherwise, something is wrong!
*/
if (is_half_bit) data_half = 1;
else reset = 1;
}
if ((cntIRbits == 12) && trigger_edge && data_half) {
/* This is the last rising edge, no more. So collect the bit */
dataIR <<= 1;
dataIR |= 1;
cntIRbits = 13;
}
if (reset) {
/*
* Abnormal exist. Maybe we are out of sync. If this
* is falling edge, maybe this is the sync of a new
* input!
*/
stateIR = IR_IDLE;
if (trigger_edge) stateIR = IR_LEADER;
} else if (cntIRbits == 13) {
/* We only care the case when system code matches */
if (((dataIR >> 6) & 0x1f) == sysIRcode) {
unsigned int prevctlbit;
prevctlbit = IR_ctlbit;
IR_ctlbit = (dataIR >> 11) & 1;
if ((unsigned int) IR_ctlbit != prevctlbit) {
int tmp = (dataIR >> 12) & 1;
if (tmp) tmp = 0x40;
codeIR = (dataIR & 0x3f) | tmp | 0x100;
IR_rep_cnt = 0;
} else
IR_rep_cnt++;
IR_int_time = (unsigned int) mvd[riface_timer2];
}
stateIR = IR_IDLE;
}
}
}
#endif /* IR_PHILIPS */
#if defined(IR_NEC) || defined(IR_SANYO)
#define CLK_LEADER_MIN (cpuclk * 1300) /* Leader minimum */
#define CLK_LEADER_MAX (cpuclk * 1390) /* Leader maximum */
#define CLK_DATA_1_MIN (cpuclk * 195) /* Data 1 minimum */
#define CLK_DATA_1_MAX (cpuclk * 255) /* Data 1 maximum */
#define CLK_DATA_0_MIN (cpuclk * 82) /* Data 0 minimum */
#define CLK_DATA_0_MAX (cpuclk * 142) /* Data 0 maximum */
#ifdef IRREP
#define CLK_REP_MIN (cpuclk * 1000) /* Data 0 minimum */
#define CLK_REP_MAX (cpuclk * 1150) /* Data 0 maximum */
#endif /* IRREP */
/* The width for IR_NEC */
#define IR_LEADER IR_table[1]
#define IR_DATA_1 IR_table[3]
#define IR_DATA_0 IR_table[5]
#ifdef IRREP
#define IR_REPEAT IR_table[7]
#endif /* IRREP */
#endif
#ifdef IR_PHILIPS
#define CLK_HALFBIT_MIN (cpuclk*50) /* minimum length of half bit */
#define CLK_HALFBIT_MAX (cpuclk*130) /* maximum length of half bit */
#define CLK_ONEBIT_MIN (cpuclk*140) /* minimum length of one bit */
#define CLK_ONEBIT_MAX (cpuclk*240) /* maximum length of one bit */
#define IR_HALFBIT IR_table[1]
#define IR_ONEBIT IR_table[3]
#endif
/* Interrupt via 4438 */
void IR_recv_interrupt_service(status)
unsigned int status;
{
unsigned int width;
unsigned int *ir_tbl;
int overflow = 0;
if (status & 0x80) {
overflow = 1; /* 4438's clock overflowed */
}
#if defined(BD_BAHAMAS) && defined(DVD_MODEM)
width = 0; wrongIRwidth = 0;
#else
width = mvd[eaux_ir_diff] & 0xff; /* Get the counter */
#endif
#ifdef IR_NEC
if(!IS_POWER_DOWN) { /* only active when power on */
/* avoid the width is 0 for the noise, we use timer2 instead */
if((width == 0) || (wrongIRwidth == 1)) {
unsigned int currIRtime;
currIRtime = mvd[riface_timer2];
width = currIRtime - intIRtime;
if (currIRtime < intIRtime) { /* Wrap around case */
width += -timer2_period;
}
if ((width >= CLK_LEADER_MIN) && (width <= CLK_LEADER_MAX)) {
width = IR_LEADER;
} else if ((width >= CLK_DATA_1_MIN) && (width <= CLK_DATA_1_MAX)) {
width = IR_DATA_1;
} else if ((width >= CLK_DATA_0_MIN) && (width <= CLK_DATA_0_MAX)) {
width = IR_DATA_0;
} else
{
#ifdef IRREP
if ((width >= CLK_REP_MIN) && (width <= CLK_REP_MAX)) {
width = IR_REPEAT;
}
else
#endif /*IRREP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -