Skip to content

Commit

Permalink
Asynchronous, robust serial protocol. (qmk#39)
Browse files Browse the repository at this point in the history
* bla personal ap2-c18 keymap.

* Bidirectional, asynchronous message-based communication with Shine.

- Requires a matching Shine version.
- Protocol is resiliant to loosing bytes during communication, chips won't lock
  waiting for bytes that aren't coming.
- Chips resynchronize in event of loosing a byte using a AA0D header.

Regressions:
- Key masking/locking doesn't work right now. (did it work before?)
- Not all user keymaps build against it.

* Clang-format + code to ease reducing speed of LED UART.

- Did clang-format --style=file -i on multiple files according to
  coding_conventions_c.md

- Added separate serial speed for IAP boot and Led communication, it's possible
  that reducing this to 9600 helped someone with faulty HW. With this code they
  can do it with simple replacing of a value.

* Main chip can set/clear foreground using a mask mechanism.

- Some preparations for selective colouring.

* Selective mask works - tested on capslock.

- Migrated personal keymaps to new status API.

* Clear the foreground colors to show profile when it's modified.

- Show example of achieving selective caps-lock painting + foreground painting
  for layers.
- annepro2LedMaskSetRow is implemented, but still requires testing.

* Implement the QMK side of led blinking to indicate the command was received.

- This stupidly blinks the key when user presses one of the bluetooth commands
to let the user know that the command was received and forwarded to the BT chip.

- TODO: Row/col key positions are hardcoded and not taken from the keymap.

* Reduce memory footprint.

Applying code review suggestions. Moved msgId to globals - preparing for
transmission without copying payload when no retries are necessary.

Added empty readme.md files - required by QMK lint.

Co-authored-by: Tomasz bla Fortuna <bla@thera.be>
  • Loading branch information
blaa and Tomasz bla Fortuna authored Jul 15, 2021
1 parent b19eaad commit 082600f
Show file tree
Hide file tree
Showing 19 changed files with 637 additions and 192 deletions.
89 changes: 53 additions & 36 deletions keyboards/annepro2/annepro2.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,31 @@
#include "annepro2_ble.h"
#include "spi_master.h"
#include "qmk_ap2_led.h"
#include "protocol.h"

static const SerialConfig ledUartConfig = {
.speed = 115200,
static const SerialConfig ledUartInitConfig = {
.speed = 115200,
};

static const SerialConfig bleUartConfig = {
.speed = 115200,
/*
* Some people have serial issues between main chip and led chip.
* This code allows them to easily reduce the speed to 9600 for testing
*/
static const SerialConfig ledUartRuntimeConfig = {
.speed = 115200,
};

static uint8_t ledMcuWakeup[11] = {
0x7b, 0x10, 0x43, 0x10, 0x03, 0x00, 0x00, 0x7d, 0x02, 0x01, 0x02
static const SerialConfig bleUartConfig = {
.speed = 115200,
};

static bool ledEnabled = false;
static uint8_t ledMcuWakeup[11] = {0x7b, 0x10, 0x43, 0x10, 0x03, 0x00, 0x00, 0x7d, 0x02, 0x01, 0x02};

ble_capslock_t BLECapsLock = {._dummy = {0}, .caps_lock = false};

uint16_t annepro2LedMatrix[MATRIX_ROWS * MATRIX_COLS] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};

void OVERRIDE bootloader_jump(void) {

// Send msg to shine to boot into IAP
sdPut(&SD0, CMD_LED_IAP);
annepro2SetIAP();

// wait for shine to boot into IAP
wait_ms(15);
Expand All @@ -42,7 +38,7 @@ void OVERRIDE bootloader_jump(void) {
wait_ms(15);

// Magic key to set keyboard to IAP
*((uint32_t*)0x20001ffc) = 0x0000fab2;
*((uint32_t *)0x20001ffc) = 0x0000fab2;

// Load the main MCU into IAP
__disable_irq();
Expand All @@ -54,19 +50,20 @@ void OVERRIDE keyboard_pre_init_kb(void) {
spi_init();
#endif
// Start LED UART
sdStart(&SD0, &ledUartConfig);
sdStart(&SD0, &ledUartInitConfig);
sdWrite(&SD0, ledMcuWakeup, 11);
// wait to receive response from wakeup
wait_ms(15);

protoInit(&proto, ledCommandCallback);

// loop to clear out receive buffer from shine wakeup
while(!sdGetWouldBlock(&SD0))
sdGet(&SD0);
while (!sdGetWouldBlock(&SD0)) sdGet(&SD0);

sdStart(&SD0, &ledUartRuntimeConfig);
}

void OVERRIDE keyboard_post_init_kb(void) {


// Start BLE UART
sdStart(&SD1, &bleUartConfig);
annepro2_ble_startup();
Expand All @@ -76,30 +73,34 @@ void OVERRIDE keyboard_post_init_kb(void) {
wait_ms(15);

// loop to clear out receive buffer from ble wakeup
while(!sdGetWouldBlock(&SD1))
sdGet(&SD1);
while (!sdGetWouldBlock(&SD1)) sdGet(&SD1);

annepro2LedGetStatus();

keyboard_post_init_user();
}

void OVERRIDE matrix_init_kb(void) {
matrix_init_user();
}
void OVERRIDE matrix_init_kb(void) { matrix_init_user(); }

void matrix_scan_kb() {
// if there's stuff on the ble serial buffer
// read it into the capslock struct
while(!sdGetWouldBlock(&SD1)) {
sdReadTimeout(&SD1, (uint8_t *) &BLECapsLock, sizeof(ble_capslock_t), 10);
while (!sdGetWouldBlock(&SD1)) {
sdReadTimeout(&SD1, (uint8_t *)&BLECapsLock, sizeof(ble_capslock_t), 10);

// if it's capslock from ble, darken led
if (BLECapsLock.caps_lock) {
annepro2LedClearMask(MATRIX_COLS * 2);
// annepro2LedClearMask(MATRIX_COLS * 2);
} else {
annepro2LedSetMask(MATRIX_COLS * 2);
// annepro2LedSetMask(MATRIX_COLS * 2);
}
}

/* While there's data from LED keyboard sent - read it. */
while (!sdGetWouldBlock(&SD0)) {
uint8_t byte = sdGet(&SD0);
protoConsume(&proto, byte);
}

matrix_scan_user();
}
Expand All @@ -109,25 +110,37 @@ void matrix_scan_kb() {
*/
bool OVERRIDE process_record_kb(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
if (AP2_LED_ENABLED && AP2_LED_DYNAMIC_PROFILE && !AP2_FOREGROUND_COLOR_SET) {
if (annepro2LedStatus.matrixEnabled && annepro2LedStatus.isReactive) {
annepro2LedForwardKeypress(record->event.key.row, record->event.key.col);
}

const annepro2Led_t blue = {
.p.blue = 0xff,
.p.red = 0x00,
.p.green = 0x00,
.p.alpha = 0xff,
};

switch (keycode) {
case KC_AP2_BT1:
annepro2_ble_broadcast(0);
/* FIXME: This hardcodes col/row position */
annepro2LedBlink(0, 1, blue, 8, 50);
return false;

case KC_AP2_BT2:
annepro2_ble_broadcast(1);
annepro2LedBlink(0, 2, blue, 8, 50);
return false;

case KC_AP2_BT3:
annepro2_ble_broadcast(2);
annepro2LedBlink(0, 3, blue, 8, 50);
return false;

case KC_AP2_BT4:
annepro2_ble_broadcast(3);
annepro2LedBlink(0, 4, blue, 8, 50);
return false;

case KC_AP2_USB:
Expand All @@ -140,31 +153,35 @@ bool OVERRIDE process_record_kb(uint16_t keycode, keyrecord_t *record) {

case KC_AP_LED_OFF:
annepro2LedDisable();
ledEnabled = false;
break;

case KC_AP_LED_ON:
if (ledEnabled) {
if (annepro2LedStatus.matrixEnabled) {
annepro2LedNextProfile();
} else {
ledEnabled = true;
annepro2LedEnable();
}
annepro2LedResetForegroundColor();
break;

case KC_AP_LED_NEXT_PROFILE:
annepro2LedNextProfile();
annepro2LedResetForegroundColor();
break;

case KC_AP_LED_PREV_PROFILE:
annepro2LedPrevProfile();
annepro2LedResetForegroundColor();
break;

case KC_AP_LED_NEXT_INTENSITY:
annepro2LedNextIntensity();
annepro2LedResetForegroundColor();
return false;

case KC_AP_LED_SPEED:
annepro2LedNextAnimationSpeed();
annepro2LedResetForegroundColor();
return false;

default:
Expand Down
4 changes: 2 additions & 2 deletions keyboards/annepro2/annepro2.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
#pragma once
#include "quantum.h"

#define OVERRIDE __attribute__ ((noinline))
#define OVERRIDE __attribute__((noinline))

typedef struct __attribute__((__packed__)) {
uint8_t _dummy[10];
bool caps_lock;
bool caps_lock;
} ble_capslock_t;

extern uint16_t annepro2LedMatrix[MATRIX_ROWS * MATRIX_COLS];
Expand Down
1 change: 1 addition & 0 deletions keyboards/annepro2/c15/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
AnnePro2, ANSI C15 version.
3 changes: 2 additions & 1 deletion keyboards/annepro2/c15/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ SRC = \
matrix.c \
hardfault_handler.c \
annepro2_ble.c \
qmk_ap2_led.c
qmk_ap2_led.c \
protocol.c

LAYOUTS +=

Expand Down
3 changes: 1 addition & 2 deletions keyboards/annepro2/c18/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,11 @@
// #define NO_DEBUG

/* disable print */
// #define NO_PRINTg
// #define NO_PRINT

/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
//#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION

1 change: 1 addition & 0 deletions keyboards/annepro2/c18/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
AnnePro2, ANSI C18 version.
3 changes: 2 additions & 1 deletion keyboards/annepro2/c18/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ SRC = \
matrix.c \
hardfault_handler.c \
annepro2_ble.c \
qmk_ap2_led.c
qmk_ap2_led.c \
protocol.c

ifeq ($(strip $(ANNEPRO2_EEPROM)), yes)
OPT_DEFS += -DANNEPRO2_EEPROM
Expand Down
2 changes: 2 additions & 0 deletions keyboards/annepro2/keymaps/bla/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Obins stock firmware has something similar to this already enabled, but disabled by default in QMK
#define PERMISSIVE_HOLD
Loading

0 comments on commit 082600f

Please sign in to comment.