diff --git a/README.md b/README.md index 3a52e6f..2df5da7 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,9 @@ de la carte électronique : - Jouer des sons - Contrôle du gain +Les données utilisées pour l'affichage sur le LCD ou pour la sortie audio doivent +être chargés depuis une carte SD insérée dans la carte microcontrôleur. + En plus de contrôler la carte, le firmware doit pouvoir intéragir avec une application développée sur Unity. En premier lieu, il doit renvoyer des identifiants correspondants aux tags RFID @@ -69,6 +72,100 @@ mise à jour et suivi des dépendances. La structure du code assume une carte Teensy. En particulier, il est conçu pour la [Teensy 4.1](https://www.pjrc.com/store/teensy41.html). +# Carte SD et données + +La carte SD est utilisée pour lire les animations et les sons, lors de l'utilisation +des figurines ou pour des cas génériques (démarrage, batterie faible…). +Le firmware attend les fichiers dans certains endroits et sous certaines formes, +détaillés ici. + +## Structure de fichiers + +Les fichiers sur la carte SD sont structurés comme suit : +``` +/ +├── RANDONNEE/ +│ ├── ANIM/ +│ │ ├── 00 +│ │ ├── 01 +│ │ ├── 02 +│ │ ├── .. +│ │ └── XX +│ └── audio.wav +├── RESTO/ +│ ├── ANIM/ +│ │ └── .. +│ └── audio.wav +├── .../ +└── SYS/ + ├── ANIM*/ + ├── ../ + └── *.wav +``` + +Tous les fichiers liés à une figurine en particulier doivent être placés dans un +dossier associé au nom de la figurine. +Les noms attendus sont ceux des tableaux définis dans `src/IDs.cpp`. +Les différentes images d'une même animation doivent être dans un même dossier, +numérotés dans l'ordre avec deux chiffres et sans extension, les fichiers audio +doivent garder leur extension. + +Le dossier SYS sera utilisé pour toute interaction qui n'est pas liée à une figurine. + +## Structure des données +### Audio + +Le format audio supporté est assez précis : les fichiers doivent être des WAV +16 bit PCM, 44100 Hz. +Mono ou stéréo n'est pas important : la carte ne supporte qu'un haut-parleur, +les deux canaux stéréo seront moyennés `(Gauche+Droit)/2`. + +### Animations + +Le format des animations est d'autant plus précis et particulier et demandera +probablement du traitement pour qu'elles soient correctes. + +Tout d'abord, chaque image de l'animation doit être dans son propre fichier, un +seul fichier pour l'animation (comme un gif) n'est pas possible. + +L'écran LCD choisi est un module pour écran Nokia 5110 de 84x48 pixels monochromes, +les images de l'animation doivent donc être à ce format et monochromes. +L'image attendue est exclusivement une bitmap d'un bit par pixel, sans aucune +autre information. +De plus, il est probable que les bits attendus soient inversés par rapport à ceux +produits "logiquement" depuis un programme normal. Par exemple `0b11001100` devrait +en réalité être `0b00110011`. + +Je n'ai pas connaissance d'un format connu qui peut être généré depuis un logiciel +et répondre à ces conditions, cependant il est possible d'y arriver automatiquement +avec quelques opérations de transformation. +Pour la facilité, il est donc possible d'arriver aux fichiers individuels requis +à partir d'un simple gif aux proportions correctes. + +À l'aide d'[ImageMagick](https://imagemagick.org/), on peut découper le gif en +ses images individuelles, et les convertir en un format de bitmap presque correct +(aux bits inversés) avec la commande suivante : + +```shell +convert -resize 84x48 -coalesce .gif -threshold 50% %02d.mono +``` + +Il peut être nécessaire d'inverser les bits comme mentionné plus haut et je n'ai +pas trouvé de façon existante de le faire. +Vous trouverez donc dans `Utils/bitmap_helper` un projet Rust qui permet de +réaliser cette opération sur les fichiers produits par la commande ci-dessus. +Une fois compilé, vous pouvez convertir les fichiers `.mono` dans le format adapté +(avec une extension `.bin` en les passant à l'utilitaire : +```shell +bitmap_helper *.mono +``` + +N'oubliez pas de retirer l'extension et de les placer dans un dossier `ANIM` sur +la carte SD, comme décrit ci-dessus. + +Un script bash est aussi fourni pour automatiser tout ce processus : +`Utils/convertAnimGif.sh`. + # Interfaçage avec l'application Unity Afin de permettre la détection automatique de l'objet, la communication se fait diff --git a/Utils/.gitignore b/Utils/.gitignore new file mode 100644 index 0000000..977a0f9 --- /dev/null +++ b/Utils/.gitignore @@ -0,0 +1,2 @@ +*.gif +ANIM*/ diff --git a/Utils/README.md b/Utils/README.md new file mode 100644 index 0000000..d27866d --- /dev/null +++ b/Utils/README.md @@ -0,0 +1,56 @@ +# Utilitaires + +Ce sous-dossier rassemble divers utilitaires liés au projet. + +# Conversion des animations + +Deux outils sont disponnibles pour aider à la conversion : un pour faire l'inversion +de bit nécessaire, et un script pour automatiser tout le protocole. + +Pour des détails sur le format de sortie, référez-vous au README principal. + +## bitmap_helper + +Un projet Rust a été créé pour permettre la conversion d'une bitmap MONO gérée +par ImageMagick en une bitmap correcte pour le LCD, en inversant les bits de chaque +octet. + +Il est possible qu'une version compilée soit disponible dans les versions sur +Github. + +### Compilation + +Pour le compiler, il suffit d'utiliser Cargo, qui peut être installé via +[rustup](https://rustup.rs/) par exemple. +Une fois Rust et Cargo disponibles, la compilation peut être faite depuis le +dossier `bitmap_helper` avec la commande suivante : +```shell +cargo build +``` +L'exécutable produit est alors `bitmap_helper/target/debug/bitmap_helper`. + +### Utilisation + +L'utilitaire peut convertir plusieurs fichiers `.mono` à la fois, passés directement +sur la ligne de commande. +```shell +bitmap_helper/target/debug/bitmap_helper .mono .mono ... +``` +Tout autre format de fichier ne sera pas traité. +⚠️ La détection du format n'est basée que sur les extensions ! + +## convertAnimGif.sh + +Ce script permet d'automatiser tout le protocole de conversion d'un ou plusieurs +gifs en suites de bitmaps utilisables par le projet. + +Il prend en argument un ou plusieurs fichier(s) `.gif` et produit les bitmap +individuelles correctement numérotées dans un dossier portant le nom du fichier +original. + +```shell +./convertAnimGif.sh .gif .gif ... +``` + +Il suffit ensuite de déposer les dossiers sur la carte SD, sous les dossiers correspondants +(voir noms dans `src/IDs.cpp`) et les renommer pour ne laisser que `ANIM`. diff --git a/Utils/bitmap_helper/.gitignore b/Utils/bitmap_helper/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/Utils/bitmap_helper/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Utils/bitmap_helper/Cargo.lock b/Utils/bitmap_helper/Cargo.lock new file mode 100644 index 0000000..ef6ca90 --- /dev/null +++ b/Utils/bitmap_helper/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitmap_helper" +version = "0.1.0" diff --git a/Utils/bitmap_helper/Cargo.toml b/Utils/bitmap_helper/Cargo.toml new file mode 100644 index 0000000..e3a07c7 --- /dev/null +++ b/Utils/bitmap_helper/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "bitmap_helper" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/Utils/bitmap_helper/src/main.rs b/Utils/bitmap_helper/src/main.rs new file mode 100644 index 0000000..a96029a --- /dev/null +++ b/Utils/bitmap_helper/src/main.rs @@ -0,0 +1,51 @@ +use std::fs::File; +use std::fs::write; +use std::env; +use std::io::Read; + +fn main() { + let args: Vec = env::args().collect(); + + for arg in &args[1..] { + println!("Processing : {}", arg); + if !arg.ends_with(".mono") { + eprintln!("{} : unsupported file type.", arg); + continue; + } + let file_r = File::open(arg); + if file_r.is_err() { + eprintln!("{} : could not open file.", arg); + continue; + } + let mut image_data = vec![]; + if file_r.unwrap().read_to_end(&mut image_data).is_err() { + eprintln!("{} : could not read file.", arg); + continue; + } + + let out_file = arg.replace(".mono", ".bin"); + flip_bits(&mut image_data); + if write(&out_file, &image_data).is_err() { + eprintln!("Failed to write bit flipped bitmap to file : {}", out_file); + } + println!("Processing successful, flipped bits and wrote to {}", out_file); + } +} + +/// Flips the bits of each individual byte (except zeroes). +/// This would transform 0b11001100 in 0b00110011. +fn flip_bits(data: &mut Vec) { + for source_id in 0..data.len() { + let mut new_int = 0; + for i in 0..8 { + if data[source_id] == 0 { break; } + new_int |= ((data[source_id] & (1 << 7 - i)) >> 7 - i) << i; + } + data[source_id] = new_int; + } + // for i in 0..data.len() { + // print!("{:2X}", data[i]); + // if i > 0 && i%16 == 0 { println!(); } + // } + // println!(); +} diff --git a/Utils/convertAnimGif.sh b/Utils/convertAnimGif.sh new file mode 100755 index 0000000..d8d33d1 --- /dev/null +++ b/Utils/convertAnimGif.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +set -euo pipefail + +if [[ $# -eq 0 ]]; then + echo "This script expects the name of the files to convert as arguments" + exit 1 +fi + +if [[ ! $(command -v convert) ]]; then + echo "Could not find 'convert' utility, cannot proceed." + exit 1 +fi + +# Get the absolute path to the source of the script +scriptSrcDir="$(dirname -- "$0")" +pushd "$scriptSrcDir" +scriptSrcDir="$(pwd)" +popd + +if [[ $(command -v bitmap_helper) ]]; then + bmp_help="$(command -v bitmap_helper)" +elif [[ $(command -v "$scriptSrcDir"/bitmap_helper/target/debug/bitmap_helper) ]]; then + bmp_help="$scriptSrcDir"/bitmap_helper/target/debug/bitmap_helper +elif [[ $(command -v "$scriptSrcDir"/bitmap_helper) ]]; then + bmp_help="$scriptSrcDir"/bitmap_helper +else + echo "Could not find 'bitmap_helper'." + echo "Have you compiled it or placed it in the same directory as the script ?" + exit 1 +fi + +for gifToConvert in "$@"; do + if [[ -z "$(echo "$gifToConvert" | grep -e 'gif')" ]]; then + echo "Cannot convert $gifToConvert : not a gif." + continue + fi + + animDir=ANIM_"${gifToConvert//.gif//}" + mkdir "$animDir" + pushd "$animDir" + + convert -resize 84x48 -coalesce ../"$gifToConvert" -threshold 50% %02d.mono + "$bmp_help" ./*.mono + # Clean up and remove the extension + rm -f ./*.mono + for f in ./*.bin; do + mv "$f" "${f//.bin/}" + done + + popd +done