漫步键圈 - 固件

nrf52-keyboard

Lotlab 开源固件,支持双模。
具体安装过程可参考 .travis.yml

环境

SDCC 用于编译 CH554
GCC 用于编译 NRF52832
nrfutil 用于生成DFU包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 安装git make和sdcc编译工具。
# 注意Ubuntu 18.04及之前的SDCC版本较旧,无法成功编译
sudo apt install git make sdcc

# 如果sdcc无法命令安装,可以手动安装
wget https://sourceforge.net/projects/sdcc/files/sdcc-linux-amd64/4.0.0/sdcc-4.0.0-amd64-unknown-linux2.5.tar.bz2 -O /tmp/sdcc-4.0.0-amd64-unknown-linux2.5.tar.bz2
tar xf /tmp/sdcc-4.0.0-amd64-unknown-linux2.5.tar.bz2 -C /tmp
sudo cp -r /tmp/sdcc-4.0.0/* /usr/local

# 下载GCC
wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2
# 解压gcc
tar xf gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2
# 将GCC移动到用户目录
mv gcc-arm-none-eabi-7-2018-q2-update/ ~/.local/
# 删除压缩包
rm gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2

sudo apt install python3 python3-pip
# 安装 nrfutil
pip3 install nrfutil

SDK

信驰达的文档中使用nRF5_SDK_15.3.0_59ac345

1
2
wget http://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v15.x.x/nRF5_SDK_15.3.0_59ac345.zip
unzip -q nRF5_SDK_15.3.0_59ac345.zip

代码

1
2
3
4
5
6
git clone https://github.com/Lotlab/nrf52-keyboard.git
git submodule init
git submodule update

# 等同于 --recurse-submodules 选项
git clone --recurse-submodules https://github.com/Lotlab/nrf52-keyboard.git

安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 构建配置文件
cp template/Makefile.posix.template template/Makefile.posix

# 指定gcc目录把所有 /user/local 换成 ~/.local
sed -i "s/\/usr\/local/~\/.local/g" template/Makefile.posix

# 复制SDK进工程
cp -r /tmp/sdk/nRF5_SDK_15.3.0_59ac345/* SDK/

# 重置TMK子模块
rm -r tmk/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0-tmk/
cd tmk/ && git reset --hard

# 回到工程根目录
cd ../

配置

config

新建 keyboard 子文件夹,配置 config.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// USB VID
#define VENDOR_ID 0x1209
// USB PID
#define PRODUCT_ID 0x0514

// 键盘省电参数
...

// 更改发射功率到+4dBm
#define HIGH_TX_POWER

// 不启用宏存储功能
//#define MACRO_STORAGE

// UART_RX口IO
#define UART_RXD 6
// UART_TX口IO
#define UART_TXD 7
  • 配置参考 keyboard/lkb-core/config.h
  • VID 作者ID不要和别的作者重复
  • PID 作者名下产品ID不要重复
  • 可根据实际使用情况调整键盘省电参数
  • 自动发射功率调整并不好用,高发射功率更稳定,尤其是在复杂无线设备环境里。
  • 不启用宏存储功能是为了在配置中写宏,如果启用宏存储
    keymap_plain.c 中定义的宏函数action_get_macro会导致编译报错
    也许有更好的宏配置方式。。。
  • USB串口RXUART_TXDTXUART_RXD

keymap

keymap_common.h
keymap_plain.c
基础键位映射可以通过qmkbuilder生成源代码
https://kbfirmware.com/
https://github.com/ruiqimao/qmkbuilder
https://git.code.tencent.com/lotkb/lotkb-builder

键值可以参考https://github.com/tmk/tmk_core/blob/master/doc/keycode.txt

https://github.com/BurningBright/nrf52-keyboard/tree/ergo88/keyboard/ergo88-left
https://github.com/BurningBright/nrf52-keyboard/tree/ergo88/keyboard/ergo88-right

layers

通过定义多层、默认层、开关层、瞬开层和透明按键,可以高度自定义键盘。
层从大到小遍历,在所有开启的层中,高优先级的层中的按键会覆盖掉低优先级层的按键。

layer: 0-31
on: { ON_PRESS | ON_RELEASE | ON_BOTH }

操作 描述 函数
开启层 指定层设置为开启 ACTION_LAYER_ON(layer, on)
关闭层 指定层设置为关闭 ACTION_LAYER_OFF(layer, on)
反转层状态 指定层的状态反转 ACTION_LAYER_TOGGLE(layer)
仅开启层 指定层设置为开启,并将其他所有层设置为关闭 ACTION_LAYER_SET_CLEAR(layer)
瞬开或按键 按住将指定层开启,松开后关闭;
快速按下松开则触发指定按键
ACTION_LAYER_TAP_KEY(layer, key)
瞬时开启 按住将指定层开启,松开后关闭 ACTION_LAYER_MOMENTARY(layer)
瞬时仅开启/清空层 按住仅开启指定层,松开后关闭所有层 ACTION_LAYER_SET_CLEAR(layer)

层状态默认层状态共同决定了一个层的开启状态。

层状态 默认层状态 层的实际状态
关闭 关闭 关闭
关闭 开启 开启
开启 关闭 开启
开启 开启 开启

键盘在启动时,会将第1层的默认层状态设置为开启。
所有的层(包括第1层)的层状态设置为关闭。
此时只有第一层保持开启,其他层都为关闭。

https://keyboard.lotlab.org/help
Keymap framework - how to define your keymap

macro

宏用于自定义一连串键盘操作

函数 描述
I() 设置每个按键之间的间隔时间
D() 按下某个键
U() 松开某个键
T() 按下并松开某个键
W() 等待指定时间(ms)
SM() 将当前修饰键状态暂存
RM() 将之前暂存的修饰键状态恢复
CM() 将所有修饰键状态设置为未按下

keymap_plain.c 中自定义宏执行函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
switch (id) {
case 0:
return (record->event.pressed ?
MACRO( I(0), T(H), T(E), T(L), T(L), W(255), T(O), END ) :
MACRO_NONE );
case 1:
return (record->event.pressed ?
MACRO( D(LALT), D(TAB), END ) :
MACRO( U(TAB), END ));
}
return MACRO_NONE;
}

构建

1
2
3
4
5
6
7
8
cd keyboard/lkb-core
make clean
# 生成引导
make bootloader -j
# 生成用于DFU升级的升级包
make package -j
# 生成USB固件
make ch554 -j

烧录

1
2
3
4
5
6
7
8
9
10
# 恢复
nrfjprog --family NRF52 --recover
# 擦除
nrfjprog --family NRF52 --eraseall
# 刷入设备程序,刷错会变砖。。。
nrfjprog --family NRF52 --program SDK/components/softdevice/s132/hex/s132_nrf52_6.1.1_softdevice.hex
# 刷入引导程序
nrfjprog --family NRF52 --program nrf52_bootloader.hex
# 重置
nrfjprog --family NRF52 --reset

手机APP nRF Connect 空中升级固件(设备名DfuTarg)
nrf52_kbd_4384d09c.zip

蓝牙键盘固件更新教程


LotKB固件编译移植指南
https://github.com/Lotlab/nrf52-keyboard

nRF52832 DFU空中升级
NRF52832 DFU功能
Nordic nRF51/nRF52开发环境搭建
Nordic nRF51/nRF52开发流程说明

BlueMicro_BLE

固件意外的好用,支持主从一体,在Mac、Linux上兼容性好。
虽然不是TMK,但也支持层、层操作、宏,自定义程度不比TMK差。

bootloader

由于PCB设计的时候占用21脚,如果烧录 Adafruit Feather nRF52 默认bootloader会导致左手第一行失效。
为了不飞线解决这个问题,需要自行修改bootloader源码,把reset针脚改掉。

NordicSemiconductor/nrfx
https://github.com/adafruit/Adafruit_nRF52_Bootloader

1
2
3
4
5
6
pip install intelhex
pip3 install --user adafruit-nrfutil

git clone https://github.com/adafruit/Adafruit_nRF52_Bootloader
cd Adafruit_nRF52_Bootloader
git submodule update --init

修改 nrfx/mdk/system_nrf52.c

1
2
3
4
// line:193
NRF_UICR->PSELRESET[0] = 4;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
NRF_UICR->PSELRESET[1] = 4;

编译

1
make BOARD=feather_nrf52832

得到合并 softdevice 和 bootloader 后的基础固件
feather_nrf52832_bootloader-0.3.2-170-g7b86264-dirty_s132_6.1.1.hex

安装

编译需要用到 Arduino
下载安装 Arduino IDE 1.8.xx

安装 BSP:

  1. Preferences附加开发板管理器网址 输入:
    https://www.adafruit.com/package_adafruit_index.json
  2. 重启 IDE
  3. 工具 -> 开发板 -> 开发板管理 中选择安装 Adafruit nRF52 by Adafruit

BSP 安装完成后,在 开发板 中选择 Adafruit Feather nRF52

安装过程中,如果出现 ARM GCC 安装失败
可以到ARM官网下载 gcc-arm-none-eabi-9-2019-q4-major-xxx 手动安装
MacOS解压目录: ~/Library/Arduino15/packages/adafruit/tools/arm-none-eabi-gcc/9-2019q4

bluefruit-nrf52-feather-learning-guide

配置

bsp设置

  • macOS : ~/Library/Arduino15/packages/adafruit/hardware/nrf52
  • Linux : ~/.arduino15/packages/adafruit/hardware/nrf52
  • Windows: %APPDATA%\Local\Arduino15\packages\adafruit\hardware\nrf52

修改 variants/feather_nrf52832/variant.h

1
2
3
// line:90
#define PIN_SERIAL_RX (0)
#define PIN_SERIAL_TX (0)

默认PIN_SERIAL_RX占用8针脚,会导致左第三行、右第六行失效。

https://github.com/adafruit/Adafruit_nRF52_Arduino

config

参考 firmware/keyboards 中的其他键盘目录结构,复制一份
由于 ERGO88,左右板针脚并不对称,需要把定义在 hardware_config.h 中的
MATRIX_ROW_PINSMATRIX_COL_PINSVBAT_PIN 迁移至 keyboard_config.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#ifndef  KEYBOARD_CONFIG_H
#define KEYBOARD_CONFIG_H
#include "hardware_config.h"

#define KEYBOARD_SIDE LEFT
#define DEVICE_NAME_R "ERGO88-R"
#define DEVICE_NAME_L "ERGO88-L"
#define DEVICE_NAME_M "ERGO88-M"

#define DEVICE_MODEL "ERGO88"
#define MANUFACTURER_NAME "Burningbright"


#if KEYBOARD_SIDE == RIGHT
#define KEYMAP( \
...
#else
#define KEYMAP( \
...
#endif

#define MATRIX_ROW_PINS { ... }
#define MATRIX_COL_PINS { ... }
#define VBAT_PIN 5

#endif /* KEYBOARD_CONFIG_H */

keymaps

HID键值可参考 firmware/hid_keycodes.h
高级键值可参考 firmware/advance_keycodes.h

firmware/keyboards/Ergo88/keymaps/3layer/keymap.h
定义层序号、键值别名、组合键值定义、宏值定义、函数名定义等

firmware/keyboards/Ergo88/keymaps/3layer/keymap.c 中定义具体映射

第一层 WINDOWS
基础按键 + 复制、粘贴、查找、选中一行

第二层 MACOS
WINDOWS的蒙板层,通过透明按键实现
交换GUI ALT 位置,重新定义复制、粘贴、查找、选中一行,兼容MacOS

第三层 功能层
亮度、音量、鼠标、小键盘、常用命令宏、层切换开关

https://github.com/BurningBright/BlueMicro_BLE/tree/ergo88/firmware/keyboards/Ergo88

构建

参数按以下层级排列,也可以用命令行交互输入
keyboard : keymap : part : model : version

1
2
3
cd BlueMicro_BLE/build/macos/
./build-macos Ergo88:3layer:left:feather52832:bluemicrov2_0c
./build-macos Ergo88:3layer:right:feather52832:bluemicrov2_0c

烧录

1
2
3
4
5
6
7
8
9
10
11
12
# 恢复
nrfjprog --family NRF52 --recover
# 擦除
nrfjprog --family NRF52 --eraseall
# softdevice + bootloader
nrfjprog --family NRF52 --program feather_nrf52832_bootloader-0.3.2-170-g7b86264-dirty_s132_6.1.1.hex
# application
nrfjprog --family NRF52 --program BlueMicro_BLE/output/Ergo88/Ergo88-feather52832-bluemicrov2_0c-3layer-right.hex
# valid
nrfjprog --family NRF52 --program BlueMicro_BLE/build/app_valid_setting_apply_nRF52832.hex
# 重置
nrfjprog --family NRF52 --reset

https://github.com/jpconstantineau/BlueMicro_BLE