<!-- PDF page 243 -->

### Other port addresses

As seen in the table at the beginning of this chapter and the discussion about decoding, all even addresses refer to ULA functions. You may find yourself in need to read the keyboard directly from the hardware. As mentioned, part of the ULA's function is to return the state of keypresses. The keyboard is divided in **8** *half-rows* of **5** keys each, each *half-row* having its own port address[^p243-5].

<table>
<thead>
<tr><th rowspan="2">Address<br>Decimal / Hex</th><th colspan="10">Bits</th><th rowspan="2">Address<br>Decimal / Hex</th></tr>
<tr><th>D0</th><th>D1</th><th>D2</th><th>D3</th><th>D4</th><th style="border-left: 3px solid">D4</th><th>D3</th><th>D2</th><th>D1</th><th>D0</th></tr>
</thead>
<tbody>
<tr><td>63486 / F7FEh</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td style="border-left: 3px solid">6</td><td>7</td><td>8</td><td>9</td><td>0</td><td>61438 / EFFEh</td></tr>
<tr><td>64510 / FBFEh</td><td>Q</td><td>W</td><td>E</td><td>R</td><td>T</td><td style="border-left: 3px solid">Y</td><td>U</td><td>I</td><td>O</td><td>P</td><td>57342 / DFFEh</td></tr>
<tr><td>65022 / FDFEh</td><td>A</td><td>S</td><td>D</td><td>F</td><td>G</td><td style="border-left: 3px solid">H</td><td>J</td><td>K</td><td>L</td><td>Enter</td><td>49150 / BFFEh</td></tr>
<tr><td>65278 / FEFEh</td><td>Caps</td><td>Z</td><td>X</td><td>C</td><td>V</td><td style="border-left: 3px solid">B</td><td>N</td><td>M</td><td>Sym</td><td>Space</td><td>32766 / 7FFEh</td></tr>
</tbody>
</table>

The diagram above neatly illustrates how the keyboard matrix is separated into *half-rows* (demarcated by the thick line in the middle). Pay attention to how bits are mirrored going from the outside of the keyboard to the inside.

The address of each *half-row* in the diagram is calculated as: **254** + **256\*(255** - **2ⁿ)**.

In the formula above, **n** is the number of *half-row* which starts with **0** at the bottom right and moves in a counterclockwise manner with each successive *half-row* increasing by **1.**

In the byte read in, bits **D0** to **D4** stand for each of the five keys in the given *half-row* – **D0** for the outside key and **D4** for the one nearest the middle. The bit is **0** if the key is pressed and **1** if it is not.

For example to find the value of the **CAPS SHIFT** key, you can do:

```
PRINT %IN 65278 & @1
```

Writing a value using **OUT** to the ULA (Port **254 / FEh**) controls other hardware as well. You can drive the beeper with **D4**, the MIC socket with **D3**, read the **EAR** socket with **D6** and modify the **BORDER** colour using bits **D0**,**D1** and **D2**. For example to make the border a nice magenta colour you can:

```
OUT 254, %@00000011
```

Port addresses **32765** (**7FFDh**), **8189** (**1FFDh**) and **57341** (**DFFDh**) control the extra memory. Executing an **OUT** to these ports from *NextBASIC* without knowing the ramifications will nearly always cause the computer to crash, losing any program and data. These ports are write-only, i.e. you cannot determine the current state of the paging by an **IN** instruction. This is why the BANKM system variable is always kept up to date with the last value output to this port. Check the last section in this chapter as well as *Chapter 23 – The Memory* where we examine the banking system in detail.

Writing to port **65533** (**FFFDh**) will select a particular PSG register (on the AY sound chip) and writing to port **49149** (**BFFDh**) will send a particular value to that register. Reading from port **65533** (**FFFDh**) returns the value stored in the selected register. Judicious use of these two registers can allow sounds to be generated while *NextBASIC* gets on with something else.

The section that follows describes all ZX Spectrum Next – specific hardware ports; addressing them is via **OUT** and **IN** commands.

[^p243-5]: *Extended keys are combinations of tther keys, so they need to be read as those key combinations. For example EXTEND is CAPS SHIFT + SYMBOL SHIFT.*

