30#pragma GCC optimize ("O2")
32#if FABGL_ESP_IDF_VERSION > FABGL_ESP_IDF_VERSION_VAL(3, 3, 5)
33 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
45VIA6522::VIA6522(
int tag)
56 m_timer1Counter = 0x0000;
57 m_timer1Latch = 0x0000;
58 m_timer2Counter = 0x0000;
71 m_timer1Triggered =
false;
72 m_timer2Triggered =
false;
86void VIA6522::setPA(
int value)
93void VIA6522::setBitPA(
int bit,
bool value)
95 uint8_t newPA = (m_PA & ~(1 << bit)) | ((int)value << bit);
100void VIA6522::openBitPA(
int bit)
102 uint8_t mask = (1 << bit);
105 setBitPA(bit, m_ORA & mask);
113void VIA6522::setPB(
int value)
116 m_IRB = (m_PB & ~m_DDRB) | (m_ORB & m_DDRB);
120void VIA6522::setBitPB(
int bit,
bool value)
122 uint8_t newPB = (m_PB & ~(1 << bit)) | ((int)value << bit);
127void VIA6522::openBitPB(
int bit)
129 uint8_t mask = (1 << bit);
132 setBitPB(bit, m_ORB & mask);
141void VIA6522::writeReg(
int reg,
int value)
144 printf(
"tick %d VIA %d writeReg(%s, 0x%02x)\n", m_tick, m_tag, VIAREG2STR[reg], value);
150 case VIA_REG_ORB_IRB:
152 m_PB = (m_ORB & m_DDRB) | (m_PB & ~m_DDRB);
153 m_IRB = (m_PB & ~m_DDRB) | (m_ORB & m_DDRB);
154 m_portOut(m_context,
this, VIA6522Port::PB);
156 m_IFR &= ~VIA_IER_CB1;
157 m_IFR &= ~VIA_IER_CB2;
161 case VIA_REG_ORA_IRA:
163 m_IFR &= ~VIA_IER_CA1;
164 m_IFR &= ~VIA_IER_CA2;
167 case VIA_REG_ORA_IRA_NH:
169 m_PA = (m_ORA & m_DDRA) | (m_PA & ~m_DDRA);
171 m_portOut(m_context,
this, VIA6522Port::PA);
177 m_PB = (m_ORB & m_DDRB) | (m_PB & ~m_DDRB);
178 m_IRB = (m_PB & ~m_DDRB) | (m_ORB & m_DDRB);
184 m_PA = (m_ORA & m_DDRA) | (m_PA & ~m_DDRA);
189 case VIA_REG_T1_C_LO:
190 m_timer1Latch = (m_timer1Latch & 0xff00) | value;
194 case VIA_REG_T1_C_HI:
195 m_timer1Latch = (m_timer1Latch & 0x00ff) | (value << 8);
198 m_timer1Counter = (m_timer1Latch & 0x00ff) | (value << 8);
200 m_IFR &= ~VIA_IER_T1;
201 m_timer1Triggered =
false;
205 case VIA_REG_T1_L_LO:
206 m_timer1Latch = (m_timer1Latch & 0xff00) | value;
210 case VIA_REG_T1_L_HI:
211 m_timer1Latch = (m_timer1Latch & 0x00ff) | (value << 8);
213 m_IFR &= ~VIA_IER_T1;
217 case VIA_REG_T2_C_LO:
218 m_timer2Latch = value;
222 case VIA_REG_T2_C_HI:
224 m_timer2Counter = (value << 8) | m_timer2Latch;
226 m_IFR &= ~VIA_IER_T2;
227 m_timer2Triggered =
false;
245 switch ((m_PCR >> 1) & 0b111) {
249 m_portOut(m_context,
this, VIA6522Port::CA2);
254 m_portOut(m_context,
this, VIA6522Port::CA2);
260 switch ((m_PCR >> 5) & 0b111) {
264 m_portOut(m_context,
this, VIA6522Port::CB2);
269 m_portOut(m_context,
this, VIA6522Port::CB2);
280 m_IFR &= ~value & 0x7f;
285 if (value & VIA_IER_CTRL) {
287 m_IER |= value & 0x7f;
290 m_IER &= ~value & 0x7f;
299int VIA6522::readReg(
int reg)
302 printf(
"tick %d VIA %d readReg(%s)\n", m_tick, m_tag, VIAREG2STR[reg]);
308 case VIA_REG_ORB_IRB:
310 m_IFR &= ~VIA_IER_CB1;
311 m_IFR &= ~VIA_IER_CB2;
313 m_portIn(m_context,
this, VIA6522Port::PB);
317 case VIA_REG_ORA_IRA:
319 m_IFR &= ~VIA_IER_CA1;
320 m_IFR &= ~VIA_IER_CA2;
322 case VIA_REG_ORA_IRA_NH:
324 m_portIn(m_context,
this, VIA6522Port::PA);
336 case VIA_REG_T1_C_LO:
338 m_IFR &= ~VIA_IER_T1;
340 return m_timer1Counter & 0xff;
343 case VIA_REG_T1_C_HI:
345 return m_timer1Counter >> 8;
348 case VIA_REG_T1_L_LO:
350 return m_timer1Latch & 0xff;
353 case VIA_REG_T1_L_HI:
355 return m_timer1Latch >> 8;
358 case VIA_REG_T2_C_LO:
360 m_IFR &= ~VIA_IER_T2;
362 return m_timer2Counter & 0xff;
365 case VIA_REG_T2_C_HI:
367 return m_timer2Counter >> 8;
383 return m_IFR | (m_IFR & m_IER ? 0x80 : 0);
395bool VIA6522::tick(
int cycles)
402 m_timer1Counter -= cycles;
403 if (m_timer1Counter <= 0) {
404 if (m_ACR & VIA_ACR_T1_FREERUN) {
406 m_timer1Counter += (m_timer1Latch - 1) + 3;
408 }
else if (!m_timer1Triggered) {
410 m_timer1Counter += 0xFFFF;
411 m_timer1Triggered =
true;
414 m_timer1Counter = (uint16_t)m_timer1Counter;
418 if ((m_ACR & VIA_ACR_T2_COUNTPULSES) == 0) {
419 m_timer2Counter -= cycles;
420 if (m_timer2Counter <= 0 && !m_timer2Triggered) {
421 m_timer2Counter += 0xFFFF;
422 m_timer2Triggered =
true;
428 if (m_CA1 != m_CA1_prev) {
430 if (((m_PCR & 1) && m_CA1) || (!(m_PCR & 1) && !m_CA1)) {
431 m_IFR |= VIA_IER_CA1;
437 if (m_CB1 != m_CB1_prev) {
439 if (((m_PCR & 0x10) && m_CB1) || (!(m_PCR & 0x10) && !m_CB1)) {
440 m_IFR |= VIA_IER_CB1;
445 return m_IER & m_IFR & 0x7f;
This file contains fabgl::VIA6522 definition.