![]() |
Elektronika MK-161
![]() ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() Une calculatrice fabriquée en Russie fonctionnant en RPN et programmable! |
Superbe évolution des modèles MK-61/52 avec:
|
MK-Compiler | Emulateur | Les menus | Programmation étendue | Module USOMK-4 | Disque UZVMK-1 | Vitesse/Précision | Interface graphique |
J'ai écrit le MK-Compiler qui permet de préparer les programmes sur un PC en utilisant un langage de haut niveau
puis de les envoyer via RS-232 vers la calculatrice. Le programme gère:
|
![]() L'écran principal du compilateur |
![]()
|
![]() |
![]() |
![]() |
Puis vous envoyez le programme vers la calculatrice... Ci-contre, l'envoi d'un programme ayant également des données en zone binaire. |
![]() |
Et vous pouvez récupérer l'écran principal ou graphique. Ci-contre, la réception de l'écran principal. |
![]() |
Un exemple: Calcul de PI
; un seul registre nécessaire #REG 0 N DO ; affiche la question sur la ligne commentaire #NUM ask EXEC \CPrintStringB ; attend la valeur INPUT ; stockée dans N STO N ; prépare l'affichage du résultat #NUM result EXEC \CPrintStringB ; la somme commence à 0 CX ; fait la somme des 1/n²=PI²/6 FOR N @N X^2 1/X + NEXT ; corrige pour trouver PI 6 * SQR ; s'arrête pour l'affichage STOP LOOP ; Zone binaire pour les données texte #BINARY ; TEXTN ajoute un caractère 0A (new line) au début et ; un cractère nul à la fin. ; newline indispensable pour effacer la ligne commentaire ask: #TEXTN "How many loops?" result: #TEXTN "Pi approximation" |
Listing compilé
PROGAM ZONE Step | Code | Keys ------------------------- 0000 | 01 | 1 0001 | 00 | 0 0002 | 00 | 0 0003 | 00 | 0 0004 | F4 | PP M 0005 | 90 | 9 0 0006 | 27 | 2 7 0007 | 50 | R/S 0008 | 40 | M 0 0009 | 01 | 1 0010 | 00 | 0 0011 | 01 | 1 0012 | 07 | 7 0013 | F4 | PP M 0014 | 90 | 9 0 0015 | 27 | 2 7 0016 | 0D | CX 0017 | 60 | RM 0 0018 | 22 | F X^2 0019 | 23 | F 1/X 0020 | 10 | + 0021 | 5D | F L0 0022 | 17 | 1 7 0023 | 06 | 6 0024 | 12 | * 0025 | 21 | F SQRT 0026 | 50 | R/S 0027 | 51 | GOTO 0028 | 00 | 0 0 |
BINARY ZONE Step | Code | Comment ------------------------- 1000 | 0A | newline 1001 | 48 | "H" 1002 | 6F | "o" 1003 | 77 | "w" 1004 | 20 | " " 1005 | 6D | "m" 1006 | 61 | "a" 1007 | 6E | "n" 1008 | 79 | "y" 1009 | 20 | " " 1010 | 6C | "l" 1011 | 6F | "o" 1012 | 6F | "o" 1013 | 70 | "p" 1014 | 73 | "s" 1015 | 3F | "?" 1016 | 00 | nul 1017 | 0A | newline 1018 | 50 | "P" 1019 | 69 | "i" 1020 | 20 | " " 1021 | 61 | "a" 1022 | 70 | "p" 1023 | 70 | "p" 1024 | 72 | "r" 1025 | 6F | "o" 1026 | 78 | "x" 1027 | 69 | "i" 1028 | 6D | "m" 1029 | 61 | "a" 1030 | 74 | "t" 1031 | 69 | "i" 1032 | 6F | "o" 1033 | 6E | "n" 1034 | 00 | nul ------------------------- Addr | Name ------------------------- B 1000 | ASK B 1017 | RESULT ------------------------- Reg | Name ------------------------- 0 | N 9027 | \CPRINTSTRINGB ------------------------- -- END OF FILE -- |
On remet le compteur programme à 0000 avec B/O, puis on lance l'exécution avec R/S. On obtient l'écran suivant: ![]() J'ai essayé 500 itérations (on tape 500 puis R/S), voici l'approximation de PI obtenue: ![]() On peut alors rappuyer sur R/S pour entrer une nouvelle valeur. J'ai essayé avec 10000: ![]() |
![]() L'émulateur exécutant mon programme PI Monte Carlo |
Ajoutez simplement la ligne:
#MKFiles 2dans votre programme source et le compilateur génèrera les trois types de fichiers selon ce qu'utilise votre programme:
Lancez l'émulateur et, avec un clic droit, faites appraître ce pop-up: ![]() Sélectionnez la ligne indiquée pour accéder au chargement des fichiers. ![]() ![]() |
Depuis sa version 1.04, MK-Compiler peut appeler directement l'émulateur en lui transmettant tous les fichiers créés.
![]() |
Tout d'abord, voici les touches importantes lors de la navigation dans les menus. Certaines touches ont plusieurs fonctions selon le contexte. Accès au menu par la touche OUTPUT |
![]() |
Touches à utiliser au clavier:
|
Les fonctions disponibles sont très nombreuses et couvrent, entre autres, les domaines suivants:
|
Ca peut être utile, les codes des touches!
Note : le code 26 n'est pas renvoyé car il met fin au programme. Les touches On et Luminosité ne renvoient pas de codes. |
Utilise #FONT/#DEFCHAR pour redéfinir des caractères.![]() |
Utilise #FINDFILE/#CREATEFILE/#LOADFILE pour gérer les fichiers et dossiers.![]() |
Utilise une interruption pour jouer une musique pendant une animation graphique.![]() |
Utilise #DEFGRAPH pour définir et afficher des formes (exemple ci-dessous)![]() |
Ce programme attend une valeur 0, 1 ou 2 sur la pile et affiche au hasard 20 fois le motif choisi sur l'écran graphique. On a le choix entre 0=étoile, 1=carré et 2=cercle. A la fin le programme attend une touche, ensuite on peut rentrer une nouvelle valeur et R/S relance le programme. ; registres utiles #reg 0 Index #reg e ObjectAddress DO ; calcule l'adresse de l'objet ; en mémoire BINAIRE selon une table ENTER #NUM Table + PRGM $1000 + STO ObjectAddress ; efface l'écran 0 EXEC \CLS ; pour 20 boucles $20 STO Index FOR Index ; coordonnées calculées au hasard $56 RND * $120 RND * SET \x0y0 ; puis on dessin l'objet @ObjectAddress EXEC \PUTGB NEXT ; affiche l'écran graphique GRPH ; attend une touche REPEAT GET \NEXTKEY NOT UNTIL(x<>0) ; attend une nouvelle valeur INPUT LOOP ; table des 3 adresses Table: #DAL star square circle #END |
; bascule en mémoire BINAIRE #BINARY star: #DEFGRAPH *..*..* .*.*.*. ..***.. ******* ..***.. .*.*.*. *..*..* #END square: #DEFGRAPH ******* *.....* *.....* *.....* *.....* *.....* *.....* ******* #END circle: #DEFGRAPH ..***.. .*...*. *.....* *.....* *.....* *.....* .*...*. ..***.. #END |
![]() Les 20 étoiles, valeur 0. ![]() Les 20 carrés, valeur 1. ![]() Les 20 cercles, valeur 2. |
Et voici le listing résultant:
PROGAM ZONE Step | Code | Keys ------------------------- 0000 | 0E | ENT 0001 | 00 | 0 0002 | 00 | 0 0003 | 04 | 4 0004 | 08 | 8 0005 | 10 | + 0006 | 28 | K PRGM 0007 | 01 | 1 0008 | 00 | 0 0009 | 00 | 0 0010 | 00 | 0 0011 | 10 | + 0012 | 4E | M e 0013 | 00 | 0 0014 | F4 | PP M 0015 | 90 | 9 0 0016 | 10 | 1 0 0017 | 02 | 2 0018 | 00 | 0 0019 | 40 | M 0 0020 | 05 | 5 0021 | 06 | 6 0022 | 3B | K RAN 0023 | 12 | * 0024 | 01 | 1 0025 | 02 | 2 0026 | 00 | 0 0027 | 3B | K RAN 0028 | 12 | * 0029 | F4 | PP M 0030 | 90 | 9 0 0031 | 00 | 0 0 0032 | 6E | RM e 0033 | F4 | PP M 0034 | 90 | 9 0 0035 | 16 | 1 6 0036 | 5D | F L0 0037 | 20 | 2 0 0038 | 56 | K GRPH 0039 | F6 | PP RM 0040 | 90 | 9 0 0041 | 29 | 2 9 0042 | 3A | K NOT 0043 | 57 | F X!=0 0044 | 39 | 3 9 0045 | 50 | R/S 0046 | 51 | GOTO 0047 | 00 | 0 0 0048 | 00 | AL(0) 0049 | 09 | AL(9) 0050 | 12 | AL(18) |
BINARY ZONE Step | Code | Comment ------------------------- 1000 | 07 | Width 1001 | 07 | Height 1002 | 49 | byte 1003 | 2A | byte 1004 | 1C | byte 1005 | 7F | byte 1006 | 1C | byte 1007 | 2A | byte 1008 | 49 | byte 1009 | 07 | Width 1010 | 08 | Height 1011 | FF | byte 1012 | 81 | byte 1013 | 81 | byte 1014 | 81 | byte 1015 | 81 | byte 1016 | 81 | byte 1017 | FF | byte 1018 | 07 | Width 1019 | 08 | Height 1020 | 3C | byte 1021 | 42 | byte 1022 | 81 | byte 1023 | 81 | byte 1024 | 81 | byte 1025 | 42 | byte 1026 | 3C | byte ------------------------- Addr | Name ------------------------- 0048 | TABLE B 1000 | STAR B 1009 | SQUARE B 1018 | CIRCLE ------------------------- Reg | Name ------------------------- 0 | INDEX e | OBJECTADDRESS 9000 | \X0Y0 9010 | \CLS 9016 | \PUTGB 9029 | \NEXTKEY ------------------------- -- END OF FILE -- |
Ce module permet d'ouvrir ou fermer deux relais et de tester l'ouverture ou la fermeture d'un circuit.
| ![]() |
Voici les valeurs possibles:
|
![]() Imaginons qu'une porte soit reliée au canal C qui surveille si elle est ouverte ou fermée. En cas d'ouverture, on enclanche une alarme reliée au canal A jusqu'à ce que la porte soit fermée. Le programme boucle indéfiniment. ; port parallèle 1 SET \IOmode DO ; attend l'ouverture du canal C REPEAT GET \IOModule 8 AND UNTIL(x<>0) ; dès l'ouverture on allume l'alarme ; sur le canal A 5 SET \IOModule ; attend la fermeture du canal C REPEAT GET \IOModule 8 AND UNTIL(x=0) ; lorsque c'est à nouveau fermé ; on éteint l'alarme du canal A 7 SET \IOModule LOOP |
Voici le listing résultant:
PROGAM ZONE Step | Code | Keys ------------------------- 0000 | 01 | 1 0001 | F4 | PP M 0002 | 90 | 9 0 0003 | 90 | 9 0 0004 | F6 | PP RM 0005 | 90 | 9 0 0006 | 92 | 9 2 0007 | 08 | 8 0008 | 37 | K AND 0009 | 57 | F X!=0 0010 | 04 | 0 4 0011 | 05 | 5 0012 | F4 | PP M 0013 | 90 | 9 0 0014 | 92 | 9 2 0015 | F6 | PP RM 0016 | 90 | 9 0 0017 | 92 | 9 2 0018 | 08 | 8 0019 | 37 | K AND 0020 | 5E | F X=0 0021 | 15 | 1 5 0022 | 07 | 7 0023 | F4 | PP M 0024 | 90 | 9 0 0025 | 92 | 9 2 0026 | 51 | GOTO 0027 | 04 | 0 4 ------------------------- Reg | Name ------------------------- 9090 | \IOMODE 9092 | \IOMODULE ------------------------- -- END OF FILE -- |
![]() |
Le disque contient 2048 blocs de 264 octets, certainement que les 8 octets supplémentaires sont utilisés à des fins de gestion et que seuls 256 sont réellement destinés aux données. Donc 256×2048=512×1024=512ko. |
![]() |
Tests de précision | Tests de vitesse | |||
Forensic Test de précision sur les fonctions scientifiques, on calcule arcsin(arccos(arctan(tan(cos(sin(9))))))en degrés. Résultat: 8,9999999772404. L'idéal serait 9 ! |
Hebdogiciel20 =0 =1 2 FOR 0 SQR NEXT FOR 1 X^2 NEXT STOPRésultat: 1,9999999837026 L'idéal serait 2 ! |
Boucle simple:
0000 + 0001 GOTO 00En partant de la pile 1 1 1 0 durant 60 secondes donne une somme de 95756. Soit à peu près 800 fois plus rapide que la MK-61... |
Calcul de PI
Selon le programme donné sur cette page, pour:
|
Utilise les "RadioButtons", menus multiples, SELECT/ENDSELECT![]() |
Utilise les lignes qu'on peut marquer.![]() |
Utilise la barre de progression, menus multiples, boucle FOR/NEXT, calcul de temps, son.![]() |
Utilise un menu graphique composé de blocks dans une icone.![]() |
#MKFiles 2 ;-------------------- ; Définition des registres ;-------------------- #reg a GrainNum ; combien de centaines de grains #reg b PiValue ; approximation de PI obtenue (pour l'affichage) #reg c Total ; accumulateur des grains lancés #reg d InsideCircle ; accumulateur des grains à l'intérieur du cercle #reg e Duration ; durée du calcul en HH.MMSS (pour l'affichage) #reg 7 Address ; adresse du sous programme selon l'élement actif du menu #reg 0 Hundred ; pour les boucles #reg 1 Iter ; idem #reg 6 progress ; valeur de 9 à 116 pour la barre de progression #reg 5 done ; flag pour le second menu #reg 4 limit ; pour limiter le nombre de grains |
Si on jette un grain de sable au hasard sur un carré, ![]() la probabilité qu'il tombe dans le quart de cercle est égale à: ![]() On peut donc simuler les lancés de grains et obtenir une approximation de PI ! |
;-------------------- ; Description du Menu Principal ;-------------------- #MENU ; c'est le menu 0 #STRING 1 "PI MonteCarlo" ; Le titre en grande fonte #HLINE ; separateur #VINPUTD "Hundreds grains :" 92 GrainNum verif ; une ligne "input" pour fixer le nombre de centaines de grains ; et une routine de vérification pour valider l'entrée #ACTION "Run !" Calculation ; une ligne "action" (executera Calculation) #OUTPUTD 0 "PI =" 32 PiValue ; une ligne "output" affichant la valeur du registre PiValue #OUTPUTF 0 "Time :" 50 Duration 2 4 ; une ligne "output" formatée affichant le temps #HLINE ; separateur #ACTION "Exit !" ProgramEnd ; une ligne "action" (executera ProgramEnd) #ENDMENU |
Voici à quoi il ressemblera: ![]() Cliquez sur
|
;-------------------- ; Description du Sous Menu ;-------------------- #MENU ; c'est le menu 1 #STRING 1 "Calculating..." ; un gros titre #BLANK 10 ; saute des lignes #STARTRECT ; un rectangle pour encadrer... #PROGRESSBAR progress ; ... la barre de progression basée sur le registre "progress" #ENDRECT ; ferme le rectangle #BLANK 10 ; saute des lignes #?LINK "Progress..." 0 Done "Done !" ; Lien avec affichage conditionnel. Affiche "Progress" pendant le calcul ; et "Done !" à la fin (quand le registre done=1) ; c'est un lien vers le menu 0. #ENDMENU |
On peut y voir la barre de progression: ![]() |
![]() Cliquez sur "Done !" pour revenir au menu 0. |
![]() On y lit la valeur de PI et le temps de calcul. |
Ensuite, il s'agit d'une construction courante de programme: on commence par initialiser les variables. Le coeur du programme est entièrement inclus dans "#MENUMAINLOOP" qui contient tout ce que le système demande pour gérer vos deux menus et appeler les sous programmes. Ensuite, il ne vous reste plus qu'à écrire ces sous-programmes qui vont réagir aux actions faites sur l'interface. |
;-------------------- ; Mes initialisations ;-------------------- CX =PiValue =Total =InsideCircle =Duration =done 1 SET GrainNum ; defaut = 1 centaine = 100 grains 9 SET progress ; 9 = 0% dans la barre de progression $1000 SET limit ; pas plus de 1000 centaines ;-------------------- ; La boucle principale se loge ici ;-------------------- #MENUMAINLOOP Address |
ProgramEnd: ; si Exit! est sélectionné, on stoppe. STOP |
est simple: il vérifie qu'on ne dépasse pas la limite et que la valeur n'est ni négative ni nulle. |
verif: @GrainNum ; valeur entrée /-/ IF(X>=0)THEN 1 =GrainNum ; si négatif ou nul, retour à 1 ELSE @limit + IF(x<0)THEN ; si limit<entrée @limit =GrainNum ; retour à la limite ENDIF ENDIF RTN |
;-------------------- ; Mon sous programme ;-------------------- Note: ; sous programme pour un son ENT $20 EXEC \Sound ; Entre la fréquence, 20/100 sec pour durée REPEAT GET \SOUND ; son terminé? UNTIL(x=0) ; si non nul, on attend RTN Calculation: 0 =done ; pour l'affichage conditionnel #GOTOMENU 1 0 ; passe au menu 1, élément actif 0 GET \TIME HMS> =Duration ; conserve l'heure de début @GrainNum =Hundred ; pour la boucle SUM Total ; met à jour l'accumulateur de grains FOR Hundred ; pour chaque centaine de grains 1 ENTER @Hundred @GrainNum / - ; calcule la position de la barre (9-116) $107 * 9 + =progress ; selon la valeur de la boucle #REDRAW ; et affiche la nouvelle barre $100 =Iter ; un paquet de 100 grains FOR Iter RAN X^2 RAN X^2 + 1 - ; compare 1 avec x^2+y^2 au hasard IF(x<0)THEN ; si <1 alors 1 SUM InsideCircle ; 1 dans le second accumulateur ENDIF NEXT NEXT $116 =progress ; barre de progression à 100% 1 =done ; modifie l'affichage conditionnel #REDRAW ; et affiche l'interface @InsideCircle @Total / $25 / =PiValue ; (inside/total) / 100 * 4 = PI GET \TIME HMS> @Duration - >HMS =Duration ; heure-heurdébut = durée $523 Gosub Note ; petite musique pour dire que c'est fini $880 Gosub Note $699 Gosub Note RTN |
Il commence à "Calculation", quelques initialisations sont faites (flag, heure de début, barre de progression, passage au Menu 1). La boucle principale met à jour la barre de progression et lance le calcul pour 100 grains à chause fois. Lorsque tout est fini, PI est calculé, le temps total également, le flag est modifié et on peut entendre trois notes musicales qui indiquent la fin. Il est inutile de forcer le retour au Menu 0, ce sera fait par la boucle principale lors de l'appui sur "Done !" du Menu 1 qui est un lien vers le Menu 0. |