RCCL V4 : développement du software

version provisoire d'une documentation  technique
Cette évolution de la version V2 a un objectif:permettre l'édition du fichier source avec l'émetteur seul, sans la nécessité d'un PC.
Elle conserve le langage RCCL inchangé (un émetteur V2 et un émetteur RCCL++ utilisent le même fichier "source")
Elle utilise un micro 32 bits et plus de mémoire, pour optimiser la clarté du programme plutôt que l'encombrement mémoire.

En utilisant C++ on se facilite la programmation (approche objet, strings, gestion de listes ...) et l'utilsation est beaucoup plus confortable grâce à l'écran touchscreen.

Pour réaliser ceci, le choix hardware est

Compilation:

Le MBED est directement prêt à l'emploi. Les compilations par "cloud" sont plus lentes que les compilations locales, car il compile toujours tout le projet, mais suffisamment rapides. Le "programmeur" USB qui est très rapide. Les drivers sont très faciles à utiliser.
La programmation se fait en C++, en utilisant les classes "vector" et "string", ce qui représente un réel confort comparé à C.

Fin novembre 2011, Mbed propose une compilation off-line, avec par exemple un compilateur GCC (Codesourcery lite). La library mbed reste cependant closed-source.
Cette procédure fonctionne bien et me permet d'utiliser un éditeur de meilleure qualité (Scite) et de disposer d'un "folding" du code.

Organisation générale:
Mémoire RAM
Le micro LPC 1768 dispose de 64k mais attribue 32k aux périphériques tels que Ethernet, Usb externe...il ne resterait donc que 32k pour le programm C++.
On peut cependant définir certaines tables au delà de cette limite de 32k , c'est le cas pour la table des opérations.

struct rccl_data rc

Cette structure comporte les données communes à tous les programmes

struct rccl_data {
    string current_file; //current model file name ,without the extension
    Calc* calcptr;  // pointer to the current calc object (NULL if not loaded)
    Lcd4D*lcdptr;   // pointer to the lcd object
    set<short> *varSelection; //selection of index to the variables to display in some menus (normal empty)
    int rccl_task_tick;  //ticker at the beginning of the last rcloop
};

Lcd.cpp : gestion du display et du touchscreen

voir core.h

Lcd4D: constructeur d'un "objet" pour gérer le display. (uniquement pour le confort, car il n'y a évidemment qu'une seule instance)

L'initialisation est lente (délai de plusieurs secondes; initialise le display, change la vitesse de communication, charge les calibrations du touchscreen ).

Les fonctions sont programmées selon les besoins de RCCL: ceci n'est pas un "driver" à usage universel.

Les fonctions dépendant du microprocesseur sont dans hw/lcdhw.cpp

Fonctions de gestion de fichier

Trois possibilités: le file system local propre au Mbed, le file system de 4D et le standard FatFs avec une carte SD externe.

Le programme filey.cpp  utilise le filesystem local du mbed. Il démarre rapidement, il est facile à partager avec le PC (le mbed se comporte comme un stick USB )...mais il masque les interruptions. On ne peut donc pas l'utiliser en cours de vol.
C'est le système utilisé.

Il est possible d'écrire un programme similaire utilisant une carte SD séparée et le software FatFS, qui n'aurait aucun de ces inconvénients.

File system du Lcd:
Le filesystem de 4D ne peut pas démarrer rapidement.
Certaines communications comportent un message long envoyé par le Lcd et ceci ne peut pas être interrompu.
Ce système est utilisé pour les sons  et  la synthèse vocale.
La carte doit être formatée en mode FAT16(Linux: utiliser Gparted ; Windows ...devrait le faire):
Les noms de fichier dans le vieux format DOS 8.3 majuscules , chiffres, quelques signes spéciaux http://en.wikipedia.org/wiki/8.3_filename
 

Mdx.cpp : gestion d'un fichier "modèle"

voir core.h
Le but est de charger un fichier . mdx en mémoire, puis d'extraire les lignes et les "tokens"

Les fonctions dépendant du hardware sont dans hw/filex.cpp: l'échange de données entre le filesystem local du mbed et un fichier en mémoire représenté par un objet Mdx.

Ed.cpp

voir core.h
Editeur d'un fichier ...ce qui était la raison de passer de V2 à V4 !

hw/timer.cpp

Génération d'un signal ppm

gestion d'un pseudo systick
GetTicker() returns un nombre incrémenté de 1 toutes les 10msec
Remarque: la librarie du mbed utilise un seul timer(timer3).

Calcload.cpp

voir calc.h
Ceci charge un modèle en mémoire.
Il construit un objet Calc(f) (Le constructeur appelle expandfile(f) pour lire les modules et crée toutes les variables en mémoire)

Structures significatives:voir calc.h
Chaque code opération connait la nature (numérique, logique, string) de ses arguments et la présence d'une variable de sortie. Seul le nombre total peut varier.



Fonctions :

calcrun.cpp

Le calcul exécuté toutes les 10 msec.
Ceci est la transposition de calc.c (V2).

Utilise mixer.cpp pour le mélangeur courbe.

calchw.cpp

On trouve ici la gestion des variables hardware en input et aussi le paramétrage pour un émetteur

Fonctions temps réel

Les besoins sont relativement simples et ne justifiait pas un RTOS
-génération du signal PPM , avec une précision d'ordre de la microseconde
-exécuter toutes les 10 msec la boucle de calcul
-gérer les transmissions avec l'écran sans bloquer les calculs
-exécuter les dialogues, les menus...

Par contre l' acquisition de la télémétrie Jeti aurait été plus aisée avec une tâche séparée et donc un RTOS.
 
La difficulté se trouve dans le démarrage:
La cause du démarrage se trouve dans un byte préservé lors du redémarrage (rc.startmode)
        0 = démarrage normal après power-off
        1 = redémarrage volontaire ( par exemple pour effacer  les "memory leaks" éventuels). Il ne faut pas redémarrer le LCD.
        2 = redémarrage après erreur LCD (NAK answer)-restart LCD
        3 = bloquage détecté par le watchdog , qui joue ici son rôle normal
Pour le moment on utilise seulement les valeurs 0 et 3 , les conditions 1 et 2 provoquent 3

L'état du Lcd : (rc.lcdstate)
2 = démarrage achevé :une utilisation complète est permise
1 = disponible pour la lecture des entrées digitales dans l'état qui précède le warmstart
0 = non disponible

Le programme  principal est rccl_dialog, qui exécute l'un des menus. Chaque menu se termine par le return d'un code (voir enum dialog) qui désigne le menu suivant. Ceci tourne sans fin en rond, en attendant une sélection par touchscreen. La fin est par le menu de power-off.

Les programmes "temps-réel"sont appelés par  rc_task(x). C'est une version très simplifiée d'un RTOS.
Ce task-switcher est appelé lorsque le programme attend un  évènement  :


La génération PPM se fait avec les interruptions d'un timer. Le plus facile est d'utiliser la library MBED, mais il est possible de s'en passer et d'utiliser un timer spécifique, différent du timer 3 utilisé par mbed.

programme principal (rccl.cpp)

Ce programme est la boucle principale (le programme main du microprocesseur)

L'initialisation rccl_init()tient compte du mode de démarrage (  normal ou après intervention du watchdog). Le fichier RCCLINIT comporte le nom du modèle courant. Ce modèle est immédiatement chargé , le signal PPM est activé et l'émetteur est en fonction après 0,5 sec.

Pendant l'initialisation du lcd, l'émetteur doit fonctionner normalement mais ne répond pas à une modification d'un interrupteur.
Ensuite, le menu principal est appelé: rccl_dialog(), voir menu.cpp.
C'est une boucle perpétuelle; chaque menu renvoie le code du menu suivant.
Le menu initial dépend de l'état :

paramètres mis à jour en vol, trims

Ceci est un aspect important pour l'utilisateur.

les fichiers comportant les paramètres de l'émetteur

La situation actuelle est:

Snd :sound.cpp  et sound_xx.cpp

L'objet Lcd4D fournit les accès de base aux fichiers sons de la carte SD( voir plus haut :play(filename) pour jouer un fichier son et getSoundLen(filename) pour en connaître la longueur.
Ces fonctions sont codées dans le programme sound.cpp

L'objet Snd est codé dans sound.cpp . Ce programme  comporte toutes les fonctions indépendantes de la langue.
Le fichier sound_xx.cpp comporte les quelques fonctions qui dépendent de la langue xx

L'objet Snd comporte une file d'atttente FIFO avec les noms des fichiers à jouer , ou les silences.

Les fonctions programmées dans sound.cpp sont:
Le programme sound_fr  comporte la conversion de nombres en sons, ici pour une conversion en français.Un "#define" spécifie le mode français ou belge.

Pour adapter la langue de l'émetteur il suffit de recompiler RCCL. Il faut également remplacer les fichiers son de la carte SD.

développement des messages (chr, show, play,break) voir rccl

Affichage
Le programme de calcul prépare les données à afficher sous la forme d'une table lcd[8], qui se trouve dans l'objet Calc. Cette table est mise à jour par chaque cycle de calcul.
Les menus de dialogue comportent un "menu_normal.cpp" qui est celui qui s'affiche en temps normal, lorsque le pilote ne manipule pas l'écran.
Ce menu prépare 8 zones de texte qui sont des objets graphiques Grt. Ils portent également le nom lcd[ ] mais ils sont définis dans le menu.
Les deux première lignes sont de petite hauteur, la dernière est de couleur rouge .
En permanence, le programme "menu_normal" copie le string lcd vers l'élément graphique lcd . Notons que  si le string ne change pas ceci ne réécrit pas l'écran (pas de flicker).

L'affichage utilise les instructions RCCL CHR, SHOW et BREAK

Messages sonores:

Des messages sonores sont définis par le modéliste . Il crée les fichiers xxx.wav sur la carte SD du lcd , puis utilise ce nom de fichier dans des instructions RCCL.


L'instruction BREAK est particulière: elle est réservée aux contrôles au moment du démarrage.
Les instructions BREAK ne sont pas traitées en cas de redémarrage après intervention du watchdog.
L'écran affiche le mesage d'une instruction BREAK à la fois
Quant une instruction BREAK est exécutée, elle affiche son message en dernière ligne de l'écran , fait sonner une alarme et un message standart et n'exécute pas les instructions suivantes.
Lorsque la condition d'erreur est corrigée, les instructions suivantes snt exécutées et éventuellement une nouvelle ligne BREAK.

sons pour le vario

La variable de télémétrie est exprimée en m/sec.
Un mélangeur non linéaire transforme cette variable en tonalité. Pour tenir compte des valeurs autorisées pour les variables, la tonalité est un nombre égal à la fréquence / 40 .
Ensuite l'instruction PLAY en format 8 (vario) appelle le fichier son qui y correspond. Ce fichier est de la forme VVffff.WAV, fff étant la fréquence.
Pour générer ces fichiers, on utilise sous Linux la commande tones du package siggen
Voici un petit script qui génère les fichiers de 400Hz à 2200Hz (j'utilise Linux)
#!/bin/bash
# tones files
for (( c=400; c<=2200; c=c+40 ))
do
    echo "Tones $c Hz..."
    tones -w  VV$c.wav -s 16000 -16 200 $c
    # variable c = frequency in Hz
    # wav file name VV..
    # 200 = duration in msec
done

interface JETI

hwjeti/jeti.cpp
la communication entre module Jeti et JetiBox se fait à 9600 Bauds, avec des caractères de 9bits +parité + 2 stop bits, qui n'est pas possible pour l'UART du mbed. Il faut donc une autre solution, par exemple un UART software.
Cette routine gère un UART software pour des messages  "reçus"  de 32 caractères, un message émis a un seul caractère.

La routine  s'inspire de la note AVR 274,pour réaliser une lecture UART en utilisant des interruptions.
Le buffer mis à la disposition des programmes comporte 32 bytes, les 2lignes de 16 bytes de la JetiBox.

hwjeti/menu_jeti.cpp
JetiBox "active"
Le menu  affiche le message courant et propose des boutons (flèches) pour les actions possibles, y compris un bouton pour actionner simultanément deux touches (fonction Erase).
Le mode de détection tacile est
-normalement "One Touch" = une seule transmission vers le module Jeti
-ou bien "Long Touch"= transmission en rafale, tant que l'on appuie sur une touche

En complément on utilise les fonctions décrites ci-dessous pour déterminer le code du nœud affiché et en extraire les variables.
JetiBox passive
Ce menu affiche les messages de la JetiBox sans interférence, il est utile pour contrôler la navigation automatique.
hwjeti/explorer.cpp
Ceci est le programme de navigation, qui est relativement complexe car si le protocole Jeti est bien adapté à un dialogue avec l'utilisateur il n'est par contre pas du tout adapté à une communication entre programmes.
De plus, cette navigation est lente et RCCL V4 a été écrit sans RTOS ce qui impose une navigation "non transactionnelle" et un certain nombre de variables d'état.
core/calcrun.cpp

Images

Pour afficher les textes et les images en mode landscape, il faut à la fois (très troublant !)

Logging

le logging se fait vers la carte SD du LCD, et ceci est délicat car la voie de communication est encombrée, principalement par la lecture des entrées digitales.

Le programme de calcul écrit un message de logging dans une file d'attente, si deux conditions sont remplies:
- les données de télémétrie ont été rafraîchies (toutes les 80 msec environ)
- la file d'attente n'est pas trop grande

Les messages sont écrit vers la carte SD par rccl_task, lorsque c'est possible.
La transmission se fait à 282353 bauds (cette valeur bizarre est une anomalie dans 4D) soit à environ 31 bytes/msec.

Watchdog

implémenté.
Pendant le redémarrage du LCD, on n'a pas accès aux digital inputs du lcd. Leur état est cependant restauré.


to do

to do power

évolutions futures envisagées

Retour au sommaire

© Copyright 2008-2012 Robert Spilleboudt   - Tous droits réservés.
Projet rcopensource - Licence GPL V2