[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC 07/10] hw/mos6522: Fix initial timer counter reload
From: |
Finn Thain |
Subject: |
Re: [RFC 07/10] hw/mos6522: Fix initial timer counter reload |
Date: |
Sat, 28 Aug 2021 10:46:10 +1000 (AEST) |
On Wed, 25 Aug 2021, Mark Cave-Ayland wrote:
> On 24/08/2021 11:09, Finn Thain wrote:
>
> > 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 5b1657ac0d..0a241fe9f8 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)
> > @@ -103,11 +104,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) {
>
> I think the code looks right, but I couldn't see an explicit reference to this
> behaviour in
> http://archive.6502.org/datasheets/mos_6522_preliminary_nov_1977.pdf.
Yes, that datasheet is missing a lot of information.
> Presumably this matches what you've observed on real hardware?
>
Yes.
- Re: [RFC 04/10] hw/mos6522: Rename timer callback functions, (continued)
- [RFC 08/10] hw/mos6522: Call mos6522_update_irq() when appropriate, Finn Thain, 2021/08/24
- [RFC 05/10] hw/mos6522: Don't clear T1 interrupt flag on latch write, Finn Thain, 2021/08/24
- [RFC 07/10] hw/mos6522: Fix initial timer counter reload, Finn Thain, 2021/08/24
- [RFC 03/10] hw/mos6522: Remove redundant mos6522_timer1_update() calls, Finn Thain, 2021/08/24
- [RFC 10/10] hw/mos6522: Synchronize timer interrupt and timer counter, Finn Thain, 2021/08/24
- [RFC 02/10] hw/mos6522: Remove get_counter_value() methods and functions, Finn Thain, 2021/08/24
- [RFC 06/10] hw/mos6522: Implement oneshot mode, Finn Thain, 2021/08/24