[Coco] CoCo bitbanger does 115200 bps !
Boisy Pitre
boisy at boisypitre.com
Wed Apr 5 09:30:05 EDT 2006
On Apr 4, 2006, at 11:41 PM, George's Coco Address wrote:
> I'm a bit ignorant about just how fast the coco can process data.
> So, please be kind to me when I present my thoughts on this..
>
> If we were to process 115,200 bits per second through the bitbanger
> port, how many clock cycles and instructions per bit, would this
> require?
> I pushed this into my calculator and found that each bit from the
> bitbanger port takes about fifteen and a half clock cycles per bit
> when the coco is running at 1.78mhz. Machine code instructions take
> several clock cycles. Don't ask me how many, but I know it isn't
> one per cycle.
Your calculations are correct, as is your observation about cycle
count: every instruction on the CoCo takes at least 2 clock cycles,
unless you're running a 6309 in native mode where some instructions
are just 1 cycle.
The code below could be optimized for size, and there are most
certainly variations of how this could be done, but it amply
demonstrates how a CoCo 3 could receive a byte from a sender at
115,200 bps (cycle counts for each instruction are in parentheses):
* Mask interrupts
orcc #IRQ+FIRQ
* Wait for an incoming start bit
WaiStart lda >$FF20+2 (5) get byte that holds bit banger bit
lsra (2) shift in data bit 0 to carry
bcs WaiStart (3) branch if bit 0 was zero
clra (2)
nop (2)
* Bit 0
ldb >$FF20+2 (5) get PIA byte into B...
lsrb (2) shift bit 0 into carry...
rora (2) and roll Carry into hi bit of A
nop (2)
nop (2)
nop (2)
* Bit 1
ldb >$FF20+2 (5) get PIA byte into B...
lsrb (2) shift bit 0 into carry...
rora (2) and roll Carry into hi bit of A
nop (2)
nop (2)
nop (2)
* Bit 2
ldb >$FF20+2 (5) get PIA byte into B...
lsrb (2) shift bit 0 into carry...
rora (2) and roll Carry into hi bit of A
nop (2)
nop (2)
nop (2)
* Bit 3
ldb >$FF20+2 (5) get PIA byte into B...
lsrb (2) shift bit 0 into carry...
rora (2) and roll Carry into hi bit of A
nop (2)
nop (2)
nop (2)
* Bit 4
ldb >$FF20+2 (5) get PIA byte into B...
lsrb (2) shift bit 0 into carry...
rora (2) and roll Carry into hi bit of A
nop (2)
nop (2) additional NOP to catch up to the 4 .5 cycles
passed already
nop (2)
nop (2)
* Bit 5
ldb >$FF20+2 (5) get PIA byte into B...
lsrb (2) shift bit 0 into carry...
rora (2) and roll Carry into hi bit of A
nop (2)
nop (2)
nop (2)
* Bit 6
ldb >$FF20+2 (5) get PIA byte into B...
lsrb (2) shift bit 0 into carry...
rora (2) and roll Carry into hi bit of A
nop (2)
nop (2)
nop (2)
* Bit 7
ldb >$FF20+2 (5) get PIA byte into B...
lsrb (2) shift bit 0 into carry...
rora (2) and roll Carry into hi bit of A
rts (5)
The goal is to perform the nine "ldb >$FF20+2" instructions as close
to the middle of the bit transition time as possible. The code that
loops waiting for the start bit is as small as I can possibly imagine
and is 10 cycles in length. The bit is actually sampled by the ldb
instruction around cycle 4. Therefore, worst case is that the start
bit comes at cycle 5 (right after we sampled it) so we have to wait
10 cycles to see it and 6 more cycles to clear the final cycle of the
lda and the lsra/bcs instructions for a total worst case of 16
cycles. The best case is that the bit comes in right when we check,
meaning we stay in the loop for only 6 cycles. We get the average
case: (16 + 6)/2 = 11 cycles. To get up to the magic 15.5, I've
added 2 nops after the bcs. Additional tweaking by adding or
removing these nops may be necessary.
Things get a little more interesting if we want to implement a
timeout. Additional code in the WaiStart portion would be necessary,
adding to the best/worst/average case timings. Also, this code
doesn't take into account any additional code that would normally
'bsr' into this code to get a byte. There are about 18 additional
cycles that we can use up after the 'rts' since we aren't waiting
around for the stop bit. We've got enough time to store the data
byte in A somewhere and call WaiStart again to recover the next byte
(assuming the sending ACIA is going at full speed).
Code to send out a byte at 115,200 from the CoCo 3 would look
similar, except that the CoCo would be in control of the timing at
that point, not the other end. So while timing is critical here too,
there is no start bit to detect since it is generated.
I believe this is close to the approach Roger took with his code.
Roger?
> That being asked, does a "stock" coco at 1.78mhz have time to do
> this and still be able to store data onto a storage device? Or is
> this just displaying it to the VDG generator?
There's enough time to grab a byte and store it. The code is
idealized however. What is desirable in a normal situation is to
have some type of timeout so that if the start bit isn't detected
after a certain amount of time, the routine is exited. This is
especially true of OS-9; it would not be nice to just sit and wait
forever. Adding code at WaiStart to handle a timeout would push the
average case computed above outside of the critical 15.5 cycles. It
becomes a hit or miss proposition at that point.
> Can this be useable?
It depends upon the design of the protocol. The challenge I had when
developing DriveWire was to balance speed with reliability. At
57,600 errors can occur occasionally, that's why DriveWire uses a
checksum method on larger data packets to provide some degree of data
integrity.
> If so, I bet when other folks jump in and expand on it, this could
> be a winfall for OS-9.
When I developed DriveWire some three years ago, I analyzed
communications behavior at 115,200 on the bitbanger with code similar
to the above. Given the requirements that I placed on the desired
product, going that fast was just too problematic. For a disk access
product like DriveWire, reliability must trump speed or else data
corruption will become a reality.
For a DLOAD type protocol that Roger has talked about, then 115,200
bps could be workable. With DLOAD, no timeout is necessary and so
timeout code is not an issue. A simple protocol could be developed
to allow the sender to send out bursts of data of a predetermined
size that the CoCo would then consume. Some form of bi-directional
communication would need to be hashed out, and I think that's the
next challenge.
Boisy
More information about the Coco
mailing list