Après avoir expériementé avec les sleep modes avec plus ou moins de succès (j'en reparlerai bientôt) je me suis dit que ça serait sympa que l'horloge affiche un message d'accueil à la mise sous tension.
J'ai donc décidé de lui faire afficher un 你好 (ni hao) autrement dit "bonjour" scrollant de droite à gauche en utilisant chaque caractère de la matrice comme un point lumineux.
Encore un truc qui m'a rappelé des souvenirs de jeunesse!
Je m'amusais à faire des scrollings en assembleur Z80 en rentrant du collège quand j'étais en cinquième (ça plantait souvent et fallait recharcher l'assembleur depuis une cassette à chaque plantage!).
Donc comment faire ça avec un Arduino et un MAX7219.
Eh bien encore une fois la librairie LedControl simplifie énormément la tâche puisqu'elle permet entre autre un pilotage ligne par ligne avec un bit par led.
J'ai donc commencé par tracer le message à afficher sur un papier quadrillé sur une hauteur de 5 cases. Pas facile!
Ensuite, j'ai découpé la longueur en blocs de 8 cases (mes futurs octets) et j'ai utilisé ce dessin pour créer un tableau de 5*6 octets pour le stocker.
Voilà ce que ça donne:
//message d'accueil scrollant "ni hao"
const static int text[5][6]={
{0,B00101111,B10001000,B01111100,0,0},
{0,B01010000,B10001000,B00001000,0,0},
{0,B11000010,B00011111,B00111100,0,0},
{0,B01001010,B10000100,B00010000,0,0},
{0,B01000010,B00001010,B00010000,0,0},
};
Au début j'ai un caractère vide pour permettre d'introduire le premier caractère progressivement.
Et à la fin j'ai deux caractères vides pour l'effacement progressif du dernier caractère.
Chaque bit à 1 est un "pixel" de mon message.
L'astuce pour faire scroller ça c'est d'avoir un "pointeur" qui va indiquer sur quel bit des 5*8 bits formant les cololonnes doit commencer l'affichage.
Ensuite on sait que notre matrice fait 8 bits de long (par 5 de haut), on va donc copier 8 bits à partir de cette position dans le tableau qui représente la matrice d'affichage.
Comme on va commencer par lire un bit situé à n'importe quel endroit d'un octet on doit jouer avec des décalages de bits pour prendre les bits à afficher dans les bons octets et les décaler pour les placer là où ils doivent être dans la matrice d'affichage à un instant donné.
Une fois qu'on a fait ça pour les 5 lignes à afficher, y'a plus qu'à transférer tout ça au Max7219 via LedControl.
Voilà ce que ça donne niveau implémentation :
/*
* Message d'accueil
*/
void greet(){
int i; //bit à partir duquel on commence à afficher
int b; //octet suivant celui en cours d'affichage
int r; //ligne
int octet=0; //octet en cours d'affichage
int offset=0; //nombre de bits à prendre dans l'octet suivant
for(i=0;i<32;i++){ //on a 32 bits à afficher
octet = i / 8; //octet de départ
offset = i % 8; //nombre de bits à prendre dans l'octet suivant
for(r=0;r<5;r++){ //pour chaque ligne de la matrice
row[r]=0;
//on transfert dans la matrice l'octet de départ décalé de l'offset (on décale le caractère
//de N crans vers la droite de la matrice)
row[r] |= text[r][octet] << offset;
//si on n'est pas sur le premier bit d'un octet il faut prendre les bits qui restent à
//afficher dans l'octet suivant
if(offset>0){
b = text[r][octet+1];
row[r] |= b >> (8-offset) ;
}
}
//on a calculé la matrice à afficher, reste plus qu'à la transférer ligne par ligne
//dans le Max7219
for(r=0;r<5;r++){
lc.setRow(0,r,row[r]);
}
delay(70);
}
}
Et comme un bon dessin, en l'occurence une vidéo, vaut mieux qu'un long discours, voici ce qu'elle affiche à la mise sous tension:
Elle va aussi afficher une fois "ni hao" lors du premier allumage de la journée à la sortie de veille (c'est une horloge polie ). Pour un peu je la ferais parler mais je sens que ça risque m'énerver à la longue.