Adaptation GWBasic en PureBasic

Sujets variés concernant le développement en PureBasic
PureDev
Messages : 31
Inscription : sam. 25/janv./2014 9:42

Adaptation GWBasic en PureBasic

Message par PureDev »

Je réécrit un programme GWbasic, vieux de plus de 20 ans, en PureBasic. Une instruction me pose problème.
Après l'instriction suivante :
OPEN "COM1:2400,N,8,1" AS #2

se trouve l'instruction qui me pose problème :
OUT 1019,27

le programme se poursuit par :
PRINT #2, CHR$(195)+CHR$(27)+CHR$(4)+CHR$(98)

OUT sert à cibler un port de la machine. Mais pourquoi 1027, et pourquoi y placer la valeur 27?

Une aide serait bien venue.

Merci d'avance.
PureDev
Messages : 31
Inscription : sam. 25/janv./2014 9:42

Re: Adaptation GWBasic en PureBasic

Message par PureDev »

Pardon ma question est pourquoi 1019?
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: Adaptation GWBasic en PureBasic

Message par G-Rom »

une recherche sur google m'a amener ici :http://www.divonasperi.it/divona/tam/te ... glese).pdf
et plus précisément :
OUT Statement
Purpose:
To send a byte to a machine output port.
Syntax:
OUT h,j
Comments:
h and j are integer expressions. h may be within the range of 0 to 65535. j may be within the
range of 0 to 255. h is a machine port number, and j is the data to be transmitted.
OUT is the complementary statement to the INP function.
Examples:
100 OUT 12345,225
Outputs the decimal value 225 to port number 12345. In assembly language, this is equivalent to
the following:
MOV DX,12345
MOV AL,255
OUT DX,AL
donc , 1019 est un port réseau.

edit:

27 , c'est le code ascii de la touche echap.
PureDev
Messages : 31
Inscription : sam. 25/janv./2014 9:42

Re: Adaptation GWBasic en PureBasic

Message par PureDev »

Merci d'avoir pris le temps de me répondre.
J'avais déjà trouvé ces renseignements.
Le code 27 ASCII ne m'avait pas échappé non plus.

Par contre, je ne comprend toujours pas le pourquoi de cette instruction.

Que va-t-elle déclencher?

Pourquoi envoyer le code Esc à un port réseau, avant la communication par le port série RS232?

S'agit-il de faire un "ofset" de 27 pour ne pas envoyer les codes de contrôle de 0 à 26?

Je me perd en conjectures diverses.

Merci.
Mesa
Messages : 1098
Inscription : mer. 14/sept./2011 16:59

Re: Adaptation GWBasic en PureBasic

Message par Mesa »

Ou la ! pas du tout :D

ça fleure bon le DOS voir le bon vieux ordi MSX. :wink:

Port ne veut pas forcement dire réseau.
Les microprocesseurs ont des ports, les microcontrôleurs et pratiquement toutes les puces que l'on trouve dans un ordinateur et autres machines programmables ont des ports. Les kernels et autres systèmes d'exploitations ont des ports aussi.

Ici le port 1019 c'est le port 3FB en hexadécimal.
Il permet, en utilisant les vieux basic ou le langage assembleur, d'accéder à la puce 8250 (de chez National Semiconductor)
http://en.wikipedia.org/wiki/8250_UART
C'est cette puce électronique qui permet d'avoir un port COM.
On la programme en passant par tous ces ports là :
http://stanislavs.org/helppc/8250.html
dont le Port 3FB - Line Control Register - LCR (read/write)
|7|6|5|4|3|2|1|0| 2FB, 3FB Line Control Register
| | | | | | `------ word length select bits (see below)
| | | | | `------- 0 = 1 stop bit, 1 = 1.5 or 2 (see note)
| | | | `-------- 0 = no parity, 1 = parity (PEN)
| | | `--------- 0 = odd parity, 1 = even (EPS)
| | `---------- 0 = parity disabled, 1 = enabled
| `----------- 0 = turn break off, 1 = force spacing break state
`------------ 1 = baud rate divisor (DLAB); 0 = RBR, THR or IER

Bits
10 Word length bits
00 = 5 bits per character
01 = 6 bits per character
10 = 7 bits per character
11 = 8 bits per character

- stop bits = 1.5 for 5 bit words or 2 for 6, 7 or 8 bit words
- bit 7 changes the mode of registers 3F8 and 3F9. If set these
registers become the LSB and MSB of the baud rate divisor.
Otherwise 3F8 is the Transmit/Receive Buffer Register and 3F9 is
the Interrupt Enable Register.


[Édition : Voir ici pour plus d'explication sur le LCR http://www.lammertbies.nl/comm/info/ser ... t.html#LCR]

Donc l'envoi de 27 en décimal soit 1B en hexadécimal, va programmer la puce avec le binaire 0001 1011
0 = RBR, THR or IER
0 = turn break off
0 = parity disabled
1 = even (EPS)
1 = parity (PEN)
0 = 1 stop bit
11 = 8 bits per character

C'est redondant avec l'instruction OPEN "COM1:2400,N,8,1".
Peut-être que l'instruction OPEN "COM1:2400,N,8,1" n'était pas suffisante pour le programmeur, ou alors elle était boguée.

Voir aussi http://www.gladir.com/LEXIQUE/PORTS/INDEX.HTM
http://www.oocities.org/KindlyRat/GWBASIC.html

Même s'il est possible d’utiliser l'instruction assembleur "OUT", il est quand même plus que conseiller d'utiliser les instructions COM de PureBasic.

M.
PureDev
Messages : 31
Inscription : sam. 25/janv./2014 9:42

Re: Adaptation GWBasic en PureBasic

Message par PureDev »

Merci Mesa.
Explication claire et précise.
J'ai enfin compris.
PureDev
Messages : 31
Inscription : sam. 25/janv./2014 9:42

Re: Adaptation GWBasic en PureBasic

Message par PureDev »

Encore une question concernant le paramétrage du port série.

Est-il possible de programmer en PureBasic l'équivalent de "out 1019,27"?

Mon activité consiste à communiquer avec 7 microcrontoleurs cablés en boucle de courant liaison série.

Je ne connait pas les paramétres de configuration de cette liaison.

Un ancien programme en GWBASIC utilisait avec succès la commande out 1019,27.

Pouvez vous m'aider à paramétrer correctement OpenSerialPort ?

J'ai tenté OpenSerialPort( 1,"COM1",2400,#PB_serialPort_EvenParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)

La communication s'établit, mais les valeurs en retour me semblent incorrectes.

Davance merci.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Adaptation GWBasic en PureBasic

Message par djes »

Ce serait plus simple si tu nous permettais de voir le programme original et ta conversion...
PureDev
Messages : 31
Inscription : sam. 25/janv./2014 9:42

Re: Adaptation GWBasic en PureBasic

Message par PureDev »

Merci d'avoir répondu
A mon avis, voir le programme n'apportera pas de renseignements complementaires.
D'une part, je possede seulement le listing sur papier du GWBASIC (environ 30 pages).
D'autre part, mon programme équivalent en PureBasic, commence à être une vraie usine à gaz.
Il gère 7 boitiers électroniques analysant des sondes de température, balances électroniques et diverses informations ou ordres.

Mon problème ne se situe pas au niveau de la programmation. Pour pouvoir créer mon programme j'ai créé d'abord un simulateur de l'atelier.
Celui-ci tourne sur un micro. Je développe sur un autre micro en communication RS232 avec le premier. Je gère très bien cet ensemble par un paramétrage série qui fonctionne parfaitement. C'et normal, puisque j'ai mis les mêmes paramètres sur les deux machines.

Je suis arrivé au stade de l'instalation de mon programme en situation réélle, en communication avec le matériel. Et c'est là que se situe mon problème.

L'ancien programmeur (en GWBASIC) avait placé la commande suivante : OPEN "COM1:2400,N,8,1" AS #2

Cette commande ne devait pas fonctionner puisqu'il faisait suivre cette commande par : OUT 1019,27.

Il s'agit de la programmation directe de l'UART. On place sur le port 1019, la valeur 27 qui définit le comportement de la liaison série. J'ai déjà été aidé pour la compréhension de la programmation de ce port dans ce forum, et je remercie à nouveau pour les éclaircissements apportés. J'ai tenté de traduire cette valeur 27 en programmation PureBasic. C'est l'OpenSerialPort de mon précédent message.

La communication avec le matériel de l'atelier a été établi, mais je pense qu'elle n'est pas parfaite, car je ne reçois pas les valeurs attendues. Plusieurs hypothèses peuvent être avancées. L'une concerne la programmation (en PureBasic) du port série.

Je reformule donc mes deux demandes:

1) Est-il possible de programmer en PureBasic l'équivalent de OUT 1019,27 du GWBASIC? Et plus généralement, est-il possible de placer une valeur dans une adresse mémoire?

2) Pouvez vous m'aider à écrire la commande OpenSerialPort correspondant à OUT 1019,27?

Merci de prendre le temps de me répondre. Cordialement.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Adaptation GWBasic en PureBasic

Message par djes »

Oui, j'avais bien compris ton problème, et je pense maintenant que si cela ne fonctionne pas à ce niveau, c'est parce que tu dois mal t'y prendre pour gérer le port série (ne le prends pas mal!). C'est assez différent du GW-BASIC et de la commande OUT, qui était une commande bas niveau (accès direct au matériel). Depuis Windows 95/NT, il n'est plus permis à un programme de faire ce genre de chose, c'est l'OS (Windows), qui s'en charge, et qui offre les mêmes (ahem!) possibilités, via une file d'attente (buffer/tampon). Je ne te demande évidemment pas tout ton programme (surtout pas!!!!), mais juste la partie qui gère les E/S via le port série.
PureDev
Messages : 31
Inscription : sam. 25/janv./2014 9:42

Re: Adaptation GWBasic en PureBasic

Message par PureDev »

Merci, j'enverrai la partie de code demain. Pas dispo ce soir.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Adaptation GWBasic en PureBasic

Message par Ollivier »

C'est ta parité qui merde. Et, effectivement, c'était bogué.

If INKEY$ = CHR$(0) + "H"
(ça c'est touche flèche haut)
La même chose mais avec la lettre majuscule P
ça c'est la flèche bas
K (flèche gauche)
M (flèche droite)

La saisie subit un délai quand tu reste appuyé sur la touche exactement comme les touches classiques.

Les chaînes ne doivent pas dépasser 255 caractères.
Ce ne sont pas des zéro terminal.


CSRLIN et POS(0)
Le 1er indique le numéro de ligne du curseur entre 1 inclus et 24 inclus si mode KEY ON ou 25 inclus si mode KEY OFF.

Le 2nd indique le numéro de colonne du curseur entre 1 et 80 (quand on traitait l'ASM, fallait gérer ces merdes de décalage de 1 caractère et d'une ligne dans le &hb800...)
Ou entre 1 et 40 si tu étais où quittais le mode SCREEN 1.

D'ailleurs WIDTH 40 ou WIDTH 80 s'utilisait pour switcher ou corriger une largeur d'écran de texte.

DEF SEG
VARSEG
VARPTR
POKE
PEEK
CALL

Si tu as une routine ASM en machine en data autant la scanner avec le débogueur pb que de lui faire croire que tu as 16 segments, etc...

si tu trouve &hA000 et d'autres ports in/out, c'est pour contrôler les 4 plans de bits pour le plus "puissants" des mode graphiques : 640x350x4
(transferts fichier BSAVE et BLOAD à côté sûrement...
BSAVE "fichier.dat",offset%,taille%
le bload s'induit...

La ligne... Ah, ça c'était trop fort:
LINE (x1, y1)-(x2,y2),couleur,motif

La ligne avait les motifs sur 16 bits (le tramage était d'usage)

GET (x1,y1)-(x2,y2),a%(0)
PUT (x1,y1),a%(1)
ça, ça fait le scrolling horizontal de derrick.

INSTR(A$,B$,depart) = findstring$()

DRAW "blablasansespace"
c'est la tortue qui trace
U1 monte d'un pixel
D1 descend
L1 va gauche
R2 va de 2pixels à droite
E1 diagonale haut droite
F1 dia basdroi
G1 dia basgauche
H1 dia hautgauche
Cx
(x de 0 à 15) couleur
Px,y se localise ailleurs

Note : avant un draw on met un PSET(x,y),c pour indiquer où commence le dessin.

bon allez.. de vieux souvenirs tout ça, le 2ème language informatique appris il y a 26 ans maintenant... (ce2...) ça reste gravé...
Mesa
Messages : 1098
Inscription : mer. 14/sept./2011 16:59

Re: Adaptation GWBasic en PureBasic

Message par Mesa »

Le OPEN "COM1:2400,N,8,1" AS #2 se traduit par

Code : Tout sélectionner

OpenSerialPort( 1,"COM1",2400,#PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
et le out 1019,27 change la parité et se traduit par

Code : Tout sélectionner

OpenSerialPort( 1,"COM1",2400,#PB_SerialPort_EvenParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
C'est donc ok.

A cette adresse http://www.purebasic.fr/english/viewtop ... 05#p405305 , on peut télécharger
http://pure-basic.narod.ru/forum_files/ ... PortIO.zip


Il permet de faire un "out" sous windows avec une dll (dans le zip).

Avec le code ci-dessous, le debug doit afficher 27.

Code : Tout sélectionner

CompilerIf Defined(PBIO_OK, #PB_Constant)=0
  Enumeration
    #PBIO_OK
    #PBIO_ErrCopyDriver
    #PBIO_ErrInstallDriver
    #PBIO_ErrAccess
  EndEnumeration
CompilerEndIf

If OpenLibrary(2, "PB_IO.dll")=0
  MessageRequester("", "Íåò PB_IO.dll.", #MB_OK|#MB_ICONERROR)
  End
EndIf

Prototype Inp(PortAddress.u)
Prototype Out(PortAddress.u, Byte.a)
Prototype Status()
Prototype.f Version()

Inp.Inp =        GetFunction(2, "Inp")
Out.Out =        GetFunction(2, "Out")
Status.Status =  GetFunction(2, "Status")
Version.Version =GetFunction(2, "Version")

Err = Status()
If Err<>#PBIO_OK
  MessageRequester("", "Îøèáêà äðàéâåðà "+Str(Err))
EndIf


; Out($378, 120)
; Byte = Inp($378)


;OPEN "COM1:2400,N,8,1" AS #2 -> equivaut à out 1019, 3
;OpenSerialPort( 1,"COM1",2400,#PB_SerialPort_NoParity, 8, 1)

;out 1019, 27
OpenSerialPort( 1,"COM1",2400,#PB_SerialPort_EvenParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
;OpenSerialPort( 1,"COM1",2400,#PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
Byte = Inp($3FB)

MessageRequester("", Str(Byte))

Après, il faudrait vérifier que le port 1019 n'aie pas été redirigé soit en hardware soit en software, sur la machine d'origine. Dans ce cas c'est indiqué dans la notice de la machine ou la notice du basic livré avec la machine et voir à quoi il correspond. Ça serait pas de chance.

Il faut bien faire attention lors de la lecture car ce sont des octets qu'il faut lire, un à un, pas une string ,ni un caracter (.c) ni un long (.l)
Nom Extension Encombrement en mémoire Plage
Byte .b 1 octet -128 à +127
Ascii .a 1 octet 0 à +255

Code : Tout sélectionner

Resultat = ReadSerialPortData(#PortSerie, *Memoire, Taille)
+
Valeur = PeekB(*Memoire)
ou 
Valeur = PeekA(*Memoire)
Il faudrait essayé aussi les différents temps de latences avec SerialPortTimeouts() et tenter d'autres status avec SetSerialPortStatus().


M.
PureDev
Messages : 31
Inscription : sam. 25/janv./2014 9:42

Re: Adaptation GWBasic en PureBasic

Message par PureDev »

Merci pour vos réponses. Vous mavez donner des idées pour tester.
Je retourne sur site demain. Je vous tiendrai au courant.
J'avais bien traduit le out 1019,27 dans sa correspondance Purebasic.
Mes erreurs en reception de données proviennent vraisemblablement d'ailleurs.
PureDev
Messages : 31
Inscription : sam. 25/janv./2014 9:42

Re: Adaptation GWBasic en PureBasic

Message par PureDev »

Aprés avoir effectué les essais sur site, je pense avoir cerné mon problème de réception, mais ne parvient pas à le résoudre.
L'ordinateur sur lequel est implémanté l'application PureBasic interroge tour à tour 7 boitiers construits chacuns autour d'un microcontroleur.

La communication s'effectue en boucle de courant sur liaison série RS232.

L'interrogation d'un boitier se fait en envoyant une chaine de 4 caractères. Exemple pour le boitier 1:
Chr(192)+Chr(27)+Chr(4)+Chr(95)
Ces paramètres sont définis par le constructeur des boitiers électroniques.
L'ordinateur reçoit d'abord cette même chaine, en boucle de courant on reçoit d'abord la question posée comme un eccho.
Mon programme fonctionne parfaitement, le paramétrage de la liaison série est donc correcte.

Vient ensuite la réponse du boitier interrogé. La réponse est une chaine de 10 caractères.
D'abord 3 caractères qui confirment l'adresse du boitier 1 : Chr(128)+Chr(27)+Chr(4)
Puis 6 caractères qui donnent les valeurs des événements gérés par le boitier : température de sonde, poids sur balance, débit d'eau etc.
Et enfin le dixième et dernier caractère qui la checksum.

Mon problème réside dans la gestion des valeurs zéros. Exemple:
quand le boitier doit envoyé la chaine : Chr(192)+Chr(27)+Chr(4)+Chr(95)+Chr(22)+Chr(18)+Chr(0)+Chr(54)+Chr(0)+Chr(195)
Mon programme reçoit :
192 27 4 95 22 18 54 195 0 0
A mon avis quand la valeur 0, correspondant au code ASCII 0 (NULL), aucune valeur est déposée dans la zone mémoire. Les zéros sont ignorés.
Comme la trame est sur 10 caractères, l'algorithme de réception ne trouvant pas de valeurs dans les mémoires vides, elles sont ignorées, et à la fin n'ayant pas de valeur il m'est des 0.

J'ai tenté sans succès diverses stratégies, la réception d'une trame de 14 caractères (l'eccho 4 caractères, plus la données 10 caractères). J'ai imaginé des algorithmes les plus fumeux les uns que les autres sans succès. Vous en trouverez des exemples ci-dessous.
Comme créer 14 zones mémoires (une par caratère) afin de gérer individuellement la réception des caratères afin de traiter la réception des 0.
Tout cela sans succès.
Pouvez-vous m'aider? Il est possible qu'une mauvaise maitrise du port série soit la cause de mes difficultés.

Code : Tout sélectionner

Procedure EmissionCom(NumeroBoitier.i)
  
*Memoire=AllocateMemory(4)         
If IsSerialPort(#PortSerie) <> 0
Debug  NumeroBoitier 
Debug boitier(NumeroBoitier)
  Resultat = PokeS(*Memoire, boitier(NumeroBoitier) , 4,#PB_Ascii)
  WriteSerialPortData(#PortSerie,*Memoire,4)
Else
  Debug "le port série n'est pas initialisé"
EndIf

              ;####################################
              ;#      RECEVOIR ECCHO #
              ;####################################
   ;Reception.s=PeekS(*Memoire,14,#PB_Ascii)

*Memoire1=AllocateMemory(1)
*Memoire2=AllocateMemory(1)
*Memoire3=AllocateMemory(1)
*Memoire4=AllocateMemory(1)
*Memoire5=AllocateMemory(1)
*Memoire6=AllocateMemory(1)
*Memoire7=AllocateMemory(1)
*Memoire8=AllocateMemory(1)
*Memoire9=AllocateMemory(1)
*Memoire10=AllocateMemory(1)
*Memoire11=AllocateMemory(1)
*Memoire12=AllocateMemory(1)
*Memoire13=AllocateMemory(1)
*Memoire14=AllocateMemory(1)


ReadSerialPortData(#PortSerie,*Memoire1,1)
ReadSerialPortData(#PortSerie,*Memoire2,1)
ReadSerialPortData(#PortSerie,*Memoire3,1)
ReadSerialPortData(#PortSerie,*Memoire4,1)
ReadSerialPortData(#PortSerie,*Memoire5,1)
ReadSerialPortData(#PortSerie,*Memoire6,1)
ReadSerialPortData(#PortSerie,*Memoire7,1) 
ReadSerialPortData(#PortSerie,*Memoire8,1)
ReadSerialPortData(#PortSerie,*Memoire9,1)
ReadSerialPortData(#PortSerie,*Memoire10,1)
ReadSerialPortData(#PortSerie,*Memoire11,1)
ReadSerialPortData(#PortSerie,*Memoire12,1)
ReadSerialPortData(#PortSerie,*Memoire13,1)
ReadSerialPortData(#PortSerie,*Memoire14,1)



  ; DRchaine(1)=PeekS(*Memoire1,1,#PB_Ascii)
  ; DRchaine(2)=PeekS(*Memoire2,1,#PB_Ascii)
  ; DRchaine(3)=PeekS(*Memoire3,1,#PB_Ascii)
  ; DRchaine(4)=PeekS(*Memoire4,1,#PB_Ascii)
  ; DRchaine(5)=PeekS(*Memoire5,1,#PB_Ascii)
  ; DRchaine(6)=PeekS(*Memoire6,1,#PB_Ascii)
  ; DRchaine(7)=PeekS(*Memoire7,1,#PB_Ascii)
  ; DRchaine(8)=PeekS(*Memoire8,1,#PB_Ascii)
  ; DRchaine(9)=PeekS(*Memoire9,1,#PB_Ascii)
  ; DRchaine(10)=PeekS(*Memoire10,1,#PB_Ascii)
  ; DRchaine(11)=PeekS(*Memoire11,1,#PB_Ascii)
  ; DRchaine(12)=PeekS(*Memoire12,1,#PB_Ascii)
  ; DRchaine(13)=PeekS(*Memoire13,1,#PB_Ascii)
  ; DRchaine(14)=PeekS(*Memoire14,1,#PB_Ascii)
   DRchaine(1)=PeekA(*Memoire1)
   DRchaine(2)=PeekA(*Memoire2)
   DRchaine(3)=PeekA(*Memoire3)
   DRchaine(4)=PeekA(*Memoire4)
   DRchaine(5)=PeekA(*Memoire5)
   DRchaine(6)=PeekA(*Memoire6)
   DRchaine(7)=PeekA(*Memoire7)
   DRchaine(8)=PeekA(*Memoire8)
   DRchaine(9)=PeekA(*Memoire9)
   DRchaine(10)=PeekA(*Memoire10)
   DRchaine(11)=PeekA(*Memoire11)
   DRchaine(12)=PeekA(*Memoire12)
   DRchaine(13)=PeekA(*Memoire13)
   DRchaine(14)=PeekA(*Memoire14)
Répondre