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

📄 gamectrl.c

📁 一个两碟控制的VCD的代码,两碟之间的转动及连续播放,已大量生产的CODE.
💻 C
📖 第 1 页 / 共 4 页
字号:
 * routine is called mostly inside timer interrupt handler. Originally,
 * we have a semaphore to prevent calling this while communicating
 * with 3207. The new mechanism will disable any interrupt while
 * communicating with 3207, so semaphore is no longer needed.
 */
void DSC_toggle()
{
    DSC_DESELECT;
    DSC_SELECT;
}


/*
 * Send DSC command from 3208/3210 to 3207
 *	dcs_c:	CS1
 *	dsc_s:	AUX3
 *	d[7:0]:	data[7:0]
 * DSC data space is at address 0x14000003 (i.e. assert CS1)
 */
unsigned int DSC_cmd(unsigned int addr, unsigned int data)
{
    volatile unsigned char* prt;

    /* 
     * Disable interrupt while communicating with 3207 such address
     * and data can always be in pair.
     */
    mvd[riface_irqsuppress] = 0;
    asm("nop");
    prt = (char *) x14000003;
    /* asserting dsc strobe from 3210 */
    *prt = addr;
    asm("nop"); asm("nop");
    if (!(addr & 0x1)) {
	*prt = data;
	data = 0;
    } else data = *prt;

    return(data);
}
 
/*
 * Fuction to set and/or clear AUX pins on 3205/3207/3209.
 *
 * Inputs:
 *	sel:	0 - for dsc_aux0 
 *		1 - for dsc_aux1
 *	set:	0 - clear    according to mask
 *		1 - set      according to mask
 *		2 - tristate pads specified by mask
 *	mask:	mask to be used
 */
void DSC_set_aux(sel, set, mask)
int sel, set, mask;
{
    register psw_shadow, temp;
    volatile char *ptr;
    int data, ctl, *pdat, *pctl;

    asm volatile("movfrs psw,%0":  "=r" (psw_shadow) ); 
    /* Non-cachable bank1 address (CS1) */
    ptr = (char *) x14000003;

    /* Decide which 3207 register to use (dsc_aux0 vs. dsc_aux1) */
    if (sel) {
	pdat = &shadow_eaux1_dat;
	pctl = &shadow_eaux1_ctl;
	data = dsc_aux1_data;
	ctl  = dsc_aux1_ctl;
    } else {
	pdat = &shadow_eaux0_dat;
	pctl = &shadow_eaux0_ctl;
	data = dsc_aux0_data;
	ctl  = dsc_aux0_ctl;
    }

    /* Disable interrupt so everything can happen together */
    temp = 0x1fd5;
    asm volatile("movtos %0,psw" :  :"r" (temp)); 
    asm("nop");
    asm("nop");

    /* Set the PAD value first (keep a copy in shadow) */
    *ptr = data;
    /* When setting or tri-stating, OR in the mask */
    if (set) *ptr = (*pdat |= mask);
    else *ptr = (*pdat &= ~mask);
    
    /* Set the enable bit (unless it is tri-state) */
    asm("nop");
    *ptr = ctl;
    /* When tri-stating, turn the bit off */
    if (set == 2) *ptr = (*pctl &= ~mask);
    else *ptr = (*pctl |= mask);

    /* Restore PSD */
    asm volatile("movtos %0,psw" :  :"r" (psw_shadow)); 
}

PRIVATE int la_trigger;		/* For logic analyzer */
/*
 * This routine will be called inside interrupt handler. With 3207, we'll
 * be reset by 3207; without 3207, we'll just jump to start up code.
 */
void DSC_dead(trigger)
int trigger;
{
    /* Sit here and wait for 3207 to reset us. */
    while (1) la_trigger = trigger;
}

#ifdef DSC_IRQ
/*
 * This routine updates dsc_aux_mode and dsc_irq_ctl registers.
 *
 * Inputs:
 *      on:     0: turning off
 *              1: turning on
 *      edge:   0: trigger on rising  edge
 *              1: trigger on falling edge
 *      setmode:0: Don't touch dsc_aux_mode and IRQOUT. They are right (only
 *                 used for change IR trigger edge for Philips IR.)
 *              1: Drive IRQOUT high and set dsc_aux_mode (normal case)
 *      mask:   interrupt mask;
 *      falling:patter to enable triggering on falling edge
 */
PRIVATE void DSC_init_irq_ctl(on, edge, setmode, mask, falling)
int on, edge, setmode, mask, falling;
{
    int mode, ctl;
 
    mode = shadow_aux_mode;
    ctl = shadow_irq_ctl;
 
    /* Set irq_ctl register */
    ctl &= ~mask;                       /* Clear the mask first         */
    if (on) {
        ctl |= mask;                    /* Enable the interrupt         */
        ctl &= ~falling;                /* Assume trigger on rising edge*/
        if (edge == DSC_FALLING_EDGE) 
          ctl |= falling;
    }
            
    if (setmode) {
        /* Set aux_mode register */
        mode &= ~2;                     /* Clear SQCK                   */
        /* If S0S1 is enabled, then enable SQCK */
        if (ctl & 2) mode |= 2;
 
        /* If no interrupt mask is on, then disable interrupt output */
        mode &= ~1;
        if (ctl & 0xf) {
            mode |= 1;
            CLEAR_IRQOUT;               /* Drive EAUX11 low             */
            CLEAR_IRXOR;                /* EAUX11 is active high        */
        }
 
        /*
         * The only time setmode is not set is when changing the
         * IR triggering edge for Philips IR. In which case, there
         * is no need to change mode.
         */
        shadow_aux_mode = mode;
        DSC_cmd(dsc_aux_mode, shadow_aux_mode);
    }
 
    /* 
     * Need to protect because we may change IR's edge in IR handler.
     * Thus, it is possible that interrupt hits after shadow_irq_ctl
     * but before dsc_irq_ctl is really updated.
     *
     * riface_irqsuppress should be good enought because we do
     * riface_irqsuppress inside DSC_cmd;
     */
    mvd[riface_irqsuppress] = 0;
    asm("nop");
    shadow_irq_ctl = ctl;
    DSC_cmd(dsc_irq_ctl, shadow_irq_ctl);
}

/*
 * Turn ON or OFF IR handling by 3881
 * Inputs:
 *      on:     0: turn off
 *              1: turn on
 *      edge:   0: rising
 *              1: falling
 *      setmode:0: Don't set dsc_aux_mode (assume it is set right already)
 *              1: Set dsc_aux_mode as well as pull IRQOUT high (normal case)
 */
void DSC_init_ir(on, edge, setmode)
int on, edge, setmode;
{
    TRISTATE_IRIN;              /* Allow IR to come in on EAUX15        */
    DSC_init_irq_ctl(on, edge, setmode, 1, 0x10);
}
#endif	/* DSC_IRQ */

/************************************************************************/
/************** This part is from version 1.56 of ir.c *******************/
/************************************************************************/

#ifdef IR_PHILIPS
#define IR_SYSCODE              0x6
#endif /* IR_PHILIPS */

#ifdef IR_NEC
#define IR_SYSCODE              0x00ff
#endif

#ifdef IR_SANYO
#define IR_SYSCODE              0x0cc0
#endif

#define ASSIGN_SYSCODE          sysIRcode = IR_SYSCODE

/* Timer values when CPU is running at full speed */
unsigned int IR_powerup_tbl[] = {
#ifdef DSC_IRQ
    /* Use 3881's internal counter to keep track of time                */
#ifdef IR_PHILIPS
    /* For Philips format */
    3,
    8,
    9,
    16,
#else
    /* For NEC and SANYO formats */
    85,                                 /* Leader low+high min (12.89ms)*/
    93,                                 /* Leader low+high max (14.10ms)*/
    12,                                 /* Gap+data 1 minimum (1.82ms)  */
    19,                                 /* Gap+data 1 maximum (2.88ms)  */
    4,                                  /* Gap+data 0 minimum (0.61ms)  */
    11,                                 /* Gap+data 0 maximum (1.67ms)  */
#ifdef IRREP
    70,                                 /* Rep low+high min (10.62ms)   */
    78,                                 /* Rep low+high max (11.83ms)   */
#endif /* IRREP */
#endif /* else of IR_PHILIPS */
 
#else
    /* Use CPU's timer2 to keep track of time                           */
#ifdef IR_PHILIPS
    /* For Philips format */
    CPUCLK * 50,                        /* minimum length of half bit   */
    CPUCLK * 130,                       /* maximum length of half bit   */
    CPUCLK * 140,                       /* minimum length of one bit    */
    CPUCLK * 240,                       /* maximum length of one bit    */
#else
    /* For NEC and SANYO formats */
    CPUCLK * 880,                       /* Leader low minimum           */
    CPUCLK * 920,                       /* Leader low maximum           */
    CPUCLK * 430,                       /* Leader high minimum          */
    CPUCLK * 470,                       /* Leader high maximum          */
    CPUCLK * 205,                       /* Data 1 minimum               */
    CPUCLK * 245,                       /* Data 1 maximum               */
    CPUCLK * 92,                        /* Data 0 minimum               */
    CPUCLK * 132,                       /* Data 0 maximum               */
#ifdef IRREP
    CPUCLK * 205,                       /* Repeat high minimun          */
    CPUCLK * 245,                       /* Repeat high mazimun          */
    CPUCLK * 36,                        /* Repeat data minimum          */
    CPUCLK * 76                         /* Repeat data maxmun           */
#endif /* IRREP */
#endif /* else of IR_PHILIPS */
#endif /* else of DSC_IRQ */
};

#ifdef DSC_IRQ
/* For the new style of IR handling (i.e. via 3881) */
/************************************************************************
 * 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;

#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);

void IR_init()
{
    ASSIGN_SYSCODE;	/* Initialize IR system code			*/
    CLEAR_IRXOR;	/* Clear IR XOR (EAUX11 is active high!!	*/

#ifdef IR_SANYO
    IR_sanyo_codebar = (~sysIRcode) & 0x1fff;
#endif /* IR_SANYO */

    DSC_INIT_IR(1, DSC_FALLING_EDGE, 1);	/* Start 3881 IR	*/
    trigger_edge = 0;
    mvd[riface_clear_dbgirq] = 0;		/* Clear debug_irq	*/
    enable_int(debug);
}

#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

    unsigned int *ir_tbl;
    unsigned char data;
    char reset = 0;
 
    ir_tbl = IR_powerup_tbl;

    /*
     * If 3881'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 ((cntIRbits == 16) && (dataIR != sysIRcode)) reset = 1;
 
        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;
#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 ((width >= LEADER_MIN) && (width <= LEADER_MAX)) {
	    stateIR = IR_CUSTOM;
	    dataIR = cntIRbits = 0;
#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 */
        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)
unsigned int width;
{
    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 = T_IR_powerup_tbl;

    reset = 0;
    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) {

⌨️ 快捷键说明

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