[Tradução/adaptação] Como fazer o firmware para seu teclado – parte 2

By | 21/11/2017

Autor: matt3o
Artigo original: https://deskthority.net/viewtopic.php?f=7&t=7177&start=#p141386

Bem-vindo à parte 2 de “Como fazer o firmware para seu teclado”! Leia a parte 1 primeiro se ainda não tiver feito isso.

Isso pode parecer difícil num primeiro momento mas se você seguir estas instruções passo a passo perceberá que é mais difícil explicar do que fazer.

Nós ainda estamos no diretório keyboard/gh60. Tudo o que precisamos está aqui. Agora nós iremos personalizar a matriz do teclado propriamente falando e suas camadas de função (FN).

Definindo a matriz

Antes de mais nada nós precisamos mapear a matriz no arquivo keymap_common.h.

A parte que precisamos é esta:

#define KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, \
    K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \
    K40, K41, K42,           K45,                K49, K4A, K4B, K4C, K4D  \
) { \
    { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D }, \
    { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D }, \
    { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D }, \
    { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D }, \
    { KC_##K40, KC_##K41, KC_##K42, KC_NO,    KC_NO,    KC_##K45, KC_NO,    KC_NO,    KC_NO,    KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D }  \
}

Lembre-se que aqui estamos vendo um exemplo (de um teclado 60%, para ser mais específico). O esquema do seu arquivo deve refletir a matriz do seu teclado, ou seja, a forma como os botões estão conectados.

Vejamos a primeira linha:

K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D,

Isto significa que todos os botões da primeira linha estão todos conectados em conjunto. Se você precisar de mais teclas você pode continuar adicionando mais posições, por exemplo:

K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, K0F,

Aqui eu adicionei duas novas teclas na primeira linha (K0E e K0F). Lembre-se de adicionar , \ (vírgula + barra invertida) no fim de cada linha.

Você tem que repetir esta mesma configuração de teclas no bloco de código seguinte.

{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D }, \

Como você pode ver é a mesma coisa que fizemos mais acima, porém com uma sintaxe um pouco diferente.

Agora olhemos para a última linha:

K40, K41, K42,           K45,                K49, K4A, K4B, K4C, K4D \

Desta vez nós temos um salto de K42 para K45. A linha inferior de um teclado  normalmente possui menos teclas que as demais e há um buraco entre a tecla ALT e a barra de espaço. Tome cuidado ao checar em qual coluna cada botão está respectivamente conectado.

{ KC_##K40, KC_##K41, KC_##K42, KC_NO,    KC_NO,    KC_##K45, KC_NO,    KC_NO,    KC_NO,    KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D }  \

No segundo bloco de código nós temos que identificar os espaços vazios com o código KC_NO. Então, enquanto que no primeiro bloco nós simplesmente pulávamos de uma coluna para outra se não há conexão física presente, no segundo bloco nós precisamos preencher o vazio com KC_NO.

Como exemplo, veja a matriz do HHFox (talvez seja melhor você copiar o código abaixo e colar num editor de texto).

#define KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, \
    K10,      K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, \
    K20,      K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C,      K2E, \
    K30,           K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, K3E, \
         K41,      K43,                     K48,           K4B, K4C            \
) { \
    { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E }, \
    { KC_##K10, KC_NO   , KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E }, \
    { KC_##K20, KC_NO   , KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_NO   , KC_##K2E }, \
    { KC_##K30, KC_NO   , KC_NO   , KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E }, \
    { KC_NO   , KC_##K41, KC_NO   , KC_##K43, KC_NO   , KC_NO   , KC_NO   , KC_NO   , KC_##K48, KC_NO,    KC_NO   , KC_##K4B, KC_##K4C, KC_NO   , KC_NO    }  \
}

Isso reflete exatamente a matriz feita à mão. É um pouco chato escrever isso tudo mas não é nada complexo. Apenas tenha cuidado na hora de anotar as letras e números para não cometer nenhum erro.

Você pode ignorar completamente a parte que tem o código KEYMAP_ANSI.

Mapa de teclas

E finalmente a parte divertida! Por padrão o arquivo Makefile está compilando o mapa de teclas do teclado Poker então, no intuito de simplificar as coisas, iremos modificar este arquivo. Abra o arquivo keymap_poker.c.

Apague tudo e substitua com isto:

#include "keymap_common.h"

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {

};

const uint16_t PROGMEM fn_actions[] = {

};

Primeiro temos de fazer a lista do mapa de teclas. O primeiro elemento da lista será o nosso mapa de teclas principal (QWERTY ou outro que você queira). Você pode copiar/colar um mapa de teclas já pronto ou começar do zero. Em nosso exemplo, o mapa de teclas básico será o seguinte:

    KEYMAP(ESC,  1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, GRV, BSLS, \
           TAB,  Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSPC,      \
           LCTL, A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,ENT,            \
           LSFT, Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,RSFT,  FN0,          \
           LALT, FN1,           SPC,                     PAUS,RALT),

Note que esta é apenas uma lista de caracteres da esquerda para a direita assim como você as vê no teclado. Você não precisa adicionar espaços, barras invertidas ou códigos especiais, mas nós os colocamos apenas para tornar o código mais legível. Tecnicamente, entretanto, tudo isso poderia estar em apenas uma linha.

Basicamente apenas leia os caracteres de seu teclado da esquerda para a direita, de cima para baixo.

O mapa de teclas para o HHFox se pareceria com algo assim:

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    /* 0: qwerty */
    KEYMAP(ESC,  1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, GRV, BSLS, \
           TAB,  Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSPC,      \
           LCTL, A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,ENT,            \
           LSFT, Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,RSFT,FN0,            \
           LALT, FN1,           SPC,                     PAUS,RALT),
};

Se você quiser ser capaz de reprogramar o firmware sem precisar acessar o botão de reset do Teensy, é melhor você incluir a tecla PAUS, e ela deve estar na primeira camada (e não numa camada FN).

Camadas de Função

Teclas de Função são definidas com a sintaxe FNx, onde x é um número de 0 a 5.

Para adicionar uma camada de função você precisa apenas acrescentar um novo mapa de teclas à lista. O código a seguir é a primeira camada FN do HHFox.

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    /* 0: qwerty */
    KEYMAP(ESC,  1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, GRV, BSLS, \
           TAB,  Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSPC,      \
           LCTL, A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,ENT,            \
           LSFT, Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,RSFT,FN0,            \
           LALT, FN1,           SPC,                     PAUS,FN2),

    /* 1: FN 1 */
    KEYMAP(MUTE, F1,   F2,   F3,   F4,   F5,   F6,   F7,   F8,   F9,   F10,  F11,  F12,  VOLU, VOLD, \
           TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, PGUP, UP,   TRNS, DEL,  \
           TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, MYCM, TRNS, TRNS, PGDN, LEFT, RGHT, TRNS,  \
           TRNS, TRNS, TRNS, CALC, TRNS, TRNS, TRNS, TRNS, HOME, END,  DOWN, TRNS, TRNS, \
           LGUI, TRNS,             TRNS,                   PSCR, RCTL),
};

Mesma coisa que falei antes, a única diferença é que nós usamos a palavra-chave TRNS (transparente) para todas as teclas que não mudam de comportamento quando a tecla de função é pressionada.

Até agora nós apenas definimos a camada de função, para realmente ativá-la nós precisamos acrescentar algo à lista fn_action

const uint16_t PROGMEM fn_actions[] = {
    [0] = ACTION_LAYER_MOMENTARY(1),
};

Isso significa que a tecla FN[0] irá acionar a camada (1) com uma ação ACTION_LAYER_MOMENTARY. Você pode definir muitas ações, as mais comuns/úteis são:

    • ACTION_LAYER_MOMENTARY(camada), aciona a camada enquanto a tecla FN estiver pressionada
    • ACTION_LAYER_TOGGLE(camada), ativa a camada no primeiro pressionamento, desativa no segundo
  • ACTION_LAYER_TAP_KEY(camada, tecla), funciona como ACTION_LAYER_MOMENTARY enquanto você a pressiona, mas executa a tecla especificada quando faz apenas um tap (pressionamento/soltura rápidos)

Vamos acrescentar uma ação tap ao HHFox.

const uint16_t PROGMEM fn_actions[] = {
  [0] = ACTION_LAYER_MOMENTARY(1),
  [1] = ACTION_LAYER_TAP_KEY(1, KC_ESC),
};

Pressionando a tecla FN1 nós ativamos a primeira camada de função (assim como FN0), mas ao fazer um tap na mesma tecla nós temos como resultado a tecla ESC. Maneiro, não é? Obrigado por isto, Hasu.

O restante seria o último mapa de teclas para o HHFox (este é apenas um exemplo, não a minha configuração atual de teclas). Eu tomei a liberdade de adicionar uma segunda camada de função que é ativada ao pressionar a tecla FN2.

#include "keymap_common.h"

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* 0: qwerty */
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, GRV, BSLS, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
LCTL, A, S, D, F, G, H, J, K, L, SCLN,QUOT,ENT, \
LSFT, Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT, FN0, \
LALT, FN1, SPC, PAUS,RALT),

/* 1: FN 1 */
KEYMAP(MUTE, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, VOLU, VOLD, \
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, PGUP, UP, TRNS, DEL, \
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, MYCM, TRNS, TRNS, PGDN, LEFT, RGHT, TRNS, \
TRNS, TRNS, TRNS, CALC, TRNS, TRNS, TRNS, TRNS, HOME, END, DOWN, TRNS, TRNS, \
LGUI, TRNS, TRNS, PSCR, RCTL),

/* 2: FN 2 */
KEYMAP(MUTE, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, VOLU, VOLD, \
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, PGUP, UP, TRNS, DEL, \
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, MYCM, TRNS, TRNS, PGDN, LEFT, RGHT, TRNS, \
TRNS, TRNS, TRNS, CALC, TRNS, TRNS, TRNS, TRNS, HOME, END, DOWN, TRNS, TRNS, \
LGUI, TRNS, TRNS, PSCR, SLEP),
};
const uint16_t PROGMEM fn_actions[] = {
[0] = ACTION_LAYER_MOMENTARY(1),
[1] = ACTION_LAYER_TAP_KEY(1, KC_ESC),
[2] = ACTION_LAYER_TOGGLE(2)
};

Que bonito, que beleza, que alegria! Nós acabamos!

Preparar; Apontar; Compilar!

Feche o arquivo. Abra o terminal, vá para o diretório gh60 e execute:

make -f Makefile

Se você tiver feito tudo certo, ao final da compilação terá um arquivo chamado gh60_lufa.hex.

Conecte seu teclado à porta USB. No Linux você não precisa fazer mais nada, tudo já deverá estar funcionando. No Mac e no Windows você provavelmente terá de fazer uma rápida instalação.

Quando tudo estiver pronto, execute o Teensy Loader, acione o botão “Auto”, carregue o firmware (o arquivo hex) e aperte o botão reset no Teensy. O firmware será carregado e o teclado começará a funcionar em seguida!

Correção de problemas

Agora um dos seguintes cenários pode acontecer:

Tudo está bem e seu teclado está funcionando de cara

Legal! Você é um mestre dos teclados!

O teclado começa a disparar caracteres aleatórios na tela e o computador começa a bipar

Desconecte o teclado, rápido! Isso provavelmente é um problema de software. Confira novamente seu código. Quando estiver pronto para recarregar, abra o seu novo firmware no Teensy Loader, reconecte o teclado e rapidamente aperte o botão de reset.

O teclado funciona mas algumas teclas estão com defeito

Isso é muito provavelmente um problema de hardware. Confira sua fiação e veja se não há curtos-circuitos.

Eu montei meu teclado e não tenho acesso ao botão de reset de hardware

Assumindo que seu teclado esteja funcionando corretamente, você pode fazer um reset de software pressionando LSHIFT + RSHIFT + PAUSE.

Tudo parece funcionar mas algumas teclas modificadoras retornam a tecla errada

Desconecte o teclado e reconecte-o segurando a tecla BACKSPACE.

Isso é tudo, pessoal. Obrigado por lerem este guia. Se tiverem qualquer problema não tenha medo de perguntar no fórum.