qmk-keychron-q3-colemak-dh/keyboards/annepro2/protocol.h

126 lines
3.2 KiB
C

/*
* (c) 2021 by Tomasz bla Fortuna
* License: GPLv2
*
* This file is shared with the Shine firmware. Keep it in sync (and in the
* shine's clang formatting).
*/
#pragma once
#include <stdint.h>
#define PROTOCOL_SD SD0
enum {
/*
* Main -> LED
*/
/* Basic config */
CMD_LED_ON = 0x01,
CMD_LED_OFF = 0x02,
CMD_LED_SET_PROFILE = 0x03,
CMD_LED_NEXT_PROFILE = 0x04,
CMD_LED_PREV_PROFILE = 0x05,
CMD_LED_NEXT_INTENSITY = 0x06,
CMD_LED_NEXT_ANIMATION_SPEED = 0x07,
/* Masks */
/* Override a key color, eg. capslock */
CMD_LED_MASK_SET_KEY = 0x10,
/* Override all keys in a row with configurable colors */
CMD_LED_MASK_SET_ROW = 0x11,
/* Override all keys with single color (eg. foreground color) */
CMD_LED_MASK_SET_MONO = 0x12,
/* Reactive / status */
CMD_LED_GET_STATUS = 0x20,
CMD_LED_KEY_BLINK = 0x21,
CMD_LED_KEY_DOWN = 0x22,
CMD_LED_KEY_UP = 0x23, /* TODO */
CMD_LED_IAP = 0x24,
/* Manual color control */
CMD_LED_SET_MANUAL = 0x30,
CMD_LED_COLOR_SET_KEY = 0x31,
CMD_LED_COLOR_SET_ROW = 0x32,
CMD_LED_COLOR_SET_MONO = 0x33,
/* LED -> Main */
/* Payload with data to send over HID */
CMD_LED_DEBUG = 0x40,
/* Number of profiles, current profile, on/off state,
reactive flag, brightness, errors */
CMD_LED_STATUS = 0x41,
/* Set sticky key, meaning the key will light up even when LEDs are turned off */
CMD_LED_STICKY_SET_KEY = 0x50,
CMD_LED_STICKY_SET_ROW = 0x51,
CMD_LED_STICKY_SET_MONO = 0x52,
CMD_LED_STICKY_UNSET_KEY = 0x53,
CMD_LED_STICKY_UNSET_ROW = 0x54,
CMD_LED_STICKY_UNSET_ALL = 0x55,
};
/* 1 ROW * 14 COLS * 4B (RGBX) = 56 + header prefix. */
#define MAX_PAYLOAD_SIZE 64
/** Enum of the states used for the serial protocol finite-state automaton */
enum proto_state {
/* 2-byte initial start-of-message sync */
STATE_SYNC_1,
STATE_SYNC_2,
/* Waiting for command byte */
STATE_CMD,
/* Waiting for ID byte */
STATE_ID,
/* Waiting for payload size */
STATE_PAYLOAD_SIZE,
/* Reading payload until payload_position == payload_size */
STATE_PAYLOAD,
};
/* Buffer holding a single message */
typedef struct {
uint8_t command;
uint8_t msg_id;
uint8_t payload_size;
uint8_t payload[MAX_PAYLOAD_SIZE];
} message_t;
/* Internal protocol state */
typedef struct {
/* Callback to call upon receiving a valid message */
void (*callback)(const message_t *);
/* Number of read payload bytes */
uint8_t payload_position;
/* Current finite-state-automata state */
enum proto_state state;
uint8_t previous_id;
uint8_t errors;
/* Currently received message */
message_t buffer;
} protocol_t;
/* NOTE: This didn't work when defined on stack */
extern protocol_t proto;
/* Init state */
extern void proto_init(protocol_t *proto, void (*callback)(const message_t *));
/* Consume one byte and push state forward - might call the callback */
extern void proto_consume(protocol_t *proto, uint8_t byte);
/* Prolonged silence - reset state */
extern void proto_silence(protocol_t *proto);
/* Transmit message */
extern void proto_tx(uint8_t cmd, const unsigned char *buf, int payload_size, int retries);