⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ir.c

📁 ESS 公司VCD软件关于IR的编程!
💻 C
📖 第 1 页 / 共 4 页
字号:
		    overflow = 1;
		}
	} else {
	    width += wrongIRwidth;
	}
	wrongIRwidth = 0;
    }
    intIRtime = mvd[riface_timer2];
#endif

    /* Apparently, timer2 is more tolerant. */
    if (cpuclk < 300) {
	unsigned int currIRtime;
	
	currIRtime = mvd[riface_timer2];
	width = currIRtime - prevIRtime;
	if (currIRtime < prevIRtime) {  /* Wrap around case		*/
	    width += -timer2_period;
	}
	prevIRtime = currIRtime;
	overflow = 0;
#if defined(IR_NEC) || defined(IR_SANYO)
	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*/
	          overflow = 1;
	    }
#endif
#ifdef IR_PHILIPS
	if ((width >= CLK_HALFBIT_MIN) && (width <= CLK_HALFBIT_MAX)) {
	    width = IR_HALFBIT; 
	} else if ((width >= CLK_ONEBIT_MIN) && (width <= CLK_ONEBIT_MAX)) {
	    width = IR_ONEBIT;
	}
#endif
    }

#if (IR_NEC || IR_SANYO)
    IR_core_NEC(width, overflow);
#endif /* IR_NEC || IR_SAYNO */

#ifdef IR_PHILIPS
    if (!trigger_edge)
        EAUX_INIT_IR(1, DSC_RISING_EDGE, 0);         /* detect rising edge   */
    else
        EAUX_INIT_IR(1, DSC_FALLING_EDGE, 0);        /* detect falling edge  */

    IR_core_Philips(width, overflow);
    trigger_edge = 1-trigger_edge;

#endif /* IR_PHILIPS */
}


#else /* else of EAUX_IRQ */
/************************************************************************
 * Local variables.							*
 ************************************************************************/
/* For IR receiving */
PRIVATE	unsigned int	prevIRtime = 0;	/* Last time IR intr. happens	*/
PRIVATE	unsigned short	dataIR;		/* System/customer IR code	*/
PRIVATE	unsigned int	diffIR[2];	/* Array to store time gap	*/
PRIVATE	char 		cntIRchg = 0;	/* Number of unprocessed IR intr*/
PRIVATE	char 		cntIRbits = 0;	/* Number of IR sys/cust. bits	*/
PRIVATE	char		killIR = 0;	/* Whether to "kill" next IR bit*/
PRIVATE volatile char	stateIR = IR_IDLE; /* IR state machine state	*/

#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(int);
PRIVATE	void		IR_core_Philips(int);

/*
 * Initialization. Properly set internal XOR's input value, then turn
 * on interrupt.
 */
void ir_init()
{

    CPRINTF(("ir_init...\n"));
#ifdef FLIP_IR
    /*
     * If incoming IR signal is flipped, then the first incoming edge
     * will be a rising edge, so we need to clear the build-in
     * XOR gate.
     */
    CLEAR_IRXOR;
#else
    SET_IRXOR; 	/* Set IR XOR to high at first */
#endif

    sysIRcode = IR_syscode[0];	/* Initialize IR system code	*/
#ifdef IR_SANYO
    IR_sanyo_codebar = (~sysIRcode) & 0x1fff;
#endif /* IR_SANYO */

#ifdef BD_MDVD
    *(int *)(0x14100000) = 2;		/*block Modem IRQ if there's a Module there*/
#endif

#if 0
def TIVO_REC
    mvd[eaux_mode] |= 0x10; /* Select AUX[7:4] as irp inputs */

    mvd[eaux_irq_ctl] = 0x88;   /* AUX4, falling edge */
    mvd[riface_wait_state] |= 0x100000; /* set ccirq */
    
#endif  
    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 = IR_table;

    /* 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;
#endif
		codeIR = data | 0x100;	/* Indicate a new code */
	    } 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 = IR_table;

    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.
 *
 * In order to be consistent with 3883, there is a dummy parameter.
 */
void IR_recv_interrupt_service(dummy)
unsigned int dummy;
{
    /* 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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -