Difference between revisions of "83Plus:Ports:01"

From WikiTI
Jump to: navigation, search
(Comments)
Line 54: Line 54:
  
 
* '''Note:''' Group FB Key FE is NEGATE, not to be confused with SUBTRACT.
 
* '''Note:''' Group FB Key FE is NEGATE, not to be confused with SUBTRACT.
* '''Note:''' Group DF Key FE would be ON, but the ON key is tested elsewhere (a "special case" key - after all, it is the ON key).
+
* '''Note:''' Group DF Key FE would be ON, but the ON key is tested through [[83Plus:Ports:04|Port 04]], bit 3.
 
* '''Note:''' Group EF Key BF (APPS) is called MATRIX on the TI-83.
 
* '''Note:''' Group EF Key BF (APPS) is called MATRIX on the TI-83.
  
 
== Comments ==
 
== Comments ==
TI's code always resets the keypad before scanning; sometimes, you may get incorrect values if you scan without resetting first.
 
 
 
You should disable interrupts or use a custom interrupt before manually reading this port, because TI's interrupt scans the keypad. If you leave TI's interrupt active when manually reading the keypad, sometimes it will fire between when you set and read the port, and you'll read garbage.
 
You should disable interrupts or use a custom interrupt before manually reading this port, because TI's interrupt scans the keypad. If you leave TI's interrupt active when manually reading the keypad, sometimes it will fire between when you set and read the port, and you'll read garbage.
 +
 +
All nonexistent keys read 1.
 +
 +
=== Delay ===
 +
TI's code always resets the keypad before scanning; sometimes, you may get incorrect values if you scan without resetting first.
  
 
Traditionally, a delay of a dozen or so clock cycles (6 MHz mode) is used between changing key groups and reading the result. The required delay seems to vary depending on the calculator; some require no delay, others a longer one. The delay is based on real time, not CPU clock cycles; you'll need to make your delay about 3 times longer in 15 MHz mode. However, as in the example, other people seem to find that resetting before every group change negates the need for a delay; some more experimentation is required.
 
Traditionally, a delay of a dozen or so clock cycles (6 MHz mode) is used between changing key groups and reading the result. The required delay seems to vary depending on the calculator; some require no delay, others a longer one. The delay is based on real time, not CPU clock cycles; you'll need to make your delay about 3 times longer in 15 MHz mode. However, as in the example, other people seem to find that resetting before every group change negates the need for a delay; some more experimentation is required.
Line 78: Line 81:
 
ex (sp),hl
 
ex (sp),hl
 
in a,(1)</pre>
 
in a,(1)</pre>
 +
 +
The reason for this has since been discovered to not be caused by slow hardware, but rather by capacitance in the keypad. When unselecting a group, it takes a while before the charge has dissipated. Resetting the keypad every time after using it will make this discharge happen while you're doing something else, and activating a group happens instantly. The number of pressed keys and the number of groups being deactivated plays a role in the time the discharge takes, but generally, 7 clock cycles should be enough. However, this may vary from keypad to keypad.
 +
 +
=== Ghosting ===
 +
Because TI didn't add a diode to each key, you can also detect keys that aren't in a currently selected keygroup, as long as the other keygroup has at least one key in common with a selected keygroup. This means, for example, if F7 is selected, and the keys 2, 3, and 6 are pressed, Then keygroup FB will also be activated because F7 and FB have one key in common (namely FD). This makes it appear as though the 5 key is also pressed. This can also be used to make nonexistent keys appear active. However, as at least three keys have to be pressed for it to be noticeable, you don't have to worry in the most common use cases.
 +
 +
=== Debouncing ===
 +
While a key is in a state between pressed and released, it will repeatedly turn on and off. If you are reading the keypad extremely quickly, it will appear as though the key is being pressed and released a number of times. You need to either wait longer between keypad scans, or you need to implement a proper debouncing algorithm. TI-OS does the first one by scanning the keypad in an interrupt that runs slowly enough for it to not have a noticeable effect.
  
 
== Example ==
 
== Example ==

Revision as of 16:37, 3 March 2020

Synopsis

Port Number: 01h

Function: Keyboard Port

This port reads key presses from the keypad. The keypad is divided into a series of groups.

Read Values

  • Bits are set according whether corresponding keys from selected groups are pressed. Groups are selected through writing to the port. A pressed key reads a 0 bit. An unpressed key reads a 1 bit. The port reads FF after a reset (write FF).

Write Values

  • $FF : Reset the keypad. This unselects all groups and resets the keypad state.
  • Anything else : Any 0 bit adds the corresponding group to the list of monitored groups. When a key in a monitored group is pressed, the corresponding key bit reads 0, otherwise it reads 1 (active-low).

Key Map

The key map is laid out as follows:

Group Bit 0 1 2 3 4 5 6 7
Group Mask FE FD FB F7 EF DF BF 7F
Key Bit (Mask)
0 (FE) DOWN ENTER (-) . 0 GRAPH
1 (FD) LEFT + 3 2 1 STO TRACE
2 (FB) RIGHT - 6 5 4 LN ZOOM
3 (F7) UP * 9 8 7 LOG WIND
4 (EF) / ) ( , x2 Y=
5 (DF) ^ TAN COS SIN x-1 2nd
6 (BF) CLEAR VARS PRGM APPS MATH MODE
7 (7F) STAT X,T,θ,n ALPHA DEL
  • Note: Group FB Key FE is NEGATE, not to be confused with SUBTRACT.
  • Note: Group DF Key FE would be ON, but the ON key is tested through Port 04, bit 3.
  • Note: Group EF Key BF (APPS) is called MATRIX on the TI-83.

Comments

You should disable interrupts or use a custom interrupt before manually reading this port, because TI's interrupt scans the keypad. If you leave TI's interrupt active when manually reading the keypad, sometimes it will fire between when you set and read the port, and you'll read garbage.

All nonexistent keys read 1.

Delay

TI's code always resets the keypad before scanning; sometimes, you may get incorrect values if you scan without resetting first.

Traditionally, a delay of a dozen or so clock cycles (6 MHz mode) is used between changing key groups and reading the result. The required delay seems to vary depending on the calculator; some require no delay, others a longer one. The delay is based on real time, not CPU clock cycles; you'll need to make your delay about 3 times longer in 15 MHz mode. However, as in the example, other people seem to find that resetting before every group change negates the need for a delay; some more experimentation is required.

For me (Sorunome) this didn't seem to work: Using the following code didn't always have the correct keygroup selected when scanning (on a TI-84+SE of a friend of mine):

ld a,$ff
out (1),a
ld a,%10111110
out (1),a
in a,(1)

While the following fixed it:

ld a,$ff
out (1),a
ld a,%10111110
out (1),a
ex (sp),hl
ex (sp),hl
in a,(1)

The reason for this has since been discovered to not be caused by slow hardware, but rather by capacitance in the keypad. When unselecting a group, it takes a while before the charge has dissipated. Resetting the keypad every time after using it will make this discharge happen while you're doing something else, and activating a group happens instantly. The number of pressed keys and the number of groups being deactivated plays a role in the time the discharge takes, but generally, 7 clock cycles should be enough. However, this may vary from keypad to keypad.

Ghosting

Because TI didn't add a diode to each key, you can also detect keys that aren't in a currently selected keygroup, as long as the other keygroup has at least one key in common with a selected keygroup. This means, for example, if F7 is selected, and the keys 2, 3, and 6 are pressed, Then keygroup FB will also be activated because F7 and FB have one key in common (namely FD). This makes it appear as though the 5 key is also pressed. This can also be used to make nonexistent keys appear active. However, as at least three keys have to be pressed for it to be noticeable, you don't have to worry in the most common use cases.

Debouncing

While a key is in a state between pressed and released, it will repeatedly turn on and off. If you are reading the keypad extremely quickly, it will appear as though the key is being pressed and released a number of times. You need to either wait longer between keypad scans, or you need to implement a proper debouncing algorithm. TI-OS does the first one by scanning the keypad in an interrupt that runs slowly enough for it to not have a noticeable effect.

Example

ld a, 0FFh ;Reset the keypad.
out (1), a
ld a, 0FEh ;Select group 0.
out (1), a
in a, (1) ;Test for keys.
and 2 ;Test for Left Arrow key by making A 0 if left was pressed.
call z, LeftArrowPressed ;If 0 then left was pressed.
ld a, 0FFh ;Reset the keypad.
out (1), a