Group 10 — UExt I/O Official
10,1 UExt Initialise · 10,2 Write GPIO · 10,3 Read GPIO · 10,4 Set Port Direction · 10,5 Write I2C · 10,6 Read I2C · 10,7 Read Analog · 10,8 I2C Status · 10,9 Read I2C Block · 10,10 Write I2C Block · 10,11 Read SPI Block · 10,12 Write SPI Block · 10,13 Read UART Block · 10,14 Write UART Block · 10,15 Set UART Speed and Protocol · 10,16 Write byte to UART · 10,17 Read byte from UART · 10,18 Check if Byte Available · 10,19 Route UART to USB CDC modem
The UEXT connector has 10 pins, known by their number: 1 the 3.3 V, 2 ground, 3 TXD and 4 RXD (serial port), 5 SCL and 6 SDA (I2C), 7 MISO, 8 MOSI, 9 SCK and 10 SSEL (SPI). Pins 3 to 10 also work as plain inputs and outputs; 3, 4, 8 and 9 can read a voltage (analogue input).
Using I2C or SPI, or setting up the serial port, reserves their pins: reading or writing them as plain pins then gives error 1, until 10,1. On the board, Trinity starts its debug port on TXD and RXD: pins 3 and 4 belong to it, even after 10,1 (in the emulator, they are free).
On the bench, Phosphoneo has nothing plugged into the UEXT port: its answers (level of an input, analogue value, I2C or SPI bytes) are dummy values. The examples of these functions are checked (the call is made, without error), but their output is not shown. Those that depend on the firmware alone (output latch, direction, reserved pins, errors, serial port with nothing plugged in) are published as elsewhere.
10,1 UExt Initialise Official
Puts the UEXT I/O back in their starting state: pins 3 to 10 as inputs, latches at 0, reserved pins given back.
Inputs: none.
Outputs: none.
The example writes over I2C, which reserves pins 5 and 6: pin 5 is refused (error 1), then accepted after 10,1. The debug port pins (3 and 4 on the board) stay reserved. In NeoBASIC, clear (and therefore run) makes this call; as clear also erases the variables, the NeoBASIC example writes the mailbox.
NeoBASIC keywords that make this call: clear
Firmware documentation text
Initialise the UExt I/O system. This resets the IO system to its default state, where all UEXT pins are I/O pins, inputs and enabled.
C (llvm-mos)
/* Libérer les broches prises par l'I2C (groupe 10, fonction 1). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t ecrire(uint8_t broche, uint8_t v) { /* 10,2 : rend l'indicateur d'erreur */
libre();
ControlPort.params[0] = broche;
ControlPort.params[1] = v;
api(10, 2);
return ControlPort.error;
}
int main(void) {
neo_uext_i2c_write(0x50, 0, 0); /* 10,5 : l'I2C prend les broches 5 (SCL) et 6 (SDA) */
uint8_t e1 = ecrire(5, 1);
neo_uext_init(); /* UExt Initialise : toutes les broches en entrée, libres */
uint8_t e2 = ecrire(5, 1);
printf("Apres 10,5 : broche 5, erreur %u\n", e1);
printf("Apres 10,1 : broche 5, erreur %u\n", e2);
return 0;
}Apres 10,5 : broche 5, erreur 1
Apres 10,1 : broche 5, erreur 0Mad Pascal
// Libérer les broches prises par l'I2C (groupe 10, fonction 1).
program uext1;
uses crt, neo6502, neo6502uext;
var e1, e2: byte;
function ecrire(broche, v: byte): byte; // 10,2 : rend l'indicateur d'erreur
begin
NeoWriteGPIO(broche, v);
NeoWaitMessage;
result := NeoMessage.error;
end;
begin
NeoWriteI2C($50, 0, 0); // 10,5 : l'I2C prend les broches 5 (SCL) et 6 (SDA)
e1 := ecrire(5, 1);
NeoUExtInitialize; // UExt Initialise : toutes les broches en entrée, libres
e2 := ecrire(5, 1);
writeln('Apres 10,5 : broche 5, erreur ', e1);
writeln('Apres 10,1 : broche 5, erreur ', e2);
end.Apres 10,5 : broche 5, erreur 1
Apres 10,1 : broche 5, erreur 0NeoBASIC
10 ' Liberer les broches prises par l'I2C (groupe 10, fonction 1)
20 iwrite $50, 0, 0 : ' 10,5 : l'I2C prend les broches 5 (SCL) et 6 (SDA)
30 b = 5 : v = 1 : gosub 1000 : e1 = e
40 while peek($ff00) : wend : poke $ff01, 1 : poke $ff00, 10 : ' UExt Initialise (clear le fait aussi, mais efface les variables)
50 gosub 1000 : e2 = e
60 print "Apres 10,5 : broche 5, erreur ";e1
70 print "Apres 10,1 : broche 5, erreur ";e2
80 end
1000 ' 10,2 : ecrire v sur la broche b ; erreur dans e
1010 while peek($ff00) : wend : poke $ff04, b : poke $ff05, v : poke $ff01, 2 : poke $ff00, 10
1020 while peek($ff00) : wend : e = peek($ff02)
1030 returnApres 10,5 : broche 5, erreur 1
Apres 10,1 : broche 5, erreur 065C02 assembly (64tass)
; Libérer les broches prises par l'I2C (groupe 10, fonction 1).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<i2c
ldx #>i2c
jsr envoi
lda #<ecr5
ldx #>ecr5
jsr envoi
lda ControlPort+2
sta e1
lda #<init
ldx #>init
jsr envoi
lda #<ecr5
ldx #>ecr5
jsr envoi
lda ControlPort+2
sta e2
lda #<t0
ldx #>t0
jsr ecrire
lda e1
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda e2
jsr decimal
lda #13
jsr WriteCharacter
rts
i2c: .byte 10, 5, 3, $50, 0, 0 ; 10,5 : l'I2C prend les broches 5 (SCL) et 6 (SDA)
ecr5: .byte 10, 2, 2, 5, 1 ; 10,2 : broche 5, valeur 1
init: .byte 10, 1, 0 ; 10,1 : UExt Initialise
t0: .text "Apres 10,5 : broche 5, erreur ", 0
t1: .text "Apres 10,1 : broche 5, erreur ", 0
e1: .byte 0
e2: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Apres 10,5 : broche 5, erreur 1
Apres 10,1 : broche 5, erreur 010,2 Write GPIO Official
Writes the output latch of a pin; it only shows on the pin if the pin is an output.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | pin (3 to 10) |
P1 | uint8 | 0 low, any other value high |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if the pin does not exist or is reserved |
The latch keeps its value even as an input: turning the pin back into an output (10,4) puts it back on the pin. As an output, 10,3 reads the latch back: the example therefore reads 255 then 0, with nothing plugged in. Pin 2 (ground) is refused. In NeoBASIC, pin n, v makes this call (and pin(n) returns 1 or 0, not 255 or 0).
NeoBASIC keywords that make this call: pin
Firmware documentation text
This copies the value Parameter:1 to the output latch for UEXT pin Parameter:0. This will only display on the output pin if it is enabled, and its direction is set to "Output" direction.
C (llvm-mos)
/* Écrire le verrou de sortie d'une broche (groupe 10, fonction 2). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t ecrire(uint8_t broche, uint8_t v) { /* Write GPIO : rend l'indicateur d'erreur */
libre();
ControlPort.params[0] = broche;
ControlPort.params[1] = v;
api(10, 2);
return ControlPort.error;
}
int main(void) {
neo_uext_init(); /* 10,1 */
neo_uext_gpio_set_direction(10, NEO_UEXT_OUTPUT); /* 10,4 : broche 10 en sortie */
ecrire(10, 1);
uint8_t haut = neo_uext_gpio_read(10); /* 10,3 : en sortie, on relit le verrou */
ecrire(10, 0);
uint8_t bas = neo_uext_gpio_read(10);
uint8_t e = ecrire(2, 1); /* la broche 2 du connecteur est la masse */
neo_uext_init(); /* tout remettre en entrée */
printf("Broche 10 : %u puis %u\n", haut, bas);
printf("Broche 2 : erreur %u\n", e);
return 0;
}Broche 10 : 255 puis 0
Broche 2 : erreur 1Mad Pascal
// Écrire le verrou de sortie d'une broche (groupe 10, fonction 2).
program uext2;
uses crt, neo6502, neo6502uext;
var haut, bas, e: byte;
function ecrire(broche, v: byte): byte; // 10,2 : rend l'indicateur d'erreur
begin
NeoWriteGPIO(broche, v);
NeoWaitMessage;
result := NeoMessage.error;
end;
begin
NeoUExtInitialize; // 10,1
NeoSetDirection(10, GPIO_PINMODE_OUTPUT); // 10,4 : broche 10 en sortie
ecrire(10, 1); // Write GPIO
haut := NeoReadGPIO(10); // 10,3 : en sortie, on relit le verrou
ecrire(10, 0);
bas := NeoReadGPIO(10);
e := ecrire(2, 1); // la broche 2 du connecteur est la masse
NeoUExtInitialize; // tout remettre en entrée
writeln('Broche 10 : ', haut, ' puis ', bas);
writeln('Broche 2 : erreur ', e);
end.Broche 10 : 255 puis 0
Broche 2 : erreur 1NeoBASIC
10 ' Ecrire le verrou de sortie d'une broche (groupe 10, fonction 2)
20 pin 10, output : ' 10,4 : broche 10 en sortie
30 pin 10, 1 : h = pin(10) : ' Write GPIO, puis 10,3 : en sortie, on relit le verrou
40 pin 10, 0 : l = pin(10)
50 b = 2 : v = 1 : gosub 1000 : ' la broche 2 du connecteur est la masse
60 pin 10, input : ' remettre en entree
70 print "Broche 10 : ";h;" puis ";l
80 print "Broche 2 : erreur ";e
90 end
1000 ' 10,2 : ecrire v sur la broche b ; erreur dans e
1010 while peek($ff00) : wend : poke $ff04, b : poke $ff05, v : poke $ff01, 2 : poke $ff00, 10
1020 while peek($ff00) : wend : e = peek($ff02)
1030 returnBroche 10 : 1 puis 0
Broche 2 : erreur 165C02 assembly (64tass)
; Écrire le verrou de sortie d'une broche (groupe 10, fonction 2).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<init
ldx #>init
jsr envoi
lda #<sortie
ldx #>sortie
jsr envoi
lda #<haut
ldx #>haut
jsr envoi
lda #10
jsr lire
sta h
lda #<bas
ldx #>bas
jsr envoi
lda #10
jsr lire
sta l
lda #<masse
ldx #>masse
jsr envoi
lda ControlPort+2
sta e
lda #<init
ldx #>init
jsr envoi
; tout remettre en entrée
lda #<t0
ldx #>t0
jsr ecrire
lda h
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda l
jsr decimal
lda #13
jsr WriteCharacter
lda #<t2
ldx #>t2
jsr ecrire
lda e
jsr decimal
lda #13
jsr WriteCharacter
rts
; 10,3 : niveau de la broche A (0 ou 255), rendu dans A.
lire: pha
jsr WaitMessage
pla
sta ControlPort+4
lda #10
ldx #3 ; 10,3 : Read GPIO
jsr appel
lda ControlPort+4
rts
init: .byte 10, 1, 0 ; 10,1 : UExt Initialise
sortie: .byte 10, 4, 2, 10, 2 ; 10,4 : broche 10 en sortie
haut: .byte 10, 2, 2, 10, 1 ; 10,2 : broche 10, valeur 1 (Write GPIO)
bas: .byte 10, 2, 2, 10, 0 ; 10,2 : broche 10, valeur 0
masse: .byte 10, 2, 2, 2, 1 ; 10,2 : broche 2, valeur 1 : la broche 2 du connecteur est la masse
t0: .text "Broche 10 : ", 0
t1: .text " puis ", 0
t2: .text "Broche 2 : erreur ", 0
h: .byte 0
l: .byte 0
e: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Broche 10 : 255 puis 0
Broche 2 : erreur 110,3 Read GPIO Official
Reads a pin: its level if it is an input, its latch if it is an output.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | pin (3 to 10) |
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | 0 low, 255 ($FF) high |
erreur | uint8 | 1 if the pin does not exist or is reserved |
A floating input (nothing plugged in) may read high or low. In NeoBASIC, pin(n) makes this call and returns 1 or 0.
NeoBASIC keywords that make this call: pin()
Firmware documentation text
If the pin is set to "Input" direction, reads the level on pin on UEXT port Parameter:0. If it is set to "Output" direction, reads the output latch for pin on UEXT port Parameter:0. If the read is successful, the result will be in Parameter:0.
C (llvm-mos)
/* Lire le niveau d'une broche en entrée (groupe 10, fonction 3). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
int main(void) {
neo_uext_init(); /* 10,1 : toutes les broches en entrée */
uint8_t v = neo_uext_gpio_read(7); /* Read GPIO : 0 (bas) ou 255 (haut) */
printf("Broche 7 : %s\n", v ? "haut" : "bas");
return 0;
}Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
Mad Pascal
// Lire le niveau d'une broche en entrée (groupe 10, fonction 3).
program uext3;
uses crt, neo6502, neo6502uext;
var v: byte;
begin
NeoUExtInitialize; // 10,1 : toutes les broches en entrée
v := NeoReadGPIO(7); // Read GPIO : 0 (bas) ou 255 (haut)
if v <> 0 then writeln('Broche 7 : haut') else writeln('Broche 7 : bas');
end.Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
NeoBASIC
10 ' Lire le niveau d'une broche en entree (groupe 10, fonction 3)
20 v = pin(7) : ' Read GPIO (au lancement, run remet les broches en entree)
30 n$ = "bas" : if v then n$ = "haut"
40 print "Broche 7 : ";n$Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
65C02 assembly (64tass)
; Lire le niveau d'une broche en entrée (groupe 10, fonction 3).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<init
ldx #>init
jsr envoi
lda #7
jsr lire ; Read GPIO : 0 (bas) ou 255 (haut)
bne _haut
lda #<tb
ldx #>tb
jsr ecrire
rts
_haut: lda #<th
ldx #>th
jsr ecrire
rts
; 10,3 : niveau de la broche A (0 ou 255), rendu dans A.
lire: pha
jsr WaitMessage
pla
sta ControlPort+4
lda #10
ldx #3 ; 10,3 : Read GPIO
jsr appel
lda ControlPort+4
rts
init: .byte 10, 1, 0 ; 10,1 : UExt Initialise
tb: .text "Broche 7 : bas", 13, 0
th: .text "Broche 7 : haut", 13, 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
10,4 Set Port Direction Official
Chooses the direction of a pin: input, output or analogue input.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | pin (3 to 10) |
P1 | uint8 | 1 input, 2 output, 3 analogue input |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if the pin does not exist, is reserved, or has no analogue input |
Only pins 3, 4, 8 and 9 have an analogue input: pin 10 is refused, pin 8 accepted. Switching to output puts the latch (10,2) on the pin at once. In NeoBASIC, pin n, input, pin n, output and pin n, analog make this call (with a comma) and raise a range error on failure.
NeoBASIC keywords that make this call: pin
Firmware documentation text
Set the port direction for UEXT Port Parameter:0 to the value in Parameter:1. This can be $01 (Input), $02 (Output), or $03 (Analogue Input).
C (llvm-mos)
/* Choisir le sens d'une broche (groupe 10, fonction 4). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t sens(uint8_t broche, uint8_t s) { /* Set Port Direction : rend l'indicateur d'erreur */
libre();
ControlPort.params[0] = broche;
ControlPort.params[1] = s; /* 1 entrée, 2 sortie, 3 entrée analogique */
api(10, 4);
return ControlPort.error;
}
int main(void) {
neo_uext_init(); /* 10,1 */
uint8_t a = sens(10, 3); /* broche 10 : pas d'entrée analogique */
uint8_t b = sens(8, 3); /* broche 8 : analogique possible */
uint8_t c = sens(10, 2);
neo_uext_init(); /* tout remettre en entrée */
printf("Broche 10 en analogique : erreur %u\n", a);
printf("Broche 8 en analogique : erreur %u\n", b);
printf("Broche 10 en sortie : erreur %u\n", c);
return 0;
}Broche 10 en analogique : erreur 1
Broche 8 en analogique : erreur 0
Broche 10 en sortie : erreur 0Mad Pascal
// Choisir le sens d'une broche (groupe 10, fonction 4).
program uext4;
uses crt, neo6502, neo6502uext;
var a, b, c: byte;
function sens(broche, s: byte): byte; // Set Port Direction : rend l'indicateur d'erreur
begin
NeoSetDirection(broche, s); // 1 entrée, 2 sortie, 3 entrée analogique
NeoWaitMessage;
result := NeoMessage.error;
end;
begin
NeoUExtInitialize; // 10,1
a := sens(10, GPIO_PINMODE_ANALOGUE); // broche 10 : pas d'entrée analogique
b := sens(8, GPIO_PINMODE_ANALOGUE); // broche 8 : analogique possible
c := sens(10, GPIO_PINMODE_OUTPUT);
NeoUExtInitialize; // tout remettre en entrée
writeln('Broche 10 en analogique : erreur ', a);
writeln('Broche 8 en analogique : erreur ', b);
writeln('Broche 10 en sortie : erreur ', c);
end.Broche 10 en analogique : erreur 1
Broche 8 en analogique : erreur 0
Broche 10 en sortie : erreur 0NeoBASIC
10 ' Choisir le sens d'une broche (groupe 10, fonction 4)
20 b = 10 : s = 3 : gosub 1000 : a = e : ' broche 10 : pas d'entree analogique
30 b = 8 : s = 3 : gosub 1000 : c8 = e : ' broche 8 : analogique possible
40 b = 10 : s = 2 : gosub 1000 : c10 = e
50 pin 8, input : pin 10, input : ' remettre en entree
60 print "Broche 10 en analogique : erreur ";a
70 print "Broche 8 en analogique : erreur ";c8
80 print "Broche 10 en sortie : erreur ";c10
90 end
1000 ' Set Port Direction : broche b, sens s (1 entree, 2 sortie, 3 analogique) ; erreur dans e
1010 while peek($ff00) : wend : poke $ff04, b : poke $ff05, s : poke $ff01, 4 : poke $ff00, 10
1020 while peek($ff00) : wend : e = peek($ff02)
1030 returnBroche 10 en analogique : erreur 1
Broche 8 en analogique : erreur 0
Broche 10 en sortie : erreur 065C02 assembly (64tass)
; Choisir le sens d'une broche (groupe 10, fonction 4).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<init
ldx #>init
jsr envoi
lda #<s10a
ldx #>s10a
jsr envoi
lda ControlPort+2
sta a
lda #<s8a
ldx #>s8a
jsr envoi
lda ControlPort+2
sta b
lda #<s10s
ldx #>s10s
jsr envoi
lda ControlPort+2
sta c
lda #<init
ldx #>init
jsr envoi
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda b
jsr decimal
lda #13
jsr WriteCharacter
lda #<t2
ldx #>t2
jsr ecrire
lda c
jsr decimal
lda #13
jsr WriteCharacter
rts
init: .byte 10, 1, 0 ; 10,1 : UExt Initialise
s10a: .byte 10, 4, 2, 10, 3 ; 10,4 : broche 10, analogique : impossible
s8a: .byte 10, 4, 2, 8, 3 ; 10,4 : broche 8, analogique : possible
s10s: .byte 10, 4, 2, 10, 2 ; 10,4 : broche 10, sortie
t0: .text "Broche 10 en analogique : erreur ", 0
t1: .text "Broche 8 en analogique : erreur ", 0
t2: .text "Broche 10 en sortie : erreur ", 0
a: .byte 0
b: .byte 0
c: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Broche 10 en analogique : erreur 1
Broche 8 en analogique : erreur 0
Broche 10 en sortie : erreur 010,5 Write I2C Official
Writes a byte into a register of an I2C device.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | device address (7 bits) |
P1 | uint8 | register |
P2 | uint8 | value |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if the transfer is not complete |
The firmware documentation says no error is flagged if the device is absent; the board code nevertheless returns 1 when the write does not complete, which is the case without a device (not checked on the board). The first I2C call reserves pins 5 and 6. In NeoBASIC, iwrite dev, reg, val makes this call.
NeoBASIC keywords that make this call: iwrite
Firmware documentation text
Write to I2C Device Parameter:0, Register Parameter:1, value Parameter:2. No error is flagged if the device is not present.
C (llvm-mos)
/* Écrire un registre d'un périphérique I2C (groupe 10, fonction 5). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
int main(void) {
libre();
ControlPort.params[0] = 0x50; /* P0 : adresse du périphérique (une EEPROM 24C02, par exemple) */
ControlPort.params[1] = 0x00; /* P1 : registre */
ControlPort.params[2] = 0x42; /* P2 : valeur */
api(10, 5); /* Write I2C */
printf("Ecriture en $50 : erreur %u\n", ControlPort.error);
return 0;
}Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
Mad Pascal
// Écrire un registre d'un périphérique I2C (groupe 10, fonction 5).
program uext5;
uses crt, neo6502, neo6502uext;
var e: byte;
begin
NeoWriteI2C($50, $00, $42); // Write I2C : périphérique $50 (une EEPROM 24C02, par exemple), registre 0, valeur $42
NeoWaitMessage;
e := NeoMessage.error;
writeln('Ecriture en $50 : erreur ', e);
end.Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
NeoBASIC
10 ' Ecrire un registre d'un peripherique I2C (groupe 10, fonction 5)
20 iwrite $50, 0, $42 : ' Write I2C : peripherique $50 (une EEPROM 24C02, par exemple), registre 0, valeur $42
30 e = peek($ff02)
40 print "Ecriture en $50 : erreur ";eChecked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
65C02 assembly (64tass)
; Écrire un registre d'un périphérique I2C (groupe 10, fonction 5).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<reg
ldx #>reg
jsr envoi
lda ControlPort+2
sta e
lda #<t0
ldx #>t0
jsr ecrire
lda e
jsr decimal
lda #13
jsr WriteCharacter
rts
reg: .byte 10, 5, 3, $50, 0, $42 ; Write I2C : périphérique $50 (une EEPROM 24C02, par exemple), registre 0, valeur $42
t0: .text "Ecriture en $50 : erreur ", 0
e: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
10,6 Read I2C Official
Reads a byte from a register of an I2C device.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | device address |
P1 | uint8 | register |
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | value read |
erreur | uint8 | 1 if the device does not answer |
The call writes the register number, then reads one byte. The example first checks that the device is there (10,8). In NeoBASIC, iread(dev, reg) makes this call.
NeoBASIC keywords that make this call: iread()
Firmware documentation text
Read from I2C Device Parameter:0, Register Parameter:1. If the read is successful, the result will be in Parameter:0. If the device is not present, this will flag an error. Use FUNCTION 10,2 first, to check for its presence.
C (llvm-mos)
/* Lire un registre d'un périphérique I2C (groupe 10, fonction 6). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
int main(void) {
if (!neo_uext_i2c_status(0x50)) { /* 10,8 : périphérique présent ? */
printf("Rien en $50\n");
return 0;
}
uint8_t v = neo_uext_i2c_read(0x50, 0x00); /* Read I2C : registre 0 */
printf("Registre 0 de $50 : %u\n", v);
return 0;
}Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
Mad Pascal
// Lire un registre d'un périphérique I2C (groupe 10, fonction 6).
program uext6;
uses crt, neo6502, neo6502uext;
var v: byte;
begin
if NeoCheckI2C($50) = 0 then // 10,8 : périphérique présent ?
writeln('Rien en $50')
else begin
v := NeoReadI2C($50, $00); // Read I2C : registre 0
writeln('Registre 0 de $50 : ', v);
end;
end.Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
NeoBASIC
10 ' Lire un registre d'un peripherique I2C (groupe 10, fonction 6)
20 if idevice($50) = 0 then print "Rien en $50" : end : ' 10,8 : peripherique present ?
30 v = iread($50, 0) : ' Read I2C : registre 0
40 print "Registre 0 de $50 : ";vChecked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
65C02 assembly (64tass)
; Lire un registre d'un périphérique I2C (groupe 10, fonction 6).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<etat
ldx #>etat
jsr envoi
lda ControlPort+4 ; non nul : présent
bne _la
lda #<t0
ldx #>t0
jsr ecrire
rts
_la: lda #<reg
ldx #>reg
jsr envoi
lda ControlPort+4
sta v
lda #<t1
ldx #>t1
jsr ecrire
lda v
jsr decimal
lda #13
jsr WriteCharacter
rts
etat: .byte 10, 8, 1, $50 ; 10,8 : périphérique $50 présent ?
reg: .byte 10, 6, 2, $50, 0 ; Read I2C : registre 0
t0: .text "Rien en $50", 13, 0
t1: .text "Registre 0 de $50 : ", 0
v: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
10,7 Read Analog Official
Reads the voltage of a pin set as an analogue input, from 0 to 4095 for 0 to 3.3 V.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | pin (3, 4, 8 or 9) |
| Bytes | Type | Meaning |
|---|---|---|
P0-P1 | uint16 | value, 0 to 4095 |
erreur | uint8 | 1 pin without analogue input, 2 pin not set to analogue (10,4) |
In millivolts: value × 3300 / 4095. The example first shows both errors (2 on pin 8, not set yet, 1 on pin 10), checked on the bench; the value read depends on what is plugged in. In NeoBASIC, analog(n) makes this call.
NeoBASIC keywords that make this call: analog()
Firmware documentation text
Read the analogue value on UEXT Pin Parameter:0. This has to be set to analogue type to work. Returns a value from 0..4095 stored in Parameters:0,1, which represents an input value of 0 to 3.3 volts.
C (llvm-mos)
/* Lire une entrée analogique (groupe 10, fonction 7). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint16_t valeur;
static uint8_t analogique(uint8_t broche) { /* Read Analog : valeur dans valeur, erreur rendue */
libre();
ControlPort.params[0] = broche;
api(10, 7);
valeur = ControlPort.params[0] | ControlPort.params[1] << 8;
return ControlPort.error;
}
int main(void) {
neo_uext_init(); /* 10,1 : broches en entrée numérique */
uint8_t e1 = analogique(8); /* pas encore réglée en analogique */
uint8_t e2 = analogique(10); /* pas d'entrée analogique sur la broche 10 */
neo_uext_gpio_set_direction(8, NEO_UEXT_ANALOGUE_INPUT); /* 10,4 */
analogique(8);
neo_uext_init();
printf("Broche 8 non reglee : erreur %u\n", e1);
printf("Broche 10 : erreur %u\n", e2);
printf("Broche 8 : %u sur 4095\n", valeur); /* 4095 : 3,3 V */
return 0;
}Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
Mad Pascal
// Lire une entrée analogique (groupe 10, fonction 7).
program uext7;
uses crt, neo6502, neo6502uext;
var e1, e2: byte;
valeur: word;
function analogique(broche: byte): byte; // Read Analog : valeur dans valeur, erreur rendue
begin
NeoReadAnalog(broche);
NeoWaitMessage; // attendre la fin de l'appel, puis relire P0-P1
valeur := NeoMessage.params[0] + NeoMessage.params[1] shl 8;
result := NeoMessage.error;
end;
begin
NeoUExtInitialize; // 10,1 : broches en entrée numérique
e1 := analogique(8); // pas encore réglée en analogique
e2 := analogique(10); // pas d'entrée analogique sur la broche 10
NeoSetDirection(8, GPIO_PINMODE_ANALOGUE); // 10,4
analogique(8);
NeoUExtInitialize;
writeln('Broche 8 non reglee : erreur ', e1);
writeln('Broche 10 : erreur ', e2);
writeln('Broche 8 : ', valeur, ' sur 4095'); // 4095 : 3,3 V
end.Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
NeoBASIC
10 ' Lire une entree analogique (groupe 10, fonction 7)
20 b = 8 : gosub 1000 : e1 = e : ' pas encore reglee en analogique
30 b = 10 : gosub 1000 : e2 = e : ' pas d'entree analogique sur la broche 10
40 pin 8, analog : ' 10,4
50 v = analog(8) : ' Read Analog, 0-4095 pour 0 a 3,3 V
70 pin 8, input
80 print "Broche 8 non reglee : erreur ";e1
90 print "Broche 10 : erreur ";e2
100 print "Broche 8 : ";v;" sur 4095"
110 end
1000 ' 10,7 sur la broche b ; erreur dans e
1010 while peek($ff00) : wend : poke $ff04, b : poke $ff01, 7 : poke $ff00, 10
1020 while peek($ff00) : wend : e = peek($ff02)
1030 returnChecked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
65C02 assembly (64tass)
; Lire une entrée analogique (groupe 10, fonction 7).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<init
ldx #>init
jsr envoi
lda #<an8
ldx #>an8
jsr envoi
lda ControlPort+2
sta e1
lda #<an10
ldx #>an10
jsr envoi
lda ControlPort+2
sta e2
lda #<s8a
ldx #>s8a
jsr envoi
lda #<an8
ldx #>an8
jsr envoi
lda ControlPort+4 ; P0-P1 : 0-4095 pour 0 à 3,3 V
sta v
lda ControlPort+5
sta v+1
lda #<init
ldx #>init
jsr envoi
lda #<t0
ldx #>t0
jsr ecrire
lda e1
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda e2
jsr decimal
lda #13
jsr WriteCharacter
lda #<t2
ldx #>t2
jsr ecrire
lda v
ldx v+1
jsr decimal16
lda #<t3 ; 4095 : 3,3 V
ldx #>t3
jsr ecrire
lda #13
jsr WriteCharacter
rts
; Affiche en décimal le nombre de 16 bits A (poids faible) X (poids fort).
decimal16:
sta n16
stx n16+1
ldy #0 ; nombre de chiffres empilés
_div10: ldx #16 ; n16 / 10 : quotient dans n16, reste dans A
lda #0
_bit: asl n16
rol n16+1
rol a
cmp #10
bcc _pas
sbc #10
inc n16
_pas: dex
bne _bit
pha
iny
lda n16
ora n16+1
bne _div10
_sort: pla
ora #'0'
jsr WriteCharacter
dey
bne _sort
rts
n16: .word 0
init: .byte 10, 1, 0 ; 10,1 : UExt Initialise
an8: .byte 10, 7, 1, 8 ; 10,7 : Read Analog, broche 8
an10: .byte 10, 7, 1, 10 ; broche 10 : pas d'entrée analogique
s8a: .byte 10, 4, 2, 8, 3 ; 10,4 : broche 8, entrée analogique
t0: .text "Broche 8 non reglee : erreur ", 0
t1: .text "Broche 10 : erreur ", 0
t2: .text "Broche 8 : ", 0
t3: .text " sur 4095", 0
e1: .byte 0
e2: .byte 0
v: .word 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
10,8 I2C Status Official
Tells whether a device answers at an I2C address.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | device address |
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | 1 if the device answers, 0 otherwise |
The call tries to read one byte. The example scans addresses $08 to $77 and prints those that answer. In NeoBASIC, idevice(dev) makes this call.
NeoBASIC keywords that make this call: idevice()
Firmware documentation text
Try to read from I2C Device Parameter:0. If present, then Parameter:0 will contain a non-zero value.
C (llvm-mos)
/* Chercher les périphériques I2C présents (groupe 10, fonction 8). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
int main(void) {
printf("Presents :");
for (uint8_t a = 0x08; a < 0x78; a++) /* adresses I2C ordinaires */
if (neo_uext_i2c_status(a)) /* I2C Status : non nul si présent */
printf(" $%02X", a);
printf("\n");
return 0;
}Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
Mad Pascal
// Chercher les périphériques I2C présents (groupe 10, fonction 8).
program uext8;
uses crt, neo6502, neo6502uext;
const hex: string[16] = '0123456789ABCDEF';
var a: byte;
begin
write('Presents :');
for a := $08 to $77 do // adresses I2C ordinaires
if NeoCheckI2C(a) <> 0 then // I2C Status : non nul si présent
write(' $', hex[a shr 4 + 1], hex[a and 15 + 1]);
writeln;
end.Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
NeoBASIC
10 ' Chercher les peripheriques I2C presents (groupe 10, fonction 8)
20 h$ = "0123456789ABCDEF"
30 print "Presents :";
40 for a = $08 to $77 : ' adresses I2C ordinaires
50 if idevice(a) then print " $";mid$(h$, (a >> 4) + 1, 1);mid$(h$, (a & 15) + 1, 1); : ' I2C Status
60 next a
70 printChecked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
65C02 assembly (64tass)
; Chercher les périphériques I2C présents (groupe 10, fonction 8).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<t0
ldx #>t0
jsr ecrire
lda #$08 ; adresses I2C ordinaires, $08 à $77
sta adr
_suiv: jsr WaitMessage
lda adr
sta ControlPort+4
lda #10
ldx #8 ; 10,8 : I2C Status
jsr appel
lda ControlPort+4 ; non nul : présent
beq _abs
lda #' '
jsr WriteCharacter
lda #'$'
jsr WriteCharacter
lda adr
lsr a
lsr a
lsr a
lsr a
jsr hex
lda adr
and #15
jsr hex
_abs: inc adr
lda adr
cmp #$78
bne _suiv
lda #13
jsr WriteCharacter
rts
; Affiche le chiffre hexadécimal A (0-15).
hex: tax
lda chiffres,x
jmp WriteCharacter
chiffres: .text "0123456789ABCDEF"
t0: .text "Presents :", 0
adr: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
10,9 Read I2C Block Changed by Trinity
Reads a run of bytes from an I2C device into 6502 memory.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | device address |
P1-P2 | addr | destination |
P3-P4 | uint16 | number of bytes |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if the transfer is not complete |
Nothing is written before the read: to read from a register, send it first (here, 10,5 sets the pointer of an EEPROM). Trinity limits the length to the end of 6502 memory. NeoBASIC has no keyword for this call.
Firmware documentation text
Try to read a block of memory from I2C Device Parameter:0 into memory at Parameters:1,2, length Parameters:3,4.
C (llvm-mos)
/* Lire un bloc d'octets d'un périphérique I2C (groupe 10, fonction 9). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t tampon[4];
int main(void) {
neo_uext_i2c_write(0x50, 0x00, 0x00); /* 10,5 : sans valeur, place le pointeur d'une EEPROM... */
libre();
ControlPort.params[0] = 0x50; /* P0 : périphérique */
ControlPort.params[1] = (uint16_t)tampon & 0xFF; /* P1-P2 : destination */
ControlPort.params[2] = (uint16_t)tampon >> 8;
ControlPort.params[3] = sizeof tampon; /* P3-P4 : longueur */
ControlPort.params[4] = 0;
api(10, 9); /* Read I2C Block */
uint8_t e = ControlPort.error;
printf("Lu en $50 (erreur %u) : %u %u %u %u\n", e, tampon[0], tampon[1], tampon[2], tampon[3]);
return 0;
}Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
Mad Pascal
// Lire un bloc d'octets d'un périphérique I2C (groupe 10, fonction 9).
program uext9;
uses crt, neo6502, neo6502uext;
var tampon: array[0..3] of byte;
e: byte;
begin
NeoWriteI2C($50, $00, $00); // 10,5 : place le pointeur d'une EEPROM...
NeoReadBlockI2C($50, word(@tampon), 4); // Read I2C Block
NeoWaitMessage;
e := NeoMessage.error;
writeln('Lu en $50 (erreur ', e, ') : ', tampon[0], ' ', tampon[1], ' ', tampon[2], ' ', tampon[3]);
end.Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
NeoBASIC
10 ' Lire un bloc d'octets d'un peripherique I2C (groupe 10, fonction 9)
20 t = alloc(4)
30 iwrite $50, 0, 0 : ' 10,5 : place le pointeur d'une EEPROM...
40 while peek($ff00) : wend
50 poke $ff04, $50 : doke $ff05, t : doke $ff07, 4 : poke $ff01, 9 : poke $ff00, 10 : ' Read I2C Block
60 while peek($ff00) : wend : e = peek($ff02)
70 print "Lu en $50 (erreur ";e;") : ";peek(t);" ";peek(t + 1);" ";peek(t + 2);" ";peek(t + 3)Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
65C02 assembly (64tass)
; Lire un bloc d'octets d'un périphérique I2C (groupe 10, fonction 9).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<ptr0
ldx #>ptr0
jsr envoi
lda #<bloc
ldx #>bloc
jsr envoi
lda ControlPort+2
sta e
lda #<t0
ldx #>t0
jsr ecrire
lda e
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
ldx #0
_oct: lda tampon,x
jsr decimal
cpx #3
beq _fin
lda #' '
jsr WriteCharacter
inx
bra _oct
_fin: lda #13
jsr WriteCharacter
rts
ptr0: .byte 10, 5, 3, $50, 0, 0 ; 10,5 : place le pointeur d'une EEPROM...
bloc: .byte 10, 9, 5, $50 ; 10,9 : Read I2C Block, périphérique, destination, longueur
.word tampon, 4
t0: .text "Lu en $50 (erreur ", 0
t1: .text ") : ", 0
e: .byte 0
tampon: .fill 4
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
10,10 Write I2C Block Changed by Trinity
Sends a run of bytes from 6502 memory to an I2C device.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | device address |
P1-P2 | addr | source |
P3-P4 | uint16 | number of bytes |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if the transfer is not complete |
The first byte is often the target register, followed by the data. Trinity limits the length to the end of 6502 memory. In NeoBASIC, isend dev, list makes this call; the list mixes numbers (one byte each) and strings.
NeoBASIC keywords that make this call: isend
Firmware documentation text
Try to write a block of memory to I2C Device Parameter:0 from memory at Parameters:1,2, length Parameters:3,4.
C (llvm-mos)
/* Envoyer un bloc d'octets à un périphérique I2C (groupe 10, fonction 10). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static const uint8_t bloc[] = { 0x00, 'N', 'E', 'O' }; /* registre 0, puis trois octets */
int main(void) {
libre();
ControlPort.params[0] = 0x50; /* P0 : périphérique */
ControlPort.params[1] = (uint16_t)bloc & 0xFF; /* P1-P2 : source */
ControlPort.params[2] = (uint16_t)bloc >> 8;
ControlPort.params[3] = sizeof bloc; /* P3-P4 : longueur */
ControlPort.params[4] = 0;
api(10, 10); /* Write I2C Block */
printf("Envoye en $50 : %u octets, erreur %u\n", sizeof bloc, ControlPort.error);
return 0;
}Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
Mad Pascal
// Envoyer un bloc d'octets à un périphérique I2C (groupe 10, fonction 10).
program uext10;
uses crt, neo6502, neo6502uext;
const bloc: array[0..3] of byte = ($00, ord('N'), ord('E'), ord('O')); // registre 0, puis trois octets
var e: byte;
begin
NeoWriteBlockI2C($50, word(@bloc), 4); // Write I2C Block
NeoWaitMessage;
e := NeoMessage.error;
writeln('Envoye en $50 : 4 octets, erreur ', e);
end.Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
NeoBASIC
10 ' Envoyer un bloc d'octets a un peripherique I2C (groupe 10, fonction 10)
20 isend $50, 0, "NEO" : ' Write I2C Block : registre 0, puis trois octets
30 e = peek($ff02)
40 print "Envoye en $50 : 4 octets, erreur ";eChecked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
65C02 assembly (64tass)
; Envoyer un bloc d'octets à un périphérique I2C (groupe 10, fonction 10).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<bloc
ldx #>bloc
jsr envoi
lda ControlPort+2
sta e
lda #<t0
ldx #>t0
jsr ecrire
lda e
jsr decimal
lda #13
jsr WriteCharacter
rts
bloc: .byte 10, 10, 5, $50 ; 10,10 : Write I2C Block, périphérique, source, longueur
.word donnees, 4
donnees: .byte 0 ; registre 0, puis trois octets
.text "NEO"
t0: .text "Envoye en $50 : 4 octets, erreur ", 0
e: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
10,11 Read SPI Block Changed by Trinity
Reads a run of bytes from the SPI bus into 6502 memory.
| Bytes | Type | Meaning |
|---|---|---|
P1-P2 | addr | destination |
P3-P4 | uint16 | number of bytes |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if the transfer is not complete |
P0 is not read: there is a single device, selected by SSEL (pin 10), pulled to 0 during the transfer. The first SPI call reserves pins 7 to 10. On a board whose storage is an SD card, SPI is taken and the call returns 1. NeoBASIC has no keyword for this call.
Firmware documentation text
Try to read a block of memory from SPI Device into memory at Parameters:1,2, length Parameters:3,4.
C (llvm-mos)
/* Lire un bloc d'octets sur le bus SPI (groupe 10, fonction 11). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t tampon[4];
int main(void) {
libre();
ControlPort.params[1] = (uint16_t)tampon & 0xFF; /* P1-P2 : destination (P0 n'est pas lu) */
ControlPort.params[2] = (uint16_t)tampon >> 8;
ControlPort.params[3] = sizeof tampon; /* P3-P4 : longueur */
ControlPort.params[4] = 0;
api(10, 11); /* Read SPI Block */
uint8_t e = ControlPort.error;
printf("Lu en SPI (erreur %u) : %u %u %u %u\n", e, tampon[0], tampon[1], tampon[2], tampon[3]);
return 0;
}Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
Mad Pascal
// Lire un bloc d'octets sur le bus SPI (groupe 10, fonction 11).
program uext11;
uses crt, neo6502, neo6502uext;
var tampon: array[0..3] of byte;
e: byte;
begin
NeoReadBlockSPI(word(@tampon), 4); // Read SPI Block
NeoWaitMessage;
e := NeoMessage.error;
writeln('Lu en SPI (erreur ', e, ') : ', tampon[0], ' ', tampon[1], ' ', tampon[2], ' ', tampon[3]);
end.Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
NeoBASIC
10 ' Lire un bloc d'octets sur le bus SPI (groupe 10, fonction 11)
20 t = alloc(4)
30 while peek($ff00) : wend
40 doke $ff05, t : doke $ff07, 4 : poke $ff01, 11 : poke $ff00, 10 : ' Read SPI Block (P0 n'est pas lu)
50 while peek($ff00) : wend : e = peek($ff02)
60 print "Lu en SPI (erreur ";e;") : ";peek(t);" ";peek(t + 1);" ";peek(t + 2);" ";peek(t + 3)Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
65C02 assembly (64tass)
; Lire un bloc d'octets sur le bus SPI (groupe 10, fonction 11).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<bloc
ldx #>bloc
jsr envoi
lda ControlPort+2
sta e
lda #<t0
ldx #>t0
jsr ecrire
lda e
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
ldx #0
_oct: lda tampon,x
jsr decimal
cpx #3
beq _fin
lda #' '
jsr WriteCharacter
inx
bra _oct
_fin: lda #13
jsr WriteCharacter
rts
bloc: .byte 10, 11, 5, 0 ; 10,11 : Read SPI Block (P0 n'est pas lu), destination, longueur
.word tampon, 4
t0: .text "Lu en SPI (erreur ", 0
t1: .text ") : ", 0
e: .byte 0
tampon: .fill 4
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
10,12 Write SPI Block Changed by Trinity
Sends a run of bytes from 6502 memory over the SPI bus.
| Bytes | Type | Meaning |
|---|---|---|
P1-P2 | addr | source |
P3-P4 | uint16 | number of bytes |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if the transfer is not complete |
As for 10,11: P0 is not read, SSEL (pin 10) goes to 0 during the send. The example shows that SPI has taken pins 7 to 10: writing pin 10 then gives error 1 (checked on the bench). In NeoBASIC, ssend list makes this call.
NeoBASIC keywords that make this call: ssend
Firmware documentation text
Try to write a block of memory to SPI Device from memory at Parameters:1,2, length Parameters:3,4.
C (llvm-mos)
/* Envoyer un bloc d'octets sur le bus SPI (groupe 10, fonction 12). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static const uint8_t bloc[] = { 0x9F, 0x00, 0x00 }; /* une commande et deux octets */
static uint8_t ecrire(uint8_t broche, uint8_t v) { /* 10,2 : rend l'indicateur d'erreur */
libre();
ControlPort.params[0] = broche;
ControlPort.params[1] = v;
api(10, 2);
return ControlPort.error;
}
int main(void) {
neo_uext_init(); /* 10,1 */
libre();
ControlPort.params[1] = (uint16_t)bloc & 0xFF; /* P1-P2 : source (P0 n'est pas lu) */
ControlPort.params[2] = (uint16_t)bloc >> 8;
ControlPort.params[3] = sizeof bloc; /* P3-P4 : longueur */
ControlPort.params[4] = 0;
api(10, 12); /* Write SPI Block */
uint8_t e = ControlPort.error;
uint8_t b = ecrire(10, 1); /* le SPI a pris les broches 7 à 10 */
neo_uext_init();
printf("Envoye en SPI : erreur %u\n", e);
printf("Broche 10 ensuite : erreur %u\n", b);
return 0;
}Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
Mad Pascal
// Envoyer un bloc d'octets sur le bus SPI (groupe 10, fonction 12).
program uext12;
uses crt, neo6502, neo6502uext;
const bloc: array[0..2] of byte = ($9F, $00, $00); // une commande et deux octets
var e, b: byte;
function ecrire(broche, v: byte): byte; // 10,2 : rend l'indicateur d'erreur
begin
NeoWriteGPIO(broche, v);
NeoWaitMessage;
result := NeoMessage.error;
end;
begin
NeoUExtInitialize; // 10,1
NeoWriteBlockSPI(word(@bloc), 3); // Write SPI Block
NeoWaitMessage;
e := NeoMessage.error;
b := ecrire(10, 1); // le SPI a pris les broches 7 à 10
NeoUExtInitialize;
writeln('Envoye en SPI : erreur ', e);
writeln('Broche 10 ensuite : erreur ', b);
end.Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
NeoBASIC
10 ' Envoyer un bloc d'octets sur le bus SPI (groupe 10, fonction 12)
20 ssend $9f, 0, 0 : ' Write SPI Block : une commande et deux octets
30 e1 = peek($ff02)
40 b = 10 : v = 1 : gosub 1000 : ' le SPI a pris les broches 7 a 10
50 print "Envoye en SPI : erreur ";e1
60 print "Broche 10 ensuite : erreur ";e
70 end
1000 ' 10,2 : ecrire v sur la broche b ; erreur dans e
1010 while peek($ff00) : wend : poke $ff04, b : poke $ff05, v : poke $ff01, 2 : poke $ff00, 10
1020 while peek($ff00) : wend : e = peek($ff02)
1030 returnChecked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
65C02 assembly (64tass)
; Envoyer un bloc d'octets sur le bus SPI (groupe 10, fonction 12).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<init
ldx #>init
jsr envoi
lda #<bloc
ldx #>bloc
jsr envoi
lda ControlPort+2
sta e
lda #<ecr10
ldx #>ecr10
jsr envoi
lda ControlPort+2
sta b
lda #<init
ldx #>init
jsr envoi
lda #<t0
ldx #>t0
jsr ecrire
lda e
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda b
jsr decimal
lda #13
jsr WriteCharacter
rts
init: .byte 10, 1, 0 ; 10,1 : UExt Initialise
bloc: .byte 10, 12, 5, 0 ; 10,12 : Write SPI Block (P0 n'est pas lu), source, longueur
.word donnees, 3
donnees: .byte $9F, 0, 0 ; une commande et deux octets
ecr10: .byte 10, 2, 2, 10, 1 ; 10,2 : broche 10, valeur 1 : le SPI a pris les broches 7 à 10
t0: .text "Envoye en SPI : erreur ", 0
t1: .text "Broche 10 ensuite : erreur ", 0
e: .byte 0
b: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Checked on the bench (call made, no error). The output depends on the hardware plugged into the UEXT port: the emulator's, a dummy one, is not shown.
10,13 Read UART Block Changed by Trinity
Waits for a run of bytes on the serial port and stores it in 6502 memory.
| Bytes | Type | Meaning |
|---|---|---|
P1-P2 | addr | destination |
P3-P4 | uint16 | number of bytes |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | 1 if a byte does not arrive within 5 seconds |
The 5 second timeout applies to each byte; while waiting, the 65C02 is stopped. With nothing plugged in, the example therefore ends on error 1 after 5 seconds, on the board as on the bench. If 10,19 routes the port to a plugged USB modem, that is what is read. NeoBASIC has no keyword for this call.
Firmware documentation text
Try to read a block of memory from UART into memory at Parameters:1,2, length Parameters:3,4. This can fail with a timeout. If UART routing (10,19) selects a USB CDC modem, the block is read from it instead.
C (llvm-mos)
/* Attendre un bloc d'octets sur le port série (groupe 10, fonction 13). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t tampon[4];
int main(void) {
libre();
ControlPort.params[1] = (uint16_t)tampon & 0xFF; /* P1-P2 : destination */
ControlPort.params[2] = (uint16_t)tampon >> 8;
ControlPort.params[3] = sizeof tampon; /* P3-P4 : longueur */
ControlPort.params[4] = 0;
api(10, 13); /* Read UART Block : attend jusqu'à 5 s par octet */
printf("4 octets attendus : erreur %u\n", ControlPort.error); /* 1 : délai dépassé */
return 0;
}4 octets attendus : erreur 1Mad Pascal
// Attendre un bloc d'octets sur le port série (groupe 10, fonction 13).
program uext13;
uses crt, neo6502, neo6502uext;
var tampon: array[0..3] of byte;
e: byte;
begin
NeoReadBlockUART(word(@tampon), 4); // Read UART Block : attend jusqu'à 5 s par octet
NeoWaitMessage;
e := NeoMessage.error;
writeln('4 octets attendus : erreur ', e); // 1 : délai dépassé
end.4 octets attendus : erreur 1NeoBASIC
10 ' Attendre un bloc d'octets sur le port serie (groupe 10, fonction 13)
20 t = alloc(4)
30 while peek($ff00) : wend
40 doke $ff05, t : doke $ff07, 4 : poke $ff01, 13 : poke $ff00, 10 : ' Read UART Block : jusqu'a 5 s par octet
50 while peek($ff00) : wend : e = peek($ff02)
60 print "4 octets attendus : erreur ";e : ' 1 : delai depasse4 octets attendus : erreur 165C02 assembly (64tass)
; Attendre un bloc d'octets sur le port série (groupe 10, fonction 13).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<bloc
ldx #>bloc
jsr envoi
lda ControlPort+2
sta e
lda #<t0
ldx #>t0
jsr ecrire
lda e
jsr decimal
lda #13
jsr WriteCharacter
rts
bloc: .byte 10, 13, 5, 0 ; 10,13 : Read UART Block, jusqu'à 5 s par octet
.word tampon, 4
t0: .text "4 octets attendus : erreur ", 0 ; 1 : délai dépassé
e: .byte 0
tampon: .fill 4
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 04 octets attendus : erreur 110,14 Write UART Block Changed by Trinity
Sends a run of bytes from 6502 memory over the serial port.
| Bytes | Type | Meaning |
|---|---|---|
P1-P2 | addr | source |
P3-P4 | uint16 | number of bytes |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | always 0 on the board's serial port; 1 if a routed USB modem (10,19) refuses |
Sending does not check that a device is listening. The serial port is shared with the Trinity debug port: its speed is that of the last 10,15. In NeoBASIC, usend list makes this call.
NeoBASIC keywords that make this call: usend
Firmware documentation text
Try to write a block of memory to UART from memory at Parameters:1,2, length Parameters:3,4. Routed to a USB CDC modem if 10,19 selects it.
C (llvm-mos)
/* Envoyer un bloc d'octets sur le port série (groupe 10, fonction 14). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static const char texte[] = "NEO\r\n";
int main(void) {
libre();
ControlPort.params[1] = (uint16_t)texte & 0xFF; /* P1-P2 : source */
ControlPort.params[2] = (uint16_t)texte >> 8;
ControlPort.params[3] = sizeof texte - 1; /* P3-P4 : longueur */
ControlPort.params[4] = 0;
api(10, 14); /* Write UART Block */
printf("Envoye : %u octets, erreur %u\n", sizeof texte - 1, ControlPort.error);
return 0;
}Envoye : 5 octets, erreur 0Mad Pascal
// Envoyer un bloc d'octets sur le port série (groupe 10, fonction 14).
program uext14;
uses crt, neo6502, neo6502uext;
var texte: string[8];
e: byte;
begin
texte := 'NEO'#13#10;
NeoWriteBlockUART(word(@texte) + 1, length(texte)); // Write UART Block
NeoWaitMessage;
e := NeoMessage.error;
writeln('Envoye : ', length(texte), ' octets, erreur ', e);
end.Envoye : 5 octets, erreur 0NeoBASIC
10 ' Envoyer un bloc d'octets sur le port serie (groupe 10, fonction 14)
20 usend "NEO", 13, 10 : ' Write UART Block
30 e = peek($ff02)
40 print "Envoye : 5 octets, erreur ";eEnvoye : 5 octets, erreur 065C02 assembly (64tass)
; Envoyer un bloc d'octets sur le port série (groupe 10, fonction 14).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<bloc
ldx #>bloc
jsr envoi
lda ControlPort+2
sta e
lda #<t0
ldx #>t0
jsr ecrire
lda e
jsr decimal
lda #13
jsr WriteCharacter
rts
bloc: .byte 10, 14, 5, 0 ; 10,14 : Write UART Block, source, longueur
.word texte, 5
texte: .text "NEO", 13, 10
t0: .text "Envoye : 5 octets, erreur ", 0
e: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Envoye : 5 octets, erreur 010,15 Set UART Speed and Protocol Changed by Trinity
Sets the speed (in bauds) and format of the serial port.
| Bytes | Type | Meaning |
|---|---|---|
P0-P3 | uint32 | speed in bauds |
P4 | uint8 | protocol: 0 = 8N1, the only one supported |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | always 0 |
The call reserves pins 3 (TXD) and 4 (RXD): writing them as plain pins gives error 1. The Trinity debug port follows the new speed (its trace becomes unreadable at a speed other than its own). If 10,19 routes to a USB modem, the call sets its line (most ignore it). In NeoBASIC, uconfig bauds makes this call, in 8N1.
NeoBASIC keywords that make this call: uconfig
Firmware documentation text
Set the Baud Rate and Serial Protocol for the UART interface. The baud rate is in Parameters:0..3 and the protocol number is Parameter:4. Currently only 8N1 is supported, this is protocol 0. If UART routing selects a USB CDC modem, this sets its line coding (most USB modems ignore it).
C (llvm-mos)
/* Régler la vitesse du port série (groupe 10, fonction 15). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t ecrire(uint8_t broche, uint8_t v) { /* 10,2 : rend l'indicateur d'erreur */
libre();
ControlPort.params[0] = broche;
ControlPort.params[1] = v;
api(10, 2);
return ControlPort.error;
}
int main(void) {
neo_uext_uart_configure(115200, 0); /* Set UART Speed and Protocol : 115200 bauds, 8N1 */
uint8_t e = ControlPort.error;
uint8_t apres = ecrire(3, 0); /* TXD (3) et RXD (4) sont au port série */
neo_uext_init();
printf("Reglage : erreur %u\n", e);
printf("Broche 3 ensuite : erreur %u\n", apres);
return 0;
}Reglage : erreur 0
Broche 3 ensuite : erreur 1Mad Pascal
// Régler la vitesse du port série (groupe 10, fonction 15).
program uext15;
uses crt, neo6502, neo6502uext;
var e, apres: byte;
function ecrire(broche, v: byte): byte; // 10,2 : rend l'indicateur d'erreur
begin
NeoWriteGPIO(broche, v);
NeoWaitMessage;
result := NeoMessage.error;
end;
begin
NeoSetupUART(115200, UART_PROTOCOL_8N1); // Set UART Speed and Protocol : 115200 bauds, 8N1
NeoWaitMessage;
e := NeoMessage.error;
apres := ecrire(3, 0); // TXD (3) et RXD (4) sont au port série
NeoUExtInitialize;
writeln('Reglage : erreur ', e);
writeln('Broche 3 ensuite : erreur ', apres);
end.Reglage : erreur 0
Broche 3 ensuite : erreur 1NeoBASIC
10 ' Regler la vitesse du port serie (groupe 10, fonction 15)
20 uconfig 115200 : ' Set UART Speed and Protocol : 115200 bauds, 8N1
30 e1 = peek($ff02)
40 b = 3 : v = 0 : gosub 1000 : ' TXD (3) et RXD (4) sont au port serie
50 print "Reglage : erreur ";e1
60 print "Broche 3 ensuite : erreur ";e
70 end
1000 ' 10,2 : ecrire v sur la broche b ; erreur dans e
1010 while peek($ff00) : wend : poke $ff04, b : poke $ff05, v : poke $ff01, 2 : poke $ff00, 10
1020 while peek($ff00) : wend : e = peek($ff02)
1030 returnReglage : erreur 0
Broche 3 ensuite : erreur 165C02 assembly (64tass)
; Régler la vitesse du port série (groupe 10, fonction 15).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<vitesse
ldx #>vitesse
jsr envoi
lda ControlPort+2
sta e
lda #<ecr3
ldx #>ecr3
jsr envoi
lda ControlPort+2
sta b
lda #<init
ldx #>init
jsr envoi
lda #<t0
ldx #>t0
jsr ecrire
lda e
jsr decimal
lda #13
jsr WriteCharacter
lda #<t1
ldx #>t1
jsr ecrire
lda b
jsr decimal
lda #13
jsr WriteCharacter
rts
init: .byte 10, 1, 0 ; 10,1 : UExt Initialise
vitesse: .byte 10, 15, 5 ; 10,15 : Set UART Speed and Protocol
.dword 115200 ; P0-P3 : bauds
.byte 0 ; P4 : protocole 0, 8N1
ecr3: .byte 10, 2, 2, 3, 0 ; 10,2 : broche 3, valeur 0 : TXD (3) et RXD (4) sont au port série
t0: .text "Reglage : erreur ", 0
t1: .text "Broche 3 ensuite : erreur ", 0
e: .byte 0
b: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Reglage : erreur 0
Broche 3 ensuite : erreur 110,16 Write byte to UART Changed by Trinity
Sends one byte over the serial port.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | byte |
| Bytes | Type | Meaning |
|---|---|---|
erreur | uint8 | always 0 |
As 10,14, without checking that a device is listening; routed to a USB modem if 10,19 selects it. NeoBASIC has no keyword for this call (usend sends a block).
Firmware documentation text
Write byte Parameter:0 to the UART (or the routed USB CDC modem).
C (llvm-mos)
/* Envoyer un octet sur le port série (groupe 10, fonction 16). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
int main(void) {
neo_uext_uart_write('A'); /* Write byte to UART */
printf("Octet envoye : erreur %u\n", ControlPort.error);
return 0;
}Octet envoye : erreur 0Mad Pascal
// Envoyer un octet sur le port série (groupe 10, fonction 16).
program uext16;
uses crt, neo6502, neo6502uext;
var e: byte;
begin
NeoWriteByteUART(ord('A')); // Write byte to UART
NeoWaitMessage;
e := NeoMessage.error;
writeln('Octet envoye : erreur ', e);
end.Octet envoye : erreur 0NeoBASIC
10 ' Envoyer un octet sur le port serie (groupe 10, fonction 16)
20 while peek($ff00) : wend : poke $ff04, asc("A") : poke $ff01, 16 : poke $ff00, 10 : ' Write byte to UART
30 while peek($ff00) : wend : e = peek($ff02)
40 print "Octet envoye : erreur ";eOctet envoye : erreur 065C02 assembly (64tass)
; Envoyer un octet sur le port série (groupe 10, fonction 16).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<octet
ldx #>octet
jsr envoi
lda ControlPort+2
sta e
lda #<t0
ldx #>t0
jsr ecrire
lda e
jsr decimal
lda #13
jsr WriteCharacter
rts
octet: .byte 10, 16, 1, 'A' ; 10,16 : Write byte to UART
t0: .text "Octet envoye : erreur ", 0
e: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Octet envoye : erreur 010,17 Read byte from UART Changed by Trinity
Reads a byte received on the serial port, without waiting.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | byte received |
erreur | uint8 | 1 if nothing has arrived |
Unlike 10,13, the call does not wait. With nothing plugged in, the example gets error 1, on the board as on the bench. NeoBASIC has no keyword for this call.
Firmware documentation text
Read a byte from the UART (or the routed USB CDC modem). It is returned in Parameter:0. Error 1 if nothing is available.
C (llvm-mos)
/* Lire un octet du port série s'il y en a un (groupe 10, fonction 17). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
int main(void) {
libre();
api(10, 17); /* Read byte from UART */
if (ControlPort.error) /* 1 : rien n'est arrivé */
printf("Rien a lire : erreur %u\n", ControlPort.error);
else
printf("Recu : %u\n", ControlPort.params[0]);
return 0;
}Rien a lire : erreur 1Mad Pascal
// Lire un octet du port série s'il y en a un (groupe 10, fonction 17).
program uext17;
uses crt, neo6502, neo6502uext;
var v, e: byte;
begin
NeoReadByteUART; // Read byte from UART
NeoWaitMessage; // attendre la fin de l'appel, puis relire P0
v := NeoMessage.params[0];
e := NeoMessage.error; // 1 : rien n'est arrivé
if e <> 0 then writeln('Rien a lire : erreur ', e)
else writeln('Recu : ', v);
end.Rien a lire : erreur 1NeoBASIC
10 ' Lire un octet du port serie s'il y en a un (groupe 10, fonction 17)
20 while peek($ff00) : wend : poke $ff01, 17 : poke $ff00, 10 : ' Read byte from UART
30 while peek($ff00) : wend : e = peek($ff02) : v = peek($ff04)
40 if e then print "Rien a lire : erreur ";e : end : ' 1 : rien n'est arrive
50 print "Recu : ";vRien a lire : erreur 165C02 assembly (64tass)
; Lire un octet du port série s'il y en a un (groupe 10, fonction 17).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<lire
ldx #>lire
jsr envoi
lda ControlPort+4
sta v
lda ControlPort+2 ; 1 : rien n'est arrivé
sta e
beq _recu
lda #<t0
ldx #>t0
jsr ecrire
lda e
jsr decimal
lda #13
jsr WriteCharacter
rts
_recu: lda #<t1
ldx #>t1
jsr ecrire
lda v
jsr decimal
lda #13
jsr WriteCharacter
rts
lire: .byte 10, 17, 0 ; 10,17 : Read byte from UART
t0: .text "Rien a lire : erreur ", 0
t1: .text "Recu : ", 0
e: .byte 0
v: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Rien a lire : erreur 110,18 Check if Byte Available Changed by Trinity
Tells whether a received byte is waiting to be read on the serial port.
Inputs: none.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | 1 if a byte is waiting, 0 otherwise |
Call it before 10,17 to read only what has arrived. In NeoBASIC, uhasdata() makes this call.
NeoBASIC keywords that make this call: uhasdata()
Firmware documentation text
See if a byte is available in the UART input buffer. If available Parameter:0 is non zero.
C (llvm-mos)
/* Savoir si un octet attend sur le port série (groupe 10, fonction 18). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
int main(void) {
printf("Octet en attente : %s\n", neo_uext_uart_available() ? "oui" : "non"); /* Check if Byte Available */
return 0;
}Octet en attente : nonMad Pascal
// Savoir si un octet attend sur le port série (groupe 10, fonction 18).
program uext18;
uses crt, neo6502, neo6502uext;
var v: byte;
begin
NeoCheckUART; // Check if Byte Available
NeoWaitMessage; // attendre la fin de l'appel, puis relire P0
v := NeoMessage.params[0];
if v <> 0 then writeln('Octet en attente : oui') else writeln('Octet en attente : non');
end.Octet en attente : nonNeoBASIC
10 ' Savoir si un octet attend sur le port serie (groupe 10, fonction 18)
20 r$ = "non" : if uhasdata() then r$ = "oui" : ' Check if Byte Available
30 print "Octet en attente : ";r$Octet en attente : non65C02 assembly (64tass)
; Savoir si un octet attend sur le port série (groupe 10, fonction 18).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<test
ldx #>test
jsr envoi
lda ControlPort+4 ; non nul : un octet attend
bne _oui
lda #<tn
ldx #>tn
jsr ecrire
rts
_oui: lda #<to
ldx #>to
jsr ecrire
rts
test: .byte 10, 18, 0 ; 10,18 : Check if Byte Available
tn: .text "Octet en attente : non", 13, 0
to: .text "Octet en attente : oui", 13, 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Octet en attente : non10,19 Route UART to USB CDC modem Trinity
Chooses where the serial port functions (10,13 to 10,18) go: the UEXT serial port, a USB modem, or the modem when one is plugged in.
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | 0 UEXT serial port, 1 first USB (CDC) modem, 2 automatic; above: automatic |
| Bytes | Type | Meaning |
|---|---|---|
P0 | uint8 | mode kept (0, 1 or 2) |
Automatic is the starting setting: a serial program (netconfig, prophet...) thus goes through a USB Wi-Fi modem when there is one, unchanged. The documentation says P0 returns the mode "in effect": it is the setting kept (2 for automatic), not the port actually used. The example puts automatic back before ending. NeoBASIC has no keyword for this call.
Firmware documentation text
Select the source/target of the UART functions 10,13-10,18. Parameter:0 = 0 for the hardware UART (UEXT), 1 for the first USB CDC modem, 2 for AUTO (the CDC modem if one is plugged in, otherwise the hardware UART). AUTO is the default, so serial programs such as netconfig/prophet use a USB Wi-Fi modem unchanged when one is present. Parameter:0 returns the mode in effect.
C (llvm-mos)
/* Choisir où vont les fonctions du port série (groupe 10, fonction 19, Trinity). */
#include <stdio.h>
#include <neo6502.h>
#include <neo/api.h>
/* Appel brut de la boîte aux lettres : fonction puis groupe (écrit en dernier, il lance l'appel). */
static void api(uint8_t groupe, uint8_t fonction) {
ControlPort.function = fonction;
ControlPort.command = groupe;
while (ControlPort.command) /* attendre la fin */
;
}
static void libre(void) { /* attendre que la boîte aux lettres soit libre */
while (ControlPort.command)
;
}
static uint8_t router(uint8_t mode) { /* Route UART to USB CDC modem : rend le mode retenu */
libre();
ControlPort.params[0] = mode; /* 0 UART du UEXT, 1 modem USB, 2 automatique */
api(10, 19);
return ControlPort.params[0];
}
int main(void) {
uint8_t a = router(0);
uint8_t b = router(9); /* hors plage : automatique */
router(2); /* remettre le mode par défaut */
printf("Demande 0 : %u, demande 9 : %u\n", a, b);
return 0;
}Demande 0 : 0, demande 9 : 2Mad Pascal
// Choisir où vont les fonctions du port série (groupe 10, fonction 19, Trinity).
program uext19;
uses crt, neo6502, neo6502uext;
var a, b: byte;
function router(mode: byte): byte; // Route UART to USB CDC modem : rend le mode retenu
begin
NeoMessage.params[0] := mode; // 0 UART du UEXT, 1 modem USB, 2 automatique
NeoSendMessage(10, 19);
NeoWaitMessage;
result := NeoMessage.params[0];
end;
begin
a := router(0);
b := router(9); // hors plage : automatique
router(2); // remettre le mode par défaut
writeln('Demande 0 : ', a, ', demande 9 : ', b);
end.Demande 0 : 0, demande 9 : 2NeoBASIC
10 ' Choisir ou vont les fonctions du port serie (groupe 10, fonction 19, Trinity)
20 m = 0 : gosub 1000 : a = r
30 m = 9 : gosub 1000 : b = r : ' hors plage : automatique
40 m = 2 : gosub 1000 : ' remettre le mode par defaut
50 print "Demande 0 : ";a;", demande 9 : ";b
60 end
1000 ' Route UART to USB CDC modem : mode m (0 UART du UEXT, 1 modem USB, 2 automatique) ; mode retenu dans r
1010 while peek($ff00) : wend : poke $ff04, m : poke $ff01, 19 : poke $ff00, 10
1020 while peek($ff00) : wend : r = peek($ff04)
1030 returnDemande 0 : 0, demande 9 : 265C02 assembly (64tass)
; Choisir où vont les fonctions du port série (groupe 10, fonction 19, Trinity).
.cpu "65c02"
* = $0800
ControlPort = $FF00 ; +0 groupe, +1 fonction, +2 erreur, +4.. paramètres
WaitMessage = $FFF4 ; attend que la boîte aux lettres soit libre
WriteCharacter = $FFF1 ; affiche le caractère de A
start: lda #<r0
ldx #>r0
jsr envoi
lda ControlPort+4 ; mode retenu
sta a
lda #<r9
ldx #>r9
jsr envoi
lda ControlPort+4
sta b
lda #<r2
ldx #>r2
jsr envoi
lda #<t0
ldx #>t0
jsr ecrire
lda a
jsr decimal
lda #<t1
ldx #>t1
jsr ecrire
lda b
jsr decimal
lda #13
jsr WriteCharacter
rts
r0: .byte 10, 19, 1, 0 ; 10,19 : 0 UART du UEXT
r9: .byte 10, 19, 1, 9 ; hors plage : automatique
r2: .byte 10, 19, 1, 2 ; remettre le mode par défaut, automatique
t0: .text "Demande 0 : ", 0
t1: .text ", demande 9 : ", 0
a: .byte 0
b: .byte 0
; Appel décrit par un bloc dont l'adresse est dans A (poids faible) et X (poids fort) :
; groupe, fonction, nombre de paramètres, puis les paramètres (P0, P1...).
envoi: sta blk
stx blk+1
jsr WaitMessage
ldy #2
lda (blk),y ; nombre de paramètres
clc
adc #3
sta fin
ldy #3
_copie: cpy fin
beq _lance
lda (blk),y
sta ControlPort+1,y ; octet 3 du bloc -> P0 ($FF04)...
iny
bra _copie
_lance: ldy #1
lda (blk),y
tax
lda (blk)
jmp appel
; Affiche la chaîne terminée par 0 dont l'adresse est dans A (poids faible) et X (poids fort).
ecrire: sta ptr
stx ptr+1
ldy #0
_e: lda (ptr),y
beq _f
jsr WriteCharacter
iny
bne _e
_f: rts
; Affiche A (0-255) en décimal, sans zéros de tête.
decimal:
phx
phy
ldx #0
ldy #100
jsr _chiffre
ldy #10
jsr _chiffre
ora #'0'
jsr WriteCharacter
ply
plx
rts
_chiffre:
sty diviseur
ldy #0
_div: cmp diviseur
bcc _fini
sbc diviseur
iny
bne _div
_fini: pha
tya
bne _ecrit
cpx #0
beq _saute
_ecrit: ora #'0'
jsr WriteCharacter
ldx #1
_saute: pla
rts
; Appel : A = groupe, X = fonction (les paramètres sont déjà en place).
appel: stx ControlPort+1
sta ControlPort ; écrit en dernier : lance l'appel
jmp WaitMessage
ptr = $80
blk = $82
diviseur: .byte 0
fin: .byte 0Demande 0 : 0, demande 9 : 2