Bluetooth 4.2 firmware for the Mitosis keyboard
Branch: master
Clone or download
Pull request Compare This branch is 10 commits behind joric:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Bluetooth firmware for the Mitosis keyboard (right half runs Bluetooth client and Gazell host simultaneously)

Precompiled Firmware

Bluetosis firmware does NOT come with the softdevice because it would violate Nordic redistribution terms, download softdevice s130 2.0.1 from the Nordic site and flash it the same way as firmware (you need to do it just once).

All fimware updates and softdevice go for the right half of the Mitosis keyboard, left half should be held intact.

Default Layout (Mitosis-BT)

  • Press Adjust + to switch between three Bluetooth devices and a receiver
  • Press Fn + Adjust + to reset three corresponding Bluetooth devices or erase all bonds


ST-Link V2

To flash nRF modules, connect ST-LINK/V2 to the module programming pins (SWCLK, SWDIO, GND, 3.3V - top to bottom) and run this batch (windows 10):

@echo off
set path=C:\SDK\openocd-0.10.0-dev-00247-g73b676c\bin-x64;%path%
set file=%~dp0custom\iar\_build\nrf51822_xxac.hex
openocd -f interface/stlink-v2.cfg -f target/nrf51.cfg ^
-c init -c "reset halt" -c "flash write_image erase %file:\=/%" -c reset -c exit


This is basically an $1.80 STM32 board (STM32F103C8T6) that you can use as an ST-Link V2 replacement. You need to flash the programmer firmware (Blackmagic) first. It creates two virtual ports (GDB and UART for debugging) no OpenOCD needed.

  • set jumpers to 0-1 0-0, download Demonstrator GUI from ST-LINK, hook up UART adapter (RX - A9, TX - A10)
  • open blackmagic.bin, built with make clean && make PROBE_HOST=stlink, select 128K device, offset 0x08002000, hit Flash
  • set jumpers to 0-0 0-0, update USB drivers with zadig, hook up production board via SWD (SWCLK - A5, SWDIO - B14)
  • upload production firmware: arm-none-eabi-gdb --quiet --batch -ex "target extended-remote \\.\COM5" -ex "mon swdp_scan" -ex "att 1" –ex "load nrf51822_xxac.hex" –ex kill (considering COM5 is the first virtual port)
Flashing Bluepill board Uploading firmware Debugging firmware


There is a built in NRF_LOG in Nordic SDK but it doesn't work with GCC (probably no memory). I had to write a small drop-in replacement. In IAR you can try using NRF_LOG_ENABLED and NRF_LOG_USES_UART in sdk-config.h. Note that built in debugging has its own pin settings in sdk-config.h (not the ones that are in the custom_board.h).

Neither nRF51822 nor ST-Link V2 have SWO pin for printf (there is no tracing hardware in the nRF51 series), so I had to use UART. You only need ONE pin to print messages via UART (e.g. using Arduino IDE Serial Monitor). There are no free broken out pins on the Mitosis so I've used pin 19 (bottom right key) as TX_PIN_NUMBER and it worked.

Hook up a single UART RX pin at 115200 baud (currently pin 21, key S15 or S23). You will also need common GND and VCC to make it work. It doesn't really interfere much with the keyboard matrix so you can use any pin you want, just don't use the same pin for TX and RX to avoid feedback.

You can also use Blackmagic probe for debugging. It is actually the best because it has a built in UART (pin A3) on the second virtual COM port so you won't need another USB. I personally use Bluepill board with Blackmagic firmware as a programmer and a debugger and Putty with enabled local echo as a serial monitor.


Copy this repository to the nRF5_SDK_12/bluetosis folder.

Mind that symlink or junction won't work on Windows 10 for some reason (GCC Makefile error ... is a directory. stop).


Open .eww, hit Make, that's it. I'm using a single plate (reversed) version for the debug configuration (modules soldered to the top of the PCB), to build standard version remove COMPILE_REVERSED from defines.


Open nRF5_SDK_12/components/toolchain/gcc/Makefile.posix make sure that GNU_INSTALL_ROOT := /usr/, then:

sudo apt install openocd gcc-arm-none-eabi
cd nRF5_SDK_12
git clone && cd bluetosis
cd firmware/custom/armgcc && make

Working GCC linker settings for softdevice s130 2.0.1 and YJ-14015 modules (256K ROM, 16K RAM) appear to be:

  FLASH (rx) : ORIGIN = 0x1b000, LENGTH = 0x25000
  RAM (rwx) :  ORIGIN = 0x20002000, LENGTH = 0x2000

To build with this settings, set stack and heap to 1024 or something in gcc_startup_nrf51.S (originally 2048). You could also use Makefile defines:


Firmware merging

You can also merge Bluetooth softdevice with Bluetooth firmware using mergehex utility from nRF5x Command Line Tools:

mergehex.exe -m s130_nrf51_2.0.1_softdevice.hex nrf51822_xxac.hex -o out.hex

But it's much faster and more convenient to flash softdevice just once and do frequent firmware updates.



  • Bluetooth and Gazell timesharing
  • Battery level reporting via Bluetooth
  • Debugging via UART
  • Basic QMK layout support
  • Bluetooth pairing shortcut
  • Switching between RF and Bluetooth modes
  • Switching between Bluetooth devices


  • Full QMK/TMK suport (maybe)

QMK support is still in progress (firmware compiles fine without QMK)

QMK firwmare has massive incompatibility issues with ICCARM (IAR) that can't be fixed with preprocessor. So it's either a fully-GCC setup (armgcc and maybe uVision Keil) or patching QMK (changes are small but I don't know if they ever get merged to the upstream). I've patched and compiled QMK for ICCARM but couldn't get correct keycodes so far.

QMK incompatibility issues

  • Excessive and unnecessary binary literals (e.g. 0b011 is C++14 only), should use hex or decimals
  • GCC-specific switch case ranges (case A ... Z, ), should use if and else
  • GCC-specific __attribute__ keyword, e.g. __attribute__ ((weak)), should use __WEAK define
  • Inplace initializations (#define MACRO(...) ({static const macro_t __m[]; PROGMEM={__VA_ARGS__}; &__m[0]}))

Patching QMK for IAR

  • add #ifdef __ICCARM__ for IAR-specific code
  • add __attribute__(x)= to the preprocessor directives, use __weak or whatever instead
  • add dummy Atmel-specific variables and functions PORTF, PORTD, etc.

QMK embedding guide

  • add QMK_KEYBOARD_H="your_hardware_name.h" to the preprocessor directives
  • add #include "keyboard.h", add QMK paths (quantum/, tmk_core/common/, etc.)
  • implement timer_read32() if it's incompatible (e.g. use app_timer_cnt_get for nrf5x)
  • implement matrix_row_t matrix_get_row(uint8_t row) callback (just read from array)
  • implement host driver callbacks, add host_set_driver(&driver) to the init sequence
  • add keyboard_task() to the main loop

See this GCC-only TMK core-based project for example (all API calls are precisely the same):



  • ST-LINK/V2: $2.54, had in stock (you can also use $1.80 STM32 board instead).
  • YJ-14015: nrf51822 modules, 3 pcs: $10.5 ($3.50 * 3), free shipping, need 2/3, so $7.
  • 10 main PCB's from EasyEDA, $13.32 ($2 + $11.32 for trackable shipping), used 4/10, so $5.32.
  • 3 receiver PCB's from OshPark, $5.40, free shipping, used only 1/3, so $1.80.
  • Arduino Pro Micro from Aliexpress (price varies from $2.54 to $4), had in stock.
  • Si2302 mosfets: board survives reverse polarity for a while, you may just short the pads.
  • ASMB-MTB1-0A3A2 from Aliexpress (or Cree CLVBA-FKA, or 3 single LEDs, very optional)
  • AMS1117: 5v to 3v regulator, had in stock. You probably can use diodes for 2v drop.
  • 1206 4.7k resistor arrays, 2 pcs: had in stock (taken from an old motherboard).
  • Switches and caps: most of you have more than you can handle.


  • Keyboard: $12.32 ($7 + $5.32) and I got enough PCBs to build 3 and they can reuse receiver.
  • Receiver: $7.84 ($3.50 + $1.80 + $2.54) firmware upgrade to ble and you wouldn't need it at all.

So, about $20 for a single keyboard.

PCB Manufacturers


There were speculations that Core 51822 has 32 GPIO pins available, so it's possible to make an Atreus62 without using a keyboard matrix. It is not true. GPIO 26/27 are shared by the 32kHz crystal and there are only 31 GPIOs hence PIN31 is not existing. So you could only have 29 keys on each side (58 total) if you manage to layout them without crossing.

Pins that can be used for side autodetection: 16 (L_S16), 18 (L_S22) (left-only pins); 22 (R_S22), 25 (R_S16) (right-only pins). There are 5 unused pins on each side (6 with LEDs): 11, 12, 20, 22, 25 (left, LED pin 23); 11, 12, 16, 18, 20 (right, LED pin 17).

Mitosis PCB


Mitosis Clones

Other wireless solutions

Bluetooth UART service

There are a few split keyboards that successfully run Bluetooth HID and Bluetooth UART service concurrently. Most of them use Adafruit nRF52 library and simple sketches written and compiled in Arduino IDE.

Arduino nRF5

There is Arduino-nRF5 by Sandeep Mistry that supports nRF51. You could use arduino-BLEPeripheral library for sketches. Works fine with BLE400 board (Arduino IDE setup, wiring). Sadly this library has multiple issues with Windows 10.

Arduino nRF52

Note that Arduino nRF52 builds (usually based on Bluefruit nRF52 boards) are NOT compatible with the Mitosis keyboard (softdevice s132 and all the software is nRF52-only, Mitosis is nRF51-based).


This is a drop-in Pro Micro replacement that is compatible with Arduino nRF52 boards (it's NOT compatible with nRF51). BlueMicro is open source, official repositories are BlueMicro_BLE (firmware) and NRF52-Board (hardware).