1
0
Fork 0

Merge branch 'master' into debounce_refactor

# Conflicts:
#	tmk_core/common/keyboard.c
This commit is contained in:
Alex Ong 2019-01-04 19:43:45 +11:00
commit 2bb2977c13
3425 changed files with 216380 additions and 20651 deletions

View file

@ -120,7 +120,7 @@ void process_hand_swap(keyevent_t *event) {
}
#endif
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
bool disable_action_cache = false;
void process_record_nocache(keyrecord_t *record)
@ -773,6 +773,13 @@ void register_code(uint8_t code)
else if IS_CONSUMER(code) {
host_consumer_send(KEYCODE2CONSUMER(code));
}
#ifdef MOUSEKEY_ENABLE
else if IS_MOUSEKEY(code) {
mousekey_on(code);
mousekey_send();
}
#endif
}
/** \brief Utilities for actions. (FIXME: Needs better description)
@ -832,6 +839,24 @@ void unregister_code(uint8_t code)
else if IS_CONSUMER(code) {
host_consumer_send(0);
}
#ifdef MOUSEKEY_ENABLE
else if IS_MOUSEKEY(code) {
mousekey_off(code);
mousekey_send();
}
#endif
}
/** \brief Utilities for actions. (FIXME: Needs better description)
*
* FIXME: Needs documentation.
*/
void tap_code(uint8_t code) {
register_code(code);
#if TAP_CODE_DELAY > 0
wait_ms(TAP_CODE_DELAY);
#endif
unregister_code(code);
}
/** \brief Utilities for actions. (FIXME: Needs better description)
@ -873,10 +898,19 @@ void clear_keyboard(void)
* FIXME: Needs documentation.
*/
void clear_keyboard_but_mods(void)
{
clear_keys();
clear_keyboard_but_mods_and_keys();
}
/** \brief Utilities for actions. (FIXME: Needs better description)
*
* FIXME: Needs documentation.
*/
void clear_keyboard_but_mods_and_keys()
{
clear_weak_mods();
clear_macro_mods();
clear_keys();
send_keyboard_report();
#ifdef MOUSEKEY_ENABLE
mousekey_clear();

View file

@ -62,7 +62,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);
bool process_record_quantum(keyrecord_t *record);
/* Utilities for actions. */
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
extern bool disable_action_cache;
#endif
@ -88,11 +88,13 @@ void process_record(keyrecord_t *record);
void process_action(keyrecord_t *record, action_t action);
void register_code(uint8_t code);
void unregister_code(uint8_t code);
void tap_code(uint8_t code);
void register_mods(uint8_t mods);
void unregister_mods(uint8_t mods);
//void set_mods(uint8_t mods);
void clear_keyboard(void);
void clear_keyboard_but_mods(void);
void clear_keyboard_but_mods_and_keys(void);
void layer_switch(uint8_t new_layer);
bool is_tap_key(keypos_t key);

View file

@ -15,13 +15,22 @@
*/
uint32_t default_layer_state = 0;
/** \brief Default Layer State Set At user Level
*
* FIXME: Needs docs
*/
__attribute__((weak))
uint32_t default_layer_state_set_user(uint32_t state) {
return state;
}
/** \brief Default Layer State Set At Keyboard Level
*
* FIXME: Needs docs
*/
__attribute__((weak))
uint32_t default_layer_state_set_kb(uint32_t state) {
return state;
return default_layer_state_set_user(state);
}
/** \brief Default Layer State Set
@ -35,7 +44,11 @@ static void default_layer_state_set(uint32_t state)
default_layer_debug(); debug(" to ");
default_layer_state = state;
default_layer_debug(); debug("\n");
#ifdef STRICT_LAYER_RELEASE
clear_keyboard_but_mods(); // To avoid stuck keys
#else
clear_keyboard_but_mods_and_keys(); // Don't reset held keys
#endif
}
/** \brief Default Layer Print
@ -118,7 +131,11 @@ void layer_state_set(uint32_t state)
layer_debug(); dprint(" to ");
layer_state = state;
layer_debug(); dprintln();
#ifdef STRICT_LAYER_RELEASE
clear_keyboard_but_mods(); // To avoid stuck keys
#else
clear_keyboard_but_mods_and_keys(); // Don't reset held keys
#endif
}
/** \brief Layer clear
@ -219,7 +236,7 @@ void layer_debug(void)
}
#endif
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}};
void update_source_layers_cache(keypos_t key, uint8_t layer)
@ -263,7 +280,7 @@ uint8_t read_source_layers_cache(keypos_t key)
*/
action_t store_or_get_action(bool pressed, keypos_t key)
{
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
if (disable_action_cache) {
return layer_switch_get_action(key);
}

View file

@ -31,6 +31,8 @@ void default_layer_set(uint32_t state);
__attribute__((weak))
uint32_t default_layer_state_set_kb(uint32_t state);
__attribute__((weak))
uint32_t default_layer_state_set_user(uint32_t state);
#ifndef NO_ACTION_LAYER
/* bitwise operation */
@ -80,15 +82,13 @@ void layer_xor(uint32_t state);
#define layer_or(state)
#define layer_and(state)
#define layer_xor(state)
__attribute__((weak))
uint32_t layer_state_set_user(uint32_t state);
__attribute__((weak))
uint32_t layer_state_set_kb(uint32_t state);
#endif
uint32_t layer_state_set_user(uint32_t state);
uint32_t layer_state_set_kb(uint32_t state);
/* pressed actions cache */
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
/* The number of bits needed to represent the layer number: log2(32). */
#define MAX_LAYER_BITS 5
void update_source_layers_cache(keypos_t key, uint8_t layer);

View file

@ -0,0 +1,51 @@
/* Copyright 2017 Fred Sundvik
*
* 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 "bootloader.h"
#include "samd51j18a.h"
#include "md_bootloader.h"
//Set watchdog timer to reset. Directs the bootloader to stay in programming mode.
void bootloader_jump(void) {
#ifdef KEYBOARD_massdrop_ctrl
//CTRL keyboards released with bootloader version below must use RAM method. Otherwise use WDT method.
uint8_t ver_ram_method[] = "v2.18Jun 22 2018 17:28:08"; //The version to match (NULL terminated by compiler)
uint8_t *ver_check = ver_ram_method; //Pointer to version match string for traversal
uint8_t *ver_rom = (uint8_t *)0x21A0; //Pointer to address in ROM where this specific bootloader version would exist
while (*ver_check && *ver_rom == *ver_check) { //While there are check version characters to match and bootloader's version matches check's version
ver_check++; //Move check version pointer to next character
ver_rom++; //Move ROM version pointer to next character
}
if (!*ver_check) { //If check version pointer is NULL, all characters have matched
*MAGIC_ADDR = BOOTLOADER_MAGIC; //Set magic number into RAM
NVIC_SystemReset(); //Perform system reset
while (1) {} //Won't get here
}
#endif
WDT->CTRLA.bit.ENABLE = 0;
while (WDT->SYNCBUSY.bit.ENABLE) {}
while (WDT->CTRLA.bit.ENABLE) {}
WDT->CONFIG.bit.WINDOW = 0;
WDT->CONFIG.bit.PER = 0;
WDT->EWCTRL.bit.EWOFFSET = 0;
WDT->CTRLA.bit.ENABLE = 1;
while (WDT->SYNCBUSY.bit.ENABLE) {}
while (!WDT->CTRLA.bit.ENABLE) {}
while (1) {} //Wait on timeout
}

View file

@ -0,0 +1,98 @@
/* Copyright 2017 Fred Sundvik
*
* 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 "eeprom.h"
#define EEPROM_SIZE 32
static uint8_t buffer[EEPROM_SIZE];
uint8_t eeprom_read_byte(const uint8_t *addr) {
uintptr_t offset = (uintptr_t)addr;
return buffer[offset];
}
void eeprom_write_byte(uint8_t *addr, uint8_t value) {
uintptr_t offset = (uintptr_t)addr;
buffer[offset] = value;
}
uint16_t eeprom_read_word(const uint16_t *addr) {
const uint8_t *p = (const uint8_t *)addr;
return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
}
uint32_t eeprom_read_dword(const uint32_t *addr) {
const uint8_t *p = (const uint8_t *)addr;
return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
| (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
}
void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
const uint8_t *p = (const uint8_t *)addr;
uint8_t *dest = (uint8_t *)buf;
while (len--) {
*dest++ = eeprom_read_byte(p++);
}
}
void eeprom_write_word(uint16_t *addr, uint16_t value) {
uint8_t *p = (uint8_t *)addr;
eeprom_write_byte(p++, value);
eeprom_write_byte(p, value >> 8);
}
void eeprom_write_dword(uint32_t *addr, uint32_t value) {
uint8_t *p = (uint8_t *)addr;
eeprom_write_byte(p++, value);
eeprom_write_byte(p++, value >> 8);
eeprom_write_byte(p++, value >> 16);
eeprom_write_byte(p, value >> 24);
}
void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
uint8_t *p = (uint8_t *)addr;
const uint8_t *src = (const uint8_t *)buf;
while (len--) {
eeprom_write_byte(p++, *src++);
}
}
void eeprom_update_byte(uint8_t *addr, uint8_t value) {
eeprom_write_byte(addr, value);
}
void eeprom_update_word(uint16_t *addr, uint16_t value) {
uint8_t *p = (uint8_t *)addr;
eeprom_write_byte(p++, value);
eeprom_write_byte(p, value >> 8);
}
void eeprom_update_dword(uint32_t *addr, uint32_t value) {
uint8_t *p = (uint8_t *)addr;
eeprom_write_byte(p++, value);
eeprom_write_byte(p++, value >> 8);
eeprom_write_byte(p++, value >> 16);
eeprom_write_byte(p, value >> 24);
}
void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
uint8_t *p = (uint8_t *)addr;
const uint8_t *src = (const uint8_t *)buf;
while (len--) {
eeprom_write_byte(p++, *src++);
}
}

View file

@ -0,0 +1,66 @@
/*
Copyright 2018 Massdrop Inc.
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/>.
*/
#ifdef CONSOLE_ENABLE
#include "samd51j18a.h"
#include "arm_atsam_protocol.h"
#include "printf.h"
#include <string.h>
#include <stdarg.h>
void console_printf(char *fmt, ...) {
while (udi_hid_con_b_report_trans_ongoing) {} //Wait for any previous transfers to complete
static char console_printbuf[CONSOLE_PRINTBUF_SIZE]; //Print and send buffer
va_list va;
int result;
va_start(va, fmt);
result = vsnprintf(console_printbuf, CONSOLE_PRINTBUF_SIZE, fmt, va);
va_end(va);
uint32_t irqflags;
char *pconbuf = console_printbuf; //Pointer to start send from
int send_out = CONSOLE_EPSIZE; //Bytes to send per transfer
while (result > 0) { //While not error and bytes remain
while (udi_hid_con_b_report_trans_ongoing) {} //Wait for any previous transfers to complete
irqflags = __get_PRIMASK();
__disable_irq();
__DMB();
if (result < CONSOLE_EPSIZE) { //If remaining bytes are less than console epsize
memset(udi_hid_con_report, 0, CONSOLE_EPSIZE); //Clear the buffer
send_out = result; //Send remaining size
}
memcpy(udi_hid_con_report, pconbuf, send_out); //Copy data into the send buffer
udi_hid_con_b_report_valid = 1; //Set report valid
udi_hid_con_send_report(); //Send report
__DMB();
__set_PRIMASK(irqflags);
result -= send_out; //Decrement result by bytes sent
pconbuf += send_out; //Increment buffer point by bytes sent
}
}
#endif //CONSOLE_ENABLE

View file

@ -0,0 +1,11 @@
#ifndef _PRINTF_H_
#define _PRINTF_H_
#define CONSOLE_PRINTBUF_SIZE 512
void console_printf(char *fmt, ...);
#define __xprintf console_printf
#endif //_PRINTF_H_

View file

@ -0,0 +1,85 @@
#include "matrix.h"
#include "i2c_master.h"
#include "led_matrix.h"
#include "suspend.h"
/** \brief Suspend idle
*
* FIXME: needs doc
*/
void suspend_idle(uint8_t time) {
/* Note: Not used anywhere currently */
}
/** \brief Run user level Power down
*
* FIXME: needs doc
*/
__attribute__ ((weak))
void suspend_power_down_user (void) {
}
/** \brief Run keyboard level Power down
*
* FIXME: needs doc
*/
__attribute__ ((weak))
void suspend_power_down_kb(void) {
suspend_power_down_user();
}
/** \brief Suspend power down
*
* FIXME: needs doc
*/
void suspend_power_down(void)
{
I2C3733_Control_Set(0); //Disable LED driver
suspend_power_down_kb();
}
__attribute__ ((weak)) void matrix_power_up(void) {}
__attribute__ ((weak)) void matrix_power_down(void) {}
bool suspend_wakeup_condition(void) {
matrix_power_up();
matrix_scan();
matrix_power_down();
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
if (matrix_get_row(r)) return true;
}
return false;
}
/** \brief run user level code immediately after wakeup
*
* FIXME: needs doc
*/
__attribute__ ((weak))
void suspend_wakeup_init_user(void) {
}
/** \brief run keyboard level code immediately after wakeup
*
* FIXME: needs doc
*/
__attribute__ ((weak))
void suspend_wakeup_init_kb(void) {
suspend_wakeup_init_user();
}
/** \brief run immediately after wakeup
*
* FIXME: needs doc
*/
void suspend_wakeup_init(void) {
/* If LEDs are set to enabled, enable the hardware */
if (led_enabled) {
I2C3733_Control_Set(1);
}
suspend_wakeup_init_kb();
}

View file

@ -0,0 +1,59 @@
#include "samd51j18a.h"
#include "timer.h"
#include "tmk_core/protocol/arm_atsam/clks.h"
void set_time(uint64_t tset)
{
ms_clk = tset;
}
void timer_init(void)
{
ms_clk = 0;
}
uint16_t timer_read(void)
{
return (uint16_t)ms_clk;
}
uint32_t timer_read32(void)
{
return (uint32_t)ms_clk;
}
uint64_t timer_read64(void)
{
return ms_clk;
}
uint16_t timer_elapsed(uint16_t tlast)
{
return TIMER_DIFF_16(timer_read(), tlast);
}
uint32_t timer_elapsed32(uint32_t tlast)
{
return TIMER_DIFF_32(timer_read32(), tlast);
}
uint32_t timer_elapsed64(uint32_t tlast)
{
uint64_t tnow = timer_read64();
return (tnow >= tlast ? tnow - tlast : UINT64_MAX - tlast + tnow);
}
void timer_clear(void)
{
ms_clk = 0;
}
void wait_ms(uint64_t msec)
{
CLK_delay_ms(msec);
}
void wait_us(uint16_t usec)
{
CLK_delay_us(usec);
}

View file

@ -10,6 +10,7 @@
#include "timer.h"
#include "led.h"
#include "host.h"
#include "rgblight_reconfig.h"
#ifdef PROTOCOL_LUFA
#include "lufa.h"
@ -55,6 +56,24 @@ void suspend_idle(uint8_t time)
sleep_disable();
}
// TODO: This needs some cleanup
/** \brief Run keyboard level Power down
*
* FIXME: needs doc
*/
__attribute__ ((weak))
void suspend_power_down_user (void) { }
/** \brief Run keyboard level Power down
*
* FIXME: needs doc
*/
__attribute__ ((weak))
void suspend_power_down_kb(void) {
suspend_power_down_user();
}
#ifndef NO_SUSPEND_POWER_DOWN
/** \brief Power down MCU with watchdog timer
*
@ -72,21 +91,6 @@ void suspend_idle(uint8_t time)
*/
static uint8_t wdt_timeout = 0;
/** \brief Run keyboard level Power down
*
* FIXME: needs doc
*/
__attribute__ ((weak))
void suspend_power_down_user (void) { }
/** \brief Run keyboard level Power down
*
* FIXME: needs doc
*/
__attribute__ ((weak))
void suspend_power_down_kb(void) {
suspend_power_down_user();
}
/** \brief Power down
*
* FIXME: needs doc
@ -143,6 +147,8 @@ static void power_down(uint8_t wdto)
*/
void suspend_power_down(void)
{
suspend_power_down_kb();
#ifndef NO_SUSPEND_POWER_DOWN
power_down(WDTO_15MS);
#endif
@ -189,12 +195,15 @@ void suspend_wakeup_init(void)
#endif
led_set(host_keyboard_leds());
#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
#ifdef BOOTLOADER_TEENSY
wait_ms(10);
#endif
rgblight_enable_noeeprom();
#ifdef RGBLIGHT_ANIMATIONS
rgblight_timer_enable();
#endif
#endif
suspend_wakeup_init_kb();
suspend_wakeup_init_kb();
}
#ifndef NO_SUSPEND_POWER_DOWN

View file

@ -76,12 +76,51 @@ void backlight_decrease(void)
*/
void backlight_toggle(void)
{
backlight_config.enable ^= 1;
if (backlight_config.raw == 1) // enabled but level = 0
backlight_config.level = 1;
eeconfig_update_backlight(backlight_config.raw);
dprintf("backlight toggle: %u\n", backlight_config.enable);
backlight_set(backlight_config.enable ? backlight_config.level : 0);
bool enabled = backlight_config.enable;
dprintf("backlight toggle: %u\n", enabled);
if (enabled)
backlight_disable();
else
backlight_enable();
}
/** \brief Enable backlight
*
* FIXME: needs doc
*/
void backlight_enable(void)
{
if (backlight_config.enable) return; // do nothing if backlight is already on
backlight_config.enable = true;
if (backlight_config.raw == 1) // enabled but level == 0
backlight_config.level = 1;
eeconfig_update_backlight(backlight_config.raw);
dprintf("backlight enable\n");
backlight_set(backlight_config.level);
}
/** /brief Disable backlight
*
* FIXME: needs doc
*/
void backlight_disable(void)
{
if (!backlight_config.enable) return; // do nothing if backlight is already off
backlight_config.enable = false;
eeconfig_update_backlight(backlight_config.raw);
dprintf("backlight disable\n");
backlight_set(0);
}
/** /brief Get the backlight status
*
* FIXME: needs doc
*/
bool is_backlight_enabled(void)
{
return backlight_config.enable;
}
/** \brief Backlight step through levels

View file

@ -15,8 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BACKLIGHT_H
#define BACKLIGHT_H
#pragma once
#include <stdint.h>
#include <stdbool.h>
@ -33,9 +32,11 @@ void backlight_init(void);
void backlight_increase(void);
void backlight_decrease(void);
void backlight_toggle(void);
void backlight_enable(void);
void backlight_disable(void);
bool is_backlight_enabled(void);
void backlight_step(void);
void backlight_set(uint8_t level);
void backlight_level(uint8_t level);
uint8_t get_backlight_level(void);
#endif

View file

@ -0,0 +1,673 @@
/*
* This software is experimental and a work in progress.
* Under no circumstances should these files be used in relation to any critical system(s).
* Use of these files is at your own risk.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
* https://github.com/leaflabs/libmaple
*
* Modifications for QMK and STM32F303 by Yiancar
*/
#include "eeprom_stm32.h"
FLASH_Status EE_ErasePage(uint32_t);
uint16_t EE_CheckPage(uint32_t, uint16_t);
uint16_t EE_CheckErasePage(uint32_t, uint16_t);
uint16_t EE_Format(void);
uint32_t EE_FindValidPage(void);
uint16_t EE_GetVariablesCount(uint32_t, uint16_t);
uint16_t EE_PageTransfer(uint32_t, uint32_t, uint16_t);
uint16_t EE_VerifyPageFullWriteVariable(uint16_t, uint16_t);
uint32_t PageBase0 = EEPROM_PAGE0_BASE;
uint32_t PageBase1 = EEPROM_PAGE1_BASE;
uint32_t PageSize = EEPROM_PAGE_SIZE;
uint16_t Status = EEPROM_NOT_INIT;
// See http://www.st.com/web/en/resource/technical/document/application_note/CD00165693.pdf
/**
* @brief Check page for blank
* @param page base address
* @retval Success or error
* EEPROM_BAD_FLASH: page not empty after erase
* EEPROM_OK: page blank
*/
uint16_t EE_CheckPage(uint32_t pageBase, uint16_t status)
{
uint32_t pageEnd = pageBase + (uint32_t)PageSize;
// Page Status not EEPROM_ERASED and not a "state"
if ((*(__IO uint16_t*)pageBase) != EEPROM_ERASED && (*(__IO uint16_t*)pageBase) != status)
return EEPROM_BAD_FLASH;
for(pageBase += 4; pageBase < pageEnd; pageBase += 4)
if ((*(__IO uint32_t*)pageBase) != 0xFFFFFFFF) // Verify if slot is empty
return EEPROM_BAD_FLASH;
return EEPROM_OK;
}
/**
* @brief Erase page with increment erase counter (page + 2)
* @param page base address
* @retval Success or error
* FLASH_COMPLETE: success erase
* - Flash error code: on write Flash error
*/
FLASH_Status EE_ErasePage(uint32_t pageBase)
{
FLASH_Status FlashStatus;
uint16_t data = (*(__IO uint16_t*)(pageBase));
if ((data == EEPROM_ERASED) || (data == EEPROM_VALID_PAGE) || (data == EEPROM_RECEIVE_DATA))
data = (*(__IO uint16_t*)(pageBase + 2)) + 1;
else
data = 0;
FlashStatus = FLASH_ErasePage(pageBase);
if (FlashStatus == FLASH_COMPLETE)
FlashStatus = FLASH_ProgramHalfWord(pageBase + 2, data);
return FlashStatus;
}
/**
* @brief Check page for blank and erase it
* @param page base address
* @retval Success or error
* - Flash error code: on write Flash error
* - EEPROM_BAD_FLASH: page not empty after erase
* - EEPROM_OK: page blank
*/
uint16_t EE_CheckErasePage(uint32_t pageBase, uint16_t status)
{
uint16_t FlashStatus;
if (EE_CheckPage(pageBase, status) != EEPROM_OK)
{
FlashStatus = EE_ErasePage(pageBase);
if (FlashStatus != FLASH_COMPLETE)
return FlashStatus;
return EE_CheckPage(pageBase, status);
}
return EEPROM_OK;
}
/**
* @brief Find valid Page for write or read operation
* @param Page0: Page0 base address
* Page1: Page1 base address
* @retval Valid page address (PAGE0 or PAGE1) or NULL in case of no valid page was found
*/
uint32_t EE_FindValidPage(void)
{
uint16_t status0 = (*(__IO uint16_t*)PageBase0); // Get Page0 actual status
uint16_t status1 = (*(__IO uint16_t*)PageBase1); // Get Page1 actual status
if (status0 == EEPROM_VALID_PAGE && status1 == EEPROM_ERASED)
return PageBase0;
if (status1 == EEPROM_VALID_PAGE && status0 == EEPROM_ERASED)
return PageBase1;
return 0;
}
/**
* @brief Calculate unique variables in EEPROM
* @param start: address of first slot to check (page + 4)
* @param end: page end address
* @param address: 16 bit virtual address of the variable to excluse (or 0XFFFF)
* @retval count of variables
*/
uint16_t EE_GetVariablesCount(uint32_t pageBase, uint16_t skipAddress)
{
uint16_t varAddress, nextAddress;
uint32_t idx;
uint32_t pageEnd = pageBase + (uint32_t)PageSize;
uint16_t count = 0;
for (pageBase += 6; pageBase < pageEnd; pageBase += 4)
{
varAddress = (*(__IO uint16_t*)pageBase);
if (varAddress == 0xFFFF || varAddress == skipAddress)
continue;
count++;
for(idx = pageBase + 4; idx < pageEnd; idx += 4)
{
nextAddress = (*(__IO uint16_t*)idx);
if (nextAddress == varAddress)
{
count--;
break;
}
}
}
return count;
}
/**
* @brief Transfers last updated variables data from the full Page to an empty one.
* @param newPage: new page base address
* @param oldPage: old page base address
* @param SkipAddress: 16 bit virtual address of the variable (or 0xFFFF)
* @retval Success or error status:
* - FLASH_COMPLETE: on success
* - EEPROM_OUT_SIZE: if valid new page is full
* - Flash error code: on write Flash error
*/
uint16_t EE_PageTransfer(uint32_t newPage, uint32_t oldPage, uint16_t SkipAddress)
{
uint32_t oldEnd, newEnd;
uint32_t oldIdx, newIdx, idx;
uint16_t address, data, found;
FLASH_Status FlashStatus;
// Transfer process: transfer variables from old to the new active page
newEnd = newPage + ((uint32_t)PageSize);
// Find first free element in new page
for (newIdx = newPage + 4; newIdx < newEnd; newIdx += 4)
if ((*(__IO uint32_t*)newIdx) == 0xFFFFFFFF) // Verify if element
break; // contents are 0xFFFFFFFF
if (newIdx >= newEnd)
return EEPROM_OUT_SIZE;
oldEnd = oldPage + 4;
oldIdx = oldPage + (uint32_t)(PageSize - 2);
for (; oldIdx > oldEnd; oldIdx -= 4)
{
address = *(__IO uint16_t*)oldIdx;
if (address == 0xFFFF || address == SkipAddress)
continue; // it's means that power off after write data
found = 0;
for (idx = newPage + 6; idx < newIdx; idx += 4)
if ((*(__IO uint16_t*)(idx)) == address)
{
found = 1;
break;
}
if (found)
continue;
if (newIdx < newEnd)
{
data = (*(__IO uint16_t*)(oldIdx - 2));
FlashStatus = FLASH_ProgramHalfWord(newIdx, data);
if (FlashStatus != FLASH_COMPLETE)
return FlashStatus;
FlashStatus = FLASH_ProgramHalfWord(newIdx + 2, address);
if (FlashStatus != FLASH_COMPLETE)
return FlashStatus;
newIdx += 4;
}
else
return EEPROM_OUT_SIZE;
}
// Erase the old Page: Set old Page status to EEPROM_EEPROM_ERASED status
data = EE_CheckErasePage(oldPage, EEPROM_ERASED);
if (data != EEPROM_OK)
return data;
// Set new Page status
FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_VALID_PAGE);
if (FlashStatus != FLASH_COMPLETE)
return FlashStatus;
return EEPROM_OK;
}
/**
* @brief Verify if active page is full and Writes variable in EEPROM.
* @param Address: 16 bit virtual address of the variable
* @param Data: 16 bit data to be written as variable value
* @retval Success or error status:
* - FLASH_COMPLETE: on success
* - EEPROM_PAGE_FULL: if valid page is full (need page transfer)
* - EEPROM_NO_VALID_PAGE: if no valid page was found
* - EEPROM_OUT_SIZE: if EEPROM size exceeded
* - Flash error code: on write Flash error
*/
uint16_t EE_VerifyPageFullWriteVariable(uint16_t Address, uint16_t Data)
{
FLASH_Status FlashStatus;
uint32_t idx, pageBase, pageEnd, newPage;
uint16_t count;
// Get valid Page for write operation
pageBase = EE_FindValidPage();
if (pageBase == 0)
return EEPROM_NO_VALID_PAGE;
// Get the valid Page end Address
pageEnd = pageBase + PageSize; // Set end of page
for (idx = pageEnd - 2; idx > pageBase; idx -= 4)
{
if ((*(__IO uint16_t*)idx) == Address) // Find last value for address
{
count = (*(__IO uint16_t*)(idx - 2)); // Read last data
if (count == Data)
return EEPROM_OK;
if (count == 0xFFFF)
{
FlashStatus = FLASH_ProgramHalfWord(idx - 2, Data); // Set variable data
if (FlashStatus == FLASH_COMPLETE)
return EEPROM_OK;
}
break;
}
}
// Check each active page address starting from begining
for (idx = pageBase + 4; idx < pageEnd; idx += 4)
if ((*(__IO uint32_t*)idx) == 0xFFFFFFFF) // Verify if element
{ // contents are 0xFFFFFFFF
FlashStatus = FLASH_ProgramHalfWord(idx, Data); // Set variable data
if (FlashStatus != FLASH_COMPLETE)
return FlashStatus;
FlashStatus = FLASH_ProgramHalfWord(idx + 2, Address); // Set variable virtual address
if (FlashStatus != FLASH_COMPLETE)
return FlashStatus;
return EEPROM_OK;
}
// Empty slot not found, need page transfer
// Calculate unique variables in page
count = EE_GetVariablesCount(pageBase, Address) + 1;
if (count >= (PageSize / 4 - 1))
return EEPROM_OUT_SIZE;
if (pageBase == PageBase1)
newPage = PageBase0; // New page address where variable will be moved to
else
newPage = PageBase1;
// Set the new Page status to RECEIVE_DATA status
FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_RECEIVE_DATA);
if (FlashStatus != FLASH_COMPLETE)
return FlashStatus;
// Write the variable passed as parameter in the new active page
FlashStatus = FLASH_ProgramHalfWord(newPage + 4, Data);
if (FlashStatus != FLASH_COMPLETE)
return FlashStatus;
FlashStatus = FLASH_ProgramHalfWord(newPage + 6, Address);
if (FlashStatus != FLASH_COMPLETE)
return FlashStatus;
return EE_PageTransfer(newPage, pageBase, Address);
}
/*EEPROMClass::EEPROMClass(void)
{
PageBase0 = EEPROM_PAGE0_BASE;
PageBase1 = EEPROM_PAGE1_BASE;
PageSize = EEPROM_PAGE_SIZE;
Status = EEPROM_NOT_INIT;
}*/
/*
uint16_t EEPROM_init(uint32_t pageBase0, uint32_t pageBase1, uint32_t pageSize)
{
PageBase0 = pageBase0;
PageBase1 = pageBase1;
PageSize = pageSize;
return EEPROM_init();
}*/
uint16_t EEPROM_init(void)
{
uint16_t status0 = 6, status1 = 6;
FLASH_Status FlashStatus;
FLASH_Unlock();
Status = EEPROM_NO_VALID_PAGE;
status0 = (*(__IO uint16_t *)PageBase0);
status1 = (*(__IO uint16_t *)PageBase1);
switch (status0)
{
/*
Page0 Page1
----- -----
EEPROM_ERASED EEPROM_VALID_PAGE Page1 valid, Page0 erased
EEPROM_RECEIVE_DATA Page1 need set to valid, Page0 erased
EEPROM_ERASED make EE_Format
any Error: EEPROM_NO_VALID_PAGE
*/
case EEPROM_ERASED:
if (status1 == EEPROM_VALID_PAGE) // Page0 erased, Page1 valid
Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED);
else if (status1 == EEPROM_RECEIVE_DATA) // Page0 erased, Page1 receive
{
FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE);
if (FlashStatus != FLASH_COMPLETE)
Status = FlashStatus;
else
Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED);
}
else if (status1 == EEPROM_ERASED) // Both in erased state so format EEPROM
Status = EEPROM_format();
break;
/*
Page0 Page1
----- -----
EEPROM_RECEIVE_DATA EEPROM_VALID_PAGE Transfer Page1 to Page0
EEPROM_ERASED Page0 need set to valid, Page1 erased
any EEPROM_NO_VALID_PAGE
*/
case EEPROM_RECEIVE_DATA:
if (status1 == EEPROM_VALID_PAGE) // Page0 receive, Page1 valid
Status = EE_PageTransfer(PageBase0, PageBase1, 0xFFFF);
else if (status1 == EEPROM_ERASED) // Page0 receive, Page1 erased
{
Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED);
if (Status == EEPROM_OK)
{
FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE);
if (FlashStatus != FLASH_COMPLETE)
Status = FlashStatus;
else
Status = EEPROM_OK;
}
}
break;
/*
Page0 Page1
----- -----
EEPROM_VALID_PAGE EEPROM_VALID_PAGE Error: EEPROM_NO_VALID_PAGE
EEPROM_RECEIVE_DATA Transfer Page0 to Page1
any Page0 valid, Page1 erased
*/
case EEPROM_VALID_PAGE:
if (status1 == EEPROM_VALID_PAGE) // Both pages valid
Status = EEPROM_NO_VALID_PAGE;
else if (status1 == EEPROM_RECEIVE_DATA)
Status = EE_PageTransfer(PageBase1, PageBase0, 0xFFFF);
else
Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED);
break;
/*
Page0 Page1
----- -----
any EEPROM_VALID_PAGE Page1 valid, Page0 erased
EEPROM_RECEIVE_DATA Page1 valid, Page0 erased
any EEPROM_NO_VALID_PAGE
*/
default:
if (status1 == EEPROM_VALID_PAGE)
Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); // Check/Erase Page0
else if (status1 == EEPROM_RECEIVE_DATA)
{
FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE);
if (FlashStatus != FLASH_COMPLETE)
Status = FlashStatus;
else
Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED);
}
break;
}
return Status;
}
/**
* @brief Erases PAGE0 and PAGE1 and writes EEPROM_VALID_PAGE / 0 header to PAGE0
* @param PAGE0 and PAGE1 base addresses
* @retval Status of the last operation (Flash write or erase) done during EEPROM formating
*/
uint16_t EEPROM_format(void)
{
uint16_t status;
FLASH_Status FlashStatus;
FLASH_Unlock();
// Erase Page0
status = EE_CheckErasePage(PageBase0, EEPROM_VALID_PAGE);
if (status != EEPROM_OK)
return status;
if ((*(__IO uint16_t*)PageBase0) == EEPROM_ERASED)
{
// Set Page0 as valid page: Write VALID_PAGE at Page0 base address
FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE);
if (FlashStatus != FLASH_COMPLETE)
return FlashStatus;
}
// Erase Page1
return EE_CheckErasePage(PageBase1, EEPROM_ERASED);
}
/**
* @brief Returns the erase counter for current page
* @param Data: Global variable contains the read variable value
* @retval Success or error status:
* - EEPROM_OK: if erases counter return.
* - EEPROM_NO_VALID_PAGE: if no valid page was found.
*/
uint16_t EEPROM_erases(uint16_t *Erases)
{
uint32_t pageBase;
if (Status != EEPROM_OK)
if (EEPROM_init() != EEPROM_OK)
return Status;
// Get active Page for read operation
pageBase = EE_FindValidPage();
if (pageBase == 0)
return EEPROM_NO_VALID_PAGE;
*Erases = (*(__IO uint16_t*)pageBase+2);
return EEPROM_OK;
}
/**
* @brief Returns the last stored variable data, if found,
* which correspond to the passed virtual address
* @param Address: Variable virtual address
* @retval Data for variable or EEPROM_DEFAULT_DATA, if any errors
*/
/*
uint16_t EEPROM_read (uint16_t Address)
{
uint16_t data;
EEPROM_read(Address, &data);
return data;
}*/
/**
* @brief Returns the last stored variable data, if found,
* which correspond to the passed virtual address
* @param Address: Variable virtual address
* @param Data: Pointer to data variable
* @retval Success or error status:
* - EEPROM_OK: if variable was found
* - EEPROM_BAD_ADDRESS: if the variable was not found
* - EEPROM_NO_VALID_PAGE: if no valid page was found.
*/
uint16_t EEPROM_read(uint16_t Address, uint16_t *Data)
{
uint32_t pageBase, pageEnd;
// Set default data (empty EEPROM)
*Data = EEPROM_DEFAULT_DATA;
if (Status == EEPROM_NOT_INIT)
if (EEPROM_init() != EEPROM_OK)
return Status;
// Get active Page for read operation
pageBase = EE_FindValidPage();
if (pageBase == 0)
return EEPROM_NO_VALID_PAGE;
// Get the valid Page end Address
pageEnd = pageBase + ((uint32_t)(PageSize - 2));
// Check each active page address starting from end
for (pageBase += 6; pageEnd >= pageBase; pageEnd -= 4)
if ((*(__IO uint16_t*)pageEnd) == Address) // Compare the read address with the virtual address
{
*Data = (*(__IO uint16_t*)(pageEnd - 2)); // Get content of Address-2 which is variable value
return EEPROM_OK;
}
// Return ReadStatus value: (0: variable exist, 1: variable doesn't exist)
return EEPROM_BAD_ADDRESS;
}
/**
* @brief Writes/upadtes variable data in EEPROM.
* @param VirtAddress: Variable virtual address
* @param Data: 16 bit data to be written
* @retval Success or error status:
* - FLASH_COMPLETE: on success
* - EEPROM_BAD_ADDRESS: if address = 0xFFFF
* - EEPROM_PAGE_FULL: if valid page is full
* - EEPROM_NO_VALID_PAGE: if no valid page was found
* - EEPROM_OUT_SIZE: if no empty EEPROM variables
* - Flash error code: on write Flash error
*/
uint16_t EEPROM_write(uint16_t Address, uint16_t Data)
{
if (Status == EEPROM_NOT_INIT)
if (EEPROM_init() != EEPROM_OK)
return Status;
if (Address == 0xFFFF)
return EEPROM_BAD_ADDRESS;
// Write the variable virtual address and value in the EEPROM
uint16_t status = EE_VerifyPageFullWriteVariable(Address, Data);
return status;
}
/**
* @brief Writes/upadtes variable data in EEPROM.
The value is written only if differs from the one already saved at the same address.
* @param VirtAddress: Variable virtual address
* @param Data: 16 bit data to be written
* @retval Success or error status:
* - EEPROM_SAME_VALUE: If new Data matches existing EEPROM Data
* - FLASH_COMPLETE: on success
* - EEPROM_BAD_ADDRESS: if address = 0xFFFF
* - EEPROM_PAGE_FULL: if valid page is full
* - EEPROM_NO_VALID_PAGE: if no valid page was found
* - EEPROM_OUT_SIZE: if no empty EEPROM variables
* - Flash error code: on write Flash error
*/
uint16_t EEPROM_update(uint16_t Address, uint16_t Data)
{
uint16_t temp;
EEPROM_read(Address, &temp);
if (temp == Data)
return EEPROM_SAME_VALUE;
else
return EEPROM_write(Address, Data);
}
/**
* @brief Return number of variable
* @retval Number of variables
*/
uint16_t EEPROM_count(uint16_t *Count)
{
if (Status == EEPROM_NOT_INIT)
if (EEPROM_init() != EEPROM_OK)
return Status;
// Get valid Page for write operation
uint32_t pageBase = EE_FindValidPage();
if (pageBase == 0)
return EEPROM_NO_VALID_PAGE; // No valid page, return max. numbers
*Count = EE_GetVariablesCount(pageBase, 0xFFFF);
return EEPROM_OK;
}
uint16_t EEPROM_maxcount(void)
{
return ((PageSize / 4)-1);
}
uint8_t eeprom_read_byte (const uint8_t *Address)
{
const uint16_t p = (const uint32_t) Address;
uint16_t temp;
EEPROM_read(p, &temp);
return (uint8_t) temp;
}
void eeprom_write_byte (uint8_t *Address, uint8_t Value)
{
uint16_t p = (uint32_t) Address;
EEPROM_write(p, (uint16_t) Value);
}
void eeprom_update_byte (uint8_t *Address, uint8_t Value)
{
uint16_t p = (uint32_t) Address;
EEPROM_update(p, (uint16_t) Value);
}
uint16_t eeprom_read_word (const uint16_t *Address)
{
const uint16_t p = (const uint32_t) Address;
uint16_t temp;
EEPROM_read(p, &temp);
return temp;
}
void eeprom_write_word (uint16_t *Address, uint16_t Value)
{
uint16_t p = (uint32_t) Address;
EEPROM_write(p, Value);
}
void eeprom_update_word (uint16_t *Address, uint16_t Value)
{
uint16_t p = (uint32_t) Address;
EEPROM_update(p, Value);
}
uint32_t eeprom_read_dword (const uint32_t *Address)
{
const uint16_t p = (const uint32_t) Address;
uint16_t temp1, temp2;
EEPROM_read(p, &temp1);
EEPROM_read(p + 1, &temp2);
return temp1 | (temp2 << 16);
}
void eeprom_write_dword (uint32_t *Address, uint32_t Value)
{
uint16_t temp = (uint16_t) Value;
uint16_t p = (uint32_t) Address;
EEPROM_write(p, temp);
temp = (uint16_t) (Value >> 16);
EEPROM_write(p + 1, temp);
}
void eeprom_update_dword (uint32_t *Address, uint32_t Value)
{
uint16_t temp = (uint16_t) Value;
uint16_t p = (uint32_t) Address;
EEPROM_update(p, temp);
temp = (uint16_t) (Value >> 16);
EEPROM_update(p + 1, temp);
}

View file

@ -0,0 +1,95 @@
/*
* This software is experimental and a work in progress.
* Under no circumstances should these files be used in relation to any critical system(s).
* Use of these files is at your own risk.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
* https://github.com/leaflabs/libmaple
*
* Modifications for QMK and STM32F303 by Yiancar
*/
// This file must be modified if the MCU is not defined below.
// This library also assumes that the pages are not used by the firmware.
#ifndef __EEPROM_H
#define __EEPROM_H
#include "ch.h"
#include "hal.h"
#include "flash_stm32.h"
// HACK ALERT. This definition may not match your processor
// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc
#if defined(EEPROM_EMU_STM32F303xC)
#define MCU_STM32F303CC
#elif defined(EEPROM_EMU_STM32F103xB)
#define MCU_STM32F103RB
#else
#error "not implemented."
#endif
#ifndef EEPROM_PAGE_SIZE
#if defined (MCU_STM32F103RB)
#define EEPROM_PAGE_SIZE (uint16_t)0x400 /* Page size = 1KByte */
#elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) || defined (MCU_STM32F103RD) || defined (MCU_STM32F303CC)
#define EEPROM_PAGE_SIZE (uint16_t)0x800 /* Page size = 2KByte */
#else
#error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
#endif
#endif
#ifndef EEPROM_START_ADDRESS
#if defined (MCU_STM32F103RB)
#define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 128 * 1024 - 2 * EEPROM_PAGE_SIZE))
#elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE)
#define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 512 * 1024 - 2 * EEPROM_PAGE_SIZE))
#elif defined (MCU_STM32F103RD)
#define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 384 * 1024 - 2 * EEPROM_PAGE_SIZE))
#elif defined (MCU_STM32F303CC)
#define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 256 * 1024 - 2 * EEPROM_PAGE_SIZE))
#else
#error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
#endif
#endif
/* Pages 0 and 1 base and end addresses */
#define EEPROM_PAGE0_BASE ((uint32_t)(EEPROM_START_ADDRESS + 0x000))
#define EEPROM_PAGE1_BASE ((uint32_t)(EEPROM_START_ADDRESS + EEPROM_PAGE_SIZE))
/* Page status definitions */
#define EEPROM_ERASED ((uint16_t)0xFFFF) /* PAGE is empty */
#define EEPROM_RECEIVE_DATA ((uint16_t)0xEEEE) /* PAGE is marked to receive data */
#define EEPROM_VALID_PAGE ((uint16_t)0x0000) /* PAGE containing valid data */
/* Page full define */
enum uint16_t
{
EEPROM_OK = ((uint16_t)0x0000),
EEPROM_OUT_SIZE = ((uint16_t)0x0081),
EEPROM_BAD_ADDRESS = ((uint16_t)0x0082),
EEPROM_BAD_FLASH = ((uint16_t)0x0083),
EEPROM_NOT_INIT = ((uint16_t)0x0084),
EEPROM_SAME_VALUE = ((uint16_t)0x0085),
EEPROM_NO_VALID_PAGE = ((uint16_t)0x00AB)
};
#define EEPROM_DEFAULT_DATA 0xFFFF
uint16_t EEPROM_init(void);
uint16_t EEPROM_format(void);
uint16_t EEPROM_erases(uint16_t *);
uint16_t EEPROM_read (uint16_t address, uint16_t *data);
uint16_t EEPROM_write(uint16_t address, uint16_t data);
uint16_t EEPROM_update(uint16_t address, uint16_t data);
uint16_t EEPROM_count(uint16_t *);
uint16_t EEPROM_maxcount(void);
#endif /* __EEPROM_H */

View file

@ -0,0 +1,188 @@
/*
* This software is experimental and a work in progress.
* Under no circumstances should these files be used in relation to any critical system(s).
* Use of these files is at your own risk.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
* https://github.com/leaflabs/libmaple
*
* Modifications for QMK and STM32F303 by Yiancar
*/
#if defined(EEPROM_EMU_STM32F303xC)
#define STM32F303xC
#include "stm32f3xx.h"
#elif defined(EEPROM_EMU_STM32F103xB)
#define STM32F103xB
#include "stm32f1xx.h"
#else
#error "not implemented."
#endif
#include "flash_stm32.h"
#if defined(EEPROM_EMU_STM32F103xB)
#define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
#endif
/* Delay definition */
#define EraseTimeout ((uint32_t)0x00000FFF)
#define ProgramTimeout ((uint32_t)0x0000001F)
#define ASSERT(exp) (void)((0))
/**
* @brief Inserts a time delay.
* @param None
* @retval None
*/
static void delay(void)
{
__IO uint32_t i = 0;
for(i = 0xFF; i != 0; i--) { }
}
/**
* @brief Returns the FLASH Status.
* @param None
* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
* FLASH_ERROR_WRP or FLASH_COMPLETE
*/
FLASH_Status FLASH_GetStatus(void)
{
if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY)
return FLASH_BUSY;
if ((FLASH->SR & FLASH_SR_PGERR) != 0)
return FLASH_ERROR_PG;
if ((FLASH->SR & FLASH_SR_WRPERR) != 0 )
return FLASH_ERROR_WRP;
if ((FLASH->SR & FLASH_OBR_OPTERR) != 0 )
return FLASH_ERROR_OPT;
return FLASH_COMPLETE;
}
/**
* @brief Waits for a Flash operation to complete or a TIMEOUT to occur.
* @param Timeout: FLASH progamming Timeout
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout)
{
FLASH_Status status;
/* Check for the Flash Status */
status = FLASH_GetStatus();
/* Wait for a Flash operation to complete or a TIMEOUT to occur */
while ((status == FLASH_BUSY) && (Timeout != 0x00))
{
delay();
status = FLASH_GetStatus();
Timeout--;
}
if (Timeout == 0)
status = FLASH_TIMEOUT;
/* Return the operation status */
return status;
}
/**
* @brief Erases a specified FLASH page.
* @param Page_Address: The page address to be erased.
* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
{
FLASH_Status status = FLASH_COMPLETE;
/* Check the parameters */
ASSERT(IS_FLASH_ADDRESS(Page_Address));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase the page */
FLASH->CR |= FLASH_CR_PER;
FLASH->AR = Page_Address;
FLASH->CR |= FLASH_CR_STRT;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status != FLASH_TIMEOUT)
{
/* if the erase operation is completed, disable the PER Bit */
FLASH->CR &= ~FLASH_CR_PER;
}
FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
}
/* Return the Erase Status */
return status;
}
/**
* @brief Programs a half word at a specified address.
* @param Address: specifies the address to be programmed.
* @param Data: specifies the data to be programmed.
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{
FLASH_Status status = FLASH_BAD_ADDRESS;
if (IS_FLASH_ADDRESS(Address))
{
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new data */
FLASH->CR |= FLASH_CR_PG;
*(__IO uint16_t*)Address = Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status != FLASH_TIMEOUT)
{
/* if the program operation is completed, disable the PG Bit */
FLASH->CR &= ~FLASH_CR_PG;
}
FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
}
}
return status;
}
/**
* @brief Unlocks the FLASH Program Erase Controller.
* @param None
* @retval None
*/
void FLASH_Unlock(void)
{
/* Authorize the FPEC Access */
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
/**
* @brief Locks the FLASH Program Erase Controller.
* @param None
* @retval None
*/
void FLASH_Lock(void)
{
/* Set the Lock Bit to lock the FPEC and the FCR */
FLASH->CR |= FLASH_CR_LOCK;
}

View file

@ -0,0 +1,53 @@
/*
* This software is experimental and a work in progress.
* Under no circumstances should these files be used in relation to any critical system(s).
* Use of these files is at your own risk.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
* https://github.com/leaflabs/libmaple
*
* Modifications for QMK and STM32F303 by Yiancar
*/
#ifndef __FLASH_STM32_H
#define __FLASH_STM32_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch.h"
#include "hal.h"
typedef enum
{
FLASH_BUSY = 1,
FLASH_ERROR_PG,
FLASH_ERROR_WRP,
FLASH_ERROR_OPT,
FLASH_COMPLETE,
FLASH_TIMEOUT,
FLASH_BAD_ADDRESS
} FLASH_Status;
#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF))
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);
FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
void FLASH_Unlock(void);
void FLASH_Lock(void);
#ifdef __cplusplus
}
#endif
#endif /* __FLASH_STM32_H */

View file

@ -181,7 +181,11 @@ static void print_version(void)
print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
"PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
"VER: " STR(DEVICE_VER) "\n");
#ifdef SKIP_VERSION
print("BUILD: (" __DATE__ ")\n");
#else
print("BUILD: " STR(QMK_VERSION) " (" __TIME__ " " __DATE__ ")\n");
#endif
/* build options */
print("OPTIONS:"

View file

@ -15,8 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMAND_H
#define COMMAND
#pragma once
/* FIXME: Add doxygen comments for the behavioral defines in here. */
@ -155,5 +154,3 @@ bool command_proc(uint8_t code);
#define XMAGIC_KC(key) KC_##key
#define MAGIC_KC(key) XMAGIC_KC(key)
#endif

View file

@ -3,29 +3,59 @@
#include "eeprom.h"
#include "eeconfig.h"
#ifdef STM32_EEPROM_ENABLE
#include "hal.h"
#include "eeprom_stm32.h"
#endif
extern uint32_t default_layer_state;
/** \brief eeconfig enable
*
* FIXME: needs doc
*/
__attribute__ ((weak))
void eeconfig_init_user(void) {
// Reset user EEPROM value to blank, rather than to a set value
eeconfig_update_user(0);
}
__attribute__ ((weak))
void eeconfig_init_kb(void) {
// Reset Keyboard EEPROM value to blank, rather than to a set value
eeconfig_update_kb(0);
eeconfig_init_user();
}
/*
* FIXME: needs doc
*/
void eeconfig_init_quantum(void) {
#ifdef STM32_EEPROM_ENABLE
EEPROM_format();
#endif
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
eeprom_update_byte(EECONFIG_DEBUG, 0);
eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
default_layer_state = 0;
eeprom_update_byte(EECONFIG_KEYMAP, 0);
eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
eeprom_update_byte(EECONFIG_STENOMODE, 0);
eeconfig_init_kb();
}
/** \brief eeconfig initialization
*
* FIXME: needs doc
*/
void eeconfig_init(void)
{
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
eeprom_update_byte(EECONFIG_DEBUG, 0);
eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
eeprom_update_byte(EECONFIG_KEYMAP, 0);
eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
#ifdef BACKLIGHT_ENABLE
eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
#endif
#ifdef AUDIO_ENABLE
eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
#endif
#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
#endif
#ifdef STENO_ENABLE
eeprom_update_byte(EECONFIG_STENOMODE, 0);
#endif
void eeconfig_init(void) {
eeconfig_init_quantum();
}
/** \brief eeconfig enable
@ -43,7 +73,10 @@ void eeconfig_enable(void)
*/
void eeconfig_disable(void)
{
eeprom_update_word(EECONFIG_MAGIC, 0xFFFF);
#ifdef STM32_EEPROM_ENABLE
EEPROM_format();
#endif
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF);
}
/** \brief eeconfig is enabled
@ -55,6 +88,15 @@ bool eeconfig_is_enabled(void)
return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER);
}
/** \brief eeconfig is disabled
*
* FIXME: needs doc
*/
bool eeconfig_is_disabled(void)
{
return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER_OFF);
}
/** \brief eeconfig read debug
*
* FIXME: needs doc
@ -88,7 +130,6 @@ uint8_t eeconfig_read_keymap(void) { return eeprom_read_byte(EECONFIG_KEYMA
*/
void eeconfig_update_keymap(uint8_t val) { eeprom_update_byte(EECONFIG_KEYMAP, val); }
#ifdef BACKLIGHT_ENABLE
/** \brief eeconfig read backlight
*
* FIXME: needs doc
@ -99,9 +140,8 @@ uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BA
* FIXME: needs doc
*/
void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); }
#endif
#ifdef AUDIO_ENABLE
/** \brief eeconfig read audio
*
* FIXME: needs doc
@ -112,4 +152,28 @@ uint8_t eeconfig_read_audio(void) { return eeprom_read_byte(EECONFIG_AUDIO)
* FIXME: needs doc
*/
void eeconfig_update_audio(uint8_t val) { eeprom_update_byte(EECONFIG_AUDIO, val); }
#endif
/** \brief eeconfig read kb
*
* FIXME: needs doc
*/
uint32_t eeconfig_read_kb(void) { return eeprom_read_dword(EECONFIG_KEYBOARD); }
/** \brief eeconfig update kb
*
* FIXME: needs doc
*/
void eeconfig_update_kb(uint32_t val) { eeprom_update_dword(EECONFIG_KEYBOARD, val); }
/** \brief eeconfig read user
*
* FIXME: needs doc
*/
uint32_t eeconfig_read_user(void) { return eeprom_read_dword(EECONFIG_USER); }
/** \brief eeconfig update user
*
* FIXME: needs doc
*/
void eeconfig_update_user(uint32_t val) { eeprom_update_dword(EECONFIG_USER, val); }

View file

@ -23,21 +23,42 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEED
#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF
/* eeprom parameteter address */
#if !defined(STM32_EEPROM_ENABLE)
#define EECONFIG_MAGIC (uint16_t *)0
#define EECONFIG_DEBUG (uint8_t *)2
#define EECONFIG_DEFAULT_LAYER (uint8_t *)3
#define EECONFIG_KEYMAP (uint8_t *)4
#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5
#define EECONFIG_BACKLIGHT (uint8_t *)6
#define EECONFIG_AUDIO (uint8_t *)7
#define EECONFIG_DEBUG (uint8_t *)2
#define EECONFIG_DEFAULT_LAYER (uint8_t *)3
#define EECONFIG_KEYMAP (uint8_t *)4
#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5
#define EECONFIG_BACKLIGHT (uint8_t *)6
#define EECONFIG_AUDIO (uint8_t *)7
#define EECONFIG_RGBLIGHT (uint32_t *)8
#define EECONFIG_UNICODEMODE (uint8_t *)12
#define EECONFIG_STENOMODE (uint8_t *)13
// EEHANDS for two handed boards
#define EECONFIG_HANDEDNESS (uint8_t *)14
#define EECONFIG_HANDEDNESS (uint8_t *)14
#define EECONFIG_KEYBOARD (uint32_t *)15
#define EECONFIG_USER (uint32_t *)19
#else
/* STM32F3 uses 16byte block. Reconfigure memory map */
#define EECONFIG_MAGIC (uint16_t *)0
#define EECONFIG_DEBUG (uint8_t *)1
#define EECONFIG_DEFAULT_LAYER (uint8_t *)2
#define EECONFIG_KEYMAP (uint8_t *)3
#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)4
#define EECONFIG_BACKLIGHT (uint8_t *)5
#define EECONFIG_AUDIO (uint8_t *)6
#define EECONFIG_RGBLIGHT (uint32_t *)7
#define EECONFIG_UNICODEMODE (uint8_t *)9
#define EECONFIG_STENOMODE (uint8_t *)10
// EEHANDS for two handed boards
#define EECONFIG_HANDEDNESS (uint8_t *)11
#define EECONFIG_KEYBOARD (uint32_t *)12
#define EECONFIG_USER (uint32_t *)14
#endif
/* debug bit */
#define EECONFIG_DEBUG_ENABLE (1<<0)
@ -57,8 +78,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
bool eeconfig_is_enabled(void);
bool eeconfig_is_disabled(void);
void eeconfig_init(void);
void eeconfig_init_quantum(void);
void eeconfig_init_kb(void);
void eeconfig_init_user(void);
void eeconfig_enable(void);
@ -83,4 +108,9 @@ uint8_t eeconfig_read_audio(void);
void eeconfig_update_audio(uint8_t val);
#endif
uint32_t eeconfig_read_kb(void);
void eeconfig_update_kb(uint32_t val);
uint32_t eeconfig_read_user(void);
void eeconfig_update_user(uint32_t val);
#endif

View file

@ -22,6 +22,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "util.h"
#include "debug.h"
#ifdef NKRO_ENABLE
#include "keycode_config.h"
extern keymap_config_t keymap_config;
#endif
static host_driver_t *driver;
static uint16_t last_system_report = 0;
static uint16_t last_consumer_report = 0;
@ -46,6 +51,20 @@ uint8_t host_keyboard_leds(void)
void host_keyboard_send(report_keyboard_t *report)
{
if (!driver) return;
#if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP)
if (keyboard_protocol && keymap_config.nkro) {
/* The callers of this function assume that report->mods is where mods go in.
* But report->nkro.mods can be at a different offset if core keyboard does not have a report ID.
*/
report->nkro.mods = report->mods;
report->nkro.report_id = REPORT_ID_NKRO;
} else
#endif
{
#ifdef KEYBOARD_SHARED_EP
report->report_id = REPORT_ID_KEYBOARD;
#endif
}
(*driver->send_keyboard)(report);
if (debug_keyboard) {
@ -60,6 +79,9 @@ void host_keyboard_send(report_keyboard_t *report)
void host_mouse_send(report_mouse_t *report)
{
if (!driver) return;
#ifdef MOUSE_SHARED_EP
report->report_id = REPORT_ID_MOUSE;
#endif
(*driver->send_mouse)(report);
}

View file

@ -73,6 +73,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef HD44780_ENABLE
# include "hd44780.h"
#endif
#ifdef QWIIC_ENABLE
# include "qwiic.h"
#endif
#ifdef MATRIX_HAS_GHOST
extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
@ -121,6 +124,14 @@ static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata)
#endif
void disable_jtag(void) {
// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
#if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
MCUCR |= _BV(JTD);
MCUCR |= _BV(JTD);
#endif
}
/** \brief matrix_setup
*
* FIXME: needs doc
@ -134,6 +145,7 @@ void matrix_setup(void) {
* FIXME: needs doc
*/
void keyboard_setup(void) {
disable_jtag();
matrix_setup();
}
@ -152,13 +164,11 @@ bool is_keyboard_master(void) {
*/
void keyboard_init(void) {
timer_init();
// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
#if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
MCUCR |= _BV(JTD);
MCUCR |= _BV(JTD);
#endif
matrix_init();
matrix_debounce_init();
#ifdef QWIIC_ENABLE
qwiic_init();
#endif
#ifdef PS2_MOUSE_ENABLE
ps2_mouse_init();
#endif
@ -256,6 +266,10 @@ void keyboard_task(void)
MATRIX_LOOP_END:
#ifdef QWIIC_ENABLE
qwiic_task();
#endif
#ifdef MOUSEKEY_ENABLE
// mousekey repeat & acceleration
mousekey_task();

View file

@ -57,6 +57,8 @@ static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) &&
.time = (timer_read() | 1) \
}
void disable_jtag(void);
/* it runs once at early stage of startup before keyboard_init. */
void keyboard_setup(void);
/* it runs once after initializing host side protocol, debug and MCU peripherals. */

View file

@ -33,7 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
#define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE)
#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_MRWD)
#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_BRID)
#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31)
@ -140,6 +140,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_LWIN KC_LGUI
#define KC_RCTL KC_RCTRL
#define KC_RSFT KC_RSHIFT
#define KC_ALGR KC_RALT
#define KC_RCMD KC_RGUI
#define KC_RWIN KC_RGUI
@ -170,6 +171,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_WFAV KC_WWW_FAVORITES
#define KC_MFFD KC_MEDIA_FAST_FORWARD
#define KC_MRWD KC_MEDIA_REWIND
#define KC_BRIU KC_BRIGHTNESS_UP
#define KC_BRID KC_BRIGHTNESS_DOWN
/* Mouse Keys */
#define KC_MS_U KC_MS_UP
@ -457,6 +460,8 @@ enum internal_special_keycodes {
KC_WWW_FAVORITES,
KC_MEDIA_FAST_FORWARD,
KC_MEDIA_REWIND,
KC_BRIGHTNESS_UP,
KC_BRIGHTNESS_DOWN,
/* Fn keys */
KC_FN0 = 0xC0,

View file

@ -29,7 +29,7 @@
#include <stdbool.h>
#include "util.h"
#if defined(PROTOCOL_CHIBIOS)
#if defined(PROTOCOL_CHIBIOS) || defined(PROTOCOL_ARM_ATSAM)
#define PSTR(x) x
#endif
@ -60,7 +60,7 @@
# define println(s) xputs(PSTR(s "\r\n"))
# define uprint(s) print(s)
# define uprintln(s) println(s)
# define uprintf(fmt, ...) xprintf(fmt, ...)
# define uprintf(fmt, ...) xprintf(fmt, ##__VA_ARGS__)
# endif /* USER_PRINT / NORMAL PRINT */
@ -73,7 +73,9 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
#elif defined(PROTOCOL_CHIBIOS) /* PROTOCOL_CHIBIOS */
#ifndef TERMINAL_ENABLE
# include "chibios/printf.h"
#endif
# ifdef USER_PRINT /* USER_PRINT */
@ -99,6 +101,34 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
# endif /* USER_PRINT / NORMAL PRINT */
#elif defined(PROTOCOL_ARM_ATSAM) /* PROTOCOL_ARM_ATSAM */
# include "arm_atsam/printf.h"
# ifdef USER_PRINT /* USER_PRINT */
// Remove normal print defines
# define print(s)
# define println(s)
# define xprintf(fmt, ...)
// Create user print defines
# define uprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
# define uprint(s) xprintf(s)
# define uprintln(s) xprintf(s "\r\n")
# else /* NORMAL PRINT */
// Create user & normal print defines
# define xprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
# define print(s) xprintf(s)
# define println(s) xprintf(s "\r\n")
# define uprint(s) print(s)
# define uprintln(s) println(s)
# define uprintf(fmt, ...) xprintf(fmt, ##__VA_ARGS__)
# endif /* USER_PRINT / NORMAL PRINT */
#elif defined(__arm__) /* __arm__ */
# include "mbed/xprintf.h"
@ -111,26 +141,26 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
# define xprintf(fmt, ...)
// Create user print defines
# define uprintf(fmt, ...) __xprintf(fmt, ...)
# define uprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
# define uprint(s) xprintf(s)
# define uprintln(s) xprintf(s "\r\n")
# else /* NORMAL PRINT */
// Create user & normal print defines
# define xprintf(fmt, ...) __xprintf(fmt, ...)
# define xprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
# define print(s) xprintf(s)
# define println(s) xprintf(s "\r\n")
# define uprint(s) print(s)
# define uprintln(s) println(s)
# define uprintf(fmt, ...) xprintf(fmt, ...)
# define uprintf(fmt, ...) xprintf(fmt, ##__VA_ARGS__)
# endif /* USER_PRINT / NORMAL PRINT */
/* TODO: to select output destinations: UART/USBSerial */
# define print_set_sendchar(func)
#endif /* __AVR__ / PROTOCOL_CHIBIOS / __arm__ */
#endif /* __AVR__ / PROTOCOL_CHIBIOS / PROTOCOL_ARM_ATSAM / __arm__ */
// User print disables the normal print messages in the body of QMK/TMK code and
// is meant as a lightweight alternative to NOPRINT. Use it when you only want to do

View file

@ -19,6 +19,7 @@
#include "keycode_config.h"
#include "debug.h"
#include "util.h"
#include <string.h>
/** \brief has_anykey
*
@ -27,8 +28,16 @@
uint8_t has_anykey(report_keyboard_t* keyboard_report)
{
uint8_t cnt = 0;
for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
if (keyboard_report->raw[i])
uint8_t *p = keyboard_report->keys;
uint8_t lp = sizeof(keyboard_report->keys);
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
p = keyboard_report->nkro.bits;
lp = sizeof(keyboard_report->nkro.bits);
}
#endif
while (lp--) {
if (*p++)
cnt++;
}
return cnt;
@ -237,7 +246,11 @@ void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key)
void clear_keys_from_report(report_keyboard_t* keyboard_report)
{
// not clear mods
for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
keyboard_report->raw[i] = 0;
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits));
return;
}
#endif
memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys));
}

View file

@ -23,9 +23,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* report id */
#define REPORT_ID_MOUSE 1
#define REPORT_ID_SYSTEM 2
#define REPORT_ID_CONSUMER 3
#define REPORT_ID_KEYBOARD 1
#define REPORT_ID_MOUSE 2
#define REPORT_ID_SYSTEM 3
#define REPORT_ID_CONSUMER 4
#define REPORT_ID_NKRO 5
/* mouse buttons */
#define MOUSE_BTN1 (1<<0)
@ -36,6 +38,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Consumer Page(0x0C)
* following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
* see also https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/display-brightness-control
*/
#define AUDIO_MUTE 0x00E2
#define AUDIO_VOL_UP 0x00E9
@ -45,6 +48,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define TRANSPORT_STOP 0x00B7
#define TRANSPORT_STOP_EJECT 0x00CC
#define TRANSPORT_PLAY_PAUSE 0x00CD
#define BRIGHTNESSUP 0x006F
#define BRIGHTNESSDOWN 0x0070
/* application launch */
#define AL_CC_CONFIG 0x0183
#define AL_EMAIL 0x018A
@ -72,27 +77,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SYSTEM_WAKE_UP 0x0083
#define NKRO_SHARED_EP
/* key report size(NKRO or boot mode) */
#if defined(NKRO_ENABLE)
#if defined(PROTOCOL_PJRC)
#include "usb.h"
#define KEYBOARD_REPORT_SIZE KBD2_SIZE
#define KEYBOARD_REPORT_KEYS (KBD2_SIZE - 2)
#define KEYBOARD_REPORT_BITS (KBD2_SIZE - 1)
#elif defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
#if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
#include "protocol/usb_descriptor.h"
#define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
#define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
#define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2)
#elif defined(PROTOCOL_ARM_ATSAM)
#include "protocol/arm_atsam/usb/udi_device_epsize.h"
#define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
#undef NKRO_SHARED_EP
#undef MOUSE_SHARED_EP
#else
#error "NKRO not supported with this protocol"
#endif
#endif
#ifdef KEYBOARD_SHARED_EP
# define KEYBOARD_REPORT_SIZE 9
#else
# define KEYBOARD_REPORT_SIZE 8
# define KEYBOARD_REPORT_KEYS 6
#endif
#define KEYBOARD_REPORT_KEYS 6
/* VUSB hardcodes keyboard and mouse+extrakey only */
#if defined(PROTOCOL_VUSB)
#undef KEYBOARD_SHARED_EP
#undef MOUSE_SHARED_EP
#endif
#ifdef __cplusplus
extern "C" {
@ -121,12 +134,18 @@ extern "C" {
typedef union {
uint8_t raw[KEYBOARD_REPORT_SIZE];
struct {
#ifdef KEYBOARD_SHARED_EP
uint8_t report_id;
#endif
uint8_t mods;
uint8_t reserved;
uint8_t keys[KEYBOARD_REPORT_KEYS];
};
#ifdef NKRO_ENABLE
struct {
struct nkro_report {
#ifdef NKRO_SHARED_EP
uint8_t report_id;
#endif
uint8_t mods;
uint8_t bits[KEYBOARD_REPORT_BITS];
} nkro;
@ -134,6 +153,9 @@ typedef union {
} __attribute__ ((packed)) report_keyboard_t;
typedef struct {
#ifdef MOUSE_SHARED_EP
uint8_t report_id;
#endif
uint8_t buttons;
int8_t x;
int8_t y;
@ -170,7 +192,9 @@ typedef struct {
(key == KC_WWW_FORWARD ? AC_FORWARD : \
(key == KC_WWW_STOP ? AC_STOP : \
(key == KC_WWW_REFRESH ? AC_REFRESH : \
(key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0)))))))))))))))))))))
(key == KC_BRIGHTNESS_UP ? BRIGHTNESSUP : \
(key == KC_BRIGHTNESS_DOWN ? BRIGHTNESSDOWN : \
(key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0)))))))))))))))))))))))
uint8_t has_anykey(report_keyboard_t* keyboard_report);
uint8_t get_first_key(report_keyboard_t* keyboard_report);