[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v1 5/9] hw/mos6522: Fix initial timer counter reload
From: |
Finn Thain |
Subject: |
[PATCH v1 5/9] hw/mos6522: Fix initial timer counter reload |
Date: |
Fri, 24 Sep 2021 08:49:56 +1000 |
The first reload of timer 1 is early by half of a clock cycle as it gets
measured from a falling edge. By contrast, the succeeding reloads are
measured from rising edge to rising edge.
Neglecting that complication, the behaviour of the counter should be the
same from one reload to the next. The sequence is always:
N, N-1, N-2, ... 2, 1, 0, -1, N, N-1, N-2, ...
But at the first reload, the present driver does this instead:
N, N-1, N-2, ... 2, 1, 0, -1, N-1, N-2, ...
Fix this deviation for both timer 1 and timer 2, and allow for the fact
that on a real 6522 the timer 2 counter is not reloaded when it wraps.
Signed-off-by: Finn Thain <fthain@linux-m68k.org>
---
hw/misc/mos6522.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c
index c0d6bee4cc..6bd60f2118 100644
--- a/hw/misc/mos6522.c
+++ b/hw/misc/mos6522.c
@@ -63,15 +63,16 @@ static unsigned int get_counter(MOS6522State *s,
MOS6522Timer *ti)
if (ti->index == 0) {
/* the timer goes down from latch to -1 (period of latch + 2) */
if (d <= (ti->counter_value + 1)) {
- counter = (ti->counter_value - d) & 0xffff;
+ counter = ti->counter_value - d;
} else {
- counter = (d - (ti->counter_value + 1)) % (ti->latch + 2);
- counter = (ti->latch - counter) & 0xffff;
+ int64_t d_post_reload = d - (ti->counter_value + 2);
+ /* XXX this calculation assumes that ti->latch has not changed */
+ counter = ti->latch - (d_post_reload % (ti->latch + 2));
}
} else {
- counter = (ti->counter_value - d) & 0xffff;
+ counter = ti->counter_value - d;
}
- return counter;
+ return counter & 0xffff;
}
static void set_counter(MOS6522State *s, MOS6522Timer *ti, unsigned int val)
@@ -102,11 +103,13 @@ static int64_t get_next_irq_time(MOS6522State *s,
MOS6522Timer *ti,
/* the timer goes down from latch to -1 (period of latch + 2) */
if (d <= (ti->counter_value + 1)) {
- counter = (ti->counter_value - d) & 0xffff;
+ counter = ti->counter_value - d;
} else {
- counter = (d - (ti->counter_value + 1)) % (ti->latch + 2);
- counter = (ti->latch - counter) & 0xffff;
+ int64_t d_post_reload = d - (ti->counter_value + 2);
+ /* XXX this calculation assumes that ti->latch has not changed */
+ counter = ti->latch - (d_post_reload % (ti->latch + 2));
}
+ counter &= 0xffff;
/* Note: we consider the irq is raised on 0 */
if (counter == 0xffff) {
--
2.26.3
- [PATCH v1 0/9] hw/mos6522: VIA timer emulation fixes and improvements, Finn Thain, 2021/09/23
- [PATCH v1 1/9] hw/mos6522: Remove get_load_time() methods and functions, Finn Thain, 2021/09/23
- [PATCH v1 2/9] hw/mos6522: Remove get_counter_value() methods and functions, Finn Thain, 2021/09/23
- [PATCH v1 3/9] hw/mos6522: Remove redundant mos6522_timer1_update() calls, Finn Thain, 2021/09/23
- [PATCH v1 4/9] hw/mos6522: Rename timer callback functions, Finn Thain, 2021/09/23
- [PATCH v1 5/9] hw/mos6522: Fix initial timer counter reload,
Finn Thain <=
- [PATCH v1 6/9] hw/mos6522: Call mos6522_update_irq() when appropriate, Finn Thain, 2021/09/23
- [PATCH v1 7/9] hw/mos6522: Avoid using discrepant QEMU clock values, Finn Thain, 2021/09/23
- [PATCH v1 8/9] hw/mos6522: Synchronize timer interrupt and timer counter, Finn Thain, 2021/09/23
- [PATCH v1 9/9] hw/mos6522: Implement oneshot mode, Finn Thain, 2021/09/23