Exciting port finding... or meh...

A project log for Vintage Z80 palmtop compy hackery

It even has a keyboard!

esot.ericesot.eric 07/31/2021 at 23:172 Comments

was all excited: wrote a program to not only test (read-back) all real ports 0-256, but also took into consideration that "b" is placed on the high address byte during port reads 

(BTW, this was part of my inspiration for my 24-bit "real" addressing idea, load a to A23-16... it'd be ignored, usually, but flip a bit, prior to a 16bit-instruction, and it'd switch in a to A23-16 on the bus for one instruction's memory-read, rather than the port5/6 map.)

So, instead of reading 256 ports, i tried all 65536 "ports"... and found "new" data!

But, it now looks like I'd've gotten the same if I just read ports 0-7 at such high rates and repetitiveness.

So, the "new" data amounts to an extra bit on port3 being active from time to time, and, the Write Only ports read-back 0x00 sometimes rather than 0x78 (which, I'm near certain, though haven't checked, 0x78 is the last byte in the 'in a, (c)' instruction, which remains on the data-bus after its fetch due to capacitance on the bus inputs, since nothing else drives it during a port read from a write-only port).

OK, looking at port3, I had to look at the docs for the TI-85, it looks like the change from the normal 0x08 to 0x0A, briefly, might be due to the bit which indicates there was a timer-interrupt (since the last read?). EXCEPT that it doesn't seem the bits at 0x08 nor 0x02 align with those in the 85's docs. They also seem inverted. But, they're almost certainly dealt with in circuitry /internal/ to the z80 VLSI, right? So, I'm kinda at a loss. One possibility might be that things like those on this port really are handled with plain ol' GPIOs. There's a lot of weird circuitry I can't follow, involving transistors and maybe even R/C networks... I thought they were related to low-power switching-off of things like ROM... but... Is it possible the 200Hz timer interrupt is simply an RC oscillator connected to GPIOs?! 

OK, then, say it is... why don't I see 0x0A on port3 very often... indicating the timer interrupted? Probably, simply, the interrupt-handler usually gets to it first, but not always.


OK, then there's reading 0x00 from the WriteOnly ports... which is also rare, but not nearly as rare... It may /also/ have to do with interrupt-handling... wherein, I'm a bit confused, because I was pretty sure the interrupt vectors after an instruction completes, but this would suggest some amount of pipelining. The instruction for port-input has already been fetched, yet gets executed /after/ reading the interrupt vector's byte(s)? Maybe.

So, then, why does 0x00 come through far more regularly than 0x0A, when they're /both/ from the same (?) source? Well, that might have something to do with how much time is spent loading then processing the in instruction, which maybe can get interrupted, if there's a tiny bufer/pipeline vs the plausibly only one clock-cycle where the in is executed before the int takes over. Or something... brain's sorta getting lost on this one.

So... no new ports, it seems.

BUT... there was some weirdness I noticed back when I was testing 65536 ports... the higher address bytes seemed to show patterns! Wait a minute... if it was timer-interrupt-related, then that should've depended /greatly/ on the amount of time between pressing enter to acknowledge the finding... wait a minute... now it doesn't make sense, at all. That was reading-back 0x00... like, one time it found 0x00 at ...

LOL... that pattern thing was /so/ repeatable I only bothered to take one picture: it never happened...

Say, like, 0x7700, 0x5700, 0x2700, 0x0700... seriously, I saw /many/ such patterns in the various runs, but the actual /timing/ of each read was determined by my pressing enter between each... how on earth could that've been the result if it had to do with timer-interrupts? HAH! it never happened.


ziggurat29 wrote 08/01/2021 at 17:40 point

I think you may be onto some good things with your port 3 work.

I had mentioned in a separate post (I know, they're long -- sorry.  I do try to edit them down) that I noticed that b0 and b1 are polled in the IM1 ISR (@ 0x38), and that if they are set that they cause different things to be done, especially keyboard related, but also automatic power down related.

I also mentioned that there was the mystery of some out (3) values and listed what was seen.  What is known in the existing documentation is that bit 3 controls LCD on/off.

Your work here suggests that the b0 and b1 (the only other bits I have seen tweaked/checked on port 3) might indicate 'interrupt source'.  And both can be set at one time.  I am currently guessing that b0 is 'keydown event', and b1 is 'timer event'.  This is a guess.  I don't know if it is possible to have neither one set.

This makes me think that write port 3, b0 and b1 means 'clear interrupt source flag' when the bit is set.  I need to study the code a bit more to find correlation in the servicing and setting of those bits, but this scheme is quite common.  It's also possible that they are 'mask' bits for the interrupt sources.  I need to study to see which is more plausible.  EDIT:  I am leaning towards '1 means mask it off', but still too early.

So you may have cracked the code of port 3.  Definitely not 'meh' at all.

If you want to get your hands dirty, you could try the IM2 hack.  I'll describe it briefly here, but you'll need to read the Z-80 docco on IM2 to fully get it.  The gist is:
*  make a bogus IM2 vector table.  This will be 256 bytes.  It can be in RAM.  Have all entries point to the same routine.  Read the docco to understand this.
*  setup the I register to point to the base of this table.
*  write a routine* that does what you want, and then (optionally*) JMP to 0x38 when done.
*  do a DI, then IM2, then EI
*  profit

The 'hack' of this is that by changing the interrupt mode then you now have control over how interrupts are handled.  You can't hack the ROM, but you can hack the CPU's behaviour!  IM2 was intended to be used by Z-80 family peripherals.  The peripheral would supply a 8-bit offset on the data bus when the interrupt was being serviced and then the CPU would vectored to that peripheral's specific routine.  However, this hardware design doesn't use IM2, and the data on the bus will be random.  Hence filling the table all pointing to the same routine!  Who cares if it's random!  But you 'waste' 256 bytes with the hack table.

After you switch to IM2, the CPU will now be calling /your/ routine instead of the one at 0x38.  So do whatever you want!  You can read those bits and think about them or whatever!

* routine
probably should switch to shadow registers so you can party on without breaking anything, then switch back afterwards.  Know that IY and IY do not have shadows.
* optionally
if you want to keep TI-OS alive, then you can simply JMP to 0x38 to have TI's OS do the things it wants to do.  If you want to print messages in your main app loop (you probably will since you have no other UI -- not even an LED to blink), then this is the thing to do.  But know that it will have done the various out (3) things.
if you do not want to do that, then you'll need to end with a RETI of your own.

A useful thing such a routine could do is simply keep some counts:
*  port 3 & 0x03 = 0
*  port 3 & 0x03 = 1
*  port 3 & 0x03 = 2
*  port 3 & 0x03 = 3

Then in your main (non ISR) program, simply loop and print out those counts.  The timer interrupt bit should increase wildly, the keyboard interrupt bit should increase only when keydown events occur, and not increase when keys are held down (subject to the TI-OS behaviour).  The value of '0' should not increase if the two bits are the sole 'interrupt sources'.  If it increases, then more thinking is needed.

If you do not want to get your hands that dirty, the 'user isr' routine is invoked before the rest of the IM1 routine, so you do have an opportunity to read port 3 there before it is fiddled with.  Then you don't have to mess with IM2.

  Are you sure? yes | no

esot.eric wrote 08/01/2021 at 20:17 point

oh man, you've provided /awesome/ insight, again...

"I know, they're long -- sorry. I do try to edit them down)" LOL. Yours tend to be far less rambly than mine... don't apologize!

I think i'll be doing some research of your port3/int findings and code/experiment suggestions and trying to combine them with mine in schematic form in the next log! Might be a little while, today my brain is half elsewhere, which is a weird feeling, being half wanting really badly to be excited about this new insight I've been researching into, and half completely incapable of understanding it... hah! Found myself in some "new scenery" due to an important mission, which I'm also really only half-capable of even thinking how to pursue.

  Are you sure? yes | no