Skip to content

Technical reference

Andrew Owen edited this page Jul 10, 2023 · 80 revisions

Boot sequence

During startup, UnoDOS 3 prints a logo in the standard screen (in page 5). After it finishes initialization, ROM 1 is paged in with the PC set to zero. This is the BASIC ROM. Because BASIC is not ready yet it pages in the BOOT ROM (ROM 0). The BOOT ROM wipes all the memory banks except for page 0 and page 5. It sets the middle 32K to be shadow RAM paged from the DOCK bank (this breaks the prototype Spectrum SE due to page contention -- this won't run on Fuse). It copies the font and palette to the framebuffer are sets the palette. At this point it activates the framebuffer and the palette, and clears page 5 (which will not be cleared by the BASIC startup code when running on the Chloe 280SE). Then it copies the last 7K of BASIC to $4000 (which will be DOCK or page 5 depending on the machine), sets the page in the top 16K to page 0, and passees control to the BASIC ROM. The BASIC ROM's NEW routine then sets hi-res mode and clears from $5C00 to $FFFF, displays the copyright notice, and passes control to the user.

Keyword tokens

The final code points of the tokens have not yet been determined. BASIC is stored in plain text format, so changes to the token arrangement will not break existing programs. These are the current assignments:

Code Token
$80 EOF #
$81 FN
$82 INKEY$
$83 LOC #
$84 LOF #
$85 PI
$86 RND
$87 INSTR
$88 LEFT$
$89 MID$
$8A RIGHT$
$8B STR$
$8C STRING$
$8D SPC
$8E TAB
$8F USING
$90 ABS
$91 ACOS
$92 ASC
$93 ASIN
$94 ATAN
$95 CHR$
$96 COS
$97 DEEK
$98 EXP
$99 FIX
$9A INP
$9B INT
$9C LEN
$9D LOG
$9E NOT
$9F PEEK
$A0 SIN
$A1 SGN
$A2 SQR
$A3 TAN
$A4 USR
$A5 VAL
$A6 VAL$
$A7 MOD
$A8 <>
$A9 <=
$AA >=
$AB AND
$AC OR
$AD XOR
$AE LINE
$AF OFF
$B0 STEP
$B1 THEN
$B2 TO
$B3 _B3
$B4 _B4
$B5 _B5
$B6 _B6
$B7 _B7
$B8 _B8
$B9 _B3
$BA _BA
$BB _BB
$BC _BC
$BD _BD
$BE _BE
$BF _BF
$C0 _C0
$C1 _C1
$C2 _C2
$C3 _C3
$C4 BLOAD
$C5 BSAVE
$C6 CALL
$C7 CHDIR
$C8 CLEAR
$C9 CLOSE #
$CA CLS
$CB COLOR
$CC CONT
$CD COPY
$CE DATA
$CF DEF FN
$D0 DELETE
$D1 DIM
$D2 DOKE
$D3 EDIT
$D4 ELSE
$D5 END
$D6 ERROR
$D7 FILES
$D8 FOR
$D9 GOSUB
$DA GOTO
$DB IF
$DC INPUT
$DD KEY
$DE KILL
$DF LET
$E0 LIST
$E1 LOAD
$E2 LOCATE
$E3 MERGE
$E4 MKDIR
$E5 NAME
$E6 NEXT
$E7 NEW
$E8 OLD
$E9 ON
$EA OPEN #
$EB OUT
$EC PALETTE
$ED POKE
$EE PRINT
$EF RANDOMIZE
$F0 READ
$F1 REM
$F2 RENUM
$F3 RESTORE
$F4 RETURN
$F5 RMDIR
$F6 RUN
$F7 SAVE
$F8 SCREEN
$F9 SEEK #
$FA SOUND
$FB STOP
$FC TRACE
$FD WAIT
$FE WEND
$FF WHILE

Microsoft Binary Format

MBF extended precision numbers consist of an 8-bit base-2 exponent with a bias of 128, so that exponents −127…−1 are represented by x = 1…127 ($01…$7F), exponents 0…127 are represented by x = 128…255 ($80…$FF), with a special case for x = 0 ($00) representing the whole number being zero, a sign bit (positive mantissa: s = 0; negative mantissa: s = 1) and a 31-bit mantissa of the significand. There is always a 1-bit implied to the left of the explicit mantissa, and the radix point is located before this assumed bit. Unlike IEEE floating point, MBF doesn't support denormal numbers, infinities or NaNs.

MBF extended-precision format (40 bits)

Exponent Sign Significand
8 bits, bit 39–32 1 bit, bit 31 31 bits, bit 30–0
xxxxxxxx s mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm

Examples

  • 10: $84, $20, $00, $00, $00
  • 1: $81, $00, $00, $00, $00
  • 0: $00, $00, $00, $00, $00
  • 0.5: $80, $00, $00, $00, $00
  • 0.25: $7F, $00, $00, $00, $00
  • -0.5: $80, $80, $00, $00, $00
  • sqrt(0.5): $80, $35, $04, $F3, $34
  • sqrt(2): $81, $35, $04, $F3, $34
  • ln(2): $80, $31, $72, $17, $F8
  • log2(e): $81, $38, $AA, $3B, $29
  • pi/2": $81, $49, $0F, $DA, $A2
  • 2*pi: $83, $49, $0F, $DA, $A2

Character codes

Depending on context, SE Basic IV will treat a code point in the control characters range as a control character or as a glyph defined by the active code page which by default is code page 437. Depending on context, code points of $80 or higher are interpreted as a token or a code page glyph.

ASCII

This is a list of the American Standard Code for Information Interchange (ASCII). ASCII only covers 128 characters and defines the code point ranges $00–$1F and $7F as control characters which do not have a printable glyph assigned to them. This includes such values as the Carriage Return (CR) character that ends a program line.

. _0` _1` _2` _3 _4 _5 _6 _7 _8 _9 _A _B _C _D _E _F
0_ NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
1_ DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
2_ ! " # $ % & ' ( ) * + , - . /
3_ 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
4_ @ A B C D E F G H I J K L M N O
5_ P Q R S T U V W X Y Z [ \ ] ^ _
6_ ` a b c d e f g h i j k l m n o
7_ p q r s t u v w x y z { | } ~ DEL

Codepage 437

This table shows the characters that are produced by the 256 single-byte code points when the DOS Latin USA code page 437 is loaded, which is the default. Other code pages can be loaded to assign other characters to these code points.

  • SE Basiv IV adds the Euro currency symbol (€) at code point 255.
  • Redefining characters in the printable ASCII code point range $20–$7E will result in a different glyph being shown on the screen, but the character will continue to be treated as the corresponding ASCII character.
  • All characters can be redefined by loading another code page.
. _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _A _B _C _D _E _F
0_
1_ §
2_ ! " # $ % & ' ( ) * + , - . /
3_ 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
4_ @ A B C D E F G H I J K L M N O
5_ P Q R S T U V W X Y Z [ \ ] ^ _
6_ ` a b c d e f g h i j k l m n o
7_ p q r s t u v w x y z { | } ~
8_ Ç ü é â ä à å ç ê ë è ï î ì Ä Å
9_ É æ Æ ô ö ò û ù ÿ Ö Ü ¢ £ ¥ ƒ
A_ á í ó ú ñ Ñ ª º ¿ ¬ ½ ¼ ¡ « »
B_
C_
D_
E_ α ß Γ π Σ σ µ τ Φ Θ Ω δ φ ε
F_ ± ÷ ° · ²

Keycodes

SE Basic IV primarily reads the keyboard using a 40-key matrix. However, the top row can only be read using the PS/2 scan codes. It stores key presses in the keyboard buffer with the following codes:

Key Code Notes
Esc $20 + SHIFT
Backspace $0C
Tab $06
Return $0D
F0 Not stored in keyboard buffer. Must be read using a user NMI routine.
F1 $11
F2 $12
F3 $13
F4 $14
F5 $15
F6 $16
F7 $17
F8 $18
F9 $19
F10 $1A
F11 $1B
F12 $1C
F13 $1D
F14 $1E
F14 $1E
F15 $1F
Home $02
End $03
Page Up $04
Page Down $05
$0B
$08
$09
$0A
Insert $00
Delete $7F
Help $10
Clr $01

Scancodes

Key Code Notes
F1 $05
F2 $06
F3 $04
F4 $0C
F5 $03
F6 $0B
F7 $83
F8 $0A
F9 $01
F10 $09
F11 $78
F12 $07
F13 $2F
F14 $37
F15 $3F

Set 2 scancodes

┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐
│76 │ │05 │06 │04 │0C │ │03 │0B │83 │0A │ │01 │09 │78 │07 │ │2F │37 │3F │
└───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬─────┐ ┌───┬───┬───┐
│0E │16 │1E │26 │25 │2E │36 │3D │3E │46 │45 │4E │55 │   66│ │70x│6Cx│7Dx│
├───┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬────┤ ├───┼───┼───┤
│0D  │15 │1D │24 │2D │2C │35 │3C │43 │44 │4D │54 │5B │  5A│ │71x│69x│7Ax│
├────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐   │ └───┴───┴───┘
│58   │1C │1B │23 │2B │34 │33 │3B │42 │4B │4C │52 │5D │   │
├────┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴───┤     ┌───┐
│12  │61 │1A │22 │21 │2A │32 │31 │3A │41 │49 │4A │51 │  59│     │75x│
├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴┬──┴─┬─┴──┬┴───┼────┤ ┌───┼───┼───┐
│14  │1Fx │11  │          29          │ 11x│ 27x│ 2Fx│ 14x│ │6Bx│72x│74x│
└────┴────┴────┴──────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘

Note: Code $61 is present only 88 key and 89 key layouts. Code $51 is present only on 89 key layouts.

Palette

To convert a 24-bit color to an 8-bit ULAplus color, take the most significant bits of the 8-bit values of the RGB color and arrange them in GRB order. Then drop the least significant bit. For example:

dark orange = #ff8c00
R = %111[11111], G = %100[01100], B = %000[00000]
9-bit GRB = %10011100[0]
8-bit GRB = %10011100

To convert an 8-bit ULAplus color to a 24-bit color, convert the 2-bit blue value to a 3-bit value by ORing the first two bits to get the least significant bit. Then repeat the values to get the 9-bit value and drop the least significant bit. For example:

dark orange - %10011100
R = %111 G = %100 B = %00[0]
9-bit R = %111 111 11[1]
9-bit G = %100 100 10[0]
9-bit B = %000 000 00[0]
24-bit RGB = %11111111 10010010 00000000
           = #FF9200

The canonical 8-bit values for the ULAplus 3-bit values are:

B      R/G  hex
%00[0] %000 #00
       %001 #24
       %010 #49
%01[1] %011 #6d
       %100 #92
%10[1] %101 #b6
       %110 #db
%11[1] %111 #ff

Memory model

In normal operation, the 64K address space is used as follows:

┌─────┬───────┬───────────┬─────────────┬───┬─────────┬───────────┬───┬────────────────────┬───┬∙∙∙
│ ROM │ BASIC │ System    │ Channel     │ 8 │ BASIC   │ Variables │ 8 │ Command or program │ N │
│     │ (RAM) │ Variables │ Information │ 0 │ Program │           │ 0 │ line being entered │ L │
├─────┼───────┼───────────┼─────────────┴───┼─────────┼───────────┴───┼────────────────────┴───┴∙∙∙
↑     ↑       ↑           ↑                 ↑         ↑               ↑
│     │       │           │                 │         │               │
0   $4000   $5BB9       CHANS              PROG      VARS           ELINE

∙∙∙┬───┬───────┬───┬────────────┬────────────┬───────┬─────────┬───────┬───┬───┐
   │ 8 │ INPUT │ N │ Temporary  │ Calculator │ Spare │ Machine │ GOSUB │ ? │ 3 │
   │ 0 │ Data  │ L │ Work Space │ Stack      │       │ Stack   │ Stack │   │ E │
∙∙∙┴───┼───────┴───┴────────────┼────────────┼───────┼─────────┴───────┴───┼───┤
       ↑                        ↑            ↑       ↑                     ↑   ↑
       │                        │            │       │                     │   │
     WORKSP                   STKBOT       STKEND    SP                RAMTOP PRAMT

Framebuffer

The framebuffer is stored outside main RAM (bank 7). In 80 column mode it is used as follows:

$FFFF ┬───────────────┬ 65535
      │ font          │
$F800 ┼───────────────┼ 63488
      │ odd columns   │
$E000 ┼───────────────┼ 57344
      │ palette       │
$DFC0 ┼───────────────┼ 57280
      │ temp stack    │
$DF80 ┼───────────────┼ 57216
      │ character map │
$D800 ┼───────────────┼ 55296
      │ even columns  │
$C000 ┴───────────────┴ 49152

In 40 column mode it is used as followes:

$FFFF +---------------+ 65535
      | font          |
$F800 +---------------+ 63488
      | attribute map |
$E000 +---------------+ 57344
      | palette       |
$DFC0 +---------------+ 57280
      | temp stack    |
$DF80 +---------------+ 57216
      | character map |
$D800 +---------------+ 55296
      | bitmap        |
$C000 +---------------+ 49152

Having the temporary stack grow down towards the character map means that in a worst case scenario some incorrect characters would be read back from the screen in 80 column mode. In 40 column mode where the character map is half the size but there is more processing to do it will never get near the character map.

In 80 column mode the palette is updated so that the foreground and background colors match the permanent attributes. When switching to 40 column mode the original palette entries are restored.

In 40 column mode the bitmap is stored in the even columns area and the attribute map is stored in the odd columns area.

System variables

MSTATE      23548   Mouse state.
JSTATE      23549   Joystick state.
K-HEAD      23550   Points to head of keyboard buffer.
K-TAIL      23551   Points to tail of keyboard buffer.
KSTATE      23552   (8) Keyboard state.
REPDEL      23560   Delay before keys auto-repeat (in 50ths. of a second); normally 25.
REPPER      23561   Delay between key repeats (in 50ths. of a second); normally 2.
DEFADD      23562   (2) DEF FN address (offset).
ONERR       23564   (2) Status of ON ERROR and line to jump to.
MASKADD     23566   (2) Address of user IM1 routine.
STREAMS     23568   (38) For streams -3 to 15, a word gives the displacement from the start of the channels area to the assigned channel. If the word is zero, the stream is closed.
SEG         23606   (2) Reserved.
RASP        23608   Length of error sound in 60ths of a second; normally 60.
PIP         23609   Length of keyboard click (normally zero).
ERR-NR      23610   Error number.
FLAGS       23611   Main flags byte.
VDU-FLAG    23612   Display flags.
ERR-SP      23613   (2) SP value to use when an error occurs.
LIST-SP     23615   (2) SP value to use when an automatic list fills the screen.
MODE        23617   Cursor mode; L, C, E or G.
NEWPPC      23618   (2) New line to jump to.
NSPPC       23620   New statement to jump to, or FFH.
PPC         23621   (2) Current line number during program execution.
SUBPPC      23623   Current statement number.
BORDCR      23624   Attributes for lower screen except in SCREEN 0.
E-PPC       23625   (2) Number of line with > cursor.
VARS        23627   (2) Address of variables.
DEST        23629   (2) Used in variable assignments.
CHANS       23631   (2) Start of channels area.
CURCHL      23633   (2) Start of current channel.
PROG        23635   (2) Program start (address of line number of first line).  
NXTLINE     23637   (2) Address of next line in BASIC program.  
DATADD      23639   (2) Data address used by READ command.  
E-LINE      23641   (2) Edit line start.
K-CUR       23643   (2) Address of cursor in the edit line.
CH-ADD      23645   (2) Current character address.
X-PTR       23647   (2) Address in the edit line of a syntax error.
WORKSP      23649   (2) workspace start.
STKBOT      23651   (2) Address of bottom of calculator stack.
STKEND      23653   (2) End of floating point calculator stack.
BREG        23655   Calculator’s B register.
MEM         23656   (2) Start of calculator’s memory area.
FLAGS2      23658   8 if caps lock is on, else zero.
DF-SZ       23659   The number of lines (including one blank line) in the lower part of the screen.
S-TOP       23660   (2) Line number of top line in an automatic listing.
OLDPPC      23662   (2) Line number that CONTINUE goes to.
OSPCC       23664   Statement number that CONTINUE goes to.
FLAGX       23665   Flags used by INPUT command and the editor.  
STRLEN      23666   (2) Used when variables are assigned to.
T-ADDR      23668   (2) Address of next item in syntax table.
SEED        23670   (2) Random number seed. Set by RANDOMIZE.
FRAME       23672   Current frame (0-59).
TIME-T      23673   (4) POSIX time (unsigned).
COORD-Y     23677   Y pixel co-ordinate (0-255).
COORD-X     23678   X pixel co-ordinate (0-65535).
NMIADD      23680   Address to jump to on non-maskable interrupt.
ECHO-E      23682   (2) 33 column number and 24 line number (in lower half) of end of input buffer.  
DF-CC       23684   (2) Address in display file of upper window PRINT position.  
DF-CCL      23686   (2) Address in display file of lower window PRINT position.  
S-POSN      23688   (2) Upper window position as column/row.  
SPOSNL      23690   (2) Lower window position as column/row.  
SCR-CT      23692   (2) Counter used to give “Scroll?” prompt.  
ATTR-P      23693   Attributes used by mode 0.  
MASK-P      23694   Mask used by mode 0. Bits which are 1 make the corresponding attribute bit be taken from the screen, not ATTRP.  
ATTR-T      23695   Temporary version of ATTR-P.  
MASK-T      23696   Temporary version of MASK-P.  
P-FLAG      23697   Bit 4 and 5 are set for paper 9, bit 6 and 7 for pen 9.  
MEMBOT      23698   (30) Calculator’s memory area.  
DOSVAR      23728   (2) Used by the operating system.  
RAMTOP     23730   (2) Address of last byte of BASIC system area.  
P-RAMT      23732   (2) Address of last byte of physical RAM.

Flags

The individual bits of certain system variables are flags as follows:

FLAGS

0: Set to suppress a leading space. 5: Set if function key macros are enabled. 6: Set if scanning result is numeric.
7: Reset if checking syntax.

VDU-FLAG

0: Set if lower screen in use.
3: Set if editing a line.
4: Set if an automatic listing required. 5: Set if lower screen to be cleared.

FLAGS2

0: Set if main screen to be cleared.
1: Set if software defined screen in use.
2: Set if a : is within quotes.
3: Set if caps lock on.
4: Set if K channel in use. 5: Set if next character should be treated as a printable character. 
6: Set if next character should be over-printed at the previous location. 7: Set if trace enabled.

FLAGX

0: Set if handling a simple string.
1: Set if handling a new variable.
5: Set if in input mode.
7: Set if handling INPUT LINE.

ONERR-H`

0-7: Set to STOP.
1-6: Set to CONTINUE.
6-7: Reset to GOTO.

Programmable sound generator

The Chloe 280SE's PSG (programmable sound generator) is clocked at 1.75MHz. However, SE Basic IV can also run on hardware with PSGs clocked at other speeds. Note tables are provided for the most common variants.

Uno / Pentagon @ 1.75000 Mhz

                Ideal            Tune Registers   Actual
Note  Octave  Frequency  Period   Coarse  Fine   Frequency
 C      1       32.703    3344      13     16      32.708
 C#     1       34.648    3157      12     85      34.645
 D      1       36.708    2980      11    164      36.703
 D#     1       38.891    2812      10    252      38.896
 E      1       41.203    2655      10     95      41.196
 F      1       43.654    2506       9    202      43.645
 F#     1       46.249    2365       9     61      46.247
 G      1       48.999    2232       8    184      49.003
 G#     1       51.913    2107       8     59      51.910
 A      1       55.000    1989       7    197      54.990
 A#     1       58.270    1877       7     85      58.271
 B      1       61.735    1772       6    236      61.724
 C      2       65.406    1672       6    136      65.416
 C#     2       69.296    1578       6     42      69.312
 D      2       73.416    1490       5    210      73.406
 D#     2       77.782    1406       5    126      77.792
 E      2       82.407    1327       5     47      82.423
 F      2       87.307    1253       4    229      87.291
 F#     2       92.499    1182       4    158      92.534
 G      2       97.999    1116       4     92      98.006
 G#     2      103.826    1053       4     29     103.870
 A      2      110.000     994       3    226     110.035
 A#     2      116.541     939       3    171     116.480
 B      2      123.471     886       3    118     123.448
 C      3      130.813     836       3     68     130.831
 C#     3      138.591     789       3     21     138.625
 D      3      146.832     745       2    233     146.812
 D#     3      155.563     703       2    191     155.583
 E      3      164.814     664       2    152     164.721
 F      3      174.614     626       2    114     174.720
 F#     3      184.997     591       2     79     185.068
 G      3      195.998     558       2     46     196.013
 G#     3      207.652     527       2     15     207.543
 A      3      220.000     497       1    241     220.070
 A#     3      233.082     469       1    213     233.209
 B      3      246.942     443       1    187     246.896
 C      4      261.626     418       1    162     261.663
 C#     4      277.183     395       1    139     276.899
 D      4      293.665     372       1    116     294.019
 D#     4      311.127     352       1     96     310.724
 E      4      329.628     332       1     76     329.443
 F      4      349.228     313       1     57     349.441
 F#     4      369.994     296       1     40     369.510
 G      4      391.995     279       1     23     392.025
 G#     4      415.305     263       1      7     415.875
 A      4      440.000     249       0    249     439.257
 A#     4      466.164     235       0    235     465.426
 B      4      493.883     221       0    221     494.910
 C      5      523.251     209       0    209     523.325
 C#     5      554.365     197       0    197     555.203
 D      5      587.330     186       0    186     588.038
 D#     5      622.254     176       0    176     621.449
 E      5      659.255     166       0    166     658.886
 F      5      698.456     157       0    157     696.656
 F#     5      739.989     148       0    148     739.020
 G      5      783.991     140       0    140     781.250
 G#     5      830.609     132       0    132     828.598
 A      5      880.000     124       0    124     882.056
 A#     5      932.328     117       0    117     934.829
 B      5      987.767     111       0    111     985.360
 C      6     1046.502     105       0    105    1041.667
 C#     6     1108.731      99       0     99    1104.798
 D      6     1174.659      93       0     93    1176.075
 D#     6     1244.508      88       0     88    1242.898
 E      6     1318.510      83       0     83    1317.771
 F      6     1396.913      78       0     78    1402.244
 F#     6     1479.978      74       0     74    1478.041
 G      6     1567.982      70       0     70    1562.500
 G#     6     1661.219      66       0     66    1657.197
 A      6     1760.000      62       0     62    1764.113
 A#     6     1864.655      59       0     59    1853.814
 B      6     1975.533      55       0     55    1988.636
 C      7     2093.005      52       0     52    2103.365
 C#     7     2217.461      49       0     49    2232.143
 D      7     2349.318      47       0     47    2327.128
 D#     7     2489.016      44       0     44    2485.795
 E      7     2637.020      41       0     41    2667.683
 F      7     2793.826      39       0     39    2804.487
 F#     7     2959.955      37       0     37    2956.081
 G      7     3135.963      35       0     35    3125.000
 G#     7     3322.438      33       0     33    3314.394
 A      7     3520.000      31       0     31    3528.226
 A#     7     3729.310      29       0     29    3771.552
 B      7     3951.066      28       0     28    3906.250
 C      8     4186.009      26       0     26    4206.731
 C#     8     4434.922      25       0     25    4375.000
 D      8     4698.636      23       0     23    4755.435
 D#     8     4978.032      22       0     22    4971.591
 E      8     5274.041      21       0     21    5208.333
 F      8     5587.652      20       0     20    5468.750
 F#     8     5919.911      18       0     18    6076.389
 G      8     6271.927      17       0     17    6433.824
 G#     8     6644.875      16       0     16    6835.938
 A      8     7040.000      16       0     16    6835.938
 A#     8     7458.620      15       0     15    7291.667
 B      8     7902.133      14       0     14    7812.500

Timex TS2068 @ 1.76400 Mhz

                Ideal            Tune Registers   Actual
Note  Octave  Frequency  Period   Coarse  Fine   Frequency
 C      1       32.703    3371      13     43      32.705
 C#     1       34.648    3182      12    110      34.648
 D      1       36.708    3003      11    187      36.713
 D#     1       38.891    2835      11     19      38.889
 E      1       41.203    2676      10    116      41.200
 F      1       43.654    2526       9    222      43.646
 F#     1       46.249    2384       9     80      46.246
 G      1       48.999    2250       8    202      49.000
 G#     1       51.913    2124       8     76      51.907
 A      1       55.000    2005       7    213      54.988
 A#     1       58.270    1892       7    100      58.272
 B      1       61.735    1786       6    250      61.730
 C      2       65.406    1686       6    150      65.391
 C#     2       69.296    1591       6     55      69.296
 D      2       73.416    1502       5    222      73.402
 D#     2       77.782    1417       5    137      77.805
 E      2       82.407    1338       5     58      82.399
 F      2       87.307    1263       4    239      87.292
 F#     2       92.499    1192       4    168      92.492
 G      2       97.999    1125       4    101      98.000
 G#     2      103.826    1062       4     38     103.814
 A      2      110.000    1002       3    234     110.030
 A#     2      116.541     946       3    178     116.543
 B      2      123.471     893       3    125     123.460
 C      3      130.813     843       3     75     130.783
 C#     3      138.591     796       3     28     138.505
 D      3      146.832     751       2    239     146.804
 D#     3      155.563     709       2    197     155.501
 E      3      164.814     669       2    157     164.798
 F      3      174.614     631       2    119     174.723
 F#     3      184.997     596       2     84     184.983
 G      3      195.998     563       2     51     195.826
 G#     3      207.652     531       2     19     207.627
 A      3      220.000     501       1    245     220.060
 A#     3      233.082     473       1    217     233.087
 B      3      246.942     446       1    190     247.197
 C      4      261.626     421       1    165     261.876
 C#     4      277.183     398       1    142     277.010
 D      4      293.665     375       1    119     294.000
 D#     4      311.127     354       1     98     311.441
 E      4      329.628     334       1     78     330.090
 F      4      349.228     316       1     60     348.892
 F#     4      369.994     298       1     42     369.966
 G      4      391.995     281       1     25     392.349
 G#     4      415.305     265       1      9     416.038
 A      4      440.000     251       0    251     439.243
 A#     4      466.164     237       0    237     465.190
 B      4      493.883     223       0    223     494.395
 C      5      523.251     211       0    211     522.512
 C#     5      554.365     199       0    199     554.020
 D      5      587.330     188       0    188     586.436
 D#     5      622.254     177       0    177     622.881
 E      5      659.255     167       0    167     660.180
 F      5      698.456     158       0    158     697.785
 F#     5      739.989     149       0    149     739.933
 G      5      783.991     141       0    141     781.915
 G#     5      830.609     133       0    133     828.947
 A      5      880.000     125       0    125     882.000
 A#     5      932.328     118       0    118     934.322
 B      5      987.767     112       0    112     984.375
 C      6     1046.502     105       0    105    1050.000
 C#     6     1108.731      99       0     99    1113.636
 D      6     1174.659      94       0     94    1172.872
 D#     6     1244.508      89       0     89    1238.764
 E      6     1318.510      84       0     84    1312.500
 F      6     1396.913      79       0     79    1395.570
 F#     6     1479.978      74       0     74    1489.865
 G      6     1567.982      70       0     70    1575.000
 G#     6     1661.219      66       0     66    1670.455
 A      6     1760.000      63       0     63    1750.000
 A#     6     1864.655      59       0     59    1868.644
 B      6     1975.533      56       0     56    1968.750
 C      7     2093.005      53       0     53    2080.189
 C#     7     2217.461      50       0     50    2205.000
 D      7     2349.318      47       0     47    2345.745
 D#     7     2489.016      44       0     44    2505.682
 E      7     2637.020      42       0     42    2625.000
 F      7     2793.826      39       0     39    2826.923
 F#     7     2959.955      37       0     37    2979.730
 G      7     3135.963      35       0     35    3150.000
 G#     7     3322.438      33       0     33    3340.909
 A      7     3520.000      31       0     31    3556.452
 A#     7     3729.310      30       0     30    3675.000
 B      7     3951.066      28       0     28    3937.500
 C      8     4186.009      26       0     26    4240.385
 C#     8     4434.922      25       0     25    4410.000
 D      8     4698.636      23       0     23    4793.478
 D#     8     4978.032      22       0     22    5011.364
 E      8     5274.041      21       0     21    5250.000
 F      8     5587.652      20       0     20    5512.500
 F#     8     5919.911      19       0     19    5802.632
 G      8     6271.927      18       0     18    6125.000
 G#     8     6644.875      17       0     17    6485.294
 A      8     7040.000      16       0     16    6890.625
 A#     8     7458.620      15       0     15    7350.000
 B      8     7902.133      14       0     14    7875.000

Spectrum 128 @ 1.77345 Mhz

                Ideal            Tune Registers   Actual
Note  Octave  Frequency  Period   Coarse  Fine   Frequency
 C      1       32.703    3389      13     61      32.706
 C#     1       34.648    3199      12    127      34.649
 D      1       36.708    3020      11    204      36.702
 D#     1       38.891    2850      11     34      38.891
 E      1       41.203    2690      10    130      41.205
 F      1       43.654    2539       9    235      43.655
 F#     1       46.249    2397       9     93      46.241
 G      1       48.999    2262       8    214      49.001
 G#     1       51.913    2135       8     87      51.916
 A      1       55.000    2015       7    223      55.008
 A#     1       58.270    1902       7    110      58.276
 B      1       61.735    1795       7      3      61.750
 C      2       65.406    1695       6    159      65.393
 C#     2       69.296    1600       6     64      69.275
 D      2       73.416    1510       5    230      73.404
 D#     2       77.782    1425       5    145      77.783
 E      2       82.407    1345       5     65      82.409
 F      2       87.307    1270       4    246      87.276
 F#     2       92.499    1198       4    174      92.521
 G      2       97.999    1131       4    107      98.002
 G#     2      103.826    1068       4     44     103.783
 A      2      110.000    1008       3    240     109.961
 A#     2      116.541     951       3    183     116.552
 B      2      123.471     898       3    130     123.431
 C      3      130.813     847       3     79     130.863
 C#     3      138.591     800       3     32     138.551
 D      3      146.832     755       2    243     146.809
 D#     3      155.563     713       2    201     155.457
 E      3      164.814     673       2    161     164.696
 F      3      174.614     635       2    123     174.552
 F#     3      184.997     599       2     87     185.043
 G      3      195.998     566       2     54     195.831
 G#     3      207.652     534       2     22     207.567
 A      3      220.000     504       1    248     219.922
 A#     3      233.082     476       1    220     232.858
 B      3      246.942     449       1    193     246.861
 C      4      261.626     424       1    168     261.417
 C#     4      277.183     400       1    144     277.102
 D      4      293.665     377       1    121     294.007
 D#     4      311.127     356       1    100     311.350
 E      4      329.628     336       1     80     329.883
 F      4      349.228     317       1     61     349.655
 F#     4      369.994     300       1     44     369.469
 G      4      391.995     283       1     27     391.663
 G#     4      415.305     267       1     11     415.133
 A      4      440.000     252       0    252     439.844
 A#     4      466.164     238       0    238     465.717
 B      4      493.883     224       0    224     494.824
 C      5      523.251     212       0    212     522.833
 C#     5      554.365     200       0    200     554.203
 D      5      587.330     189       0    189     586.458
 D#     5      622.254     178       0    178     622.700
 E      5      659.255     168       0    168     659.766
 F      5      698.456     159       0    159     697.111
 F#     5      739.989     150       0    150     738.938
 G      5      783.991     141       0    141     786.104
 G#     5      830.609     133       0    133     833.388
 A      5      880.000     126       0    126     879.688
 A#     5      932.328     119       0    119     931.434
 B      5      987.767     112       0    112     989.648
 C      6     1046.502     106       0    106    1045.666
 C#     6     1108.731     100       0    100    1108.406
 D      6     1174.659      94       0     94    1179.156
 D#     6     1244.508      89       0     89    1245.400
 E      6     1318.510      84       0     84    1319.531
 F      6     1396.913      79       0     79    1403.046
 F#     6     1479.978      75       0     75    1477.875
 G      6     1567.982      71       0     71    1561.136
 G#     6     1661.219      67       0     67    1654.338
 A      6     1760.000      63       0     63    1759.375
 A#     6     1864.655      59       0     59    1878.655
 B      6     1975.533      56       0     56    1979.297
 C      7     2093.005      53       0     53    2091.333
 C#     7     2217.461      50       0     50    2216.813
 D      7     2349.318      47       0     47    2358.311
 D#     7     2489.016      45       0     45    2463.125
 E      7     2637.020      42       0     42    2639.063
 F      7     2793.826      40       0     40    2771.016
 F#     7     2959.955      37       0     37    2995.693
 G      7     3135.963      35       0     35    3166.875
 G#     7     3322.438      33       0     33    3358.807
 A      7     3520.000      31       0     31    3575.504
 A#     7     3729.310      30       0     30    3694.688
 B      7     3951.066      28       0     28    3958.594
 C      8     4186.009      26       0     26    4263.101
 C#     8     4434.922      25       0     25    4433.625
 D      8     4698.636      24       0     24    4618.359
 D#     8     4978.032      22       0     22    5038.210
 E      8     5274.041      21       0     21    5278.125
 F      8     5587.652      20       0     20    5542.031
 F#     8     5919.911      19       0     19    5833.717
 G      8     6271.927      18       0     18    6157.813
 G#     8     6644.875      17       0     17    6520.037
 A      8     7040.000      16       0     16    6927.539
 A#     8     7458.620      15       0     15    7389.375
 B      8     7902.133      14       0     14    7917.188

DMA

The DMA engine can do these types of transfer:

  • Memory to memory (both using incrementing addresses)
  • Memory to I/O (memory address incrementing)
  • I/O to memory (memory address incrementing)
  • I/O to I/O

Like the CPU, the DMA can only access a 64K address space. Any memory paging that affects the CPU also affects the DMA.

It can operate in foreground, halting the main CPU during the transfer, or in the background, allowing the CPU to continue working (although slightly slower than usual).

Two types of transfers are possible. Burst transfers move data as fast as possible, typically halting the CPU during transfer. Timed transfers move data at a specified rate, controlled by an onchip timer. Timed transfers are best suited for audio streaming directly from memory to DAC.

Transfers can be retriggerable, or one time. When a retriggerable transfer ends, it automatically restarts from the beginning. One time transfers do not restart. Burst transfers cannot be retriggerable.

For a non-CPU halting transfer, the DMA can be queried to return if a given source or destination address has been reached.

The DMA does not trigger CPU interrupts.

The DMA registers are part of the Uno group of registers. Port #FC3B selects the register to write to:

  • $A0: DMActrl Control register. Reading it returns the last written value. A DMA transfer is initiated from the stop condition, by writing any value other than 0 into the MODE bits. Stopping and re-starting a DMA transfer does not resume it; it starts from the beginning.
    • D0-1: MODE:
      • 00 DMA is stopped. You can stop a timed DMA at any time by writing %00 to MODE.
      • 01 Burst DMA transfer. CPU is halted during the transfer.
      • 10 Timed DMA transfer.
      • 11 Retrigerrable timed DMA transfer.
    • D2: DST: 0 if destination address is memory. 1 if destination address is I/O.
    • D3: SRC: 0 if source address is memory. 1 if source address is I/O.
    • D4: PROB: 0 if address in DMAprob is related to source (read) memory address. 1 ifaddress in DMAprob is related to destination (write) memory address.
    • D5-7: Reserved. Written and read as 0.
  • $A1: DMAsrc Holds the source address for a memory-to-memory transfer, or memory-to-I/O transfer. Holds the I/O source address for a I/O-to-memory transfer, or I/O-to-I/O transfer. It requires two reads or two writes to transfer a little-endian 16-bit value to or from the register. The value of the register is not changed during or after a transfer.
  • $A2: DMAdst Holds the I/O destination address for an I/O-to-memory transfer, or an I/O-to-I/O transfer. It requires two reads or two writes to transfer a little-endian 16-bit value to or from the register. The value of the register is not changed during or after a transfer.
  • $A3: DMApre Holds the 16-bit preescaler value used to determine the frequency rate for a timed transfer. It requires two reads or two writes to transfer a little-endian 16-bit value to or from the register. The value of the register is not changed during or after a transfer. The actual rate is determined by these formula:
    • Transfers per second = 28000000 / preescaler_value (for memory to memory transfers)
    • Transfers per second = 3500000 / preescaler_value (for transfers involving some sort of I / O address)
  • $A4: DMAlen Holds the transfer byte length. 0 means 65536 bytes to transfer. It requires two reads or two writes to transfer a little-endian 16-bit value to or from the register. The value of the register is not changed during or after a transfer.
  • $A5: DMAprob Holds the 16-bit value that identifies the memory address involved in a DMA transfer (it can be a source or destination address). When the DMA reads from (if configured as a source address) or writes to (if configured as a destination address) this memory address, bit 7 of DMAstat is set. It requires two reads or two writes to transfer a little-endian 16-bit value to or from the register. The value of the register is not changed during or after a transfer.
  • $A6: DMAstat (read-only) The status register currently uses only bit 7. It is set to 1 when DMAprob address is reached. Reading this register resets its value to 0.

I/O ports

DAC

The 8-bit digital to analog converter (DAC) is available on two different ports:

  • #DF (SpecDrum)
  • #B3 (Covox)

To avoid hitting other hardware, set the high byte of BC to $FF before issuing an OUT (C), A instruction.

K-mouse

The mouse can be read directly using the MouseData and MouseStatus registers on the Uno ports. But typically it is easier to read the K-mouse ports.

  • #FADF: Button status.
    • D0: 0 if right button pressed
    • D1: 0 if leftbutton pressed
    • D2: 0 if middle button pressed
    • D3: 0 if fourth button pressed
    • D4-7: mouse wheel position (defaults to 1111)
  • #FBDF: Horizontal position (x-axis)
  • #FFDF: Vertical position (y-axis)

K-stick

The joystick I/O behavior is configurable. By default it is read using port #1F. A 1 incidates active.

  • D0: Right
  • D1: Left
  • D2: Down
  • D3: Up
  • D4: Fire button 1
  • D5:
  • D6:
  • D7:

Keyboard

Port #FE is used to read the 40-key keyboard matrix:

    INP:   Reads keys (bit 0 to bit 4 inclusive)
    #FEFE  SHIFT, Z, X, C, V    #EFFE  0, 9, 8, 7, 6
    #FDFE  A, S, D, F, G        #DFFE  P, O, I, U, Y
    #FBFE  Q, W, E, R, T        #BFFE  ENTER, L, K, J, H
    #F7FE  1, 2, 3, 4, 5        #7FFE  SPACE, SYM SHFT, M, N, B

Reading bit 6 of port #FE returns the input of the mono line-in.

Writing to port #FE has the following effect:

  • D0-2: Set border color (0 to 7)
  • D3: Enable Mic (activate 1-bit speaker)
  • D4: Enable Ear (activate 1-bit speaker)
  • D4-7: Reserved

MMU

The bit pattern of the byte sent to port #F4 sets which 8K pages of the shadow RAM are mapped over main RAM. For example, %10000000 would page in chunk 7 at $E000-$FFFF. The Ex bank or Dock bank are selected with bit 7 of the SCLD register. By default this is 0 (Dock).

By default, when shadow RAM is available, SE Basic IV sets the middle 32K of address space to be shadow RAM, effectively: OUT ($F4), %00111100. In normal operation you should not change this value. If you set the middle 32K of address space to be main RAM, then Bank 5 (the shadow frame buffer) is paged from $4000 to $7FFF and Bank 2 is paged from $8000 to $BFFF. Both those banks can be paged in at $C000 using the Paging register, and leaving the middle 32K as shadow RAM provides a contiguous 24K for code with 128K of pageable RAM in the top 16K of the address space.

Bank 0-6 can be selected using the Paging register. Bank 7 is reserved for the frame buffer, so to get all 128K you must set the top 16K to be shadow RAM, effectively: OUT ($F4), %11111100. Note, you should not attempt to write to the screen when the top 16K of shadow RAM is paged in, because it masks main RAM, rendering the frame buffer inaccessible.

Paging

In run mode, a total of 256K RAM is directly available to the user. This comprises 128K of Home RAM pageable in 16K chunks, and two 64K banks of shadow RAM (Dock and Ex banks) pageable in 8K chunks. The shadow RAM banks are mutually exclusive, so in practice it ie easier to use only one bank of shadow RAM. At boot, SE Basic IV sets the middle 32K of the address space to shadow RAM and sets the page at $C000 to Bank 0. The frame buffer uses Bank 7, but the top 16K of shadow RAM can be paged in at $C000 to provide a total of eight 16K RAM pages (128) in addition to the 24K of shadow RAM available from $6000 to $BFFF. Note, because shadow RAM masks main RAM, you must not attempt to write to the screen (Bank 7) if Dock 6-7 is paged in at $C000. Also, writes to the screen will page in Bank 7 to do the screen write and then set Bank 0, so you may need to reset the bank after writing to the screen.

The memory map of SE Basic IV on boot is:

$ffff +--------+--------+--------+--------+--------+--------+--------+--------+
      | Bank 0 | Bank 1 | Bank 2 | Bank 3 | Bank 4 | Bank 5 | Bank 6 | Dock   |
      |        |        |        |        |        |        |        | 6-7    |
      |        |        |        |        |        |        |        |        |
      |        |        |        |        |        |        |        |        |
$c000 +--------+--------+--------+--------+--------+--------+--------+--------+
      | Dock   |        Any one of these pages may be switched in.
      | 4-5    |
      |        |
      |        |
$8000 +--------+
      | Dock   |
      | 2-3    |
      |        |
      |        |
$4000 +--------+
      | ROM 1  |
      |        |
      |        |
      |        |
$0000 +--------+

To select Bank 0 to 6 write to port #7FFD:

  • D0-2: Bank (0 to 6) to map into memory at $C000.
  • D3: Framebuffer select. You should leave this as 1 unless you are doing back buffering:
    • 0: Use Bank 5 as framebuffer
    • 1: Use Bank 7 as framebuffer
  • D4: ROM select. You should always leave this as 1.
    • 0: Boot ROM
    • 1: BASIC ROM
  • D5: When set to 1, further writes to port #7FFD are ignored until a reset takes place.
  • D6-7: Reserved.

Palette

  • #BF3B: register select
  • #FF3B: data

To switch off palette mode, OUT ($BF3B), 64: OUT ($FF3B), 0. Registers 0 to 63 are the palette entries. Palette entries are stored in G3R3B2 format.

PSG

  • #BFFD: data
  • #FFFD: register select

To select channels A to C, OUT ($FFFD), 255. To select channels D to F, `OUT ($FFFD), 255).

Audio panning is set using port #F7 with bit pairs read left to right (big-endian) for channels ABC and the speaker/DAC:

  • 10: pan left
  • 11: pan middle
  • 01: pan right
  • 00: mute channel

By default this is set to %10011111 (ACB stereo with the speaker/DAC going to left and right speakers).

SCLD

  • D0-2: Mode:
    • 000: 256x192 pixles, 8x8 attributes, offset $0000.
    • 001: 256x192, 8x8 attributes, offset $2000.
    • 010: 256x192, 8x1 attributes.
    • 110: 512x192, mono
  • D3-5: Color settings for mono mode
    • 000: Foreground 0, background 7.
    • 001: Foreground 1, background 6.
    • 010: Foreground 2, background 5.
    • 011: Foreground 3, background 4.
    • 100: Foreground 4, background 3.
    • 101: Foreground 5, background 2.
    • 110: Foreground 6, background 1.
    • 111: Foreground 7, background 0.
  • D6: When set to 1, timer interrupt is switched off.
  • D7: Select shadow RAM bank used by MMU.
    • 0: Dock
    • 1: Ex

Uno

Ports $FC3B and $FD3B are used to configure the Uno's ZX core. These ports provide access to up to 256 registers.

  • $FC3B (64571): Register. Write to select a regiser. Read to find last register selected. Note, when interrupts are enabled, SE Basic IV continually updates this register to read the keyboard.
  • $FD3B (64827): Data. The behavior of this port when reading and writing depends on the register selected.

$00 UnoConf R/W

Binary format (fields in bold, the can be altered only when LOCK = 0):

D7 D6 D5 D4 D3 D2 D1 D0
LOCK MODE1 DISCONT MODE0 I2KB DISNMI DIVEN BOOTM
  • BOOTM:
    • 0: Run mode.
    • 1: Boot mode (configuration mode). Used by the firmware, where you can configure some aspects of the hardware before entering run mode. Also required to access the full 512K of RAM.
  • DIVEN:
    • 0 (default): divMMC not enabled. SPI interface access ports of the SD / MMC slot are still available. Memory used by divMMC available for other uses.
    • 1: divMMC enabled. Before entering run mode, an OS image must be loaded into the corresponding RAM bank.
  • DISNMI:
    • 0 (default): OS handles NMI events.
    • 1: BASIC handles NMI events.
  • I2KB:
    • 0 (default): Port #FE behaves as issue 3.
    • 1: Port #FE behaves as issue 2.
  • MODE1, MODE0:
    • 00: PAL, 312 lines
    • 01: PAL, 311 lines
    • 10: PAL, 320 lines
    • 11: NTSC, 262 lines
  • DISCONT:
    • 0: Video contention enabled. CPU halted during VDP framebuffer access.
    • 1: No video contention.
  • LOCK:
    • 0: Set by cold start or hard reset.
    • 1: Prevents further changes to certain bits of the UnoConf register and prevents access to the flash SPI.

UnoConf can always be read, both in boot mode and run mode.

It is set to %00000001 on cold start or hard reset. It is unaffected by a soft reset.

$01 UnoMapper R/W

In boot mode, sets the 16K RAM bank (0 to 31) paged at $C000 to $FFFF. Permits a maximum of 4MB of RAM. Ignored in run mode.

It is set to %00000000 on cold start or hard reset. It is unaffected by a soft reset.

$02 FlashSPI R/W

Values written to the port are sent to the SPI flash. Reading the port returns the last value written and changes the next value read. Therefore, in block read operations you must discard the first byte read.

It is set to %00000000 on cold start. It is unaffected by a hard or soft reset.

$03 FlashCS R/W

Bit 0 only is used to set the status of the CS line of the Flash SPI:

  • 0: Flash selected.
  • 1: Flash not selected.

It is set to %00000001 on cold start. It is unaffected by a hard or soft reset.

$04 ScanCode R/W

Read to obtain the last PS/2 scan code from the keyboard. Written to send commands to the keyboard.

$05 KeyStat R/W

Key status:

D7 D6 D5 D4 D3 D2 D1 D0
BSY 0 0 0 ERR RLS EXT PEN
  • BSY: 1 when a data transmission to the PS/2 port is still in progress. You must wait for 0 to start a new transmission.
  • ERR: 1 when the last transmission to or from the PS/2 port had errors.
  • RLS: 1 when the last event belongs to a key that has been released.
  • EXT: 1 when the last event belongs to a key with an extended code (E0 + scancode).
  • PEN: 1 when there is new data ready to be read in the SCANCODE register. After reading KeyStat, this bit is reset to 0.

$06 JoyConf R/W

  • D0-3: keyboard-mapped joystick
  • D4-7: DB9 joystick port If bit a is 1, auto-fire is enabled.
    • a000: no joystick
    • a001: Kempston (K-stick)
    • a010: Sinclair 1
    • a011: Sincalir 2
    • a100: Protek / Curosr / AGF
    • a101: Fuller

It is set to %00010000 on cold start. It is unaffected by a hard or soft reset.

$07 KeyMap R/W

When read, returns the next byte of the key map (4KB in the current core, 16KB in earlier cores). When written replaces the next byte of the key map. The pointer is reset to 0 after a reset, a write to the #FC3B register or when the key map is terminated. A key map can be loaded at boot time by specifying it in the CONFIG.SYS file.

$08 NMIevent R/W

Deprecated.

$09 MouseData R/W

Read to obtain the last PS/2 data from the mouse. Written to send commands to the mouse. For example, to initialize the mouse, the value $F4 must be sent to this register.

$0A MouseStatus R/W

Mouse status:

D7 D6 D5 D4 D3 D2 D1 D0
BSY 0 0 0 ERR 0 0 PEN
  • BSY: 1 when a data transmission to the PS/2 port is in progress. You must wait for 0 to start a new transmission.
  • ERR: 1 if the last transmission to or from the PS/2 port had errors.
  • PEN: 1 when there is new data ready to be read in the MouseData register. After reading MouseStatus, this bit is reset to 0.

$0B ScanDblCtrl R/W

Scandoubler is mainly used to set timings.

D7 D6 D5 D4 D3 D2 D1 D0
TURBO1 TURBO0 COPT FREQ2 FREQ1 FREQ0 ENSCAN VGA
  • TURBO: CPU speed:
    • 00: 3.5 MHz
    • 01: 7.0 MHz
    • 10: 14.0 MHz
    • 11: 28.0 MHz
  • COPT: composite sync for RGB and composite
    • 0: ULA
    • 1: PAL
  • FREQ: Vertical refresh rate. Note, this scales all timings to preserve raster effects. You should leave this at %000 unless your monitor has problems at that frequency.
    • 000: 50 Hz 48 / Pentagon
    • 001: 50 Hz 128
    • 010: 52 Hz
    • 011: 53 Hz
    • 100: 55 Hz
    • 101: 57 Hz
    • 110: 59 Hz
    • 111: 60 Hz
  • ENSCAN: Set to 1 to enable fake scanlines in VGA mode only.
  • VGA: Typically, even with a VGA display the scandoubler should be switched off. It can be configured in the CONFIG.SYS file.
    • 0: Switch off scandoubler for 5kHz RGB / composite video output.
    • 1: The scandoubler output is the same as the normal RGB output, but doubling the horizontal delay frequency.

It is set to %11100000 on cold start. It is unaffected by a hard or soft reset.

$0C RasterLine R/W

Combined with the value of LINE8 in RasterCtrl to set the scan line (0 to 511) on which the raster interrup is triggered.

In practice, the largest value is limited by the number of lines generated by the VDP as set in the MODE value of UnoConf (311, 310, 319 or 261). If a line number greater than the limit is set, the raster interrupt will not occur.

A screen line is made up of right edge + horizontal blanking interval + left edge + paper area. Therefore, a value of 0 triggers the interrupt just as the right edge of the line before the first screen line begins. A value of 192 triggers the raster interrupt at the beginning of the bottom edge.

The line numbers for the end of the bottom edge and the beginning of the top edge depend on the video timings set in the UnoConf register. In practice, the largest possible value (511) triggers a raster interrupt on the last line of the top border. It is set to 511 on cold start and hard or soft reset.

$0D RasterCtrl R/W

Control register and raster interrupt status. The following bits are defined:

D7 D6 D5 D4 D3 D2 D1 D0
INT 0 0 0 0 DISVINT ENARINT LINE8
  • INT (read only): It is worth 1 for 32 clock cycles from the moment the raster interrupt is triggered. Available even if interrupts are not enabled. It is not available if ENARINT is 0.
  • DISVINT: When set to 1, switches off vertical delay masking interrupts (the original ones from the ULA). Set to 0 after a reset.
  • ENARINT: Set to 1 to enable masking interrupts per raster line. Set to 0 after a reset.
  • LINE8: Bit 8 of RasterLine.

$0E DevControl R/W

Control various device properties.

D7 D6 D5 D4 D3 D2 D1 D0
DISD ENMMU DIROMSEL1F DIROMSEL7F DI1FFD DI7FFD DITAY DIAY
  • DISD: Set to 1 to switch off the SPI hardware interface for SD (divMMC). Uses ports #1F, #3F, #E7 and #EB.
  • ENMMU: Set to 1 to enable the shadow RAM (horizontal MMU). Uses bit 7 of port #FF, port #F4 is useda read from port #FF returns the last value written in it.
  • DIROM1F: The value of this bit is masked with the value of bit 2 of port #1FFD. When set to 1, the value of bit 2 to of port #1FFD is always 0.
  • DIROM7F: The value of this bit is masked with the value of bit 4 of port $ 7FFD. When set to 1, the value of bit 4 of port #7FFD is always 0.
  • DI1FFD: When set to 1 switches off +3 compatible paging. Uses port #1FFD. Always 1 when DI7FFD is 1.
  • DI7FFD: Set to 1 to switch off 128 compatilbe paging system.
  • DITAY: Set to 1 to switch off PSG channels D to F. Always 1 when DIAY is 1.
  • DIAY: Set to 1 to switch off PSG channels A to C.

Set to %01101000 on cold boot.

$0F DevCtrl2 R/W

Control various device properties.

D7 D6 D5 D4 D3 D2 D1 D0
- - - - - DIRADAS DITIMEX DIULAPLUS
  • D7-D3: Reserved. Must contain %00000 or no change is made to the hardawre.
  • DIRADES: Set to 1 to switch off Radastanian dispaly mode. When set to 0, DIULAPLUS must also be set to 0.
  • DITIMEX: Set to 1 to switch off Timex display modes. Writing to port #FF is then ignored and if the Timex MMU is enabled, a read from port #FF returns 0.
  • DIULAPLUS: Set to 1 to switch off palette support. If contention is enabled, it continues to function.

Set to %00000100 on cold boot.

$40-43 Radastanian R/W

The registers in this range control a very low resolution 16-color video mode that is not directly supported by SE Basic IV. For more details see the ZX uno wiki.

$80 HOffs48K R/W

Screen horizontal centering adjustment value for 48 ULA.

$81 VOffs48K R/W

Screen vertical centering adjustment value for 48 ULA.

$82 HOffs128K R/W

Screen horizontal centering adjustment value for 128 ULA.

$83 VOffs128K R/W

Screen vertical centering adjustment value for 128 ULA.

$84 HOffsPen R/W

Screen horizontal centering adjustment value for Pentagon ULA.

$85 VOffsPen R/W

Screen vertical centering adjustment value for Pentagon ULA.

$A0-$A6 DMA R/W

See DMA

$C0-$DF reserved R/W

Range of Uno registers reserved for experiments or private use

$FB AD724 R/W

Control of the AD724 encoder chip operating mode. Bits 7-1 are reserved. Bit 0 sets the operating mode:

  • 0: PAL
  • 1: NTSC

It is set to %00000001 on cold start. It is unaffected by a hard or soft reset.

$FC CoreAddr R/W

Stores the 24-bit address in the SPI memory of a core to be started. Three bytes in big-endian format are written or read in succession.

$FD CoreBoot WO

Sending 1 to this port instructs the FPGA to start another core from address COREADDR. Bits 7-1 are reserved and must be set to 0. If no change is made to COREADDR, this effectively performs a cold restart.

$FE ColdBoot

Deprecated

$FF CoreID RO

Reading this port returns the next ASCII character in the string containing the current revision of the Uno core. When the string ends, subsequent reads return 0 until the pointer goes back to the start of the string. This happens automatically after a reset or write to port #FC3B. The string can contain only ASCII codes 32 to 127

Accessing extended RAM

The full 512K of RAM can only be accessed in Boot mode. This is extremely hazardous because RAM used by the system may be overwritten. However, in the worst case scenario it should be possible to restore the system using a cold restart.

The full memory layout is as follows: Memory

In Boot mode the default memory map is as follows:

0xffff +--------+
       | SRAM   | Selected by UnoMapper
       |        |
       |        |
       |        |
0xc000 +--------+
       | Bank 2 |
       |        |
       |        |
       |        |
0x8000 +--------+
       | Bank 5 |
       |        |
       |        |
       |        |
0x4000 +--------+
       | FPGA   |
       | Boot   |
       | ROM    |
       |        |
0x0000 +--------+

The value written to UnoMapper is as follows:

Byte Value
$00 Home 0
$01 Home 1
$02 Home 2
$03 Home 3
$04 Home 4
$05 Home 5 (shadow frame buffer)
$06 Home 6
$07 Home 7 (frame buffer)
$08 Boot ROM
$09 BASIC ROM
$0A -
$0B -
$0C OS ROM
$0D -
$0E -
$0F -
$10 OS RAM 0-1
$11 OS RAM 2-3
$12 OS RAM 4-5
$13 OS RAM 6-7
$14 OS RAM 8-9
$15 OS RAM 10-11
$16 OS RAM 12-13
$17 OS RAM 14-15
$18 Ex 0-1
$19 Ex 2-3
$1A Ex 4-5
$1B Ex 6-7
$1C Dock 0-1
$1D Dock 2-3
$1E Dock 4-5
$1F Dock 6-7

Typically, you should not modify the contents of pages $09, $0C, $10 and $11. If you are short of memory, you can safely use the Boot ROM area, because it is only called on a hard reset which will restore the contents. Pages 4-15 of OS RAM are not used by UnoDOS 3 and are safe to use. If you have already loaded all the data you require from disk and will make no futhere use of the OS, you can switch off the divMMC hardware and then use pages $0C, $10 and $11. If your program makes no use of the service routines, you can use page $09.

Clone this wiki locally