Previous Thread
Next Thread
Print Thread
Page 60 of 80 1 2 58 59 60 61 62 79 80
Joined: Mar 2001
Posts: 17,250
Likes: 265
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,250
Likes: 265
From what Vas said, it could be that the delay isn't long enough on the AP2000's end. That would have to be measured though.

Joined: Feb 2014
Posts: 1,159
Likes: 209
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,159
Likes: 209
Ok, I stuck some code to measure the time between writes to C004 in the ap2000's e05a30 which change ack and busy:

Code
#define LASTPASSDIFFERENCE(t, name, func, str) \
  { static t staticlast##name; \
  t last##name = staticlast##name; \
  t diff##name; \
  t cur##name = func; \
  diff##name = cur##name - staticlast##name; diff##name = diff##name; \
  printf(#name": "); \
  printf(str "\n",cur##name-last##name);\
  printf("\n");\
  staticlast##name = cur##name; }
Code
        case 0x04:
                m_centronics_nack = BIT(data,5);
                m_centronics_busy = BIT(data,0);

LASTPASSDIFFERENCE(double,   WRITE_C004_TIME,   machine().time().as_double(), "time = %e");
printf("nack=%d  busy=%d    datalatched=%x\n",m_centronics_nack,m_centronics_busy,m_centronics_data_latch);

The timing looks like it takes at least 10 us:

(booting the combined graphics disk and just choosing 8 - new page (form feed)
Code
nack=0  busy=0    datalatched=0
WRITE_C004_TIME: time = 2.349610e+01

nack=1  busy=1    datalatched=c
WRITE_C004_TIME: time = 5.289714e-06   (5.2 us)

nack=1  busy=0    datalatched=c
WRITE_C004_TIME: time = 5.289714e-06     (5.2 us)

nack=0  busy=0    datalatched=c
WRITE_C004_TIME: time = 9.358724e-05            (93 us)

nack=0  busy=0    datalatched=c
it looks like it's actually quite long to drop the nack (the ap2000 must have hit an interrupt to slow it down a little)

[Linked Image from i.imgur.com]

trying to print a screen gets ESC K 18 01 (adds up to 0118 = 280 pixels wide) then 00 and it hangs reading from $c1c1

Code
nack=0  busy=0    datalatched=d
WRITE_C004_TIME: time = 9.358724e-05

nack=0  busy=1    datalatched=1b             ESC
WRITE_C004_TIME: time = 3.420003e-04

nack=1  busy=1    datalatched=1b
WRITE_C004_TIME: time = 5.289714e-06

nack=1  busy=0    datalatched=1b
WRITE_C004_TIME: time = 5.289714e-06

nack=0  busy=0    datalatched=1b
WRITE_C004_TIME: time = 1.228841e-04

nack=0  busy=1    datalatched=4b                   K
WRITE_C004_TIME: time = 2.583822e-04

nack=1  busy=1    datalatched=4b
WRITE_C004_TIME: time = 5.289714e-06

nack=1  busy=0    datalatched=4b
WRITE_C004_TIME: time = 5.289714e-06

nack=0  busy=0    datalatched=4b                         
WRITE_C004_TIME: time = 9.358724e-05

nack=0  busy=1    datalatched=18                18
WRITE_C004_TIME: time = 2.740479e-04

nack=1  busy=1    datalatched=18
WRITE_C004_TIME: time = 5.289714e-06

nack=1  busy=0    datalatched=18
WRITE_C004_TIME: time = 5.289714e-06

nack=0  busy=0    datalatched=18
WRITE_C004_TIME: time = 9.358724e-05

nack=0  busy=1    datalatched=1                 01
WRITE_C004_TIME: time = 2.307129e-04

nack=1  busy=1    datalatched=1
WRITE_C004_TIME: time = 5.289714e-06

nack=1  busy=0    datalatched=1
WRITE_C004_TIME: time = 5.289714e-06

nack=0  busy=0    datalatched=1
WRITE_C004_TIME: time = 9.358724e-05

nack=0  busy=0    datalatched=1
WRITE_C004_TIME: time = 5.853271e-04

nack=1  busy=1    datalatched=0                    00
WRITE_C004_TIME: time = 5.289714e-06

nack=1  busy=0    datalatched=0
WRITE_C004_TIME: time = 5.289714e-06

nack=0  busy=0    datalatched=0
WRITE_C004_TIME: time = 1.607259e-04

nack=1  busy=1    datalatched=0
WRITE_C004_TIME: time = 5.289714e-06

nack=1  busy=0    datalatched=0
WRITE_C004_TIME: time = 5.289714e-06

nack=0  busy=0    datalatched=0

Joined: Feb 2014
Posts: 1,159
Likes: 209
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,159
Likes: 209
I think I understand now what Vas was saying that the ack flip flop on the a2 PIC can't work since the strobe gets sent to the flip flop on the SD input which for the duration of the strobe makes it ignore the ack signal which is coming in on the CLK input.


Is it possible for things to get "jumbled" out of order? I put a bunch of printf to display the current machine time and it looks like it thinks the ack came in before the strobe was sent:



Code
nack=1  busy=1    datalatched=0
Time = 31.588152
[:sl1:parallel] /ACK=0
WRITE_C004_TIME: time = 5.289714e+00  usec ':sl1:parallel:prn:ap2000:maincpu' (20A6)

nack=1  busy=0    datalatched=0
Time = 31.588157
WRITE_C004_TIME: time = 5.289714e+00  usec ':sl1:parallel:prn:ap2000:maincpu' (20AC)

nack=0  busy=0    datalatched=0
Time = 31.588162
[:sl1:parallel] /ACK=1
[:sl1:parallel] Active /ACK edge
[:sl1:parallel] Setting acknowledge latch
[:sl1:parallel] Time = 31.588162
[:sl1:parallel] Diff = 0.000047
[:sl1:parallel] Read C0n0
[:sl1:parallel] Write C0n0=00
[:sl1:parallel] Latch data 00
[:sl1:parallel] Output /STROBE=0 for 1 cycles
[:sl1:parallel] Time = 31.588338                      <<< sent at .588338
[:sl1:parallel] Clearing acknowledge latch
WRITE_C004_TIME: time = 1.607259e+02  usec ':sl1:parallel:prn:ap2000:maincpu' (20A0)

nack=1  busy=1    datalatched=0
Time = 31.588323                                 <<<< so the ap2000 sees the data at .588323
[:sl1:parallel] /ACK=0
WRITE_C004_TIME: time = 5.289714e+00  usec ':sl1:parallel:prn:ap2000:maincpu' (20A6)

nack=1  busy=0    datalatched=0
Time = 31.588328
WRITE_C004_TIME: time = 5.289714e+00  usec ':sl1:parallel:prn:ap2000:maincpu' (20AC)

nack=0  busy=0    datalatched=0
Time = 31.588334
[:sl1:parallel] /ACK=1
[:sl1:parallel] Active /ACK edge
[:sl1:parallel] Active strobe prevents acknowledge latch from being set
[:sl1:parallel] Time = 31.588334
[:sl1:parallel] Diff = -0.000005                   <<<< time difference is negative???
[:sl1:parallel] Output /STROBE=1



Joined: Feb 2004
Posts: 2,622
Likes: 326
Very Senior Member
Very Senior Member
Joined: Feb 2004
Posts: 2,622
Likes: 326
The trouble with it is that it will ignore an ACK that comes in while strobe is active (this is how the hardware actually behaves - the strobe active signal is connected to an asynchronous set input of the acknowledge latch, so the clock input will be ignored). I had a quick look at what was going on, and the AP2000 was occasionally acknowledging a byte very quickly, before the end of the strobe pulse. If you’re seeing time move backwards, it could be an issue with the printer’s CPU taking a timeslice longer than the strobe timer interval.

How is the AP2000 implemented? At a quick glance, the only scheduled device seems to be the µPD7810. How does it generate the delay? Does it do something that just subtracts a large number of cycles in its execute loop?

Joined: Feb 2014
Posts: 1,159
Likes: 209
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,159
Likes: 209
Hi Vas,

I don't know enough about mame's scheduler to really answer how the upd7810 gets scheduled. I see that the upd7810 cpu has a member m_icount and it executes a certain number of instructions inside execute_run().


[Linked Image from i.imgur.com]

Looking at the schematic, it looks like the a2pic is getting a clock from pin 38 on the a2bus which is phi 1 I think, and that's labeled as C1M for 1Mhz.

When the a2pic sets the timer, it uses ticks based on clock() which comes in at 7M (which is pin 36 on the a2bus) which is perhaps 7x too fast.

Code
        m_strobe_timer->adjust(attotime::from_ticks(cycles, clock()));
        LOG("Now remaining = %.9f\n",m_strobe_timer->remaining().as_double());

Code
ack=0  busy=0    datalatched=3f
Time = 26.525418
[:sl1:parallel] /ACK=1
[:sl1:parallel] Active /ACK edge
[:sl1:parallel] Setting acknowledge latch
[:sl1:parallel] Time = 26.525418
[:sl1:parallel] Diff = 0.000026
[:sl1:parallel] Read C0n0
[:sl1:parallel] Write C0n0=3F
[:sl1:parallel] Latch data 3F
[:sl1:parallel] Output /STROBE=0 for 1 cycles
[:sl1:parallel] Time = 26.525616
[:sl1:parallel] Clearing acknowledge latch
[:sl1:parallel] Now remaining = 0.000000140      <<< finding out the remaining time on the timer immediately after setting
WRITE_C004_TIME: time = 1.737467e+02  usec ':sl1:parallel:prn:ap2000:maincpu' (20A0)

nack=1  busy=1    datalatched=3f
Time = 26.525592
[:sl1:parallel] /ACK=0
WRITE_C004_TIME: time = 5.289714e+00  usec ':sl1:parallel:prn:ap2000:maincpu' (20A6)

nack=1  busy=0    datalatched=3f
Time = 26.525597
WRITE_C004_TIME: time = 5.289714e+00  usec ':sl1:parallel:prn:ap2000:maincpu' (20AC)

nack=0  busy=0    datalatched=3f
Time = 26.525603
[:sl1:parallel] /ACK=1
[:sl1:parallel] Active /ACK edge
[:sl1:parallel] Active strobe prevents acknowledge latch from being set
[:sl1:parallel] m_strobe_timer remaining = 0.000013
[:sl1:parallel] attotime::from_ticks(1,clock()) = 0.000000140
[:sl1:parallel] clock = 7159090                          <<<< clock is 7M
[:sl1:parallel] Time = 26.525603
[:sl1:parallel] Diff = -0.000013
[:sl1:parallel] Output /STROBE=1
[:sl1:parallel] Read C0n0
[:sl1:parallel] Write C0n0=3F
[:sl1:parallel] Latch data 3F
[:sl1:parallel] Output /STROBE=0 for 1 cycles
[:sl1:parallel] Time = 26.525839
[:sl1:parallel] Clearing acknowledge latch
[:sl1:parallel] Now remaining = 0.000000140
[:sl1:parallel] Output /STROBE=1
WRITE_C004_TIME: time = 2.398682e+02  usec ':sl1:parallel:prn:ap2000:maincpu' (20A0)

nack=1  busy=1    datalatched=3f
Time = 26.525842


If I let it set the latch even though the strobe is still active, it seems to work perfectly.
Code
    if (m_strobe_timer->enabled())
        {
                LOG("Active strobe prevents acknowledge latch from being set\n");
                LOG("m_strobe_timer remaining = %f\n",m_strobe_timer->remaining().as_double());
                LOG("attotime::from_ticks(1,clock()) = %.9f\n",attotime::from_ticks(1,clock()).as_double());
                LOG("clock = %.9f\n",clock());
                LOG("Time = %f\n",machine().time().as_double());
                LOG("Diff = %f\n",machine().time().as_double()-time1);
                m_ack_latch = 1U;    // let it set the latch anyway
        }

030b_Combined_Enhanced_Graphics.dsk
[Linked Image from i.imgur.com]

Allowing the latch to be set, seems to work with Amperdump (treating the pic as an epson apl)
[Linked Image from i.imgur.com]

Joined: Feb 2004
Posts: 2,622
Likes: 326
Very Senior Member
Very Senior Member
Joined: Feb 2004
Posts: 2,622
Likes: 326
If the clock was seven times too fast, the parallel printer card wouldn’t work at all – it would strobe the bogus data latched on the dummy reads. That aside, if the clock was seven times too fast, there’d be almost no chance of it missing an acknowledge because the strobe pulse would be far too short. Why are you jumping to absurd conclusions and adding a hack rather than looking for a real solution?

Joined: Feb 2014
Posts: 1,159
Likes: 209
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,159
Likes: 209
Sorry Vas,

I guess it's just impatience mixed with a short attention span and a dash of ridiculous 8-).

How about this solution: the problem is that it gets out of sync because the timing is not in sync.

So in the e05a30 device why don't we make a time stamp of when the strobe falls and the data latch gets set.

Then when the ap2000 reads c002 to check the status, it won't report that the latch is true unless the current time is greater than that timestamp.
That would solve the time desync. It shouldn't report true until it "actually happens".

Code

static double input_strobe_time;


WRITE_LINE_MEMBER( e05a30_device::centronics_input_strobe )
{
        if (m_centronics_strobe == true && state == false && !m_centronics_busy) {

              printf("Centronics STROBE falling at %.9f\n",machine().time().as_double());
               input_strobe_time = machine().time().as_double();     // make a timestamp

                m_centronics_data_latch   = m_centronics_data;

                m_centronics_data_latched = true;
                m_centronics_busy         = true;
                m_write_centronics_busy(m_centronics_busy);
        }

        m_centronics_strobe = state;
}


uint8_t e05a30_device::read(offs_t offset)
{
        uint8_t result = 0;

        LOG("%s: e05a30_r([0xC0%02x]): ", machine().describe_context(), offset);

        switch (offset) {
        case 0x00:
                result = BIT(m_c000_shift_register, 23) << 7;
                if (!machine().side_effects_disabled()) {
                        m_c000_shift_register = (m_c000_shift_register << 1) & 0xffffff;
                }
                break;
        case 0x02:

                 if (m_centronics_data_latched && machine().time().as_double() - input_strobe_time > 0)
                         result = m_centronics_data_latched << 7;
                else
                           result = 0;
                break;



Joined: Mar 2001
Posts: 17,250
Likes: 265
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,250
Likes: 265
That's still not a real solution. The question is why the ap2000 is apparently violating it's own published timings, from what you've written. How does it come up with the timing for the ACK?

Joined: Feb 2014
Posts: 1,159
Likes: 209
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,159
Likes: 209
Here's the upd7810 code that checks the strobe, grabs the character from the latch and toggles busy and acknowledge:

[Linked Image from i.imgur.com]
Code
2092  LXI HL, $C002   puts the address c002 into the HL register
2095 LDAX (HL)    reads $c002 into A   (c002 = has data been latched)
2096 ONI  A,$80    now we check the high bit of A, if true we skip the next instruction
2098 RET        if no character, we return 

2099  DI  disable interrupts
209A LDEAX (HL++)    read c002 and c003 into EA register   c003 is the actual centronics data, HL now contains $c004
209C LDAX (HL)         read c004  (picks up busy set so bit 1 is set)
209D ORI A,$20            set bit 5 ack
209F STAX (HL)         store to c004  (set ack low, busy high)
20A0 NOP NOP NOP  3 nops
20A3 ANI  A,$FE         clear bit 0 busy (set busy clear)
20A5 STAX (HL)         store to c004
20A6 NOP NOP
20A8 ANI A,$DF       clears bit 5  ack
20AA EI
20AB STAX (HL)     store to c004 (set ack high)

from the time we read the latch at c002 to the first write to c004:

ONI = 7
RET (SKIP) = 4 when skipped
DI = 4
LDEAX (HL++) = 14
LDAX (HL) = 7
ORI = 7
STAX (HL) = 7

so 7+4+4+14+7+7+7 = 50 T states = (3 T states per clock)

> (1/14.7456e6) * (50*3)
1.0172526041667e-05 or 10 us from the instant we read c002


so there's 3 writes at 209F, 20A5 and 20AB

between the write at 209F and 20A5:

going by the instruction timing NOP = 4 ANI = 7 STAX = 7 we get 4*3 (for the 3 NOPS) + 7 + 7 = 12 + 14 = 26 T states
> (1/14.7456e6) * (26*3)
5.2897135416667e-06 = time = 5.289714e-06 (5.3 us)
>
and then the timing between 20A5 and 20AB
NOP NOP = 4 * 2
ANI A,$DF = 7
EI = 4
STAX = 7
so again 26 T states (8+7+4+7)

nack=0 busy=0 datalatched=0
WRITE_C004_TIME: time = 2.349610e+01

nack=1 busy=1 datalatched=c
WRITE_C004_TIME: time = 5.289714e-06 (5.2 us)

nack=1 busy=0 datalatched=c
WRITE_C004_TIME: time = 5.289714e-06 (5.2 us)

nack=0 busy=0 datalatched=c
WRITE_C004_TIME: time = 9.358724e-05 (93 us)

nack=0 busy=0 datalatched=c


It's interesting that it doesn't match the published specs of 12us but ~10.6 is still in the ballpark.

So if it reads c002 at the exact moment that the strobe is initiated and the strobe lasts 1us, there should be minimum 10 + 10.6 us (~20 us) before the ack rises to clock the flip flop, which is plenty of time.

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]


The real problem is that the apple2 can get ahead of the ap2000, so when the strobe is activated it sets the variable m_data_latched, which is read at c002 but the machine time is different when the ap2000 gets to run. The strobe is activated at time x, but when the ap2000 runs, it can see the latch at time x - some amount, so by the time it acknowledges, the apple 2 says "hey the strobe is still active", and throws it away because the machine time is different when it gets the write line callback.

Vas's code starts a timer for the strobe and if the timer is still active when it gets the ack it ignores the ack. So the strobe is supposed to be 1us, and the acknowledge should come 10us after that is initiated.

My solution was to timestamp the strobe activation (in the apple2's context) and then pretend it didn't happen until the time in the ap2000's context when it would actually be equal to or after the timestamp when it did happen.

Joined: Feb 2014
Posts: 1,159
Likes: 209
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,159
Likes: 209
Howabout if I put this in the ap2000's config:

config.set_maximum_quantum(attotime::from_usec(15));

This seems to work, I tried 5 and 15 usec and both seemed to work in limited testing.

Page 60 of 80 1 2 58 59 60 61 62 79 80

Link Copied to Clipboard
Who's Online Now
2 members (robcfg, Foxhack), 107 guests, and 0 robots.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,345
Posts122,350
Members5,082
Most Online1,283
Dec 21st, 2022
Our Sponsor
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!

Superior Solitaire
Powered by UBB.threads™ PHP Forum Software 8.0.0