Replacing the ISR (Aug 1, 2007)

(home)
  1. From: "Cyrano Jones" Aug 2, 2007
  2. From: "Jeff" Aug 19, 2007
  3. From: "Cyrano Jones" Aug 22, 2007
  4. From: "Jeff" Aug 22, 2007
  5. From: "Jeff" Aug 22, 2007
  6. From: "Jeff" Aug 22, 2007
  7. From: "Cyrano Jones" Aug 22, 2007
  8. From: "Jeff" Aug 22, 2007
  9. From: "Cyrano Jones" Aug 22, 2007
  10. From: "Cyrano Jones" Aug 22, 2007
  11. From: "Jeff" Aug 22, 2007
  12. From: "Cyrano Jones" Aug 24, 2007
  13. From: "Jeff" Aug 24, 2007
  14. From: "Cyrano Jones" Aug 25, 2007
  15. From: "Jeff" Aug 26, 2007
  16. From: "John R. Hogerhuis" Aug 26, 2007
  17. From: "Jeff" Aug 26, 2007
  18. From: "John R. Hogerhuis" Aug 26, 2007


Subject: Replacing the ISR

From: "Jeff" <fyberoptic1979@...>

Aug 1, 2007

It's been a while since I had done any Z80 programming before I got
into t=
he whole Mailstation thing, so I was referring to the
documentation on the=
interrupt modes again earlier, and came to
realize a trick one could prob=
ably use to hijack it from the MS code
to your own. The NMI would still b=
e stuck there, but maybe that
rarely gets tripped, if ever (depending on w=
hat you're doing?). Mind
you, this might be a commonly known trick, I dun=
no, but I thought it
worth mentioning anyway.

Basically, you put it into =
interrupt mode 2, which is the one where
you set I to the high address byt=
e of an interrupt table. When the
interrupt hits, the external device wri=
tes the low byte (the position
in the interrupt table) to the processor, a=
nd then it does an
indirect call to the address stored at that memory loca=
tion.

Well, I'm fairly sure the MS doesn't have anything that writes thi=
s
byte back to the processor (hence why it uses interrupt mode 1, which
c=
alls the fixed address 0x38), meaning some random byte will be there
on th=
e data bus when the interrupt happens. But that's the trick: it
doesn't m=
atter what byte is there.

You can simply use a table of 257 identical byte=
s. It has to be 257
bytes instead of 256, since normally, you leave bit 0=
of the byte fed
to the processor as 0, so that it'll stay aligned to a ta=
ble of 2-
byte addresses. Since it may or may not be aligned for us due to=
a
random value, we just use one extra byte, in case the random byte the
=
processor reads happens to be 255.

So, for example, if you set register I =
to C0, and then positioned
your lookup table from 0xC000 to 0xC100, settin=
g every byte in it to
like, 40, then when the interrupt hit, it would find=
the address
0x4040 no matter where it looked in the table. Then it would=
call
0x4040 for the actual interrupt, which of course is an address insid=
e
your range of control.

Of course replacing the codeflash is the simples=
t way to do it, but
this allows you to leave that alone, and still have it=
s functionality
intact if you need it, but be able to take control of the =
interrupts
as well if you want.


1: Subject: Re: Replacing the ISR

(top)

From: "Cyrano Jones" <cyranojones_lalp@...>

Aug 2, 2007


ut that's the trick: it
simply use a table of 257 identical bytes.
...
set register I to C0, and then positioned
to 0xC100, setting every byte in it to
hit, it would find the address
table. Then it would call
rse is an address

Pretty slick!


=


2: Subject: Re: Replacing the ISR

(top)

From: "Jeff" <fyberoptic1979@...>

Aug 19, 2007

So I finally did exactly what I mentioned here, to try making my own
entir=
e interrupt, and came across a few little gotchas that I thought
was worth=
sharing.

Oh yeah, first of all, I apparently didn't come up with the 257 =

identical byte table for interrupt mode 2, after seeing some other
write-=
ups on z80 interrupts on the web. I kinda had a feeling that I
surely did=
n't invent something for such an old processor, considering
there are coun=
tless smarter people in the electronics/programming
fields than me. Not t=
he first time I've "invented" something
somebody else already did. But it=
made me feel smart for a little
while, at least!

Anyhoo, since I'm not u=
sing the normal video memory buffer, I
somewhat randomly decided to use #c=
1c1 for my interrupt location
(putting #c1 in my 257 byte interrupt table =
of course). Though I'm
actually just putting a jump here to code in my ma=
in chunk. This
actually led to some problems for me, because AS80 was "op=
timizing"
my code, converting the JP to a JR, and it took me forever to re=
alize
it. So I finally bit the bullet and disabled optimizations. Prolly=

shoulda done it from the get go.

Once I got that out of the way, I found=
out something else strange.
If I re-enabled interrupts before my RETI, i=
t would freeze up. For a
while I was just re-enabling them in part of my =
keyboard loop
(outside the interrupt), but I knew something had to be wron=
g, since
the MS interrupt ends with an EI and works fine. I actually even=
did
a jump to #0038 at the end of my own interrupt (effectively making it=

a hook), and it worked fine.

So it wasn't until looking over the MS co=
de that I realized that it
was toggling the bit of the current interrupt o=
n port #03. It seemed
to be the only thing it COULD have been. And sure =
enough, toggling
that bit makes my interrupt work fine, letting me end it =
with the
standard EI/RETI like I wanted. So that's important to know. I'=
m
just curious what exactly toggling the bits does in the hardware, as
to=
what would cause it to freeze up like it was doing (unless I re-
enabled i=
nterrupts outside the interrupt routine).

After I added my toggling, I rea=
lized that the time16 interrupt was
much slower than I had previously expe=
rienced. With toggling, time16
occurred every 1 second. Before I figured=
that out, the interrupt
was happening pretty rapidly (perhaps not togglin=
g the bit was making
the interrupt happen repeatedly?). My bare interrupt=
routine is
actually just incrementing a 16-bit value, which I then displa=
y the
content of in my main program code loop, which is how I was able to =

see how fast the interrupt was occuring. Turning the keyboard
interrupt =
on makes it count really fast again, but I'm not sure of
the time interval=
there.

I then put my own version of my keyboard routine in the interrupt,=

and found it was freezing if I call it after toggling that bit.
Doing i=
t beforehand fixed that, as did calling it after setting the
bit to zero, =
but before setting the bit back on again. This seems to
be the method use=
d by the MS routine anyway, so I figure I should
handle it like that from =
now on.


3: Subject: Re: Replacing the ISR

(top)

From: "Cyrano Jones" <cyranojones_lalp@...>

Aug 22, 2007

s toggling the bit of the current interrupt on port #03. It seemed
e the only thing it COULD have been. And sure enough, toggling
makes my interrupt work fine, letting me end it with the
TI like I wanted. So that's important to know. I'm
xactly toggling the bits does in the hardware, as
to freeze up like it was doing (unless I re-
the interrupt routine).

It sounds like clearing the p3.x output port bit m=
ay be clearing the
coresponding p3.x input port bit.

The in & out bits a=
re not the same, the existence of the shadow
indicates you can't read back =
what you last wrote. It seems like
the output bits serve to enable the res=
pective interrupt, and now
you have found evidence that setting the enable =
bit low also clears
the request bit. Good work!!! Maybe you would even sa=
y it serves as
an "acknowledge" to the interrupting hardware?

ded my toggling, I realized that the time16 interrupt was
an I had previously experienced.

The slower one is probably correct. I =
don't know if time16 is even
used anywhere, the only reference I found to =
it was the increment
in the ISR. It is possible it was used by one of the =
functions
that got scraped out by version 2.53yr (caller id????).

Did your=
keyscan work when time16 was flying? Oh wait, I bet it
did, since it's no=
t int based, right???

Before I figured that out, the interrupt
perhaps not toggling the bit was making
).

I'll venture a hypothesis: Without the toggle of out-P3.4, the in-bi=
t
was not cleared. Since time16 int has a higher priority than
keyboard i=
nt, time16 handler was catching keyboard ints. When you
added the toggle=
of out-P3.4 the keyboard ints were now handled by
the keyboard int handle=
r.

And by toggle, I really mean setting low. You need to set high again=

to re-enable the int.

crementing a 16-bit value, which I then display the
n program code loop, which is how I was able to
pt was occuring. Turning the keyboard
y fast again, but I'm not sure of

Cool!!!

Can=
you get an idea of the actual rate of the keyboard int??????
I think the t=
imers are in millisec, and that would mean this int
happens every 1 millise=
c. Another theory is it is a 60 Hz int.,
in which case the timers can't be=
in millisec (I think I verified
they were millisec, but maybe I remember w=
rong???)

pt,

You mean in the P3.1 int, not the P3.4 (time16) int, right?

und it was freezing if I call it after toggling that bit.

Here you mean s=
etting low then high, both, before calling your
keyscan, right??? I probab=
ly used bad terminology when I said
"toggle" in the comments, which I guess=
really means "invert".

it after setting the
in. This seems to
ure I should

The keyscan interrupt (wh=
ich is a misnomer, it is really time32,
10 timers, and keyscan interrupt),=
is written to re-enable ints
inside the ISR (right after inc of time32). =
I guess the idea is
to allow the other ints to be serviced before the time=
rs &
keyscan are done. This is probably why they leave the out-P3.1
bit l=
ow while servicing int 3.1. You don't want to get a
second keyscan int ti=
ll you are done with the current scan.

I don't claim to fully understand h=
ow the interrupts work,
and I don't know if the ms code is best way to do =
it, but
if it aint broke...



4: Subject: Re: Replacing the ISR

(top)

From: "Jeff" <fyberoptic1979@...>

Aug 22, 2007

Jones" <cyranojones_lalp@...> =
wrote:
the
he same, the existence of the shadow
ou last wrote. It seems like
ive interrupt, and now
t low also clears
y it serves

enture a hypothesis: Without the toggle of out-P3.4, the in-
cleared. Since time16 int has a higher priority than
e16 handler was catching keyboard ints. When you
ut-P3.4 the keyboard ints were now handled by

gain to re-enable the int.

After I wrote my post, I thought on what migh=
t be happening, and
formed what I figured was a somewhat fair analysis of =
how the
hardware could be working. I'm no expert of course, but this is h=
ow
I'd make it myself, based on what I've seen. It also matches up with
=
some of your own hypothesis, but I didn't give you a thorough
description =
of how exactly I had my interrupt routine setup, which
I'll explain in a m=
oment, and will hopefully clear up matters a bit.

As for the hardware, I'm=
thinking that there's a flip-flop in there
for each interrupt. When an i=
nterrupt happens, the flip-flop
enables, and stays on indefinately until i=
t's reset. I figure all of
these flip-flop outputs are connected to what =
you read on port 3
input (so that you can get which interrupt occurred), a=
s well as
probably all being OR'd together (and inverted) to the processor=
's
interrupt pin. During your interrupt routine, you'd then read port 3
=
to see which interrupt happened, and "acknowledge" it by setting that
bit =
off then on again, which presumably trips that interrupt's flip-
flop's res=
et. If you don't trip the reset of the flip-flop(s), it
won't go off, and=
therefore make the interrupt routine execute again
immediately after havi=
ng just executed.

If this is all the case, then I think this is why it was=
"locking up"
on me when I wasn't toggling the port 3 output bit. I say "=
locking
up" because I had initialization code to fill in the screen with a=

particular character, which was directly underneath the code where I
set=
up my interrupt replacement and enabled interrupts. The screen
was drawin=
g only a couple columns or so before just freezing in mid
draw. If I wait=
ed until after the screen drawing code to enable
interrupts, the screen wo=
uld completely draw in just fine, of course,
but then just freeze afterwar=
ds. So without toggling that port 3
bit, it was probably actually just ex=
ecuting the interrupt function
over and over, and never getting a chance t=
o actually return to my
main code loop long enough to continue.

What I di=
dn't fully explain about my interrupt routine is that,
during the initiali=
zation process, I disabled every interrupt in the
interrupt mask of port 3=
except for the time16 one. No keyboard was
on at this point. So, when I=
was re-enabling interrupts at the end
of my interrupt routine, it would d=
o the freezing up that I mentioned
earlier. If I waited to re-enable inte=
rrupts until after I got back
into my main code loop, then the interrupt w=
ould occur fairly rapidly
(it didn't fully lock up like before because my =
code had a chance to
do stuff before the interrupt had a chance to be trig=
gered again,
which it presumably did immediately upon an EI, since I never=
toggled
the p3 bit). Once I put the port 3 time16 bit toggling into play=
,
the interrupt started to only happen once a second, which seems to be
t=
he correct interval of that particular interrupt.

I then turned on the key=
board interrupt in the interrupt mask as
well, and that's when it started =
to trigger the interrupt routine
quickly again. I was pretty much togglin=
g every bit off then on
again, so that I'd trip all the resets (therefore =
getting both the
keyboard and time16 in one swoop). But now I've separate=
d the two
interrupts out, by detecting which is occuring and jumping to a =

location to deal with it and toggle only its bit, just like the MS is
doi=
ng (and therefore also implementing an interrupt priority in
effect, by de=
pending on which I test for first). That way the code I
have associated w=
ith the time16 interrupt only runs at its one second
interval, and the key=
board code executes at its own interval.

Actually, I'm not doing it EXAC=
TLY like the MS; I'm only executing
unique code for the time16 and keyboar=
d interrupt. If one of these
two doesn't occur, I'm defaulting to togglin=
g all the rest of the
interrupt bits in one swoop, because I obviously am =
not interested in
those if they happened to occur. I turned the others of=
f of course
in the interrupt mask during initialization, but I figure ther=
e's
always a chance one could be pending from how the MS had it all
confi=
gured before I took over. Just clearing all the others if
time16 or keybo=
ard doesn't occur prevents another neverending loop,
like what plagued me =
initially.

Actually, why don't I just show you the code fragment:

in a, =
(#03)
bit 4, a
jr nz, interrupt_time16
bit 1, a
jr nz, interrupt_keyboa=
rd

ld a, (p3shadow) ; else, just toggle the bits except
keyboard and =
time16
and a, #12
out (#03), a
ld a, (p3shadow)
out (#03), a
jr interr=
upt_end

I think I might be able to measure this keyboard interrupt inter=
val
by just checking how many keyboard interrupts occur between
time16's.=
If I had to make a wild guess, I might say 60 times a
second, as you sug=
gested.

is even
t
got scraped out by version 2.53yr (caller id????).

Do you suppose they use=
it for tracking the auto power off aspect?

en time16 was flying? Oh wait, I bet it
ight???

I've pretty much stopped using my own keyscan. Now that I made=
the
one work that I ripped out of the Mailstation firmware, and can make =

my own interrupt as well, I see no reason not to just use theirs,
since I=
can relocate the variables required by it to wherever I want,
without clu=
ttering up C000-FFFF.

But I suppose all the work I put into writing my own=
version was
pretty good experience, because it's the first time I've ever=
worked
with the raw dealings of rows/columns of a keyboard matrix.


t know if the ms code is best way to do it, but

Y=
eah, there's really nothing particularly wrong with the MS interrupt
that =
I currently know of that would make me not want to use it, it's
pretty muc=
h solely the fact that its variables are all up in the
ram. If I could to=
tally relocate everything, then it'd be pretty
nice to have one contiguous=
chunk to work in.


5: Subject: Re: Replacing the ISR

(top)

From: "Jeff" <fyberoptic1979@...>

Aug 22, 2007

I think I might be able to measure this keyboard interrupt interval
just checking how many keyboard interrupts occur between
had to make a wild guess, I might say 60 times a
ed.

So I made two 16-bit variables (didn't think I needed'em this big, =

but I wanted to make sure) called kbdtest and kbdmax, and clear'em to
0 a=
t startup. Everytime the keyboard interrupt happens, I increment
kbdtest.=
Everytime the time16 interrupt happens, I copy the contents
of kbdtest i=
nto kbdmax, then clear kbdtest. I display both on the
screen during my ma=
in code loop.

kbdtest naturally increments swiftly, but kbdmax settles at =
64 after
a second or so and stays there. That would seem to indicate that=

it's not 60 times a second after all, but just a tad higher. Not
sure w=
hy they chose that value. Or maybe they were just aiming for
60 but didn'=
t care if it was entirely accurate, as long as the
keyboard got read often=
. Then again I could be doing something that
makes this not entirely accu=
rate, but I don't know exactly what
that'd be at the moment. I even took =
the call to the keyboard scan
out of the interrupt to see if that might in=
fluence the speed at all,
but it stayed the same. So, for the moment at l=
east, I'm assuming
the keyboard interrupt happens 64 times a second.


6: Subject: Re: Replacing the ISR

(top)

From: "Jeff" <fyberoptic1979@...>

Aug 22, 2007

So I made two 16-bit variables (didn't think I needed'em this big,
wanted to make sure) called kbdtest and kbdmax, and clear'em
to
tartup. Everytime the keyboard interrupt happens, I
increment
Everytime the time16 interrupt happens, I copy the
contents
t into kbdmax, then clear kbdtest. I display both on the
my main code loop.

Maybe I shoulda waited a little bit before I made th=
at post, because
here's yet another with some new info!

I decided to use =
this same technique on the other interrupts, to see
if/when/how often they=
trigger. So I implemented code to handle
every interrupt, and turned the=
m all on. One by one, I put the code
to increment kbdtest into the interr=
upt handlers. Here's what I
got(2 and 7 being the new ones):

0 - Didn't =
do anything
1 - Triggers 64 times a second, used for keyboard
2 - Triggers =
when a key is pressed (minus power button)
3 - Nothing here
4 - Triggers ev=
ery second
5 - Nada
6 - Zilch
7 - Triggers when power button is pressed/dep=
ressed. This is
apparently wired straight to the button, because it somet=
imes
triggers multiple times when pressed/released (aka not debounced).

I=
knew there had to be one connected to the power button, because how
else =
would it wake back up when you press it?

Interrupt 2 is what surprised m=
e most though: an interrupt that only
activates from the keyboard, yet the=
y never use it. I know that to
do debouncing and such, you'd need a const=
ant time interval, which is
probably why they chose to do it in interrupt =
1. Since the MS isn't
particularly cpu intensive, I guess they figured th=
ey'd just handle
it all in one swoop each time. But if one wanted to stre=
amline the
interrupts, I reckon you could pull the keyboard routines apart=
, and
save some cycles by only doing some of it when a key is down.

I act=
ually had to edit my post just now. I initially thought
interrupt 2 was t=
riggering constantly (64 times a second) as long as
a key was being held. =
But then I had a thought about the keyboard
rows, and what might happen i=
f they were off (aka bits set high). It
was then that I remembered that t=
he keyscan was switching these rows
on and off rapidly (and at a familiar =
64 times a second via interrupt
1). So I decided to stop calling keyscan =
in the interrupt routine.
As a result, interrupt 2 stopped triggering 64 =
times a second when a
key was being held; instead, it only triggered once =
per button
press. If I turn off the keyboard rows, it doesn't trigger an =

interrupt at all. If I only turn on, say, just the first row, it
only tr=
iggers when I press one of those buttons. So interrupt 2 is
entirely depe=
ndant on which keyboard rows are active.

But if keyscan was toggling all t=
he rows to check them for
keypresses, and this was causing nonstop interru=
pts on interrupt 2 as
long as the key was held, then this must mean that t=
oggling a
keyboard row effectively trips another interrupt 2 if a key in t=
hat
row is still being held. This could be useful. It's actually kind
o=
f useful just letting it increment 64 times a second when keyscan is
left =
to run normal, because you could use that as a basis for
handling key repe=
at and such.


7: Subject: Re: Replacing the ISR

(top)

From: "Cyrano Jones" <cyranojones_lalp@...>

Aug 22, 2007


second or so and stays there. That would seem to indicate that
60 times a second after all, but just a tad higher.
Could it be 62.5???? T=
hat would make time32 exactly in millisec.
Maybe you could measure total co=
unt for 10 or even 60 seconds, and
get aveverage rather than max? But, I a=
m ready to just call it
milliseconds. "Close enough for government work", =
as they say. :-)

Turns out the timers *are* in millisec, too. Well, they=
are set in
millisec, that is.

The call to "Set_a_timer(who, msec, persist=
)" takes the number
of msec, and shifts it right 4 bits before sticking it =
in the
timer table.

That explains why time32 increments by 16 each int,
wh=
ile the timers inc by just 1.

The resolution of each of the 10 timers is l=
imited to
multiples of 16 msec,
and the max count is #fff =3D ~65 sec due t=
o fact that
the 16 bit msec param is shifted right by 4 bits.
(Seems upper =
4 bits of 16 bit limit are unsettable.)

So, our current understanding is:
=

- time16 is a 16 bit counter of elapsed seconds since boot,
unknown if it =
is ever used.

- time32 is 32 bit counter of elapsed msec since boot,
units=
are msec, but resolution is 16 msec.

- the ten event generating timers ar=
e set in units of
milliseconds, but resolution is 16 msec.
Max count is #ff=
f =3D ~65 sec



br>> a second or so and stays there. That would seem to indicate that <=
br>> it's not 60 times a second after all, but just a tad higher. <br><p=
re>Could it be 62.5???? That would make time32 exactly in millisec. <br>Ma=
ybe you could measure total count for 10 or even 60 seconds, and<br>get ave=
verage rather than max? But, I am ready to just call it<br>milliseconds. =
"Close enough for government work", as they say. :-) <br><br>Turns out the=
timers *are* in millisec, too. Well, they are set in<br>millisec, that is=
. <br><br>The call to "Set_a_timer(who, msec, persist)" takes the number<b=
r>of msec, and shifts it right 4 bits before sticking it in the<br>timer ta=
ble.<br><br>That explains why time32 increments by 16 each int, <br>while t=
he timers inc by just 1. <br><br>The resolution of each of the 10 timers i=
s limited to <br>multiples of 16 msec, <br>and the max count is #fff =3D ~6=
5 sec due to fact that <br>the 16 bit msec param is shifted right by 4 bits=
.<br>(Seems upper 4 bits of 16 bit limit are unsettable.)<br><br>So, our cu=
rrent understanding is:<br><br>- time16 is a 16 bit counter of elapsed seco=
nds since boot,<br> unknown if it is ever used.<br><br>- time32 is 32 bit =
counter of elapsed msec since boot, <br> units are msec, but resolution is=
16 msec.<br><br>- the ten event generating timers are set in units of <br>=
milliseconds, but resolution is 16 msec. <br> Max count is #fff =3D ~65=
sec<br><br>--CJ</pre><br>



8: Subject: Re: Replacing the ISR

(top)

From: "Jeff" <fyberoptic1979@...>

Aug 22, 2007

Jones" <cyranojones_lalp@...> =
wrote:
.
t aveverage rather than max? But, I am ready to just call it
s. "Close enough for government work", as they say. :-)

Welp, I wante=
d to check, so I set it on 10 seconds first. After time
to settle, kbdmax=
stayed a consistant 640. So I did the longer test
of 60 seconds, and got=
3840. I tried another different method as
well (which included waiting u=
ntil after the first time16 before
starting any counters, to ensure everyt=
hing was in sync), and got the
same result. So it seems to confirm the 64=
times a second I
initially got.

So then I thought I should test the ti=
me16 interrupt, just to verify
that it's in actual exact seconds. I let i=
t run for about 14 minutes
counting (14 minutes just because it ended it a=
t the hour mark on the
clock, easier to remember when to check back on it)=
. 14 minutes =3D
840 seconds, and this is exactly what my counter said wh=
en it hit the
hour mark. Here it is 8 minutes after, and I checked the co=
unter
again, and it's still accurate. So time16 interrupt is pretty much =

guaranteed to be in seconds, or it would surely have gotten skewed
from t=
he clock by now.

So I dunno. Maybe they don't care about exact millisecon=
ds on the
Mailstation, and just do it as close as possible. I doubt it do=
es
anything particularly time critical in the software in which
microseco=
nds would matter anyway.

Actually, do you think they might have used this =
time interval due to
the modem in some way? I know that you need exact fr=
equencies in
order to communicate serially without an error percentage. B=
ut I
have no idea if the modem chip and cpu run off the same oscillator or=

what. I don't even know what the oscillator speed is. Obviously
it's l=
ikely to be some high amount if the Mailstation is capable of
switching up=
in speed.

There's three different versions of the modem chip, and I dunno=
which
is in the Mailstation without possibly pulling it apart yet again. =

One runs at 28.224mhz, one at 52.416mhz, and the other at 56.448mhz.

B=
ut if we only knew the exact cpu frequency, some math could come
into play=
to figure out other things.


9: Subject: Re: Replacing the ISR

(top)

From: "Cyrano Jones" <cyranojones_lalp@...>

Aug 22, 2007


That's certainly=
interesting! I wonder if it is detecting any
change on keyboard col input=
port, or just "not #ff" condition.

essed/depressed. This is
se it sometimes
ebounced).

I don't know about that, it sure seems that the isr associated
=
with int7 is the caller id handler.

The power button is connected to P9.=
4. I suppose it *could*
generate interupt on P9.4 low, but then where is t=
he isr???

There doesn't seem to be anything in the isr (labeled
"caller_id=
_handler") to turn on power. In fact, the first
thing it does is check P2.=
2, which is wired to the data-ready
pin on the caller-id chip. The isr ret=
s immediately if
there is no data ready.

ected to the power button, because how
ou press it?

I think maybe power button sets the power-control flip-flop=

directly, without cpu's help. I have to find the drawings I
made (4 years=
ago, but they are around here somewhere).

I don't really know if the cpu =
is off, or just in halt state
when mailstation is "off" (asleep). If it is=
halted, it
would need an int or a reset to get it started again.

Is ther=
e any possibility that any port bits are getting
changed accidentally????
=

I am assuming you are using your own shadow vars, right???
What do you ini=
t them to? (0, or the value of the coresponding
"real" shadow)????

Are yo=
u preventing *all* of the original int code from running?

s what surprised me most though: an interrupt that only
he keyboard, yet they never use it.

Perhaps it *is* used, to wake up fro=
m a "screensaver" mode
where unit goes to sleep, but needs to wake up right=
where you
left off? I don't know if the mailstation even has this mode,
=
though. The isr would not need to do anything, just the int
would restart =
halted cpu.



10: Subject: Re: Replacing the ISR

(top)

From: "Cyrano Jones" <cyranojones_lalp@...>

Aug 22, 2007

to settle, kbdmax stayed a consistant 640. So I did the longer test
60 seconds, and got 3840. I tried another different method as
ch included waiting until after the first time16 before
nters, to ensure everything was in sync), and got the
t seems to confirm the 64 times a second I

Mebbe we sh=
ould call the units "almost millisecs"???
Or, howzabout "bogomillisecs"??=
? :-)

erify

Ya took the words right outt=
a my mouth...

...
conds on the

Sounds=
likely.

due to

Doubt that.

ct frequencies in
age.

Modem is parallel interfaced to cpu.

e modem chip and cpu run off the same oscillator or
know what the oscillator speed is. Obviously
h amount if the Mailstation is capable of

Modem =
chip has it's own xtal.

hip, and I dunno which
apart yet again.
r at 56.448mhz.

Probably the slowest! (cheaper)
OK, I looked at mine, t=
he xtal next to modem chip says
"524AS9X", and I am gonna jump to conclusio=
n that means 52.4 MHz.

math could come

I don't think cp=
u freq has anything to do with modem or timers.
The RTC has it's own xtal, =
too. (rtc stops if you short it out).

X101 (cpu xtal) has number "122AS9Y=
" which I am assuming means
12.2 MHz.

X102 (rtc xtal) has no number (that=
I can see, at least).



11: Subject: Re: Replacing the ISR

(top)

From: "Jeff" <fyberoptic1979@...>

Aug 22, 2007

Jones" <cyranojones_lalp@...> =
wrote:

ggers multiple times when pressed/released (aka not debounced).
t know about that, it sure seems that the isr associated
caller id handler.
e it *could*
=

I stripped everything out and made a standalone interrupt 7 test, if
you =
want to try it yourself. This will make the LED come on when you
press th=
e power button:

(URL)

I=
put the description and instructions at the top there.

ly know if the cpu is off, or just in halt state
" (asleep). If it is halted, it
started again.

I tested this finally to see just what happens. I pulle=
d the
powerdown function out and changed it so that it would jump to the
=
beginning of my code after the halt. If the processor was merely
asleep, =
then it should jump back to the start of my code and keep on
trucking.

We=
ll, it doesn't, unfortunately. It always resets the MS entirely.
So it m=
ust do more than merely wake it back up. P28.0 must
completely kill the p=
ower to the cpu, or at least maybe somehow holds
it in a state of reset.

=
However! We can make our own "sleep" mode. Upon getting a power
button p=
ress during the normal keyscan, we can disable interrupts,
unmask all of t=
hem except like 2 (a keypress interrupt), turn off the
lcd, re-enable inte=
rrupts, and halt immediately thereafter. Below
the halt we just put a jum=
p to where we want to go when it wakes up.
I just tried it, and it works =
like a charm! It woke right back up
and went back to my code. I also tri=
ed using interrupt 7 (power
button), but since it's not debounced, and act=
ivates again when you
release it, it doesn't work well unless one went to =
some extra
trouble in software.

bits are getting
ing your own shadow vars, right???
value of the coresponding

I'm still using the MS's=
shadow vars, actually.

code from running?

Yep, as can be seen in the test app above.

Here's y=
ou something kind of interesting. The v2.53 powerdown at
#1AC0:

di =

ld a,(p28shadow) ;; set p28.0 either modem reset, or I am a pin off
=
on Vcc control bit?????
set 0,a ;; Yeah, this makes more sense as "powe=
r off"
ld b,a
out (28),a
ld de,03E8
push de
call Delay(msec) =
;; delay
pop de
ld a,b ;; reset p28.0
res 0,a
out (28),a =

halt ;; stop cpu. interrupts can wake it, I guess.
ret

And now t=
he v3.03a powerdown:

di
ld a,(p28shadow)
set 0,a
ld b,=
a
out (#28),a
halt
ret

No delay, no other bit resets or anyt=
hing. Just straight and to the
point. Wonder what the delay and other st=
uff is for, then?


12: Subject: Re: Replacing the ISR

(top)

From: "Cyrano Jones" <cyranojones_lalp@...>

Aug 24, 2007

int7 is the caller id handler.
P9.4. I suppose it *could*
ere is the isr???
rrupt 7 test, if

OK, I am getting int7 t=
oo when I run your test. I wonder if
anything else triggers int7? Does th=
e callerid chip?

The isr sure looks like it is caller-id related. And it =
most
definitely does not turn the power on. Or off.

I did some poking aro=
und with continuity checker tonight.
There are three things that set the po=
wer flip-flop to the
"on" state: Power button, reset button, and a pin on =
cpu.

The two buttons can pull the /set pin of the f-f to ground
via two d=
iodes. The pin from cpu chip is connected to /set
thru a 10k resistor.

Here's you something kind of interesting. The v2.53 powerdown at
:
...
e

Hmmmm... =
I wonder if they decided it works better that way?
It almost seems like a =
waste of time to take the delay out,
even if it is not needed.

What PCB is=
in your 3.03a? What color is your case? The white
(or whatever you call =
that color) ones have a different PCB
than the brown ones. Maybe there is =
some difference in circuit???



13: Subject: Re: Replacing the ISR

(top)

From: "Jeff" <fyberoptic1979@...>

Aug 24, 2007

Jones" <cyranojones_lalp@...> =
wrote:
nything else triggers int7? Does the callerid chip?
s like it is caller-id related. And it most
power on. Or off.

I actually made my test program because I honestly did=
n't know if
your MS might behave differently.

I've never doubted your ass=
umption of interrupt 7 being used for
caller id though, especially after h=
aving looked at the function the
interrupt routine is calling. It's just =
that the same interrupt
obviously has a second and unexpected use. Whethe=
r they actually
actively use it though is another story, and at the moment=
, I'd lean
towards "no". Much like with interrupt 2. It makes me wonder =
how
many other aspects of the device have multiple and/or unused
function=
s.

The thing is though, I'm fairly sure my model doesn't have caller ID
(=
as with all DET1 models, correct?). So I wonder if the models that
do hav=
e caller id still have the power button associated with their
interrupt 7?=

I wonder if maybe they tied the power button to it on these earlier
mo=
dels just for testing purposes? That, or maybe they actually
thought they=
'd use it in early planning stages, until they changed
their minds, and de=
cided to use it for caller ID instead. This is
the version 2.xx and 3.xx =
firmware after all. Who knows what was in
earlier revisions.

Have you tr=
ied tracing that interrupt's pin off the cpu to see where
all it goes?


hree things that set the power flip-flop to the
, reset button, and a pin on cpu.

Well look at that, it does come on when =
I press reset! Is the pin on
the cpu you're referring to the P28.0 one?

=

ost seems like a waste of time to take the delay out,
eeded.

rown ones. Maybe there is some difference in circuit???

It's black, th=
ough I'm not exactly sure which number is my PCB
version. I took some pho=
tos though so that I wouldn't have to keep
opening it everytime I wanted t=
o check something. The middle and
right ones probably have the info you'r=
e interested in along the
bottom. They're not super quality, but they're =
high-res enough to
get most of the part numbers and such if interested. T=
hey're almost
2MB a piece.

(URL)
pg
(URL)
(URL)
net/mailstation/ms_right.jpg


14: Subject: Re: Replacing the ISR

(top)

From: "Cyrano Jones" <cyranojones_lalp@...>

Aug 25, 2007

(as with all DET1 models, correct?).

AFAIK only the eMessage had caller=
-id function. DET1 covers
a whole bunch of different models, so it really =
is not very
useful as an identifier. All the brown & white mailstations,
a=
nd the emessage are "DET1".

The first ergonomic case model was called DE=
T2 (purple mivo 200).
The 250's are DET2B, the 350 is IWT2B.

Now, everythi=
ng else (the "AFAIK is still in effect) is a DET1x,
where the x is a letter=
. This includes both old and new 120, and
both old and new 150. Also, I t=
hink one of the older models was
"DET1-01". And it makes a difference wher=
e you look for number.
The older 120 says DET2 on bottom of unit, but DET1E=
on the box!

I have a white "mailstation" (came in box with brown picture,=
and
a sticker that said "new color!". It has same PCB as the eMessages,
w=
ith caller-id chip, but no caller-id function. I'm as sure as I
need to be=
that it is really a reflashed eMessage. The oddest
part is that it has sa=
me firmware version # (3.03a) as your black
unit, which doesn't have caller=
-id chip. (is yours really very
dark brown???)

The PCB in brown units (=
1T0863BMB-33)is different than the white
(1T0863CMB-32) mainly in that ther=
e is no caller-id chip.

2.53yr (brown, no chip) still has the caller-id is=
r. I took a
quick look at your 3.03a dump, and it seems to have same isr.
=

button associated with their

The cpu is same in all of =
them (except 350), so it seems a sure
bet.

the power button to it on these earlier
s? That, or maybe they actually
stages, until they changed
r ID instead. This is
o knows what was in

Earliest I have seen is 2.21 (eM=
essage).

where

I think int is associated with an i/o bit, (or bits,=
it seems).
Power button is on P9.4 ,and my best guess is call-id int is
on=
P2.2 (callid_data_rdy).

cker tonight.
e
look at that, it does come on when I press reset! Is the pin on
you're referring to the P28.0 one?

No, P28.0 is an output, and it *clears=
" power f-f, turning
power off.

I don't think the signal that turns power=
on is a port bit,
rather the "alarm" out from rtc. Just a guess, though.=

If cpu is off, then ports prolly don't work. I am assuming
that rtc insid=
e cpu is powered, even when rest of chip is
off. It has to keep time/date =
counting, even when off.
My guess is they use a timer to wake unit up at ma=
il check
time.

I think maybe reason it comes on with reset button might =

have to do with reflashing in the box. Brown units at
least. They had h=
oles in the inner box giving access to
power jack, par port, and reset but=
ton.

ersion. I took some photos though so that I wouldn't have to keep
ng it everytime I wanted to check something. The middle and
probably have the info you're interested in along the
ot super quality, but they're high-res enough to
mbers and such if interested. They're almost
ww.fybertech.net/mailstation/ms_left.jpg
tion/ms_center.jpg

Hec=
k, those are darn nice pics! Did you use macro lens,
or a scanner?

That =
is same board I found in all the brown units I looked
inside (1T0863BMB-33)=
. Same as in 2.53yr.

I listed all the units I opened up in groups databas=
e section
(URL)
reportRows&tbl=3D1&sortBy=3D2

(we'll see if that works. if not, just open=
the hard way.
best ordering is sort on "firmware" column).



15: Subject: Re: Replacing the ISR

(top)

From: "Jeff" <fyberoptic1979@...>

Aug 26, 2007

Jones" <cyranojones_lalp@...> =
wrote:

old and new 150. Also, I think one of the older models was
And it makes a difference where you look for number.
ET2 on bottom of unit, but DET1E on the box!

I don't have a box or anythin=
g. All I know about mine is from the
label on the back, with "DET1", whic=
h I now know is fairly generic
unfortunately. It does also say "REN: 0.1B=
" on the sticker too, if
that means anything.

tation" (came in box with brown picture, and
or!". It has same PCB as the eMessages,
er-id function. I'm as sure as I
d eMessage. The oddest
a) as your black
ly very

I've never considered it dark brown, it truly l=
ooks black to me, but
I dunno. I can't even really capture the color well=
enough with a
camera, but I tried: (URL)
=
ms_front1.jpg

Odd thing happened with the LCD there. Guess the camera is =
faster
than the LCD refresh.

As for the content on the screen, that's w=
here I'm testing C code. I
finally figured out SDCC enough to modify its =
CRT0.s to work with my
app loader (since code starts at 0x8000 after loadi=
ng), and then
added in my text lcd functionality by replacing their placeh=
older
'putchar' with my own (which uses global cursorx and cursory
variab=
les accessable from C, as well as being capable of interpreting
carriage r=
eturns/line feeds), which is the most basic function of all
of C's charact=
er and string drawing functions. So now I can use
printf and such to outp=
ut text, which is so much less time consuming
than fiddling around in asse=
mbly. I've implemented a few basic
functions in actual C, like for cleari=
ng the screen and getting
scancodes, but that really needs to be redone in=
assembly. I've
already done those things in assembly before, it's mostly=
a matter of
modifying the code to work with SDCC. Unfortunately code I m=
ake now
is certainly more bulky with all of C's libraries crammed in, and =

things are a bit more noticably slow from the overhead.

One problem I hav=
e with SDCC is that I have no idea how to align data
by a particular amoun=
t of bytes! In AS80, I have my cga font table
aligned to a 256 byte area,=
so that the font drawing code works
quickly. But now I have to specifica=
lly 'org' the code to a location
in order to make it work. I really don't=
know if SDCC can even do
it, which is a huge downside. For now, I'm just=
putting the 2k of
font data at the very end of page8000 to avoid messing =
with the
memory areas C uses, which makes all my binaries 16kb.

Anyhoo, w=
hen I have more functionality worked in for at least
handling the keyboard=
properly with standard C functions, I'll upload
some stuff.

those are darn nice pics! Did you use macro lens,

It's a=
Sony Cybershot 3.2 megapixel that I found on sale a year or
two ago. It'=
s a good camera for the most part, and has a macro mode
for when you want =
to get close to things. But you can't turn off the
flash without going in=
to slow exposure, which is pretty useless
unless you have it on a stand. =
So I always manage to kill most up-
close pictures with the flash, or take =
a bunch until I get one that
I'm somewhat satisfied with. I had to block =
out some of the light
with paper just for those I took of the MS board.

I=
thought about using a scanner actually, but then I figured it'd
prolly be=
kind of hard to position it on there without taking the
whole board out.
=

://tech.groups.yahoo.com/group/mailstation/
tbl=3D1&sortBy=3D2

You've sure opened a lot, then! That's a good list.=
This is the
only one I've owned (hence my fear of breaking it). It's on=
e of the
few I've even seen too, for that matter. I remember seeing one o=
f
the fancier new models on display at the store before, but I never
mess=
ed with it. It's just funny how this thing sat under the bed
with a layer=
of dust on it for ages before I ever realized the
breakthroughs that had =
been made with it here.


16: Subject: Re: [mailstation] Re: Replacing the ISR

(top)

From: "John R. Hogerhuis" <jhoger@...>

Aug 26, 2007

If you're running from RAM, instead of 256 byte table, allocate an
extra 256 bytes before or after.

Them memmove the table data to the aligned location at runtime calculated by:

U = table address
A = (U + 0xFF) & 0xFF00

You will "waste" 256 bytes using this method. However, either above or
below the table you will have at least 128 bytes, so you may be able
to find some other purpose for it.

If you are running from flash, you could allocate 256 bytes and then
attempt to realloc only as many bytes as a you need to get an aligned
chunk in there somewhere. Probably the allocator will not change the
location, but you need to verify that the address does not change.



17: Subject: Re: Replacing the ISR

(top)

From: "Jeff" <fyberoptic1979@...>

Aug 26, 2007

wrote=
:
extra 256 bytes before or after.
igned location at runtime
calculated by:
(U + 0xFF) & 0xFF00
ver, either
above or
o you may be
able

Hey that's a pr=
etty clever method. After I wrote my last post, I
stopped wasting so much=
space in the binary by moving it to the last
2k of slot8000 ram during C'=
s initialization, but that was still
wasting ram by leaving it in the orig=
inal position too. This method
is much better, and only takes four lines =
more assembly than the
previous method to find the new address. So 8 line=
s total, plus a
variable now to store the address. Not quite as clean as =
using a
simple "align 256" in AS80, but it works.

from flash, you could allocate 256 bytes and
then
y as many bytes as a you need to get an
aligned
. Probably the allocator will not change
the
erify that the address does not change.

Yeah it'd be a little bit trick=
ier if I were using rom, which
fortunately I'm not at the moment. But I c=
ould probably write a
little app in C or Perl or something to read the sym=
bols file SDCC
produces to get the offsets, then shift the font data aroun=
d to be
aligned, and then also change a location that pointed to the font =

data position.

I found the other day that I could look at the symbols fil=
e and use a
calculator to manually pad the area above the font data, but i=
t meant
updating the padding value fairly often while I was working on it.=

But I suppose that once I got all that code squared away, it'd be a
sim=
ple method to do the job, without wasting any more bytes than
necessary.

=
Actually, now that I think about it, I could probably whip together a
Perl=
script that could read the symbols file, then rewrite a one-line
include =
file with the number of padding bytes I need to align the
font data, then =
have it recompile again.

Anyhoo I'm just rambling now, so thanks for the t=
ips!


18: Subject: Re: [mailstation] Re: Replacing the ISR

(top)

From: "John R. Hogerhuis" <jhoger@...>

Aug 26, 2007

On 8/26/07, Jeff <fyberoptic1979@...> wrote:


That would work. That would get you to an average case of 128 bytes
lost instead of 256. Worst case is 255 I guess.

A word of advice from another Perl programmer: 'use bytes;'

Perl will by a set of defined rules but which to me looks like magic
spontaneously decide to consider a string as Unicode. Try to unpack
that beastie, and hilarity ensues. Data::HexDump will show it as it
is, but unpack will do some translations you don't expect.

So if you are doing a lot of binary manipulation but you don't care
about unicode, just use bytes; and the problem will not appear.

(I learned this recently... I know, very reasonable engineers will
ignore this advice right up until it kicks them in the butt... I
probably would ignore it myself.)

Keep up the good work here... with a reasonable C environment I may
have to dust off my mailstation too :-) It would be fun to boot ZCN or
CP/M on the MS. I also have on my "one of these days" projects
transplanting a MS PCB and display into a Tandy 102 case. The T102's
ROM chip is based on 8085, a much simpler offshoot of the 8080 than
the Z80, so it might be possible to port that ROM over.