Q: What does reading / writing registers do?
The API of the Rex and Dataslim provide firmware calls to most common hardware functions, however by using registers a more direct way of accessing hardware is possible. Most importantly it is possible to achieve things that are not supported by the API.

Q: How do I read or write registers?
This is from common.h:

#define REGISTER_WRITE( reg, data ) output8( reg, data )
#define REGISTER_READ( reg ) input8( reg )

(These input8 and output8 functions map (almost) 1:1 to a Z80 assembler instruction (IN and OUT?) for i/o.)

Q: What registers are there?
See the list below and also here.
Register Hex value Description
REG_MEMTYPE 0x00
REG_BANK1_LO 0x01Determines the page mapped to $8000-$9FFF
REG_BANK1_HI 0x02Determines the page mapped to $8000-$9FFF
REG_BANK2_LO 0x03Determines the page mapped to $A000-$BFFF
REG_BANK2_HI 0x04Determines the page mapped to $A000-$BFFF
REG_INT_REGDAT 0x05
REG_INT_REGRST 0x06bitwise clear interrupt bits in REG_INT_REGDATA
REG_INT_MASK 0x07
REG_HALT 0x08
REG_FRC 0x09
REG_EXEC 0x0a
REG_EXT_CTRL 0x0b
REG_BLD_CTRL 0x0c
REG_KI_DATA 0x10
REG_KO_DATA 0x11
REG_P_DATA 0x12
REG_P_IOSET 0x13
REG_P_OUTSET 0x14

Beep sounds
REG_ALM 0x15standard tone
REG_MELODY 0x16custom tone
REG_MELFRQ_LO 0x17freq low
REG_MELFRQ_HI 0x18freq high
REG_MLDALM 0x19switch standard/custom tone

REG_RMT_CTRL1 0x1a
REG_RMT_CTRL2 0x1b
REG_RMT_CTRL3 0x1c
REG_SIOCLK 0x1d
REG_RTC 0x1f
REG_SRLCD_DSP 0x20
REG_SRLCD_SEG 0x21
REG_SRLCD_LO 0x22
REG_SRLCD_HI 0x23
REG_SRLCD_COM 0x24
REG_RMLCD_SEG1 0x25
REG_RMLCD_SEG2 0x27
REG_RMLCD_SEG3 0x29
REG_RMLCD_COM 0x2b
REG_DRV_CTRL 0x2d

RTC = Real Time Clock
REG_RTC_1SEC 0x30
REG_RTC_10SEC 0x31
REG_RTC_1MIN 0x32
REG_RTC_10MIN 0x33
REG_RTC_1HR 0x34
REG_RTC_10HR 0x35
REG_RTC_DAY 0x36
REG_RTC_1DAY 0x37
REG_RTC_10DAY 0x38
REG_RTC_1MON 0x39
REG_RTC_10MON 0x3a
REG_RTC_1YR 0x3b
REG_RTC_10YR 0x3c
REG_RTC_PAGE 0x3d
REG_RTC_TEST 0x3e
REG_RTC_RESET 0x3f
REG_RTC_24 0x3a
REG_RTC_URU 0x3b

SIO=Serial Input/Output
REG_SIO_RDB 0x40See below
REG_SIO_TDB 0x40
REG_SIO_DLL 0x40DLL, Division Latch LSB: port 0x40 = 0x07 //
REG_SIO_IER 0x41IER, Interrupt Enable Register: port 0x41 = 0 // this disables interrupts.
REG_SIO_DLM 0x41DLM, Division Latch MSB: port 0x41 = 0x00 // 9600 baud or near enough
REG_SIO_IIR 0x42
REG_SIO_LCR 0x43LCR, Line Control Register: port 0x43 = 0x80 // access division latches
=0x03 // 8 bit, No parity, No stop bit
REG_SIO_MCR 0x44 MCR, Modem Control Register: port 0x46 = 0x00
REG_SIO_LSR 0x45
REG_SIO_MSR 0x46
REG_SIO_SCR 0x47

LCDC I/O
REG_LCEN 0x50
REG_LCMD 0x51

Key Scan */
REG_SCNEN 0x60SCaN ENable?
REG_ATPC 0x68
REG_COLD 0x69Touch screen data - see below
REG_COLU 0x6ATouch screen data - see below
REG_ROWD 0x6BTouch screen data - see below
REG_ROWU 0x6CTouch screen data - see below

0x01-0x04 : Memory paging
Memory paging on REX is done by IO registers 1-4 in this order:

IO port 1 = bank 1 LOW (bit 14 to 21)
IO port 2 = bank 1 HiGH (bit 22 to 25)
IO port 3 = bank 2 LOW (bit 14 to 21)
IO port 4 = bank 2 HIGH (bit 22 to 26)

Bank1 starts at $8000 and bank 2 at $a000. Both are 8192 bytes long.
If you write the following values:
port 0x03 = 0x00
port 0x04 = 0x10
you see the normal 8k RAM at address 0xA000 and
port 0x03 = 0x01
port 0x04 = 0x10
you see a second 8k RAM at addres 0xA000 which can apparently be used safely.

0x15-0x19 : Beep sounds
Used as follows:
REGISTER_WRITE(REG_MELFRQ_HI,frqhi);
REGISTER_WRITE(REG_MELFRQ_LO,frqlo);

The freq parameters are not actually frequencies, but the inverse (wavelength?). The higher the frq the lower the tone the high-frequency is best set to 0 to produce audible beeps. with frq_hi>0 a low tone is produced.

REGISTER_WRITE(REG_MELODY,2); // set command??
REGISTER_WRITE(REG_MELODY,1); // play command

REGISTER_WRITE(REG_MLDALM,1); //choose melody instead of alarmsound
REGISTER_WRITE(REG_MLDALM,0); // default to alarm sound

REGISTER_WRITE(REG_ALM,0); ?

0x22-0x23 : LCD display
port 0x22 = 0x00
port 0x23 = 0x10
displays the first 8k RAM on the LCD,
port 0x22 = 0x01
port 0x23 = 0x10
displays the second 8k RAM on the LCD.
This way you can show any 8k on the LCD, even flash memory.

0x40-0x47 : Serial Input Output
The rex appears to have a basic 16450 UART (or similar) which can be controlled by registers 0x40-0x47
z80.h with definitions of all IO Docs about using serial ports should not be a problem (eg., http://www.lammertbies.nl/comm/info/RS-232_uart.html)
It is indeed somewhat like the stuff you see in a PC so you can use it much the same. The clock that is used to drive it is different though which leads to different values for the division latches. (probably they saved a crystal by reusing the signal used for the processor or RTC)

Now you can send data by sending out'ing it to port 0x40 and receive it by reading from port 0x40. Use the LSR (line status register) to see if the byte has been sent and a new one can be sent and to see if a byte can be read. LSR bit 0 : data available
LSR bit 1 : overrun error (previous data was overwritten)
LSR bit 2 : parity error
LSR bit 3 : framing error (usually baudrate difference between sender & receiver)
LSR bit 5 : byte was sent (can write next byte).
Funny thing is that the Rex is capable of higher speeds than 9600 baud, but because the Rex uses a divider of 7, and the PC uses a divider of 12, there are some troubles getting it to work.

Known working was at 57600 baud which is the same a RexTools appears to use. Apparently the Rex uses by default a divisor of 1, giving about 67200 baud (this is not an exact science !!) together with a setting of 2 stopbits & low parity. If you use 57600 baud on the PC and 1 or 2 topbits with low parity, you can actually communicate with the occasional parity error (!!!) but that may be why a checksum is needed?

0x69-0x6C : Read the touch screen
This might be useful for games or applications (drawing?) that require animation or speed in general, since event-processing (DsEventMessageGet(&msg);) takes some time. They contain the (uncalibrated?) touchscreen position, or 0 if the screen isn't touched.

The 16-bit value ranges Rex are approximately (decimal):
Y: 80 (bottom), 862 (top)
X: 62 (right) , 940 (left)
Note that the values range in the opposite direction to the screen coordinates.