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); } }
static inline void FPGACommandSend(unsigned char command) { outPortC(0, bmBIT0); outPortC(command, bmBIT2); }
void Intel8255::writePortC(const uint8_t data,uint8_t mask) { mask &= portCWriteMask; latchOutPortC = (latchOutPortC & (~mask)) + (data & mask); if (mask) outPortC(mask); }
static inline unsigned char FPGACommandRecv(void) { outPortC(0x80, bmBIT0); return inPortC(bmBIT1); }