Omnimaga
Calculator Community => TI Calculators => ASM => Topic started by: the_mad_joob on May 15, 2014, 04:34:23 am
-
At first, i was kinda curious to know why sending $FF would remove the necessity to wait for a delay between writing & reading.
I couldn't believe that sending that was processed somehow differently than sending anything else.
After many boring tests, here is what i discovered :
> About sending $FF :
Sending that to port 1 was called a "reset" by some.
It is true in the fact that it disables the scanning of all groups.
But, i can confirm that it doesn't have any additional effects.
I mean, sending $FF has the exact same effect as sending $7F (the unused group).
It just disables all groups, and is interpreted by port 1 like any other sending.
> About the (famous) needed delay :
Whenever you need to check specific keys (IN), you sometimes have to send one or more group map(s) first (OUT), to be sure that the key presses will be detected.
Sometimes, a delay is needed between OUT & IN, sometimes not.
First, you have to understand that the port always remember the last group map you have sent to him.
We'll call it the current group map.
If you really want to optimize your code, you'd better know what the current group map is, each time you intend to update it.
In other words, each time you use an OUT, it's better to know what you last sended to the port with the previous OUT.
When you update the current group map, here is how it works :
1) You write a 0 to a group bit.
Technically, it can be :
- sending a 0 over a 0 : It has no effect on the concerned group. > No delay is required before reading keys in that group.
- sending a 0 over a 1 : You actually ask the port to enable a group. Fortunately, it is done almost instantly. > No delay is required before reading keys in that group.
In other words, if you don't disable any group(s), you're free to use a IN right after a OUT without fear, even at 15Mhz.
2) You write a 1 to a group bit.
Technically, it can be :
- sending a 1 over a 1 : It has no effect on the concerned group. > No delay is required cause all the keys in that group should already be disabled.
- sending a 1 over a 0 : You actually ask the port to disable a group. > A variable delay is required before all the keys in that group are disabled.
Disabling a group actually means that you don't need to check keys in it anymore.
However, if some of those keys are pressed when you read the port, and are not disabled yet, they will return a zero bit if pressed, even if you think you are reading another (enabled) group.
So, basically, if you don't care if the keys in a disabled group are pressed or not, you don't need to wait.
But, if you want to be 100% sure that all the keys in that group have been disabled, continue reading.
When you disable a group, the keys in it are not disabled simultaneously.
Actually, some take more time than others.
Here is what i gathered :
- Disabling only one group :
Strangely, the more keys are being pressed during the disabling process, the faster it is.
The slowest scenario is when only one key is pressed.
The highest needed delays measured were 7 cycles at 6 Mhz, and 31 at 15 Mhz (Using 8 & 32 would be safe enough.).
- Disabling multiple groups :
The delay can go pretty high.
The slowest scenario is when you disable the entire keyboard (changing the group map from %00000000 to %11111111).
In that case, The delays measured were 46 cycles at 6 Mhz, and 125 at 15 Mhz (Using 48 & 128 would be safe enough.).
According to several tests, what makes that delay so high is that many keys of the same key bit are being pressed at the same time (The keyboard needs a huge time to disable those.).
> Note :
The way i made my tests, all delays refer to the needed cycles between a OUT (1),A line and a IN A,(1) line.
Those values were all obtained by checking pressed keys.
Due to how the keyboard works, the real time it needs to enable|disable unpressed key(s) remains unknown...
-
Wow pretty impressive research job, I'm sure this will be useful ! :D
-
Wow pretty impressive research job, I'm sure this will be useful ! :D
Thx =]
Well, the discovery could be at least useful in some unusual circumstances.
Like, for example, if you need to add some new group(s) in your scan, without disabling the previous ones, you don't need a delay.
Also, we now know that when you send 0 to port 1 (code checking for any key pressed, etc)., you can read directly without waiting =]
Here is the piece of code i'm testing (interrupts disabled ofc) :
xor a
loop
out (1),a ; all groups enabled
dec a
out (1),a ; asking to disable all groups
; delay needed here
in a,(1)
inc a
jr z,loop
As you can see, i ask the port to disable all groups, to see the maximum needed delay.
It seems that 29 cycles isn't enough (tested @ 15Mhz).
Even more fun, only the [5] key can exit that loop, don't ask me why XD
EDIT 1 : I suspect it's because the group including [5] is in the middle of the disabling process, when the IN instruction occurs.
EDIT 2 :
@ 30 cycles, no single key can exit the loop.
However, 2 keys from different groups can XD
Seems like the only way to know the real maximum delay is to hold absolutely all keys at once.
Checking that right away...
EDIT 3 :
@ 66 cycles, 4 keys from different groups can exit the loop...
@ 88 cycles, 5 keys...
@ 96 cycles : 6...
LAST EDIT FOR THAT POST :
It appears that when you enable all groups, and then ask the port to disable them, my calc needs exactly 121 cycles to perform a full disabling, in cpu speed 1.
In other words, that's the time the keyboard needs to switch all 8 groups from 0 to 1.
That is huge.
Anyway, my second theory was right : the more groups the port has to disable, the longer it takes.
-
All set bits will disable the corresponding groups, but it will take some time (the famous delay).
Note that when you ask the keyboard to disable a group that is already disabled, it will do nothing (no delay).
So, basically, the keyboard only needs a delay when changing a group bit from 0 to 1.
That's been my suspicion for years, but I don't have any knowledge of how the hardware actually works so could never definitively say so. Good to hear that my suspicion can now be upgraded to a probable truth.
It appears that when you enable all groups, and then ask the port to disable them, my calc needs exactly 121 cycles to perform a full disabling, in cpu speed 1.
In other words, that's the time the keyboard needs to switch all 8 groups from 0 to 1.
That's about 16 cycles per group, which is huge.
Anyway, my second theory was right : the more groups the port has to disable, the longer it takes.
Whoa, that I did not expect. I'll definitely want to play with that myself on hardware. Maybe that could explain the rare occurrences I still hear about of mis-registered keypresses in Axe, as the getKey(0) command reads from all groups to check if any key is pressed and might be causing issues for any subsequent single key read attempt.
-
Whoa, that I did not expect. I'll definitely want to play with that myself on hardware. Maybe that could explain the rare occurrences I still hear about of mis-registered keypresses in Axe, as the getKey(0) command reads from all groups to check if any key is pressed and might be causing issues for any subsequent single key read attempt.
Neither did i =]
I re-checked it, and it appears all keys corresponding to key bit 2 at once could break the loop, but after a few loop iterations.
So, i had to let the loop run with a heavy thing on all keys for long enough, overlol.
New world record : 123 cycles (tested with cpu speeds 1,2,3).
-
That's some useful information :) do you mind if I detail that on WikiTI with your name in the credits as the finder of these info ?
-
@Matrefeytontias : You should wait a little, cause some values would need to be more accurate.
#####
Some new discoveries =]
> My intuition was right, it seems the time the port needs to do a disabling is not the same for each group (looks like bits are processed in a a linear way).
Group bit 0 is the fastest to set, whereas group bit 7 is the longest.
Example :
00000010 > 00000011 : 23 cycles needed
00000010 > 01000010 : 27 cycles needed
> I was wrong when i said that writing a 1 over a 1 is instantaneous.
Looks like it takes around 1/4 cycles per group at 15 Mhz.
> I updated post 1 with all that juicy stuff =]
> I'm trying to think of a way to know when the group map has been totally updated...
-
Interesting...
It seems that each key on the keyboard needs a specific time to be disabled.
old group map > new group map group,key=delay6mhz/delay15mhz
00000000>00000001 0,0=4/21 0,3=4/20
11111110>11111111 0,0=4/21 0,3=4/20
00000000>00010000 4,0=6/29 4,7=4/20
11101111>11111111 4,0=6/29 4,7=4/20
00000000>01000000 6,0=5/26 6,7=4/18
10111111>11111111 6,0=5/26 6,7=4/18
00000000>11111111 0,0=4/21 0,3=4/20 4,0=6/29 4,7=4/20 6,0=5/26 6,7=4/18
Such results prove that i was wrong about 2 things :
1) Key bits are NOT processed in a linear order during the disabling process (bit0, bit1, ..., bit7). Instead, it seems it is hardware specific (probably depends on the electric scheme).
2) Writing 1 over 1 does NOT take time.
(post#1 updated)
It's getting clearer & clearer.
Now, i'm curious to find which key needs the longest time to be disabled =P
EDIT :
Tested all keys.
It's official, the key that takes the longest time to be disabled is [5] : 7 cycles at 6 Mhz & 31 cycles at 15 Mhz.
That's very funny, cause that totally explains why that was the only key that could break my loop (see one of my previous posts) =]
The fastest is [ALPHA], with 4 cycles at 6 Mhz and 16 cycles at 15 Mhz.
So, i think it's safe enough to use 8 cycles at 6 Mhz, and 32 at 15 Mhz.
But again, such delays are only safe when checking one key at once !
-
Whoa nice. Only weird thing is that it looks like it takes 4 times more cycles for 15-16MHz but it's not even 3 times the speed. :P
-
Whoa nice. Only weird thing is that it looks like it takes 4 times more cycles for 15-16MHz but it's not even 3 times the speed. :P
Yeah, i really never figured out why myself...
Next steps :
> check the maximum possible delay at 6 Mhz
> code a decent prog & find someone to test on another 84+se (to know if the fastest/slowest keys are the same, me curious)
> find a trick to know when the keyboard has finished the enabling/disabling job, to avoid having to use a predefined delay
> reformating post#1 into something more understandable
-
I have an 83+SE, a 128k 84+ and a TI-82stats.fr (TI 83 rom on 83+BE hw) that I can test for you. :3
-
Whoa nice. Only weird thing is that it looks like it takes 4 times more cycles for 15-16MHz but it's not even 3 times the speed. :P
Yeah, i really never figured out why myself...
Your delay figures don't count the amount of cycles spent in the out/in instructions, do they? I believe that could account for the discrepancy you're seeing. It may not add exactly 11 cycles of delay though, as a physical port write might not happen after the same amount of time/cycles relative to the start of the instruction as a physical port read.
-
I have an 83+SE, a 128k 84+ and a TI-82stats.fr (TI 83 rom on 83+BE hw) that I can test for you. :3
I'll post my program tomorow, but i'm not sure your TI-82stats.fr will like it XD
Anyway, i just tested the keys of my 83+be.
The shortest delay is 0.
The longest is 6.
The concerned keys are not the same as on my 84+se.
It seems keyboards may differ...
Your delay figures don't count the amount of cycles spent in the out/in instructions, do they? I believe that could account for the discrepancy you're seeing. It may not add exactly 11 cycles of delay though, as a physical port write might not happen after the same amount of time/cycles relative to the start of the instruction as a physical port read.
All my tests were made using OUT (1),A and IN A,(1), without including any cycles spended by the instructions themselves.
Mainly because i think it's easier for the programmer to just know how much delay he has to put between the two lines.
From what i've tested, the delays are about the same when using the C register (delay-1 or so...).
#####
I was thinking of something.
What happens when you write to the port in the middle of a disabling job ?
I mean, is the second OUT failing, or does the port stops what he was doing and follow the new instructions ?
Some interesting questions...
-
Your delay figures don't count the amount of cycles spent in the out/in instructions, do they? I believe that could account for the discrepancy you're seeing. It may not add exactly 11 cycles of delay though, as a physical port write might not happen after the same amount of time/cycles relative to the start of the instruction as a physical port read.
All my tests were made using OUT (1),A and IN A,(1), without including any cycles spended by the instructions themselves.
Mainly because i think it's easier for the programmer to just know how much delay he has to put between the two lines.
From what i've tested, the delays are about the same when using the C register (delay-1 or so...).
I understand that you don't count the cycles spent in the in/out instructions for simplicity purposes. I just wanted to clarify why the 6MHz and 15MHz delays you recorded are not in a ratio of 6:15.
-
I understand that you don't count the cycles spent in the in/out instructions for simplicity purposes. I just wanted to clarify why the 6MHz and 15MHz delays you recorded are not in a ratio of 6:15.
I understood the clarification, but i wasn't sure about the "do they?".
Thx =]
-
This is your research; you should document it on the Wiki.
-
It requires a bit more investigations, but yeah, i do that for the community (and personal curiosity) and i hope it will be of use for some.
I'm currently coding some stuff at work for a few testers...
-
Did some new tests.
I can say i was a bit surprised by the results.
Examples of some delays my program returns.
The values are the needed delay to disable those keys while being pressed, at 15 Mhz :
DOWN : 21
LEFT : 21
RIGHT : 22
UP : 20
DOWN+LEFT : 15
DOWN+LEFT+RIGHT : 13
DOWN+LEFT+RIGHT+UP : 12
As you can see, it appears that the more keys are being pressed in the same group, the faster it takes to disable them.
And now, some results in different groups :
LEFT+-+9+(+SIN+MATH+DEL : 24
LEFT+++3+2+1+STO+TRACE : 123
It took me a while to figure out why such a huge difference.
In the first case, all keys correspond to different key bits, and in the second, to the same.
-
Wow. Your research is making this hardware sound more and more obscure. O.O What the hell TI ?
-
Yeah, obscure as hell.
An important thing to note is that all my tests were realised checking the needed delay to disable keys while those are actually being pressed.
Due to how the keyboard works, i think it's impossible to test those delays without pressing them.
In other words, it won't be possible to know the real needed time for the keybord to disable unpressed keys.
-
Allright, performed a few verifications, and nothing contradictory showed up.
I have reformated post#1 with all my discoveries.
Right now, i need a few testers (attached program).
You can use it on any 8X+, except the CSE.
Just run it with Asm(.
As soon as it starts, you have 3 seconds to hold the desired key(s).
Plz hold the keys until the program tells you to release them.
The returned values are for all available CPU speeds on your calc (in order : 0,1,2,3).
What it does is check the needed delay for the pressed key(s) to be disabled.
Despite it recognizes all possible key combinations, i'm particularly interested in the following ones :
1) Check all keys, separately, and let me know the maximum delays the program returns.
The "5" key is expected to have the highest delays, whereas "ALPHA" should have the lowest.
2) Check the following combinations :
LEFT + 3 2 1 STO TRACE
RIGHT - 6 5 4 LN ZOOM
UP * 9 8 7 LOG WINDOW
Thx in advance for your time =]
-
Wow. Your research is making this hardware sound more and more obscure. O.O What the hell TI ?
This behavior is most likely due to capacitance in the keyboard traces. When you select a group for reading, charge almost instantly rushes onto the group traces on the PCB, so you can read instantly. But when you unselect a group, TI makes no effort to discharge the traces. (They're also too cheap to add a 1-cent diode to each key so that we could detect multiple key presses without ghosting.) The pins that control the group traces simply go into a high-impedance state, meaning change can't flow back into them. As a result, electric charge stays on the traces until internal resistance dissipates it. When you read from the keyboard right after disabling a group, the charge that was previously on the keyboard traces is still there, giving you the false signal. The capacitance effect is small and the charge dissipates in just a few microseconds, but the Z80 is running fast enough that we can see those microseconds.
-
Wow. Your research is making this hardware sound more and more obscure. O.O What the hell TI ?
This behavior is most likely due to capacitance in the keyboard traces. When you select a group for reading, charge almost instantly rushes onto the group traces on the PCB, so you can read instantly. But when you unselect a group, TI makes no effort to discharge the traces. (They're also too cheap to add a 1-cent diode to each key so that we could detect multiple key presses without ghosting.) The pins that control the group traces simply go into a high-impedance state, meaning change can't flow back into them. As a result, electric charge stays on the traces until internal resistance dissipates it. When you read from the keyboard right after disabling a group, the charge that was previously on the keyboard traces is still there, giving you the false signal. The capacitance effect is small and the charge dissipates in just a few microseconds, but the Z80 is running fast enough that we can see those microseconds.
Excellent, some hardware explanations =]
Makes me remember how far my knowledge of electronic suck XD
I still need at least a few testers (prgm available @ my previous post).
-
Yeah, me too I suck at analog electronics. ._.