Close

Before I lose it...

A project log for Z80 Reverse-Engineering And Hacking Adventures

What else can I say?

eric-hertzEric Hertz 06/15/2022 at 03:3812 Comments

[Editted]

I'll try to write-up an intro to this project, later... but if I don't write-out today's findings, stat, I'll probably forget.

[outdated photo]

OK, what have we learned? IF I got this right:

There are two 3-in-8-out I/O port decoders (74LS138) attached to A3-A6. Thus, decoding port addresses 0x00-0x7f. The first three address bits are not decoded, so that makes for 16 total possible separate port-things, which have base-addresses at 0x00, 0x08, 0x10, 0x18, and so-forth.

OK, now I think I can make the list:

(X:Y = Decoder:Output)

0:0 0x00: N/C

0:1 0x08: Z80DART (pin 35)

0:2 0x10: GPIB Controller (? not populated) (pin 8)

0:3 0x18: N/C

0:4 0x20: Z80CTC

0:5 0x28: 8255 (pin 6)

0:6 0x30: Z80PIO#0 (pin4), near back panel*

0:7 0x38: GPIB DIP Switch (Read-only)

1:0 0x40: AMD chip (pin 10)

1:1 0x48: MONO output -> DB-9 pin4

1:2 0x50: L297 Stepper-Motor "Clock" (Step?)

1:3 0x58: Z80PIO#1 (pin4), near front panel*

1:4 0x60: RS232 Configuration Switches (Read Only)

1:5 0x68: LCD

1:6 0x70: N/C

1:7 0x78: N/C

*Note, PIOs' Pin*4* are connected to the LS138 outputs, Pin5 is connected to A0.

...

Interestingly, they used a 74240 (inverting, unidirectional, two groups of four bits, hardwired together) for the GPIB switches, and a 245 (non-inverting, bidirectional, 8 bits grouped. Direction hard-wired) for the RS-232 switches. Switches themselves connect to ground, pulled-up otherwise).

I'm Guessing: The "MONO" output I traced-out controls a precisely-timed shutter... I'll get back to that.

Meh, seriously? That's all I got from that page since I last wrote about it?

Well, from last time, I also determined that the third LS138 breaks the memory-map into 4 16KB chunks. The ROM is at 0x0000. The RAM starts at 48KB.

The two unused chunks are wired to unpopulated chips. The lower seems to have been intended for ROM, the higher for RAM (it has /WR).

The Z80 has /NMI, /BUSRQ, and /WAIT all tied directly high (disabled, permanently).

The crystal frequency, which definitely goes to other devices (e.g. the unknown AMD chip) is marked 4.9152. (Good for RS-232?)

There is also a 26pin header (unpopulated) which carries several bus signals (including, oddly, M1); the full 8 data bits, two address bits, RD/WR, and a few pins I have yet to track-down. I guess whatever this is, it's intended to be at port0-3? But, wait... Nothing there to disable it if higher address bits are set. Hmm. (TODO).

I guess that's it for/from that page.

On to  The Mysterious and Gigantic AMD chip...

MOST of the 40(!) pins are either unused or tied together. Heh.

Something makes me think it's something like a presettable 16-bit counter. And that it precisely times a shutter (through the MONO output).

I'm guessing a write to the port starts it, then there's time to do a few instructions before enabling ... Oh, wait. What?

No, this ain't like a GPIO port, the LS138 output is only active for one instruction cycle. Huh. I'm at a loss, now. Whatever the weird AMD chip does for the MONO output apparently gets blocked if Port 0x48 is accessed. But only *during* the access... which doesn't appear to go anywhere else. No idea.

.....

AMD observation: Chip manufactured in 1981. Unit serial number implies December of 1988. Chips around the board have many widely-varying date-codes, but the AMD is by far the oldest I've noticed.

Could this be some relic of the TTL era prior to the standardization of 74xx markings? If so, what kind of TTL chip would be so huge? Nevermind, the fact it's whacked with numerous bytes seems to suggest otherwise. Unless, maybe, a large register...

I found an old AMD catalog of processors and support chips from 1984(?), but nothing in there matched the markings.

I did discover AMD did PLDs for a while, when using my chip programmer to read the ROM. But the ones it supports didn't match, either.

Weirdly, the font in the markings seems off... Was it an era thing?

Seriously, that *huge* chip for nothing more than driving two inputs of a NAND gate?!

Discussions

ziggurat29 wrote 06/15/2022 at 15:40 point

"Before I lose it..." -- I think you lost it long ago; lol!

But seriously, this is stupendous work and is just what I need right now.

As for the 26 pin header, I would suggest testing (at your leisure) if at least one of the pins goes to port selects on the '138s. That would make the most sense. The M1 and IORQ you found would be important if whatever was intended for that plug was to support some ports (up to 4 since they didn't bring out A2) to differentiate from and io request versus and interrupt vector request (which cannot happen since we are in IM2 and we've figured out the complete daisy chain).

I can tell you I have never seen any references to these port blocks in the code:
00 - 07
18 - 1f
50 - 57
70 - 77
78 - 7f
I am still disassembling, so there is the possibility that I might convert some data to code and reveal some new IO logic, but I'm pretty confident that I've got code and data separated now. So we may never know. And with the large number of unpopulated devices on this board, there's a good chance that this same board is used for different products in the SpectraData line, and those might have different firmware than what we have on hand, and it may have been used for something in those products.

That said, the stepper motor port you list as being in the 0x50 block raises an eyebrow because it is in one of the port blocks unreferenced in the code. I am guessing that you have that physically in your hardware or else you wouldn't have mentioned it, so that is a surprise.

Speaking of stepper motors, as mentioned I discovered yesterday some logic that whacks port 48h between 00 and ff hundreds of times and then does a read of port 30h to check a bit. Now that /does/ sound like a stepper motor and the checking of a limit switch. Which under some conditions can lead to my favorite message 'SWITCH CLOSED !! ***PANIKSTOP***@'

Well, you've given me great info that should make for a productive day of continuing to reverse the firmware.

  Are you sure? yes | no

Eric Hertz wrote 06/15/2022 at 20:56 point

I think you're on to something regarding stepping and a limit-switch. And, I did think it a bit odd the stepper-driver's clock input would be driven directly by a port select... So, yahknow, I verified that a few times, but that's not to say I shouldn't recheck those traces.

The port 48 whacking for stepping... I'm boggled by the NANDs (and AMD) in that logic... It seems ... Oh, I think I see it now, if either of the AMD outputs are low, then it inhibits the port-whacking from being output to the MONO connector. Right. So, maybe the AMD is a counter that output soft-limits?

Again, I really have Zero experience with spectroscopy, so this is very much hypothesis:

I imagine two actuators in this system... The stepper-driver outputs to the FILTER connector, which I'm guessing moves the diffraction-grating/prism, or moves the light sensor with respect to it. I'd definitely think that would have limit switches.

There's probably a switchable light-source that, I imagine, probably *can't* be switched off-and-on quickly (warms up?).

There's probably a light sensor (photodiode?) which may need a precisely-timed shutter.

Holy schmoly, it occurs to me I haven't noticed any analog circuitry for actually reading the amount of light sensed! I wonder if that's fed into a separate piece of equipment since it would probably require quite a bit of calibration depending on the spectrum of the light source, itself, as well as plausibly a real-world diffraction-grating might not pass all wavelengths perfectly equally. Hmm.

But, then... A stepper to select the wavelength, and I'm still kinda set on the idea there's a shutter (why?). Or maybe the light source is a strobe, like an old camera flash? But, either way, why not just do a constant reading? No idea why my brain went that route. I think the AMD's being wired-up like it's a re/presettable counter? 

There could, I suppose, be a second stepper for an aperture. It may have stepper drivers of its own.

Oof, hypothesizing rabbithole. I need to breakfast! 2PM!

  Are you sure? yes | no

ziggurat29 wrote 06/15/2022 at 21:36 point

This is ostensibly supposed to be the control panel, so I assume there is a separate piece of hardware that we do not have, and some things will forever be a mystery. (Well, unless we find some manuals, but I'm not holding out hope for that.)

I don't know what a 'MONO' port is -- I'm assuming that is something printed on the case.

There is mention of 'grating' in some of the error messages.

I am working on the DART and CTC and back annotating your chip select findings just now. At the moment I'm studying the init sequence for the DART. (It appears that this only uses port A, btw.) I don't know if there is a legend on the box for the dip switches, because I'm having to reverse engineer what they are from the code just now.  I can see the lower 3 are for BRG, and 7 does something weird, and 654 look like maybe (maybe) choosing things like parity, but I'll know soon enough.

Since you figured out the AMD is on port 40h, all I can tell you at this point is it is used by blasting sequences between 40h and 41h at full CPU speed. There's a routine at 1BC4 that takes a crudely compressed list of port/value pairs and squirts them out. There's two such lists for port 40/41: one at 2144 and another at 216E. The list consists of elementary operations of one write to 41, then two to 40. The lists consist of either 12 or 10 elements, with subtly different values. These port writes are done at full CPU speed with no pacing.

I mention this because this behaviour might throw a monkey wrench into your timer hypothesis for the AMD. Anyway, we don't really know what that chip is, but that does make it all the more intriguing.  I need to do a human readable writeup of those and other findings, but just I'm wanting to try to wrap up the DART and maybe some of the CTC.  (CTC channel 0 appears to the the BRG to the DART, btw.)

Oh, and thanks for buzzing out the daisy chain. I am so pleased that the CTC is in the chain. From a product standpoint, it didn't need to be since it isn't configured to be an interrupt source, but we'll really want that for a hardware clock if/when we make custom firmware. As I interpret your results, the chain is (from highest priority to lowest):

DART
FrontPanel PIO
BackPanel PIO
CTC

Not that it is critical to understanding the code, but I am glad to know all the parts in it.

  Are you sure? yes | no

Eric Hertz wrote 06/15/2022 at 23:38 point

Well, shoot, I didn't mean to make you figure that stuff out the hard way, I can easily give you photos of the back panel. DIP Switch labels... Check back in a few minutes, They'll be on this page.

  Are you sure? yes | no

Eric Hertz wrote 06/15/2022 at 23:44 point

Actually, maybe a new page for photos

https://hackaday.io/project/185919-z80-reverse-engineering-and-hacking-adventures/log/207547-sd70-photos

  Are you sure? yes | no

ziggurat29 wrote 06/16/2022 at 00:19 point

lol; too late. already figured out the DIP switches and the RTSCTS logic the hard way a few hours back.
It's amusing that the numeric of the bit rates is out of whack on the last two. You probably wouldn't notice because they printed the settings in the sane order, but if you study the on-off, you'll see that 19.2 is actually the 6th value, and 9600 the 7th. That threw me off a little.

  Are you sure? yes | no

Eric Hertz wrote 06/16/2022 at 02:34 point

LOL, Great catch on the Baud-switch silkscreen error!

This thing seems to have some fun little easter-eggs (strudels?) like that. I also just caught that the front panel PCB looks to have been etched in-house, and is clearly marked in bare yet uncorroded copper(?): "sd70 keyboard" (Elsewhere the traces are definitely a bit less shiney, including what look like some dark splotchy fingerprints).

I just went through tracing the LS138 outputs again. They are now in pen instead of pencil. No changes detected (except, of course, the LCD).

Yep, that L297 stepper controller's clock input is definitely tied to the LS138 output associated with port 0x50-0x57.

Weird you found nothing about it.

Between the bodge-wires, cut traces, and etched keyboard PCB, am definitely starting to think this a small run using parts from other units. It's entirely plausible this board was already designed *and* soldered-up before they even got this order... The actual stepper-driver may be of no use in this product!

Frankly, the idea of pushing a stepper at a rate at the mercy of intermediate instruction-cycles suggests to me it probably wasn't going very far very fast. Maybe the newer spectrometry machinery this was maybe targetting had inbuilt stepper drivers.

Great sleuthing on those DIP Switches. Sorry you had to do it the hard way, I did try to get it to you as soon as I got that message. But am I right in thinking part of you enjoyed the challenge, and finding out you were right?

I forgot to respond to your Q about the ISR daisy-chain... Yes, your order looks correct as far as I understand the chain-handling ;)

Also, interesting about the AMD... That's a lot of data. Yeah, I think you're right, my timer idea seems questionable, now.

  Are you sure? yes | no

Eric Hertz wrote 06/16/2022 at 04:06 point

Add to the interrupt-chain that CTC IEO goes to the unpopulated header. I don't get this daisy-chain thing... at all. Heh.

So, one more time 

DART IEI (pin6) is Tied High

DART IEO (p7) -> PIOFront IEI (p24)

PIOFront IEO (p22) -> PIOBack IEI (p24)

PIOBack IEO (p22) -> CTC IEI (p13)

CTC IEO (p11) goes to the unpopulated header.

But, I thought you said a PIO has to be at the end(?) And, this seems completely backwards.

  Are you sure? yes | no

ziggurat29 wrote 06/16/2022 at 06:22 point

Don't ask me, I'm lost, too! lol. I've never worked with an IM2 system, which is one reason why I was particularly interested in this find.

The scheme was meant to be a selling point for the Z80 family because it eliminated support chip(s) (a separate interrupt controller). But it wound up being not that popular. Maybe because you're practically locked into the family peripherals and can't add your own things easily. With IM1, anyone can pull the /INT line low and join the party. But with IM2, the cost of entry is having to handle M1 and IORQ and vectors and sniffing for RETI and EIEIO and all the rest of Ol' McDonald's farm.

I'm not sure what I said before, but it was quite possibly uninformed. My present understanding is that the IEO to IEI device-to-device form the daisy chain and are essentially enable/inhibit lines. The one with its IEI tied high (DART in this case) is basically always allowed to interrupt. The others are allowed to interrupt only if the one prior to it in the chain says it's OK to do so. And if that unit is being serviced, it inhibits the others down the line until it is completed. In this unit, the last guy is the CTC, and his IEO is flapping in the wind. But you just discovered that it is brought out to the unpopulated header, so notionally that can extend the chain to even more peripherals. And they will all be progressively lower in priority.

These guys seemed to have had big plans, or maybe they just drank the Zilog KoolAid and designed by-the-databook.

One other detail is that I'm not sure they're doing prioritized interrupts quite right. The daisy chain establishes priority through the enable/inhibit chain, but what you're /meant/ to wind up with is a scheme where the in-process servicing of a lower priority interrupt can itself be interrupted by a higher priority interrupt. This means doing an EI early in your handler, and the databook seems to say as much. However, in this code, the EI is done at the very end, just prior to RETI. So a higher priority interrupts /cannot/ interrupt an in-process lower priority interrupt. So I think the net result is somewhat like conventional IM1: first come, first serve. In IM1 you /are/ meant to do the EI at the end of your ISR. In this code, doing EI early would be potentially disastrous because they are using the EXX to context switch during ISR. You only get one of those, so nesting interrupts would be a great way to clobber your non ISR process.

There's only 4 ISRs in this firmware. I suspect that IM1 with polling for source would have been just as performant, but I don't know for a fact. I just have the hunch based on that's how most folks wind up doing it. But maybe they knew exactly what they were doing and this was how they had to meet their hard real-time requirements. Though the code that whacks a port 512 times (reading!) gives one pause.

Again my understanding is sketchy because I've never seen or used an IM2 system except as a hack to side-step ROM firmware that I could not replace. Odds are I'm wrong about something. I just don't know what, if anything.

  Are you sure? yes | no

Eric Hertz wrote 06/16/2022 at 13:03 point

LOL at EIEIO.

Your explanation makes a ton of sense. I was imagining EIEIO was more like "Int In" and "Int Out" then, logically the first one would have its IntOut tied to the Z80. But, I totally get it, now... "Int Inhibit In/Out," allowing for priority-handling!

I've been planning to print (on paper!) datasheets for all the chips, marking them up with notes is essential for me. But, I gotta setup the printer to do that... heh! Sorry that probably means a bit more explaining (and pin-listing) for you. Seriously, if you saw the amount of flat surface area I have in here, you might think I should figure out how to hang things like that from the ceiling. In fact, that's a real plan, a workbench on pulleys for things like the soldering iron, power supply, maybe even chip programmer and printer. But, there's near ziltch chance of that getting done before you'll have to curb your addiction...

Anyhow, you give great explanations.

  Are you sure? yes | no

ziggurat29 wrote 06/16/2022 at 14:21 point

I thought the same thing, too, and there's some stuff on the net that suggests that, but it didn't make sense. Then I broke down and got the official docs from zilog.com

https://www.zilog.com/index.php?option=com_doc&task=search_term&Itemid=99

And this one from '84 is handy because it also covers the DART (which I guess has long been discontinued). It's a scan, but I find it much more legible than most of the other scanned ones out there on the web:

http://www.bitsavers.org/components/zilog/z80/Z80_Family_Product_Specifications_Handbook_Feb84.pdf

Oh, btw, I did find a port 0x50 write. I have idea how I missed it before, but there it is. I can't see this stepper motor in your photos. No worries about that -- I don't think it will give me useful insight to have such, but I am curious as to where the "L297" is located since I don't see it on the board.

  Are you sure? yes | no

Eric Hertz wrote 06/17/2022 at 00:49 point

Handy Links, thanks! 

For the first link, Gotta go to the menu on the left, click Classic, then Z80. Don't have to click under there, the results should show up anyhow (hard to notice on a small screen).

The L297/L298 stepper drivers are on the left, near the back panel. One's a 20pin DIP, one upright with a heatsink... some passives surrounding them make it look power-supply-related. (BTW, I copied the photos from the other project-page, so now every photo of this should be in this guy's gallery). 

Oh wow! The Elusive Port 50 found!

  Are you sure? yes | no