Close

UARtoT Functions -Flash Transferred

A project log for Vintage Z80 palmtop compy hackery (TI-86)

It even has a keyboard!

eric-hertzEric Hertz 08/21/2021 at 04:3922 Comments

Brief recap:

The ultimate goal of this project was long long burried under tangent after tangent that each seemed almost certain to take only a few hours at most, and wound-up taking weeks, instead.

I piggy-backed a 256K FLASH chip on the TI-86's OTP ROM what must've been months ago for the sake of being able to run full system backups while I was doing gnarly testing of hardware/software ideas that could easily result in "Memory Cleared" on countless occasions... which would be quite a setback, since I'm writing the software /on/ the calculator...

Yes, I understand I could back it up regularly to a computer. That's another story. But, sufficed to say that's what I've been doing for backups these past weeks, instead of backing up to the flash, which is already installed and functioning.

Why?

Because I found that chip in my long-ago-scavenged sorted-parts bin, and realized that over the past few years I've dug out old PCBs that'd been scavenged and realized many times that I might like to get some of them functional again someday. So, somewhere in there is one missing its firmware... and this chip might contain it. 

So, no idea /what/ it came from, I decided to dedicate a few /hours/ to backing up its contents.

Three (more?) WEEKS later, it's /finally/ done.

What's it from? Apparently it's the BIOS from a Compaq Presario... which, frankly, even if it's from my once-beloved P150 laptop (as opposed to, say, some random desktop someone passed onto me), I certainly wouldn't've gone to all that effort for it... (Oddly, I don't see many strings in there at all... basically just "Phoenix BIOS" and "Compaq Presario"... what about all the settings /in/ the BIOS Setup program?!)

OTOH, in the process I managed to give the TI-86 a new trick... it can now transmit RS-232-compatible serial data through the "Windows Only" "blacklink" graph-link cable, which was originally designed to be bit-banged from Windows via the handshaking lines.

Yep, that's right... My TI-86 has UART capability, now... and it was "only" a matter of rewiring the blacklink's DB-9 through a passive adapter and a little software.

OK, not quite... The TI-86 doesn't seem to have a high-speed counter/timer/clock accessible via software. The only thing like that is an interrupt about 200 times a second... and, I'm not too interested in 200Baud communication. So, really, not being a z80 wiz, bitbanging asynchronous serial frames would be quite difficult.

I actually spent quite a bit of time near-certain there must be a higher-speed counter accessible /somewhere/, and dug all around the ports, for many days, to no avail...

Then a moment of clarity... Hey, I need a clock, why not use the computer as the clock?

So, now, the computer transmits 0x55, which results in 10 alternating bits (including start and stop) and the calculator looks for those edges and transmits its own serial frames/bytes synchronized to those edges.

I have this weird feeling I have, yet also haven't, heard of this before. I mean, it's so friggin' simple, surely others have done this... but, I can't at all think of /where/ I might've heard of it. 

Regardless, it /does/ work, and surprisingly well. I transferred all 256KB of the Flash twice without a single bit error. 4800baud was more than fine for my needs. But that speed-choice was a remnant of something else, by no means the limit. Interesting side-effect of this technique, the other device doesn't care what the computer's baudrate is, as long as it has enough processing time. Kinda groovy.

So, I call it a UARtoT. Receive 0x55, Transmit whatever you want. Unidirectional, but that's all I needed.

...

Ugh... now why did something /so/ simple throw me off-course for WEEKS?!

Lemme put it this way: 

DO NOT ATTEMPT TO PROCESS BINARY DATA WITH BASH.

NO! You CANNOT store every possible combination of 8 bits in a bash variable. No. Don't even try it. Even if you think you've found "the trick" I assure you you've only found one workaround for only one of the tricks bash has up /its/ sleeve. I doubt it's even possible, but /if/ somehow you managed to get every byte value storable in a bash variable, then surely you haven't considered every /two-byte/ combination... "But, what? I'm only reading ONE byte at a time!" HAH HAH HAH! That's what YOU think!

Convert it to a two-byte string, hex, seriously, using hexdump and redirection.

Seriously, DO NOT take the above as some sort of challenge, like I foolishly did. I didn't have the luxury of someone's saying it wasn't possible. I'm Trying To Save You DAYS Of Futile Aggravation.

Surely there were other reasons this took so long...

Oh yeah, stty is /barely/ comprehensible, but also has a tremendous impact on binary data.

Oddly, the code I wrote-up in assembly, of all languages I know near ziltch about, apparently worked perfectly all along, from the start. Hah!

...

I'm sure there was /plenty/ more that turned my three hour tour into weeks, it's probably rambled-about in past logs. This was all supposed to be a brief explanation about the joy of FINALLY having this part of the project (which was never really /part/ of "The Project") finished so I can actually get to the parts I'd originally had in mind... 

Now, what were those?

I suppose some of this helps that stuff, anyhow... all sorts of new libraries... lots of new details about the calc's hardware and hackability...

It really hasn't at all sunken in that I've finally reached some huge milestone.

..

Surely I shoulda been calling it UARtoST...

Discussions

ziggurat29 wrote 08/21/2021 at 16:18 point

congratulations on your dumping of that flash -- I know this has been bugging you for some time.
I don't think you've never mentioned explicitly the part number of the flash chip that you have that can piggybacks onto the existing OTP.

  Are you sure? yes | no

Eric Hertz wrote 08/21/2021 at 18:38 point

hmm, good call...

The OTP in mine is an Atmel AT27C020, as I recall... And I just happened to have an AT29C020 FLASH in my parts-bin.

I actually grabbed four different pin-compatible PLCC FLASH chips, and weeded it down to two based on voltage requirements. (One was 3.6V, the other required 12V). The third I weeded-out on account of its strange sector-scheme which meant in some locations no less than 8K would have to be (re)written at a time. This guy takes 256byte sector-rewrites.

Later research revealed that the "engineering samples" of TI-86's have that same AT29C020 FLASH in the place of the OTP. So, I guess it's a good choice!

Note, of course, piggybacking a PLCC means bending out the pins, and in this case keeping a couple separate for hand-wiring elsewhere e.g. /CS and /OE (Though, It /may/ be that the ROM's /OE can be toggled via a port bit, then could be used for the FLASH as well... I haven't tried it... disabling that for FLASH-writes would mean not being able to execute ROM function-calls, nor interrupts, which I kinda thought might get me in trouble)

I might be experiencing a bit of post-project-partum-depression, thankya for the congrats, that helps a bit.  :)

  Are you sure? yes | no

Eric Hertz wrote 08/21/2021 at 21:07 point

oh, btw... since I recall your looking for alternatives to a graphlink cable...

This "UARtoST" thing should work fine connecting the link-port directly to 5V-serial Tx/Rx e.g. like those USB-serial arduino deelybobs. I didn't go that route because mine's 3.6V, and I don't have my zeners and resistors here with me. (Software-wise, it's merely a matter of inverting the bits).

But... of course... this is serial, not the TI-link protocol, and requires getting software to run it on there in the first place.

I've some /vague/ ideas of how to make this Tx/Rx wiring TI-link compatible... but it requires some glue-logic and would require an addon link library to tilp. Makes for a bit of a chicken/egg problem.

Though, on that note, I've another /vague/ idea of how to make this UARtoST thing bidirectional without a /huge/ amount of assembly... in which case, if it's somehow possible to patch-in that code to override the normal two-bidir-wire low-level link protocol (while still using the high level linking packet protocol), like, for instance how the timer interrupt can be patched, then it /might/ be small-enough to hand-type the hex values of the assembly instructions... in which case, then, all you'd need is one of those TTL-serial-USB doolybabs wired directly to the 2.5mm phone plug, and a mod to tilp's connection-library, which'd be just a download/compile matter.

But: gotta find out how difficult it'd be to override/patch the low-level linking protocol, first.

  Are you sure? yes | no

Eric Hertz wrote 08/21/2021 at 22:00 point

_altslinkptr appears to be a thing... per your RAM detective-work, (found via google, no less, nice job!) and there's a system flag for enabling it... so, then, I guess somewhere in there a disassembly of the real link-handler might reveal another functioncall or twelve to actually process the commands and respond at a higher packet-level... so, then, if those can be found i think it could be done over serial with Tx/Rx.

best I've got so far is that the link ports are tested for a low wire in the getkey(?) function (isn't that handled in the interrupt?)... so, from there must be a call to the link handler.

http://jgmalcolm.com/z80/advanced/syst

https://wikiti.brandonw.net/index.php?title=83Plus:OS:Hooks

From the looks of it, the 86 may be similar...

https://wikiti.brandonw.net/index.php?title=83Plus:Hooks:9B78

  Are you sure? yes | no

ziggurat29 wrote 08/22/2021 at 00:39 point

yes, most (all?) of the link stuff is on ROM page 9. I disassembled that to study the protocol a bit, though I was coming bottom-up from the port I/O, so I haven't gone up the call chain enough to understand the where and why of the alt slink stuff.  I did see the (silly) checksum being computed, though, so possibly some unexplored code nearby.
RAMP0:D3C7   _alt_slink_exec:ds 200
Is a buffer presumably for some user-installed hooking code.
The iy+35 seems to be the flags byte for activating several of the 'alt' routines, and bit 4 seems to be the 'alt slink' enable bit.
At 
ROMP9:48A0 FD CB 23 66                 bit     4, (iy+35)
the bit is tested, and if set, then the checksum is validated, and if it passes, then the code in the _alt_slink_exec is CALL'ed.  Otherwise all that is skipped.
I am guessing 'slink' means 'silent link' which was a feature added later on whereby you don't have to explicitly go through the menu to set the calculator to receive/send.  It appears to work through the keyboard scan code at interrupt time by checking the levels on the port to see if someone started a transmission (either line pulled low).
The flash chip seems to be out-of-production (I think), but maybe I can find some pulls on eBay or something.  It will be sweet to have flash capability.  I guess I should find the datasheet.  Will we be able to program in circuit?
I couldn't get tilp to run on my Windows, so I may have to try Linux.  The USB seems to be a custom device class, and the UART seems to be less uart and more bitfiddling signal lines, but I could be wrong.  This may throw a monkey wrench into my BluePill aspirations, but I haven't had time to look at it.  I did figure that for safety I'm going to have to make an interface circuit, though.  Straightforward, but it's not /quite/ as nice as directly connecting the BluePill without a separate board of stuff.  [BluePills have shot up in price! I guess it's good that I have a little pile of them.]
I have to rummage for a T6 torx before I can open this up, anyway.

  Are you sure? yes | no

Eric Hertz wrote 08/22/2021 at 03:25 point

oh, wow.. somehow I'da thought things like the AT29C020 would be around for quite some time... JEDEC-standard-n-all...

Well, its pinout is pretty standard, I'd be shocked if there's not something 5V compatible still made... yes, I've already done a sector-write from in the calc... it is /not/ supported by the OS,mind you ;)

BluePill, somehow I had it in mind you were talking about an SBC, ahhh a microcontroller! Well, yeah, that'd work! Are you thinking to use it like a custom graphlink to a regular computer, then? 'Spose if you wrote it in Arduino's IDE then it wouldn't matter much which uC was used... if someone else planned to make one. Are you saying you bought a USB graphlink? :/ I was under the impression both that and tilp were well suited for Windows... have you considered looking for TI's actual software?

Good call re: slink... was wondering what that s was all about. 

I did some disassembling earlier... the other direction, from _getkey. Have yet to find port I/O, neither for the link nor the keypad... but always learn something disassembling! Though, so far I'm pretty much at a loss for what it actually /does/. Heh. Something about copying a 9byte buffer, and i did see some IY flags. It's probably that "silly checksum" catching me up again.

... oh. Duh... i saw hl being loaded with a RAM address for jumping/calling and thought "wait a minute... that can't be right". Of course.... the alt function.

  Are you sure? yes | no

Eric Hertz wrote 08/22/2021 at 10:35 point

more disassembling... wee! Oh hey, i discovered the online disassembler has a save to text file. So much easier to understand when you can add comments... of course, I didn't discover /that/ feature until after buying a new spiral notebook.

Whatever rabbithole I wound-up in via getkey seems a bit backwards to me...

Looks to me pretty much the first thing getkey does is /transmit/ a packet identifying itself.

This seems weird to me for /many/ reasons... not the least of which is the large timeouts that would have to be waited-for during /every/(?!) Interrupt, if there's no attached device to ack. So I think I'd better go back up a few function-calls to see what's next.

There seems to be a general-purpose error-handler, I think you mentioned before, that I need to look into, too. Because, maybe the whole point is that the other device /usually/ would already have started its transmission /before/ the getkey machineID transmission... so, then, the error handler is /really/ the packet-receiving function, that happens to be called if there's a transmission-error. This is weird, hard to explain, but sorta makes sense... dual-purpose: if the attached device isn't talking, then tell it the calc is attached every so often. If it /is/ talking, then the next time the calc tries to talk it'll get immediately interrupted.... and that's how it'll know to start receiving. Weird. But the only explanation I can think of from what I've seen thus far.

As far as hooking, though... i mean, it looks like there's essentially a "Transmit Byte" function which gets called directly from the higer-level protocol stuff... getting complicated, now... basically those functions would have to be modified to call a different TxByte function. I highly doubt that could be done in a few hand-enterable hex values :/ spose I shoulda seen this coming.

  Are you sure? yes | no

ziggurat29 wrote 08/22/2021 at 15:13 point

maybe that chip is still around, and just not popular with the vendors.  it showed up as 'discontinued' from the few I checked.
Yes, I was hoping to use the BluePill to make it a GraphLInk knockoff, since that is to wit a discontinued product and anyway is pretty spendy.  The BluePill /used/ to be $3, but now it seems that the price has doubled.  Maybe the covid chip shortage I heard about?
I did find TI's software and it does run, but again it is a custom USB device driver rather than say a USB CDC device, so I'd have to understand all that stuff.
Yes 'silly checksum' is silly.  Instead of 'sum all the bytes' it sums just six of them spread around in the buffer, and calls that a checksum.  I suspect this is a best effort spot check done this way for speed.  The slink one is done at ROMP9:48A6, and a similar one is done for the ISR hook at ROM:0040, and probably is done for the other checksummed buffers.
The '9 byte buffer' is some header.
I haven't seen a getkey that transmits, but by now I have so many getkey routines strewn about that I'm probably not looking at the specific one you mention.  I did see in the one I looked at that it checks at the end if the slink is quiescent, and if not, it does something.  It did this near the end of its implementation.
Yes there is a general-purpose error handler that the sendByte and receiveByte routines that I have seen will jump to; essentially resetting the calculator state (not erasing stuff; not that far reset).  This suggests that those routines may not be helpful in most cases.  I would rather have them return to the caller with a flag set and then let the caller decide what to do in an error situation.  But I'm sure these routines are internal stuff that TI didn't really expect other folks to use themselves.

  Are you sure? yes | no

Eric Hertz wrote 08/22/2021 at 21:29 point

LOL sheeeiiitttt...

Apparently _getkey @ 55aa is /NOT/ _get_key @ 4068

But, now im even more confused, because _get_csc is /also/ at 4068 according to my inc file.

55aa /almost/ looks like it's for the TI keyboard peripheral I'd heard of.

Many hours, am drained... i'll take a look at your latest in a bit

  Are you sure? yes | no

ziggurat29 wrote 08/23/2021 at 00:13 point

yeah I know.
The _getkey() I know is at ROM page 13, at 55AA, which then thunks to ROM page 0, at 3E39          (which I call impl_getkey), which then thunks to ROM page 10, at 68B7, (which I call impl_getkey_D68B7), and then around ROM page 10 at 68FE it checks for quiescence on the link port.  If it is quiescent, then it moves on and ultimately calls 0245 (which I call impl_get_key; lol!) which is a very simple routine that gets (drum roll) the key.  If the link is /not/ quiescent, it does some other stuff on ROM page 9 at 4855.  I haven't looked at that, but page 9 does have most of the link impl, so who knows. Oh, there's some silly checksum in there.
Confused?  I am!  lol, it's twisty to disassemble with this paging scheme!
I think _get_csc is different, the scan code, but what do I know anymore?
If you want my current work I can send it, but it is very very much a work in progress.
Aside from that, I'm thinking it's about time to kick Ghidra's tires.

  Are you sure? yes | no

Eric Hertz wrote 08/23/2021 at 04:51 point

!!! Whaaat???

55aa is where i started, i don't see anything /other/ than link-port stuff going down that path! No keymatrix scanning, no checksums, nada. Just loading up what looks like a machine-ident, then sending it.

Now I'm totally lost.

  Are you sure? yes | no

ziggurat29 wrote 08/23/2021 at 14:50 point

It's so easy to get lost in these paged/overlaid systems.  You might be on ROM page 9 instead of page 10.  The addresses don't mean much without also the page number.

If it helps, please find my current work (quite incomplete) uploaded as "ti86-20210822a.zip".

Some things about the listing:

*  because of the paged/overlaid design, I imported the ROM not as one big block, because addresses would be harder to follow.  What I chose to do was a hack, and abuse the 'segments' feature of the disassembler to create 'segments' that represent the ROM pages (and RAM, but I haven't needed that).  By tweaking the segment start address, I can keep the address of each of those ROM chunks at the 4000h offset.  This is not perfect, but it helps a little.

*  because for user ASM routines page 13 is mapped in at 4000h, I went ahead an mapped page 13 at that location instead of way out there.  So ROM page 0 and 13 are where expected, and all the other pages have to get by out in segment land.  But I did name those segments ROMP1 - ROMPC so you can see in the listing what's what.  The main ROM page area (which here is pre-loaded with page 13) is called ROMpage because I started out that way and hadn't devised the segment scheme yet.

*  I chose to stick with the names that were publicly known in existing headers even though they are not to my taste.  This helped when researching other's work which often uses these well known names.  For internal functions that are not publicly documented, I used my own style.

*  In particular, because this design uses a lot of thunks and page flipping, I use the prefix 'impl' for 'implementation', and then the suffix of the public name for which the code implements.  Even further, since the thunks to page 0 often then page-call out to the real implementation on another ROM page, I extended that further to include the address on the ROM page.  This was just to disambiguate.

So, with that background, we can trace _getkey():

[I have included line numbers so you can follow along, but know that those will only be valid for this listing 20210822a, which will be out-of date the moment I do more work]

*  It starts on page 13:  (at line 34856)
ROMpage:55AA _getkey:

*  That just thunks to page 0:  (at line 20671)
ROM:3E39 impl_getkey:

*  That is just ye olde bank call to page 10 ('a'):  (at line 193578)
ROMPA:68B7 impl_getkey_D68B7:

*  Now we do real work.
...alt_sqrt ???
...impl_showCursor
...lock APD ???
...ROMPA:68CD call 245h  ; impl_get_key

*  OK, now we're getting somewhere interesting.  ROMP0 call (at line 725)
ROM:0245 impl_get_key:
...di
...read and clear a _kbdScanCode
...clear an unknown flag (possibly 'have key to read' given what we're doing)
...ei, and out

The di/ei are needed because keyboard matrix scanning is done in the ISR (ROM:0038 _IM1ISR:) down lower at ROM:00A9, which calls impl_kbdScan that does the work.  (Incidentally, at the start of _IM1ISR you can see the first 'silly checksum' I found.)

*  OK, that was kind of mundane -- we just plucked a character from a single character buffer.  So back to ROMPA:68D0: (at line 193591)
...fiddle with some mystery flags
...see if the ON key has been pressed.  If it has, do something at sub_29A5, which then calls to page 13 at impl_sub_5A70, which is not in existing documentation and I don't really know what any of that does yet, but since there's a conditional return after that call, it probably checks something.  If it has not been pressed, if the mystery call clears the Z flag, then press on.
... some more stuff, another check for the ON key, a magic flag that causes some stuff to be skipped in the ISR that has to do with activating keyboard rows, and then!
...ROMPA:68FE in  a, (7)   (at line 193617) we check if the Link port is quiescent.  If it is we do some stuff (looping back?) and if it is not, we do some other magikry, and get the keyboard character from a completely different location (0C005h) _kbdkey and return that if it is non-zero.  This might mean that the key presses are being stuffed from link port data in certain cases.

Incidentally, ROM page 9 is where a lot of link stuff happens.  All the other pages that touch port 7 really seem to either be in resetting the calculator to a known (quiescent) state, or peeking to see if someone has started a transaction (because the lines do not read quiescent; i.e. not '3') and if so set flags or call out elsewhere.

ROMP9:4255 linkReceive_C4255 (line 177358) you can see how to read a byte.  You can go up the call chain to some places that are using that to fill incoming buffers (headers are all I have disassembled yet).

ROMP9:40F4 linkSendByte_C40F4: (line 177061)  sends a byte!  Interestingly there is linkSendByte_C40F3 which also sends a byte, so I guess they couldn't standardize on A or C being the calling convention.  But there's ROM to spare on that page.

So, that's the walkthrough.  This paged design is much more difficult to disassemble, especially since it bops about so much.  A text editor with bookmark and easy highlight-and-search capability makes it easier to follow.  I use Notepad++, but that's Windows, and if you're puissant with vi then you probably can do even greater things.

HTH, but then again maybe I've given you a migraine.

  Are you sure? yes | no

Eric Hertz wrote 08/23/2021 at 17:27 point

dagnabbit... I gotta work through this...

55AA, when page d is mapped:

0x0d-> A14+

55AA=0101 0101  1010 1010

A15-14 get removed

55AA[addrBus]=01 0101  1010 1010

(what happens to A15-14=01? They select the z80 page mapper, in this case the one configured by port5, which is loaded with 0x0d)

Then 0x0d=0000 1101 -> A14+

00 0011 0101 0101 1010 1010

Yeah, I think I got this right...

And the ROM is at CS0, so A21-20=0 (bits 7-6 in port5) so needn't be considered...

00 0011 0101 0101 1010 1010

0  3  5  5  A  A

Is what's written to the VLSI's external address bus, directly wired to the ROM

Pretty sure that's right... I made note, in numerous such paper calculations, how it seems they chose certain commonly-used pages such that the "math" was easy...

Page D, simply tag "3" to the address. AS Long As it's mapped with port5 (not 6) into the range 0x4000-0x7fff

Since, again, D ends in 01, and, again, 01 selects the port5 page mapper.

(IF they'da chosen C or E, this scheme wouldn't work)

So, in the case where a ROM page number is selected that has its lowest two bits=01, (page 1, 5, 9, D) it's easy to look up the address in the ROM image, it's just the higher two bits shifted right twice, tacked onto the z80 address.

Page 1 -> 0001 >>2=00=0

Page 5 -> 0101 >>2=01=1

9 -> 1001 -> 10=2

D -> 1101 -> 11=3

So, page1 mapped-in, then a jump to address 0x6789 jumps to 0x006789 in the rom image

Page5 mapped-in, then a jump to 0x4567 is 0x014567 in the ROM image

PageD 55AA -> 0x0355AA.

It's not that those two lower bits in D aren't messing with the mapper (they do, which is why this only works with pages 1,5,9,D) it's that they /match/ the upper two bits in 0x55AA (or any address in that mapping range 0x4000-0x7fff)... thus making it easier to "math"...

Really quite clever of them... if I've got this right.

But, then, what about the other pages, say 2?

2=0010, 10 doesn't match the upper two bits of the range 4-7...

Math... can I do it?

Page2 0x4567

Uhh...

Ok...

The upper two bits in 4 are 01, those choose the port5 mapper, it's loaded with 2, 10 replaces the upper two bits of 4...

So, 1000 instead of 0100... so 0x8567 in the ROM image. Ugly math... i think that's why they chose page d for the jump table.

Lemme see if I can do page C... 0x5678

C=1100

3 ...

Then 00 in the upper two bits of 5, 0001 =1

0x31678 I think...

Or page F... 0x4567

F    4

1111, 0100...567

||\\   xx| |    ||||||||

11 11    00...567

||  ||//         |||||||

3 C          567

yeah, that's kinda gnarly, especially considering "the trick" almost makes it seem like this is in page D. Heh!

...

My 0x355AA calls 0x3e2b...

OTOH, it's plausible our rom images differ. Maybe due to how it was downloaded (how'd they map it when dumping?).

Yours makes more sense to actually be a getkey routine... mine looks like it does nothing more than send a machine-id packet through the link port.

Maybe I should use my new UARtoST to dump my own ROM. Heh!

...

Sheesh... now I'm trying to follow through yours step by step and even the first byte doesn't match... starting to think i got a funky rom dump.

  Are you sure? yes | no

ziggurat29 wrote 08/23/2021 at 18:46 point

there were, to wit, something like 5 known versions in the field (1.2-1.6).  My ROM image came off the web  (https://tiroms.weebly.com/) because I didn't have a physical device at the time, and that one is 1.3.  My recently-acuqired physical device is 1.6.

[2nd] [MORE] [ALPHA] [6]

Press [EXIT] after you take a gander.

There will be discrepancies between versions, of course.  It will be interesting to have your dump if it is not 1.3.  I haven't bothered to dump mine because I don't have a link yet.

The page numbers are super straightforward, but I'm looking at it from software.

But maybe just try to follow along my discussion above with the paper listing I sent.  It will all make sense.  Then if you want to do the same for your own ROM disassembly, it will be pretty much the same, just maybe some address and code differences here and there.

  Are you sure? yes | no

Eric Hertz wrote 08/23/2021 at 20:21 point

will do... i've got a bit of catching-up in your earlier comments as well. Errands today, so it might be a few. Thanks for the reading/ learning material!

  Are you sure? yes | no

Eric Hertz wrote 08/24/2021 at 20:55 point

well, sheesh... I was dang-certain the rom-call thing (cdcb28 on my rom 1.2, cdd928 on yours, impl___bank_call, at line 20673) uses the three bytes /above/ the call as the page/address... I bet that sent me down the wrong path... sheesh.

Ok, still following... after I look at 28d9...

...

LOL, here it is in my notebook... three bytes /after/ the call (inc de). I guess I was remembering dec hl, used to address/modify the stack.

...

  Are you sure? yes | no

ziggurat29 wrote 08/24/2021 at 22:52 point

Oh, now that would definitely send you barking up the wrong tree; lol.  Sorry you had to pursue the undomesticated aquatic fowl, unless that's just your thing!

  Are you sure? yes | no

Eric Hertz wrote 08/24/2021 at 23:47 point

hahaha, Wild goose chase... took me a minute.

Ok, I think I've followed the real path with your guidance. Seems there are some weird things going on, like you say... what's the keyboard buffer doing in the link buffer? Heh! I wonder if you could literally send a link command via the keyboard? Or, maybe again, it's related to the external keyboard peripheral.

I think I also see some parsing of the link data(?) Going on 'round line 178670 and thereafter...

In the interest of maybe plausibly hacking in UART instead of TI-Link, it might be a matter of disabling the normal linking (flag?) then alt-slinking to a serial grabber loading into the buffer starting at c33e, then when the buffer's loaded calling the parser. Then, of course, the parser/s/ probably brach out to functions that eventually /respond/, which /may/ also be redirectable to UART... without having to modify the ROM, but, I think this is far too deep for entering in via hex values on the keyboard...

/maybe/ a much simpler one-function UART-receive could be "bootstrapped" that way to load the bigger program from the computer. but, still, I think there's the acks and such from the calc, making for quite a bit of hex to type...

I think we're back to chicken-egg.

My idea was maybe to make a link cable from nothing more than a USB-TTL-level-UART of the $5 variety so commonly available these days... but, it's really only useful if you already have the program/hooks on the calculator.

Alternatively, maybe, would be an even smaller hand-entered download-bootstrapper which disables the OS's linking/interrupts altogether, does nothing but download the bigger program/installer, not even using the OS routines...

I dunno anything about accessing/creating variables/programs, but maybe it's not too much to enter via hexcodes.

But, then, of course, eventually that bigger program/installer has to install the proper hooks, etc. And so far I don't know enough to see whether that's even possible in the calc, except /maybe/ on the receiving (as opposed to acking/sending) side.

From what I've seen of TILP's blacklink library, it shouldn't be particularly difficult to add UART as another link library option. Rather, I think i could add the /functionality/ to link that way, but I don't know about all the mods necessary to make it an option (e.g. from the commandline or the configuration file). (For my earlier mods, I just modified the blacklink library and access them through hardcoded stuff like /dev/ttyUSB when choosing "Serial Port 4").

This, here, I think would be quite an undertaking... months, I'm guessing (and I very much underestimate, usually). Though it /may/ be worth it for others... I dunno.

For my own purposes, it's unnecessary... I have a blacklink, it runs at 100Bps, I can wait 20min for a backup... AND, for others, there is a "$4 homebrew link" compatible with the blacklink library which is a well documented (albeit a bit wonky) day-build...

I suppose, maybe, adding /dev/ttyUSBn as an /option/ for it would be useful, even at 100Bps.

  Are you sure? yes | no

Eric Hertz wrote 08/25/2021 at 00:18 point

going back through your messages...

I see, now... you were thinking to emulate the USB-Graphlink with a bluepill... but it'd be difficult because the usb graphlink is not USB-CDC.

There may be another alternative: as I recall there's a "gray" /serial/ link... that, I think, converts TI-Link from the calculator to /real/ RS232, Tx/Rx... that was way more expensive than the "black" "serial" "Windows Only"  link which is bitbanged via RS-232 handshaking lines.

TILP does the blacklink through hardcoded port locations, but at least for the blacklink it was simply a matter of changing the library's "port 4" device-node from /dev/ttyS3 to /dev/ttyUSB0. Really, those should be commandline options. Also, under linux anyhow, the port addresses are completely unused. I think it's a result of its originally having been written for Windows (in the real serial port era) then ported to linux.

So, I bet you could emulate the gray serial link with the bluepill... and, if you can make it look like a USB-CDC (it does USB?!) you could prb bypass a usb-serial dongle. Then making it work with the graylink library would just be a matter of making sure the /dev/ node is selectable (or hacked in) under linux, or the COM port, in Windows... presuming they've replaced the /direct/ port-address accesses, by now...

  Are you sure? yes | no

ziggurat29 wrote 08/26/2021 at 15:35 point

yes, TI seems to have had so many 'links' over the years -- I have to defer to your expertise on what's what.

It did similarly occur to me that there was once a 'serial' link that could be realised wtih an FTDI-esque adapter.  The serial link as I understood it was really bit-fiddling the various status lines rather than actual UART.  But that can still that could be done, and perhaps more straightforwardly than with the BluePill.  For the BlulePill, to be GraphLink compatible, I would have to implement a custom USB device class (blick).  I did find this:
http://lpg.ticalc.org/prj_usb/informations.html
To do so would really test my limits because USB is a huge learning curve both in general theory and also in the particulars of whatever IP blocks are on your chip-of-choice.
So I could make a BluePill look like an FTDI, but is that really useful vs just using an FTDI?  Well, maybe.  If I can make it bisexual and look like the kooky serial graphlink and then /also/ a non-standard-but-much-more-sane CDC (that would only be usable by my own stuff), then the BluePill might make more sense again.

My personal hope is to get something working that I can interface with the calculator with the existing software.  This I can use to upload a 'bootstrap' loader, which would need to be a 'standard' TI86 asm program.  Then that program would then download the rest of the notional alternative OS in whatever format I like.  But the first step requires speaking TI86 link protocol, and if I have to do that anyway, then I might as well play along later, too.

I'm not sure why TI evolved the adapter the way they did, but possibly because they started in the 90's when we had physical RS-232 and Centronix, and then later those went away so they needed to make a USB one.  Though I really wish they had not made a new device class but oh well I'm not the Director of Engineering at TI.

  Are you sure? yes | no

Eric Hertz wrote 08/25/2021 at 00:59 point

you mentioned sendbyte... linkSendByte_C40F4

That's exactly where i wound-up during the wild goose chase... actually the function above it, send-header, which calls it many times. Hey, least i got /something/ right, disassembling that bit!

  Are you sure? yes | no

Eric Hertz wrote 08/26/2021 at 22:24 point

I haven't looked into TILP's other supported links/libraries, and I'm not /certain/ TI made a /real/ ASync Tx/Rx RS232 link adapter, but I'm /almost/ certain I recall they did... in middleschool I wanted a link, (we had a Macintosh, this long before USB existed). but it was some $40... there was, as I recall, a DB-9 to DIN8 (mac serial) adapter. until they came out with the $20 bit-twiddled hanshaking-line "Windows only" link that I eventually bought (and also had a Windows machine by that time).

Thus, again, I'm almost certain the original graphlink adapter was /real/ serial at the computer-side, and regular-ol' TI-Link at the calc side. Emulating that in a microcontroller shouldn't be too difficult.

.....

If you go the "direct ftdi" route, as it exists, now, you're going to need one with handshaking lines, you'll have to watch those voltage levels, and you'll have to modify tilp's blacklink library to access the USB com/tty port, and you'll have to accept ~100bytes per second as the bit-banging via flooded USB limit.

Essentially what you'd be doing in that route is the same setup I have, minus a couple level-shifters.

Mine's:

1) USB ->

2) PL-2303 ->

3) inbuilt HIN213 ->

4) inbuilt DB-9 ->

5) "Windows Only" graphlink ->

6) Calculator

You can remove all the level-shifting, 1->2->6

Where 2 might be an FTDI.

HOWEVER I think the levels would be inverted.

Again, that's /handshaking/ signals, not TxRx, and 100Bytes/sec, and a slight mod to tilp's blacklink library.

But, does not require any special software on the calc.

Another allegedly-compatible option is the "$4 link" which can be made from passives. But, expects RS-232 Levels. It's a cheaper homebrew blacklink, basically just a level-shifter... the setup would again be the same as mine.

...

Bluepill/microcontroller route: I would think TI-Link at one side, UART at the other, could be identical to the real original $40 graphlink... if it was as I remember. Throwing in USB-CDC compatibility wouldn't be necessary if you've already got a USB-serial dongle. At least, that's how I see it. I'd be kinda shocked if TILP doesn't support that already.

.

The route I discuss in the nextish log is /entirely/ different, and very much NYI, if it ever will be. That of directly connecting an FTDI's TxRx lines directly to the calculator. Does Not Exist (yet?). Requires custom software on the calc /and/ tilp. And is a big chicken/egg problem. The benefit would be using the same setup I have now, just rerouting the blacklink's handshaking lines to the TxRx lines, So That it wouldn't be limited to 100bytes/sec... (I could also remove the hin213, DB9, and blacklink, as they're just level shifters at that point)... maybe closer to a flooded 9600baud, around 960bytes/sec.

Chicken/egg is introduced in trying to do this with a fresh/"Memory Cleared" calculator. And, also, in that most the cheap "FTDI" adapters that can be bought don't expose the handshaking lines, so the initial upload wouldn't be possible that way.

...

I'm dang-near certain a real async serial adapter existed once....

  Are you sure? yes | no