?? ir.c
字號:
killIR = 1;
reset = 1;
#endif /* IR_NEC */
#ifdef IR_SANYO
if (cntIRbits == 0) {
/*
* SANYO's repeat is the same as leader low/high.
* So we may mistaken repeat as a new code. So if
* we are broken on the first bit of new cutsom code,
* we shall assume it is a new code overall.
*
* The last one is probably a repeat, so this is
* really the first bit of leader low.
*/
cntIRchg = 1; /* We just need one more edge */
stateIR = IR_LEADER_LOW;
} else {
killIR = 1;
reset = 1;
}
#endif /* IR_SANYO */
}
cntIRbits++;
#ifdef IR_NEC
/* First 16 bits are syscode */
if ((cntIRbits == 16) && (dataIR != sysIRcode))
reset = 1;
if (cntIRbits == 24) {
#ifdef CUST71
data = dataIR & 0x01;
if (data)
reset = 1;
else
#endif
{
/*
* We will not wait for data bar. Base on data, we'll
* decide whether we want to pass the IR to CD loader.
* If we decided that the code shouldn't be passed on,
* we'll intentionally destroy the output IR so CD
* loader will not get it.
*/
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 */
/* Get the kill bit from the kill IR table */
#ifdef IRXMT
killIR = tblKillIR[data >> 3] & ptrLshift[data & 7];
#endif
}
} else if (cntIRbits == 32) reset = 1;
#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 */
} else if (stateIR == IR_LEADER_LOW) {
if ((width >= LEADER_LOW_MIN) && (width <= LEADER_LOW_MAX)) {
stateIR = IR_LEADER_HIGH;
cntIRchg = 1; /* We'll only collect 1 change next time */
} else reset = 1;
#ifdef IRREP
} else if (stateIR == IR_REPEAT) {
if ((width >= REPEAT_DATA_MIN) && (width <= REPEAT_DATA_MAX)) {
/* the width is 0.56 ms */
if (repeat_IRkey_allowed(previous_data))
codeIR = previous_data | 0x100; /* Indicate a new code */
}
reset = 1;
#endif
} else {
/* stateIR has to be equal to IR_LEADER_HIGH */
if ((width >= LEADER_HIGH_MIN) && (width <= LEADER_HIGH_MAX)) {
dataIR = cntIRbits = 0;
stateIR = IR_CUSTOM;
#ifdef IRREP
} else if ((width >= REPEAT_HIGH_MIN) &&
(width <= REPEAT_HIGH_MAX)) {
/* if the width is 2.25 ms, it is repeat code leader */
cntIRchg = 1; /* We'll only collect 1 change next time */
stateIR = IR_REPEAT;
#endif
} else reset = 1;
}
if (reset) {
/* Reset all, start from the very beginning */
stateIR = IR_IDLE;
cntIRchg = prevIRtime = 0;
}
}
}
#endif /* IR_NEC || IR_SAYNO */
#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(falling_edge)
int falling_edge;
{
unsigned int *ir_tbl;
unsigned int width;
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 = T_IR_powerup_tbl;
#ifdef DSC
if (IS_POWER_DOWN) ir_tbl = T_IR_powerdn_tbl;
#endif
width = diffIR[0];
cntIRchg = 0;
reset = 0;
is_half_bit = (width >= HALFBIT_MIN) && (width <= HALFBIT_MAX);
is_full_bit = (width >= ONEBIT_MIN) && (width <= ONEBIT_MAX);
if (stateIR == IR_IDLE) {
if (falling_edge) stateIR = IR_LEADER;
else prevIRtime = 0;
} else if (stateIR == IR_LEADER) {
/* 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;
prevIRtime = 0;
}
} 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 (falling_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) && !falling_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 (falling_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 */
/*
* DBG IRQ INTERUPT SERVICE for IR
*
* This routine recognizes IR input and selectively retransmit signals.
*/
void IR_recv_interrupt_service()
{
/* I shift data bit coming from IR from LSB to the left. */
int falling_edge = 0, tmp;
unsigned int currIRtime, tmp1;
currIRtime = ((unsigned int) mvd[riface_timer2]);
tmp1 = currIRtime - prevIRtime;
if (currIRtime < prevIRtime) {/* Wrap around case */
tmp1 += -timer2_period;
}
diffIR[cntIRchg++] = tmp1;
prevIRtime = currIRtime;
#ifdef IRQSHARE
if (xor1value) {
falling_edge = 1;
CLEAR_XOR1;
xor1value = 0;
tmp = killIR? 1: 0;
}
else {
falling_edge = 0;
SET_XOR1;
xor1value = 1;
tmp = killIR? 0: 1;
}
#else
/* Toggle XOR to get next interupt */
#ifdef FLIP_IR
/*
* If the polarity of the incoming IR is flipped (e.g. on the Internet
* board), then if the internal XOR input is 1, we received a falling
* edge from the remote sensor, and we want to send out a rising edge.
* Vice versa.
*
* To make minimum change to the remaining code, when we recive a
* falling edge, we'll tell the internal code that we have received
* a rising edge. Vice versa.
*/
if (IS_IRXOR_HIGH) {
CLEAR_IRXOR; /* set to low */
/* If we want to kill IR, then send 0; else send 1 */
tmp = killIR ? 0 : 1;
} else {
SET_IRXOR;
falling_edge = 1; /* Interupt caused by IR falling edge */
/* If we want to kill IR, then send 1; else send 0 */
tmp = killIR ? 1 : 0;
}
#else
if (IS_IRXOR_HIGH) {
CLEAR_IRXOR; /* set to low */
falling_edge = 1; /* Interupt caused by IR falling edge */
/* If we want to kill IR, then send 1; else send 0 */
tmp = killIR ? 1 : 0;
} else {
SET_IRXOR;
/* If we want to kill IR, then send 0; else send 1 */
tmp = killIR ? 0 : 1;
}
#endif
#endif IRQSHARE
mvd[riface_clear_dbgirq] = 0; /* Clear debug_irq */
#ifdef IRXMT
if (!connect_inout) {
/* IR comes from us, so we'll send it now */
if (tmp) {OUTIR_HIGH;}
else {OUTIR_LOW;}
}
/*
* If we meant to kill IR, then IR is effectly killed now
* i.e. CD won't get the correct key bar.
*/
killIR = 0;
#endif
#if (IR_NEC || IR_SANYO)
IR_core_NEC(falling_edge);
#endif /* IR_NEC || IR_SAYNO */
#ifdef IR_PHILIPS
IR_core_Philips(falling_edge);
#endif /* IR_PHILIPS */
#if defined(WEBDVD) && defined(SLAVE)
CLEAR_AUX0;
_8259_EOI();
SET_AUX0;
#endif
}
#endif /* else of DSC_IRQ */
#endif /* IR */
#ifdef IRXMT
PRIVATE void RISC_start_timer1(unsigned int);
/************************************************************************
* Local typedef. *
************************************************************************/
typedef struct {
unsigned char level; /* Assert this output level */
unsigned char next; /* Goto this state */
unsigned short timer; /* Timer1 value (need to << 9) */
} IR_XMIT_INFO;
/* For IR transmission */
PRIVATE unsigned char IR_xmit_state = IR_XMIT_IDLE;
PRIVATE unsigned char IR_xmit_bitcount = 0;
PRIVATE unsigned int IR_xmit_code;
PRIVATE char origConnectInOut;
/* State machine for transmitting IR */
PRIVATE IR_XMIT_INFO IR_xmit_array[] = { /* Current state */
{0, IR_XMIT_LEADER_LOW, IRW_LEADER_LOW}, /* IR_XMIT_IDLE */
{1, IR_XMIT_LEADER_HIGH, IRW_LEADER_HIGH}, /* IR_XMIT_LEADER_LOW */
{0, IR_XMIT_GAP, IRW_GAP_LOW}, /* IR_XMIT_LEADER_HIGH */
{0, IR_XMIT_GAP, IRW_GAP_LOW}, /* IR_XMIT_DATA */
{1, IR_XMIT_DATA, IRW_DATA_ONE}, /* IR_XMIT_GAP *
* (Possible targets *
* are IDLE, DATA, and *
* REP_HIGH1) */
{0, IR_XMIT_REP_LOW1, IRW_REP_LOW1}, /* IR_XMIT_REP_HIGH1 */
{1, IR_XMIT_REP_HIGH2, IRW_REP_HIGH2}, /* IR_XMIT_REP_LOW1 */
{0, IR_XMIT_REP_LOW2, IRW_REP_LOW2}, /* IR_XMIT_REP_HIGH2 */
/* IR_XMIT_REP_LOW2 *
* (disable timer1) */
};
/************************************************************************
* Start timer1 (for transmitting IR signals) *
************************************************************************/
PRIVATE void RISC_start_timer1(period)
unsigned int period;
{
mvd[riface_clear_timer1] = 0;
mvd[riface_timer1] = 0 - (period << 9);
/*
* Since this routine will be called repeatedly, it is better
* to enable interrupt outside.
*/
}
/*
* Main routine to start tranmission of IR signal. IR transmission is
* interrupt driven (by timer1). Therefore, this routine will enable
* the timer1 interrupt.
*
* Inputs;
* code: user code to be transmitted
* repeate: 1 transmit repeat
* 0 transmit code
*/
void IR_send_data(unsigned char code, int repeat)
{
register int psw;
unsigned char code_bar;
unsigned int begTimer = glbTimer;
unsigned int period;
/*
* We'll do detailed checking only if interrupt is enabled.
* If this routine is called inside the interrupt service routine,
* then interrupt can't come in (i.e. glbTimer won't change).
* In which case, just send the code (at worst, we'll loss the code,
* but the machine won't hang)
*/
asm volatile("movfrs psw,%0": "=r" (psw) );
if (!(psw & 0x10)) {
/*
* If we are in the middle of receiving, then wait up to 1/8 of
* a second to finish reciving. Otherwise, if we are in the middle
* of FF/FB/SLOW, IR misses at high frequency.
*/
do {
if (stateIR == IR_IDLE) break;
} while ((glbTimer - begTimer) < EIGHTH_SECOND);
/*
* If we are in the middle of transmitting an IR, then wait it to
* finish
*/
begTimer = glbTimer;
do {
if (IR_xmit_state == IR_XMIT_IDLE) break;
} while ((glbTimer - begTimer) < EIGHTH_SECOND);
}
/* reverse data to meet NEC remote control standard */
mvd[riface_reflect] = code;
code = mvd[riface_reflect];
code_bar = ~code;
IR_xmit_code = (((unsigned int) sysIRcode) << 16) | (code << 8) | code_bar;
origConnectInOut = connect_inout;
connect_inout = 1; /* While transmitting IR, don't relay any IR input */
if (repeat) {
IR_xmit_state = IR_XMIT_REP_LOW1;
period = IRW_REP_LOW1;
} else {
/* Leader low is 9ms wide */
IR_xmit_bitcount = 32;
IR_xmit_state = IR_XMIT_LEADER_LOW;
period = IRW_LEADER_LOW;
}
OUTIR_LOW;
RISC_start_timer1(period);
enable_int(tim1);
}
/*
* Timer 1 interrupt service routine. This service routine goes through
* a state machine to transmit IR.
*/
void IR_xmit_interrupt_service(void)
{
IR_XMIT_INFO *ptrXmit = &IR_xmit_array[IR_xmit_state];
if (IR_xmit_state == IR_XMIT_REP_LOW2) {
OUTIR_HIGH;
IR_xmit_state = IR_XMIT_IDLE;
disable_int(tim1);
connect_inout = origConnectInOut;
} else if (IR_xmit_state == IR_XMIT_GAP) {
/* We have to make some decision here */
OUTIR_HIGH;
if (IR_xmit_bitcount != 0) {
/* More bits to transmit */
IR_xmit_state = IR_XMIT_DATA;
RISC_start_timer1((IR_xmit_code & x80000000) ? IRW_DATA_ONE
: IRW_DATA_ZERO);
IR_xmit_code <<= 1;
IR_xmit_bitcount--;
} else {
#ifdef JIANGHAI
IR_xmit_state = IR_XMIT_REP_HIGH1;
RISC_start_timer1(IRW_REP_HIGH1);
#else
IR_xmit_state = IR_XMIT_IDLE;
disable_int(tim1);
connect_inout = origConnectInOut;
#endif
}
} else {
/* Do a table lookup */
IR_xmit_state = ptrXmit->next;
if (ptrXmit->level) {OUTIR_HIGH;}
else {OUTIR_LOW;}
RISC_start_timer1((unsigned int) ptrXmit->timer);
}
}
#endif /* IRXMT */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -