ir.c
来自「ESS3890+SL原代码(1*16内存)」· C语言 代码 · 共 1,376 行 · 第 1/3 页
C
1,376 行
mvd[riface_clear_dbgirq] = 0; /* Clear debug_irq */ enable_int(debug);}#if (IR_NEC || IR_SANYO)PRIVATE void IR_core_NEC(falling_edge)int falling_edge;{ unsigned int *ir_tbl;#define LEADER_LOW_MIN ir_tbl[0]#define LEADER_LOW_MAX ir_tbl[1]#define LEADER_HIGH_MIN ir_tbl[2]#define LEADER_HIGH_MAX ir_tbl[3]#define DATA_1_MIN ir_tbl[4]#define DATA_1_MAX ir_tbl[5]#define DATA_0_MIN ir_tbl[6]#define DATA_0_MAX ir_tbl[7]#ifdef IRREP#define REPEAT_HIGH_MIN ir_tbl[8]#define REPEAT_HIGH_MAX ir_tbl[9]#define REPEAT_DATA_MIN ir_tbl[10]#define REPEAT_DATA_MAX ir_tbl[11]#endif ir_tbl = T_IR_powerup_tbl;#ifdef DSC if (IS_POWER_DOWN) ir_tbl = T_IR_powerdn_tbl;#endif /* First IR interrupt should be a falling edge */ if (stateIR == IR_IDLE) { if (falling_edge) stateIR = IR_LEADER_LOW; else cntIRchg = prevIRtime = 0; } /* * We only process things when we get 2 bits (i.e. 2 time period). */ if (cntIRchg == 2) { unsigned char data; char reset = 0; unsigned int width; cntIRchg = 0; width = diffIR[1]; if (stateIR == IR_CUSTOM) {/* Put most common case first */ /* * We are collecting system code or custom code */ width += diffIR[0]; /* Get data + gap */ 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 /* * I am assert kill here because we may not recognize * the singal because our checks are too tight; yet * the external micro controller can still recognize it. * By killing it, we guarantee that external logic won't * recognize it. * * However, there may also be a downside: if IR input * has noise, the external micro controll may still * properly receive signal if we don't kill the input; * if killIR is asserted, then this may be a problem. */ 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) { /* * 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; rep_timeout = glbTimer + QUARTER_SECOND;#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 (rep_timeout > glbTimer) { if (repeat_IRkey_allowed(previous_data)) { codeIR = previous_data | 0x100; /* Indicate a new code */ rep_timeout = glbTimer + QUARTER_SECOND; } } else { previous_data = 0xff; } } 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_PHILIPSPRIVATE 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; /* 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#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 */}#endif /* else of DSC_IRQ */#endif /* IR */#ifdef IRXMTPRIVATE 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. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?