void C6821::set_input_cb2(int data) { /* limit the data to 0 or 1 */ data = data ? 1 : 0; /* CB2 is in input mode */ if((ControlB & CTRL_C2_OUTPUT) == 0) { /* the new state has caused a transition */ if (InputCB2 ^ data) { /* handle the active transition */ if ((data && (ControlB & 2)) || (!data && (ControlB & 2) == 0)) { /* mark the IRQ */ IRQB2 = 1; /* update externals */ update_6821_interrupts(); } } } /* set the new value for CA2 */ InputCB2 = data; // p->in_set |= PIA_IN_SET_CB2; }
void pia_set_input_cb2(int which, int data) { struct pia6821 *p = pia + which; /* limit the data to 0 or 1 */ data = data ? 1 : 0; /* CB2 is in input mode */ if (C2_INPUT(p->ctl_b)) { /* the new state has caused a transition */ if (p->in_cb2 ^ data) { /* handle the active transition */ if ((data && C2_LOW_TO_HIGH(p->ctl_b)) || (!data && C2_HIGH_TO_LOW(p->ctl_b))) { /* mark the IRQ */ p->irq_b2 = 1; /* update externals */ update_6821_interrupts(p); } } } /* set the new value for CA2 */ p->in_cb2 = data; p->in_set |= PIA_IN_SET_CB2; }
void pia_set_input_cb1(int which, int data) { pia6821 *p = pia + which; /* limit the data to 0 or 1 */ data = data ? 1 : 0; /* the new state has caused a transition */ if (p->in_cb1 ^ data) { /* handle the active transition */ if ((data && C1_LOW_TO_HIGH(p->ctl_b)) || (!data && C1_HIGH_TO_LOW(p->ctl_b))) { /* mark the IRQ */ p->irq_b1 = 1; /* update externals */ update_6821_interrupts(p); /* If CB2 is configured as a write-strobe output which is reset by a CB1 transition, this reset will only happen when a read from port B implicitly clears the IRQ B1 flag. So we handle the CB2 reset there. Note that this is different from what happens with port A. */ } } /* set the new value for CB1 */ p->in_cb1 = data; p->in_set |= PIA_IN_SET_CB1; }
void C6821::set_input_cb1(int data) { /* limit the data to 0 or 1 */ data = data ? 1 : 0; /* the new state has caused a transition */ if (InputCB1 ^ data) { /* handle the active transition */ if ((data && (ControlB & 2)) || (!data && (ControlB & 2) == 0)) { /* mark the IRQ */ IRQB1 = 1; /* update externals */ update_6821_interrupts(); /* If CB2 is configured as a write-strobe output which is reset by a CB1 transition, this reset will only happen when a read from port B implicitly clears the IRQ B1 flag. So we handle the CB2 reset there. Note that this is different from what happens with port A. */ } } /* set the new value for CB1 */ InputCB1 = data; // p->in_set |= PIA_IN_SET_CB1; }
static void pia_postload(int which) { struct pia6821 *p = pia + which; update_6821_interrupts(p); if (p->intf->out_a_func && p->ddr_a) p->intf->out_a_func(0, p->out_a & p->ddr_a); if (p->intf->out_b_func && p->ddr_b) p->intf->out_b_func(0, p->out_b & p->ddr_b); if (p->intf->out_ca2_func) p->intf->out_ca2_func(0, p->out_ca2); if (p->intf->out_cb2_func) p->intf->out_cb2_func(0, p->out_cb2); }
void pia_set_input_cb1(int which, int data) { struct pia6821 *p = pia + which; /* limit the data to 0 or 1 */ data = data ? 1 : 0; /* the new state has caused a transition */ if (p->in_cb1 ^ data) { /* handle the active transition */ if ((data && C1_LOW_TO_HIGH(p->ctl_b)) || (!data && C1_HIGH_TO_LOW(p->ctl_b))) { /* mark the IRQ */ p->irq_b1 = 1; /* update externals */ update_6821_interrupts(p); /* CB2 is configured as output and in write strobe mode and cleared by a CA1 transition */ if (C2_OUTPUT(p->ctl_b) && C2_STROBE_MODE(p->ctl_b) && STROBE_C1_RESET(p->ctl_b)) { /* the IRQ1 flag must have also been cleared */ if (!p->irq_b1) { /* call the CB2 output function */ if (!p->out_cb2) if (p->intf->out_cb2_func) p->intf->out_cb2_func(0, 1); /* clear CB2 */ p->out_cb2 = 1; } } } } /* set the new value for CB1 */ p->in_cb1 = data; p->in_set |= PIA_IN_SET_CB1; }
void pia_set_input_ca1(int which, int data) { pia6821 *p = pia + which; /* limit the data to 0 or 1 */ data = data ? 1 : 0; /* the new state has caused a transition */ if (p->in_ca1 ^ data) { /* handle the active transition */ if ((data && C1_LOW_TO_HIGH(p->ctl_a)) || (!data && C1_HIGH_TO_LOW(p->ctl_a))) { /* mark the IRQ */ p->irq_a1 = 1; /* update externals */ update_6821_interrupts(p); /* CA2 is configured as output and in read strobe mode and cleared by a CA1 transition */ if (C2_OUTPUT(p->ctl_a) && C2_STROBE_MODE(p->ctl_a) && STROBE_C1_RESET(p->ctl_a)) { /* call the CA2 output function */ if (!p->out_ca2) if (p->intf->out_ca2_func) p->intf->out_ca2_func(0, 1); /* clear CA2 */ p->out_ca2 = 1; } } } /* set the new value for CA1 */ p->in_ca1 = data; p->in_set |= PIA_IN_SET_CA1; }
void C6821::set_input_ca1(int data) { /* limit the data to 0 or 1 */ data = data ? 1 : 0; /* the new state has caused a transition */ if(InputCA1 ^ data) { /* handle the active transition */ if ((data && (ControlA & 2)) || (!data && (ControlA & 2) == 0)) { /* mark the IRQ */ IRQA1 = 1; /* update externals */ update_6821_interrupts(); /* CA2 is configured as output and in read strobe mode and cleared by a CA1 transition */ if(ControlA & CTRL_C2_OUTPUT && (ControlA & CTRL_C2_SETMODE) == 0 && (ControlA & CTRL_STROBE_E_RESET) == 0) { /* call the CA2 output function */ if (OutputCA2 == 0 && OutputCA2Func) OutputCA2Func(user,1); /* clear CA2 */ OutputCA2 = 1; } } } /* set the new value for CA1 */ InputCA1 = data; // p->in_set |= PIA_IN_SET_CA1; }
void pia_write(int which, int offset, int data) { struct pia6821 *p = pia + which; /* adjust offset for 16-bit and ordering */ offset &= 3; if (p->addr & PIA_ALTERNATE_ORDERING) offset = swizzle_address[offset]; switch (offset) { /******************* port A output/DDR write *******************/ case PIA_DDRA: /* write output register */ if (OUTPUT_SELECTED(p->ctl_a)) { LOG(("%04x: PIA%d port A write = %02X\n", activecpu_get_previouspc(), which, data)); /* update the output value */ p->out_a = data;/* & p->ddr_a; */ /* NS990130 - don't mask now, DDR could change later */ /* send it to the output function */ if (p->intf->out_a_func && p->ddr_a) p->intf->out_a_func(0, p->out_a & p->ddr_a); /* NS990130 */ } /* write DDR register */ else { LOG(("%04x: PIA%d DDR A write = %02X\n", activecpu_get_previouspc(), which, data)); if (p->ddr_a != data) { /* NS990130 - if DDR changed, call the callback again */ p->ddr_a = data; /* send it to the output function */ if (p->intf->out_a_func && p->ddr_a) p->intf->out_a_func(0, p->out_a & p->ddr_a); } } break; /******************* port B output/DDR write *******************/ case PIA_DDRB: /* write output register */ if (OUTPUT_SELECTED(p->ctl_b)) { LOG(("%04x: PIA%d port B write = %02X\n", activecpu_get_previouspc(), which, data)); /* update the output value */ p->out_b = data;/* & p->ddr_b */ /* NS990130 - don't mask now, DDR could change later */ /* send it to the output function */ if (p->intf->out_b_func && p->ddr_b) p->intf->out_b_func(0, p->out_b & p->ddr_b); /* NS990130 */ /* CB2 is configured as output and in write strobe mode */ if (C2_OUTPUT(p->ctl_b) && C2_STROBE_MODE(p->ctl_b)) { /* this will cause a transition low; call the output function if we're currently high */ if (p->out_cb2) if (p->intf->out_cb2_func) p->intf->out_cb2_func(0, 0); p->out_cb2 = 0; /* if the CB2 strobe is cleared by the E, reset it right away */ if (STROBE_E_RESET(p->ctl_b)) { if (p->intf->out_cb2_func) p->intf->out_cb2_func(0, 1); p->out_cb2 = 1; } } } /* write DDR register */ else { LOG(("%04x: PIA%d DDR B write = %02X\n", activecpu_get_previouspc(), which, data)); if (p->ddr_b != data) { /* NS990130 - if DDR changed, call the callback again */ p->ddr_b = data; /* send it to the output function */ if (p->intf->out_b_func && p->ddr_b) p->intf->out_b_func(0, p->out_b & p->ddr_b); } } break; /******************* port A control write *******************/ case PIA_CTLA: /* Bit 7 and 6 read only - PD 16/01/00 */ data &= 0x3f; LOG(("%04x: PIA%d control A write = %02X\n", activecpu_get_previouspc(), which, data)); /* CA2 is configured as output and in set/reset mode */ /* 10/22/98 - MAB/FMP - any C2_OUTPUT should affect CA2 */ // if (C2_OUTPUT(data) && C2_SET_MODE(data)) if (C2_OUTPUT(data)) { /* determine the new value */ int temp = SET_C2(data) ? 1 : 0; /* if this creates a transition, call the CA2 output function */ if (p->out_ca2 ^ temp) if (p->intf->out_ca2_func) p->intf->out_ca2_func(0, temp); /* set the new value */ p->out_ca2 = temp; } /* update the control register */ p->ctl_a = data; /* update externals */ update_6821_interrupts(p); break; /******************* port B control write *******************/ case PIA_CTLB: /* Bit 7 and 6 read only - PD 16/01/00 */ data &= 0x3f; LOG(("%04x: PIA%d control B write = %02X\n", activecpu_get_previouspc(), which, data)); /* CB2 is configured as output and in set/reset mode */ /* 10/22/98 - MAB/FMP - any C2_OUTPUT should affect CB2 */ // if (C2_OUTPUT(data) && C2_SET_MODE(data)) if (C2_OUTPUT(data)) { /* determine the new value */ int temp = SET_C2(data) ? 1 : 0; /* if this creates a transition, call the CA2 output function */ if (p->out_cb2 ^ temp) if (p->intf->out_cb2_func) p->intf->out_cb2_func(0, temp); /* set the new value */ p->out_cb2 = temp; } /* update the control register */ p->ctl_b = data; /* update externals */ update_6821_interrupts(p); break; } }
int pia_read(int which, int offset) { struct pia6821 *p = pia + which; int val = 0; /* adjust offset for 16-bit and ordering */ offset &= 3; if (p->addr & PIA_ALTERNATE_ORDERING) offset = swizzle_address[offset]; switch (offset) { /******************* port A output/DDR read *******************/ case PIA_DDRA: /* read output register */ if (OUTPUT_SELECTED(p->ctl_a)) { /* update the input */ if ((FPTR)(p->intf->in_a_func) > 0x100) p->in_a = p->intf->in_a_func(0); #ifdef MAME_DEBUG else if ((p->ddr_a ^ 0xff) && !(p->in_set & PIA_IN_SET_A)) { logerror("PIA%d: Warning! no port A read handler. Assuming pins %02x not connected\n", which, p->ddr_a ^ 0xff); p->in_set |= PIA_IN_SET_A; // disable logging } #endif // MAME_DEBUG /* combine input and output values */ val = (p->out_a & p->ddr_a) + (p->in_a & ~p->ddr_a); /* IRQ flags implicitly cleared by a read */ p->irq_a1 = p->irq_a2 = 0; update_6821_interrupts(p); /* CA2 is configured as output and in read strobe mode */ if (C2_OUTPUT(p->ctl_a) && C2_STROBE_MODE(p->ctl_a)) { /* this will cause a transition low; call the output function if we're currently high */ if (p->out_ca2) if (p->intf->out_ca2_func) p->intf->out_ca2_func(0, 0); p->out_ca2 = 0; /* if the CA2 strobe is cleared by the E, reset it right away */ if (STROBE_E_RESET(p->ctl_a)) { if (p->intf->out_ca2_func) p->intf->out_ca2_func(0, 1); p->out_ca2 = 1; } } LOG(("%04x: PIA%d read port A = %02X\n", activecpu_get_previouspc(), which, val)); } /* read DDR register */ else { val = p->ddr_a; LOG(("%04x: PIA%d read DDR A = %02X\n", activecpu_get_previouspc(), which, val)); } break; /******************* port B output/DDR read *******************/ case PIA_DDRB: /* read output register */ if (OUTPUT_SELECTED(p->ctl_b)) { /* update the input */ if ((FPTR)(p->intf->in_b_func) > 0x100) p->in_b = p->intf->in_b_func(0); #ifdef MAME_DEBUG else if ((p->ddr_b ^ 0xff) && !(p->in_set & PIA_IN_SET_B)) { logerror("PIA%d: Error! no port B read handler. Three-state pins %02x are undefined\n", which, p->ddr_b ^ 0xff); p->in_set |= PIA_IN_SET_B; // disable logging } #endif // MAME_DEBUG /* combine input and output values */ val = (p->out_b & p->ddr_b) + (p->in_b & ~p->ddr_b); /* IRQ flags implicitly cleared by a read */ p->irq_b1 = p->irq_b2 = 0; update_6821_interrupts(p); LOG(("%04x: PIA%d read port B = %02X\n", activecpu_get_previouspc(), which, val)); } /* read DDR register */ else { val = p->ddr_b; LOG(("%04x: PIA%d read DDR B = %02X\n", activecpu_get_previouspc(), which, val)); } break; /******************* port A control read *******************/ case PIA_CTLA: /* Update CA1 & CA2 if callback exists, these in turn may update IRQ's */ if ((FPTR)(p->intf->in_ca1_func) > 0x100) pia_set_input_ca1(which, p->intf->in_ca1_func(0)); #ifdef MAME_DEBUG else if (!(p->in_set & PIA_IN_SET_CA1)) { logerror("PIA%d: Warning! no CA1 read handler. Assuming pin not connected\n",which); p->in_set |= PIA_IN_SET_CA1; // disable logging } #endif // MAME_DEBUG if ((FPTR)(p->intf->in_ca2_func) > 0x100) pia_set_input_ca2(which, p->intf->in_ca2_func(0)); #ifdef MAME_DEBUG else if (C2_INPUT(p->ctl_a) && !(p->in_set & PIA_IN_SET_CA2)) { logerror("PIA%d: Warning! no CA2 read handler. Assuming pin not connected\n",which); p->in_set |= PIA_IN_SET_CA2; // disable logging } #endif // MAME_DEBUG /* read control register */ val = p->ctl_a; /* set the IRQ flags if we have pending IRQs */ if (p->irq_a1) val |= PIA_IRQ1; if (p->irq_a2 && C2_INPUT(p->ctl_a)) val |= PIA_IRQ2; LOG(("%04x: PIA%d read control A = %02X\n", activecpu_get_previouspc(), which, val)); break; /******************* port B control read *******************/ case PIA_CTLB: /* Update CB1 & CB2 if callback exists, these in turn may update IRQ's */ if ((FPTR)(p->intf->in_cb1_func) > 0x100) pia_set_input_cb1(which, p->intf->in_cb1_func(0)); #ifdef MAME_DEBUG else if (!(p->in_set & PIA_IN_SET_CB1)) { logerror("PIA%d: Error! no CB1 read handler. Three-state pin is undefined\n",which); p->in_set |= PIA_IN_SET_CB1; // disable logging } #endif // MAME_DEBUG if ((FPTR)(p->intf->in_cb2_func) > 0x100) pia_set_input_cb2(which, p->intf->in_cb2_func(0)); #ifdef MAME_DEBUG else if (C2_INPUT(p->ctl_b) && !(p->in_set & PIA_IN_SET_CB2)) { logerror("PIA%d: Error! no CB2 read handler. Three-state pin is undefined\n",which); p->in_set |= PIA_IN_SET_CB2; // disable logging } #endif // MAME_DEBUG /* read control register */ val = p->ctl_b; /* set the IRQ flags if we have pending IRQs */ if (p->irq_b1) val |= PIA_IRQ1; if (p->irq_b2 && C2_INPUT(p->ctl_b)) val |= PIA_IRQ2; LOG(("%04x: PIA%d read control B = %02X\n", activecpu_get_previouspc(), which, val)); break; } return val; }
void C6821::Write(int reg,u8 data) { switch(reg) { case c6821_ddra: if(ControlA & CTRL_OUTPUT) { OutputA = data; if(OutputAFunc && DataA) OutputAFunc(user,OutputA & DataA); } else { if(DataA != data) { DataA = data; if(OutputAFunc && DataA) OutputAFunc(user,OutputA & DataA); } } break; case c6821_ctrla: data &= 0x3F; if(data & CTRL_C2_OUTPUT) { u8 t; if(data & CTRL_C2_SETMODE) { if((data & 8) == 0) t = 0; else t = 1; } else t = 1; if((ControlA & CTRL_C2_OUTPUT) == 0 || ((ControlA & CTRL_C2_OUTPUT) && (OutputCA2 ^ t))) { if(OutputCA2Func) OutputCA2Func(user,t); } OutputCA2 = t; } ControlA = data; update_6821_interrupts(); break; case c6821_ddrb: if(ControlB & CTRL_OUTPUT) { OutputB = data; if(OutputBFunc && DataB) OutputBFunc(user,OutputB & DataB); if(ControlB & CTRL_C2_OUTPUT && (ControlB & CTRL_C2_SETMODE) == 0) { if(OutputCB2 && OutputCB2Func) OutputCB2Func(user,0); OutputCB2 = 0; if(ControlB & CTRL_STROBE_E_RESET) { if(OutputCB2Func) OutputCB2Func(user,1); OutputCB2 = 1; } } } else { if(DataB != data) { DataB = data; if(OutputBFunc && DataB) OutputBFunc(user,OutputB & DataB); } } break; case c6821_ctrlb: data &= 0x3F; if(data & CTRL_C2_OUTPUT) { u8 t; if(data & CTRL_C2_SETMODE) { if((data & 8) == 0) t = 0; else t = 1; } else t = 1; if((ControlB & CTRL_C2_OUTPUT) == 0 || ((ControlB & CTRL_C2_OUTPUT) && (OutputCB2 ^ t))) { if(OutputCB2Func) OutputCB2Func(user,t); } OutputCB2 = t; } ControlB = data; update_6821_interrupts(); break; } }
u8 C6821::Read(int reg) { u8 ret; switch(reg) { case c6821_ddra: if(ControlA & CTRL_OUTPUT) //output selected { if(InputAFunc) //function specified to get input data? InputA = InputAFunc(user); ret = OutputA & DataA; //combine input and output data ret |= InputA & ~DataA; IRQA1 = 0; //clear irq data IRQA2 = 0; update_6821_interrupts(); if(ControlA & CTRL_C2_OUTPUT && //ca2 is output and strobe is on (ControlA & CTRL_C2_SETMODE) == 0) { if(OutputCA2 && OutputCA2Func)//if output ca2 specified OutputCA2Func(user,0); //send low signal OutputCA2 = 0; if(ControlA & CTRL_STROBE_E_RESET) { if(OutputCA2Func) //if output ca2 specified OutputCA2Func(user,1); //send high signal OutputCA2 = 1; } } } else //input selected, read data register ret = DataA; return(ret); case c6821_ctrla: if(InputCA1Func) set_input_ca1(InputCA1Func(user)); if(InputCA2Func) set_input_ca2(InputCA2Func(user)); ret = ControlA; if(IRQA1) ret |= 0x80; if(IRQA2 && (ControlA & CTRL_C2_OUTPUT) == 0) ret |= 0x40; return(ret); case c6821_ddrb: if(ControlB & CTRL_OUTPUT) //output selected { if(InputBFunc) //function specified to get input data? InputB = InputBFunc(user); ret = OutputB & DataB; //combine input and output data ret |= InputB & ~DataB; if(IRQB1 && ControlB & CTRL_C2_OUTPUT && (ControlB & CTRL_C2_SETMODE) == 0 && (ControlB & CTRL_STROBE_E_RESET) == 0) { if(OutputCB2 == 0 && OutputCB2Func) OutputCB2Func(user,1); //send high signal OutputCB2 = 1; } IRQB1 = 0; //clear irq data IRQB2 = 0; update_6821_interrupts(); } else //input selected, read data register ret = DataB; return(ret); case c6821_ctrlb: if(InputCB1Func) set_input_cb1(InputCB1Func(user)); if(InputCB2Func) set_input_cb2(InputCB2Func(user)); ret = ControlB; if(IRQB1) ret |= 0x80; if(IRQB2 && (ControlB & CTRL_C2_OUTPUT) == 0) ret |= 0x40; return(ret); } return(0); }