Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » [Bêta] PythonExtra.
Lephenixnoir Hors ligne Administrateur Points: 24248 Défis: 170 Message

[Bêta] PythonExtra.

Posté le 29/10/2022 09:49

PythonExtra est un add-in Python alternatif pour (à ce stade) Graph 35+E II, Prizm et Graph 90+E. L'objectif est de fournir plus de fonctionnalités : modules standard, getkey(), fonctions de dessin plus performantes, etc.

Version Bêta 0.2
Graph 35+E II / Prizm / Graph 90+E : PythonExtra-pe-0.2.0-beta.zip


Aperçu de PythonExtra sur Graph 90+E. (Cliquez pour agrandir)

Description sommaire des fonctionnalités :
  • Compile pour Graph 90+E (fx-CG 10/20/50) et Graph 35+E II (fx-9860G III)
  • Peu de RAM sur Graph 35+E II (c'est difficile d'en trouver sur ce modèle)
  • Un shell pas trop mal (saisie rapide, scrolling) avec de bonnes performances
  • Plein de modules standard
    • array, builtins, cmath, collections, io, math, random, struct, sys, time
  • Le module spécifique CASIO : casioplot (fidèle à part sur les polices)
  • Un nouveau module gint avec les fonctionnalités avancées de gint :
    • Pour l'instant, une bonne partie de <gint/display.h> et <gint/keyboard.h>
    • Donc getkey() (attente de touche) ainsi que keydown() (test instantané) !
    • Et des fonctions de dessin rapides comme dline() ou drect()

Le plan actuel :
  • Être sensiblement compatible avec l'appli Python officielle.
  • Pousser les fonctionnalités ajoutées pour vraiment relever le niveau de Python !
  • Si du temps de développement se débloque : support autres Graph mono (pas de promesses).

Updates et screenshots à venir. Je n'ai pas l'intention d'implémenter un million de fonctionnalités, juste ce qu'il faut pour s'assurer que ça ne finisse pas mal documenté et non maintenu comme CasioPython.

Dépôt Git : https://gitea.planet-casio.com/Lephenixnoir/PythonExtra
PythonExtra est notamment possible grâce à l'aide précieuse de Mb88.

Comparaison directe

Dans l'exemple ci-dessous (réalisé par Mb88), un Flappy Bird déjà bien optimisé (dessin partiel etc, à gauche) est accéléré un bon gros coup en utilisant PythonExtra et le module gint pour le dessin (à droite).


Contexte historique

Aux journées APMEP 2022, redgl0w racontait comment le port MicroPython pour Numworks n'était finalement pas super difficile. Moi je parlais de comment un port maison résoudrait le problème de getkey(), et Critor m'a convaincu d'essayer sur-le-champ.

En fin de compte, j'ai clôné MicroPython Dimanche à midi et à 1 heure du matin j'avais un port fonctionnel avec getkey() sur ma Graph 90+E (que j'ai d'ailleurs montré à CASIO Lundi, pour la démo). Comme quoi, des fois ça marche tout seul !

(Enfin, le début marche tout seul. Faire une bonne UI et gérer tous les détails ensuite c'est une autre paire de manches !)

Fichier joint


Précédente 1, 2, 3 ··· 10, 11, 12, 13, 14, 15, 16 ··· 19, 20, 21 Suivante
Slyvtt Hors ligne Maître du Puzzle Points: 2311 Défis: 17 Message

Citer : Posté le 15/01/2024 10:52 | #


Alors j'ai fait un petit test rapide sur fxCG50 pour laquelle je ne vois pas apparaître le bug malgré beaucoup (mais alors beaucoup) de lancements du script.

Ma procédure de test est la suivante : script dans aaa.py
from utime import *
print (ticks_cpu())
Je lance en boucle le script via FILES (F1) --> selection aaa.py --> EXE
J'ai lancé au moins 50 fois sans voir le crash.

Je testerai cet après-midi sur G35+EII qui dispose de nettement moins de RAM (je l'ai pas sous la main là tout de suite), peut être un pb de ce côté là. Si la procédure de test est pas la même que toi, hésite pas à explicité comment tu arrives au plantage.
There are only 10 types of people in the world: Those who understand binary, and those who don't ...
Lephenixnoir Hors ligne Administrateur Points: 24248 Défis: 170 Message

Citer : Posté le 15/01/2024 10:55 | #


Merci pour l'info Ptitjoz. Décidément y'a des trucs...

Sly hésite pas à regarder la consommation de RAM dans PythonExtra, même sur Graph 90+E. Si c'est lancer le script plusieurs fois d'affilée c'est probablement pas la fonction (qui est ultimement juste un rtc_ticks() avec différents facteurs multiplicatifs) mais probablement plus l'action de réinitialiser MicroPython et lancer le script en boucle. Si la mémoire descend sur Graph 90+E alors on aura probablement une bonne piste.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Slyvtt Hors ligne Maître du Puzzle Points: 2311 Défis: 17 Message

Citer : Posté le 15/01/2024 11:13 | #


Oui, je soupçonne aussi un truc de ce style.
Je vais refaire un build avec PE_DEBUG activé pour avoir la conso RAM affichée.
Je me souviens qu'il y avait un truc sur la libération mémoire des modules importés en fin de run, mais je sais plus si cela avait été réglé ou pas. Faudra que je remonte l'historique.
There are only 10 types of people in the world: Those who understand binary, and those who don't ...
Ptitjoz Hors ligne Membre Points: 225 Défis: 10 Message

Citer : Posté le 15/01/2024 11:15 | #


Bonjour Slyvtt et Lephe

oui je vais sur mon fichier butime.py et EXE puis F1 et EXE
et ça plante à 30 essais (environ) à chaque fois sur ma machine
Un peu poète, un peu geek, un peu rêveur, un peu écolo.

Lephenixnoir Hors ligne Administrateur Points: 24248 Défis: 170 Message

Citer : Posté le 15/01/2024 11:22 | #


SlyVTT a écrit :
Je me souviens qu'il y avait un truc sur la libération mémoire des modules importés en fin de run, mais je sais plus si cela avait été réglé ou pas. Faudra que je remonte l'historique.

Pas exactement. Il y avait une subtilité sur Bad Apple qui avait besoin de supprimer les modules pendant l'exécution et libérer la mémoire associée, mais ça marche pas super bien parce que y'a plus de références aux modules dans PythonExtra que dans l'appli Python officielle, donc même si tu del la globale et l'entrée associée dans sys.modules le GC ne libère quand même pas la mémoire.

Je réinitialise MicroPython entièrement à chaque fois que tu lances un nouveau script donc normalement toute la mémoire de Python doit être libérée. Mais si ça se trouve c'est la mémoire de PythonExtra lui-même avec le shell et les widgets qui elle tombe à court. J'utilise le malloc() de l'OS pour ça et s'il a autant de fragmentation que dans les éditions précédentes il est pas impossible que ce soit un problème. Une intuition que j'aurais c'est essaie d'attraper les appels au malloc() système et de mettre un panic si ça renvoie NULL.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Slyvtt Hors ligne Maître du Puzzle Points: 2311 Défis: 17 Message

Citer : Posté le 15/01/2024 11:22 | #


Ok merci Ptitjoz pour la confirmation. Je vais regarder cela tout à l'heure. Je vous tiens au courant.
There are only 10 types of people in the world: Those who understand binary, and those who don't ...
Slyvtt Hors ligne Maître du Puzzle Points: 2311 Défis: 17 Message

Citer : Posté le 15/01/2024 11:27 | #


Lephenixnoir a écrit :
Je réinitialise MicroPython entièrement à chaque fois que tu lances un nouveau script donc normalement toute la mémoire de Python doit être libérée. Mais si ça se trouve c'est la mémoire de PythonExtra lui-même avec le shell et les widgets qui elle tombe à court. J'utilise le malloc() de l'OS pour ça et s'il a autant de fragmentation que dans les éditions précédentes il est pas impossible que ce soit un problème. Une intuition que j'aurais c'est essaie d'attraper les appels au malloc() système et de mettre un panic si ça renvoie NULL.


Oui et vu qu'on a un crash "rattrapé" par gint c'est effectivement plus à ça que je pensais donc suivre l'evolution de "_uram" et "ostk".
De ce que j'ai vu, si on a pas assez de RAM pour MicroPython, il se passe juste rien (pas de crash), même si "cas individuel ne vaut pas démonstration générale".
There are only 10 types of people in the world: Those who understand binary, and those who don't ...
Ptitjoz Hors ligne Membre Points: 225 Défis: 10 Message

Citer : Posté le 15/01/2024 11:35 | #


Pour info, le script suivant donne le même crash (exécuté une trentaine de fois)
from gint import *
print(DHEIGHT)

Un peu poète, un peu geek, un peu rêveur, un peu écolo.

Lephenixnoir Hors ligne Administrateur Points: 24248 Défis: 170 Message

Citer : Posté le 15/01/2024 11:36 | #


Aha merci, ça confirme donc que ce n'est pas le module time mais bien le chargement le problème.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Slyvtt Hors ligne Maître du Puzzle Points: 2311 Défis: 17 Message

Citer : Posté le 15/01/2024 11:39 | #


Ok si je comprends bien, je mettrais un pe_debug_panic() ici : https://gitea.planet-casio.com/Slyvtt/PythonExtra/src/branch/dev/ports/sh/main.c#L105

Potentiellement ça pourrait être là que ça coince.
There are only 10 types of people in the world: Those who understand binary, and those who don't ...
Lephenixnoir Hors ligne Administrateur Points: 24248 Défis: 170 Message

Citer : Posté le 15/01/2024 11:43 | #


Ce malloc-là est assez innocent, mais il y en a plein ailleurs notamment dans l'implémentation du shell. Le shell est assez intensif dans le sens où si je me souviens bien il realloc() souvent les lignes, ce qui pourrait causer de la fragmentation.

Idéalement je suggère l'approche suivante.
  1. Chercher les malloc() dans tous les fichiers de ports/sh et vérifier que ça arrive bien sur le malloc() système.
  2. Soit remplacer tous les appels par une macro pour pouvoir injecter un if(... == NULL) à chaque appel quand PE_DEBUG est activé, soit modifier gint pour ajouter cette fonctionnalité (de préférence le second).
  3. Pour le second, c'est juste une affaire d'aller dans le dépôt gint dans src/kmalloc/kmalloc.c et d'appeler un callback fourni par l'utilisateur dès que kmalloc(), kmalloc_max() ou krealloc() renvoie NULL. Je peux faire un draft rapidement après manger.

Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Ptitjoz Hors ligne Membre Points: 225 Défis: 10 Message

Citer : Posté le 15/01/2024 11:54 | #


pour info sur l'émulateur je reproduis le crash (casio 35 +EII)
avec la même version de PE
from gint import *
print(DHEIGHT)


Un peu poète, un peu geek, un peu rêveur, un peu écolo.

Slyvtt Hors ligne Maître du Puzzle Points: 2311 Défis: 17 Message

Citer : Posté le 15/01/2024 12:01 | #


Lephenixnoir a écrit :
Ce malloc-là est assez innocent, mais il y en a plein ailleurs notamment dans l'implémentation du shell. Le shell est assez intensif dans le sens où si je me souviens bien il realloc() souvent les lignes, ce qui pourrait causer de la fragmentation.

Idéalement je suggère l'approche suivante.
  1. Chercher les malloc() dans tous les fichiers de ports/sh et vérifier que ça arrive bien sur le malloc() système.
  2. Soit remplacer tous les appels par une macro pour pouvoir injecter un if(... == NULL) à chaque appel quand PE_DEBUG est activé, soit modifier gint pour ajouter cette fonctionnalité (de préférence le second).
  3. Pour le second, c'est juste une affaire d'aller dans le dépôt gint dans src/kmalloc/kmalloc.c et d'appeler un callback fourni par l'utilisateur dès que kmalloc(), kmalloc_max() ou krealloc() renvoie NULL. Je peux faire un draft rapidement après manger.


Effectivement dans la console il y a plein de malloc/realloc.
L'option 1 nous permettra de rapidement voir si c'est là cause, pour du plus long terme (et plus transverse car ça pourrait se produire sur d'autres addins), on peut effectivement mettre en place un callback dans gint si tu as le temps de regarder ça.
There are only 10 types of people in the world: Those who understand binary, and those who don't ...
Slyvtt Hors ligne Maître du Puzzle Points: 2311 Défis: 17 Message

Citer : Posté le 15/01/2024 13:09 | #


Alors si j'essaie de compiler avec PE_DEBUG, l'addin ne se lance pas sur la G35+EII.
En mettant des pe_debug_panic() dans console.c sur les malloc et les realloc.
J'arrive à obtenir une sortie sur panique sur la ligne
char *newdata = realloc(line->data, newsize);
de bool console_line_alloc(console_line_t *line, int n)

Il y a visiblement un truc ici à regarder de plus près.
There are only 10 types of people in the world: Those who understand binary, and those who don't ...
Lephenixnoir Hors ligne Administrateur Points: 24248 Défis: 170 Message

Citer : Posté le 16/01/2024 21:07 | #


Info, pendant qu'on gère ça (qui s'avère être le manque de mémoire, comme d'hab...) j'ai ajouté le support de l'extinction. Donc Shift+AC/ON éteint la calculatrice, ça marche quand on est dans l'add-in et ça marche aussi si on le fait dans le menu pendant que l'add-in tourne.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Ptitjoz Hors ligne Membre Points: 225 Défis: 10 Message

Citer : Posté le 16/01/2024 22:32 | #


Lephenixnoir a écrit :
Info, pendant qu'on gère ça (qui s'avère être le manque de mémoire, comme d'hab...) j'ai ajouté le support de l'extinction. Donc Shift+AC/ON éteint la calculatrice, ça marche quand on est dans l'add-in et ça marche aussi si on le fait dans le menu pendant que l'add-in tourne.

Merci ! ça va être un plus et je suppose que ça va aussi gérer l'auto-extinction si pas d'activité ?
Un peu poète, un peu geek, un peu rêveur, un peu écolo.

Lephenixnoir Hors ligne Administrateur Points: 24248 Défis: 170 Message

Citer : Posté le 16/01/2024 23:10 | #


Pas d'auto-extinction encore. Je préfère vérifier que c'est stable à l'usage sinon ça risque d'être un auto-crash... :3
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Ptitjoz Hors ligne Membre Points: 225 Défis: 10 Message

Citer : Posté le 17/01/2024 08:46 | #


Merci. D'accord pas de soucis ; c'est juste des suggestions que j'émets (pas des demandes)
de toute façon si j'ai des crashs sur cet addin que je peux reproduire, je les remonterai sur cette discussion
Un peu poète, un peu geek, un peu rêveur, un peu écolo.

Lephenixnoir Hors ligne Administrateur Points: 24248 Défis: 170 Message

Citer : Posté le 30/01/2024 22:35 | # | Fichier joint


Ok ! Après un certain délai j'ai réussi à caler entre du boulot IRL et un déplacement en ce moment un peu de code sur les images. Et ça commence à marcher ! Voici un teaser.

import gint

data = b'\xa0\x00\x00\x00\x50\x00\x00\x00\xa0\x00\x00\x00'
IMAGE_MONO = 0
img = gint.image(IMAGE_MONO, width=3, height=3, data=data)

print(img) # "<mono image (1 layers), 3x3 (py, 12 bytes)>"
# img.format, img.width, img.height, img.data

segments = gint.image(IMAGE_MONO, 79, 12, b'|\x00||\x00|||||\x00\x00\xba\x02::\x82\xb8\xb8:\xba\xba\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\x82\x02\x02\x02\x82\x80\x80\x02\x82\x82\x00\x00\x00\x00|||||\x00||\x00\x00\x82\x02\xb8:::\xba\x02\xba:\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xba\x02\xb8:\x02:\xba\x02\xba:\x00\x00|\x00||\x00||\x00||\x00\x00')
print(segments) # "<mono image (1 layers), 79x12 (py, 144 bytes)>"

gint.dclear(gint.C_WHITE)
gint.dimage(10, 10, img)
gint.dimage(10, 20, segments)
gint.dupdate()


Pour l'instant c'est pas super glamour : on peut "juste" créer les images à partir des paquets d'octets à la façon traditionnelle. Je n'ai pas encore d'outil à vous proposer pour générer automatiquement les données, je l'ai fait en récupérant la sortie de fxconv (l'outil utilisé pour faire ça en C avec le fxSDK).

Quelque chose de cool c'est qu'on peut fournir les données avec n'importe quel type qui implémente le protocole "buffer" de MicroPython, c'est-à-dire str, bytes, bytearray, array, memoryview...

Sur le moyen/long terme, voilà les fonctionnalités prévues (certaines étant déjà codées).

  • Bien sûr support des différents formats mono (n&b, gris, ±transparent) et couleur (RGB565, P8, P4, ±transparent)
  • On peut créer une image en fournissant des données depuis des variables Python
  • Je compte aussi fournir de quoi "packager" les assets d'un projet sous la forme d'un fichier binaire (.bin) à installer avec le .py, qui pourra être chargé par une fonction de gint. Ainsi les données ne sont pas dans le code Python ce qui économise de la mémoire.
  • Les pixels des images chargées de façon externe peuvent quand même être utilisés dans le code Python (img.data est une memoryview) ce qui permet de lire/modifier les pixels (la taille est fixe par contre).
  • Pour l'instant pas de plan de porter l'API de manipulation d'images de la Graph 90+E, c'est que dimage() et dsubimage().

Edit : Il est passé où ton avatar Ptitjoz ? :'-
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Tuper4 Hors ligne Membre Points: 832 Défis: 19 Message

Citer : Posté le 30/01/2024 23:02 | #


Donc si je comprends bien, il ne peut pas récupérer et "dessiner" les images â partir d'image externe (sous format .png ou .bmp)? Sinon, du progrès reste du progrès et bravo à toi et Slyvtt pour votre travail!

Tuper
Ne vous arrêtez pas quand vous êtes fatigé(e), arrêtez vous quand vous avez terminez.
Lephenixnoir Hors ligne Administrateur Points: 24248 Défis: 170 Message

Citer : Posté le 31/01/2024 07:08 | #


On pourrait en théorie mais personnellement je ne comprends pas du tout l'intérêt. Ça fait plein de fichiers à installer en plus, le chargement + décodage serait relativement lent, et ça oblige à passer par le système de fichiers plein de fois au démarrage...
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Précédente 1, 2, 3 ··· 10, 11, 12, 13, 14, 15, 16 ··· 19, 20, 21 Suivante

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 37 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd