6850 ACIA transmit write timing
6850 ACIA transmit write timing
Over in the Latest version of BeebEm thread, there's been an interesting discussion recently on saving of tape images and the timing of the 6850 ACIA.
I have a question about the 6850 TDR empty interrupt. If a write to TDR happens when TDR and TDSR are both empty (and so the TDRE bit is set in the status register), how long does it take for the data to move from TDR to TDSR, and when should the TDR empty interrupt fire?
At the moment I've implemented that on a write, TDRE is cleared for a short time, after which TDR is copied to TDSR and TDRE is set and IRQ asserted, but how long should TDRE be cleared for in this case?
I have a question about the 6850 TDR empty interrupt. If a write to TDR happens when TDR and TDSR are both empty (and so the TDRE bit is set in the status register), how long does it take for the data to move from TDR to TDSR, and when should the TDR empty interrupt fire?
At the moment I've implemented that on a write, TDRE is cleared for a short time, after which TDR is copied to TDSR and TDRE is set and IRQ asserted, but how long should TDRE be cleared for in this case?
Atom / BBC B with Music 5000/4000/2000 / Electron / A3000 / Master 128
Re: 6850 ACIA transmit write timing
Interesting question! One sub-question which turned up is whether the answer depends on the baud rate. (Indeed, maybe not just the baud rate but also the clock divider setting...)
And I suppose a question behind the question might be, how far in advance of the leading edge of the start bit does the interrupt fire, if at all, in case the outgoing byte is going to be cancelled by a reset.
And I suppose a question behind the question might be, how far in advance of the leading edge of the start bit does the interrupt fire, if at all, in case the outgoing byte is going to be cancelled by a reset.
Re: 6850 ACIA transmit write timing
I've hooked up the HP scope/logic analyzer to the 6850:
- Ch0 - TxCLK (pin 4)
- Ch1 - TxDATA (pin 6)
- Ch2 - nIRQ (pin 7)
- Ch3 - not connected
- Ch4 - 1MHzE (pin 14)
- Ch5 - nACIA (pin 9)
- Ch6 - RnW (pin 13
- Ch7 - A0 (pin 11)
I've set the scope to trigger on the 1st write to TxDATA at &FE09 (falling edge of Ch4 when Ch5=0 Ch6=0 Ch7=1)
Here's a close-up of the trigger event: You can see nIRQ is released ~1us after the write, indicating the TxDATA register is in use.
Zooming much further out now, the here are the two interesting measurements: nIRQ goes low 1.196ms after the TxDATA write.
TxD goes low 1.616ms after the TxDATA write, which is exactly half a bit time later.
Now, I look several different measurements, and the delay to nIRQ is quite variable. I've seen a range of values from 0.72ms to 1.24ms. So internally it looks the the write is being synchronised to the asynchronous baud rate clock.
It would be very interesting to measure this distribution in software.
Dave
The channels are connected as follows:- Ch0 - TxCLK (pin 4)
- Ch1 - TxDATA (pin 6)
- Ch2 - nIRQ (pin 7)
- Ch3 - not connected
- Ch4 - 1MHzE (pin 14)
- Ch5 - nACIA (pin 9)
- Ch6 - RnW (pin 13
- Ch7 - A0 (pin 11)
I've set the scope to trigger on the 1st write to TxDATA at &FE09 (falling edge of Ch4 when Ch5=0 Ch6=0 Ch7=1)
Here's a close-up of the trigger event: You can see nIRQ is released ~1us after the write, indicating the TxDATA register is in use.
Zooming much further out now, the here are the two interesting measurements: nIRQ goes low 1.196ms after the TxDATA write.
TxD goes low 1.616ms after the TxDATA write, which is exactly half a bit time later.
Now, I look several different measurements, and the delay to nIRQ is quite variable. I've seen a range of values from 0.72ms to 1.24ms. So internally it looks the the write is being synchronised to the asynchronous baud rate clock.
It would be very interesting to measure this distribution in software.
Dave
Re: 6850 ACIA transmit write timing
Here's a test program that measures the time between writing the Tx Data register and the "Tx Data Register Empty" bit in the status register being set:
The measurement runs 3,000 times and the program plots the distribution:
The vertical red lines are drawn every 100us.
So the delay varies roughly uniformly between about 420us and 1,260us.
At 1200 baud a serial bit is 832us, so this is between 0.5 and 1.5 bits.
Dave
Code: Select all
10 N=160
20 DIM code% 256
30 DIM times%(N)
40 FOR I%=0 TO 2 STEP 2
50 P%=code%
60[OPT I%
70.test
80 SEI
90 LDA #&85
100 STA &FE10
110 LDA #&35
120 STA &FE08
130 LDA #&FF
140 STA &FE68
150 STA &FE69
160 LDA #&02
170 STA &FE09
180.loop
190 BIT &FE08
200 BEQ loop
210 LDX &FE69
220 LDY &FE68
230 CPX &FE69
240 BEQ ok
250 LDY #&00
260.ok
270 STX &81
280 STY &80
290 CLI
300 RTS
310]
320 NEXT
330:
340 FOR I=0 TO N-1
350 times%(I)=0
360 FOR I=1 TO 3000
370 D=RND(20)
380 FOR J=1 TO D:NEXT
390 CALL test
400 T=&FFFF-(!&80 AND &FFFF)
410 PRINTI,T
420 T=T DIV 10
430 IF T>N-1 T=N-1
440 times%(T)=times%(T)+1
450 NEXT
460 MODE 1
470 SX=1280/N
480 SY=16
490 GCOL 0,1
500 FOR X=0 TO N-1 STEP 10
510 MOVE X*SX,0
520 DRAW X*SX,1023
530 NEXT
540 GCOL 0,3
550 FOR X=0 TO N-1
560 MOVE X*SX,0
570 DRAW X*SX,times%(X)*SY
580 NEXT
So the delay varies roughly uniformly between about 420us and 1,260us.
At 1200 baud a serial bit is 832us, so this is between 0.5 and 1.5 bits.
Dave
Re: 6850 ACIA transmit write timing
Nice one Dave - I ran on my Master and got the same results.
Do you set the baud rate clock and the 6850 divisor in that program? I tried *TAPE3 and *CO.BAUD8 but got the same results every time.
Do you set the baud rate clock and the 6850 divisor in that program? I tried *TAPE3 and *CO.BAUD8 but got the same results every time.
Re: 6850 ACIA transmit write timing
Yes I do..
In cassette mode the MOS writes a hard-coded &85 to the SerialULA, which actually selects the clocks for 19,200 baud.
Code: Select all
90 LDA #&85
100 STA &FE10
Code: Select all
110 LDA #&35
120 STA &FE08
- 00 = /64
- 01 = /16
- 10 = /1
- 11 = Reset
So to try 300 baud, change line 110 to:
Code: Select all
110 LDA #&34
You will also have to increase the delay between tests to at least 50ms, to allow the previous byte to be sent.
Dave
Re: 6850 ACIA transmit write timing
(What I'm wondering is whether we're looking at events the 6850 syncs to its incoming clock, or to the divided clock...)
Re: 6850 ACIA transmit write timing
I bet it will be the divided clock. If you want to see how good a job the chip designers did try sending a byte then switch the divider
Re: 6850 ACIA transmit write timing
I also think it's syncing to the divided clock; the delay range of 0.5 to 1.5 bit times has a varience of exactly one divided clock cycle.
I'd be very interested to see the graph at 300 baud.
You will need some extra delay between tests, so the characters don't run into each other, i.e. change
to maybe
I'm just guessing here; the transmission time of a character are 300 baud is ~33ms, so you maybe need to aim for no more that 20 tests/second. Maybe 10 tests/second being really conservative. Then the whole program would take ~5 minutes.
You will also need to tweak line 420 to extend the graph X axis range. Change:
to:
The red lines will now be every 500us.
I would expect the delay measurement to be 1.67->5.00ms.
Dave
I'd be very interested to see the graph at 300 baud.
You will need some extra delay between tests, so the characters don't run into each other, i.e. change
Code: Select all
360 D=RND(20)
Code: Select all
360 D=100+RND(20)
You will also need to tweak line 420 to extend the graph X axis range. Change:
Code: Select all
420 T=T DIV 10
Code: Select all
420 T=T DIV 50
I would expect the delay measurement to be 1.67->5.00ms.
Dave
Last edited by hoglet on Sat Jul 23, 2022 1:22 pm, edited 1 time in total.
Re: 6850 ACIA transmit write timing
Indeed, then, changing the clock divider from /16 to /1 shifted the histogram. But /64 just locked up...
Re: 6850 ACIA transmit write timing
Sorry, I got the divider's the wrong way around, the correct values (bits 1/0) are:
00 = /1
01 = /16
10 = /64
11 = reset
(actually the CPC Wiki gets it wrong)
So for /64 (300 baud) you need to write &36 to &FE08
Here's my graph at 300 baud, with the red lines every 500us: Dave
Re: 6850 ACIA transmit write timing
Thank you, this is so helpful. BeebEm hangs on your test program, so I've got some investigating to do. I'll report back when I know more...
Atom / BBC B with Music 5000/4000/2000 / Electron / A3000 / Master 128
- Diminished
- Posts: 1235
- Joined: Fri Dec 08, 2017 9:47 pm
- Contact:
Re: 6850 ACIA transmit write timing
Here is a slightly more user-friendly version of the Hoglet Histogram program, which allows you to select the baud rate to test. I have taken the liberty of labelling it version 1.1.
It is expected that this may be of use to people working on emulator tape writing support. (Like me.)
I've included a disc image, as well as the listing. (CHAIN "ACIATST").
It is expected that this may be of use to people working on emulator tape writing support. (Like me.)
I've included a disc image, as well as the listing. (CHAIN "ACIATST").
Code: Select all
1 MODE 7
2 PRINT CHR$129;"ACIA write-to-TXRE timing test v1.1"';CHR$130;"by hoglet"
3 PRINT '"Hit 1 for 1200 baud, or 3 for 300 baud."
4 REPEAT A$=GET$:UNTIL A$="1" OR A$="3"
5 IF A$="1" THEN BAUD=1200 ELSE BAUD=300
6 IF BAUD=1200 THEN D=&35:XDV=10:DELAY=0 ELSE D=&36:XDV=50:DELAY=100
7 IF BAUD=1200 THEN PRINT ';CHR$131;"1200 baud selected."''"Vertical red lines will be spaced every 100 us."
8 IF BAUD=300 THEN PRINT ';CHR$131;"300 baud selected."''"Vertical red lines will be spaced every 500 us."
9 PRINT '"Press any key to start.":A$=GET$
10 N=160
20 DIM code% 256
30 DIM times%(N)
40 FOR I%=0 TO 2 STEP 2
50 P%=code%
60[OPT I%
70.test
80 SEI
90 LDA #&85
100 STA &FE10
110 LDA #D
120 STA &FE08
130 LDA #&FF
140 STA &FE68
150 STA &FE69
160 LDA #&02
170 STA &FE09
180.loop
190 BIT &FE08
200 BEQ loop
210 LDX &FE69
220 LDY &FE68
230 CPX &FE69
240 BEQ ok
250 LDY #&00
260.ok
270 STX &81
280 STY &80
290 CLI
300 RTS
310]
320 NEXT
330:
340 FOR I=0 TO N-1
350 times%(I)=0
360 FOR I=1 TO 3000
370 D=RND(20)+DELAY
380 FOR J=1 TO D:NEXT
390 CALL test
400 T=&FFFF-(!&80 AND &FFFF)
410 PRINTI,T
420 T=T DIV XDV
430 IF T>N-1 T=N-1
440 times%(T)=times%(T)+1
450 NEXT
460 MODE 1
470 SX=1280/N
480 SY=16
490 GCOL 0,1
500 FOR X=0 TO N-1 STEP 10
510 MOVE X*SX,0
520 DRAW X*SX,1023
530 NEXT
540 GCOL 0,3
550 FOR X=0 TO N-1
560 MOVE X*SX,0
570 DRAW X*SX,times%(X)*SY
580 NEXT
- Attachments
-
- acia-write-to-txre-timing-test-hoglet-1.1.ssd
- (1.75 KiB) Downloaded 11 times
Re: 6850 ACIA transmit write timing
I did some testing back in 2010 and you can work out what frequency the ACIA is being driven at by timing how long it takes for the TxD register to empty, in order to determine whether to set the ACIA to div64 or div16. The timings bunch in two distinct non-overlapping ranges. See link.
The code resulted in:
The code resulted in:
Code: Select all
570 LDA #&15:STA mClock:JSR midiReset :\ Set to Divide By 16
580 PHP:SEI:LDY #4 :\ Time TxData clearing, X=0 from earlier
590 .initLp1:LDA #0:JSR midiOutWR :\ Send note=0,vel=0
600 .initLp2:DEX:JSR midiTxRDY:BEQ initLp2
610 DEY:BNE initLp1:PLP:TXA:AND #&40 :\ X should be about &B0
620 BEQ initClock:INC mClock :\ If not, use Divide By 64
630 .initClock
...
790 .midiReset
800 LDA #3:JSR midiReset2:LDA #&15
810 ]:mClock=P%-1:[OPT P*3+4
820 .midiReset2
830 STA &FCF0:RTS
...
1950 .midiOutWR
1960 STA &FCF1:RTS
1980 .midiTxRDY
1990 LDA &FCF0:AND #2:RTS
Code: Select all
$ bbcbasic
PDP11 BBC BASIC IV Version 0.45
(C) Copyright J.G.Harston 1989,2005-2024
>_