ZSA Moonlander : QMK : compilation
Ma compilation
Guide complet pour compiler et flasher le firmware QMK sur le Moonlander
Pourquoi Compiler Soi-Même ?
Bien que ZSA propose Oryx (leur configurateur en ligne), compiler le firmware QMK directement offre plusieurs avantages :
- Accès à toutes les fonctionnalités avancées de QMK
- Possibilité d’ajouter du code personnalisé
- Contrôle total sur la configuration
- Apprentissage approfondi du fonctionnement
- Pas de limitation des couches ou fonctionnalités
🎯 Mon Objectif
Je voulais implémenter des fonctionnalités spécifiques comme des macros complexes pour mon workflow de développement et des combos personnalisés que Oryx ne permettait pas à l’époque.
Prérequis et Installation
Environnement de Développement
IMPORTANT : J’utilise exclusivement une machine Ubuntu 22.04. Oubliez Windows et sa merde – même avec WSL2 c’est galère. Prenez une vraie distribution basée sur Debian (Ubuntu, Debian, Mint, Pop!_OS) ou au pire macOS.
🚫 Windows = Problèmes Garantis
J’ai testé sur Windows 11 avec WSL2 : drivers USB foireux, permissions de merde, bugs aléatoires. Économisez-vous des heures de galère et utilisez un vrai OS Unix-like.
sudo apt update
sudo apt install git python3-pip
python3 -m pip install –user qmk
Clonage du dépôt (repository) QMK
git clone https://github.com/qmk/qmk_firmware.git
cd qmk_firmware
# Configuration initiale
qmk setup
🔗 Liens officiels
Repository QMK : https://github.com/qmk/qmk_firmware
Documentation : https://docs.qmk.fm/
⚠️ Attention Version
Assurez-vous d’utiliser une version stable de QMK. J’ai eu des problèmes avec certaines versions de développement qui cassaient la compilation pour le Moonlander. Vérifiez les releases sur GitHub.
Structure du projet Moonlander
Le Moonlander se trouve dans le dossier keyboards/moonlander/
avec cette structure :
├── config.h # Configuration matérielle
├── moonlander.c # Code spécifique au clavier
├── moonlander.h # Définitions des touches
├── rules.mk # Règles de compilation
└── keymaps/ # Configurations de touches
├── default/ # Configuration par défaut
├── via/ # Configuration pour VIA
└── mon_keymap/ # Ma configuration personnalisée
Création de Ma Configuration
mkdir keyboards/moonlander/keymaps/mon_keymap
cd keyboards/moonlander/keymaps/mon_keymap
# Copier la base depuis default
cp ../default/* .
Mon Processus de Développement
Étape 1 : Analyse des Besoins
J’ai d’abord analysé mes patterns de frappe pendant une semaine avec un keylogger pour identifier les touches et combinaisons les plus utilisées.
Étape 2 : Design des Layers
Création du schéma de mes couches sur papier avant de commencer le code, en optimisant pour mes besoins de développeur Python/JavaScript.
Étape 3 : Implémentation Progressive
Développement couche par couche, en testant chaque modification avant de passer à la suivante.
Étape 4 : Optimisation
Ajustements fins basés sur l’usage réel et l’ajout de fonctionnalités avancées.
Configuration de Base
Le fichier keymap.c
Voici la structure de base de mon fichier de configuration :
#include « version.h »
// Définition des couches
enum layers {
BASE, // Couche de base (Colemak-DH)
NAV, // Navigation et flèches
SYM, // Symboles et ponctuation
NUM, // Pavé numérique et fonctions
ADJ // Ajustements (RGB, reset, etc.)
};
// Définition des keycodes personnalisés
enum custom_keycodes {
RGB_SLD = ML_SAFE_RANGE,
MY_MACRO_1,
MY_MACRO_2
};
Gestion des Couches
J’utilise des Mod-Tap keys et des Layer-Tap keys pour un accès fluide :
MT(MOD_LSFT, KC_SPC)
// Layer-Tap : Couche NAV quand maintenu, Enter quand tapé
LT(NAV, KC_ENT)
// Hold-Tap avec timing personnalisé
LCTL_T(KC_ESC) // Ctrl maintenu, Escape tapé
Fonctionnalités Avancées Implémentées
Macros Personnalisées
J’ai créé des macros pour mes workflows de développement les plus fréquents :
switch (keycode) {
case MY_MACRO_1:
if (record->event.pressed) {
SEND_STRING(« console.log() » SS_TAP(X_LEFT));
}
break;
case MY_MACRO_2:
if (record->event.pressed) {
SEND_STRING(« git add . && git commit -m \ »\ » » SS_TAP(X_LEFT));
}
break;
}
return true;
}
Combos
Implémentation de combos pour des actions rapides :
const uint16_t PROGMEM combo_esc[] = {KC_Q, KC_W, COMBO_END};
const uint16_t PROGMEM combo_del[] = {KC_O, KC_P, COMBO_END};
combo_t key_combos[COMBO_COUNT] = {
COMBO(combo_esc, KC_ESC),
COMBO(combo_del, KC_DEL),
};
Leader Key Sequences
Séquences de touches inspirées de Vim pour des actions complexes :
void matrix_scan_user(void) {
LEADER_DICTIONARY() {
leading = false;
leader_end();
SEQ_ONE_KEY(KC_R) {
reset_keyboard();
}
SEQ_TWO_KEYS(KC_G, KC_C) {
SEND_STRING(« git commit -m \ »\ » » SS_TAP(X_LEFT));
}
}
}
Compilation et Flash
Commandes de Compilation
qmk compile -kb moonlander -km mon_keymap
# Compilation et flash en une fois
qmk flash -kb moonlander -km mon_keymap
# Compilation avec verbose pour debug
qmk compile -kb moonlander -km mon_keymap –verbose
Processus de Flash
Pour flasher le firmware sur le Moonlander :
1. Mise en Mode Bootloader
Appuyer sur le petit bouton reset à l’arrière du clavier ou utiliser la séquence de touches configurée.
2. Vérification du Device
Le clavier apparaît comme un device USB en mode DFU. Vérifier avec lsusb
sur Linux.
3. Flash du Firmware
La commande qmk flash
détecte automatiquement le clavier et lance le processus.
4. Redémarrage
Le clavier redémarre automatiquement avec la nouvelle configuration.
⚠️ Problèmes Courants
Si le flash échoue, vérifiez les permissions USB avec sudo usermod -a -G dialout $USER
et reconnectez-vous. Parfois il faut utiliser sudo
pour la première fois. Guide complet : QMK Linux udev rules
Debugging et Optimisation
Console de Debug
QMK offre une console de debug très utile pour le développement :
#define CONSOLE_ENABLE
# Dans le code, utiliser
dprintf(« Debug: Layer = %d\n », get_highest_layer(layer_state));
Monitoring en Temps Réel
qmk console
# Ou avec hid_listen
sudo hid_listen
Optimisation de la Mémoire
Le Moonlander a des limitations de mémoire. J’ai dû optimiser :
- Désactiver les fonctionnalités non utilisées dans rules.mk
- Réduire le nombre de RGB modes
- Optimiser les macros et combos
- Utiliser PROGMEM pour les données constantes
MOUSEKEY_ENABLE = no # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
AUDIO_ENABLE = no # Audio output
RGBLIGHT_ENABLE = yes # Enable WS2812 RGB underlight
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
Configuration Avancée
Fichier config.h Personnalisé
Mon fichier config.h avec les optimisations importantes :
// Timing optimisé pour les Mod-Tap
#define TAPPING_TERM 200
#define PERMISSIVE_HOLD
#define TAPPING_FORCE_HOLD
// Auto-shift pour les majuscules
#define AUTO_SHIFT_TIMEOUT 150
#define NO_AUTO_SHIFT_ALPHA
// Combos configuration
#define COMBO_COUNT 10
#define COMBO_TERM 40
// Leader key
#define LEADER_TIMEOUT 300
#define LEADER_PER_KEY_TIMING
// RGB optimization
#define RGBLIGHT_LIMIT_VAL 120
#define RGBLIGHT_HUE_STEP 10
#define RGBLIGHT_SAT_STEP 17
#define RGBLIGHT_VAL_STEP 17
Rules.mk Optimisé
BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
NKRO_ENABLE = yes # Enable N-Key Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow
AUDIO_ENABLE = yes # Audio output
AUTO_SHIFT_ENABLE = yes # Auto Shift
COMBO_ENABLE = yes # Key combos
LEADER_ENABLE = yes # Leader key sequences
Gestion des Versions
Git Workflow
J’ai créé un repository séparé pour ma configuration :
cd keyboards/moonlander/keymaps/mon_keymap
git init
git remote add origin https://github.com/mon-user/moonlander-config
# Workflow quotidien
git add .
git commit -m « Ajout macro pour debugging JavaScript »
git push origin main
Branches pour Expérimentations
git checkout -b feature/nouveau-layout
# … modifications …
git commit -m « Test nouveau layout Colemak-DH »
# Revenir à la config stable si problème
git checkout main
💡 Conseil Pro
Gardez toujours une version stable fonctionnelle ! Rien de pire que de casser sa config un vendredi soir et de ne plus pouvoir travailler le weekend.
Automatisation du Build
Script de Compilation
J’ai créé un script pour automatiser le processus :
# build.sh
set -e # Arrêter en cas d’erreur
echo « 🔧 Compilation du firmware Moonlander… »
# Nettoyer les builds précédents
qmk clean
# Compiler
qmk compile -kb moonlander -km mon_keymap
# Copier le fichier .bin vers un dossier de backup
cp moonlander_mon_keymap.bin ~/moonlander-firmwares/$(date +%Y%m%d_%H%M%S)_moonlander.bin
echo « ✅ Compilation terminée ! »
echo « 📁 Firmware sauvegardé dans ~/moonlander-firmwares/ »
Script de Flash Automatisé
# flash.sh
echo « 🚀 Flash du firmware Moonlander… »
# Compiler et flasher
qmk flash -kb moonlander -km mon_keymap
# Attendre que le clavier revienne
echo « ⏳ Attente du redémarrage du clavier… »
sleep 3
# Test rapide
echo « ✅ Flash terminé ! Testez votre clavier. »
GitHub Actions
Pour automatiser les builds sur GitHub :
name: Build Moonlander Firmware
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Install QMK
run: |
python3 -m pip install qmk
qmk setup -y
– name: Build firmware
run: qmk compile -kb moonlander -km mon_keymap
– name: Upload firmware
uses: actions/upload-artifact@v3
with:
name: moonlander-firmware
path: « *.bin »
🔗 Exemple Complet
Voir un exemple complet de CI/CD pour QMK : QMK Official Workflow
Tests et Validation
Procédure de Test
Avant chaque flash en production, je suis une procédure de test rigoureuse :
Test de Compilation
Vérifier que le firmware compile sans erreurs ni warnings
Test des Couches
Vérifier que chaque couche s’active correctement
Test des Macros
Valider toutes les macros et séquences personnalisées
Test d’Usage Réel
Session de programmation de 30 minutes minimum
Outils de Test
- QMK Configurator : Validation visuelle du layout
- Key Tester : Vérification que toutes les touches fonctionnent
- Via/Vial : Test rapide des modifications en live
- Custom script : Validation automatisée des macros
Troubleshooting
Problèmes Courants et Solutions
❌ Compilation Failed
- Vérifier la syntaxe du keymap.c
- Contrôler les #include
- Valider les enum et defines
❌ Flash Failed
- Vérifier les permissions USB
- Réessayer le mode bootloader
- Utiliser sudo si nécessaire
❌ Touches qui ne Répondent Pas
- Vérifier la matrix dans moonlander.h
- Contrôler les keycodes
- Tester avec un layout simple
❌ Macros Dysfonctionnelles
- Vérifier la syntaxe SEND_STRING
- Contrôler les delays
- Tester isolément
Recovery Procedures
1. Forcer le mode bootloader (bouton physique)
2. Flash un firmware de base connu fonctionnel
3. Identifier le problème dans la config personnalisée
4. Corriger et re-tester progressivement
Optimisations Avancées
Réduction de la Latence
Optimisations pour réduire la latence du clavier :
#define USB_POLLING_INTERVAL_MS 1 // Polling à 1000Hz
#define QMK_KEYS_PER_SCAN 4 // Limite le nombre de touches par scan
#define DEBOUNCE 5 // Réduire le debounce si pas de problème
Économie d’Énergie
Pour prolonger l’autonomie en mode sans fil :
#define RGBLIGHT_SLEEP // Éteindre RGB en veille
#define AUTO_SHIFT_TIMEOUT 150 // Réduire les timeouts
#define COMBO_TERM 40 // Timeout combos plus court
Personnalisation du Bootloader
void keyboard_post_init_user(void) {
rgblight_enable_noeeprom();
rgblight_sethsv_noeeprom(HSV_PURPLE);
wait_ms(500);
rgblight_sethsv_noeeprom(HSV_BLUE);
}
Performance et Monitoring
Analyse des Performances
Outils pour analyser les performances de votre firmware :
- Memory usage : Vérifier l’utilisation RAM/Flash
- Scan rate : Fréquence de scan de la matrice
- Latency testing : Mesurer la latence totale
- Power consumption : Monitoring de la consommation
qmk console –verbose # Debug détaillé
qmk doctor # Diagnostic de l’environnement
qmk list-keyboards # Liste des claviers supportés
Profiling du Code
static uint16_t timer;
void matrix_scan_user(void) {
timer = timer_read();
// … code à profiler …
if (timer_elapsed(timer) > 1) {
dprintf(« Slow operation: %dms\n », timer_elapsed(timer));
}
}
Documentation et Maintenance
Documentation de ma Config
J’ai créé une documentation complète pour ma configuration :
├── README.md # Documentation principale
├── CHANGELOG.md # Historique des modifications
├── keymap.c # Code principal
├── config.h # Configuration
├── rules.mk # Règles de compilation
├── diagrams/ # Schémas des layouts
└── backup/ # Versions précédentes
Routine de Maintenance
Hebdomadaire
Backup de la configuration actuelle, review des modifications
Mensuelle
Mise à jour QMK, optimisations basées sur l’usage
Trimestrielle
Review complète de la config, nouvelles fonctionnalités
Annuelle
Refonte majeure basée sur l’évolution des besoins
Leçons Apprises et Conseils
Erreurs à Éviter
- Ne pas tester suffisamment avant de flasher une grosse modification
- Oublier de sauvegarder la config qui marche
- Vouloir tout changer d’un coup au lieu d’y aller progressivement
- Négliger la documentation des modifications
- Ignorer les warnings de compilation
Bonnes Pratiques Développées
- Toujours commenter le code personnalisé
- Tester chaque fonctionnalité isolément
- Garder un changelog des modifications
- Avoir plusieurs versions de backup
- Documenter les keymaps avec des diagrammes
- Utiliser des branches Git pour les expérimentations
🎯 Conseil Final
La compilation QMK peut sembler intimidante au début, mais c’est un processus très logique. Commencez simple, ajoutez progressivement les fonctionnalités, et n’hésitez pas à consulter la documentation QMK qui est excellente.
Ressources et Communauté
Documentation Essentielle
- QMK Documentation : https://docs.qmk.fm/ – Guide officiel complet
- ZSA Support : https://blog.zsa.io/ – Documentation spécifique Moonlander
- QMK Discord : https://discord.gg/Uq7gcHh – Communauté très active pour l’aide
- r/olkb : https://reddit.com/r/olkb – Subreddit dédié aux claviers programmables
Outils Utiles
QMK Toolbox
Interface graphique pour flasher les firmwares
Télécharger QMK Toolbox
KLE
Keyboard Layout Editor pour visualiser les layouts
keyboard-layout-editor.com
QMK Configurator
Interface web pour générer des configurations
config.qmk.fm
Conclusion
Compiler son propre firmware QMK est un voyage passionnant qui ouvre des possibilités infinies de personnalisation. Ce processus m’a non seulement permis de créer un clavier parfaitement adapté à mes besoins, mais aussi de comprendre en profondeur le fonctionnement des claviers programmables.
Bénéfices Obtenus
- Contrôle total : Chaque aspect du clavier correspond exactement à mes besoins
- Évolutivité : Possibilité d’ajouter de nouvelles fonctionnalités à tout moment
- Apprentissage : Compréhension approfondie de QMK et des claviers mécaniques
- Communauté : Accès à une communauté passionnée et entraide
ROI du Temps Investi
Les 40+ heures investies dans l’apprentissage et la configuration se sont révélées être l’un des meilleurs investissements de productivité de ma carrière. Chaque jour, je gagne du temps et du confort grâce aux optimisations mises en place.
🚀 Pour Aller Plus Loin
La compilation n’est que le début. Dans l’article suivant, je détaille ma configuration finale avec tous les choix de design et les optimisations qui rendent mon workflow de développement si efficace.
Mon Setup Final
Après plusieurs mois d’itérations, j’ai obtenu un firmware parfaitement adapté à mes besoins de développeur. Le processus de compilation m’a permis de comprendre en profondeur le fonctionnement de QMK et d’implémenter des fonctionnalités impossibles avec les configurateurs graphiques.
Statistiques Finales
📊 Firmware
28KB utilisés / 32KB disponibles
85% de la mémoire flash utilisée
⌨️ Fonctionnalités
5 couches principales
12 macros personnalisées
8 combos optimisés
🎯 Performance
Latence < 1ms
1000Hz polling rate
N-Key Rollover complet
🔧 Maintenance
Update mensuelle
Backup automatique
CI/CD sur GitHub
Dans l’article suivant, je détaille ma configuration finale avec les choix de layout et les raisons derrière chaque décision.