UART Tx bitbanging without a precise timer

A project log for Vintage Z80 palmtop compy hackery

It even has a keyboard!

esot.ericesot.eric 08/03/2021 at 02:196 Comments

HOLY MOLY this is /EASY/ to solve....

Send To Calculator, white wire: 0xAA,

After startbit edge, set caclulator red wire low, shift first (7th?) bit into C, wait for bit 7 edge input, load bit 7 to red wire, so on. Repeat for next byte. Profit. 

Sheesh. Nothing to it. And, automatically adjusts to the baud-rate, as well.


How come I've never heard of this????



$ cat /dev/ttyUSB0 -> FLASHcontents.bin

If you're forgetful like me, open another terminal window

$ while [ 1 ] ; do printf "%c" $((  0xAA )) > /dev/ttyUSB0 ; done

CTRL-C both when filesize stops growing.

The End.

I'd be utterly shocked if 9600 would be too much. So no need to remember stty...

(Of course, I'll have to rewire the DB9 or make an adapter)

(How long have I been looking for a precision timer?! And to think I was even starting to consider cycle-counting and adding nops! Nevermind the ADC-"counter" idea, which'd just be fun)



This thing's getting HUGE, and nowhere near as easy as I thought...


How does one implement a time-out without a timer? Or implement key entry to exit early with the interrupts disabled?

The Link Port, allegedly, is tested during key-scanning. I think that's in the timer interrupt. So, if misusing the link port, the OS thinks it's the start of a link.


Ok,now I've got a delayms (ish) for debouncing, which is necessary because the cable can't be attached before the port's set up... and arbitrary multisecond timeouts via 32bit counts are multiplying...

ALL of this would be nearly "easy" with a constantly running counter... but, then, I could use that for timing serial bits, in the first place.

Assembly is a PITA, too.


Stupid: write your own keypress test, give up on timeouts. Key (haha) factor... don't try writing/reading port1 without disabling interrupts, I think that's what i did wrong before... calc returned home like all was well, but keyboard was dead. Don't forget to reenable ints after!

...<sigh> twenty minutes, maybe... twenty+ lines deleted... hours of trying to implement timeouts n such... just press enter when ready. Twenty friggin minutes, at most is all it took. And to test.


ziggurat29 wrote 08/05/2021 at 17:44 point

Hmm.  I can't see the code, nor the circuit, but am I to understand that you simply shifted out the data flat-out with no delays?  And received it on a separate computer via a conventional serial port?
That's interesting, though if true, it seems like it would be relying on auto-bad capability on the receiving side.
Have you tried computer->calc?

  Are you sure? yes | no

esot.eric wrote 08/05/2021 at 21:30 point

err... no... one way data transfer from calc to comp. 

the computer Tx's 0xAA to the calculator through the white wire. (The graphlink has to be wired differently to the serial port).

The calculator watches each edge of 0xAA (start->1->0->1->0, 1, 0, 1->Stop)...and immediately after receiving each edge, transmits the corresponding bit.

It's like a loopback to the computer, which just happens to modify the bits being looped.

LOL @no code/schematic... I've been at it for /days/

  Are you sure? yes | no

Thomas wrote 08/07/2021 at 06:32 point

There could many variants to this scheme, e.g. implement something like the Dallas 1-Wire protocol using the PC's TX.

  Are you sure? yes | no

esot.eric wrote 08/07/2021 at 23:15 point

@Thomas... interesting. I'll have to look that up. In the meantime, it's a curious mental challenge to imagine how such a protocol might work, and fit into RS-232 at the same time! I think I've got an idea, requiring a packet protocol, and plausibly two or more Async bytes to represent one. 

  Are you sure? yes | no

Thomas wrote 08/08/2021 at 06:13 point

It's an interesting challenge, indeed. For the protocol Dallas 1-Wire might serve as a template.

It's perhaps possible to pack two bits in PC Tx transmission, like this:
Tx 00: xxx-__XX___Xx
Tx 01 xxx-__XX_XXXx
Tx 10: xxx-XXXX___Xx
Tx 11: xxx-XXXX_XXXx

In 1-Wire fashion reading would require polling by sending 00 transmissions:

Rx 00: xxx-___X____x

Rx 01: xxx-___X_zZzx
Rx 10: xxx-zZzX____x
Rx 11: xxx-zZzX_zZzx

Here is the meaning of the "graphemes":
x: PC Tx idle state of the serial line
-: PC TX start bit
_: PC Tx "recessive" (0)
X: PC Tx "dominant" (1)
Z: PC Rx "other side dominant" (1)
z: PC Rx "other side maybe dominant, time jitter (1?)"

If the time resolution on the Z80 vintage platform side (calulator) is poor it may be safer to transmit just one bit per link transaction.

  Are you sure? yes | no

esot.eric wrote 08/25/2021 at 01:23 point

@Thomas ohh, interesting... i was just trying to work out a means for making this bi-dir (two wire), and turns out it's very similar to what you describe, here... though, I tried to pack four bits in each transmission (two in two out) and i think that was a bit much to expect reliability. Of course! Send a different frame for rx vs tx!

  Are you sure? yes | no