diff options
author | 2020-07-16 16:07:06 +0200 | |
---|---|---|
committer | 2020-07-16 16:10:58 +0200 | |
commit | a20013147862dc9381860e97692546690db7e319 (patch) | |
tree | 669e52e8ddce41e4069384eb12308534177bdad1 /src/devices/cpu/avr8 | |
parent | b2aba645fbded4a58c0f5391d3c73fed203299af (diff) |
-avr8: Added support for Timer 1 'Fast PWM with ICR' mode. [Ryan Holtz]
New working machines
--------------------
Phasor [Ryan Holtz]
Diffstat (limited to 'src/devices/cpu/avr8')
-rw-r--r-- | src/devices/cpu/avr8/avr8.cpp | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/src/devices/cpu/avr8/avr8.cpp b/src/devices/cpu/avr8/avr8.cpp index ab00d9bd804..cbd56d599e8 100644 --- a/src/devices/cpu/avr8/avr8.cpp +++ b/src/devices/cpu/avr8/avr8.cpp @@ -1376,10 +1376,9 @@ inline void avr8_device::timer1_tick() static const uint8_t s_ocf1[2] = { (1 << AVR8_TIFR1_OCF1A_SHIFT), (1 << AVR8_TIFR1_OCF1B_SHIFT) }; static const uint8_t s_int1[2] = { AVR8_INTIDX_OCF1A, AVR8_INTIDX_OCF1B }; + const uint16_t icr1 = AVR8_ICR1; int32_t increment = m_timer_increment[1]; - LOGMASKED(LOG_TIMER1_TICK, "%s: AVR8_WGM1: %d\n", machine().describe_context(), AVR8_WGM1); - for (int32_t reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) { switch (m_wgm1) @@ -1484,10 +1483,79 @@ inline void avr8_device::timer1_tick() m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg)); break; } + } + break; + + case WGM1_FAST_PWM_ICR: + if (m_timer1_count == m_ocr1[reg]) + { + switch (m_timer1_compare_mode[reg] & 3) + { + case 0: /* Normal Operation; OC1A/B disconnected */ + break; + + case 1: /* Toggle OC1A on compare match */ + if (reg == 0) + { + LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1%c on match\n", machine().describe_context()); + m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg)); + } + break; - m_r[AVR8_REGIDX_TIFR1] &= ~s_ocf1[reg]; + case 2: /* Clear OC1A/B on compare match */ + LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A'); + m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg)); + break; + + case 3: /* Set OC1A/B on compare match */ + LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A'); + m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg)); + break; + } + + m_r[AVR8_REGIDX_TIFR1] |= s_ocf1[reg]; update_interrupt(s_int1[reg]); } + else if (m_timer1_count == 0) + { + if (reg == 0) + { + m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK; + update_interrupt(AVR8_INTIDX_TOV1); + } + + switch (m_timer1_compare_mode[reg] & 3) + { + case 0: /* Normal Operation; OC1A/B disconnected */ + break; + + case 1: /* Toggle OC1A at BOTTOM*/ + if (reg == 0) + { + LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1A at BOTTOM\n", machine().describe_context()); + m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg)); + } + break; + + case 2: /* Set OC1A/B at BOTTOM*/ + LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c at BOTTOM\n", machine().describe_context(), reg ? 'B' : 'A'); + m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg)); + break; + + case 3: /* Clear OC1A/B at BOTTOM */ + LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c at BOTTOM\n", machine().describe_context(), reg ? 'B' : 'A'); + m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg)); + break; + } + } + + if (m_timer1_count == icr1 && reg == 1) + { + m_r[AVR8_REGIDX_TIFR1] |= AVR8_TIFR1_TOV1_MASK; + update_interrupt(AVR8_INTIDX_TOV1); + m_timer1_count = 0; + increment = 0; + } break; default: |