HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Ici, on fait dans le petit, le LCD qui déchire sa race, on y cause même calculatrices quand on est en manque !

Modérateur : Politburo

Répondre
Avatar du membre
pcscote
Fonctionne à 300 bauds
Fonctionne à 300 bauds
Messages : 160
Enregistré le : 11 juil. 2018 01:06
Localisation : Québec/Canada

HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Message par pcscote »

Début 2021, Mark Power webmaster du club HPCC m'a demandé de l'aide pour récupérer les données d'une cassette numérique.

La particularité de cette cassette est qu'elle était compatible au lecteur HP-82161A mais que son formatage lui ne l'était pas.
PVI, le format utilisé pour les médiums de stockage par les contrôleurs HP-IL de poche (41, 71 & 75) s'appelle Logical Interchange Format ou LIF.
La conséquence de ce format non-LIF est qu'aucune machine HP n'est capable de lire la cassette avec les fonctions habituelles.
Donc, pour récupérer les données, j'ai été obligé d'écrire un programme qui utilise que les commandes HP-IL de bas niveau.

Afin de limiter la complexité d'utiliser deux périphériques, un pour la lecture et l'autre pour l'écriture, j'ai décidé de sauvegarder le contenu de la cassette (128K) dans l'ordinateur de poche. (HP-71B)
Le fichier final à été transféré avec la PIL-Box sur un ordinateur pour traitement ultérieur.

Matériels nécessaires pour la lecture de la cassette:
  • HP-71B (~16K de RAM interne)
  • 82401A module HP-IL pour HP-71
  • 128K de RAM additionnel (modules CMT, HHP, FRAM71, etc)
  • 82167x deux câbles HP-IL
  • 82161A lecteur de cassette numérique
  • 82176A cassette numérique
Choisir l'option "Aperçu avant impression" pour obtenir une meilleure visualisation du programme.

Programme d'extraction ...

Code : Tout sélectionner

 10 ! TAPEDUMP @Copyrights 2021, Sylvain Cote
 11 ! last updated on: 2021-03-20 21h10 EDT
 12 ! Program: do a sector by sector tape dump to a file in main memory (~130KB)
 13 ! Needs  : 71B, 82401A, ~140KB of main RAM

 30 ! A   : DriveAddress       (constant)
 31 ! B   : DriveBusyFlag
 32 ! C   : DriveErrorCode
 33 ! D   : DeviceAccessoryID
 34 ! E   : DriveErrorFlag
 35 ! L   : DriveErrorLevel
 36 ! L0  : InputBufferLength
 37 ! L2  : LogDriveError
 38 ! R0  : ActiveReadTimes
 39 ! R1  : MaxReadTimes       (constant)
 40 ! S   : DriveStatus
 41 ! S0  : TapeSectorActive
 42 ! S1  : TapeSectorNumbers  (constant)
 43 ! S2  : TapeSectorSize     (constant)
 44 ! S3  : TapeSeekFlag       : tell the drive to do a tape seek if set to 1
 45 ! T1  : TapeTrackNumbers   (constant)
 50 ! B0$ : InputBuffer
 51 ! M$  : DriveErrorLevel

100 OPTION BASE 0                                                                         ! array index start at 0
105 DIM B0$[256]                                                                          ! input buffer creation
110 IMAGE #,256A                                                                          ! input format
115 A=1 @ R1=3 @ T1=2 @ S1=256 @ S2=256                                                   ! app constants
120 S=0 @ B=0 @ E=0 @ C=0 @ L=0 @ M$=""                                                   ! init values
125 B0$="" @ L0=0 @ D=0 @ L2=0 @ R0=0                                                     ! init values
130 SFLAG -1 @ PURGE TD @ PURGE TE @ CFLAG -1                                             ! delete old files, disregard error if files are missing
135 CREATE TEXT TD @ CREATE TEXT TE                                                       ! create TapeDump and TapeError files
140 ASSIGN #1 TO TD @ ASSIGN #2 TO TE                                                     ! open TapeDump and TapeError files
145 SFLAG -23                                                                             ! use variable size as tape read length
150 DELAY 0,0                                                                             ! set display and scrolling delays
155 RESET HPIL @ RESTORE IO                                                               ! reset loop
160 GOSUB 'AIDCHECK'                                                                      ! verify that we have a tape drive at specified loop address
165 GOSUB 'REWIND'                                                                        ! rewind tape
170 S3=1                                                                                  ! seek tape to track 0 sector 0
175 FOR T0=0 TO T1-1                                                                      ! track outer loop
180   FOR S0=0 TO S1-1                                                                    !   sector inner loop
185     GOSUB 'READSEC'                                                                   !     read sector from tape
190   NEXT S0                                                                             !   sector inner loop end
195 NEXT T0                                                                               ! track outer loop end
200 GOSUB 'REWIND'                                                                        ! rewind tape
205 ASSIGN #1 TO * @ ASSIGN #2 TO *                                                       ! close files
210 CFLAG -23 @ DELAY 1,1/8                                                               ! restore environment
215 DISP "DUMP DONE"                                                                      ! warn
220 END                                                                                   ! end of program

500 ! device accessory id check                                                           !
505 'AIDCHECK': ! IN: A / UPD: D / OUT: -                                                 ! sub check device type at loop address
510 ! D=DEVAID(A) @ IF D DIV 16#1 THEN DISP "Err: Invalid Device" @ STOP                  !   get accessory id and if device type is a mass storage then stop the program
515   D=DEVAID(A) @ IF D#16       THEN DISP "Err: Invalid Device" @ STOP                  !   get accessory id and if device is not a 82161A then stop the program
520 RETURN                                                                                ! end sub

525 ! loop until drive is ready                                                           !
530 'BUSYWAIT': ! IN: A / UPD: S / OUT: -                                                 ! sub wait until drive is ready
535   'BW': S=SPOLL(A) @ IF BIT(S,5)=1 THEN GOTO 'BW'                                     !   loop until drive is no longer busy
540 RETURN                                                                                ! end sub

545 ! reset drive status variables                                                        !
550 'RSETSTAT': ! IN: A / UPD: S,B,E,C,L / OUT: -                                         ! sub reset status variables
555   S=0 @ B=0 @ E=0 @ C=0 @ L=0                                                         !   set drive status related variables to 0
560 RETURN                                                                                ! end sub

565 ! read & decode drive status byte                                                     !
570 'READSTAT': ! IN: A / UPD: - / OUT: S,B,E,C,L                                         ! sub read and decode drive status
575   S=SPOLL(A) @ B=BIT(S,5) @ E=BIT(S,4) @ C=BINAND(S,15)                               !   read drive status and get busy flag, error flag and error code
580   IF E=0 AND B=0 THEN L=0 @ RETURN                                                    !   if drive not in error and not busy -> set error level to normal  and return
585   IF E=0 AND B=1 THEN L=1 @ RETURN                                                    !   if drive not in error but is busy  -> set error level to warning and return
590   IF C=9 OR C=10 THEN L=1 ELSE L=2                                                    !   if drive error is recoverable      -> set error level to warning otherwise set error level to
595 RETURN                                                                                ! end sub

600 ! build status message                                                                !
605 'BUILDMSG': ! IN: B,E,C,L / UPD: - / OUT: M$                                          ! sub build drive status message
610   IF E=0 AND B=0 THEN M$=""             @ RETURN                                      !   drive is normal, return
615   IF E=0 AND B=1 THEN M$="Drive Busy"   @ GOTO 'BM'                                   !   drive is busy
620   IF C=9         THEN M$="Rec Number"   @ GOTO 'BM'                                   !   unexpected record number, tape read failed, try to re-read the sector
625   IF C=10        THEN M$="Rec Checksum" @ GOTO 'BM'                                   !   invalid record checksum, tape read failed, try to re-read the sector
630   IF C=7         THEN M$="New Tape"     @ GOTO 'BM'                                   !   new tape has been inserted in the drive and need to be seeked
635   IF C=4         THEN M$="No Tape"      @ GOTO 'BM'                                   !   there is no tape in drive
640   IF C=8         THEN M$="Time Out"     @ GOTO 'BM'                                   !   no data record has been found on the tape
645   IF C=3         THEN M$="Tape:EOT+TS"  @ GOTO 'BM'                                   !   unexpected end of tape has been reached AND tape has stalled
650   IF C=1         THEN M$="End of Tape"  @ GOTO 'BM'                                   !   unexpected end of tape has been reached
655   IF C=2         THEN M$="Tape Stalled" @ GOTO 'BM'                                   !   tape has stalled
660   IF C=5 OR C=6  THEN M$="Device"       @ GOTO 'BM'                                   !   generic device error
665   IF C=12        THEN M$="Tape Size"    @ GOTO 'BM'                                   !   track number greather than 1 has been requested
670                       M$="Unknown"                                                    !   unknown error (covers code=0, 11, 13, 14 & 15)
675   'BM': ! build message                                                               !   build message
680   IF L=1 THEN M$="Wrn:"&STR$(C)&":"&M$                                                !   warning message
685   IF L=2 THEN M$="Err:"&STR$(C)&":"&M$                                                !   error message
690 RETURN                                                                                ! end sub

695 ! verify that drive is ready and not in error                                         !
700 'PRECHECK': ! IN: A / UPD: S,B,E,C,L,M$ / OUT: -                                      ! sub pre-check before doing a drive operation
705   GOSUB 'BUSYWAIT' @ GOSUB 'READSTAT' @ M$=""                                         !   wait for drive to be ready, then read current status and decode it
710   IF L=2 THEN GOSUB 'BUILDMSG' @ DISP M$ @ STOP                                       !   if error level is error then display error message then stop the program
715 RETURN                                                                                ! end sub

720 ! rewind drive tape                                                                   !
725 'REWIND': ! IN: A / UPD: S,B,E,C,L,M$ / OUT: -                                        ! sub rewind tape
730   GOSUB 'PRECHECK'                                                                    !   pre-check drive for readyness
735   DISP "Rewinding Tape ..."                                                           !   tell user the action to be taken
740   SEND UNT UNL LISTEN A DDL 7                                                         !   rewind tape
745   GOSUB 'BUSYWAIT'                                                                    !   wait for drive to be ready
750 RETURN                                                                                ! end sub

755 ! position drive head to the specified track & sector                                 !
760 'SEEK': ! IN: A,T0,S0 / UPD: S,B,E,C,L,M$ / OUT: -                                    ! sub seek track:record
765   GOSUB 'PRECHECK'                                                                    !   pre-check drive for readyness
770   DISP "Seek: T="&STR$(T0)&" S="&STR$(S0)                                             !   tell user the action to be taken
775   SEND UNT UNL MTA LISTEN A DDL 4 DATA T0 DATA S0                                     !   seek tape and wait for drive to be ready
780   GOSUB 'BUSYWAIT'                                                                    !   wait for drive to be ready
785 RETURN                                                                                ! end sub

790 ! Set Drive in Read Mode - Drive Fill Buffer 0 with Current Sector                    !
795 'READMODE': ! IN: A / UPD: - / OUT: -                                                 ! sub activate data transfert mode
800   DISP "Read mode activated"                                                          !   tell user the action to be taken
805   SEND UNT UNL TALK A DDT 2                                                           !   drive set in read mode, trigger the drive to fill buffer 0 with current sector
810 RETURN                                                                                ! end sub

815 ! Read Sector                                                                         !
820 'READSEC': ! IN: A,R1,T0,S0,S2,S3,#1,#2 / UPD: R0,S,B,E,C,L,M$,B0$,L0,S3 / OUT: -     ! sub read sector
825   FOR R0=1 TO R1                                                                      !   read times loop
830     IF S3=1 THEN GOSUB 'SEEK' @ GOSUB 'READMODE' @ S3=0                               !     activate data transfer from tape drive
835     DISP "Read T:"&STR$(T0)&" S:"&STR$(S0)&" #"&STR$(R0)                              !     tell user the action to be taken
840     ENTER :A USING 110;B0$ @ L0=LEN(B0$)                                              !     get drive buffer 0, trigger the drive to fill buffer 0 with next sector
845     GOSUB 'BUSYWAIT' @ GOSUB 'READSTAT'                                               !     wait for drive to be ready & get drive status
850     IF L=0 AND L0=S2 THEN PRINT #1;B0$ @ RETURN                                       !     if no error and record length is valid then save record and return
855     IF L=0 THEN DISP "Wrn: Inv.Rec.Length" @ PRINT #2;B0$ @ BEEP 440,1 @ RETURN       !     if no error and record length is invalid then log data and return
860     IF L=1 THEN GOSUB 'BUILDMSG' @ DISP M$ @ BEEP 523,1 @ S3=1                        !     there was an problem reading the tape, warn user
865     IF L=2 THEN GOSUB 'BUILDMSG' @ DISP M$ @ STOP                                     !     if error level is error then display error message then stop the program
870   NEXT R0                                                                             !   end loop
875   PRINT #2;":T="&DTH$(T0)[5]&":S="&DTH$(S0)[4,5]&":E="&DTH$(S)[5]&":"                 !   too many retry, log error (ex.: ":T=1:S=A8:E=A:")
880   DISP "Wrn: Skipped Bad Rec." @ BEEP 440,1 @ S3=1                                    !   warn user, next record will be seeked
885 RETURN                                                                                ! end sub
Quelques commentaires ...
  • La sous-routine 'AIDCHECK' vérifie si le périphérique sélectionné est bien une unité de stockage.
  • La sous-routine 'BUSYWAIT' attend que l'unité de stockage soit prête à accepter une commande HP-IL.
    La fonction SPOLL du HP-71B utilise la commande HP-IL Send Status (SST) pour récupérer le statut du lecteur.

    Code : Tout sélectionner

    HP-82161A Status Byte Definition
    ---------------------------------
     0  00000000  Idle Condition
    ..
    15  00001111  Idle Condition
    16  00010000  Not Used
    17  00010001  End Of Tape Error
    18  00010010  Stall Error
    19  00010011  End/Stall Error
    20  00010100  No Tape Error
    21  00010101  Device Error
    22  00010110  Device Error
    23  00010111  New Tape Error
    24  00011000  Timeout Error
    25  00011001  Record Number Error
    26  00011010  Checksum Error
    27  00011011  Not Used
    28  00011100  Size Error
    29  00011101  Not Used
    30  00011110  Not Used
    31  00011111  Not Used
    32  001xxxx   Busy Condition
    ..
    63  001xxxx   Busy Condition
    
  • La sous-routine 'RSETSTAT' remet les variables reliées au statut à 0
  • La sous-routine 'READSTAT' retourne un niveau d'erreur (0=normal, 1=busy ou en erreur mais gérable & 2=erreur fatal)
  • La sous-routine 'BUILDMSG' crée un message d'erreur à partir du résultat du statut (SST)
  • La sous-routine 'PRECHECK' vérifie que le lecteur est fonctionnel
  • La sous-routine 'REWIND' rembobine la cassette
  • La sous-routine 'SEEK' positionne la cassette à un endroit spécifique (piste et secteur)
  • La sous-routine 'READMODE' met le lecteur en mode lecture et remplis son buffer de transmission avec le secteur sélectionné
  • La sous-routine 'READSEC' lecture du secteur courant (le lecteur transmet son buffer de transmission, puis il remplis son buffer de transmission avec le secteur suivant)
Sylvain
Sylvain
Calculatrices et Pockets HP > J'ai tous les modèles, manuels, accessoires et périphériques, mes préférés: 41, 71 & 75.
Techno : 41 > 41CL, MLDL2K, Clonix-d, NoV-64d, MAXX | 71 > FRAM71, MultiMod | IL > PIL-Box, PIL-IO, GPIO | ...
Avatar du membre
Marge
Fonctionne à 14400 bauds
Fonctionne à 14400 bauds
Messages : 6172
Enregistré le : 01 oct. 2008 14:39
Localisation : En bas, tout au fond à gauche.

Re: HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Message par Marge »

C’est très impressionnant, félicitations ! Il faut avoir de sacrées connaissances pour sortir un tel programme...
Je me demande cependant comment ton ami a pu formater une cassette numérique de type HP dans un autre standard. Qu’a-t-il utilisé ?
3 hommes, 3 demis, un 3a... Magnéto, Serge !

Quelques-uns de mes petits programmes pour machines Hewlett-Packard :
15C : Knight's Tour ;
29C : (k-)Permutations, Combinations, Linear Regression and Pseudo-random number ;
34C : Hanoi Towers - Automatic & Manual resolutions ;
67
__: A L I E N .

« Boris », c'était juste Maurice enrhumé.
Avatar du membre
pcscote
Fonctionne à 300 bauds
Fonctionne à 300 bauds
Messages : 160
Enregistré le : 11 juil. 2018 01:06
Localisation : Québec/Canada

Re: HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Message par pcscote »

Marge a écrit : 27 janv. 2022 02:48 C’est très impressionnant, félicitations ! Il faut avoir de sacrées connaissances pour sortir un tel programme...
Dans les 40 dernières années, j'ai souvent écrit des programmes qui utilisaient HP-IB (ou HP-IL) pour contrôler des équipements électroniques.
Marge a écrit : 27 janv. 2022 02:48 Je me demande cependant comment ton ami a pu formater une cassette numérique de type HP dans un autre standard. Qu’a-t-il utilisé ?
Sous toute réserve, il est possible que HP ait utilisé un OEM pour la partie interface cassette.
Le produit final par contre, est spécifique à HP (Formatage LIF, interface HP-IL, etc.).
Si le scénario OEM s'avère exact, il serait alors possible qu'un autre manufacturier ait utilisé le même OEM mais avec un formatage de haut niveau différent.

Cassette digitale → HP 82176A est identique à Verbatim MI-80, les deux fonctionnent dans le lecteur 82161A.
Formatage de bas niveau → 2 pistes, 256 secteurs par piste et 256 octets par secteur → 128 KiB
Formatage de haut niveau → LIF pour HP et un autre format pour un manufacturier différent.

Sylvain
Sylvain
Calculatrices et Pockets HP > J'ai tous les modèles, manuels, accessoires et périphériques, mes préférés: 41, 71 & 75.
Techno : 41 > 41CL, MLDL2K, Clonix-d, NoV-64d, MAXX | 71 > FRAM71, MultiMod | IL > PIL-Box, PIL-IO, GPIO | ...
Avatar du membre
Hobiecat
Fonctionne à 9600 bauds
Fonctionne à 9600 bauds
Messages : 3626
Enregistré le : 06 sept. 2011 14:57
Localisation : Normandie

Re: HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Message par Hobiecat »

Je partage l'avis de Marge, c'est du beau travail ! 8O

Bravo Sylvain !

J'avoue humblement qu'avec la PILBox, mon lecteur de cassette ne sert plus beaucoup, même si ça reste amusant de le mettre dans la boucle. :wink:
Avatar du membre
Danny
Fonctionne à 2400 bauds
Fonctionne à 2400 bauds
Messages : 1248
Enregistré le : 28 déc. 2013 16:34

Re: HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Message par Danny »

Amazing !

J'ai pas essayé de comprendre le programme d'extraction, du coup ma question est peut-être bête : est-ce que ton programme est générique pour extraire n'importe quelles données d'une cassette dont on ne connaît pas le format (donc à analyser après), ou est-ce qu'il est adapté spécialement au cas de la cassette dont on parle ? (et si oui, comment t'avais fait au préalable pour connaître ce format ?) :geek:
? Apple, Atari, Canon, Casio, ????????????, HP, Psion, Sharp, Tandy... même TI.
Avatar du membre
pcscote
Fonctionne à 300 bauds
Fonctionne à 300 bauds
Messages : 160
Enregistré le : 11 juil. 2018 01:06
Localisation : Québec/Canada

Re: HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Message par pcscote »

Danny a écrit : 27 janv. 2022 15:35 J'ai pas essayé de comprendre le programme d'extraction, du coup ma question est peut-être bête : est-ce que ton programme est générique pour extraire n'importe quelles données d'une cassette dont on ne connaît pas le format (donc à analyser après), ou est-ce qu'il est adapté spécialement au cas de la cassette dont on parle ? (et si oui, comment t'avais fait au préalable pour connaître ce format ?) :geek:
Euh!
Le programme ...
  1. est spécifique au lecteur 82161A
  2. est bâti pour qu'il soit très facile de l'adapter à une autre unité de stockage de masse. (ex.: HP 9114A/B)
  3. nécessite une cassette compatible à ce lecteur (HP 82176A ou Verbatim MI-80)
  4. nécessite que la cassette ait été préalablement formatée à bas niveau (low level format → tracks, sectors, bytes/sector)
  5. fait abstraction du formatage de haut niveau (high level format, ex.: LIF, FAT, etc)
  6. dépend de la RAM disponible du HP-71B
  7. effectue un "dump" du contenu de la cassette
Par manque de temps, j'ai pris un raccourci en transférant le contenu de la cassette vers la RAM du HP-71B.
Une amélioration serait de modifier ce comportement et de copier le contenu vers un autre périphérique de stockage.
Par contre, la complexité augmente de beaucoup si la lecture/écriture s'effectue sur la même boucle HP-IL,
mais est grandement simplifié si l'adaptateur Dual-HP-IL est utilisé. (boucle #1 → lecture, boucle #2 → écriture)

Sylvain
Sylvain
Calculatrices et Pockets HP > J'ai tous les modèles, manuels, accessoires et périphériques, mes préférés: 41, 71 & 75.
Techno : 41 > 41CL, MLDL2K, Clonix-d, NoV-64d, MAXX | 71 > FRAM71, MultiMod | IL > PIL-Box, PIL-IO, GPIO | ...
Avatar du membre
Danny
Fonctionne à 2400 bauds
Fonctionne à 2400 bauds
Messages : 1248
Enregistré le : 28 déc. 2013 16:34

Re: HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Message par Danny »

Ok, oui j'avais compris que le programme est spécifique au lecteur 82161A, mais ce que je voulais dire c'est est-ce que ton programme fait seulement une copie des données brutes, ou il les décode aussi dans un format lisible ? (apparemment non, si je comprends bien)

Sinon, intéressant le coup de la double boucle :geek:
? Apple, Atari, Canon, Casio, ????????????, HP, Psion, Sharp, Tandy... même TI.
Avatar du membre
pcscote
Fonctionne à 300 bauds
Fonctionne à 300 bauds
Messages : 160
Enregistré le : 11 juil. 2018 01:06
Localisation : Québec/Canada

Re: HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Message par pcscote »

Danny a écrit : 27 janv. 2022 17:36 mais ce que je voulais dire c'est est-ce que ton programme fait seulement une copie des données brutes, ou il les décode aussi dans un format lisible ? (apparemment non, si je comprends bien)
Tu as très bien compris. :wink:
Danny a écrit : 27 janv. 2022 17:36 Sinon, intéressant le coup de la double boucle :geek:
Faut bien que ça serve à quelque chose ces petits jouets. :geek:
Sylvain
Calculatrices et Pockets HP > J'ai tous les modèles, manuels, accessoires et périphériques, mes préférés: 41, 71 & 75.
Techno : 41 > 41CL, MLDL2K, Clonix-d, NoV-64d, MAXX | 71 > FRAM71, MultiMod | IL > PIL-Box, PIL-IO, GPIO | ...
Avatar du membre
Danny
Fonctionne à 2400 bauds
Fonctionne à 2400 bauds
Messages : 1248
Enregistré le : 28 déc. 2013 16:34

Re: HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Message par Danny »

Okay :)
Et tu sais si Mark Power a su comment décoder tout ça ensuite ?
? Apple, Atari, Canon, Casio, ????????????, HP, Psion, Sharp, Tandy... même TI.
Avatar du membre
pcscote
Fonctionne à 300 bauds
Fonctionne à 300 bauds
Messages : 160
Enregistré le : 11 juil. 2018 01:06
Localisation : Québec/Canada

Re: HP-IL: Contrôle du lecteur de cassette numérique (82161A)

Message par pcscote »

Danny a écrit : 27 janv. 2022 19:27 Okay :)
Et tu sais si Mark Power a su comment décoder tout ça ensuite ?
Je ne sais pas, Mark a servi d'intermédiaire entre moi et le propriétaire de la cassette.
Sylvain
Calculatrices et Pockets HP > J'ai tous les modèles, manuels, accessoires et périphériques, mes préférés: 41, 71 & 75.
Techno : 41 > 41CL, MLDL2K, Clonix-d, NoV-64d, MAXX | 71 > FRAM71, MultiMod | IL > PIL-Box, PIL-IO, GPIO | ...
Répondre

Retourner vers « Tous les Pockets »