Esempio n. 1
0
void Intel8255::writeControl(const uint8_t data) {
    if (data & 0x80) {
        /* bit[7:7] = 1             mode set flag
         * bit[6:5] = mode select   00=mode 0  01=mode 1  1x=mode 2
         * bit[4:4] = Port A        1=input  0=output
         * bit[3:3] = Port C upper  1=input  0=output
         * bit[2:2] = mode select   0=mode 0   1=mode 1
         * bit[1:1] = Port B        1=input  0=output
         * bit[0:0] = Port C lower  1=input  0=output */
        /* mode byte */
        mode = data;

        /* update write masks */
        portAWriteMask  =  (mode & 0x10) ? 0x00 : 0xFF;  /* bit 4 */
        portBWriteMask  =  (mode & 0x02) ? 0x00 : 0xFF;  /* bit 1 */
        portCWriteMask  = ((mode & 0x01) ? 0x00 : 0x0F) +/* bit 0 */
                          ((mode & 0x08) ? 0x00 : 0xF0); /* bit 3 */

        /* modes take additional bits from port C */
        if (mode & 0x04) { /* port B mode 1 */
            /* port C meanings:
             *
             * output:
             * bit[2:2] = Acknowledge, from device (IN)
             * bit[1:1] = Output buffer full aka CPU has written data to this port (OUT)
             * bit[0:0] = Interrupt request B (OUT)
             *
             * input:
             * bit[2:2] = Strobe input (loads data into the latch) (IN)
             * bit[1:1] = Input buffer full (OUT)
             * bit[0:0] = Interrupt request B (OUT) */
            portCWriteMask &= ~0x07;
        }
        if (mode & 0x40) { /* port A mode 2 */
            /* port C meanings:
             *
             * bit[7:7] = Output buffer full aka CPU has written data to this port (OUT)
             * bit[6:6] = Acknowledge, from device. This latches the output. Else output is high impedance (IN)
             * bit[5:5] = Input buffer full (OUT)
             * bit[4:4] = Strobe input (loads data into the latch) (IN)
             * bit[3:3] = Interrupt request A (OUT) */
            portCWriteMask &= ~0xF8;
        }
        else if (mode & 0x20) { /* port A mode 1 */
            /* port C meanings:
             *
             * output:
             * bit[7:7] = Output buffer full aka CPU has written data to this port (OUT)
             * bit[6:6] = Acknowledge, from device (IN)
             * bit[3:3] = Interrupt request A (OUT)
             *
             * input:
             * bit[5:5] = Input buffer full (OUT)
             * bit[4:4] = Strobe input (loads data input the latch) (IN) 
             * bit[3:3] = Interrupt request A (OUT) */
            portCWriteMask &= ~((mode & 0x10) ? 0x38 : 0xC8);
        }

        /* according to PC-98 hardware it seems changing a port to input makes the latch forget it's contents */
        latchOutPortA &= ~portAWriteMask;
        latchOutPortB &= ~portBWriteMask;
        latchOutPortC &= ~portCWriteMask;

        /* update */
        outPortA(portAWriteMask);
        outPortB(portBWriteMask);
        outPortC(portCWriteMask);

        /* HACK: I get the impression from the PC-98 platform and "Metal Force" that writing the mode
         *       byte can cause the chip to re-trigger an interrupt. So... */
        /* FIXME: Or am I wrong here, and the retriggering of the interrupt may simply be that internal
         *        interrupts on the PC-98 are level triggered? */
        INTR_A = INTR_B = false;
        checkINTR_A();
        checkINTR_B();

        /* then reset actual state again */
        updateINTR_A();
        updateINTR_B();
        checkINTR_A();
        checkINTR_B();
    }
    else {
        /* bit[7:7] = 0             bit set/reset
         * bit[6:4] = X             don't care
         * bit[3:1] = bit           bit select
         * bit[0:0] = set/reset     1=set 0=reset */
        /* single bit set/reset port C */
        const uint8_t bit = ((unsigned int)data >> 1U) & 7U;

        if (mode & 0x40) { /* Port A mode 2 */
            if (bit == 4) {
                INTE_2 = !!(data & 1);
                updateINTR_A();
                checkINTR_A();
            }
            else if (bit == 6) {
                INTE_1 = !!(data & 1);
                updateINTR_A();
                checkINTR_A();
            }
        }
        else if (mode & 0x20) { /* Port A mode 1 */
            if (bit == ((mode & 0x10) ? /*input*/ 4 : /*output*/6)) {
                INTE_A = !!(data & 1);
                updateINTR_A();
                checkINTR_A();
            }
        }

        if (mode & 0x04) { /* Port B mode 1 */
            if (bit == 2) {
                INTE_B = !!(data & 1);
                updateINTR_B();
                checkINTR_B();
            }
        }

        writePortC(/*data*/(data & 1U) << bit,/*mask*/1U << bit);
    }
}
Esempio n. 2
0
static inline void FPGACommandSend(unsigned char command) {
    outPortC(0, bmBIT0);
    outPortC(command, bmBIT2);
}
Esempio n. 3
0
void Intel8255::writePortC(const uint8_t data,uint8_t mask) {
    mask &= portCWriteMask;
    latchOutPortC = (latchOutPortC & (~mask)) + (data & mask);
    if (mask) outPortC(mask);
}
Esempio n. 4
0
static inline unsigned char FPGACommandRecv(void) {
    outPortC(0x80, bmBIT0);
    return inPortC(bmBIT1);
}