Back to Qmk Firmware

Memo

keyboards/hhkb/yang/memo.md

4.05.9 KB
Original Source

Hardware Information

The YANG HHKB BLE controller design is similiar to hasu's controller. Most pins are compatiable.

MCU: ATmega32U4
Bluetooth: MDBT40 (nRF51822-based), with Adafruit Bluefruit LE UART Friend firmware.
Power: 3.3V
CPU Frequency: 8MHz
Bootloader: Lufa MassStorage

Pin usage

DescriptionHASU pin usageYANG mod changed
~KEY: Lo(0) when key is pressedPD7 input(with pullup)
Hysteresis: Hi(1) if key was pressedPB7 output
Row selector bit0PB0 output
Row selector bit1PB1 output
Row selector bit2PB2 output
Col selector bit0PB3 output
Col selector bit1PB4 output
Col selector bit2PB5 output
Key unablePB6 output
Switch powerPD4 outputPD6 output (PMOS FET)
Bluetooth UART RxPC4 inputPD2
Bluetooth UART TxPC5 outputPD3
Bluetooth powerPD5 output (low: power on)
LED 0PF4
LED 2PF1
LED 4PF0
Unused for PRO2PC6
Unused for PRO2PC7
Inner USB powerPF7

How to flash LUFA MassStorage bootloader on Linux

The FAT filesystem on Linux very often cannot flush the write cache, leading to broken firmware in the flash.

We can use dd to write to the virtual block storage directly to bypass the vfs layer.

dd if=FLASH.bin of=<path of virtual block device> seek=4

Skip 4 sectors because the default sector size of the virtual device and dd is 512 bytes and the emulated flash file starts at 5th sector.

How to find the path of the virtual block device

After the keyboard boots into flash mode, on Linux system you should be able to find the block device in dmesg logs.

For exmaple if you type

sudo dmesg

You should find something like

[357885.143593] usb 1-1.4: USB disconnect, device number 24
[357885.627740] usb 1-1.4: new full-speed USB device number 25 using xhci_hcd
[357885.729486] usb 1-1.4: New USB device found, idVendor=03eb, idProduct=1962, bcdDevice= 0.01
[357885.729492] usb 1-1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[357885.745620] SCSI subsystem initialized
[357885.746712] usb-storage 1-1.4:1.0: USB Mass Storage device detected
[357885.746818] scsi host0: usb-storage 1-1.4:1.0
[357885.746919] usbcore: registered new interface driver usb-storage
[357885.747689] usbcore: registered new interface driver uas
[357886.766755] scsi 0:0:0:0: Direct-Access     LUFA     Bootloader       0.00 PQ: 0 ANSI: 0
[357886.773216] scsi 0:0:0:0: Attached scsi generic sg0 type 0
[357886.777474] sd 0:0:0:0: [sdx] 134 512-byte logical blocks: (68.6 kB/67.0 KiB)
[357886.780300] sd 0:0:0:0: [sdx] Write Protect is off
[357886.780302] sd 0:0:0:0: [sdx] Mode Sense: 00 00 00 00
[357886.783113] sd 0:0:0:0: [sdx] Asking for cache data failed
[357886.783114] sd 0:0:0:0: [sdx] Assuming drive cache: write through
[357886.842676]  sdx:
[357886.859528] sd 0:0:0:0: [sdx] Attached SCSI removable disk

The sdx is the block device name and the full path is at /dev/sdx The above flash command will become

dd if=FLASH.bin of=/dev/sdx seek=4

Adafruit Bluefruit LE UART configuraton

The default baud rate used by the firmware is 76800 although adafruit do not recommend using higher baudrates than 9600 because the nRF51 UART can drop characters.

Double speed mode to get more accurate async reading because the F_CPU speed is 8MHz.

Power saving mode design

Power saving is only enabled when USB is detached and using battery power. Here we define several levels of power saving mode, each saves more power but takes longer to resume operation.

  1. Level 1: idle mode is activated after a short configurable time (MATRIX_POWER_SAVE_TIMEOUT_MS) MCU is put into sleep mode and only scan the matrix per 15ms. PORTB pins are set to input with pull-up to save power. Sensing PCB is powered down between scans.

  2. Level 2: after idling for longer (MATRIX_POWER_SAVE_TIMEOUT_L2_MS) we entry this state. Matrix scan is skipped until the time lapses 900ms.

  3. Level 3: sleep mode is activated after a longer timeout (MATRIX_POWER_SAVE_TIMEOUT_L3_MS) Bluetooth module is powered down.

Battery reading

VBAT is connected to AIN6 pin on the MDBT40 module and the AREF pin is the reference voltage. Doing a ADC with AT+HWDAC=6 will return the difference between VBAT and VREF.

It seems when fully charged the ADC read is 550. Likely VREF is 3311mV and the fully charged VBAT is thus 3861mV.

Enable battery service with AT+BLEBATTEN=1 first then we can update the battery level by using AT+BLEBATTVAL=%d

References