mirror of
https://github.com/qmk/qmk_firmware.git
synced 2026-10-02 06:49:16 +02:00
Add persistent led support with eeprom (#9)
* adding HT32 support to chibios SPI master driver * add support for W25X20CL SPI eeprom * add makefile flag for eeprom feature * add spi support to keyboard startup and config * example keymap using eeprom profile loading
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include "hal.h"
|
||||
#include "annepro2.h"
|
||||
#include "annepro2_ble.h"
|
||||
#include "spi_master.h"
|
||||
#include "qmk_ap2_led.h"
|
||||
|
||||
static const SerialConfig ledUartConfig = {
|
||||
@@ -26,6 +27,9 @@ uint16_t annepro2LedMatrix[MATRIX_ROWS * MATRIX_COLS] = {
|
||||
};
|
||||
|
||||
void OVERRIDE keyboard_pre_init_kb(void) {
|
||||
#if HAL_USE_SPI == TRUE
|
||||
spi_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void OVERRIDE keyboard_post_init_kb(void) {
|
||||
@@ -33,10 +37,21 @@ void OVERRIDE keyboard_post_init_kb(void) {
|
||||
sdStart(&SD0, &ledUartConfig);
|
||||
sdWrite(&SD0, ledMcuWakeup, 11);
|
||||
|
||||
// wait to receive response from wakeup
|
||||
wait_ms(15);
|
||||
|
||||
// loop to clear out receive buffer from shine wakeup
|
||||
while(!sdGetWouldBlock(&SD0))
|
||||
sdGet(&SD0);
|
||||
|
||||
// Start BLE UART
|
||||
sdStart(&SD1, &bleUartConfig);
|
||||
annepro2_ble_startup();
|
||||
|
||||
// Give the send uart thread some time to
|
||||
// send out the queue before we read back
|
||||
wait_ms(5);
|
||||
|
||||
keyboard_post_init_user();
|
||||
}
|
||||
|
||||
@@ -77,20 +92,21 @@ bool OVERRIDE process_record_kb(uint16_t keycode, keyrecord_t *record) {
|
||||
case KC_AP_LED_OFF:
|
||||
annepro2LedPrevProfile();
|
||||
annepro2LedDisable();
|
||||
return false;
|
||||
break;
|
||||
|
||||
case KC_AP_LED_ON:
|
||||
annepro2LedNextProfile();
|
||||
annepro2LedEnable();
|
||||
return false;
|
||||
break;
|
||||
|
||||
case KC_AP_LED_NEXT_PROFILE:
|
||||
annepro2LedNextProfile();
|
||||
return false;
|
||||
break;
|
||||
|
||||
case KC_AP_LED_PREV_PROFILE:
|
||||
annepro2LedPrevProfile();
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -60,6 +60,31 @@
|
||||
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
|
||||
#define DEBOUNCE 5
|
||||
|
||||
#if defined(ANNEPRO2_EEPROM)
|
||||
// SPI Config
|
||||
#define SPI_DRIVER SPID1
|
||||
#define SPI_SCK_PIN A0
|
||||
#define SPI_SCK_PAL_MODE 5
|
||||
#define SPI_MOSI_PIN A1
|
||||
#define SPI_MOSI_PAL_MODE 5
|
||||
#define SPI_MISO_PIN A2
|
||||
#define SPI_MISO_PAL_MODE 5
|
||||
// EEPROM Config for W25X20CL
|
||||
#define EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN A3
|
||||
#define EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR 16
|
||||
#define EXTERNAL_EEPROM_BYTE_COUNT 1024 // 262144
|
||||
#define EXTERNAL_EEPROM_PAGE_SIZE 256
|
||||
#define EXTERNAL_EEPROM_ADDRESS_SIZE 3
|
||||
#define EXTERNAL_EEPROM_SPI_LSBFIRST false
|
||||
#define EXTERNAL_EEPROM_SPI_MODE 3
|
||||
// HAL Config
|
||||
#define HAL_USE_SPI TRUE
|
||||
#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
|
||||
// MCU Config
|
||||
#define HT32_SPI_USE_SPI1 TRUE
|
||||
#define HT32_SPI1_IRQ_PRIORITY 9
|
||||
#endif
|
||||
|
||||
/* number of backlight levels */
|
||||
// #define BACKLIGHT_LEVELS 10
|
||||
|
||||
|
||||
@@ -5,6 +5,11 @@ SRC = \
|
||||
annepro2_ble.c \
|
||||
qmk_ap2_led.c
|
||||
|
||||
ifeq ($(strip $(ANNEPRO2_EEPROM)), yes)
|
||||
OPT_DEFS += -DANNEPRO2_EEPROM
|
||||
SRC += spi_master.c eeprom_w25x20cl.c
|
||||
endif
|
||||
|
||||
LAYOUTS +=
|
||||
|
||||
# MCU
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
/* Copyright 2020 Nick Brassel (tzarc) and tech2077
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
Note that the implementations of eeprom_XXXX_YYYY on AVR are normally
|
||||
provided by avr-libc. The same functions are reimplemented below and are
|
||||
rerouted to the external SPI equivalent.
|
||||
|
||||
Seemingly, as this is compiled from within QMK, the object file generated
|
||||
during the build overrides the avr-libc implementation during the linking
|
||||
stage.
|
||||
|
||||
On other platforms such as ARM, there are no provided implementations, so
|
||||
there is nothing to override during linkage.
|
||||
*/
|
||||
|
||||
#include "wait.h"
|
||||
#include "spi_master.h"
|
||||
#include "eeprom.h"
|
||||
#include "eeprom_w25x20cl.h"
|
||||
|
||||
#define CMD_WREN 0x06u
|
||||
#define CMD_WRDI 0x04u
|
||||
#define CMD_RDSR 0x05u
|
||||
#define CMD_WRSR 0x01u
|
||||
#define CMD_READ 0x03u
|
||||
#define CMD_WRITE 0x02u
|
||||
#define CMD_SECTOR_ERASE 0x20u
|
||||
|
||||
#define SR_WIP 0x01u
|
||||
|
||||
// #define DEBUG_EEPROM_OUTPUT
|
||||
|
||||
#ifndef EXTERNAL_EEPROM_SPI_TIMEOUT
|
||||
# define EXTERNAL_EEPROM_SPI_TIMEOUT 100
|
||||
#endif
|
||||
|
||||
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
|
||||
# include "timer.h"
|
||||
# include "debug.h"
|
||||
#endif // CONSOLE_ENABLE
|
||||
|
||||
bool spi_eeprom_start(void) {
|
||||
return spi_start(EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN, EXTERNAL_EEPROM_SPI_LSBFIRST, EXTERNAL_EEPROM_SPI_MODE, EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR);
|
||||
}
|
||||
|
||||
static spi_status_t spi_eeprom_wait_while_busy(int timeout) {
|
||||
uint32_t deadline = timer_read32() + timeout;
|
||||
spi_status_t response;
|
||||
spi_write(CMD_RDSR);
|
||||
do {
|
||||
response = spi_read();
|
||||
if (timer_read32() >= deadline) {
|
||||
return SPI_STATUS_TIMEOUT;
|
||||
}
|
||||
} while ((uint16_t)response & SR_WIP);
|
||||
return SPI_STATUS_SUCCESS;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void eeprom_erase(uint32_t addr) {
|
||||
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
|
||||
uint32_t start = timer_read32();
|
||||
#endif
|
||||
|
||||
spi_eeprom_start();
|
||||
spi_write(CMD_WREN);
|
||||
spi_stop();
|
||||
|
||||
spi_eeprom_start();
|
||||
spi_write(CMD_SECTOR_ERASE);
|
||||
spi_write((uint8_t)((addr & 0xFF0000u) >> 16u));
|
||||
spi_write((uint8_t)((addr & 0x00FF00u) >> 8u));
|
||||
spi_write((uint8_t)((addr & 0x0000FFu)));
|
||||
spi_stop();
|
||||
|
||||
spi_eeprom_start();
|
||||
spi_status_t response = spi_eeprom_wait_while_busy(10000);
|
||||
spi_stop();
|
||||
if (response == SPI_STATUS_TIMEOUT) {
|
||||
dprint("SPI timeout for WIP check\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
|
||||
dprintf("EEPROM erase took %ldms to complete\n", ((long)(timer_read32() - start)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void eeprom_read(void *buf, uint32_t addr, size_t len) {
|
||||
//-------------------------------------------------
|
||||
// Wait for the write-in-progress bit to be cleared
|
||||
bool res = spi_eeprom_start();
|
||||
if (!res) {
|
||||
dprint("failed to start SPI for WIP check\n");
|
||||
spi_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
spi_status_t response = spi_eeprom_wait_while_busy(EXTERNAL_EEPROM_SPI_TIMEOUT);
|
||||
spi_stop();
|
||||
if (response == SPI_STATUS_TIMEOUT) {
|
||||
dprint("SPI timeout for WIP check\n");
|
||||
spi_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Perform read
|
||||
res = spi_eeprom_start();
|
||||
if (!res) {
|
||||
dprint("failed to start SPI for read\n");
|
||||
spi_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
spi_write(CMD_READ);
|
||||
spi_write((uint8_t)((addr & 0xFF0000u) >> 16u));
|
||||
spi_write((uint8_t)((addr & 0x00FF00u) >> 8u));
|
||||
spi_write((uint8_t)((addr & 0x0000FFu)));
|
||||
spi_receive(buf, len);
|
||||
spi_stop();
|
||||
|
||||
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
|
||||
dprintf("[EEPROM R] 0x%08lX: ", (addr));
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
dprintf(" %02X", (int)(((uint8_t *)buf)[i]));
|
||||
}
|
||||
dprintf("\n");
|
||||
#endif // DEBUG_EEPROM_OUTPUT
|
||||
|
||||
}
|
||||
|
||||
void eeprom_write(const void *buf, uint32_t addr, size_t len) {
|
||||
eeprom_erase(addr);
|
||||
|
||||
//-------------------------------------------------
|
||||
// Enable writes
|
||||
bool res = spi_eeprom_start();
|
||||
if (!res) {
|
||||
dprint("failed to start SPI for write-enable\n");
|
||||
spi_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
spi_write(CMD_WREN);
|
||||
spi_stop();
|
||||
|
||||
wait_us(1);
|
||||
|
||||
//-------------------------------------------------
|
||||
// Perform the write
|
||||
res = spi_eeprom_start();
|
||||
if (!res) {
|
||||
dprint("failed to start SPI for write\n");
|
||||
spi_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
|
||||
dprintf("[EEPROM W] 0x%08lX: ", ((uint32_t)(uintptr_t)addr));
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
dprintf(" %02X", (int)(uint8_t)(buf[i]));
|
||||
}
|
||||
dprintf("\n");
|
||||
#endif // DEBUG_EEPROM_OUTPUT
|
||||
|
||||
spi_write(CMD_WRITE);
|
||||
spi_write((uint8_t)((addr & 0xFF0000u) >> 16u));
|
||||
spi_write((uint8_t)((addr & 0x00FF00u) >> 8u));
|
||||
spi_write((uint8_t)((addr & 0x0000FFu)));
|
||||
spi_transmit(buf, len);
|
||||
spi_stop();
|
||||
|
||||
res = spi_eeprom_start();
|
||||
if (!res) {
|
||||
dprint("failed to start SPI for status\n");
|
||||
spi_stop();
|
||||
return;
|
||||
}
|
||||
spi_status_t response = spi_eeprom_wait_while_busy(EXTERNAL_EEPROM_SPI_TIMEOUT);
|
||||
spi_stop();
|
||||
if (response == SPI_STATUS_TIMEOUT) {
|
||||
dprint("SPI timeout for WIP check\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/* Copyright 2020 Nick Brassel (tzarc) and tech2077
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void eeprom_erase(uint32_t addr);
|
||||
void eeprom_read(void *buf, uint32_t addr, size_t len);
|
||||
void eeprom_write(const void *buf, uint32_t addr, size_t len);
|
||||
|
||||
/*
|
||||
The slave select pin of the EEPROM.
|
||||
This needs to be a normal GPIO pin_t value, such as A7.
|
||||
*/
|
||||
#ifndef EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN
|
||||
# error "No chip select pin defined -- missing EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN"
|
||||
#endif
|
||||
|
||||
/*
|
||||
The clock divisor for SPI to ensure that the MCU is within the
|
||||
specifications of the EEPROM chip. Generally this will be PCLK divided by
|
||||
the intended divisor -- check your clock settings and the datasheet of
|
||||
your EEPROM.
|
||||
*/
|
||||
#ifndef EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR
|
||||
# ifdef __AVR__
|
||||
# define EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR 8
|
||||
# else
|
||||
# define EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR 64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
The SPI mode to communicate with the EEPROM.
|
||||
*/
|
||||
#ifndef EXTERNAL_EEPROM_SPI_MODE
|
||||
# define EXTERNAL_EEPROM_SPI_MODE 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
Whether or not the SPI communication between the MCU and EEPROM should be
|
||||
LSB-first.
|
||||
*/
|
||||
#ifndef EXTERNAL_EEPROM_SPI_LSBFIRST
|
||||
# define EXTERNAL_EEPROM_SPI_LSBFIRST false
|
||||
#endif
|
||||
|
||||
/*
|
||||
The total size of the EEPROM, in bytes. The EEPROM datasheet will usually
|
||||
specify this value in kbits, and will require conversion to bytes.
|
||||
*/
|
||||
#ifndef EXTERNAL_EEPROM_BYTE_COUNT
|
||||
# define EXTERNAL_EEPROM_BYTE_COUNT 8192
|
||||
#endif
|
||||
|
||||
/*
|
||||
The page size in bytes of the EEPROM, as specified in the datasheet.
|
||||
*/
|
||||
#ifndef EXTERNAL_EEPROM_PAGE_SIZE
|
||||
# define EXTERNAL_EEPROM_PAGE_SIZE 32
|
||||
#endif
|
||||
|
||||
/*
|
||||
The address size in bytes of the EEPROM. For EEPROMs with <=256 bytes, this
|
||||
will likely be 1. For EEPROMs >256 and <=65536, this will be 2. For EEPROMs
|
||||
>65536, this will likely need to be 4.
|
||||
|
||||
As expected, consult the datasheet for specifics of your EEPROM.
|
||||
*/
|
||||
#ifndef EXTERNAL_EEPROM_ADDRESS_SIZE
|
||||
# define EXTERNAL_EEPROM_ADDRESS_SIZE 2
|
||||
#endif
|
||||
@@ -0,0 +1,206 @@
|
||||
#include "annepro2.h"
|
||||
#include <stdint.h>
|
||||
#include <print.h>
|
||||
#include <string.h>
|
||||
#include "qmk_ap2_led.h"
|
||||
#include "eeprom_w25x20cl.h"
|
||||
|
||||
// layout using eeprom and bidir-comms to keep user led settings persistent
|
||||
|
||||
// eeprom memory layout
|
||||
typedef union {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint8_t magic : 8;
|
||||
bool leds_on : 1;
|
||||
uint8_t leds_profile : 8;
|
||||
};
|
||||
} user_config_t;
|
||||
|
||||
// define out default user_config
|
||||
user_config_t user_config = {.magic = 0xDE, .leds_on = 0, .leds_profile = 0};
|
||||
|
||||
// keep the number of profiles so we can track along with the shine proc
|
||||
uint8_t numProfiles = 0;
|
||||
|
||||
static uint8_t usb_buf[256];
|
||||
static uint8_t buf_fil = 0;
|
||||
|
||||
enum anne_pro_layers {
|
||||
_BASE_LAYER,
|
||||
_FN1_LAYER,
|
||||
_FN2_LAYER,
|
||||
};
|
||||
|
||||
/*
|
||||
* Layer _BASE_LAYER
|
||||
* ,-----------------------------------------------------------------------------------------.
|
||||
* | esc | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | Bksp |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Tab | q | w | e | r | t | y | u | i | o | p | [ | ] | \ |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Caps | a | s | d | f | g | h | j | k | l | ; | ' | Enter |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Shift | z | x | c | v | b | n | m | , | . | / | Shift |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Ctrl | GUI | Alt | space | GUI | ALT | FN1 | Ctrl |
|
||||
* \-----------------------------------------------------------------------------------------/
|
||||
* Layer TAP in _BASE_LAYER
|
||||
* ,-----------------------------------------------------------------------------------------.
|
||||
* | | | | | | | | | | | | | | |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | | | | | | | | | | | | | | |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | | | | | | | | | | | | | |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | | | | | | | | | | | | UP |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | | | | | | LEFT | DOWN | RIGHT |
|
||||
* \-----------------------------------------------------------------------------------------/
|
||||
*/
|
||||
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[_BASE_LAYER] = KEYMAP(/* Base */
|
||||
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
|
||||
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
|
||||
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, RSFT_T(KC_UP),
|
||||
KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, LT(KC_RALT, KC_LEFT), LT(_FN1_LAYER, KC_DOWN), RCTL_T(KC_RGHT)),
|
||||
/*
|
||||
* Layer _FN1_LAYER
|
||||
* ,-----------------------------------------------------------------------------------------.
|
||||
* | ` | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | DELETE |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Tab | q | UP | e | r | t | y | u | i | o | PS | HOME | END | \ |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Esc |LEFT |DOWN |RIGHT| f | g | h | j | k | l | PGUP|PGDN | Enter |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Shift |V-UP |V-DWN|MUTE | v | b | n | m | , |INSRT| DEL | Shift |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Ctrl | L1 | Alt | space | Alt | FN2 | FN1 | Ctrl |
|
||||
* \-----------------------------------------------------------------------------------------/
|
||||
*
|
||||
*/
|
||||
[_FN1_LAYER] = KEYMAP(/* Base */
|
||||
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL,
|
||||
KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_HOME, KC_END, KC_TRNS,
|
||||
MO(_FN2_LAYER), KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_PGDN, KC_TRNS,
|
||||
KC_TRNS, KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_INS, KC_DEL, KC_TRNS,
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FN2_LAYER), KC_TRNS, KC_TRNS),
|
||||
/*
|
||||
* Layer _FN2_LAYER
|
||||
* ,-----------------------------------------------------------------------------------------.
|
||||
* | ~ | BT1 | BT2 | BT3 | BT4 | F5 | F6 | F7 |LEDOF|LEDON| F10 | F11 | F12 | Bksp |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Tab | q | UP | e | r | t | y | u | i | o | PS | HOME | END | \ |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Esc |LEFT |DOWN |RIGHT| f | g | h | j | k | l | PGUP|PGDN | Enter |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Shift | z | x | c | v | b | n | m | , |INSRT| DEL | Shift |
|
||||
* |-----------------------------------------------------------------------------------------+
|
||||
* | Ctrl | L1 | Alt | space | Alt | FN2 | FN1 | Ctrl |
|
||||
* \-----------------------------------------------------------------------------------------/
|
||||
*
|
||||
*/
|
||||
[_FN2_LAYER] = KEYMAP(/* Base */
|
||||
KC_TRNS, KC_AP2_BT1, KC_AP2_BT2, KC_AP2_BT3, KC_AP2_BT4, KC_TRNS, KC_TRNS, KC_TRNS, KC_AP_LED_OFF, KC_AP_LED_ON, KC_AP_LED_NEXT_PROFILE, KC_TRNS, KC_TRNS, KC_TRNS,
|
||||
MO(_FN2_LAYER), KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_HOME, KC_END, KC_TRNS,
|
||||
KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_PGDN, KC_TRNS,
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_INS, KC_DEL, KC_TRNS,
|
||||
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FN2_LAYER), MO(_FN1_LAYER), KC_TRNS),
|
||||
};
|
||||
const uint16_t keymaps_size = sizeof(keymaps);
|
||||
|
||||
void matrix_init_user(void)
|
||||
{
|
||||
}
|
||||
|
||||
void matrix_scan_user(void)
|
||||
{
|
||||
}
|
||||
|
||||
layer_state_t layer_state_set_user(layer_state_t layer)
|
||||
{
|
||||
return layer;
|
||||
}
|
||||
|
||||
void raw_hid_receive(uint8_t *data, uint8_t length) {
|
||||
uprintf("raw_hid len: %u\n", length);
|
||||
if (length == 1)
|
||||
annepro2LedSetProfile(data[0]);
|
||||
else {
|
||||
for (uint8_t i = 0; i < length; i++){
|
||||
usb_buf[buf_fil + i] = data[i];
|
||||
}
|
||||
buf_fil += length;
|
||||
if (buf_fil >= 211) {
|
||||
sdWrite(&SD0, usb_buf, 211);
|
||||
buf_fil = 0;
|
||||
}
|
||||
// for (int i = 0; i < length; i++) {
|
||||
// sdPut(&SD0, data[i]);
|
||||
// sdGet(&SD0);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @returns false processing for this keycode has been completed.
|
||||
*/
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t* record)
|
||||
{
|
||||
switch (keycode) {
|
||||
case KC_AP_LED_OFF:
|
||||
if (record->event.pressed) {
|
||||
user_config.leds_on = false;
|
||||
eeprom_write((void*)&user_config, 0, sizeof(user_config_t));
|
||||
}
|
||||
return false;
|
||||
case KC_AP_LED_ON:
|
||||
if (record->event.pressed) {
|
||||
user_config.leds_on = true;
|
||||
eeprom_write((void*)&user_config, 0, sizeof(user_config_t));
|
||||
}
|
||||
return false;
|
||||
case KC_AP_LED_NEXT_PROFILE:
|
||||
if (record->event.pressed) {
|
||||
user_config.leds_profile = (user_config.leds_profile + 1) % numProfiles;
|
||||
annepro2LedSetProfile(user_config.leds_profile);
|
||||
eeprom_write((void*)&user_config, 0, sizeof(user_config_t));
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void keyboard_post_init_user(void)
|
||||
{
|
||||
// Customize these values to desired behavior
|
||||
debug_enable = true;
|
||||
//debug_matrix = true;
|
||||
//debug_keyboard=true;
|
||||
//debug_mouse=true;
|
||||
|
||||
// Read the user config from EEPROM
|
||||
eeprom_read((void*)&user_config, 0, sizeof(user_config_t));
|
||||
|
||||
// initialize a new eeprom
|
||||
if (user_config.magic != 0xDE)
|
||||
{
|
||||
user_config.magic = 0xDE;
|
||||
user_config.leds_on = false;
|
||||
user_config.leds_profile = 0;
|
||||
eeprom_write((void*)&user_config, 0, sizeof(user_config_t));
|
||||
}
|
||||
|
||||
numProfiles = annepro2LedGetNumProfiles();
|
||||
|
||||
if (user_config.leds_on) {
|
||||
// send profile before so that we don't get a flicker on startup
|
||||
annepro2LedSetProfile(user_config.leds_profile);
|
||||
annepro2LedEnable();
|
||||
} else {
|
||||
annepro2LedDisable();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
# Anne Pro 2
|
||||
SRC = \
|
||||
matrix.c \
|
||||
hardfault_handler.c \
|
||||
annepro2_ble.c \
|
||||
qmk_ap2_led.c
|
||||
|
||||
LAYOUTS +=
|
||||
|
||||
# MCU
|
||||
MCU = cortex-m0plus
|
||||
ARMV = 6
|
||||
USE_FPU = no
|
||||
MCU_FAMILY = HT32
|
||||
MCU_SERIES = HT32F523x2
|
||||
MCU_LDSCRIPT = HT32F52342_ANNEPRO2
|
||||
MCU_STARTUP = ht32f523x2
|
||||
|
||||
BOARD = ANNEPRO2_C18
|
||||
|
||||
OPT_DEFS = -Wno-unused-function -fdump-rtl-dfinish -fstack-usage
|
||||
#EXTRALDFLAGS = -Wl,--print-memory-usage
|
||||
|
||||
# Options
|
||||
|
||||
# Keys
|
||||
CUSTOM_MATRIX = yes
|
||||
NKRO_ENABLE = no
|
||||
MOUSEKEY_ENABLE = no
|
||||
EXTRAKEY_ENABLE = yes
|
||||
KEY_LOCK_ENABLE = no
|
||||
|
||||
# Other featues
|
||||
BOOTMAGIC_ENABLE = no
|
||||
CONSOLE_ENABLE = yes
|
||||
COMMAND_ENABLE = yes
|
||||
DEBUG_EEPROM = yes
|
||||
RAW_ENABLE = no
|
||||
MIDI_ENABLE = no
|
||||
VIRTSER_ENABLE = no
|
||||
COMBO_ENABLE = no
|
||||
ANNEPRO2_EEPROM = yes
|
||||
|
||||
ifeq ($(strip $(ANNEPRO2_EEPROM)), yes)
|
||||
OPT_DEFS += -DANNEPRO2_EEPROM
|
||||
SRC += spi_master.c eeprom_w25x20cl.c
|
||||
endif
|
||||
@@ -38,9 +38,13 @@ __attribute__((weak)) void spi_init(void) {
|
||||
|
||||
chThdSleepMilliseconds(10);
|
||||
#if defined(USE_GPIOV1)
|
||||
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), SPI_SCK_PAL_MODE);
|
||||
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), SPI_MOSI_PAL_MODE);
|
||||
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_PAL_MODE);
|
||||
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
|
||||
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
|
||||
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
|
||||
#elif defined(HT32_SPI_USE_SPI1) || defined(HT32_SPI_USE_SPI2)
|
||||
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_HT32_MODE_AF(SPI_SCK_PAL_MODE) | PAL_MODE_OUTPUT_PUSHPULL);
|
||||
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_HT32_MODE_AF(SPI_MOSI_PAL_MODE) | PAL_MODE_OUTPUT_PUSHPULL);
|
||||
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_HT32_MODE_AF(SPI_MISO_PAL_MODE) | PAL_MODE_OUTPUT_PUSHPULL);
|
||||
#else
|
||||
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
|
||||
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
|
||||
@@ -63,60 +67,36 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(K20x) || defined(KL2x)
|
||||
spiConfig.tar0 = SPIx_CTARn_FMSZ(7) | SPIx_CTARn_ASC(1);
|
||||
#if defined(HT32_SPI_USE_SPI1) || defined(HT32_SPI_USE_SPI2)
|
||||
spiConfig.cr0 = SPI_CR0_SELOEN;
|
||||
spiConfig.cr1 = SPI_CR1_MODE | 8; // 8 bits and in master mode
|
||||
|
||||
if (lsbFirst) {
|
||||
spiConfig.tar0 |= SPIx_CTARn_LSBFE;
|
||||
spiConfig.cr1 |= SPI_CR1_FIRSTBIT;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
spiConfig.tar0 |= SPIx_CTARn_CPHA;
|
||||
break;
|
||||
case 2:
|
||||
spiConfig.tar0 |= SPIx_CTARn_CPOL;
|
||||
break;
|
||||
case 3:
|
||||
spiConfig.tar0 |= SPIx_CTARn_CPHA | SPIx_CTARn_CPOL;
|
||||
break;
|
||||
case 0:
|
||||
spiConfig.cr1 |= SPI_CR1_FORMAT_MODE0;
|
||||
break;
|
||||
case 1:
|
||||
spiConfig.cr1 |= SPI_CR1_FORMAT_MODE1;
|
||||
break;
|
||||
case 2:
|
||||
spiConfig.cr1 |= SPI_CR1_FORMAT_MODE2;
|
||||
break;
|
||||
case 3:
|
||||
spiConfig.cr1 |= SPI_CR1_FORMAT_MODE3;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (roundedDivisor) {
|
||||
case 2:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(0);
|
||||
break;
|
||||
case 4:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(1);
|
||||
break;
|
||||
case 8:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(3);
|
||||
break;
|
||||
case 16:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(4);
|
||||
break;
|
||||
case 32:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(5);
|
||||
break;
|
||||
case 64:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(6);
|
||||
break;
|
||||
case 128:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(7);
|
||||
break;
|
||||
case 256:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(8);
|
||||
break;
|
||||
}
|
||||
spiConfig.cpr = (roundedDivisor - 1) >> 1;
|
||||
#else
|
||||
spiConfig.cr1 = 0;
|
||||
|
||||
if (lsbFirst) {
|
||||
spiConfig.cr1 |= SPI_CR1_LSBFIRST;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user