Utilisation d'une TI 84 en terminal

From Eric

(Difference between revisions)
Jump to: navigation, search
m
m
Line 13: Line 13:
On trouvera [http://www.ticalc.org/pub/text/calcinfo/82-ports.txt ici] une description des signaux. Le protocole physique est le suivant :
On trouvera [http://www.ticalc.org/pub/text/calcinfo/82-ports.txt ici] une description des signaux. Le protocole physique est le suivant :
-
<à compléter>
+
  Write:
 +
 
 +
  Write $C0: white wire positive, red wire positive
 +
  Write $D4: white wire positive, red wire negative
 +
  Write $E8: white wire negative, red wire positive
 +
  Write $FC: white wire negative, red wire negative
 +
  Read:
 +
 
 +
  bit 1 set: White wire is positive, but circuit is open
 +
  bit 1 res: White wire negative, or positive with electrons flowing
 +
  bit 0 set: Red wire is positibe, but circuit is open
 +
  bit 0 res: Red wire negative, or positive with electrons flowing
Line 38: Line 49:
Or, si je veux utiliser la calculatrice comme un terminal, je veux pouvoir émettre et recevoir des flux composés uniquement d'octets "utilisateur". La solution consiste à implémenter dans l'interface un bout de logiciel qui va convertir un format dans l'autre. C'est faisable, assez simple, mais il y a plus simple.
Or, si je veux utiliser la calculatrice comme un terminal, je veux pouvoir émettre et recevoir des flux composés uniquement d'octets "utilisateur". La solution consiste à implémenter dans l'interface un bout de logiciel qui va convertir un format dans l'autre. C'est faisable, assez simple, mais il y a plus simple.
-
On peut en effet piloter directement, "à la main", l'interface matérielle de la calculatrice, mais il faut alors faire un peu d'assembleur Z80. On trouvera dans la rubrique [[Programmation assembleur de la TI84 Stats]] quelques explications sur les outils à utiliser et la façon de les utiliser... Le pilotage est assez simple car il se résume à des quelques "in" et "out" sur le port adéquat. Voici, par exemple, le bout d'assembleur Z80 qui réalise les opérations d'émission et de réception d'un octet :  
+
On peut en effet piloter directement, "à la main", l'interface matérielle de la calculatrice, mais il faut alors faire un peu d'assembleur Z80. On trouvera dans la rubrique [[Programmation assembleur de la TI84 Stats]] quelques explications sur les outils à utiliser et la façon de les utiliser... Le pilotage est assez simple car il se résume à des quelques "in" et "out" sur le port adéquat.
 +
 
 +
Voici, par exemple, le bout d'assembleur Z80 qui réalise les opérations d'émission et de réception d'un octet :  
   ;
   ;
Line 45: Line 58:
   ; To use them call "ReceiveByte" or "SendByte". You can test the port
   ; To use them call "ReceiveByte" or "SendByte". You can test the port
   ; (and receive byte if necessary) with "TryReceiveByte".
   ; (and receive byte if necessary) with "TryReceiveByte".
-
 
+
 
   ;      LINK PORT WRITE EQUATES
   ;      LINK PORT WRITE EQUATES
   ;
   ;
Line 53: Line 66:
   #define D0HD1H                    0C0h
   #define D0HD1H                    0C0h
   #define BPORT                    0
   #define BPORT                    0
-
 
+
 
   #define LINKMASK 12
   #define LINKMASK 12
-
 
+
 
   TryReceiveByte:
   TryReceiveByte:
-
in a,(BPORT)
+
  in a,(BPORT)
-
and LINKMASK
+
  and LINKMASK
-
cp LINKMASK
+
  cp LINKMASK
-
scf
+
  scf
-
ret z
+
  ret z
   ReceiveByteCont:
   ReceiveByteCont:
-
call LinkPrep
+
  call LinkPrep
-
jr ReceiveCont
+
  jr ReceiveCont
   ReceiveByte:
   ReceiveByte:
-
call LinkPrep
+
  call LinkPrep
   ReceiveBits:
   ReceiveBits:
-
ld de,-1
+
  ld de,-1
   WaitRecBit:
   WaitRecBit:
-
call CheckLink
+
  call CheckLink
-
jr z,LinkFailed
+
  jr z,LinkFailed
-
cp LINKMASK
+
  cp LINKMASK
-
jr z,WaitRecBit
+
  jr z,WaitRecBit
   ReceiveCont:
   ReceiveCont:
-
sub LINKMASK/3*2
+
  sub LINKMASK/3*2
-
ld a,LINKMASK/3*2
+
  ld a,LINKMASK/3*2
-
ld d,D0LD1H
+
  ld d,D0LD1H
-
jr c,ReceiveLow
+
  jr c,ReceiveLow
-
rra
+
  rra
-
ld d,D0HD1L
+
  ld d,D0HD1L
   ReceiveLow:
   ReceiveLow:
-
rr c
+
  rr c
-
ld (AckBit),a
+
  ld (AckBit),a
-
ld a,d
+
  ld a,d
-
out (BPORT),a
+
  out (BPORT),a
-
ld de,-1
+
  ld de,-1
   WaitAckRec:
   WaitAckRec:
-
call CheckLink
+
  call CheckLink
-
cp 0
+
  cp 0
   AckBit =$-1
   AckBit =$-1
-
jr nz,WaitAckRec
+
  jr nz,WaitAckRec
-
ld a,D0HD1H
+
  ld a,D0HD1H
-
out (BPORT),a
+
  out (BPORT),a
-
ld d,4
+
  ld d,4
   WaitReadyRec:
   WaitReadyRec:
-
dec d
+
  dec d
-
jr z,ReadyRec
+
  jr z,ReadyRec
-
in a,(BPORT)
+
  in a,(BPORT)
-
cp LINKMASK
+
  cp LINKMASK
-
jr nz,WaitReadyRec
+
  jr nz,WaitReadyRec
   ReadyRec:
   ReadyRec:
-
djnz ReceiveBits
+
  djnz ReceiveBits
-
jr LinkSuccess
+
  jr LinkSuccess
-
 
+
 
   LinkPrep:
   LinkPrep:
-
ex (sp),hl
+
  ex (sp),hl
-
push bc
+
  push bc
-
push de
+
  push de
-
set indicOnly,(iy+indicflags)
+
  set indicOnly,(iy+indicflags)
-
ld b,8
+
  ld b,8
-
jp (hl)
+
  jp (hl)
-
 
+
 
   SendByte:
   SendByte:
-
call LinkPrep
+
  call LinkPrep
-
ld c,a
+
  ld c,a
-
;ld a, 255
+
-
;ld (stime), a
+
   SendBits:
   SendBits:
-
rr c
+
  rr c
-
ld a,D0LD1H
+
  ld a,D0LD1H
-
jr nc,SendLow
+
  jr nc,SendLow
-
ld a,D0HD1L
+
  ld a,D0HD1L
   SendLow:
   SendLow:
-
out (BPORT),a
+
  out (BPORT),a
-
ld de,-1
+
  ld de,-1
   WaitAckSend:
   WaitAckSend:
-
call CheckLink
+
  call CheckLink
-
jr nz,WaitAckSend
+
  jr nz,WaitAckSend
   SendAcked:
   SendAcked:
-
ld a,D0HD1H
+
  ld a,D0HD1H
-
out (BPORT),a
+
  out (BPORT),a
-
ld de,-1
+
  ld de,-1
   WaitReadySend:
   WaitReadySend:
-
call CheckLink
+
  call CheckLink
-
cp LINKMASK
+
  cp LINKMASK
-
jr nz,WaitReadySend
+
  jr nz,WaitReadySend
-
djnz SendBits
+
  djnz SendBits
   LinkSuccess:
   LinkSuccess:
-
or 0
+
  or 0
   .org $-1
   .org $-1
   LinkFailed:
   LinkFailed:
-
scf
+
  scf
-
res indicOnly,(iy+indicflags)
+
  res indicOnly,(iy+indicflags)
-
ld a,0D0h
+
  ld a,0D0h
-
out (BPORT),a
+
  out (BPORT),a
-
ld a,c
+
  ld a,c
-
pop de
+
  pop de
-
pop bc
+
  pop bc
-
pop hl
+
  pop hl
-
ret
+
  ret
-
 
+
 
   CheckLink:
   CheckLink:
-
pop hl
+
  pop hl
-
dec de
+
  dec de
-
ld a,d
+
  ld a,d
-
or e
+
  or e
-
jr z,LinkFailed
+
  jr z,LinkFailed
-
ld a,0BFh
+
  ld a,0BFh
-
;call stimeout
+
  in a,(BPORT)
-
;cp 0
+
  and LINKMASK
-
;call _readkeypad
+
  jp (hl)
-
;bit 6,a
+
 
-
;jr z,LinkFailed
+
-
in a,(BPORT)
+
-
and LINKMASK
+
-
jp (hl)
+
-
 
+
= Conclusion =
= Conclusion =

Revision as of 12:16, 16 June 2012

Contents

Objectifs

L'objectif est d'utiliser une calculatrice TI82-stats comme terminal de debug de mes montages à microcontrôleurs, en lieu et place de mon vieux portable.

En pratique, il va s'agir de réaliser une petite interface matérielle et logicielle permettant de transformer un flux au format électrique et logique "texas" en en flux au format RS232 TTL.

Réalisation

Adaptation des signaux électriques

La calculatrice dispose de deux ports bidirectionnels en collecteur ouvert (fil rouge et fil blanc). La transmission d'un bit se fait en positionnant l'un des fils au niveau haut et en récupérant l'accusé de réception sur l'autre fil. Il semble que les niveaux soient TTL.

On trouvera ici une description des signaux. Le protocole physique est le suivant :

 Write:
 
 Write $C0: white wire positive, red wire positive
 Write $D4: white wire positive, red wire negative
 Write $E8: white wire negative, red wire positive
 Write $FC: white wire negative, red wire negative
 Read:
 
 bit 1 set: White wire is positive, but circuit is open
 bit 1 res: White wire negative, or positive with electrons flowing
 bit 0 set: Red wire is positibe, but circuit is open
 bit 0 res: Red wire negative, or positive with electrons flowing


L'interface hardware est chargée de transformer le flux en provenance de la calculatrice en un flux série standard. L'idée est d'utiliser un port d'entrée et un port de sortie par fil (on pourrait n'utiliser qu'un port par fil mais : ça complique vaguement le logiciel et n'importe quel microcontrôleur disposant de voies d'entrées / sorties série dispose aussi d'un nombre plus que suffisant de ports.

L'interface matérielle est la suivante (c'est un peu luxueux, on pourrait faire plus simple) :

Naturellement, on trouve bien des montages sur internet :

Tilink-original.jpg
  • Le fameux $4 serial link (et d'autres solutions) dont voici le schéma :
Tilink-4-dollars.jpg
  • Le modèle de Sami qui utilise un microcontrôleur. Voici le schéma :
Tilink-sami.jpg


Le logiciel

Du côté de la calculatrice, il va s'agir de transmettre et recevoir des flux émis par le micro-contrôleur. La calculatrice dispose de fonctions (en basic) permettant de transmettre une variable, une liste, etc. Cependant, ces données sont transmises selon un protocole particulier qui permet (notamment) de connaître la nature du flux, sa taille, etc. On trouve de l'information sur le format de trames sans avoir à faire trop de rétro-ingénierie, par exemple [<à completer> ici].

Or, si je veux utiliser la calculatrice comme un terminal, je veux pouvoir émettre et recevoir des flux composés uniquement d'octets "utilisateur". La solution consiste à implémenter dans l'interface un bout de logiciel qui va convertir un format dans l'autre. C'est faisable, assez simple, mais il y a plus simple.

On peut en effet piloter directement, "à la main", l'interface matérielle de la calculatrice, mais il faut alors faire un peu d'assembleur Z80. On trouvera dans la rubrique Programmation assembleur de la TI84 Stats quelques explications sur les outils à utiliser et la façon de les utiliser... Le pilotage est assez simple car il se résume à des quelques "in" et "out" sur le port adéquat.

Voici, par exemple, le bout d'assembleur Z80 qui réalise les opérations d'émission et de réception d'un octet :

 ;
 ; Link routines taken from Telnet 83,
 ; Sent to me by Scott Dial <homosapian@geocities.com>.
 ; To use them call "ReceiveByte" or "SendByte". You can test the port
 ; (and receive byte if necessary) with "TryReceiveByte".
 
 ;       LINK PORT WRITE EQUATES
 ;
 #define		D0LD1L                    0C3h
 #define		D0LD1H                    0C1h
 #define		D0HD1L                    0C2h
 #define		D0HD1H                    0C0h
 #define		BPORT                     0
 
 #define	LINKMASK	12
 
 TryReceiveByte:
 	in	a,(BPORT)
 	and	LINKMASK
 	cp	LINKMASK
 	scf
 	ret	z
 ReceiveByteCont:
 	call	LinkPrep
 	jr	ReceiveCont
 ReceiveByte:
 	call	LinkPrep
 ReceiveBits:
 	ld	de,-1
 WaitRecBit:
 	call	CheckLink
 	jr	z,LinkFailed
 	cp	LINKMASK
 	jr	z,WaitRecBit
 ReceiveCont:
 	sub	LINKMASK/3*2
 	ld	a,LINKMASK/3*2
 	ld	d,D0LD1H
 	jr	c,ReceiveLow
 	rra
 	ld	d,D0HD1L
 ReceiveLow:
 	rr	c
 	ld	(AckBit),a
 	ld	a,d
 	out	(BPORT),a
 	ld	de,-1
 WaitAckRec:
 	call	CheckLink
 	cp	0
 AckBit =$-1
 	jr	nz,WaitAckRec
 	ld	a,D0HD1H
 	out	(BPORT),a
 	ld	d,4
 WaitReadyRec:
 	dec	d
 	jr	z,ReadyRec
 	in	a,(BPORT)
 	cp	LINKMASK
 	jr	nz,WaitReadyRec
 ReadyRec:
 	djnz	ReceiveBits
 	jr	LinkSuccess
 
 LinkPrep:
 	ex	(sp),hl
 	push	bc
 	push	de
 	set	indicOnly,(iy+indicflags)
 	ld	b,8
 	jp	(hl)
 
 SendByte:
 	call	LinkPrep
 	ld	c,a
 SendBits:
 	rr	c
 	ld	a,D0LD1H
 	jr	nc,SendLow
 	ld	a,D0HD1L
 SendLow:
 	out	(BPORT),a
 	ld	de,-1
 WaitAckSend:
 	call	CheckLink
 	jr	nz,WaitAckSend
 SendAcked:
 	ld	a,D0HD1H
 	out	(BPORT),a
 	ld	de,-1
 WaitReadySend:
 	call	CheckLink
 	cp	LINKMASK
 	jr	nz,WaitReadySend
 	djnz	SendBits
 LinkSuccess:
 	or	0
 .org $-1
 LinkFailed:
 	scf
 	res	indicOnly,(iy+indicflags)
 	ld	a,0D0h
 	out	(BPORT),a
 	ld	a,c
 	pop	de
 	pop	bc
 	pop	hl
 	ret
 
 CheckLink:
 	pop	hl
 	dec	de
 	ld	a,d
 	or	e
 	jr	z,LinkFailed
 	ld	a,0BFh
 	in	a,(BPORT)
 	and	LINKMASK
 	jp	(hl)
 

Conclusion

Voici le résultat :

<à compléter>

Personal tools