Skip to content

📝 Blog

Bienvenue dans ce petit coin CALM.

Une étape de plus

Welcome friends

Après bien trop de tergiversations, il est temps de lancer un site qui me permettra de rassembler plusieurs de mes activités, projets et idées.
J'aimerais un endroit qui accueille mes quelques posts en mode blog.

Ensuite, j'ai envie d'ajouter des éléments pour la communauté qui existe autour de mon stream sur Twitch : CALM.
Il y aura probablement une section dédiée aux tutoriels, et pas seulement les miens.

J'ai également commencé ce qui devrait permettre de lister et rechercher dans l'historique des émissions CALM (déjà plus de 200, merci à vous 💞)

Le premier point, qui est l'objet de cette première étape, est de supprimer le blog que j'hébergeais sur une droplet Ghost chez DigitalOcean.
Ce n'est pas un énorme chambardement, mais je ne publie pas suffisamment pour que cela nécessite de générer des frais que je peux éviter.
Et puisque j'ai envie que ça avance (même si ça me fait plaisir de tester 10 stacks techniques 😇), je suis parti que quelque chose qui m'a déjà permis de remplacer mon usage de noti.st J'ai en effet lancé un petit site listant les conférences que je donne, afin d'avoir un point central pour celles et ceux qui souhaitent les retrouver.
Ça permet d'avoir les slides et les éventuels liens de replay, je trouve ça pratique.

Du coup, comme j'avais utilisé MkDocs et plus précisément Material for MkDocs, je me suis lancé avec ça aussi.
Et on verra bien si j'ai besoin de plus, s'il me faut des éléments dynamiques à tout prix.
Si je ne me lance pas, rien ne bougera.

Du coup, n'hésitez pas à me contacter pour tout ce que vous pouvez trouver de cassé ici, ou qui manque.
Commencez par me dire que je n'ai pas de système de commentaire, c'est dans ma liste 😜
Il y a ensuite de petites choses comme l'absence d'icône dans la navigation à gauche pour l'entrée du blog. J'utilise le plugin intégré mais je ne sais pas s'il me permettra de modifier ça.
Il y a aussi la TOC à droite du blog qui ne comporte qu'une série de 5 articles affichés sans proposer de voir le reste.

J'ai plein d'idées : mais pour une fois, j'essaie de faire plutôt que de penser trop longtemps à vide 😎

Ah... si tu lis ça le jour de sa sortie, c'est que tu as récupéré le lien GitLab Pages sur le Discord.
Et ça veut dire qu'on se connaît un peu déjà et que je peux te remercier pour ta présence dans cette chouette communauté CALM 💞

Alors, soyons forts, et en avant !!

PS: oui, je vais aussi mettre un vrai nom de domaine, j'en ai déjà 2 mais je voulais quelque chose avec calm dedans et c'est soit déjà pris, soit très cher 🐼

Aidez le Maroc 🇲🇫💖🇲🇦

Comme vous l'avez malheureusement sûrement suivi, un séisme de magnitude 7 a frappé le Maroc.
L'épicentre était dans le Haut Atlas, au niveau de la ville de Amizmiz et en ce lundi 11 septembre on dénombre plus de 2000 morts.

Au delà de la peine que je peux éprouver pour ce pays et ce peuple qui a une place particulière dans mon coeur, j'aimerai que ce rapide article serve d'appel à l'aide.

Cette aide peut prendre bien des formes, l'urgence et la rapidité passe bien sûr par un don a des associations qui agissent sur place.

Je peux actuellement citer :
- la Fondation de France
- le Secours Populaire
- directement auprès d'une banque sous le contrôle des autorités marocaines.

Mais n'hésitez pas à m'indiquer d'autres organismes que j'ajouterai à cette liste au fur et à mesure.

Ensuite, parce que donner de votre temps est aussi important, il est possible d'aider le projet OpenStreetMap.
Une équipe est dédiée aux actions humanitaires et elle a décidé d'activer un projet d'urgence.

Si vous avez vent d'autres initiatives, je me ferai un devoir de les relayer ici bien évidemment.

N'oubliez pas non plus de communiquer autour de vous et d'apporter toutes les preuves d'affections à nos ami·es marocain·es.

Comme je le dis dans le titre, aidez le Maroc, mais bien plus aimez les marocain·es 🇲🇫💖🇲🇦

Open minded to the bone

initialement publie surhttps://titimoby.hashnode.dev/open-minded-to-the-bone

C'est suite au post de Stéphane Robert à propos d'un article d'un ingénieur de chez Amazon qui expliquait pourquoi Python était si mauvais que l'idée d'enfin écrire tout ce qui suit à germé.

Je dis enfin parce que ça fait un moment que pas mal de choses se bousculent dans ma tête et je ne vous garanti pas en écrivant ces premiers mots que je saurais trouver une cohérence et une conclusion, mais au moins j'aurais exprimé plusieurs points qui me tarabustent depuis un moment (accrochez vous à un dico s'il y a des mots inhabituels, j'aime bien essayer des mots moins courants 😇).

Déjà, réglons un point majeur tout de suite : je cite Stéphane parce que le tweet venait de lui mais je n'ai aucun grief à son encontre 🥰.
L'article cité était en plus une traduction affreuse d'un site en mal de contenu gratuit, donc restons sur l'article initial.
Il se trouve que l'auteur, Jos Visser, a également plus tard posté l'article suivant : Why Python is amazing .

Les 2 articles sont intéressants, mais clairement il y a une petite touche de provocation de la part de l'auteur dans les 2 cas pour des raisons qui lui sont personnelles.
En tout cas, il y a matière à comprendre les intérêts et limites du language Python, mais il faut bien lire les 2 pour un équilibre 😎.

De toute façon, là n'est finalement pas le propos. Tout cela m'a rappelé ce qui m'a attiré dans ce monde qu'on appelait simplement "informatique" et également ce qui me déplait aujourd'hui dans ce qui l'entoure.

Au départ, je fais partie de la génération ayant connu l'arrivée de ce que l'on appelait la micro informatique dans les foyers. Après avoir rêvé sur de nombreux magazines, puis une première machine chez un copain, un ZX81, j'ai eu la chance d'avoir des parents qui ont compris que j'avais une attirance profonde pour ce domaine.
J'ai donc eu un Sinclair ZX Spectrum+ 🤩.

Ces machines, que ce soit les Amstrad, les Oric, les MSX, eurent un point commun quelque soit leur architecture et choix techniques par ailleurs : à l'allumage, on avait un prompt et il fallait entrer des commandes.

Du coup, tout curieux avait sous la main de quoi faire autre chose que lancer un jeu, activité néanmoins importante dans mon parcours.
C'est comme ça que je me suis retrouvé à coder mes premiers programmes avec le Basic de Sinclair.
J'ai même tenté mes premiers pas en assembleur avec un livre dont je ne me souviens que de la couverture rouge 😇
Toujours est il que j'ai codé ainsi de superbes aventures dont vous êtes le héros, à l'image des livres qui apparurent à cette époque (ahhh, la série Loup Solitaire 🐺⚔️)

Par la suite, le virus ayant pris, j'ai acheté un Atari 520STF avec l'intégralité de mes paies de mon premier job d'été de mes 17 ans. Et là, la claque intégrale : un desktop graphique, des disquettes tellement plus pratiques que les cassettes audio du Spectrum...
Mais surtout une première pour moi puisqu'il y avait une petite communauté autour des Atari proche de chez moi, et même si c'était surtout des échanges de jeux piratés, c'est grâce à ça que je suis tombé sur le GFA Basic puis le STOS

En me repenchant récemment sur le GFA Basic dans un émulateur Hatari, j'y vois à présent des éléments venant du C, du Python et d'autres languages.

Et c'est là où je voulais en venir (vous voyez, j'y arrive 😆)
Ces plus de trente années de machines en languages m'ont au moins montré une chose : chaque language a des éléments qui lui sont propres, mais aussi des éléments piochés dans ces prédécesseurs voire ces contemporains.

Du coup, nous allons pouvoir aborder l'aspect plus sociétal.
Déjà que ce qui précède est évidemment mon opinion, sans plus de valeur que l'opinion d'autrui, mais ce qui suit l'est forcément encore plus.
Il me semble qu'il y a toujours eu des affrontements assez stériles du genre Amstrad/Spectrum/Commodore ou Atari/Amiga mais la surconnexion dans laquelle nous vivons donne trop vite de l'importance à ce qui aurait du rester une pique dans un coin.

A cela se rajoute le besoin d'attention qui vire à la psychose, cumulé à des intérêts financiers. Il en découle des sujets peu développés mais systématiquement clivants et provocateurs. Les mécanismes d'un Twitter, d'un TikTok ou même d'un YouTube ou Twitch font qu'il est préférable de publier énormément mais toujours court et en opposition forte à d'autres.

Pour rester dans ce modeste domaine qui est le mien, cela n'apporte rien à mon sens de donner des avis 100% catastrophiques sur une technologie, la réalité est un patchwork de cas avec des besoins et des contextes nécessitant justement cette variété d'outils, languages, librairies...

De toute façon, pour que l'outil parfait existe, il faudrait que nos activités de code, CI, infra... soient toutes parfaitement définies et immuables.
Or, il me semble que l'informatique a toujours été un hybride entre science et artisanat, certainement pas industrielle.
Du coup, c'est un sujet en perpétuel changement, les solutions uniques à chaque problème n'existent pas : il faut une multitude d'outils pour répondre à une multitude de situations.

Dernier point pour moi, mais qui est essentiel à ma présence dans l'écosystème : il y a des préférences personnelles qui interviennent.
Si je suis plus heureux, littéralement, parce que j'ai codé tel ou tel projet avec Python ou Go, pourquoi irais je le faire en C ou en Javascript ?
Je n'ai jamais regretté d'avoir fait du PHP, ou du C++ ou que sais je. Toutes ces années m'ont permis de tester plus ou moins profondément des technologies très variées. Et si je n'ai pas à chaque fois eu un usage complexe, un projet entier, j'en ai toujours retiré quelque chose : j'apprend, j'évolue.

TinyGo - Joystick et boutons

Toute cette série est bien jolie, mais une console de jeu sans moyens d'interaction, c'est pas génial.
Je vous propose aujourd'hui de voir comment contrôler le joystick et les boutons de la Pygamer.

Je rappelle ici le disclaimer de l'article sur les fontes : la partie graphique va nécessiter un peu de travail, l'usage de tinyfont ou tinydraw ne fournira pas les performances nécessaires. Des projets ont tenté des approches, il faudra aller les analyser pour voir ce qui est faisable. Je pense au projet GoBadge, destiné au Pybadge, qui a plein de points communs avec la Pygamer, ou au projet Xship qui propose un jeu sur Pygamer, mais je ne l'ai pas encore essayé.
Merci d'ailleurs à Daniel Esteban et Jean-Yves Pellé pour ces 2 projets qui m'ont permis de comprendre beaucoup de choses.

Mais sans plus attendre, le code du jour :

package main

import (
    "image/color"
    "machine"
    "strconv"

    "tinygo.org/x/drivers/st7735"
    "tinygo.org/x/tinyfont"
    "tinygo.org/x/tinyfont/freemono"
)

var black = color.RGBA{0, 0, 0, 0}
var red = color.RGBA{255, 0, 0, 255}
var gray = color.RGBA{200, 200, 200, 255}

func main() {
    buttons := NewButtons()
    buttons.Configure()

    joystick := NewJoystick()
    joystick.configure()

    display := st7735.New(machine.SPI1, machine.TFT_RST, machine.TFT_DC, machine.TFT_CS, machine.TFT_LITE)
    machine.SPI1.Configure(machine.SPIConfig{
        Frequency: 16000000,
        SCK:       machine.SPI1_SCK_PIN,
        SDO:       machine.SPI1_SDO_PIN,
        SDI:       machine.SPI1_SDI_PIN,
    })
    display.Configure(st7735.Config{Rotation: st7735.ROTATION_90})
    display.FillScreen(black)

    var buttons_pressed = ""
    var x_axis uint16 = 0
    var y_axis uint16 = 0
    for {
        x_axis = joystick.getX()
        y_axis = joystick.getY()
        buttons_pressed = ""
        pressed, _ := buttons.Read8Input()
        if pressed != 0 {
            println(pressed)
        }
        if pressed&machine.BUTTON_A_MASK > 0 {
            buttons_pressed += "BTN A"
            println("BTN A")
        }
        if pressed&machine.BUTTON_B_MASK > 0 {
            buttons_pressed += "BTN B"
            println("BTN B")
        }
        if pressed&machine.BUTTON_SELECT_MASK > 0 {
            buttons_pressed += "SELECT"
            println("SELECT")
        }
        if pressed&machine.BUTTON_START_MASK > 0 {
            buttons_pressed += "START"
            println("START")
        }

        display.FillScreen(black)
        tinyfont.WriteLine(&display, &freemono.Bold9pt7b, 10, 20, strconv.Itoa(int(x_axis)), gray)
        tinyfont.WriteLine(&display, &freemono.Bold9pt7b, 10, 50, strconv.Itoa(int(y_axis)), gray)
        tinyfont.WriteLine(&display, &freemono.Bold9pt7b, 10, 80, buttons_pressed, gray)
    }
}

Cette fois, ça fait un fichier plus conséquent et en plus il y a un fichier à côté pour aider à simplifier la gestion des boutons et du joystick.
Je vais tâcher d'expliquer au maximum tout ce qui se passe.

Commençons par les boutons.

buttons := NewButtons()
buttons.Configure()

Vous voyez comme c'est simple ? ;)
Le code nécessaire se trouve bien sûr dans pygamer.go et une version brute de ce qui est appellé serait en fait :

var buttons = shifter.New(shifter.EIGHT_BITS, machine.BUTTON_LATCH, machine.BUTTON_CLK, machine.BUTTON_OUT)

Vous pouvez regarder le code entier, mais à part déclarer la fonction NewButtons et gérer le retour d'un objet device que nous stockons dans la variable buttons, il n'y a rien de plus.
Vous voyez qu'il s'agit d'utiliser le driver tinygo.org/x/drivers/shifter qui va gérer le composant qui permet d'accédr à l'état des boutons de la Pygamer.
Ce type de composant permet de ne pas monopoliser autant de broches du micro contrôleur qu'il y a de boutons.

Il suffit alors de récupérer l'état de ce composant :

pressed, _ := buttons.Read8Input()

La variable contient alors une information qu'il faut décoder à l'aide de masques logiques. Je vous laisse faire des recherches sur les registres à décalages ( = Shift registers => shifter) mais il y a un article assez complet sur Electronique amateur.

if pressed&machine.BUTTON_B_MASK > 0 {...

C'est ce que l'on fait par cette ligne qui sert ici à savoir si le bouton B est appuyé.
Notez que l'on peut tester l'appui simultanné de plusieurs boutons, la variable pressed contient alors une valeur cumulant les différents bits correspondants.

Pour la partie joystick, nous allons aussi décortiquer ce que signifie les lignes :

joystick := NewJoystick()
joystick.configure()

Le code brut si on se passait du fichier pygamer.go serait alors :

type joystickStruct struct {
    x machine.ADC
    y machine.ADC
}
// équivalent à joystick := NewJoystick()
joystick := joystickStruct{x: machine.ADC{machine.JOYX}, y: machine.ADC{machine.JOYY}}

// équivalent à joystick.configure
joystick.x.Configure(machine.ADCConfig{})
joystick.y.Configure(machine.ADCConfig{})

Pour rassembler la logique, on utilise une structure qui contiendra en fait les 2 axes du joystick.
Ces 2 axes sont des composants générants des valeurs analogiques qui ont ensuite besoin d'êtres converties en valeurs numériques pour que nous puissions les utiliser.
Cela passe par une couche d'abstraction matérielle ADC (Analog to Digital Conversion).
machine.JOYX et machine.JOYY sont les 2 objets définis dans TinyGo pour Pygamer pour représenter les 2 axes.

Nous pouvons ensuite lire les valeurs de ces axes :

x_axis = joystick.getX()
y_axis = joystick.getY()

Ce qui correspond au code :

x_axis = joystick.x.Get()
y_axis = joystick.y.Get()

Le reste du code est ma tentative pour afficher les informations récupérées.
Vous pouvez constater qu'il y a un phénomène de clignotement qu'il faudra gommer par la suite par un usage différent des ressources graphiques.

Sorry, your browser doesn't support embedded videos.

Vous en avez maintenant l'habitude, cet exemple est disponible dans le repository dédié aux exemples TinyGo.

Merci, n'hésitez pas à me faire parvenir vos remarques par email ou par le biais d'issues sur le repository.

TinyGo - Les fontes

Utiliser les Neopixels de la Pygamer peut déjà apporter un moyen de communication visuelle mais il faut pouvoir écrire des textes sur l'écran.

Pour cela, TinyGo propose un module appellé TinyFont.
Ce projet fourni même un outil pour générer vos fontes au format utilisable par TinyFont.
Ici, je me contenterai d'utiliser les fontes déjà fournies par le projet afin de ne pas rajouter de complexité supplementaire.

Avant de se lancer, j'ajouterai que nous entrons là dans un domaine manipulant les ressources graphiques de la Pygamer et que rapidement il faudra creuser le fonctionnement du driver. Mais nous y reviendrons ultérieurement.

Sans plus attendre, comme à mon habitude, je vous propose le code utilisé pour cet article :

package main

import (
    "image/color"
    "machine"
    "time"

    "tinygo.org/x/drivers/st7735"
    "tinygo.org/x/tinyfont"
    "tinygo.org/x/tinyfont/freemono"
    "tinygo.org/x/tinyfont/freesans"
)

var black = color.RGBA{0, 0, 0, 0}
var red = color.RGBA{255, 0, 0, 255}
var green = color.RGBA{0, 255, 0, 255}

func main() {
    display := st7735.New(machine.SPI1, machine.TFT_RST, machine.TFT_DC, machine.TFT_CS, machine.TFT_LITE)
    machine.SPI1.Configure(machine.SPIConfig{
        Frequency: 16000000,
        SCK:       machine.SPI1_SCK_PIN,
        SDO:       machine.SPI1_SDO_PIN,
        SDI:       machine.SPI1_SDI_PIN,
    })
    display.Configure(st7735.Config{Rotation: st7735.ROTATION_90})

    for {
        display.FillScreen(black)
        tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 10, 20, "No rotation", red)
        time.Sleep(1 * time.Second)

        display.FillScreen(black)
        tinyfont.WriteLineRotated(&display, &freemono.Bold9pt7b, 10, 10, "HELLO", green, tinyfont.ROTATION_90)
        time.Sleep(1 * time.Second)

        display.FillScreen(black)
        tinyfont.WriteLineRotated(&display, &freemono.Bold9pt7b, 100, 50, "Hello", red, tinyfont.ROTATION_180)
        time.Sleep(1 * time.Second)

        display.FillScreen(black)
        tinyfont.WriteLineRotated(&display, &freemono.Bold9pt7b, 120, 100, "HELLO", green, tinyfont.ROTATION_270)
        time.Sleep(1 * time.Second)
    }
}

Tout le début a été vu dans l'article de base sur la manipulation de l'écran.
J'ai apporté une modification à la configuration de l'écran.

display.Configure(st7735.Config{Rotation: st7735.ROTATION_90})

Par défaut, l'écran de la Pygamer est géré par le chip st7735 comme si vous le teniez avec le joystick en haut. Les librairies pour cette console en C ou en CircuitPython ont fait le choix de fournir un driver qui opère cette rotation d'initialisation, la rendant transparente pour l'utilisateur.
Cela peut être une suggestion de modification pour le driver st7735 dans le cas de la Pygamer, je vous tiendrais au courant si je me lance à proposer une PR dans ce sens.

La partie concernant les fontes commence par les imports des éléments utiles comme TinyFont lui même, mais également 2 fontes pour que vous ayez déjà le choix.

"tinygo.org/x/tinyfont"
"tinygo.org/x/tinyfont/freemono"
"tinygo.org/x/tinyfont/freesans"

L'affichage de texte se fera dans la boucle for où j'ai alterné 3 messages, entrecoupé d'un effacement de l'écran.
Pour effacer l'écran justement, j'ai utilisé la fonction :

display.FillScreen(black)

Je me contente donc de remplir l'écran de pixels noirs pour effacer le texte précédent.
Comme nous allons ensuite tracer les lettres, ce n'est surement pas la méthode que je conseillerai pour un jeu, l'usage d'un buffer mémoire sera à envisager, et nous le ferons surement dans un prochain article.
L'affichage des textes se fera avec les fonctions tinyfont.WriteLine et tinyfont.WriteLineRotated

tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 10, 20, "No rotation", red)

tinyfont.WriteLine permet ici d'afficher le message en respectant l'orientation de l'écran configurée. Vous noterez l'usage de l'appel de fonction avec des références (symbole &)
Si vous souhaitez comprendre ce point précis, je vous conseille un peu de lecture avec un chapitre sur les pointeurs, notament le 2.4 qui montre l'utilisation des pointeurs dans le cadre de paramètres de fonction.

Vous voyez donc que l'on confie à cette fonction la variable display gérant l'écran.
Cela servira en interne pour afficher les pixels des lettres.
Le second paramètre indique la fonte qui sera utilisée. En l'occurence, il s'agit de la famille de fonte freesans dans son format Regular9pt7b qui indique la taille et les détails tels que préparés par l'utilitaire TinyFontGen
Viennent ensuite les paramètres x et y permettant de positionner le texte.
Le paramètre suivant est le texte à afficher, suivi de la couleur souhaitée.

La seconde fonction utilisée est tinyfont.WriteLineRotated :

tinyfont.WriteLineRotated(&display, &freemono.Bold9pt7b, 10, 10, "HELLO", green, tinyfont.ROTATION_90)

Le comportement est identique, avec l'ajout du dernier paramètre permettant d'indiquer l'orientation du texte par rapport à celle de l'écran.

Bien entendu, il ne vous reste plus qu'à flasher la Pygamer :

tinygo flash -target=pygamer

Et voici ce que cela donne :

Sorry, your browser doesn't support embedded videos.

Bien entendu, cet exemple est disponible dans le repository dédié aux exemples TinyGo.
N'hésitez pas à essayer vos propres paramètres, jouez avec les couleurs, les positions et orientations. Je serai ravi de voir vos essais, partagez les moi.

Merci, n'hésitez pas à me faire parvenir vos remarques par email ou par le biais d'issues sur le repository.