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 + -
显示快捷键?