diff options
Diffstat (limited to 'quantum')
82 files changed, 723 insertions, 6320 deletions
diff --git a/quantum/action.c b/quantum/action.c index be135f18f2..95f39d23d4 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "keycode.h" #include "keyboard.h" #include "mousekey.h" +#include "programmable_button.h" #include "command.h" #include "led.h" #include "action_layer.h" @@ -988,6 +989,10 @@ void clear_keyboard_but_mods_and_keys() { mousekey_clear(); mousekey_send(); #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE + programmable_button_clear(); + programmable_button_send(); +#endif } /** \brief Utilities for actions. (FIXME: Needs better description) diff --git a/quantum/api.c b/quantum/api.c deleted file mode 100644 index 1685744589..0000000000 --- a/quantum/api.c +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright 2016 Jack Humbert - * - * 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 "api.h" -#include "quantum.h" - -void dword_to_bytes(uint32_t dword, uint8_t* bytes) { - bytes[0] = (dword >> 24) & 0xFF; - bytes[1] = (dword >> 16) & 0xFF; - bytes[2] = (dword >> 8) & 0xFF; - bytes[3] = (dword >> 0) & 0xFF; -} - -uint32_t bytes_to_dword(uint8_t* bytes, uint8_t index) { return ((uint32_t)bytes[index + 0] << 24) | ((uint32_t)bytes[index + 1] << 16) | ((uint32_t)bytes[index + 2] << 8) | (uint32_t)bytes[index + 3]; } - -__attribute__((weak)) bool process_api_quantum(uint8_t length, uint8_t* data) { return process_api_keyboard(length, data); } - -__attribute__((weak)) bool process_api_keyboard(uint8_t length, uint8_t* data) { return process_api_user(length, data); } - -__attribute__((weak)) bool process_api_user(uint8_t length, uint8_t* data) { return true; } - -void process_api(uint16_t length, uint8_t* data) { - // SEND_STRING("\nRX: "); - // for (uint8_t i = 0; i < length; i++) { - // send_byte(data[i]); - // SEND_STRING(" "); - // } - if (!process_api_quantum(length, data)) return; - - switch (data[0]) { - case MT_SET_DATA: - switch (data[1]) { - case DT_DEFAULT_LAYER: { - eeconfig_update_default_layer(data[2]); - default_layer_set((uint32_t)(data[2])); - break; - } - case DT_KEYMAP_OPTIONS: { - eeconfig_update_keymap(data[2]); - break; - } - case DT_RGBLIGHT: { -#ifdef RGBLIGHT_ENABLE - uint32_t rgblight = bytes_to_dword(data, 2); - eeconfig_update_rgblight(rgblight); -#endif - break; - } - } - case MT_GET_DATA: - switch (data[1]) { - case DT_HANDSHAKE: { - MT_GET_DATA_ACK(DT_HANDSHAKE, NULL, 0); - break; - } - case DT_DEBUG: { - uint8_t debug_bytes[1] = {eeprom_read_byte(EECONFIG_DEBUG)}; - MT_GET_DATA_ACK(DT_DEBUG, debug_bytes, 1); - break; - } - case DT_DEFAULT_LAYER: { - uint8_t default_bytes[1] = {eeprom_read_byte(EECONFIG_DEFAULT_LAYER)}; - MT_GET_DATA_ACK(DT_DEFAULT_LAYER, default_bytes, 1); - break; - } - case DT_CURRENT_LAYER: { - uint8_t layer_state_bytes[4]; - dword_to_bytes(layer_state, layer_state_bytes); - MT_GET_DATA_ACK(DT_CURRENT_LAYER, layer_state_bytes, 4); - break; - } - case DT_AUDIO: { -#ifdef AUDIO_ENABLE - uint8_t audio_bytes[1] = {eeprom_read_byte(EECONFIG_AUDIO)}; - MT_GET_DATA_ACK(DT_AUDIO, audio_bytes, 1); -#else - MT_GET_DATA_ACK(DT_AUDIO, NULL, 0); -#endif - break; - } - case DT_BACKLIGHT: { -#ifdef BACKLIGHT_ENABLE - uint8_t backlight_bytes[1] = {eeprom_read_byte(EECONFIG_BACKLIGHT)}; - MT_GET_DATA_ACK(DT_BACKLIGHT, backlight_bytes, 1); -#else - MT_GET_DATA_ACK(DT_BACKLIGHT, NULL, 0); -#endif - break; - } - case DT_RGBLIGHT: { -#ifdef RGBLIGHT_ENABLE - uint8_t rgblight_bytes[4]; - dword_to_bytes(eeconfig_read_rgblight(), rgblight_bytes); - MT_GET_DATA_ACK(DT_RGBLIGHT, rgblight_bytes, 4); -#else - MT_GET_DATA_ACK(DT_RGBLIGHT, NULL, 0); -#endif - break; - } - case DT_KEYMAP_OPTIONS: { - uint8_t keymap_bytes[1] = {eeconfig_read_keymap()}; - MT_GET_DATA_ACK(DT_KEYMAP_OPTIONS, keymap_bytes, 1); - break; - } - case DT_KEYMAP_SIZE: { - uint8_t keymap_size[2] = {MATRIX_ROWS, MATRIX_COLS}; - MT_GET_DATA_ACK(DT_KEYMAP_SIZE, keymap_size, 2); - break; - } - // This may be too much - // case DT_KEYMAP: { - // uint8_t keymap_data[MATRIX_ROWS * MATRIX_COLS * 4 + 3]; - // keymap_data[0] = data[2]; - // keymap_data[1] = MATRIX_ROWS; - // keymap_data[2] = MATRIX_COLS; - // for (int i = 0; i < MATRIX_ROWS; i++) { - // for (int j = 0; j < MATRIX_COLS; j++) { - // keymap_data[3 + (i*MATRIX_COLS*2) + (j*2)] = pgm_read_word(&keymaps[data[2]][i][j]) >> 8; - // keymap_data[3 + (i*MATRIX_COLS*2) + (j*2) + 1] = pgm_read_word(&keymaps[data[2]][i][j]) & 0xFF; - // } - // } - // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, MATRIX_ROWS * MATRIX_COLS * 4 + 3); - // // uint8_t keymap_data[5]; - // // keymap_data[0] = data[2]; - // // keymap_data[1] = data[3]; - // // keymap_data[2] = data[4]; - // // keymap_data[3] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) >> 8; - // // keymap_data[4] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) & 0xFF; - - // // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, 5); - // break; - // } - default: - break; - } - break; - case MT_SET_DATA_ACK: - case MT_GET_DATA_ACK: - break; - case MT_SEND_DATA: - break; - case MT_SEND_DATA_ACK: - break; - case MT_EXE_ACTION: - break; - case MT_EXE_ACTION_ACK: - break; - case MT_TYPE_ERROR: - break; - default:; // command not recognised - SEND_BYTES(MT_TYPE_ERROR, DT_NONE, data, length); - break; - - // #ifdef RGBLIGHT_ENABLE - // case 0x27: ; // RGB LED functions - // switch (*data++) { - // case 0x00: ; // Update HSV - // rgblight_sethsv((data[0] << 8 | data[1]) % 360, data[2], data[3]); - // break; - // case 0x01: ; // Update RGB - // break; - // case 0x02: ; // Update mode - // rgblight_mode(data[0]); - // break; - // } - // break; - // #endif - } -} diff --git a/quantum/api.h b/quantum/api.h deleted file mode 100644 index 0a30e9d6cc..0000000000 --- a/quantum/api.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2016 Jack Humbert - * - * 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 - -#ifdef __AVR__ -# include "lufa.h" -#endif - -enum MESSAGE_TYPE { - MT_GET_DATA = 0x10, // Get data from keyboard - MT_GET_DATA_ACK = 0x11, // returned data to process (ACK) - MT_SET_DATA = 0x20, // Set data on keyboard - MT_SET_DATA_ACK = 0x21, // returned data to confirm (ACK) - MT_SEND_DATA = 0x30, // Sending data/action from keyboard - MT_SEND_DATA_ACK = 0x31, // returned data/action confirmation (ACK) - MT_EXE_ACTION = 0x40, // executing actions on keyboard - MT_EXE_ACTION_ACK = 0x41, // return confirmation/value (ACK) - MT_TYPE_ERROR = 0x80 // type not recognised (ACK) -}; - -enum DATA_TYPE { DT_NONE = 0x00, DT_HANDSHAKE, DT_DEFAULT_LAYER, DT_CURRENT_LAYER, DT_KEYMAP_OPTIONS, DT_BACKLIGHT, DT_RGBLIGHT, DT_UNICODE, DT_DEBUG, DT_AUDIO, DT_QUANTUM_ACTION, DT_KEYBOARD_ACTION, DT_USER_ACTION, DT_KEYMAP_SIZE, DT_KEYMAP }; - -void dword_to_bytes(uint32_t dword, uint8_t* bytes); -uint32_t bytes_to_dword(uint8_t* bytes, uint8_t index); - -#define MT_GET_DATA(data_type, data, length) SEND_BYTES(MT_GET_DATA, data_type, data, length) -#define MT_GET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_GET_DATA_ACK, data_type, data, length) -#define MT_SET_DATA(data_type, data, length) SEND_BYTES(MT_SET_DATA, data_type, data, length) -#define MT_SET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SET_DATA_ACK, data_type, data, length) -#define MT_SEND_DATA(data_type, data, length) SEND_BYTES(MT_SEND_DATA, data_type, data, length) -#define MT_SEND_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SEND_DATA_ACK, data_type, data, length) -#define MT_EXE_ACTION(data_type, data, length) SEND_BYTES(MT_EXE_ACTION, data_type, data, length) -#define MT_EXE_ACTION_ACK(data_type, data, length) SEND_BYTES(MT_EXE_ACTION_ACK, data_type, data, length) - -void process_api(uint16_t length, uint8_t* data); - -__attribute__((weak)) bool process_api_quantum(uint8_t length, uint8_t* data); - -__attribute__((weak)) bool process_api_keyboard(uint8_t length, uint8_t* data); - -__attribute__((weak)) bool process_api_user(uint8_t length, uint8_t* data); diff --git a/quantum/api/api_sysex.c b/quantum/api/api_sysex.c deleted file mode 100644 index 07c90cf804..0000000000 --- a/quantum/api/api_sysex.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright 2016 Jack Humbert, 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 "api_sysex.h" -#include "sysex_tools.h" -#include "print.h" -#include "qmk_midi.h" - -void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t* bytes, uint16_t length) { - // SEND_STRING("\nTX: "); - // for (uint8_t i = 0; i < length; i++) { - // send_byte(bytes[i]); - // SEND_STRING(" "); - // } - if (length > API_SYSEX_MAX_SIZE) { - xprintf("Sysex msg too big %d %d %d", message_type, data_type, length); - return; - } - - // The buffer size required is calculated as the following - // API_SYSEX_MAX_SIZE is the maximum length - // In addition to that we have a two byte message header consisting of the message_type and data_type - // This has to be encoded with an additional overhead of one byte for every starting 7 bytes - // We just add one extra byte in case it's not divisible by 7 - // Then we have an unencoded header consisting of 4 bytes - // Plus a one byte terminator - const unsigned message_header = 2; - const unsigned unencoded_message = API_SYSEX_MAX_SIZE + message_header; - const unsigned encoding_overhead = unencoded_message / 7 + 1; - const unsigned encoded_size = unencoded_message + encoding_overhead; - const unsigned unencoded_header = 4; - const unsigned terminator = 1; - const unsigned buffer_size = encoded_size + unencoded_header + terminator; - uint8_t buffer[encoded_size + unencoded_header + terminator]; - // The unencoded header - buffer[0] = 0xF0; - buffer[1] = 0x00; - buffer[2] = 0x00; - buffer[3] = 0x00; - - // We copy the message to the end of the array, this way we can do an inplace encoding, using the same - // buffer for both input and output - const unsigned message_size = length + message_header; - uint8_t* unencoded_start = buffer + buffer_size - message_size; - uint8_t* ptr = unencoded_start; - *(ptr++) = message_type; - *(ptr++) = data_type; - memcpy(ptr, bytes, length); - - unsigned encoded_length = sysex_encode(buffer + unencoded_header, unencoded_start, message_size); - unsigned final_size = unencoded_header + encoded_length + terminator; - buffer[final_size - 1] = 0xF7; - midi_send_array(&midi_device, final_size, buffer); - - // SEND_STRING("\nTD: "); - // for (uint8_t i = 0; i < encoded_length + 5; i++) { - // send_byte(buffer[i]); - // SEND_STRING(" "); - // } -} diff --git a/quantum/api/api_sysex.h b/quantum/api/api_sysex.h deleted file mode 100644 index eb0a18848d..0000000000 --- a/quantum/api/api_sysex.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright 2016 Jack Humbert - * - * 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 - -#include "api.h" - -#define API_SYSEX_MAX_SIZE 32 - -void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t* bytes, uint16_t length); - -#define SEND_BYTES(mt, dt, b, l) send_bytes_sysex(mt, dt, b, l) diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index 56b9158a1a..290d461f5a 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h @@ -26,17 +26,12 @@ #if defined(__AVR__) # include <avr/io.h> -# if defined(AUDIO_DRIVER_PWM) -# include "driver_avr_pwm.h" -# endif #endif -#if defined(PROTOCOL_CHIBIOS) -# if defined(AUDIO_DRIVER_PWM) -# include "driver_chibios_pwm.h" -# elif defined(AUDIO_DRIVER_DAC) -# include "driver_chibios_dac.h" -# endif +#if defined(AUDIO_DRIVER_PWM) +# include "audio_pwm.h" +#elif defined(AUDIO_DRIVER_DAC) +# include "audio_dac.h" #endif typedef union { diff --git a/quantum/audio/driver_avr_pwm.h b/quantum/audio/driver_avr_pwm.h deleted file mode 100644 index d6eb3571da..0000000000 --- a/quantum/audio/driver_avr_pwm.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright 2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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 diff --git a/quantum/audio/driver_avr_pwm_hardware.c b/quantum/audio/driver_avr_pwm_hardware.c deleted file mode 100644 index df03a4558c..0000000000 --- a/quantum/audio/driver_avr_pwm_hardware.c +++ /dev/null @@ -1,332 +0,0 @@ -/* Copyright 2016 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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/>. - */ - -#if defined(__AVR__) -# include <avr/pgmspace.h> -# include <avr/interrupt.h> -# include <avr/io.h> -#endif - -#include "audio.h" - -extern bool playing_note; -extern bool playing_melody; -extern uint8_t note_timbre; - -#define CPU_PRESCALER 8 - -/* - Audio Driver: PWM - - drive up to two speakers through the AVR PWM hardware-peripheral, using timer1 and/or timer3 on Atmega32U4. - - the primary channel_1 can be connected to either pin PC4 PC5 or PC6 (the later being used by most AVR based keyboards) with a PMW signal generated by timer3 - and an optional secondary channel_2 on either pin PB5, PB6 or PB7, with a PWM signal from timer1 - - alternatively, the PWM pins on PORTB can be used as only/primary speaker -*/ - -#if defined(AUDIO_PIN) && (AUDIO_PIN != C4) && (AUDIO_PIN != C5) && (AUDIO_PIN != C6) && (AUDIO_PIN != B5) && (AUDIO_PIN != B6) && (AUDIO_PIN != B7) && (AUDIO_PIN != D5) -# error "Audio feature enabled, but no suitable pin selected as AUDIO_PIN - see docs/feature_audio under the AVR settings for available options." -#endif - -#if (AUDIO_PIN == C4) || (AUDIO_PIN == C5) || (AUDIO_PIN == C6) -# define AUDIO1_PIN_SET -# define AUDIO1_TIMSKx TIMSK3 -# define AUDIO1_TCCRxA TCCR3A -# define AUDIO1_TCCRxB TCCR3B -# define AUDIO1_ICRx ICR3 -# define AUDIO1_WGMx0 WGM30 -# define AUDIO1_WGMx1 WGM31 -# define AUDIO1_WGMx2 WGM32 -# define AUDIO1_WGMx3 WGM33 -# define AUDIO1_CSx0 CS30 -# define AUDIO1_CSx1 CS31 -# define AUDIO1_CSx2 CS32 - -# if (AUDIO_PIN == C6) -# define AUDIO1_COMxy0 COM3A0 -# define AUDIO1_COMxy1 COM3A1 -# define AUDIO1_OCIExy OCIE3A -# define AUDIO1_OCRxy OCR3A -# define AUDIO1_PIN C6 -# define AUDIO1_TIMERx_COMPy_vect TIMER3_COMPA_vect -# elif (AUDIO_PIN == C5) -# define AUDIO1_COMxy0 COM3B0 -# define AUDIO1_COMxy1 COM3B1 -# define AUDIO1_OCIExy OCIE3B -# define AUDIO1_OCRxy OCR3B -# define AUDIO1_PIN C5 -# define AUDIO1_TIMERx_COMPy_vect TIMER3_COMPB_vect -# elif (AUDIO_PIN == C4) -# define AUDIO1_COMxy0 COM3C0 -# define AUDIO1_COMxy1 COM3C1 -# define AUDIO1_OCIExy OCIE3C -# define AUDIO1_OCRxy OCR3C -# define AUDIO1_PIN C4 -# define AUDIO1_TIMERx_COMPy_vect TIMER3_COMPC_vect -# endif -#endif - -#if defined(AUDIO_PIN) && defined(AUDIO_PIN_ALT) && (AUDIO_PIN == AUDIO_PIN_ALT) -# error "Audio feature: AUDIO_PIN and AUDIO_PIN_ALT on the same pin makes no sense." -#endif - -#if ((AUDIO_PIN == B5) && ((AUDIO_PIN_ALT == B6) || (AUDIO_PIN_ALT == B7))) || ((AUDIO_PIN == B6) && ((AUDIO_PIN_ALT == B5) || (AUDIO_PIN_ALT == B7))) || ((AUDIO_PIN == B7) && ((AUDIO_PIN_ALT == B5) || (AUDIO_PIN_ALT == B6))) -# error "Audio feature: PORTB as AUDIO_PIN and AUDIO_PIN_ALT at the same time is not supported." -#endif - -#if defined(AUDIO_PIN_ALT) && (AUDIO_PIN_ALT != B5) && (AUDIO_PIN_ALT != B6) && (AUDIO_PIN_ALT != B7) -# error "Audio feature: the pin selected as AUDIO_PIN_ALT is not supported." -#endif - -#if (AUDIO_PIN == B5) || (AUDIO_PIN == B6) || (AUDIO_PIN == B7) || (AUDIO_PIN_ALT == B5) || (AUDIO_PIN_ALT == B6) || (AUDIO_PIN_ALT == B7) || (AUDIO_PIN == D5) -# define AUDIO2_PIN_SET -# define AUDIO2_TIMSKx TIMSK1 -# define AUDIO2_TCCRxA TCCR1A -# define AUDIO2_TCCRxB TCCR1B -# define AUDIO2_ICRx ICR1 -# define AUDIO2_WGMx0 WGM10 -# define AUDIO2_WGMx1 WGM11 -# define AUDIO2_WGMx2 WGM12 -# define AUDIO2_WGMx3 WGM13 -# define AUDIO2_CSx0 CS10 -# define AUDIO2_CSx1 CS11 -# define AUDIO2_CSx2 CS12 - -# if (AUDIO_PIN == B5) || (AUDIO_PIN_ALT == B5) -# define AUDIO2_COMxy0 COM1A0 -# define AUDIO2_COMxy1 COM1A1 -# define AUDIO2_OCIExy OCIE1A -# define AUDIO2_OCRxy OCR1A -# define AUDIO2_PIN B5 -# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPA_vect -# elif (AUDIO_PIN == B6) || (AUDIO_PIN_ALT == B6) -# define AUDIO2_COMxy0 COM1B0 -# define AUDIO2_COMxy1 COM1B1 -# define AUDIO2_OCIExy OCIE1B -# define AUDIO2_OCRxy OCR1B -# define AUDIO2_PIN B6 -# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPB_vect -# elif (AUDIO_PIN == B7) || (AUDIO_PIN_ALT == B7) -# define AUDIO2_COMxy0 COM1C0 -# define AUDIO2_COMxy1 COM1C1 -# define AUDIO2_OCIExy OCIE1C -# define AUDIO2_OCRxy OCR1C -# define AUDIO2_PIN B7 -# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPC_vect -# elif (AUDIO_PIN == D5) && defined(__AVR_ATmega32A__) -# pragma message "Audio support for ATmega32A is experimental and can cause crashes." -# undef AUDIO2_TIMSKx -# define AUDIO2_TIMSKx TIMSK -# define AUDIO2_COMxy0 COM1A0 -# define AUDIO2_COMxy1 COM1A1 -# define AUDIO2_OCIExy OCIE1A -# define AUDIO2_OCRxy OCR1A -# define AUDIO2_PIN D5 -# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPA_vect -# endif -#endif - -// C6 seems to be the assumed default by many existing keyboard - but sill warn the user -#if !defined(AUDIO1_PIN_SET) && !defined(AUDIO2_PIN_SET) -# pragma message "Audio feature enabled, but no suitable pin selected - see docs/feature_audio under the AVR settings for available options. Don't expect to hear anything... :-)" -// TODO: make this an error - go through the breaking-change-process and change all keyboards to the new define -#endif -// ----------------------------------------------------------------------------- - -#ifdef AUDIO1_PIN_SET -static float channel_1_frequency = 0.0f; -void channel_1_set_frequency(float freq) { - if (freq == 0.0f) // a pause/rest is a valid "note" with freq=0 - { - // disable the output, but keep the pwm-ISR going (with the previous - // frequency) so the audio-state keeps getting updated - // Note: setting the duty-cycle 0 is not possible on non-inverting PWM mode - see the AVR data-sheet - AUDIO1_TCCRxA &= ~(_BV(AUDIO1_COMxy1) | _BV(AUDIO1_COMxy0)); - return; - } else { - AUDIO1_TCCRxA |= _BV(AUDIO1_COMxy1); // enable output, PWM mode - } - - channel_1_frequency = freq; - - // set pwm period - AUDIO1_ICRx = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); - // and duty cycle - AUDIO1_OCRxy = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre / 100); -} - -void channel_1_start(void) { - // enable timer-counter ISR - AUDIO1_TIMSKx |= _BV(AUDIO1_OCIExy); - // enable timer-counter output - AUDIO1_TCCRxA |= _BV(AUDIO1_COMxy1); -} - -void channel_1_stop(void) { - // disable timer-counter ISR - AUDIO1_TIMSKx &= ~_BV(AUDIO1_OCIExy); - // disable timer-counter output - AUDIO1_TCCRxA &= ~(_BV(AUDIO1_COMxy1) | _BV(AUDIO1_COMxy0)); -} -#endif - -#ifdef AUDIO2_PIN_SET -static float channel_2_frequency = 0.0f; -void channel_2_set_frequency(float freq) { - if (freq == 0.0f) { - AUDIO2_TCCRxA &= ~(_BV(AUDIO2_COMxy1) | _BV(AUDIO2_COMxy0)); - return; - } else { - AUDIO2_TCCRxA |= _BV(AUDIO2_COMxy1); - } - - channel_2_frequency = freq; - - AUDIO2_ICRx = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); - AUDIO2_OCRxy = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre / 100); -} - -float channel_2_get_frequency(void) { return channel_2_frequency; } - -void channel_2_start(void) { - AUDIO2_TIMSKx |= _BV(AUDIO2_OCIExy); - AUDIO2_TCCRxA |= _BV(AUDIO2_COMxy1); -} - -void channel_2_stop(void) { - AUDIO2_TIMSKx &= ~_BV(AUDIO2_OCIExy); - AUDIO2_TCCRxA &= ~(_BV(AUDIO2_COMxy1) | _BV(AUDIO2_COMxy0)); -} -#endif - -void audio_driver_initialize() { -#ifdef AUDIO1_PIN_SET - channel_1_stop(); - setPinOutput(AUDIO1_PIN); -#endif - -#ifdef AUDIO2_PIN_SET - channel_2_stop(); - setPinOutput(AUDIO2_PIN); -#endif - - // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers TCCR3A/TCCR3B, TCCR1A/TCCR1B - // Compare Output Mode (COM3An and COM1An) = 0b00 = Normal port operation - // OC3A -- PC6 - // OC3B -- PC5 - // OC3C -- PC4 - // OC1A -- PB5 - // OC1B -- PB6 - // OC1C -- PB7 - - // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14. Period = ICR3, Duty Cycle OCR3A) - // OCR3A - PC6 - // OCR3B - PC5 - // OCR3C - PC4 - // OCR1A - PB5 - // OCR1B - PB6 - // OCR1C - PB7 - - // Clock Select (CS3n) = 0b010 = Clock / 8 -#ifdef AUDIO1_PIN_SET - // initialize timer-counter - AUDIO1_TCCRxA = (0 << AUDIO1_COMxy1) | (0 << AUDIO1_COMxy0) | (1 << AUDIO1_WGMx1) | (0 << AUDIO1_WGMx0); - AUDIO1_TCCRxB = (1 << AUDIO1_WGMx3) | (1 << AUDIO1_WGMx2) | (0 << AUDIO1_CSx2) | (1 << AUDIO1_CSx1) | (0 << AUDIO1_CSx0); -#endif - -#ifdef AUDIO2_PIN_SET - AUDIO2_TCCRxA = (0 << AUDIO2_COMxy1) | (0 << AUDIO2_COMxy0) | (1 << AUDIO2_WGMx1) | (0 << AUDIO2_WGMx0); - AUDIO2_TCCRxB = (1 << AUDIO2_WGMx3) | (1 << AUDIO2_WGMx2) | (0 << AUDIO2_CSx2) | (1 << AUDIO2_CSx1) | (0 << AUDIO2_CSx0); -#endif -} - -void audio_driver_stop() { -#ifdef AUDIO1_PIN_SET - channel_1_stop(); -#endif - -#ifdef AUDIO2_PIN_SET - channel_2_stop(); -#endif -} - -void audio_driver_start(void) { -#ifdef AUDIO1_PIN_SET - channel_1_start(); - if (playing_note) { - channel_1_set_frequency(audio_get_processed_frequency(0)); - } -#endif - -#if !defined(AUDIO1_PIN_SET) && defined(AUDIO2_PIN_SET) - channel_2_start(); - if (playing_note) { - channel_2_set_frequency(audio_get_processed_frequency(0)); - } -#endif -} - -static volatile uint32_t isr_counter = 0; -#ifdef AUDIO1_PIN_SET -ISR(AUDIO1_TIMERx_COMPy_vect) { - isr_counter++; - if (isr_counter < channel_1_frequency / (CPU_PRESCALER * 8)) return; - - isr_counter = 0; - bool state_changed = audio_update_state(); - - if (!playing_note && !playing_melody) { - channel_1_stop(); -# ifdef AUDIO2_PIN_SET - channel_2_stop(); -# endif - return; - } - - if (state_changed) { - channel_1_set_frequency(audio_get_processed_frequency(0)); -# ifdef AUDIO2_PIN_SET - if (audio_get_number_of_active_tones() > 1) { - channel_2_set_frequency(audio_get_processed_frequency(1)); - } else { - channel_2_stop(); - } -# endif - } -} -#endif - -#if !defined(AUDIO1_PIN_SET) && defined(AUDIO2_PIN_SET) -ISR(AUDIO2_TIMERx_COMPy_vect) { - isr_counter++; - if (isr_counter < channel_2_frequency / (CPU_PRESCALER * 8)) return; - - isr_counter = 0; - bool state_changed = audio_update_state(); - - if (!playing_note && !playing_melody) { - channel_2_stop(); - return; - } - - if (state_changed) { - channel_2_set_frequency(audio_get_processed_frequency(0)); - } -} -#endif diff --git a/quantum/audio/driver_chibios_dac.h b/quantum/audio/driver_chibios_dac.h deleted file mode 100644 index 07cd622ead..0000000000 --- a/quantum/audio/driver_chibios_dac.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright 2019 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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 - -#ifndef A4 -# define A4 PAL_LINE(GPIOA, 4) -#endif -#ifndef A5 -# define A5 PAL_LINE(GPIOA, 5) -#endif - -/** - * Size of the dac_buffer arrays. All must be the same size. - */ -#define AUDIO_DAC_BUFFER_SIZE 256U - -/** - * Highest value allowed sample value. - - * since the DAC is limited to 12 bit, the absolute max is 0xfff = 4095U; - * lower values adjust the peak-voltage aka volume down. - * adjusting this value has only an effect on a sample-buffer whose values are - * are NOT pregenerated - see square-wave - */ -#ifndef AUDIO_DAC_SAMPLE_MAX -# define AUDIO_DAC_SAMPLE_MAX 4095U -#endif - -#if !defined(AUDIO_DAC_SAMPLE_RATE) && !defined(AUDIO_MAX_SIMULTANEOUS_TONES) && !defined(AUDIO_DAC_QUALITY_VERY_LOW) && !defined(AUDIO_DAC_QUALITY_LOW) && !defined(AUDIO_DAC_QUALITY_HIGH) && !defined(AUDIO_DAC_QUALITY_VERY_HIGH) -# define AUDIO_DAC_QUALITY_SANE_MINIMUM -#endif - -/** - * These presets allow you to quickly switch between quality settings for - * the DAC. The sample rate and maximum number of simultaneous tones roughly - * has an inverse relationship - slightly higher sample rates may be possible. - * - * NOTE: a high sample-rate results in a higher cpu-load, which might lead to - * (audible) discontinuities and/or starve other processes of cpu-time - * (like RGB-led back-lighting, ...) - */ -#ifdef AUDIO_DAC_QUALITY_VERY_LOW -# define AUDIO_DAC_SAMPLE_RATE 11025U -# define AUDIO_MAX_SIMULTANEOUS_TONES 8 -#endif - -#ifdef AUDIO_DAC_QUALITY_LOW -# define AUDIO_DAC_SAMPLE_RATE 22050U -# define AUDIO_MAX_SIMULTANEOUS_TONES 4 -#endif - -#ifdef AUDIO_DAC_QUALITY_HIGH -# define AUDIO_DAC_SAMPLE_RATE 44100U -# define AUDIO_MAX_SIMULTANEOUS_TONES 2 -#endif - -#ifdef AUDIO_DAC_QUALITY_VERY_HIGH -# define AUDIO_DAC_SAMPLE_RATE 88200U -# define AUDIO_MAX_SIMULTANEOUS_TONES 1 -#endif - -#ifdef AUDIO_DAC_QUALITY_SANE_MINIMUM -/* a sane-minimum config: with a trade-off between cpu-load and tone-range - * - * the (currently) highest defined note is NOTE_B8 with 7902Hz; if we now - * aim for an even even multiple of the buffer-size, we end up with: - * ( roundUptoPow2(highest note / AUDIO_DAC_BUFFER_SIZE) * nyquist-rate * AUDIO_DAC_BUFFER_SIZE) - * 7902/256 = 30.867 * 2 * 256 ~= 16384 - * which works out (but the 'scope shows some sampling artifacts with lower harmonics :-P) - */ -# define AUDIO_DAC_SAMPLE_RATE 16384U -# define AUDIO_MAX_SIMULTANEOUS_TONES 8 -#endif - -/** - * Effective bit-rate of the DAC. 44.1khz is the standard for most audio - any - * lower will sacrifice perceptible audio quality. Any higher will limit the - * number of simultaneous tones. In most situations, a tenth (1/10) of the - * sample rate is where notes become unbearable. - */ -#ifndef AUDIO_DAC_SAMPLE_RATE -# define AUDIO_DAC_SAMPLE_RATE 44100U -#endif - -/** - * The number of tones that can be played simultaneously. If too high a value - * is used here, the keyboard will freeze and glitch-out when that many tones - * are being played. - */ -#ifndef AUDIO_MAX_SIMULTANEOUS_TONES -# define AUDIO_MAX_SIMULTANEOUS_TONES 2 -#endif - -/** - * The default value of the DAC when not playing anything. Certain hardware - * setups may require a high (AUDIO_DAC_SAMPLE_MAX) or low (0) value here. - * Since multiple added sine waves tend to oscillate around the midpoint, - * and possibly never/rarely reach either 0 of MAX, 1/2 MAX can be a - * reasonable default value. - */ -#ifndef AUDIO_DAC_OFF_VALUE -# define AUDIO_DAC_OFF_VALUE AUDIO_DAC_SAMPLE_MAX / 2 -#endif - -#if AUDIO_DAC_OFF_VALUE > AUDIO_DAC_SAMPLE_MAX -# error "AUDIO_DAC: OFF_VALUE may not be larger than SAMPLE_MAX" -#endif - -/** - *user overridable sample generation/processing - */ -uint16_t dac_value_generate(void); diff --git a/quantum/audio/driver_chibios_dac_additive.c b/quantum/audio/driver_chibios_dac_additive.c deleted file mode 100644 index db304adb87..0000000000 --- a/quantum/audio/driver_chibios_dac_additive.c +++ /dev/null @@ -1,335 +0,0 @@ -/* Copyright 2016-2019 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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 "audio.h" -#include <ch.h> -#include <hal.h> - -/* - Audio Driver: DAC - - which utilizes the dac unit many STM32 are equipped with, to output a modulated waveform from samples stored in the dac_buffer_* array who are passed to the hardware through DMA - - it is also possible to have a custom sample-LUT by implementing/overriding 'dac_value_generate' - - this driver allows for multiple simultaneous tones to be played through one single channel by doing additive wave-synthesis -*/ - -#if !defined(AUDIO_PIN) -# error "Audio feature enabled, but no suitable pin selected as AUDIO_PIN - see docs/feature_audio under 'ARM (DAC additive)' for available options." -#endif -#if defined(AUDIO_PIN_ALT) && !defined(AUDIO_PIN_ALT_AS_NEGATIVE) -# pragma message "Audio feature: AUDIO_PIN_ALT set, but not AUDIO_PIN_ALT_AS_NEGATIVE - pin will be left unused; audio might still work though." -#endif - -#if !defined(AUDIO_PIN_ALT) -// no ALT pin defined is valid, but the c-ifs below need some value set -# define AUDIO_PIN_ALT PAL_NOLINE -#endif - -#if !defined(AUDIO_DAC_SAMPLE_WAVEFORM_SINE) && !defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE) && !defined(AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE) && !defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID) -# define AUDIO_DAC_SAMPLE_WAVEFORM_SINE -#endif - -#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SINE -/* one full sine wave over [0,2*pi], but shifted up one amplitude and left pi/4; for the samples to start at 0 - */ -static const dacsample_t dac_buffer_sine[AUDIO_DAC_BUFFER_SIZE] = { - // 256 values, max 4095 - 0x0, 0x1, 0x2, 0x6, 0xa, 0xf, 0x16, 0x1e, 0x27, 0x32, 0x3d, 0x4a, 0x58, 0x67, 0x78, 0x89, 0x9c, 0xb0, 0xc5, 0xdb, 0xf2, 0x10a, 0x123, 0x13e, 0x159, 0x175, 0x193, 0x1b1, 0x1d1, 0x1f1, 0x212, 0x235, 0x258, 0x27c, 0x2a0, 0x2c6, 0x2ed, 0x314, 0x33c, 0x365, 0x38e, 0x3b8, 0x3e3, 0x40e, 0x43a, 0x467, 0x494, 0x4c2, 0x4f0, 0x51f, 0x54e, 0x57d, 0x5ad, 0x5dd, 0x60e, 0x63f, 0x670, 0x6a1, 0x6d3, 0x705, 0x737, 0x769, 0x79b, 0x7cd, 0x800, 0x832, 0x864, 0x896, 0x8c8, 0x8fa, 0x92c, 0x95e, 0x98f, 0x9c0, 0x9f1, 0xa22, 0xa52, 0xa82, 0xab1, 0xae0, 0xb0f, 0xb3d, 0xb6b, 0xb98, 0xbc5, 0xbf1, 0xc1c, 0xc47, 0xc71, 0xc9a, 0xcc3, 0xceb, 0xd12, 0xd39, 0xd5f, 0xd83, 0xda7, 0xdca, 0xded, 0xe0e, 0xe2e, 0xe4e, 0xe6c, 0xe8a, 0xea6, 0xec1, 0xedc, 0xef5, 0xf0d, 0xf24, 0xf3a, 0xf4f, 0xf63, 0xf76, 0xf87, 0xf98, 0xfa7, 0xfb5, 0xfc2, 0xfcd, 0xfd8, 0xfe1, 0xfe9, 0xff0, 0xff5, 0xff9, 0xffd, 0xffe, - 0xfff, 0xffe, 0xffd, 0xff9, 0xff5, 0xff0, 0xfe9, 0xfe1, 0xfd8, 0xfcd, 0xfc2, 0xfb5, 0xfa7, 0xf98, 0xf87, 0xf76, 0xf63, 0xf4f, 0xf3a, 0xf24, 0xf0d, 0xef5, 0xedc, 0xec1, 0xea6, 0xe8a, 0xe6c, 0xe4e, 0xe2e, 0xe0e, 0xded, 0xdca, 0xda7, 0xd83, 0xd5f, 0xd39, 0xd12, 0xceb, 0xcc3, 0xc9a, 0xc71, 0xc47, 0xc1c, 0xbf1, 0xbc5, 0xb98, 0xb6b, 0xb3d, 0xb0f, 0xae0, 0xab1, 0xa82, 0xa52, 0xa22, 0x9f1, 0x9c0, 0x98f, 0x95e, 0x92c, 0x8fa, 0x8c8, 0x896, 0x864, 0x832, 0x800, 0x7cd, 0x79b, 0x769, 0x737, 0x705, 0x6d3, 0x6a1, 0x670, 0x63f, 0x60e, 0x5dd, 0x5ad, 0x57d, 0x54e, 0x51f, 0x4f0, 0x4c2, 0x494, 0x467, 0x43a, 0x40e, 0x3e3, 0x3b8, 0x38e, 0x365, 0x33c, 0x314, 0x2ed, 0x2c6, 0x2a0, 0x27c, 0x258, 0x235, 0x212, 0x1f1, 0x1d1, 0x1b1, 0x193, 0x175, 0x159, 0x13e, 0x123, 0x10a, 0xf2, 0xdb, 0xc5, 0xb0, 0x9c, 0x89, 0x78, 0x67, 0x58, 0x4a, 0x3d, 0x32, 0x27, 0x1e, 0x16, 0xf, 0xa, 0x6, 0x2, 0x1}; -#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SINE -#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE -static const dacsample_t dac_buffer_triangle[AUDIO_DAC_BUFFER_SIZE] = { - // 256 values, max 4095 - 0x0, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0x400, 0x420, 0x440, 0x460, 0x480, 0x4a0, 0x4c0, 0x4e0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5a0, 0x5c0, 0x5e0, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6a0, 0x6c0, 0x6e0, 0x700, 0x720, 0x740, 0x760, 0x780, 0x7a0, 0x7c0, 0x7e0, 0x800, 0x81f, 0x83f, 0x85f, 0x87f, 0x89f, 0x8bf, 0x8df, 0x8ff, 0x91f, 0x93f, 0x95f, 0x97f, 0x99f, 0x9bf, 0x9df, 0x9ff, 0xa1f, 0xa3f, 0xa5f, 0xa7f, 0xa9f, 0xabf, 0xadf, 0xaff, 0xb1f, 0xb3f, 0xb5f, 0xb7f, 0xb9f, 0xbbf, 0xbdf, 0xbff, 0xc1f, 0xc3f, 0xc5f, 0xc7f, 0xc9f, 0xcbf, 0xcdf, 0xcff, 0xd1f, 0xd3f, 0xd5f, 0xd7f, 0xd9f, 0xdbf, 0xddf, 0xdff, 0xe1f, 0xe3f, 0xe5f, 0xe7f, 0xe9f, 0xebf, 0xedf, 0xeff, 0xf1f, 0xf3f, 0xf5f, 0xf7f, 0xf9f, 0xfbf, 0xfdf, - 0xfff, 0xfdf, 0xfbf, 0xf9f, 0xf7f, 0xf5f, 0xf3f, 0xf1f, 0xeff, 0xedf, 0xebf, 0xe9f, 0xe7f, 0xe5f, 0xe3f, 0xe1f, 0xdff, 0xddf, 0xdbf, 0xd9f, 0xd7f, 0xd5f, 0xd3f, 0xd1f, 0xcff, 0xcdf, 0xcbf, 0xc9f, 0xc7f, 0xc5f, 0xc3f, 0xc1f, 0xbff, 0xbdf, 0xbbf, 0xb9f, 0xb7f, 0xb5f, 0xb3f, 0xb1f, 0xaff, 0xadf, 0xabf, 0xa9f, 0xa7f, 0xa5f, 0xa3f, 0xa1f, 0x9ff, 0x9df, 0x9bf, 0x99f, 0x97f, 0x95f, 0x93f, 0x91f, 0x8ff, 0x8df, 0x8bf, 0x89f, 0x87f, 0x85f, 0x83f, 0x81f, 0x800, 0x7e0, 0x7c0, 0x7a0, 0x780, 0x760, 0x740, 0x720, 0x700, 0x6e0, 0x6c0, 0x6a0, 0x680, 0x660, 0x640, 0x620, 0x600, 0x5e0, 0x5c0, 0x5a0, 0x580, 0x560, 0x540, 0x520, 0x500, 0x4e0, 0x4c0, 0x4a0, 0x480, 0x460, 0x440, 0x420, 0x400, 0x3e0, 0x3c0, 0x3a0, 0x380, 0x360, 0x340, 0x320, 0x300, 0x2e0, 0x2c0, 0x2a0, 0x280, 0x260, 0x240, 0x220, 0x200, 0x1e0, 0x1c0, 0x1a0, 0x180, 0x160, 0x140, 0x120, 0x100, 0xe0, 0xc0, 0xa0, 0x80, 0x60, 0x40, 0x20}; -#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE -#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE -static const dacsample_t dac_buffer_square[AUDIO_DAC_BUFFER_SIZE] = { - [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = 0, // first and - [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = AUDIO_DAC_SAMPLE_MAX, // second half -}; -#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE -/* -// four steps: 0, 1/3, 2/3 and 1 -static const dacsample_t dac_buffer_staircase[AUDIO_DAC_BUFFER_SIZE] = { - [0 ... AUDIO_DAC_BUFFER_SIZE/3 -1 ] = 0, - [AUDIO_DAC_BUFFER_SIZE / 4 ... AUDIO_DAC_BUFFER_SIZE / 2 -1 ] = AUDIO_DAC_SAMPLE_MAX / 3, - [AUDIO_DAC_BUFFER_SIZE / 2 ... 3 * AUDIO_DAC_BUFFER_SIZE / 4 -1 ] = 2 * AUDIO_DAC_SAMPLE_MAX / 3, - [3 * AUDIO_DAC_BUFFER_SIZE / 4 ... AUDIO_DAC_BUFFER_SIZE -1 ] = AUDIO_DAC_SAMPLE_MAX, -} -*/ -#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID -static const dacsample_t dac_buffer_trapezoid[AUDIO_DAC_BUFFER_SIZE] = {0x0, 0x1f, 0x7f, 0xdf, 0x13f, 0x19f, 0x1ff, 0x25f, 0x2bf, 0x31f, 0x37f, 0x3df, 0x43f, 0x49f, 0x4ff, 0x55f, 0x5bf, 0x61f, 0x67f, 0x6df, 0x73f, 0x79f, 0x7ff, 0x85f, 0x8bf, 0x91f, 0x97f, 0x9df, 0xa3f, 0xa9f, 0xaff, 0xb5f, 0xbbf, 0xc1f, 0xc7f, 0xcdf, 0xd3f, 0xd9f, 0xdff, 0xe5f, 0xebf, 0xf1f, 0xf7f, 0xfdf, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, - 0xfff, 0xfdf, 0xf7f, 0xf1f, 0xebf, 0xe5f, 0xdff, 0xd9f, 0xd3f, 0xcdf, 0xc7f, 0xc1f, 0xbbf, 0xb5f, 0xaff, 0xa9f, 0xa3f, 0x9df, 0x97f, 0x91f, 0x8bf, 0x85f, 0x7ff, 0x79f, 0x73f, 0x6df, 0x67f, 0x61f, 0x5bf, 0x55f, 0x4ff, 0x49f, 0x43f, 0x3df, 0x37f, 0x31f, 0x2bf, 0x25f, 0x1ff, 0x19f, 0x13f, 0xdf, 0x7f, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; -#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID - -static dacsample_t dac_buffer_empty[AUDIO_DAC_BUFFER_SIZE] = {AUDIO_DAC_OFF_VALUE}; - -/* keep track of the sample position for for each frequency */ -static float dac_if[AUDIO_MAX_SIMULTANEOUS_TONES] = {0.0}; - -static float active_tones_snapshot[AUDIO_MAX_SIMULTANEOUS_TONES] = {0, 0}; -static uint8_t active_tones_snapshot_length = 0; - -typedef enum { - OUTPUT_SHOULD_START, - OUTPUT_RUN_NORMALLY, - // path 1: wait for zero, then change/update active tones - OUTPUT_TONES_CHANGED, - OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE, - // path 2: hardware should stop, wait for zero then turn output off = stop the timer - OUTPUT_SHOULD_STOP, - OUTPUT_REACHED_ZERO_BEFORE_OFF, - OUTPUT_OFF, - OUTPUT_OFF_1, - OUTPUT_OFF_2, // trailing off: giving the DAC two more conversion cycles until the AUDIO_DAC_OFF_VALUE reaches the output, then turn the timer off, which leaves the output at that level - number_of_output_states -} output_states_t; -output_states_t state = OUTPUT_OFF_2; - -/** - * Generation of the waveform being passed to the callback. Declared weak so users - * can override it with their own wave-forms/noises. - */ -__attribute__((weak)) uint16_t dac_value_generate(void) { - // DAC is running/asking for values but snapshot length is zero -> must be playing a pause - if (active_tones_snapshot_length == 0) { - return AUDIO_DAC_OFF_VALUE; - } - - /* doing additive wave synthesis over all currently playing tones = adding up - * sine-wave-samples for each frequency, scaled by the number of active tones - */ - uint16_t value = 0; - float frequency = 0.0f; - - for (uint8_t i = 0; i < active_tones_snapshot_length; i++) { - /* Note: a user implementation does not have to rely on the active_tones_snapshot, but - * could directly query the active frequencies through audio_get_processed_frequency */ - frequency = active_tones_snapshot[i]; - - dac_if[i] = dac_if[i] + ((frequency * AUDIO_DAC_BUFFER_SIZE) / AUDIO_DAC_SAMPLE_RATE) * 2 / 3; - /*Note: the 2/3 are necessary to get the correct frequencies on the - * DAC output (as measured with an oscilloscope), since the gpt - * timer runs with 3*AUDIO_DAC_SAMPLE_RATE; and the DAC callback - * is called twice per conversion.*/ - - dac_if[i] = fmod(dac_if[i], AUDIO_DAC_BUFFER_SIZE); - - // Wavetable generation/lookup - uint16_t dac_i = (uint16_t)dac_if[i]; - -#if defined(AUDIO_DAC_SAMPLE_WAVEFORM_SINE) - value += dac_buffer_sine[dac_i] / active_tones_snapshot_length; -#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE) - value += dac_buffer_triangle[dac_i] / active_tones_snapshot_length; -#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID) - value += dac_buffer_trapezoid[dac_i] / active_tones_snapshot_length; -#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE) - value += dac_buffer_square[dac_i] / active_tones_snapshot_length; -#endif - /* - // SINE - value += dac_buffer_sine[dac_i] / active_tones_snapshot_length / 3; - // TRIANGLE - value += dac_buffer_triangle[dac_i] / active_tones_snapshot_length / 3; - // SQUARE - value += dac_buffer_square[dac_i] / active_tones_snapshot_length / 3; - //NOTE: combination of these three wave-forms is more exemplary - and doesn't sound particularly good :-P - */ - - // STAIRS (mostly usefully as test-pattern) - // value_avg = dac_buffer_staircase[dac_i] / active_tones_snapshot_length; - } - - return value; -} - -/** - * DAC streaming callback. Does all of the main computing for playing songs. - * - * Note: chibios calls this CB twice: during the 'half buffer event', and the 'full buffer event'. - */ -static void dac_end(DACDriver *dacp) { - dacsample_t *sample_p = (dacp)->samples; - - // work on the other half of the buffer - if (dacIsBufferComplete(dacp)) { - sample_p += AUDIO_DAC_BUFFER_SIZE / 2; // 'half_index' - } - - for (uint8_t s = 0; s < AUDIO_DAC_BUFFER_SIZE / 2; s++) { - if (OUTPUT_OFF <= state) { - sample_p[s] = AUDIO_DAC_OFF_VALUE; - continue; - } else { - sample_p[s] = dac_value_generate(); - } - - /* zero crossing (or approach, whereas zero == DAC_OFF_VALUE, which can be configured to anything from 0 to DAC_SAMPLE_MAX) - * ============================*=*========================== AUDIO_DAC_SAMPLE_MAX - * * * - * * * - * --------------------------------------------------------- - * * * } AUDIO_DAC_SAMPLE_MAX/100 - * --------------------------------------------------------- AUDIO_DAC_OFF_VALUE - * * * } AUDIO_DAC_SAMPLE_MAX/100 - * --------------------------------------------------------- - * * - * * * - * * * - * =====*=*================================================= 0x0 - */ - if (((sample_p[s] + (AUDIO_DAC_SAMPLE_MAX / 100)) > AUDIO_DAC_OFF_VALUE) && // value approaches from below - (sample_p[s] < (AUDIO_DAC_OFF_VALUE + (AUDIO_DAC_SAMPLE_MAX / 100))) // or above - ) { - if ((OUTPUT_SHOULD_START == state) && (active_tones_snapshot_length > 0)) { - state = OUTPUT_RUN_NORMALLY; - } else if (OUTPUT_TONES_CHANGED == state) { - state = OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE; - } else if (OUTPUT_SHOULD_STOP == state) { - state = OUTPUT_REACHED_ZERO_BEFORE_OFF; - } - } - - // still 'ramping up', reset the output to OFF_VALUE until the generated values reach that value, to do a smooth handover - if (OUTPUT_SHOULD_START == state) { - sample_p[s] = AUDIO_DAC_OFF_VALUE; - } - - if ((OUTPUT_SHOULD_START == state) || (OUTPUT_REACHED_ZERO_BEFORE_OFF == state) || (OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE == state)) { - uint8_t active_tones = MIN(AUDIO_MAX_SIMULTANEOUS_TONES, audio_get_number_of_active_tones()); - active_tones_snapshot_length = 0; - // update the snapshot - once, and only on occasion that something changed; - // -> saves cpu cycles (?) - for (uint8_t i = 0; i < active_tones; i++) { - float freq = audio_get_processed_frequency(i); - if (freq > 0) { // disregard 'rest' notes, with valid frequency 0.0f; which would only lower the resulting waveform volume during the additive synthesis step - active_tones_snapshot[active_tones_snapshot_length++] = freq; - } - } - - if ((0 == active_tones_snapshot_length) && (OUTPUT_REACHED_ZERO_BEFORE_OFF == state)) { - state = OUTPUT_OFF; - } - if (OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE == state) { - state = OUTPUT_RUN_NORMALLY; - } - } - } - - // update audio internal state (note position, current_note, ...) - if (audio_update_state()) { - if (OUTPUT_SHOULD_STOP != state) { - state = OUTPUT_TONES_CHANGED; - } - } - - if (OUTPUT_OFF <= state) { - if (OUTPUT_OFF_2 == state) { - // stopping timer6 = stopping the DAC at whatever value it is currently pushing to the output = AUDIO_DAC_OFF_VALUE - gptStopTimer(&GPTD6); - } else { - state++; - } - } -} - -static void dac_error(DACDriver *dacp, dacerror_t err) { - (void)dacp; - (void)err; - - chSysHalt("DAC failure. halp"); -} - -static const GPTConfig gpt6cfg1 = {.frequency = AUDIO_DAC_SAMPLE_RATE * 3, - .callback = NULL, - .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ - .dier = 0U}; - -static const DACConfig dac_conf = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_DHRM_12BIT_RIGHT}; - -/** - * @note The DAC_TRG(0) here selects the Timer 6 TRGO event, which is triggered - * on the rising edge after 3 APB1 clock cycles, causing our gpt6cfg1.frequency - * to be a third of what we expect. - * - * Here are all the values for DAC_TRG (TSEL in the ref manual) - * TIM15_TRGO 0b011 - * TIM2_TRGO 0b100 - * TIM3_TRGO 0b001 - * TIM6_TRGO 0b000 - * TIM7_TRGO 0b010 - * EXTI9 0b110 - * SWTRIG 0b111 - */ -static const DACConversionGroup dac_conv_cfg = {.num_channels = 1U, .end_cb = dac_end, .error_cb = dac_error, .trigger = DAC_TRG(0b000)}; - -void audio_driver_initialize() { - if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { - palSetLineMode(A4, PAL_MODE_INPUT_ANALOG); - dacStart(&DACD1, &dac_conf); - } - if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) { - palSetLineMode(A5, PAL_MODE_INPUT_ANALOG); - dacStart(&DACD2, &dac_conf); - } - - /* enable the output buffer, to directly drive external loads with no additional circuitry - * - * see: AN4566 Application note: Extending the DAC performance of STM32 microcontrollers - * Note: Buffer-Off bit -> has to be set 0 to enable the output buffer - * Note: enabling the output buffer imparts an additional dc-offset of a couple mV - * - * this is done here, reaching directly into the stm32 registers since chibios has not implemented BOFF handling yet - * (see: chibios/os/hal/ports/STM32/todo.txt '- BOFF handling in DACv1.' - */ - DACD1.params->dac->CR &= ~DAC_CR_BOFF1; - DACD2.params->dac->CR &= ~DAC_CR_BOFF2; - - if (AUDIO_PIN == A4) { - dacStartConversion(&DACD1, &dac_conv_cfg, dac_buffer_empty, AUDIO_DAC_BUFFER_SIZE); - } else if (AUDIO_PIN == A5) { - dacStartConversion(&DACD2, &dac_conv_cfg, dac_buffer_empty, AUDIO_DAC_BUFFER_SIZE); - } - - // no inverted/out-of-phase waveform (yet?), only pulling AUDIO_PIN_ALT to AUDIO_DAC_OFF_VALUE -#if defined(AUDIO_PIN_ALT_AS_NEGATIVE) - if (AUDIO_PIN_ALT == A4) { - dacPutChannelX(&DACD1, 0, AUDIO_DAC_OFF_VALUE); - } else if (AUDIO_PIN_ALT == A5) { - dacPutChannelX(&DACD2, 0, AUDIO_DAC_OFF_VALUE); - } -#endif - - gptStart(&GPTD6, &gpt6cfg1); -} - -void audio_driver_stop(void) { state = OUTPUT_SHOULD_STOP; } - -void audio_driver_start(void) { - gptStartContinuous(&GPTD6, 2U); - - for (uint8_t i = 0; i < AUDIO_MAX_SIMULTANEOUS_TONES; i++) { - dac_if[i] = 0.0f; - active_tones_snapshot[i] = 0.0f; - } - active_tones_snapshot_length = 0; - state = OUTPUT_SHOULD_START; -} diff --git a/quantum/audio/driver_chibios_dac_basic.c b/quantum/audio/driver_chibios_dac_basic.c deleted file mode 100644 index fac6513506..0000000000 --- a/quantum/audio/driver_chibios_dac_basic.c +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright 2016-2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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 "audio.h" -#include "ch.h" -#include "hal.h" - -/* - Audio Driver: DAC - - which utilizes both channels of the DAC unit many STM32 are equipped with to output a modulated square-wave, from precomputed samples stored in a buffer, which is passed to the hardware through DMA - - this driver can either be used to drive to separate speakers, wired to A4+Gnd and A5+Gnd, which allows two tones to be played simultaneously - OR - one speaker wired to A4+A5 with the AUDIO_PIN_ALT_AS_NEGATIVE define set - see docs/feature_audio - -*/ - -#if !defined(AUDIO_PIN) -# pragma message "Audio feature enabled, but no suitable pin selected as AUDIO_PIN - see docs/feature_audio under 'ARM (DAC basic)' for available options." -// TODO: make this an 'error' instead; go through a breaking change, and add AUDIO_PIN A5 to all keyboards currently using AUDIO on STM32 based boards? - for now: set the define here -# define AUDIO_PIN A5 -#endif -// check configuration for ONE speaker, connected to both DAC pins -#if defined(AUDIO_PIN_ALT_AS_NEGATIVE) && !defined(AUDIO_PIN_ALT) -# error "Audio feature: AUDIO_PIN_ALT_AS_NEGATIVE set, but no pin configured as AUDIO_PIN_ALT" -#endif - -#ifndef AUDIO_PIN_ALT -// no ALT pin defined is valid, but the c-ifs below need some value set -# define AUDIO_PIN_ALT -1 -#endif - -#if !defined(AUDIO_STATE_TIMER) -# define AUDIO_STATE_TIMER GPTD8 -#endif - -// square-wave -static const dacsample_t dac_buffer_1[AUDIO_DAC_BUFFER_SIZE] = { - // First half is max, second half is 0 - [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = AUDIO_DAC_SAMPLE_MAX, - [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = 0, -}; - -// square-wave -static const dacsample_t dac_buffer_2[AUDIO_DAC_BUFFER_SIZE] = { - // opposite of dac_buffer above - [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = 0, - [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = AUDIO_DAC_SAMPLE_MAX, -}; - -GPTConfig gpt6cfg1 = {.frequency = AUDIO_DAC_SAMPLE_RATE, - .callback = NULL, - .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ - .dier = 0U}; -GPTConfig gpt7cfg1 = {.frequency = AUDIO_DAC_SAMPLE_RATE, - .callback = NULL, - .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ - .dier = 0U}; - -static void gpt_audio_state_cb(GPTDriver *gptp); -GPTConfig gptStateUpdateCfg = {.frequency = 10, - .callback = gpt_audio_state_cb, - .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ - .dier = 0U}; - -static const DACConfig dac_conf_ch1 = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_DHRM_12BIT_RIGHT}; -static const DACConfig dac_conf_ch2 = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_DHRM_12BIT_RIGHT}; - -/** - * @note The DAC_TRG(0) here selects the Timer 6 TRGO event, which is triggered - * on the rising edge after 3 APB1 clock cycles, causing our gpt6cfg1.frequency - * to be a third of what we expect. - * - * Here are all the values for DAC_TRG (TSEL in the ref manual) - * TIM15_TRGO 0b011 - * TIM2_TRGO 0b100 - * TIM3_TRGO 0b001 - * TIM6_TRGO 0b000 - * TIM7_TRGO 0b010 - * EXTI9 0b110 - * SWTRIG 0b111 - */ -static const DACConversionGroup dac_conv_grp_ch1 = {.num_channels = 1U, .trigger = DAC_TRG(0b000)}; -static const DACConversionGroup dac_conv_grp_ch2 = {.num_channels = 1U, .trigger = DAC_TRG(0b010)}; - -void channel_1_start(void) { - gptStart(&GPTD6, &gpt6cfg1); - gptStartContinuous(&GPTD6, 2U); - palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); -} - -void channel_1_stop(void) { - gptStopTimer(&GPTD6); - palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL); - palSetPad(GPIOA, 4); -} - -static float channel_1_frequency = 0.0f; -void channel_1_set_frequency(float freq) { - channel_1_frequency = freq; - - channel_1_stop(); - if (freq <= 0.0) // a pause/rest has freq=0 - return; - - gpt6cfg1.frequency = 2 * freq * AUDIO_DAC_BUFFER_SIZE; - channel_1_start(); -} -float channel_1_get_frequency(void) { return channel_1_frequency; } - -void channel_2_start(void) { - gptStart(&GPTD7, &gpt7cfg1); - gptStartContinuous(&GPTD7, 2U); - palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); -} - -void channel_2_stop(void) { - gptStopTimer(&GPTD7); - palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); - palSetPad(GPIOA, 5); -} - -static float channel_2_frequency = 0.0f; -void channel_2_set_frequency(float freq) { - channel_2_frequency = freq; - - channel_2_stop(); - if (freq <= 0.0) // a pause/rest has freq=0 - return; - - gpt7cfg1.frequency = 2 * freq * AUDIO_DAC_BUFFER_SIZE; - channel_2_start(); -} -float channel_2_get_frequency(void) { return channel_2_frequency; } - -static void gpt_audio_state_cb(GPTDriver *gptp) { - if (audio_update_state()) { -#if defined(AUDIO_PIN_ALT_AS_NEGATIVE) - // one piezo/speaker connected to both audio pins, the generated square-waves are inverted - channel_1_set_frequency(audio_get_processed_frequency(0)); - channel_2_set_frequency(audio_get_processed_frequency(0)); - -#else // two separate audio outputs/speakers - // primary speaker on A4, optional secondary on A5 - if (AUDIO_PIN == A4) { - channel_1_set_frequency(audio_get_processed_frequency(0)); - if (AUDIO_PIN_ALT == A5) { - if (audio_get_number_of_active_tones() > 1) { - channel_2_set_frequency(audio_get_processed_frequency(1)); - } else { - channel_2_stop(); - } - } - } - - // primary speaker on A5, optional secondary on A4 - if (AUDIO_PIN == A5) { - channel_2_set_frequency(audio_get_processed_frequency(0)); - if (AUDIO_PIN_ALT == A4) { - if (audio_get_number_of_active_tones() > 1) { - channel_1_set_frequency(audio_get_processed_frequency(1)); - } else { - channel_1_stop(); - } - } - } -#endif - } -} - -void audio_driver_initialize() { - if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { - palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); - dacStart(&DACD1, &dac_conf_ch1); - - // initial setup of the dac-triggering timer is still required, even - // though it gets reconfigured and restarted later on - gptStart(&GPTD6, &gpt6cfg1); - } - - if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) { - palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); - dacStart(&DACD2, &dac_conf_ch2); - - gptStart(&GPTD7, &gpt7cfg1); - } - - /* enable the output buffer, to directly drive external loads with no additional circuitry - * - * see: AN4566 Application note: Extending the DAC performance of STM32 microcontrollers - * Note: Buffer-Off bit -> has to be set 0 to enable the output buffer - * Note: enabling the output buffer imparts an additional dc-offset of a couple mV - * - * this is done here, reaching directly into the stm32 registers since chibios has not implemented BOFF handling yet - * (see: chibios/os/hal/ports/STM32/todo.txt '- BOFF handling in DACv1.' - */ - DACD1.params->dac->CR &= ~DAC_CR_BOFF1; - DACD2.params->dac->CR &= ~DAC_CR_BOFF2; - - // start state-updater - gptStart(&AUDIO_STATE_TIMER, &gptStateUpdateCfg); -} - -void audio_driver_stop(void) { - if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { - gptStopTimer(&GPTD6); - - // stop the ongoing conversion and put the output in a known state - dacStopConversion(&DACD1); - dacPutChannelX(&DACD1, 0, AUDIO_DAC_OFF_VALUE); - } - - if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) { - gptStopTimer(&GPTD7); - - dacStopConversion(&DACD2); - dacPutChannelX(&DACD2, 0, AUDIO_DAC_OFF_VALUE); - } - gptStopTimer(&AUDIO_STATE_TIMER); -} - -void audio_driver_start(void) { - if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { - dacStartConversion(&DACD1, &dac_conv_grp_ch1, (dacsample_t *)dac_buffer_1, AUDIO_DAC_BUFFER_SIZE); - } - if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) { - dacStartConversion(&DACD2, &dac_conv_grp_ch2, (dacsample_t *)dac_buffer_2, AUDIO_DAC_BUFFER_SIZE); - } - gptStartContinuous(&AUDIO_STATE_TIMER, 2U); -} diff --git a/quantum/audio/driver_chibios_pwm.h b/quantum/audio/driver_chibios_pwm.h deleted file mode 100644 index 86cab916e1..0000000000 --- a/quantum/audio/driver_chibios_pwm.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright 2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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 - -#if !defined(AUDIO_PWM_DRIVER) -// NOTE: Timer2 seems to be used otherwise in QMK, otherwise we could default to A5 (= TIM2_CH1, with PWMD2 and alternate-function(1)) -# define AUDIO_PWM_DRIVER PWMD1 -#endif - -#if !defined(AUDIO_PWM_CHANNEL) -// NOTE: sticking to the STM data-sheet numbering: TIMxCH1 to TIMxCH4 -// default: STM32F303CC PA8+TIM1_CH1 -> 1 -# define AUDIO_PWM_CHANNEL 1 -#endif - -#if !defined(AUDIO_PWM_PAL_MODE) -// pin-alternate function: see the data-sheet for which pin needs what AF to connect to TIMx_CHy -// default: STM32F303CC PA8+TIM1_CH1 -> 6 -# define AUDIO_PWM_PAL_MODE 6 -#endif - -#if !defined(AUDIO_STATE_TIMER) -// timer used to trigger updates in the audio-system, configured/enabled in chibios mcuconf. -// Tim6 is the default for "larger" STMs, smaller ones might not have this one (enabled) and need to switch to a different one (e.g.: STM32F103 has only Tim1-Tim4) -# define AUDIO_STATE_TIMER GPTD6 -#endif diff --git a/quantum/audio/driver_chibios_pwm_hardware.c b/quantum/audio/driver_chibios_pwm_hardware.c deleted file mode 100644 index 3c7d89b290..0000000000 --- a/quantum/audio/driver_chibios_pwm_hardware.c +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright 2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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/>. - */ - -/* -Audio Driver: PWM - -the duty-cycle is always kept at 50%, and the pwm-period is adjusted to match the frequency of a note to be played back. - -this driver uses the chibios-PWM system to produce a square-wave on specific output pins that are connected to the PWM hardware. -The hardware directly toggles the pin via its alternate function. see your MCUs data-sheet for which pin can be driven by what timer - looking for TIMx_CHy and the corresponding alternate function. - - */ - -#include "audio.h" -#include "ch.h" -#include "hal.h" - -#if !defined(AUDIO_PIN) -# error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings" -#endif - -extern bool playing_note; -extern bool playing_melody; -extern uint8_t note_timbre; - -static PWMConfig pwmCFG = { - .frequency = 100000, /* PWM clock frequency */ - // CHIBIOS-BUG? can't set the initial period to <2, or the pwm (hard or software) takes ~130ms with .frequency=500000 for a pwmChangePeriod to take effect; with no output=silence in the meantime - .period = 2, /* initial PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */ - .callback = NULL, /* no callback, the hardware directly toggles the pin */ - .channels = - { -#if AUDIO_PWM_CHANNEL == 4 - {PWM_OUTPUT_DISABLED, NULL}, /* channel 0 -> TIMx_CH1 */ - {PWM_OUTPUT_DISABLED, NULL}, /* channel 1 -> TIMx_CH2 */ - {PWM_OUTPUT_DISABLED, NULL}, /* channel 2 -> TIMx_CH3 */ - {PWM_OUTPUT_ACTIVE_HIGH, NULL} /* channel 3 -> TIMx_CH4 */ -#elif AUDIO_PWM_CHANNEL == 3 - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH3 */ - {PWM_OUTPUT_DISABLED, NULL} -#elif AUDIO_PWM_CHANNEL == 2 - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH2 */ - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL} -#else /*fallback to CH1 */ - {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH1 */ - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL} -#endif - }, -}; - -static float channel_1_frequency = 0.0f; -void channel_1_set_frequency(float freq) { - channel_1_frequency = freq; - - if (freq <= 0.0) // a pause/rest has freq=0 - return; - - pwmcnt_t period = (pwmCFG.frequency / freq); - pwmChangePeriod(&AUDIO_PWM_DRIVER, period); - pwmEnableChannel(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1, - // adjust the duty-cycle so that the output is for 'note_timbre' duration HIGH - PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100)); -} - -float channel_1_get_frequency(void) { return channel_1_frequency; } - -void channel_1_start(void) { - pwmStop(&AUDIO_PWM_DRIVER); - pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); -} - -void channel_1_stop(void) { pwmStop(&AUDIO_PWM_DRIVER); } - -static void gpt_callback(GPTDriver *gptp); -GPTConfig gptCFG = { - /* a whole note is one beat, which is - per definition in musical_notes.h - set to 64 - the longest note is BREAVE_DOT=128+64=192, the shortest SIXTEENTH=4 - the tempo (which might vary!) is in bpm (beats per minute) - therefore: if the timer ticks away at .frequency = (60*64)Hz, - and the .interval counts from 64 downwards - audio_update_state is - called just often enough to not miss any notes - */ - .frequency = 60 * 64, - .callback = gpt_callback, -}; - -void audio_driver_initialize(void) { - pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); - - // connect the AUDIO_PIN to the PWM hardware -#if defined(USE_GPIOV1) // STM32F103C8 - palSetLineMode(AUDIO_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL); -#else // GPIOv2 (or GPIOv3 for f4xx, which is the same/compatible at this command) - palSetLineMode(AUDIO_PIN, PAL_STM32_MODE_ALTERNATE | PAL_STM32_ALTERNATE(AUDIO_PWM_PAL_MODE)); -#endif - - gptStart(&AUDIO_STATE_TIMER, &gptCFG); -} - -void audio_driver_start(void) { - channel_1_stop(); - channel_1_start(); - - if (playing_note || playing_melody) { - gptStartContinuous(&AUDIO_STATE_TIMER, 64); - } -} - -void audio_driver_stop(void) { - channel_1_stop(); - gptStopTimer(&AUDIO_STATE_TIMER); -} - -/* a regular timer task, that checks the note to be currently played - * and updates the pwm to output that frequency - */ -static void gpt_callback(GPTDriver *gptp) { - float freq; // TODO: freq_alt - - if (audio_update_state()) { - freq = audio_get_processed_frequency(0); // freq_alt would be index=1 - channel_1_set_frequency(freq); - } -} diff --git a/quantum/audio/driver_chibios_pwm_software.c b/quantum/audio/driver_chibios_pwm_software.c deleted file mode 100644 index 15c3e98b6a..0000000000 --- a/quantum/audio/driver_chibios_pwm_software.c +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright 2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * 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/>. - */ - -/* -Audio Driver: PWM - -the duty-cycle is always kept at 50%, and the pwm-period is adjusted to match the frequency of a note to be played back. - -this driver uses the chibios-PWM system to produce a square-wave on any given output pin in software -- a pwm callback is used to set/clear the configured pin. - - */ -#include "audio.h" -#include "ch.h" -#include "hal.h" - -#if !defined(AUDIO_PIN) -# error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings" -#endif -extern bool playing_note; -extern bool playing_melody; -extern uint8_t note_timbre; - -static void pwm_audio_period_callback(PWMDriver *pwmp); -static void pwm_audio_channel_interrupt_callback(PWMDriver *pwmp); - -static PWMConfig pwmCFG = { - .frequency = 100000, /* PWM clock frequency */ - // CHIBIOS-BUG? can't set the initial period to <2, or the pwm (hard or software) takes ~130ms with .frequency=500000 for a pwmChangePeriod to take effect; with no output=silence in the meantime - .period = 2, /* initial PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */ - .callback = pwm_audio_period_callback, - .channels = - { - // software-PWM just needs another callback on any channel - {PWM_OUTPUT_ACTIVE_HIGH, pwm_audio_channel_interrupt_callback}, /* channel 0 -> TIMx_CH1 */ - {PWM_OUTPUT_DISABLED, NULL}, /* channel 1 -> TIMx_CH2 */ - {PWM_OUTPUT_DISABLED, NULL}, /* channel 2 -> TIMx_CH3 */ - {PWM_OUTPUT_DISABLED, NULL} /* channel 3 -> TIMx_CH4 */ - }, -}; - -static float channel_1_frequency = 0.0f; -void channel_1_set_frequency(float freq) { - channel_1_frequency = freq; - - if (freq <= 0.0) // a pause/rest has freq=0 - return; - - pwmcnt_t period = (pwmCFG.frequency / freq); - pwmChangePeriod(&AUDIO_PWM_DRIVER, period); - - pwmEnableChannel(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1, - // adjust the duty-cycle so that the output is for 'note_timbre' duration HIGH - PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100)); -} - -float channel_1_get_frequency(void) { return channel_1_frequency; } - -void channel_1_start(void) { - pwmStop(&AUDIO_PWM_DRIVER); - pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); - - pwmEnablePeriodicNotification(&AUDIO_PWM_DRIVER); - pwmEnableChannelNotification(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1); -} - -void channel_1_stop(void) { - pwmStop(&AUDIO_PWM_DRIVER); - - palClearLine(AUDIO_PIN); // leave the line low, after last note was played - -#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE) - palClearLine(AUDIO_PIN_ALT); // leave the line low, after last note was played -#endif -} - -// generate a PWM signal on any pin, not necessarily the one connected to the timer -static void pwm_audio_period_callback(PWMDriver *pwmp) { - (void)pwmp; - palClearLine(AUDIO_PIN); - -#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE) - palSetLine(AUDIO_PIN_ALT); -#endif -} -static void pwm_audio_channel_interrupt_callback(PWMDriver *pwmp) { - (void)pwmp; - if (channel_1_frequency > 0) { - palSetLine(AUDIO_PIN); // generate a PWM signal on any pin, not necessarily the one connected to the timer -#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE) - palClearLine(AUDIO_PIN_ALT); -#endif - } -} - -static void gpt_callback(GPTDriver *gptp); -GPTConfig gptCFG = { - /* a whole note is one beat, which is - per definition in musical_notes.h - set to 64 - the longest note is BREAVE_DOT=128+64=192, the shortest SIXTEENTH=4 - the tempo (which might vary!) is in bpm (beats per minute) - therefore: if the timer ticks away at .frequency = (60*64)Hz, - and the .interval counts from 64 downwards - audio_update_state is - called just often enough to not miss anything - */ - .frequency = 60 * 64, - .callback = gpt_callback, -}; - -void audio_driver_initialize(void) { - pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); - - palSetLineMode(AUDIO_PIN, PAL_MODE_OUTPUT_PUSHPULL); - palClearLine(AUDIO_PIN); - -#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE) - palSetLineMode(AUDIO_PIN_ALT, PAL_MODE_OUTPUT_PUSHPULL); - palClearLine(AUDIO_PIN_ALT); -#endif - - pwmEnablePeriodicNotification(&AUDIO_PWM_DRIVER); // enable pwm callbacks - pwmEnableChannelNotification(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1); - - gptStart(&AUDIO_STATE_TIMER, &gptCFG); -} - -void audio_driver_start(void) { - channel_1_stop(); - channel_1_start(); - - if (playing_note || playing_melody) { - gptStartContinuous(&AUDIO_STATE_TIMER, 64); - } -} - -void audio_driver_stop(void) { - channel_1_stop(); - gptStopTimer(&AUDIO_STATE_TIMER); -} - -/* a regular timer task, that checks the note to be currently played - * and updates the pwm to output that frequency - */ -static void gpt_callback(GPTDriver *gptp) { - float freq; // TODO: freq_alt - - if (audio_update_state()) { - freq = audio_get_processed_frequency(0); // freq_alt would be index=1 - channel_1_set_frequency(freq); - } -} diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h index b54b397e1c..8e80a016aa 100644 --- a/quantum/audio/song_list.h +++ b/quantum/audio/song_list.h @@ -20,11 +20,9 @@ #include "musical_notes.h" -#if __GNUC__ > 5 // don't use for older gcc compilers since check isn't supported. -# if __has_include("user_song_list.h") -# include "user_song_list.h" -# endif // if file exists -#endif // __GNUC__ +#if __has_include("user_song_list.h") +# include "user_song_list.h" +#endif // if file exists #define NO_SOUND diff --git a/quantum/backlight/backlight_chibios.c b/quantum/backlight/backlight_chibios.c index 4d5a69e14e..7c6edd10d6 100644 --- a/quantum/backlight/backlight_chibios.c +++ b/quantum/backlight/backlight_chibios.c @@ -8,9 +8,13 @@ # define BACKLIGHT_LIMIT_VAL 255 #endif -// GPIOV2 && GPIOV3 #ifndef BACKLIGHT_PAL_MODE -# define BACKLIGHT_PAL_MODE 2 +# if defined(USE_GPIOV1) +# define BACKLIGHT_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL +# else +// GPIOV2 && GPIOV3 +# define BACKLIGHT_PAL_MODE 5 +# endif #endif // GENERIC @@ -70,7 +74,7 @@ static uint32_t rescale_limit_val(uint32_t val) { void backlight_init_ports(void) { #ifdef USE_GPIOV1 - palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); + palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), BACKLIGHT_PAL_MODE); #else palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_ALTERNATE(BACKLIGHT_PAL_MODE)); #endif diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c index 92f0ac4439..4c2ad2490c 100644 --- a/quantum/eeconfig.c +++ b/quantum/eeconfig.c @@ -4,11 +4,6 @@ #include "eeconfig.h" #include "action_layer.h" -#ifdef STM32_EEPROM_ENABLE -# include <hal.h> -# include "eeprom_stm32.h" -#endif - #if defined(EEPROM_DRIVER) # include "eeprom_driver.h" #endif @@ -43,9 +38,6 @@ __attribute__((weak)) void eeconfig_init_kb(void) { * FIXME: needs doc */ void eeconfig_init_quantum(void) { -#ifdef STM32_EEPROM_ENABLE - EEPROM_Erase(); -#endif #if defined(EEPROM_DRIVER) eeprom_driver_erase(); #endif @@ -111,9 +103,6 @@ void eeconfig_enable(void) { eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_N * FIXME: needs doc */ void eeconfig_disable(void) { -#ifdef STM32_EEPROM_ENABLE - EEPROM_Erase(); -#endif #if defined(EEPROM_DRIVER) eeprom_driver_erase(); #endif diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h index bd39971b2c..22d874273c 100644 --- a/quantum/eeconfig.h +++ b/quantum/eeconfig.h @@ -111,3 +111,29 @@ void eeconfig_update_haptic(uint32_t val); bool eeconfig_read_handedness(void); void eeconfig_update_handedness(bool val); + +#define EECONFIG_DEBOUNCE_HELPER(name, offset, config) \ + static uint8_t dirty_##name = false; \ + \ + static inline void eeconfig_init_##name(void) { \ + eeprom_read_block(&config, offset, sizeof(config)); \ + dirty_##name = false; \ + } \ + static inline void eeconfig_flush_##name(bool force) { \ + if (force || dirty_##name) { \ + eeprom_update_block(&config, offset, sizeof(config)); \ + dirty_##name = false; \ + } \ + } \ + static inline void eeconfig_flush_##name##_task(uint16_t timeout) { \ + static uint16_t flush_timer = 0; \ + if (timer_elapsed(flush_timer) > timeout) { \ + eeconfig_flush_##name(false); \ + flush_timer = timer_read(); \ + } \ + } \ + static inline void eeconfig_flag_##name(bool v) { dirty_##name |= v; } \ + static inline void eeconfig_write_##name(typeof(config) conf) { \ + memcpy(&config, &conf, sizeof(config)); \ + eeconfig_flag_##name(true); \ + } diff --git a/quantum/keyboard.c b/quantum/keyboard.c index b98fc64e45..f2a0889c12 100644 --- a/quantum/keyboard.c +++ b/quantum/keyboard.c @@ -43,9 +43,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef SERIAL_MOUSE_ENABLE # include "serial_mouse.h" #endif -#ifdef ADB_MOUSE_ENABLE -# include "adb.h" -#endif #ifdef RGBLIGHT_ENABLE # include "rgblight.h" #endif @@ -61,12 +58,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef STENO_ENABLE # include "process_steno.h" #endif -#ifdef SERIAL_LINK_ENABLE -# include "serial_link/system/serial_link.h" -#endif -#ifdef VISUALIZER_ENABLE -# include "visualizer/visualizer.h" -#endif #ifdef POINTING_DEVICE_ENABLE # include "pointing_device.h" #endif @@ -76,12 +67,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef JOYSTICK_ENABLE # include "process_joystick.h" #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE +# include "programmable_button.h" +#endif #ifdef HD44780_ENABLE # include "hd44780.h" #endif -#ifdef QWIIC_ENABLE -# include "qwiic.h" -#endif #ifdef OLED_ENABLE # include "oled_driver.h" #endif @@ -97,9 +88,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef DIP_SWITCH_ENABLE # include "dip_switch.h" #endif -#ifdef STM32_EEPROM_ENABLE -# include "eeprom_stm32.h" -#endif #ifdef EEPROM_DRIVER # include "eeprom_driver.h" #endif @@ -246,9 +234,6 @@ void keyboard_setup(void) { disable_jtag(); #endif print_set_sendchar(sendchar); -#ifdef STM32_EEPROM_ENABLE - EEPROM_Init(); -#endif #ifdef EEPROM_DRIVER eeprom_driver_init(); #endif @@ -316,9 +301,6 @@ void keyboard_init(void) { #if defined(CRC_ENABLE) crc_init(); #endif -#ifdef QWIIC_ENABLE - qwiic_init(); -#endif #ifdef OLED_ENABLE oled_init(OLED_ROTATION_0); #endif @@ -331,9 +313,6 @@ void keyboard_init(void) { #ifdef SERIAL_MOUSE_ENABLE serial_mouse_init(); #endif -#ifdef ADB_MOUSE_ENABLE - adb_mouse_init(); -#endif #ifdef BACKLIGHT_ENABLE backlight_init(); #endif @@ -384,7 +363,6 @@ void switch_events(uint8_t row, uint8_t col, bool pressed) { * * * scan matrix * * handle mouse movements - * * run visualizer code * * handle midi commands * * light LEDs * @@ -473,10 +451,6 @@ MATRIX_LOOP_END: if (encoders_changed) last_encoder_activity_trigger(); #endif -#ifdef QWIIC_ENABLE - qwiic_task(); -#endif - #ifdef OLED_ENABLE oled_task(); # if OLED_TIMEOUT > 0 @@ -514,18 +488,6 @@ MATRIX_LOOP_END: serial_mouse_task(); #endif -#ifdef ADB_MOUSE_ENABLE - adb_mouse_task(); -#endif - -#ifdef SERIAL_LINK_ENABLE - serial_link_update(); -#endif - -#ifdef VISUALIZER_ENABLE - visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds()); -#endif - #ifdef POINTING_DEVICE_ENABLE pointing_device_task(); #endif @@ -548,6 +510,10 @@ MATRIX_LOOP_END: digitizer_task(); #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE + programmable_button_send(); +#endif + // update LED if (led_status != host_keyboard_leds()) { led_status = host_keyboard_leds(); diff --git a/quantum/keymap_extras/keymap_turkish_f.h b/quantum/keymap_extras/keymap_turkish_f.h index 226f8cbeb0..f86ef21546 100644 --- a/quantum/keymap_extras/keymap_turkish_f.h +++ b/quantum/keymap_extras/keymap_turkish_f.h @@ -111,7 +111,7 @@ #define TR_LPRN S(TR_8) // ( #define TR_RPRN S(TR_9) // ) #define TR_EQL S(TR_0) // = -#define TR_QUES S(TR_ASTR) // ? +#define TR_QUES S(TR_SLSH) // ? #define TR_UNDS S(TR_MINS) // _ // Row 4 #define TR_RABK S(TR_LABK) // > diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c index 50510e49aa..85556d1573 100644 --- a/quantum/led_matrix/led_matrix.c +++ b/quantum/led_matrix/led_matrix.c @@ -33,14 +33,6 @@ const led_point_t k_led_matrix_center = {112, 32}; const led_point_t k_led_matrix_center = LED_MATRIX_CENTER; #endif -// clang-format off -#ifndef LED_MATRIX_IMMEDIATE_EEPROM -# define led_eeconfig_update(v) led_update_eeprom |= v -#else -# define led_eeconfig_update(v) if (v) eeconfig_update_led_matrix() -#endif -// clang-format on - // Generic effect runners #include "led_matrix_runners.inc" @@ -107,7 +99,6 @@ last_hit_t g_last_hit_tracker; // internals static bool suspend_state = false; -static bool led_update_eeprom = false; static uint8_t led_last_enable = UINT8_MAX; static uint8_t led_last_effect = UINT8_MAX; static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; @@ -127,9 +118,9 @@ static last_hit_t last_hit_buffer; const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; #endif -void eeconfig_read_led_matrix(void) { eeprom_read_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); } +EECONFIG_DEBOUNCE_HELPER(led_matrix, EECONFIG_LED_MATRIX, led_matrix_eeconfig); -void eeconfig_update_led_matrix(void) { eeprom_update_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); } +void eeconfig_update_led_matrix(void) { eeconfig_flush_led_matrix(true); } void eeconfig_update_led_matrix_default(void) { dprintf("eeconfig_update_led_matrix_default\n"); @@ -138,7 +129,7 @@ void eeconfig_update_led_matrix_default(void) { led_matrix_eeconfig.val = LED_MATRIX_STARTUP_VAL; led_matrix_eeconfig.speed = LED_MATRIX_STARTUP_SPD; led_matrix_eeconfig.flags = LED_FLAG_ALL; - eeconfig_update_led_matrix(); + eeconfig_flush_led_matrix(true); } void eeconfig_debug_led_matrix(void) { @@ -279,9 +270,8 @@ static void led_task_timers(void) { } static void led_task_sync(void) { + eeconfig_flush_led_matrix(false); // next task - if (led_update_eeprom) eeconfig_update_led_matrix(); - led_update_eeprom = false; if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING; } @@ -449,7 +439,7 @@ void led_matrix_init(void) { eeconfig_update_led_matrix_default(); } - eeconfig_read_led_matrix(); + eeconfig_init_led_matrix(); if (!led_matrix_eeconfig.mode) { dprintf("led_matrix_init_drivers led_matrix_eeconfig.mode = 0. Write default values to EEPROM.\n"); eeconfig_update_led_matrix_default(); @@ -472,7 +462,7 @@ bool led_matrix_get_suspend_state(void) { return suspend_state; } void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) { led_matrix_eeconfig.enable ^= 1; led_task_state = STARTING; - led_eeconfig_update(write_to_eeprom); + eeconfig_flag_led_matrix(write_to_eeprom); dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable); } void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); } @@ -480,7 +470,7 @@ void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); } void led_matrix_enable(void) { led_matrix_enable_noeeprom(); - led_eeconfig_update(true); + eeconfig_flag_led_matrix(true); } void led_matrix_enable_noeeprom(void) { @@ -490,7 +480,7 @@ void led_matrix_enable_noeeprom(void) { void led_matrix_disable(void) { led_matrix_disable_noeeprom(); - led_eeconfig_update(true); + eeconfig_flag_led_matrix(true); } void led_matrix_disable_noeeprom(void) { @@ -512,7 +502,7 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { led_matrix_eeconfig.mode = mode; } led_task_state = STARTING; - led_eeconfig_update(write_to_eeprom); + eeconfig_flag_led_matrix(write_to_eeprom); dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode); } void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); } @@ -539,7 +529,7 @@ void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) { return; } led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val; - led_eeconfig_update(write_to_eeprom); + eeconfig_flag_led_matrix(write_to_eeprom); dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val); } void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); } @@ -557,7 +547,7 @@ void led_matrix_decrease_val(void) { led_matrix_decrease_val_helper(true); } void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { led_matrix_eeconfig.speed = speed; - led_eeconfig_update(write_to_eeprom); + eeconfig_flag_led_matrix(write_to_eeprom); dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed); } void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); } diff --git a/quantum/led_matrix/led_matrix_drivers.c b/quantum/led_matrix/led_matrix_drivers.c index 1d46b2c506..2157619a0b 100644 --- a/quantum/led_matrix/led_matrix_drivers.c +++ b/quantum/led_matrix/led_matrix_drivers.c @@ -26,128 +26,123 @@ */ #if defined(IS31FL3731) || defined(IS31FL3733) - # include "i2c_master.h" static void init(void) { i2c_init(); -# ifdef IS31FL3731 -# ifdef LED_DRIVER_ADDR_1 + +# if defined(IS31FL3731) IS31FL3731_init(LED_DRIVER_ADDR_1); -# endif -# ifdef LED_DRIVER_ADDR_2 +# if defined(LED_DRIVER_ADDR_2) IS31FL3731_init(LED_DRIVER_ADDR_2); -# endif -# ifdef LED_DRIVER_ADDR_3 +# if defined(LED_DRIVER_ADDR_3) IS31FL3731_init(LED_DRIVER_ADDR_3); -# endif -# ifdef LED_DRIVER_ADDR_4 +# if defined(LED_DRIVER_ADDR_4) IS31FL3731_init(LED_DRIVER_ADDR_4); -# endif -# else -# ifdef LED_DRIVER_ADDR_1 -# ifndef LED_DRIVER_SYNC_1 -# define LED_DRIVER_SYNC_1 0 +# endif # endif - IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1); # endif -# ifdef LED_DRIVER_ADDR_2 -# ifndef LED_DRIVER_SYNC_2 + +# elif defined(IS31FL3733) +# if !defined(LED_DRIVER_SYNC_1) +# define LED_DRIVER_SYNC_1 0 +# endif + IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1); +# if defined(LED_DRIVER_ADDR_2) +# if !defined(LED_DRIVER_SYNC_2) # define LED_DRIVER_SYNC_2 0 # endif IS31FL3733_init(LED_DRIVER_ADDR_2, LED_DRIVER_SYNC_2); -# endif -# ifdef LED_DRIVER_ADDR_3 -# ifndef LED_DRIVER_SYNC_3 -# define LED_DRIVER_SYNC_3 0 -# endif +# if defined(LED_DRIVER_ADDR_3) +# if !defined(LED_DRIVER_SYNC_3) +# define LED_DRIVER_SYNC_3 0 +# endif IS31FL3733_init(LED_DRIVER_ADDR_3, LED_DRIVER_SYNC_3); -# endif -# ifdef LED_DRIVER_ADDR_4 -# ifndef LED_DRIVER_SYNC_4 -# define LED_DRIVER_SYNC_4 0 -# endif +# if defined(LED_DRIVER_ADDR_4) +# if !defined(LED_DRIVER_SYNC_4) +# define LED_DRIVER_SYNC_4 0 +# endif IS31FL3733_init(LED_DRIVER_ADDR_4, LED_DRIVER_SYNC_4); +# endif +# endif # endif # endif for (int index = 0; index < DRIVER_LED_TOTAL; index++) { -# ifdef IS31FL3731 +# if defined(IS31FL3731) IS31FL3731_set_led_control_register(index, true); -# else +# elif defined(IS31FL3733) IS31FL3733_set_led_control_register(index, true); # endif } + // This actually updates the LED drivers -# ifdef IS31FL3731 -# ifdef LED_DRIVER_ADDR_1 +# if defined(IS31FL3731) IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_1, 0); -# endif -# ifdef LED_DRIVER_ADDR_2 +# if defined(LED_DRIVER_ADDR_2) IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_2, 1); -# endif -# ifdef LED_DRIVER_ADDR_3 +# if defined(LED_DRIVER_ADDR_3) IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_3, 2); -# endif -# ifdef LED_DRIVER_ADDR_4 +# if defined(LED_DRIVER_ADDR_4) IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_4, 3); +# endif +# endif # endif -# else -# ifdef LED_DRIVER_ADDR_1 + +# elif defined(IS31FL3733) IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_1, 0); -# endif -# ifdef LED_DRIVER_ADDR_2 +# if defined(LED_DRIVER_ADDR_2) IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_2, 1); -# endif -# ifdef LED_DRIVER_ADDR_3 +# if defined(LED_DRIVER_ADDR_3) IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_3, 2); -# endif -# ifdef LED_DRIVER_ADDR_4 +# if defined(LED_DRIVER_ADDR_4) IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_4, 3); +# endif +# endif # endif # endif } +# if defined(IS31FL3731) static void flush(void) { -# ifdef IS31FL3731 -# ifdef LED_DRIVER_ADDR_1 IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_1, 0); -# endif -# ifdef LED_DRIVER_ADDR_2 +# if defined(LED_DRIVER_ADDR_2) IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_2, 1); -# endif -# ifdef LED_DRIVER_ADDR_3 +# if defined(LED_DRIVER_ADDR_3) IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_3, 2); -# endif -# ifdef LED_DRIVER_ADDR_4 +# if defined(LED_DRIVER_ADDR_4) IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_4, 3); +# endif +# endif # endif -# else -# ifdef LED_DRIVER_ADDR_1 +} + +const led_matrix_driver_t led_matrix_driver = { + .init = init, + .flush = flush, + .set_value = IS31FL3731_set_value, + .set_value_all = IS31FL3731_set_value_all, +}; + +# elif defined(IS31FL3733) +static void flush(void) { IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_1, 0); -# endif -# ifdef LED_DRIVER_ADDR_2 +# if defined(LED_DRIVER_ADDR_2) IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_2, 1); -# endif -# ifdef LED_DRIVER_ADDR_3 +# if defined(LED_DRIVER_ADDR_3) IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_3, 2); -# endif -# ifdef LED_DRIVER_ADDR_4 +# if defined(LED_DRIVER_ADDR_4) IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_4, 3); +# endif +# endif # endif -# endif } const led_matrix_driver_t led_matrix_driver = { - .init = init, + .init = init, .flush = flush, -# ifdef IS31FL3731 - .set_value = IS31FL3731_set_value, - .set_value_all = IS31FL3731_set_value_all, -# else .set_value = IS31FL3733_set_value, .set_value_all = IS31FL3733_set_value_all, -# endif }; - +# endif #endif diff --git a/quantum/matrix.c b/quantum/matrix.c index 33586c431b..4fbcc2419c 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -288,10 +288,8 @@ void matrix_init(void) { matrix_init_pins(); // initialize matrix state: all keys off - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - raw_matrix[i] = 0; - matrix[i] = 0; - } + memset(matrix, 0, sizeof(matrix)); + memset(raw_matrix, 0, sizeof(raw_matrix)); debounce_init(ROWS_PER_HAND); @@ -312,24 +310,22 @@ __attribute__((weak)) bool transport_master_if_connected(matrix_row_t master_mat bool matrix_post_scan(void) { bool changed = false; if (is_keyboard_master()) { + static bool last_connected = false; matrix_row_t slave_matrix[ROWS_PER_HAND] = {0}; if (transport_master_if_connected(matrix + thisHand, slave_matrix)) { - for (int i = 0; i < ROWS_PER_HAND; ++i) { - if (matrix[thatHand + i] != slave_matrix[i]) { - matrix[thatHand + i] = slave_matrix[i]; - changed = true; - } - } - } else { - // reset other half if disconnected - for (int i = 0; i < ROWS_PER_HAND; ++i) { - matrix[thatHand + i] = 0; - slave_matrix[i] = 0; - } + changed = memcmp(matrix + thatHand, slave_matrix, sizeof(slave_matrix)) != 0; + last_connected = true; + } else if (last_connected) { + // reset other half when disconnected + memset(slave_matrix, 0, sizeof(slave_matrix)); changed = true; + + last_connected = false; } + if (changed) memcpy(matrix + thatHand, slave_matrix, sizeof(slave_matrix)); + matrix_scan_quantum(); } else { transport_slave(matrix + thatHand, matrix + thisHand); diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index f7eaeec8ac..7c4a617af0 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk @@ -81,7 +81,7 @@ ifneq ($(findstring MK20DX256, $(MCU)),) BOARD ?= PJRC_TEENSY_3_1 endif -ifneq ($(findstring MK66F18, $(MCU)),) +ifneq ($(findstring MK66FX1M0, $(MCU)),) # Cortex version MCU = cortex-m4 @@ -138,6 +138,11 @@ ifneq ($(findstring STM32F042, $(MCU)),) # UF2 settings UF2_FAMILY ?= STM32F0 + + # Stack sizes: Since this chip has limited RAM capacity, the stack area needs to be reduced. + # This ensures that the EEPROM page buffer fits into RAM + USE_PROCESS_STACKSIZE = 0x600 + USE_EXCEPTIONS_STACKSIZE = 0x300 endif ifneq ($(findstring STM32F072, $(MCU)),) @@ -273,6 +278,38 @@ ifneq ($(findstring STM32F401, $(MCU)),) UF2_FAMILY ?= STM32F4 endif +ifneq ($(findstring STM32F405, $(MCU)),) + # Cortex version + MCU = cortex-m4 + + # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 + ARMV = 7 + + ## chip/board settings + # - the next two should match the directories in + # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) + MCU_FAMILY = STM32 + MCU_SERIES = STM32F4xx + + # Linker script to use + # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ + # or <keyboard_dir>/ld/ + MCU_LDSCRIPT ?= STM32F405xG + + # Startup code to use + # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ + MCU_STARTUP ?= stm32f4xx + + # Board: it should exist either in <chibios>/os/hal/boards/, + # <keyboard_dir>/boards/, or drivers/boards/ + BOARD ?= GENERIC_STM32_F405XG + + USE_FPU ?= yes + + # UF2 settings + UF2_FAMILY ?= STM32F4 +endif + ifneq ($(findstring STM32F407, $(MCU)),) # Cortex version MCU = cortex-m4 @@ -504,6 +541,37 @@ ifneq (,$(filter $(MCU),STM32L412 STM32L422)) UF2_FAMILY ?= STM32L4 endif +ifneq ($(findstring GD32VF103, $(MCU)),) + # RISC-V + MCU = risc-v + + # RISC-V extensions and abi configuration + MCU_ARCH = rv32imac + MCU_ABI = ilp32 + MCU_CMODEL = medlow + + ## chip/board settings + # - the next two should match the directories in + # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) + MCU_FAMILY = GD32V + MCU_SERIES = GD32VF103 + + # Linker script to use + # - it should exist either in <chibios>/os/common/startup/RISCV-ECLIC/compilers/GCC/ld/ + # or <keyboard_dir>/ld/ + MCU_LDSCRIPT ?= GD32VF103xB + + # Startup code to use + # - it should exist in <chibios>/os/common/startup/RISCV-ECLIC/compilers/GCC/mk/ + MCU_STARTUP ?= gd32vf103 + + # Board: it should exist either in <chibios>/os/hal/boards/, + # <keyboard_dir>/boards/, or drivers/boards/ + BOARD ?= SIPEED_LONGAN_NANO + + USE_FPU ?= no +endif + ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287)) PROTOCOL = LUFA diff --git a/quantum/process_keycode/process_haptic.c b/quantum/process_keycode/process_haptic.c index 64d455d009..1b9c2f24fa 100644 --- a/quantum/process_keycode/process_haptic.c +++ b/quantum/process_keycode/process_haptic.c @@ -32,6 +32,7 @@ __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t break; case KC_LCTRL ... KC_RGUI: case QK_MOMENTARY ... QK_MOMENTARY_MAX: + case QK_LAYER_MOD ... QK_LAYER_MOD_MAX: #endif #ifdef NO_HAPTIC_FN case KC_FN0 ... KC_FN31: diff --git a/quantum/process_keycode/process_programmable_button.c b/quantum/process_keycode/process_programmable_button.c new file mode 100644 index 0000000000..c6e77faacc --- /dev/null +++ b/quantum/process_keycode/process_programmable_button.c @@ -0,0 +1,31 @@ +/* +Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de> + +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 "process_programmable_button.h" +#include "programmable_button.h" + +bool process_programmable_button(uint16_t keycode, keyrecord_t *record) { + if (keycode >= PROGRAMMABLE_BUTTON_MIN && keycode <= PROGRAMMABLE_BUTTON_MAX) { + uint8_t button = keycode - PROGRAMMABLE_BUTTON_MIN + 1; + if (record->event.pressed) { + programmable_button_on(button); + } else { + programmable_button_off(button); + } + } + return true; +} diff --git a/quantum/process_keycode/process_programmable_button.h b/quantum/process_keycode/process_programmable_button.h new file mode 100644 index 0000000000..47c6ce5614 --- /dev/null +++ b/quantum/process_keycode/process_programmable_button.h @@ -0,0 +1,23 @@ +/* +Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de> + +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 + +#include <stdint.h> +#include "quantum.h" + +bool process_programmable_button(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c index 46fcaaa86b..7853c22c5d 100644 --- a/quantum/process_keycode/process_unicode_common.c +++ b/quantum/process_keycode/process_unicode_common.c @@ -22,6 +22,7 @@ unicode_config_t unicode_config; uint8_t unicode_saved_mods; bool unicode_saved_caps_lock; +bool unicode_saved_num_lock; #if UNICODE_SELECTED_MODES != -1 static uint8_t selected[] = {UNICODE_SELECTED_MODES}; @@ -79,13 +80,14 @@ void persist_unicode_input_mode(void) { eeprom_update_byte(EECONFIG_UNICODEMODE, __attribute__((weak)) void unicode_input_start(void) { unicode_saved_caps_lock = host_keyboard_led_state().caps_lock; + unicode_saved_num_lock = host_keyboard_led_state().num_lock; // Note the order matters here! // Need to do this before we mess around with the mods, or else // UNICODE_KEY_LNX (which is usually Ctrl-Shift-U) might not work // correctly in the shifted case. if (unicode_config.input_mode == UC_LNX && unicode_saved_caps_lock) { - tap_code(KC_CAPS); + tap_code(KC_CAPSLOCK); } unicode_saved_mods = get_mods(); // Save current mods @@ -99,8 +101,12 @@ __attribute__((weak)) void unicode_input_start(void) { tap_code16(UNICODE_KEY_LNX); break; case UC_WIN: + // For increased reliability, use numpad keys for inputting digits + if (!unicode_saved_num_lock) { + tap_code(KC_NUMLOCK); + } register_code(KC_LALT); - tap_code(KC_PPLS); + tap_code(KC_KP_PLUS); break; case UC_WINC: tap_code(UNICODE_KEY_WINC); @@ -117,13 +123,16 @@ __attribute__((weak)) void unicode_input_finish(void) { unregister_code(UNICODE_KEY_MAC); break; case UC_LNX: - tap_code(KC_SPC); + tap_code(KC_SPACE); if (unicode_saved_caps_lock) { - tap_code(KC_CAPS); + tap_code(KC_CAPSLOCK); } break; case UC_WIN: unregister_code(KC_LALT); + if (!unicode_saved_num_lock) { + tap_code(KC_NUMLOCK); + } break; case UC_WINC: tap_code(KC_ENTER); @@ -139,26 +148,44 @@ __attribute__((weak)) void unicode_input_cancel(void) { unregister_code(UNICODE_KEY_MAC); break; case UC_LNX: - tap_code(KC_ESC); + tap_code(KC_ESCAPE); if (unicode_saved_caps_lock) { - tap_code(KC_CAPS); + tap_code(KC_CAPSLOCK); } break; case UC_WINC: - tap_code(KC_ESC); + tap_code(KC_ESCAPE); break; case UC_WIN: unregister_code(KC_LALT); + if (!unicode_saved_num_lock) { + tap_code(KC_NUMLOCK); + } break; } set_mods(unicode_saved_mods); // Reregister previously set mods } +// clang-format off + +static void send_nibble_wrapper(uint8_t digit) { + if (unicode_config.input_mode == UC_WIN) { + uint8_t kc = digit < 10 + ? KC_KP_1 + (10 + digit - 1) % 10 + : KC_A + (digit - 10); + tap_code(kc); + return; + } + send_nibble(digit); +} + +// clang-format on + void register_hex(uint16_t hex) { for (int i = 3; i >= 0; i--) { uint8_t digit = ((hex >> (i * 4)) & 0xF); - send_nibble(digit); + send_nibble_wrapper(digit); } } @@ -171,10 +198,10 @@ void register_hex32(uint32_t hex) { uint8_t digit = ((hex >> (i * 4)) & 0xF); if (digit == 0) { if (!onzerostart) { - send_nibble(digit); + send_nibble_wrapper(digit); } } else { - send_nibble(digit); + send_nibble_wrapper(digit); onzerostart = false; } } diff --git a/quantum/programmable_button.c b/quantum/programmable_button.c new file mode 100644 index 0000000000..be828fd17c --- /dev/null +++ b/quantum/programmable_button.c @@ -0,0 +1,37 @@ +/* +Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de> + +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 "programmable_button.h" +#include "host.h" + +#define REPORT_BIT(index) (((uint32_t)1) << (index - 1)) + +static uint32_t programmable_button_report = 0; + +void programmable_button_clear(void) { programmable_button_report = 0; } + +void programmable_button_send(void) { host_programmable_button_send(programmable_button_report); } + +void programmable_button_on(uint8_t index) { programmable_button_report |= REPORT_BIT(index); } + +void programmable_button_off(uint8_t index) { programmable_button_report &= ~REPORT_BIT(index); } + +bool programmable_button_is_on(uint8_t index) { return !!(programmable_button_report & REPORT_BIT(index)); }; + +uint32_t programmable_button_get_report(void) { return programmable_button_report; }; + +void programmable_button_set_report(uint32_t report) { programmable_button_report = report; } diff --git a/quantum/programmable_button.h b/quantum/programmable_button.h new file mode 100644 index 0000000000..e89b8b9fd6 --- /dev/null +++ b/quantum/programmable_button.h @@ -0,0 +1,30 @@ +/* +Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de> + +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 + +#include <stdint.h> +#include <stdbool.h> +#include "report.h" + +void programmable_button_clear(void); +void programmable_button_send(void); +void programmable_button_on(uint8_t index); +void programmable_button_off(uint8_t index); +bool programmable_button_is_on(uint8_t index); +uint32_t programmable_button_get_report(void); +void programmable_button_set_report(uint32_t report); diff --git a/quantum/quantum.c b/quantum/quantum.c index e60378afe4..ac8857df85 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -25,10 +25,6 @@ # include "backlight.h" #endif -#ifdef API_ENABLE -# include "api.h" -#endif - #ifdef MIDI_ENABLE # include "process_midi.h" #endif @@ -145,12 +141,13 @@ void reset_keyboard(void) { /* Convert record into usable keycode via the contained event. */ uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache) { #ifdef COMBO_ENABLE - if (record->keycode) { return record->keycode; } + if (record->keycode) { + return record->keycode; + } #endif return get_event_keycode(record->event, update_layer_cache); } - /* Convert event into usable keycode. Checks the layer cache to ensure that it * retains the correct keycode after a layer change, if the key is still pressed. * "update_layer_cache" is to ensure that it only updates the layer cache when @@ -179,12 +176,12 @@ uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache) { bool pre_process_record_quantum(keyrecord_t *record) { if (!( #ifdef COMBO_ENABLE - process_combo(get_record_keycode(record, true), record) && + process_combo(get_record_keycode(record, true), record) && #endif - true)) { + true)) { return false; } - return true; // continue processing + return true; // continue processing } /* Get keycode, and then call keyboard function */ @@ -296,6 +293,9 @@ bool process_record_quantum(keyrecord_t *record) { #ifdef JOYSTICK_ENABLE process_joystick(keycode, record) && #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE + process_programmable_button(keycode, record) && +#endif true)) { return false; } @@ -465,14 +465,6 @@ void matrix_scan_quantum() { # include "hd44780.h" #endif -void api_send_unicode(uint32_t unicode) { -#ifdef API_ENABLE - uint8_t chunk[4]; - dword_to_bytes(unicode, chunk); - MT_SEND_DATA(DT_UNICODE, chunk, 5); -#endif -} - //------------------------------------------------------------------------------ // Override these functions in your keymap file to play different tunes on // different events such as startup and bootloader jump @@ -480,3 +472,99 @@ void api_send_unicode(uint32_t unicode) { __attribute__((weak)) void startup_user() {} __attribute__((weak)) void shutdown_user() {} + +/** \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(); } + +void suspend_power_down_quantum(void) { +#ifndef NO_SUSPEND_POWER_DOWN +// Turn off backlight +# ifdef BACKLIGHT_ENABLE + backlight_set(0); +# endif + +# ifdef LED_MATRIX_ENABLE + led_matrix_task(); +# endif +# ifdef RGB_MATRIX_ENABLE + rgb_matrix_task(); +# endif + + // Turn off LED indicators + uint8_t leds_off = 0; +# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE) + if (is_backlight_enabled()) { + // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off + leds_off |= (1 << USB_LED_CAPS_LOCK); + } +# endif + led_set(leds_off); + +// Turn off audio +# ifdef AUDIO_ENABLE + stop_all_notes(); +# endif + +// Turn off underglow +# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) + rgblight_suspend(); +# endif + +# if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(true); +# endif +# if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(true); +# endif + +# ifdef OLED_ENABLE + oled_off(); +# endif +# ifdef ST7565_ENABLE + st7565_off(); +# endif +#endif +} + +/** \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(); } + +__attribute__((weak)) void suspend_wakeup_init_quantum(void) { +// Turn on backlight +#ifdef BACKLIGHT_ENABLE + backlight_init(); +#endif + + // Restore LED indicators + led_set(host_keyboard_leds()); + +// Wake up underglow +#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) + rgblight_wakeup(); +#endif + +#if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(false); +#endif +#if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(false); +#endif + suspend_wakeup_init_kb(); +} diff --git a/quantum/quantum.h b/quantum/quantum.h index 86b717e445..9250f5acce 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -147,6 +147,10 @@ extern layer_state_t layer_state; # include "process_joystick.h" #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE +# include "process_programmable_button.h" +#endif + #ifdef GRAVE_ESC_ENABLE # include "process_grave_esc.h" #endif @@ -233,5 +237,3 @@ void led_set_user(uint8_t usb_led); void led_set_kb(uint8_t usb_led); bool led_update_user(led_t led_state); bool led_update_kb(led_t led_state); - -void api_send_unicode(uint32_t unicode); diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index ef4b0f457b..2ea81dd4c8 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -524,6 +524,40 @@ enum quantum_keycodes { // Additional magic key MAGIC_TOGGLE_GUI, + // Programmable Button + PROGRAMMABLE_BUTTON_1, + PROGRAMMABLE_BUTTON_2, + PROGRAMMABLE_BUTTON_3, + PROGRAMMABLE_BUTTON_4, + PROGRAMMABLE_BUTTON_5, + PROGRAMMABLE_BUTTON_6, + PROGRAMMABLE_BUTTON_7, + PROGRAMMABLE_BUTTON_8, + PROGRAMMABLE_BUTTON_9, + PROGRAMMABLE_BUTTON_10, + PROGRAMMABLE_BUTTON_11, + PROGRAMMABLE_BUTTON_12, + PROGRAMMABLE_BUTTON_13, + PROGRAMMABLE_BUTTON_14, + PROGRAMMABLE_BUTTON_15, + PROGRAMMABLE_BUTTON_16, + PROGRAMMABLE_BUTTON_17, + PROGRAMMABLE_BUTTON_18, + PROGRAMMABLE_BUTTON_19, + PROGRAMMABLE_BUTTON_20, + PROGRAMMABLE_BUTTON_21, + PROGRAMMABLE_BUTTON_22, + PROGRAMMABLE_BUTTON_23, + PROGRAMMABLE_BUTTON_24, + PROGRAMMABLE_BUTTON_25, + PROGRAMMABLE_BUTTON_26, + PROGRAMMABLE_BUTTON_27, + PROGRAMMABLE_BUTTON_28, + PROGRAMMABLE_BUTTON_29, + PROGRAMMABLE_BUTTON_30, + PROGRAMMABLE_BUTTON_31, + PROGRAMMABLE_BUTTON_32, + // Start of custom keycode range for keyboards and keymaps - always leave at the end SAFE_RANGE }; @@ -854,3 +888,39 @@ enum quantum_keycodes { #define OS_TOGG ONESHOT_TOGGLE #define OS_ON ONESHOT_ENABLE #define OS_OFF ONESHOT_DISABLE + +// Programmable Button aliases +#define PB_1 PROGRAMMABLE_BUTTON_1 +#define PB_2 PROGRAMMABLE_BUTTON_2 +#define PB_3 PROGRAMMABLE_BUTTON_3 +#define PB_4 PROGRAMMABLE_BUTTON_4 +#define PB_5 PROGRAMMABLE_BUTTON_5 +#define PB_6 PROGRAMMABLE_BUTTON_6 +#define PB_7 PROGRAMMABLE_BUTTON_7 +#define PB_8 PROGRAMMABLE_BUTTON_8 +#define PB_9 PROGRAMMABLE_BUTTON_9 +#define PB_10 PROGRAMMABLE_BUTTON_10 +#define PB_11 PROGRAMMABLE_BUTTON_11 +#define PB_12 PROGRAMMABLE_BUTTON_12 +#define PB_13 PROGRAMMABLE_BUTTON_13 +#define PB_14 PROGRAMMABLE_BUTTON_14 +#define PB_15 PROGRAMMABLE_BUTTON_15 +#define PB_16 PROGRAMMABLE_BUTTON_16 +#define PB_17 PROGRAMMABLE_BUTTON_17 +#define PB_18 PROGRAMMABLE_BUTTON_18 +#define PB_19 PROGRAMMABLE_BUTTON_19 +#define PB_20 PROGRAMMABLE_BUTTON_20 +#define PB_21 PROGRAMMABLE_BUTTON_21 +#define PB_22 PROGRAMMABLE_BUTTON_22 +#define PB_23 PROGRAMMABLE_BUTTON_23 +#define PB_24 PROGRAMMABLE_BUTTON_24 +#define PB_25 PROGRAMMABLE_BUTTON_25 +#define PB_26 PROGRAMMABLE_BUTTON_26 +#define PB_27 PROGRAMMABLE_BUTTON_27 +#define PB_28 PROGRAMMABLE_BUTTON_28 +#define PB_29 PROGRAMMABLE_BUTTON_29 +#define PB_30 PROGRAMMABLE_BUTTON_30 +#define PB_31 PROGRAMMABLE_BUTTON_31 +#define PB_32 PROGRAMMABLE_BUTTON_32 +#define PROGRAMMABLE_BUTTON_MIN PROGRAMMABLE_BUTTON_1 +#define PROGRAMMABLE_BUTTON_MAX PROGRAMMABLE_BUTTON_32 diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c index 8f00b40877..c260b6e1e8 100644 --- a/quantum/rgb_matrix/rgb_matrix.c +++ b/quantum/rgb_matrix/rgb_matrix.c @@ -31,14 +31,6 @@ const led_point_t k_rgb_matrix_center = {112, 32}; const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; #endif -// clang-format off -#ifndef RGB_MATRIX_IMMEDIATE_EEPROM -# define rgb_eeconfig_update(v) rgb_update_eeprom |= v -#else -# define rgb_eeconfig_update(v) if (v) eeconfig_update_rgb_matrix() -#endif -// clang-format on - __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } // Generic effect runners @@ -128,7 +120,6 @@ last_hit_t g_last_hit_tracker; // internals static bool suspend_state = false; -static bool rgb_update_eeprom = false; static uint8_t rgb_last_enable = UINT8_MAX; static uint8_t rgb_last_effect = UINT8_MAX; static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; @@ -148,9 +139,9 @@ static last_hit_t last_hit_buffer; const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; #endif -void eeconfig_read_rgb_matrix(void) { eeprom_read_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); } +EECONFIG_DEBOUNCE_HELPER(rgb_matrix, EECONFIG_RGB_MATRIX, rgb_matrix_config); -void eeconfig_update_rgb_matrix(void) { eeprom_update_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); } +void eeconfig_update_rgb_matrix(void) { eeconfig_flush_rgb_matrix(true); } void eeconfig_update_rgb_matrix_default(void) { dprintf("eeconfig_update_rgb_matrix_default\n"); @@ -159,7 +150,7 @@ void eeconfig_update_rgb_matrix_default(void) { rgb_matrix_config.hsv = (HSV){RGB_MATRIX_STARTUP_HUE, RGB_MATRIX_STARTUP_SAT, RGB_MATRIX_STARTUP_VAL}; rgb_matrix_config.speed = RGB_MATRIX_STARTUP_SPD; rgb_matrix_config.flags = LED_FLAG_ALL; - eeconfig_update_rgb_matrix(); + eeconfig_flush_rgb_matrix(true); } void eeconfig_debug_rgb_matrix(void) { @@ -314,9 +305,8 @@ static void rgb_task_timers(void) { } static void rgb_task_sync(void) { + eeconfig_flush_rgb_matrix(false); // next task - if (rgb_update_eeprom) eeconfig_update_rgb_matrix(); - rgb_update_eeprom = false; if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING; } @@ -491,7 +481,7 @@ void rgb_matrix_init(void) { eeconfig_update_rgb_matrix_default(); } - eeconfig_read_rgb_matrix(); + eeconfig_init_rgb_matrix(); if (!rgb_matrix_config.mode) { dprintf("rgb_matrix_init_drivers rgb_matrix_config.mode = 0. Write default values to EEPROM.\n"); eeconfig_update_rgb_matrix_default(); @@ -514,7 +504,7 @@ bool rgb_matrix_get_suspend_state(void) { return suspend_state; } void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) { rgb_matrix_config.enable ^= 1; rgb_task_state = STARTING; - rgb_eeconfig_update(write_to_eeprom); + eeconfig_flag_rgb_matrix(write_to_eeprom); dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable); } void rgb_matrix_toggle_noeeprom(void) { rgb_matrix_toggle_eeprom_helper(false); } @@ -522,7 +512,7 @@ void rgb_matrix_toggle(void) { rgb_matrix_toggle_eeprom_helper(true); } void rgb_matrix_enable(void) { rgb_matrix_enable_noeeprom(); - rgb_eeconfig_update(true); + eeconfig_flag_rgb_matrix(true); } void rgb_matrix_enable_noeeprom(void) { @@ -532,7 +522,7 @@ void rgb_matrix_enable_noeeprom(void) { void rgb_matrix_disable(void) { rgb_matrix_disable_noeeprom(); - rgb_eeconfig_update(true); + eeconfig_flag_rgb_matrix(true); } void rgb_matrix_disable_noeeprom(void) { @@ -554,7 +544,7 @@ void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { rgb_matrix_config.mode = mode; } rgb_task_state = STARTING; - rgb_eeconfig_update(write_to_eeprom); + eeconfig_flag_rgb_matrix(write_to_eeprom); dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode); } void rgb_matrix_mode_noeeprom(uint8_t mode) { rgb_matrix_mode_eeprom_helper(mode, false); } @@ -583,7 +573,7 @@ void rgb_matrix_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, boo rgb_matrix_config.hsv.h = hue; rgb_matrix_config.hsv.s = sat; rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val; - rgb_eeconfig_update(write_to_eeprom); + eeconfig_flag_rgb_matrix(write_to_eeprom); dprintf("rgb matrix set hsv [%s]: %u,%u,%u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v); } void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { rgb_matrix_sethsv_eeprom_helper(hue, sat, val, false); } @@ -620,7 +610,7 @@ void rgb_matrix_decrease_val(void) { rgb_matrix_decrease_val_helper(true); } void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { rgb_matrix_config.speed = speed; - rgb_eeconfig_update(write_to_eeprom); + eeconfig_flag_rgb_matrix(write_to_eeprom); dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed); } void rgb_matrix_set_speed_noeeprom(uint8_t speed) { rgb_matrix_set_speed_eeprom_helper(speed, false); } diff --git a/quantum/rgb_matrix/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c index 2cec162e22..4335088eb8 100644 --- a/quantum/rgb_matrix/rgb_matrix_drivers.c +++ b/quantum/rgb_matrix/rgb_matrix_drivers.c @@ -24,110 +24,126 @@ */ #if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FL3737) || defined(IS31FL3741) - # include "i2c_master.h" +// TODO: Remove this at some later date +# if defined(DRIVER_ADDR_1) && defined(DRIVER_ADDR_2) +# if DRIVER_ADDR_1 == DRIVER_ADDR_2 +# error "Setting DRIVER_ADDR_2 == DRIVER_ADDR_1 is obsolete. If you are only using one ISSI driver, set DRIVER_COUNT to 1 and remove DRIVER_ADDR_2" +# endif +# endif + static void init(void) { i2c_init(); -# ifdef IS31FL3731 + +# if defined(IS31FL3731) IS31FL3731_init(DRIVER_ADDR_1); -# ifdef DRIVER_ADDR_2 +# if defined(DRIVER_ADDR_2) IS31FL3731_init(DRIVER_ADDR_2); -# endif -# ifdef DRIVER_ADDR_3 +# if defined(DRIVER_ADDR_3) IS31FL3731_init(DRIVER_ADDR_3); -# endif -# ifdef DRIVER_ADDR_4 +# if defined(DRIVER_ADDR_4) IS31FL3731_init(DRIVER_ADDR_4); +# endif +# endif # endif + # elif defined(IS31FL3733) -# ifndef DRIVER_SYNC_1 +# if !defined(DRIVER_SYNC_1) # define DRIVER_SYNC_1 0 # endif IS31FL3733_init(DRIVER_ADDR_1, DRIVER_SYNC_1); -# if defined DRIVER_ADDR_2 && (DRIVER_ADDR_1 != DRIVER_ADDR_2) -# ifndef DRIVER_SYNC_2 +# if defined(DRIVER_ADDR_2) +# if !defined(DRIVER_SYNC_2) # define DRIVER_SYNC_2 0 # endif IS31FL3733_init(DRIVER_ADDR_2, DRIVER_SYNC_2); -# endif -# ifdef DRIVER_ADDR_3 -# ifndef DRIVER_SYNC_3 -# define DRIVER_SYNC_3 0 -# endif +# if defined(DRIVER_ADDR_3) +# if !defined(DRIVER_SYNC_3) +# define DRIVER_SYNC_3 0 +# endif IS31FL3733_init(DRIVER_ADDR_3, DRIVER_SYNC_3); -# endif -# ifdef DRIVER_ADDR_4 -# ifndef DRIVER_SYNC_4 -# define DRIVER_SYNC_4 0 -# endif +# if defined(DRIVER_ADDR_4) +# if !defined(DRIVER_SYNC_4) +# define DRIVER_SYNC_4 0 +# endif IS31FL3733_init(DRIVER_ADDR_4, DRIVER_SYNC_4); +# endif +# endif # endif + # elif defined(IS31FL3737) IS31FL3737_init(DRIVER_ADDR_1); -# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility +# if defined(DRIVER_ADDR_2) IS31FL3737_init(DRIVER_ADDR_2); # endif -# else + +# elif defined(IS31FL3741) IS31FL3741_init(DRIVER_ADDR_1); # endif + for (int index = 0; index < DRIVER_LED_TOTAL; index++) { bool enabled = true; + // This only caches it for later -# ifdef IS31FL3731 +# if defined(IS31FL3731) IS31FL3731_set_led_control_register(index, enabled, enabled, enabled); # elif defined(IS31FL3733) IS31FL3733_set_led_control_register(index, enabled, enabled, enabled); # elif defined(IS31FL3737) IS31FL3737_set_led_control_register(index, enabled, enabled, enabled); -# else +# elif defined(IS31FL3741) IS31FL3741_set_led_control_register(index, enabled, enabled, enabled); # endif } + // This actually updates the LED drivers -# ifdef IS31FL3731 +# if defined(IS31FL3731) IS31FL3731_update_led_control_registers(DRIVER_ADDR_1, 0); -# ifdef DRIVER_ADDR_2 +# if defined(DRIVER_ADDR_2) IS31FL3731_update_led_control_registers(DRIVER_ADDR_2, 1); -# endif -# ifdef DRIVER_ADDR_3 +# if defined(DRIVER_ADDR_3) IS31FL3731_update_led_control_registers(DRIVER_ADDR_3, 2); -# endif -# ifdef DRIVER_ADDR_4 +# if defined(DRIVER_ADDR_4) IS31FL3731_update_led_control_registers(DRIVER_ADDR_4, 3); +# endif +# endif # endif + # elif defined(IS31FL3733) IS31FL3733_update_led_control_registers(DRIVER_ADDR_1, 0); -# ifdef DRIVER_ADDR_2 +# if defined(DRIVER_ADDR_2) IS31FL3733_update_led_control_registers(DRIVER_ADDR_2, 1); -# endif -# ifdef DRIVER_ADDR_3 +# if defined(DRIVER_ADDR_3) IS31FL3733_update_led_control_registers(DRIVER_ADDR_3, 2); -# endif -# ifdef DRIVER_ADDR_4 +# if defined(DRIVER_ADDR_4) IS31FL3733_update_led_control_registers(DRIVER_ADDR_4, 3); +# endif +# endif # endif + # elif defined(IS31FL3737) IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, 0); -# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility +# if defined(DRIVER_ADDR_2) IS31FL3737_update_led_control_registers(DRIVER_ADDR_2, 1); # endif -# else + +# elif defined(IS31FL3741) IS31FL3741_update_led_control_registers(DRIVER_ADDR_1, 0); # endif } -# ifdef IS31FL3731 +# if defined(IS31FL3731) static void flush(void) { IS31FL3731_update_pwm_buffers(DRIVER_ADDR_1, 0); -# ifdef DRIVER_ADDR_2 +# if defined(DRIVER_ADDR_2) IS31FL3731_update_pwm_buffers(DRIVER_ADDR_2, 1); -# endif -# ifdef DRIVER_ADDR_3 +# if defined(DRIVER_ADDR_3) IS31FL3731_update_pwm_buffers(DRIVER_ADDR_3, 2); -# endif -# ifdef DRIVER_ADDR_4 +# if defined(DRIVER_ADDR_4) IS31FL3731_update_pwm_buffers(DRIVER_ADDR_4, 3); +# endif +# endif # endif } @@ -137,17 +153,18 @@ const rgb_matrix_driver_t rgb_matrix_driver = { .set_color = IS31FL3731_set_color, .set_color_all = IS31FL3731_set_color_all, }; + # elif defined(IS31FL3733) static void flush(void) { IS31FL3733_update_pwm_buffers(DRIVER_ADDR_1, 0); -# ifdef DRIVER_ADDR_2 +# if defined(DRIVER_ADDR_2) IS31FL3733_update_pwm_buffers(DRIVER_ADDR_2, 1); -# endif -# ifdef DRIVER_ADDR_3 +# if defined(DRIVER_ADDR_3) IS31FL3733_update_pwm_buffers(DRIVER_ADDR_3, 2); -# endif -# ifdef DRIVER_ADDR_4 +# if defined(DRIVER_ADDR_4) IS31FL3733_update_pwm_buffers(DRIVER_ADDR_4, 3); +# endif +# endif # endif } @@ -157,10 +174,11 @@ const rgb_matrix_driver_t rgb_matrix_driver = { .set_color = IS31FL3733_set_color, .set_color_all = IS31FL3733_set_color_all, }; + # elif defined(IS31FL3737) static void flush(void) { IS31FL3737_update_pwm_buffers(DRIVER_ADDR_1, 0); -# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility +# if defined(DRIVER_ADDR_2) IS31FL3737_update_pwm_buffers(DRIVER_ADDR_2, 1); # endif } @@ -171,10 +189,11 @@ const rgb_matrix_driver_t rgb_matrix_driver = { .set_color = IS31FL3737_set_color, .set_color_all = IS31FL3737_set_color_all, }; -# else + +# elif defined(IS31FL3741) static void flush(void) { IS31FL3741_update_pwm_buffers(DRIVER_ADDR_1, 0); -# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility +# if defined(DRIVER_ADDR_2) IS31FL3741_update_pwm_buffers(DRIVER_ADDR_2, 1); # endif } @@ -189,17 +208,19 @@ const rgb_matrix_driver_t rgb_matrix_driver = { #elif defined(AW20216) # include "spi_master.h" + static void init(void) { spi_init(); + AW20216_init(DRIVER_1_CS, DRIVER_1_EN); -# ifdef DRIVER_2_CS +# if defined(DRIVER_2_CS) AW20216_init(DRIVER_2_CS, DRIVER_2_EN); # endif } static void flush(void) { AW20216_update_pwm_buffers(DRIVER_1_CS, 0); -# ifdef DRIVER_2_CS +# if defined(DRIVER_2_CS) AW20216_update_pwm_buffers(DRIVER_2_CS, 1); # endif } diff --git a/quantum/sequencer/tests/rules.mk b/quantum/sequencer/tests/rules.mk index 76c221cf92..87a204669c 100644 --- a/quantum/sequencer/tests/rules.mk +++ b/quantum/sequencer/tests/rules.mk @@ -1,5 +1,5 @@ # The letter case of these variables might seem odd. However: -# - it is consistent with the serial_link example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features) +# - it is consistent with the example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features) # - Neither `make test:sequencer` or `make test:SEQUENCER` work when using SCREAMING_SNAKE_CASE sequencer_DEFS := -DNO_DEBUG -DMIDI_MOCKED diff --git a/quantum/serial_link/LICENSE b/quantum/serial_link/LICENSE deleted file mode 100644 index d13cc4b26a..0000000000 --- a/quantum/serial_link/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -The MIT License (MIT) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. diff --git a/quantum/serial_link/README.md b/quantum/serial_link/README.md deleted file mode 100644 index 05871dbdf7..0000000000 --- a/quantum/serial_link/README.md +++ /dev/null @@ -1 +0,0 @@ -# qmk_serial_link diff --git a/quantum/serial_link/protocol/byte_stuffer.c b/quantum/serial_link/protocol/byte_stuffer.c deleted file mode 100644 index d3a91d8286..0000000000 --- a/quantum/serial_link/protocol/byte_stuffer.c +++ /dev/null @@ -1,135 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "serial_link/protocol/byte_stuffer.h" -#include "serial_link/protocol/frame_validator.h" -#include "serial_link/protocol/physical.h" -#include <stdbool.h> - -// This implements the "Consistent overhead byte stuffing protocol" -// https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing -// http://www.stuartcheshire.org/papers/COBSforToN.pdf - -typedef struct byte_stuffer_state { - uint16_t next_zero; - uint16_t data_pos; - bool long_frame; - uint8_t data[MAX_FRAME_SIZE]; -} byte_stuffer_state_t; - -static byte_stuffer_state_t states[NUM_LINKS]; - -void init_byte_stuffer_state(byte_stuffer_state_t* state) { - state->next_zero = 0; - state->data_pos = 0; - state->long_frame = false; -} - -void init_byte_stuffer(void) { - int i; - for (i = 0; i < NUM_LINKS; i++) { - init_byte_stuffer_state(&states[i]); - } -} - -void byte_stuffer_recv_byte(uint8_t link, uint8_t data) { - byte_stuffer_state_t* state = &states[link]; - // Start of a new frame - if (state->next_zero == 0) { - state->next_zero = data; - state->long_frame = data == 0xFF; - state->data_pos = 0; - return; - } - - state->next_zero--; - if (data == 0) { - if (state->next_zero == 0) { - // The frame is completed - if (state->data_pos > 0) { - validator_recv_frame(link, state->data, state->data_pos); - } - } else { - // The frame is invalid, so reset - init_byte_stuffer_state(state); - } - } else { - if (state->data_pos == MAX_FRAME_SIZE) { - // We exceeded our maximum frame size - // therefore there's nothing else to do than reset to a new frame - state->next_zero = data; - state->long_frame = data == 0xFF; - state->data_pos = 0; - } else if (state->next_zero == 0) { - if (state->long_frame) { - // This is part of a long frame, so continue - state->next_zero = data; - state->long_frame = data == 0xFF; - } else { - // Special case for zeroes - state->next_zero = data; - state->data[state->data_pos++] = 0; - } - } else { - state->data[state->data_pos++] = data; - } - } -} - -static void send_block(uint8_t link, uint8_t* start, uint8_t* end, uint8_t num_non_zero) { - send_data(link, &num_non_zero, 1); - if (end > start) { - send_data(link, start, end - start); - } -} - -void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) { - const uint8_t zero = 0; - if (size > 0) { - uint16_t num_non_zero = 1; - uint8_t* end = data + size; - uint8_t* start = data; - while (data < end) { - if (num_non_zero == 0xFF) { - // There's more data after big non-zero block - // So send it, and start a new block - send_block(link, start, data, num_non_zero); - start = data; - num_non_zero = 1; - } else { - if (*data == 0) { - // A zero encountered, so send the block - send_block(link, start, data, num_non_zero); - start = data + 1; - num_non_zero = 1; - } else { - num_non_zero++; - } - ++data; - } - } - send_block(link, start, data, num_non_zero); - send_data(link, &zero, 1); - } -} diff --git a/quantum/serial_link/protocol/byte_stuffer.h b/quantum/serial_link/protocol/byte_stuffer.h deleted file mode 100644 index 397ed3baae..0000000000 --- a/quantum/serial_link/protocol/byte_stuffer.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#pragma once - -#include <stdint.h> - -#define MAX_FRAME_SIZE 1024 -#define NUM_LINKS 2 - -void init_byte_stuffer(void); -void byte_stuffer_recv_byte(uint8_t link, uint8_t data); -void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size); diff --git a/quantum/serial_link/protocol/frame_router.c b/quantum/serial_link/protocol/frame_router.c deleted file mode 100644 index 5292673700..0000000000 --- a/quantum/serial_link/protocol/frame_router.c +++ /dev/null @@ -1,64 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "serial_link/protocol/frame_router.h" -#include "serial_link/protocol/transport.h" -#include "serial_link/protocol/frame_validator.h" - -static bool is_master; - -void router_set_master(bool master) { is_master = master; } - -void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) { - if (is_master) { - if (link == DOWN_LINK) { - transport_recv_frame(data[size - 1], data, size - 1); - } - } else { - if (link == UP_LINK) { - if (data[size - 1] & 1) { - transport_recv_frame(0, data, size - 1); - } - data[size - 1] >>= 1; - validator_send_frame(DOWN_LINK, data, size); - } else { - data[size - 1]++; - validator_send_frame(UP_LINK, data, size); - } - } -} - -void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) { - if (destination == 0) { - if (!is_master) { - data[size] = 1; - validator_send_frame(UP_LINK, data, size + 1); - } - } else { - if (is_master) { - data[size] = destination; - validator_send_frame(DOWN_LINK, data, size + 1); - } - } -} diff --git a/quantum/serial_link/protocol/frame_router.h b/quantum/serial_link/protocol/frame_router.h deleted file mode 100644 index 9325fe4eed..0000000000 --- a/quantum/serial_link/protocol/frame_router.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#pragma once - -#include <stdint.h> -#include <stdbool.h> - -#define UP_LINK 0 -#define DOWN_LINK 1 - -void router_set_master(bool master); -void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size); -void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size); diff --git a/quantum/serial_link/protocol/frame_validator.c b/quantum/serial_link/protocol/frame_validator.c deleted file mode 100644 index bc9136f70b..0000000000 --- a/quantum/serial_link/protocol/frame_validator.c +++ /dev/null @@ -1,57 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "serial_link/protocol/frame_validator.h" -#include "serial_link/protocol/frame_router.h" -#include "serial_link/protocol/byte_stuffer.h" -#include <string.h> - -const uint32_t poly8_lookup[256] = {0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D}; - -static uint32_t crc32_byte(uint8_t* p, uint32_t bytelength) { - uint32_t crc = 0xffffffff; - while (bytelength-- != 0) crc = poly8_lookup[((uint8_t)crc ^ *(p++))] ^ (crc >> 8); - // return (~crc); also works - return (crc ^ 0xffffffff); -} - -void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) { - if (size > 4) { - uint32_t frame_crc; - memcpy(&frame_crc, data + size - 4, 4); - uint32_t expected_crc = crc32_byte(data, size - 4); - if (frame_crc == expected_crc) { - route_incoming_frame(link, data, size - 4); - } - } -} - -void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size) { - uint32_t crc = crc32_byte(data, size); - memcpy(data + size, &crc, 4); - byte_stuffer_send_frame(link, data, size + 4); -} diff --git a/quantum/serial_link/protocol/frame_validator.h b/quantum/serial_link/protocol/frame_validator.h deleted file mode 100644 index 0f78768a00..0000000000 --- a/quantum/serial_link/protocol/frame_validator.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#pragma once - -#include <stdint.h> - -void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size); -// The buffer pointed to by the data needs 4 additional bytes -void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size); diff --git a/quantum/serial_link/protocol/physical.h b/quantum/serial_link/protocol/physical.h deleted file mode 100644 index 399c9d1f76..0000000000 --- a/quantum/serial_link/protocol/physical.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#pragma once - -void send_data(uint8_t link, const uint8_t* data, uint16_t size); diff --git a/quantum/serial_link/protocol/transport.c b/quantum/serial_link/protocol/transport.c deleted file mode 100644 index 73b8dc62e9..0000000000 --- a/quantum/serial_link/protocol/transport.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "serial_link/protocol/transport.h" -#include "serial_link/protocol/frame_router.h" -#include "serial_link/protocol/triple_buffered_object.h" -#include <string.h> - -#define MAX_REMOTE_OBJECTS 16 -static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS]; -static uint32_t num_remote_objects = 0; - -void reinitialize_serial_link_transport(void) { num_remote_objects = 0; } - -void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) { - unsigned int i; - for (i = 0; i < _num_remote_objects; i++) { - remote_object_t* obj = _remote_objects[i]; - remote_objects[num_remote_objects++] = obj; - if (obj->object_type == MASTER_TO_ALL_SLAVES) { - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; - triple_buffer_init(tb); - uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); - tb = (triple_buffer_object_t*)start; - triple_buffer_init(tb); - } else if (obj->object_type == MASTER_TO_SINGLE_SLAVE) { - uint8_t* start = obj->buffer; - unsigned int j; - for (j = 0; j < NUM_SLAVES; j++) { - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; - triple_buffer_init(tb); - start += LOCAL_OBJECT_SIZE(obj->object_size); - } - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; - triple_buffer_init(tb); - } else { - uint8_t* start = obj->buffer; - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; - triple_buffer_init(tb); - start += LOCAL_OBJECT_SIZE(obj->object_size); - unsigned int j; - for (j = 0; j < NUM_SLAVES; j++) { - tb = (triple_buffer_object_t*)start; - triple_buffer_init(tb); - start += REMOTE_OBJECT_SIZE(obj->object_size); - } - } - } -} - -void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) { - uint8_t id = data[size - 1]; - if (id < num_remote_objects) { - remote_object_t* obj = remote_objects[id]; - if (obj->object_size == size - 1) { - uint8_t* start; - if (obj->object_type == MASTER_TO_ALL_SLAVES) { - start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); - } else if (obj->object_type == SLAVE_TO_MASTER) { - start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); - start += (from - 1) * REMOTE_OBJECT_SIZE(obj->object_size); - } else { - start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size); - } - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; - void* ptr = triple_buffer_begin_write_internal(obj->object_size, tb); - memcpy(ptr, data, size - 1); - triple_buffer_end_write_internal(tb); - } - } -} - -void update_transport(void) { - unsigned int i; - for (i = 0; i < num_remote_objects; i++) { - remote_object_t* obj = remote_objects[i]; - if (obj->object_type == MASTER_TO_ALL_SLAVES || obj->object_type == SLAVE_TO_MASTER) { - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; - uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb); - if (ptr) { - ptr[obj->object_size] = i; - uint8_t dest = obj->object_type == MASTER_TO_ALL_SLAVES ? 0xFF : 0; - router_send_frame(dest, ptr, obj->object_size + 1); - } - } else { - uint8_t* start = obj->buffer; - unsigned int j; - for (j = 0; j < NUM_SLAVES; j++) { - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; - uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb); - if (ptr) { - ptr[obj->object_size] = i; - uint8_t dest = j + 1; - router_send_frame(dest, ptr, obj->object_size + 1); - } - start += LOCAL_OBJECT_SIZE(obj->object_size); - } - } - } -} diff --git a/quantum/serial_link/protocol/transport.h b/quantum/serial_link/protocol/transport.h deleted file mode 100644 index 3ce0c9fe4e..0000000000 --- a/quantum/serial_link/protocol/transport.h +++ /dev/null @@ -1,139 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#pragma once - -#include "serial_link/protocol/triple_buffered_object.h" -#include "serial_link/system/serial_link.h" - -#define NUM_SLAVES 8 -#define LOCAL_OBJECT_EXTRA 16 - -// master -> slave = 1 local(target all), 1 remote object -// slave -> master = 1 local(target 0), multiple remote objects -// master -> single slave (multiple local, target id), 1 remote object -typedef enum { - MASTER_TO_ALL_SLAVES, - MASTER_TO_SINGLE_SLAVE, - SLAVE_TO_MASTER, -} remote_object_type; - -typedef struct { - remote_object_type object_type; - uint16_t object_size; - uint8_t buffer[] __attribute__((aligned(4))); -} remote_object_t; - -#define REMOTE_OBJECT_SIZE(objectsize) (sizeof(triple_buffer_object_t) + objectsize * 3) -#define LOCAL_OBJECT_SIZE(objectsize) (sizeof(triple_buffer_object_t) + (objectsize + LOCAL_OBJECT_EXTRA) * 3) - -#define REMOTE_OBJECT_HELPER(name, type, num_local, num_remote) \ - typedef struct { \ - remote_object_t object; \ - uint8_t buffer[num_remote * REMOTE_OBJECT_SIZE(sizeof(type)) + num_local * LOCAL_OBJECT_SIZE(sizeof(type))]; \ - } remote_object_##name##_t; - -#define MASTER_TO_ALL_SLAVES_OBJECT(name, type) \ - REMOTE_OBJECT_HELPER(name, type, 1, 1) \ - remote_object_##name##_t remote_object_##name = {.object = { \ - .object_type = MASTER_TO_ALL_SLAVES, \ - .object_size = sizeof(type), \ - }}; \ - type* begin_write_##name(void) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \ - return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \ - } \ - void end_write_##name(void) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \ - triple_buffer_end_write_internal(tb); \ - signal_data_written(); \ - } \ - type* read_##name(void) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ - return (type*)triple_buffer_read_internal(obj->object_size, tb); \ - } - -#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \ - REMOTE_OBJECT_HELPER(name, type, NUM_SLAVES, 1) \ - remote_object_##name##_t remote_object_##name = {.object = { \ - .object_type = MASTER_TO_SINGLE_SLAVE, \ - .object_size = sizeof(type), \ - }}; \ - type* begin_write_##name(uint8_t slave) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - uint8_t* start = obj->buffer; \ - start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ - return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \ - } \ - void end_write_##name(uint8_t slave) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - uint8_t* start = obj->buffer; \ - start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ - triple_buffer_end_write_internal(tb); \ - signal_data_written(); \ - } \ - type* read_##name() { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size); \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ - return (type*)triple_buffer_read_internal(obj->object_size, tb); \ - } - -#define SLAVE_TO_MASTER_OBJECT(name, type) \ - REMOTE_OBJECT_HELPER(name, type, 1, NUM_SLAVES) \ - remote_object_##name##_t remote_object_##name = {.object = { \ - .object_type = SLAVE_TO_MASTER, \ - .object_size = sizeof(type), \ - }}; \ - type* begin_write_##name(void) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \ - return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \ - } \ - void end_write_##name(void) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \ - triple_buffer_end_write_internal(tb); \ - signal_data_written(); \ - } \ - type* read_##name(uint8_t slave) { \ - remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ - uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); \ - start += slave * REMOTE_OBJECT_SIZE(obj->object_size); \ - triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ - return (type*)triple_buffer_read_internal(obj->object_size, tb); \ - } - -#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name - -void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects); -void reinitialize_serial_link_transport(void); -void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size); -void update_transport(void); diff --git a/quantum/serial_link/protocol/triple_buffered_object.c b/quantum/serial_link/protocol/triple_buffered_object.c deleted file mode 100644 index e0c6d702a5..0000000000 --- a/quantum/serial_link/protocol/triple_buffered_object.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "serial_link/protocol/triple_buffered_object.h" -#include "serial_link/system/serial_link.h" -#include <stdbool.h> -#include <stddef.h> - -#define GET_READ_INDEX() object->state & 3 -#define GET_WRITE_INDEX() (object->state >> 2) & 3 -#define GET_SHARED_INDEX() (object->state >> 4) & 3 -#define GET_DATA_AVAILABLE() (object->state >> 6) & 1 - -#define SET_READ_INDEX(i) object->state = ((object->state & ~3) | i) -#define SET_WRITE_INDEX(i) object->state = ((object->state & ~(3 << 2)) | (i << 2)) -#define SET_SHARED_INDEX(i) object->state = ((object->state & ~(3 << 4)) | (i << 4)) -#define SET_DATA_AVAILABLE(i) object->state = ((object->state & ~(1 << 6)) | (i << 6)) - -void triple_buffer_init(triple_buffer_object_t* object) { - object->state = 0; - SET_WRITE_INDEX(0); - SET_READ_INDEX(1); - SET_SHARED_INDEX(2); - SET_DATA_AVAILABLE(0); -} - -void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object) { - serial_link_lock(); - if (GET_DATA_AVAILABLE()) { - uint8_t shared_index = GET_SHARED_INDEX(); - uint8_t read_index = GET_READ_INDEX(); - SET_READ_INDEX(shared_index); - SET_SHARED_INDEX(read_index); - SET_DATA_AVAILABLE(false); - serial_link_unlock(); - return object->buffer + object_size * shared_index; - } else { - serial_link_unlock(); - return NULL; - } -} - -void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object) { - uint8_t write_index = GET_WRITE_INDEX(); - return object->buffer + object_size * write_index; -} - -void triple_buffer_end_write_internal(triple_buffer_object_t* object) { - serial_link_lock(); - uint8_t shared_index = GET_SHARED_INDEX(); - uint8_t write_index = GET_WRITE_INDEX(); - SET_SHARED_INDEX(write_index); - SET_WRITE_INDEX(shared_index); - SET_DATA_AVAILABLE(true); - serial_link_unlock(); -} diff --git a/quantum/serial_link/protocol/triple_buffered_object.h b/quantum/serial_link/protocol/triple_buffered_object.h deleted file mode 100644 index 717d6d7b8b..0000000000 --- a/quantum/serial_link/protocol/triple_buffered_object.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#pragma once - -#include <stdint.h> - -typedef struct { - uint8_t state; - uint8_t buffer[] __attribute__((aligned(4))); -} triple_buffer_object_t; - -void triple_buffer_init(triple_buffer_object_t* object); - -#define triple_buffer_begin_write(object) (typeof(*object.buffer[0])*)triple_buffer_begin_write_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object) - -#define triple_buffer_end_write(object) triple_buffer_end_write_internal((triple_buffer_object_t*)object) - -#define triple_buffer_read(object) (typeof(*object.buffer[0])*)triple_buffer_read_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object) - -void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object); -void triple_buffer_end_write_internal(triple_buffer_object_t* object); -void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object); diff --git a/quantum/serial_link/system/serial_link.c b/quantum/serial_link/system/serial_link.c deleted file mode 100644 index 6363f8ff3b..0000000000 --- a/quantum/serial_link/system/serial_link.c +++ /dev/null @@ -1,250 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ -#include "report.h" -#include "host_driver.h" -#include "serial_link/system/serial_link.h" -#include <hal.h> -#include "serial_link/protocol/byte_stuffer.h" -#include "serial_link/protocol/transport.h" -#include "serial_link/protocol/frame_router.h" -#include "matrix.h" -#include "sync_timer.h" -#include <stdbool.h> -#include "print.h" -#include "config.h" - -#define SYNC_TIMER_OFFSET 2 - -static event_source_t new_data_event; -static bool serial_link_connected; -static bool is_master = false; - -static uint8_t keyboard_leds(void); -static void send_keyboard(report_keyboard_t* report); -static void send_mouse(report_mouse_t* report); -static void send_system(uint16_t data); -static void send_consumer(uint16_t data); - -host_driver_t serial_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; - -// Define these in your Config.h file -#ifndef SERIAL_LINK_BAUD -# error "Serial link baud is not set" -#endif - -#ifndef SERIAL_LINK_THREAD_PRIORITY -# error "Serial link thread priority not set" -#endif - -static SerialConfig config = {.sc_speed = SERIAL_LINK_BAUD}; - -//#define DEBUG_LINK_ERRORS - -static uint32_t read_from_serial(SerialDriver* driver, uint8_t link) { - const uint32_t buffer_size = 16; - uint8_t buffer[buffer_size]; - uint32_t bytes_read = sdAsynchronousRead(driver, buffer, buffer_size); - uint8_t* current = buffer; - uint8_t* end = current + bytes_read; - while (current < end) { - byte_stuffer_recv_byte(link, *current); - current++; - } - return bytes_read; -} - -static void print_error(char* str, eventflags_t flags, SerialDriver* driver) { -#ifdef DEBUG_LINK_ERRORS - if (flags & SD_PARITY_ERROR) { - print(str); - print(" Parity error\n"); - } - if (flags & SD_FRAMING_ERROR) { - print(str); - print(" Framing error\n"); - } - if (flags & SD_OVERRUN_ERROR) { - print(str); - uint32_t size = qSpaceI(&(driver->iqueue)); - xprintf(" Overrun error, queue size %d\n", size); - } - if (flags & SD_NOISE_ERROR) { - print(str); - print(" Noise error\n"); - } - if (flags & SD_BREAK_DETECTED) { - print(str); - print(" Break detected\n"); - } -#else - (void)str; - (void)flags; - (void)driver; -#endif -} - -bool is_serial_link_master(void) { return is_master; } - -// TODO: Optimize the stack size, this is probably way too big -static THD_WORKING_AREA(serialThreadStack, 1024); -static THD_FUNCTION(serialThread, arg) { - (void)arg; - event_listener_t new_data_listener; - event_listener_t sd1_listener; - event_listener_t sd2_listener; - chEvtRegister(&new_data_event, &new_data_listener, 0); - eventflags_t events = CHN_INPUT_AVAILABLE | SD_PARITY_ERROR | SD_FRAMING_ERROR | SD_OVERRUN_ERROR | SD_NOISE_ERROR | SD_BREAK_DETECTED; - chEvtRegisterMaskWithFlags(chnGetEventSource(&SD1), &sd1_listener, EVENT_MASK(1), events); - chEvtRegisterMaskWithFlags(chnGetEventSource(&SD2), &sd2_listener, EVENT_MASK(2), events); - bool need_wait = false; - while (true) { - eventflags_t flags1 = 0; - eventflags_t flags2 = 0; - if (need_wait) { - eventmask_t mask = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(1000)); - if (mask & EVENT_MASK(1)) { - flags1 = chEvtGetAndClearFlags(&sd1_listener); - print_error("DOWNLINK", flags1, &SD1); - } - if (mask & EVENT_MASK(2)) { - flags2 = chEvtGetAndClearFlags(&sd2_listener); - print_error("UPLINK", flags2, &SD2); - } - } - - // Always stay as master, even if the USB goes into sleep mode - is_master |= usbGetDriverStateI(&USBD1) == USB_ACTIVE; - router_set_master(is_master); - - need_wait = true; - need_wait &= read_from_serial(&SD2, UP_LINK) == 0; - need_wait &= read_from_serial(&SD1, DOWN_LINK) == 0; - update_transport(); - } -} - -void send_data(uint8_t link, const uint8_t* data, uint16_t size) { - if (link == DOWN_LINK) { - sdWrite(&SD1, data, size); - } else { - sdWrite(&SD2, data, size); - } -} - -static systime_t last_update = 0; - -typedef struct { - matrix_row_t rows[MATRIX_ROWS]; -} matrix_object_t; - -static matrix_object_t last_matrix = {}; - -SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t); -MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool); -#ifndef DISABLE_SYNC_TIMER -MASTER_TO_ALL_SLAVES_OBJECT(sync_timer, uint32_t); -#endif - -static remote_object_t* remote_objects[] = { - REMOTE_OBJECT(serial_link_connected), - REMOTE_OBJECT(keyboard_matrix), -#ifndef DISABLE_SYNC_TIMER - REMOTE_OBJECT(sync_timer), -#endif -}; - -void init_serial_link(void) { - serial_link_connected = false; - init_serial_link_hal(); - add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*)); - init_byte_stuffer(); - sdStart(&SD1, &config); - sdStart(&SD2, &config); - chEvtObjectInit(&new_data_event); - (void)chThdCreateStatic(serialThreadStack, sizeof(serialThreadStack), SERIAL_LINK_THREAD_PRIORITY, serialThread, NULL); -} - -void matrix_set_remote(matrix_row_t* rows, uint8_t index); - -void serial_link_update(void) { - if (read_serial_link_connected()) { - serial_link_connected = true; - } - - matrix_object_t matrix; - bool changed = false; - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - matrix.rows[i] = matrix_get_row(i); - changed |= matrix.rows[i] != last_matrix.rows[i]; - } - - systime_t current_time = chVTGetSystemTimeX(); - systime_t delta = current_time - last_update; - if (changed || delta > TIME_US2I(5000)) { - last_update = current_time; - last_matrix = matrix; - matrix_object_t* m = begin_write_keyboard_matrix(); - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - m->rows[i] = matrix.rows[i]; - } - end_write_keyboard_matrix(); - - *begin_write_serial_link_connected() = true; - end_write_serial_link_connected(); - -#ifndef DISABLE_SYNC_TIMER - *begin_write_sync_timer() = sync_timer_read32() + SYNC_TIMER_OFFSET; - end_write_sync_timer(); -#endif - } - - matrix_object_t* m = read_keyboard_matrix(0); - if (m) { - matrix_set_remote(m->rows, 0); - } - -#ifndef DISABLE_SYNC_TIMER - uint32_t* t = read_sync_timer(); - if (t) { - sync_timer_update(*t); - } -#endif -} - -void signal_data_written(void) { chEvtBroadcast(&new_data_event); } - -bool is_serial_link_connected(void) { return serial_link_connected; } - -host_driver_t* get_serial_link_driver(void) { return &serial_driver; } - -// NOTE: The driver does nothing, because the master handles everything -uint8_t keyboard_leds(void) { return 0; } - -void send_keyboard(report_keyboard_t* report) { (void)report; } - -void send_mouse(report_mouse_t* report) { (void)report; } - -void send_system(uint16_t data) { (void)data; } - -void send_consumer(uint16_t data) { (void)data; } diff --git a/quantum/serial_link/system/serial_link.h b/quantum/serial_link/system/serial_link.h deleted file mode 100644 index adc1f6e93d..0000000000 --- a/quantum/serial_link/system/serial_link.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#pragma once - -#include "host_driver.h" -#include <stdbool.h> - -void init_serial_link(void); -void init_serial_link_hal(void); -bool is_serial_link_connected(void); -bool is_serial_link_master(void); -host_driver_t* get_serial_link_driver(void); -void serial_link_update(void); - -#if defined(PROTOCOL_CHIBIOS) -# include <ch.h> - -static inline void serial_link_lock(void) { chSysLock(); } - -static inline void serial_link_unlock(void) { chSysUnlock(); } - -void signal_data_written(void); - -#else - -inline void serial_link_lock(void) {} - -inline void serial_link_unlock(void) {} - -void signal_data_written(void); - -#endif diff --git a/quantum/serial_link/tests/Makefile b/quantum/serial_link/tests/Makefile deleted file mode 100644 index 11dd355b22..0000000000 --- a/quantum/serial_link/tests/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -# The MIT License (MIT) -# -# Copyright (c) 2016 Fred Sundvik -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# 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. - -CC = gcc -CFLAGS = -INCLUDES = -I. -I../../ -LDFLAGS = -L$(BUILDDIR)/cgreen/build-c/src -shared -LDLIBS = -lcgreen -UNITOBJ = $(BUILDDIR)/serialtest/unitobj -DEPDIR = $(BUILDDIR)/serialtest/unit.d -UNITTESTS = $(BUILDDIR)/serialtest/unittests -DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td -EXT = .so -UNAME := $(shell uname) -ifneq (, $(findstring MINGW, $(UNAME))) - EXT = .dll -endif -ifneq (, $(findstring CYGWIN, $(UNAME))) - EXT = .dll -endif - -SRC = $(wildcard *.c) -TESTFILES = $(patsubst %.c, $(UNITTESTS)/%$(EXT), $(SRC)) -$(shell mkdir -p $(DEPDIR) >/dev/null) - -test: $(TESTFILES) - @$(BUILDDIR)/cgreen/build-c/tools/cgreen-runner --color $(TESTFILES) - -$(UNITTESTS)/%$(EXT): $(UNITOBJ)/%.o - @mkdir -p $(UNITTESTS) - $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) - -$(UNITOBJ)/%.o : %.c -$(UNITOBJ)/%.o: %.c $(DEPDIR)/%.d - @mkdir -p $(UNITOBJ) - $(CC) $(CFLAGS) $(DEPFLAGS) $(INCLUDES) -c $< -o $@ - @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d - -$(DEPDIR)/%.d: ; -.PRECIOUS: $(DEPDIR)/%.d - --include $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRC))) diff --git a/quantum/serial_link/tests/byte_stuffer_tests.cpp b/quantum/serial_link/tests/byte_stuffer_tests.cpp deleted file mode 100644 index 9e4e1768f4..0000000000 --- a/quantum/serial_link/tests/byte_stuffer_tests.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include <vector> -#include <algorithm> -extern "C" { -#include "serial_link/protocol/byte_stuffer.h" -#include "serial_link/protocol/frame_validator.h" -#include "serial_link/protocol/physical.h" -} - -using testing::_; -using testing::Args; -using testing::ElementsAreArray; - -class ByteStuffer : public ::testing::Test { - public: - ByteStuffer() { - Instance = this; - init_byte_stuffer(); - } - - ~ByteStuffer() { Instance = nullptr; } - - MOCK_METHOD3(validator_recv_frame, void(uint8_t link, uint8_t* data, uint16_t size)); - - void send_data(uint8_t link, const uint8_t* data, uint16_t size) { std::copy(data, data + size, std::back_inserter(sent_data)); } - std::vector<uint8_t> sent_data; - - static ByteStuffer* Instance; -}; - -ByteStuffer* ByteStuffer::Instance = nullptr; - -extern "C" { -void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) { ByteStuffer::Instance->validator_recv_frame(link, data, size); } - -void send_data(uint8_t link, const uint8_t* data, uint16_t size) { ByteStuffer::Instance->send_data(link, data, size); } -} - -TEST_F(ByteStuffer, receives_no_frame_for_a_single_zero_byte) { - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_no_frame_for_a_single_FF_byte) { - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0); - byte_stuffer_recv_byte(0, 0xFF); -} - -TEST_F(ByteStuffer, receives_no_frame_for_a_single_random_byte) { - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0); - byte_stuffer_recv_byte(0, 0x4A); -} - -TEST_F(ByteStuffer, receives_no_frame_for_a_zero_length_frame) { - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_single_byte_valid_frame) { - uint8_t expected[] = {0x37}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 0x37); - byte_stuffer_recv_byte(0, 0); -} -TEST_F(ByteStuffer, receives_three_bytes_valid_frame) { - uint8_t expected[] = {0x37, 0x99, 0xFF}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 4); - byte_stuffer_recv_byte(0, 0x37); - byte_stuffer_recv_byte(0, 0x99); - byte_stuffer_recv_byte(0, 0xFF); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_single_zero_valid_frame) { - uint8_t expected[] = {0}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_valid_frame_with_zeroes) { - uint8_t expected[] = {5, 0, 3, 0}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 5); - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 3); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_two_valid_frames) { - uint8_t expected1[] = {5, 0}; - uint8_t expected2[] = {3}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected1))); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected2))); - byte_stuffer_recv_byte(1, 2); - byte_stuffer_recv_byte(1, 5); - byte_stuffer_recv_byte(1, 1); - byte_stuffer_recv_byte(1, 0); - byte_stuffer_recv_byte(1, 2); - byte_stuffer_recv_byte(1, 3); - byte_stuffer_recv_byte(1, 0); -} - -TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_zero) { - uint8_t expected[] = {5, 7}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(1, 3); - byte_stuffer_recv_byte(1, 1); - byte_stuffer_recv_byte(1, 0); - byte_stuffer_recv_byte(1, 3); - byte_stuffer_recv_byte(1, 5); - byte_stuffer_recv_byte(1, 7); - byte_stuffer_recv_byte(1, 0); -} - -TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) { - uint8_t expected[] = {5, 7}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 9); - byte_stuffer_recv_byte(0, 4); // This should have been zero - byte_stuffer_recv_byte(0, 0); - byte_stuffer_recv_byte(0, 3); - byte_stuffer_recv_byte(0, 5); - byte_stuffer_recv_byte(0, 7); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_of_frame) { - uint8_t expected[254]; - int i; - for (i = 0; i < 254; i++) { - expected[i] = i + 1; - } - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 0xFF); - for (i = 0; i < 254; i++) { - byte_stuffer_recv_byte(0, i + 1); - } - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_non_zero) { - uint8_t expected[255]; - int i; - for (i = 0; i < 254; i++) { - expected[i] = i + 1; - } - expected[254] = 7; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 0xFF); - for (i = 0; i < 254; i++) { - byte_stuffer_recv_byte(0, i + 1); - } - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 7); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_zero) { - uint8_t expected[255]; - int i; - for (i = 0; i < 254; i++) { - expected[i] = i + 1; - } - expected[254] = 0; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 0xFF); - for (i = 0; i < 254; i++) { - byte_stuffer_recv_byte(0, i + 1); - } - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_two_long_frames_and_some_more) { - uint8_t expected[515]; - int i; - int j; - for (j = 0; j < 2; j++) { - for (i = 0; i < 254; i++) { - expected[i + 254 * j] = i + 1; - } - } - for (i = 0; i < 7; i++) { - expected[254 * 2 + i] = i + 1; - } - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - byte_stuffer_recv_byte(0, 0xFF); - for (i = 0; i < 254; i++) { - byte_stuffer_recv_byte(0, i + 1); - } - byte_stuffer_recv_byte(0, 0xFF); - for (i = 0; i < 254; i++) { - byte_stuffer_recv_byte(0, i + 1); - } - byte_stuffer_recv_byte(0, 8); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 3); - byte_stuffer_recv_byte(0, 4); - byte_stuffer_recv_byte(0, 5); - byte_stuffer_recv_byte(0, 6); - byte_stuffer_recv_byte(0, 7); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) { - uint8_t expected[MAX_FRAME_SIZE] = {}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - int i; - byte_stuffer_recv_byte(0, 1); - for (i = 0; i < MAX_FRAME_SIZE; i++) { - byte_stuffer_recv_byte(0, 1); - } - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) { - uint8_t expected[1] = {0}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0); - int i; - byte_stuffer_recv_byte(0, 1); - for (i = 0; i < MAX_FRAME_SIZE; i++) { - byte_stuffer_recv_byte(0, 1); - } - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, received_frame_is_aborted_when_its_too_long) { - uint8_t expected[1] = {1}; - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - int i; - byte_stuffer_recv_byte(0, 1); - for (i = 0; i < MAX_FRAME_SIZE; i++) { - byte_stuffer_recv_byte(0, 1); - } - byte_stuffer_recv_byte(0, 2); - byte_stuffer_recv_byte(0, 1); - byte_stuffer_recv_byte(0, 0); -} - -TEST_F(ByteStuffer, does_nothing_when_sending_zero_size_frame) { - EXPECT_EQ(sent_data.size(), 0); - byte_stuffer_send_frame(0, NULL, 0); -} - -TEST_F(ByteStuffer, send_one_byte_frame) { - uint8_t data[] = {5}; - byte_stuffer_send_frame(1, data, 1); - uint8_t expected[] = {2, 5, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_two_byte_frame) { - uint8_t data[] = {5, 0x77}; - byte_stuffer_send_frame(0, data, 2); - uint8_t expected[] = {3, 5, 0x77, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_one_byte_frame_with_zero) { - uint8_t data[] = {0}; - byte_stuffer_send_frame(0, data, 1); - uint8_t expected[] = {1, 1, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_zero) { - uint8_t data[] = {0, 9}; - byte_stuffer_send_frame(1, data, 2); - uint8_t expected[] = {1, 2, 9, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_non_zero) { - uint8_t data[] = {9, 0}; - byte_stuffer_send_frame(1, data, 2); - uint8_t expected[] = {2, 9, 1, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_three_byte_frame_zero_in_the_middle) { - uint8_t data[] = {9, 0, 0x68}; - byte_stuffer_send_frame(0, data, 3); - uint8_t expected[] = {2, 9, 2, 0x68, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_three_byte_frame_data_in_the_middle) { - uint8_t data[] = {0, 0x55, 0}; - byte_stuffer_send_frame(0, data, 3); - uint8_t expected[] = {1, 2, 0x55, 1, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_three_byte_frame_with_all_zeroes) { - uint8_t data[] = {0, 0, 0}; - byte_stuffer_send_frame(0, data, 3); - uint8_t expected[] = {1, 1, 1, 1, 0}; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes) { - uint8_t data[254]; - int i; - for (i = 0; i < 254; i++) { - data[i] = i + 1; - } - byte_stuffer_send_frame(0, data, 254); - uint8_t expected[256]; - expected[0] = 0xFF; - for (i = 1; i < 255; i++) { - expected[i] = i; - } - expected[255] = 0; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_frame_with_255_non_zeroes) { - uint8_t data[255]; - int i; - for (i = 0; i < 255; i++) { - data[i] = i + 1; - } - byte_stuffer_send_frame(0, data, 255); - uint8_t expected[258]; - expected[0] = 0xFF; - for (i = 1; i < 255; i++) { - expected[i] = i; - } - expected[255] = 2; - expected[256] = 255; - expected[257] = 0; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) { - uint8_t data[255]; - int i; - for (i = 0; i < 254; i++) { - data[i] = i + 1; - } - data[254] = 0; - byte_stuffer_send_frame(0, data, 255); - uint8_t expected[258]; - expected[0] = 0xFF; - for (i = 1; i < 255; i++) { - expected[i] = i; - } - expected[255] = 1; - expected[256] = 1; - expected[257] = 0; - EXPECT_THAT(sent_data, ElementsAreArray(expected)); -} - -TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet) { - uint8_t original_data[] = {1, 2, 3}; - byte_stuffer_send_frame(0, original_data, sizeof(original_data)); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data))); - int i; - for (auto& d : sent_data) { - byte_stuffer_recv_byte(1, d); - } -} - -TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet_with_zeros) { - uint8_t original_data[] = {1, 0, 3, 0, 0, 9}; - byte_stuffer_send_frame(1, original_data, sizeof(original_data)); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data))); - int i; - for (auto& d : sent_data) { - byte_stuffer_recv_byte(1, d); - } -} - -TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes) { - uint8_t original_data[254]; - int i; - for (i = 0; i < 254; i++) { - original_data[i] = i + 1; - } - byte_stuffer_send_frame(0, original_data, sizeof(original_data)); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data))); - for (auto& d : sent_data) { - byte_stuffer_recv_byte(1, d); - } -} - -TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) { - uint8_t original_data[256]; - int i; - for (i = 0; i < 254; i++) { - original_data[i] = i + 1; - } - original_data[254] = 22; - original_data[255] = 23; - byte_stuffer_send_frame(0, original_data, sizeof(original_data)); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data))); - for (auto& d : sent_data) { - byte_stuffer_recv_byte(1, d); - } -} - -TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) { - uint8_t original_data[255]; - int i; - for (i = 0; i < 254; i++) { - original_data[i] = i + 1; - } - original_data[254] = 0; - byte_stuffer_send_frame(0, original_data, sizeof(original_data)); - EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data))); - for (auto& d : sent_data) { - byte_stuffer_recv_byte(1, d); - } -} diff --git a/quantum/serial_link/tests/frame_router_tests.cpp b/quantum/serial_link/tests/frame_router_tests.cpp deleted file mode 100644 index f76dfb33d6..0000000000 --- a/quantum/serial_link/tests/frame_router_tests.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include <array> -extern "C" { -#include "serial_link/protocol/transport.h" -#include "serial_link/protocol/byte_stuffer.h" -#include "serial_link/protocol/frame_router.h" -} - -using testing::_; -using testing::Args; -using testing::ElementsAreArray; - -class FrameRouter : public testing::Test { - public: - FrameRouter() : current_router_buffer(nullptr) { - Instance = this; - init_byte_stuffer(); - } - - ~FrameRouter() { Instance = nullptr; } - - void send_data(uint8_t link, const uint8_t* data, uint16_t size) { - auto& buffer = current_router_buffer->send_buffers[link]; - std::copy(data, data + size, std::back_inserter(buffer)); - } - - void receive_data(uint8_t link, uint8_t* data, uint16_t size) { - int i; - for (i = 0; i < size; i++) { - byte_stuffer_recv_byte(link, data[i]); - } - } - - void activate_router(uint8_t num) { - current_router_buffer = router_buffers + num; - router_set_master(num == 0); - } - - void simulate_transport(uint8_t from, uint8_t to) { - activate_router(to); - if (from > to) { - receive_data(DOWN_LINK, router_buffers[from].send_buffers[UP_LINK].data(), router_buffers[from].send_buffers[UP_LINK].size()); - } else if (to > from) { - receive_data(UP_LINK, router_buffers[from].send_buffers[DOWN_LINK].data(), router_buffers[from].send_buffers[DOWN_LINK].size()); - } - } - - MOCK_METHOD3(transport_recv_frame, void(uint8_t from, uint8_t* data, uint16_t size)); - - std::vector<uint8_t> received_data; - - struct router_buffer { - std::vector<uint8_t> send_buffers[2]; - }; - - router_buffer router_buffers[8]; - router_buffer* current_router_buffer; - - static FrameRouter* Instance; -}; - -FrameRouter* FrameRouter::Instance = nullptr; - -typedef struct { - std::array<uint8_t, 4> data; - uint8_t extra[16]; -} frame_buffer_t; - -extern "C" { -void send_data(uint8_t link, const uint8_t* data, uint16_t size) { FrameRouter::Instance->send_data(link, data, size); } - -void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) { FrameRouter::Instance->transport_recv_frame(from, data, size); } -} - -TEST_F(FrameRouter, master_broadcast_is_received_by_everyone) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(0); - router_send_frame(0xFF, (uint8_t*)&data, 4); - EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); - EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(0, 1); - EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(1, 2); - EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0); -} - -TEST_F(FrameRouter, master_send_is_received_by_targets) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(0); - router_send_frame((1 << 1) | (1 << 2), (uint8_t*)&data, 4); - EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); - - simulate_transport(0, 1); - EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(1, 2); - EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(2, 3); - EXPECT_GT(router_buffers[3].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[3].send_buffers[UP_LINK].size(), 0); -} - -TEST_F(FrameRouter, first_link_sends_to_master) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(1); - router_send_frame(0, (uint8_t*)&data, 4); - EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(1, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(1, 0); - EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); -} - -TEST_F(FrameRouter, second_link_sends_to_master) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(2); - router_send_frame(0, (uint8_t*)&data, 4); - EXPECT_GT(router_buffers[2].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[2].send_buffers[DOWN_LINK].size(), 0); - - simulate_transport(2, 1); - EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(2, _, _)).With(Args<1, 2>(ElementsAreArray(data.data))); - simulate_transport(1, 0); - EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); -} - -TEST_F(FrameRouter, master_sends_to_master_does_nothing) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(0); - router_send_frame(0, (uint8_t*)&data, 4); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); -} - -TEST_F(FrameRouter, link_sends_to_other_link_does_nothing) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(1); - router_send_frame(2, (uint8_t*)&data, 4); - EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); -} - -TEST_F(FrameRouter, master_receives_on_uplink_does_nothing) { - frame_buffer_t data; - data.data = {0xAB, 0x70, 0x55, 0xBB}; - activate_router(1); - router_send_frame(0, (uint8_t*)&data, 4); - EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0); - - EXPECT_CALL(*this, transport_recv_frame(_, _, _)).Times(0); - activate_router(0); - receive_data(UP_LINK, router_buffers[1].send_buffers[UP_LINK].data(), router_buffers[1].send_buffers[UP_LINK].size()); - EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0); - EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0); -} diff --git a/quantum/serial_link/tests/frame_validator_tests.cpp b/quantum/serial_link/tests/frame_validator_tests.cpp deleted file mode 100644 index 43dc57b633..0000000000 --- a/quantum/serial_link/tests/frame_validator_tests.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "gtest/gtest.h" -#include "gmock/gmock.h" -extern "C" { -#include "serial_link/protocol/frame_validator.h" -} - -using testing::_; -using testing::Args; -using testing::ElementsAreArray; - -class FrameValidator : public testing::Test { - public: - FrameValidator() { Instance = this; } - - ~FrameValidator() { Instance = nullptr; } - - MOCK_METHOD3(route_incoming_frame, void(uint8_t link, uint8_t* data, uint16_t size)); - MOCK_METHOD3(byte_stuffer_send_frame, void(uint8_t link, uint8_t* data, uint16_t size)); - - static FrameValidator* Instance; -}; - -FrameValidator* FrameValidator::Instance = nullptr; - -extern "C" { -void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) { FrameValidator::Instance->route_incoming_frame(link, data, size); } - -void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) { FrameValidator::Instance->byte_stuffer_send_frame(link, data, size); } -} - -TEST_F(FrameValidator, doesnt_validate_frames_under_5_bytes) { - EXPECT_CALL(*this, route_incoming_frame(_, _, _)).Times(0); - uint8_t data[] = {1, 2}; - validator_recv_frame(0, 0, 1); - validator_recv_frame(0, data, 2); - validator_recv_frame(0, data, 3); - validator_recv_frame(0, data, 4); -} - -TEST_F(FrameValidator, validates_one_byte_frame_with_correct_crc) { - uint8_t data[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3}; - EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 1))); - validator_recv_frame(0, data, 5); -} - -TEST_F(FrameValidator, does_not_validate_one_byte_frame_with_incorrect_crc) { - uint8_t data[] = {0x44, 0, 0, 0, 0}; - EXPECT_CALL(*this, route_incoming_frame(_, _, _)).Times(0); - validator_recv_frame(1, data, 5); -} - -TEST_F(FrameValidator, validates_four_byte_frame_with_correct_crc) { - uint8_t data[] = {0x44, 0x10, 0xFF, 0x00, 0x74, 0x4E, 0x30, 0xBA}; - EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 4))); - validator_recv_frame(1, data, 8); -} - -TEST_F(FrameValidator, validates_five_byte_frame_with_correct_crc) { - uint8_t data[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47}; - EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 5))); - validator_recv_frame(0, data, 9); -} - -TEST_F(FrameValidator, sends_one_byte_with_correct_crc) { - uint8_t original[] = {0x44, 0, 0, 0, 0}; - uint8_t expected[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3}; - EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - validator_send_frame(0, original, 1); -} - -TEST_F(FrameValidator, sends_five_bytes_with_correct_crc) { - uint8_t original[] = {1, 2, 3, 4, 5, 0, 0, 0, 0}; - uint8_t expected[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47}; - EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected))); - validator_send_frame(0, original, 5); -} diff --git a/quantum/serial_link/tests/rules.mk b/quantum/serial_link/tests/rules.mk deleted file mode 100644 index b81515bc55..0000000000 --- a/quantum/serial_link/tests/rules.mk +++ /dev/null @@ -1,22 +0,0 @@ -serial_link_byte_stuffer_SRC :=\ - $(SERIAL_PATH)/tests/byte_stuffer_tests.cpp \ - $(SERIAL_PATH)/protocol/byte_stuffer.c - -serial_link_frame_validator_SRC := \ - $(SERIAL_PATH)/tests/frame_validator_tests.cpp \ - $(SERIAL_PATH)/protocol/frame_validator.c - -serial_link_frame_router_SRC := \ - $(SERIAL_PATH)/tests/frame_router_tests.cpp \ - $(SERIAL_PATH)/protocol/byte_stuffer.c \ - $(SERIAL_PATH)/protocol/frame_validator.c \ - $(SERIAL_PATH)/protocol/frame_router.c - -serial_link_triple_buffered_object_SRC := \ - $(SERIAL_PATH)/tests/triple_buffered_object_tests.cpp \ - $(SERIAL_PATH)/protocol/triple_buffered_object.c - -serial_link_transport_SRC := \ - $(SERIAL_PATH)/tests/transport_tests.cpp \ - $(SERIAL_PATH)/protocol/transport.c \ - $(SERIAL_PATH)/protocol/triple_buffered_object.c diff --git a/quantum/serial_link/tests/testlist.mk b/quantum/serial_link/tests/testlist.mk deleted file mode 100644 index c5edaf478f..0000000000 --- a/quantum/serial_link/tests/testlist.mk +++ /dev/null @@ -1,6 +0,0 @@ -TEST_LIST +=\ - serial_link_byte_stuffer\ - serial_link_frame_validator\ - serial_link_frame_router\ - serial_link_triple_buffered_object\ - serial_link_transport diff --git a/quantum/serial_link/tests/transport_tests.cpp b/quantum/serial_link/tests/transport_tests.cpp deleted file mode 100644 index cfd1110460..0000000000 --- a/quantum/serial_link/tests/transport_tests.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "gtest/gtest.h" -#include "gmock/gmock.h" - -using testing::_; -using testing::Args; -using testing::ElementsAreArray; - -extern "C" { -#include "serial_link/protocol/transport.h" -} - -struct test_object1 { - uint32_t test; -}; - -struct test_object2 { - uint32_t test1; - uint32_t test2; -}; - -MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1); -MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1); -SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1); - -static remote_object_t* test_remote_objects[] = { - REMOTE_OBJECT(master_to_slave), - REMOTE_OBJECT(master_to_single_slave), - REMOTE_OBJECT(slave_to_master), -}; - -class Transport : public testing::Test { - public: - Transport() { - Instance = this; - add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*)); - } - - ~Transport() { - Instance = nullptr; - reinitialize_serial_link_transport(); - } - - MOCK_METHOD0(signal_data_written, void()); - MOCK_METHOD1(router_send_frame, void(uint8_t destination)); - - void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) { - router_send_frame(destination); - std::copy(data, data + size, std::back_inserter(sent_data)); - } - - static Transport* Instance; - - std::vector<uint8_t> sent_data; -}; - -Transport* Transport::Instance = nullptr; - -extern "C" { -void signal_data_written(void) { Transport::Instance->signal_data_written(); } - -void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) { Transport::Instance->router_send_frame(destination, data, size); } -} - -TEST_F(Transport, write_to_local_signals_an_event) { - begin_write_master_to_slave(); - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_slave(); - begin_write_slave_to_master(); - EXPECT_CALL(*this, signal_data_written()); - end_write_slave_to_master(); - begin_write_master_to_single_slave(1); - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_single_slave(1); -} - -TEST_F(Transport, writes_from_master_to_all_slaves) { - update_transport(); - test_object1* obj = begin_write_master_to_slave(); - obj->test = 5; - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_slave(); - EXPECT_CALL(*this, router_send_frame(0xFF)); - update_transport(); - transport_recv_frame(0, sent_data.data(), sent_data.size()); - test_object1* obj2 = read_master_to_slave(); - EXPECT_NE(obj2, nullptr); - EXPECT_EQ(obj2->test, 5); -} - -TEST_F(Transport, writes_from_slave_to_master) { - update_transport(); - test_object1* obj = begin_write_slave_to_master(); - obj->test = 7; - EXPECT_CALL(*this, signal_data_written()); - end_write_slave_to_master(); - EXPECT_CALL(*this, router_send_frame(0)); - update_transport(); - transport_recv_frame(3, sent_data.data(), sent_data.size()); - test_object1* obj2 = read_slave_to_master(2); - EXPECT_EQ(read_slave_to_master(0), nullptr); - EXPECT_NE(obj2, nullptr); - EXPECT_EQ(obj2->test, 7); -} - -TEST_F(Transport, writes_from_master_to_single_slave) { - update_transport(); - test_object1* obj = begin_write_master_to_single_slave(3); - obj->test = 7; - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_single_slave(3); - EXPECT_CALL(*this, router_send_frame(4)); - update_transport(); - transport_recv_frame(0, sent_data.data(), sent_data.size()); - test_object1* obj2 = read_master_to_single_slave(); - EXPECT_NE(obj2, nullptr); - EXPECT_EQ(obj2->test, 7); -} - -TEST_F(Transport, ignores_object_with_invalid_id) { - update_transport(); - test_object1* obj = begin_write_master_to_single_slave(3); - obj->test = 7; - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_single_slave(3); - EXPECT_CALL(*this, router_send_frame(4)); - update_transport(); - sent_data[sent_data.size() - 1] = 44; - transport_recv_frame(0, sent_data.data(), sent_data.size()); - test_object1* obj2 = read_master_to_single_slave(); - EXPECT_EQ(obj2, nullptr); -} - -TEST_F(Transport, ignores_object_with_size_too_small) { - update_transport(); - test_object1* obj = begin_write_master_to_slave(); - obj->test = 7; - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_slave(); - EXPECT_CALL(*this, router_send_frame(_)); - update_transport(); - sent_data[sent_data.size() - 2] = 0; - transport_recv_frame(0, sent_data.data(), sent_data.size() - 1); - test_object1* obj2 = read_master_to_slave(); - EXPECT_EQ(obj2, nullptr); -} - -TEST_F(Transport, ignores_object_with_size_too_big) { - update_transport(); - test_object1* obj = begin_write_master_to_slave(); - obj->test = 7; - EXPECT_CALL(*this, signal_data_written()); - end_write_master_to_slave(); - EXPECT_CALL(*this, router_send_frame(_)); - update_transport(); - sent_data.resize(sent_data.size() + 22); - sent_data[sent_data.size() - 1] = 0; - transport_recv_frame(0, sent_data.data(), sent_data.size()); - test_object1* obj2 = read_master_to_slave(); - EXPECT_EQ(obj2, nullptr); -} diff --git a/quantum/serial_link/tests/triple_buffered_object_tests.cpp b/quantum/serial_link/tests/triple_buffered_object_tests.cpp deleted file mode 100644 index 8de9bfdebf..0000000000 --- a/quantum/serial_link/tests/triple_buffered_object_tests.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "gtest/gtest.h" -extern "C" { -#include "serial_link/protocol/triple_buffered_object.h" -} - -struct test_object { - uint8_t state; - uint32_t buffer[3]; -}; - -test_object test_object; - -class TripleBufferedObject : public testing::Test { - public: - TripleBufferedObject() { triple_buffer_init((triple_buffer_object_t*)&test_object); } -}; - -TEST_F(TripleBufferedObject, writes_and_reads_object) { - *triple_buffer_begin_write(&test_object) = 0x3456ABCC; - triple_buffer_end_write(&test_object); - EXPECT_EQ(*triple_buffer_read(&test_object), 0x3456ABCC); -} - -TEST_F(TripleBufferedObject, does_not_read_empty) { EXPECT_EQ(triple_buffer_read(&test_object), nullptr); } - -TEST_F(TripleBufferedObject, writes_twice_and_reads_object) { - *triple_buffer_begin_write(&test_object) = 0x3456ABCC; - triple_buffer_end_write(&test_object); - *triple_buffer_begin_write(&test_object) = 0x44778899; - triple_buffer_end_write(&test_object); - EXPECT_EQ(*triple_buffer_read(&test_object), 0x44778899); -} - -TEST_F(TripleBufferedObject, performs_another_write_in_the_middle_of_read) { - *triple_buffer_begin_write(&test_object) = 1; - triple_buffer_end_write(&test_object); - uint32_t* read = triple_buffer_read(&test_object); - *triple_buffer_begin_write(&test_object) = 2; - triple_buffer_end_write(&test_object); - EXPECT_EQ(*read, 1); - EXPECT_EQ(*triple_buffer_read(&test_object), 2); - EXPECT_EQ(triple_buffer_read(&test_object), nullptr); -} - -TEST_F(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) { - *triple_buffer_begin_write(&test_object) = 1; - triple_buffer_end_write(&test_object); - uint32_t* read = triple_buffer_read(&test_object); - *triple_buffer_begin_write(&test_object) = 2; - triple_buffer_end_write(&test_object); - *triple_buffer_begin_write(&test_object) = 3; - triple_buffer_end_write(&test_object); - EXPECT_EQ(*read, 1); - EXPECT_EQ(*triple_buffer_read(&test_object), 3); - EXPECT_EQ(triple_buffer_read(&test_object), nullptr); -} diff --git a/quantum/usb_device_state.c b/quantum/usb_device_state.c new file mode 100644 index 0000000000..5ccd309ec2 --- /dev/null +++ b/quantum/usb_device_state.c @@ -0,0 +1,51 @@ +/* + * Copyright 2021 Andrei Purdea <andrei@purdea.ro> + * + * 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 "usb_device_state.h" + +enum usb_device_state usb_device_state = USB_DEVICE_STATE_NO_INIT; + +__attribute__((weak)) void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state) { notify_usb_device_state_change_user(usb_device_state); } + +__attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {} + +static void notify_usb_device_state_change(enum usb_device_state usb_device_state) { notify_usb_device_state_change_kb(usb_device_state); } + +void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) { + usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; + notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber) { + usb_device_state = USB_DEVICE_STATE_SUSPEND; + notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber) { + usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; + notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_set_reset(void) { + usb_device_state = USB_DEVICE_STATE_INIT; + notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_init(void) { + usb_device_state = USB_DEVICE_STATE_INIT; + notify_usb_device_state_change(usb_device_state); +} diff --git a/quantum/usb_device_state.h b/quantum/usb_device_state.h new file mode 100644 index 0000000000..c229311d46 --- /dev/null +++ b/quantum/usb_device_state.h @@ -0,0 +1,39 @@ +/* + * Copyright 2021 Andrei Purdea <andrei@purdea.ro> + * + * 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 + +#include <stdbool.h> +#include <stdint.h> + +void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber); +void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber); +void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber); +void usb_device_state_set_reset(void); +void usb_device_state_init(void); + +enum usb_device_state { + USB_DEVICE_STATE_NO_INIT = 0, // We're in this state before calling usb_device_state_init() + USB_DEVICE_STATE_INIT = 1, // Can consume up to 100mA + USB_DEVICE_STATE_CONFIGURED = 2, // Can consume up to what is specified in configuration descriptor, typically 500mA + USB_DEVICE_STATE_SUSPEND = 3 // Can consume only suspend current +}; + +extern enum usb_device_state usb_device_state; + +void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state); +void notify_usb_device_state_change_user(enum usb_device_state usb_device_state); diff --git a/quantum/visualizer/LICENSE.md b/quantum/visualizer/LICENSE.md deleted file mode 100644 index 22d4c3f08b..0000000000 --- a/quantum/visualizer/LICENSE.md +++ /dev/null @@ -1,29 +0,0 @@ -The files in this project are licensed under the MIT license -It uses the following libraries -uGFX - with it's own license, see the license.html file in the uGFX subfolder for more information -tmk_core - is indirectly used and not included in the repository. It's licensed under the GPLv2 license -Chibios - which is used by tmk_core is licensed under GPLv3. - -Therefore the effective license for any project using the library is GPLv3 - -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. diff --git a/quantum/visualizer/common_gfxconf.h b/quantum/visualizer/common_gfxconf.h deleted file mode 100644 index e0735b37d0..0000000000 --- a/quantum/visualizer/common_gfxconf.h +++ /dev/null @@ -1,354 +0,0 @@ -/** - * This file has a different license to the rest of the uGFX system. - * You can copy, modify and distribute this file as you see fit. - * You do not need to publish your source modifications to this file. - * The only thing you are not permitted to do is to relicense it - * under a different license. - */ - -/** - * Copy this file into your project directory and rename it as gfxconf.h - * Edit your copy to turn on the uGFX features you want to use. - * The values below are the defaults. - * - * Only remove the comments from lines where you want to change the - * default value. This allows definitions to be included from - * driver makefiles when required and provides the best future - * compatibility for your project. - * - * Please use spaces instead of tabs in this file. - */ - -#pragma once - -/////////////////////////////////////////////////////////////////////////// -// GFX - Compatibility options // -/////////////////////////////////////////////////////////////////////////// -//#define GFX_COMPAT_V2 GFXON -//#define GFX_COMPAT_OLDCOLORS GFXON - -/////////////////////////////////////////////////////////////////////////// -// GOS - One of these must be defined, preferably in your Makefile // -/////////////////////////////////////////////////////////////////////////// -//#define GFX_USE_OS_CHIBIOS GFXOFF -//#define GFX_USE_OS_FREERTOS GFXOFF -// #define GFX_FREERTOS_USE_TRACE GFXOFF -//#define GFX_USE_OS_WIN32 GFXOFF -//#define GFX_USE_OS_LINUX GFXOFF -//#define GFX_USE_OS_OSX GFXOFF -//#define GFX_USE_OS_ECOS GFXOFF -//#define GFX_USE_OS_RAWRTOS GFXOFF -//#define GFX_USE_OS_ARDUINO GFXOFF -//#define GFX_USE_OS_KEIL GFXOFF -//#define GFX_USE_OS_RTX5 GFXOFF -//#define GFX_USE_OS_CMSIS GFXOFF -//#define GFX_USE_OS_CMSIS2 GFXOFF -//#define GFX_USE_OS_RAW32 GFXOFF -//#define GFX_USE_OS_ZEPHYR GFXOFF -//#define GFX_USE_OS_NIOS GFXOFF -//#define GFX_USE_OS_QT GFXOFF -// #define INTERRUPTS_OFF() optional_code -// #define INTERRUPTS_ON() optional_code - -// Options that (should where relevant) apply to all operating systems -#define GFX_NO_INLINE GFXON -// #define GFX_COMPILER GFX_COMPILER_UNKNOWN -// #define GFX_SHOW_COMPILER GFXOFF -// #define GFX_CPU GFX_CPU_UNKNOWN -// #define GFX_CPU_NO_ALIGNMENT_FAULTS GFXOFF -// #define GFX_CPU_ENDIAN GFX_CPU_ENDIAN_UNKNOWN -// #define GFX_OS_HEAP_SIZE 0 -// #define GFX_OS_NO_INIT GFXOFF -// #define GFX_OS_INIT_NO_WARNING GFXOFF -// #define GFX_OS_PRE_INIT_FUNCTION myHardwareInitRoutine -// #define GFX_OS_EXTRA_INIT_FUNCTION myOSInitRoutine -// #define GFX_OS_EXTRA_DEINIT_FUNCTION myOSDeInitRoutine -// #define GFX_OS_CALL_UGFXMAIN GFXOFF -// #define GFX_OS_UGFXMAIN_STACKSIZE 0 -// #define GFX_EMULATE_MALLOC GFXOFF -// #define GFX_MEM_LT64K GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GDISP // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GDISP GFXON - -//#define GDISP_NEED_AUTOFLUSH GFXOFF -//#define GDISP_NEED_TIMERFLUSH GFXOFF -//#define GDISP_NEED_VALIDATION GFXON -//#define GDISP_NEED_CLIP GFXON -#define GDISP_NEED_CIRCLE GFXON -//#define GDISP_NEED_DUALCIRCLE GFXOFF -#define GDISP_NEED_ELLIPSE GFXON -#define GDISP_NEED_ARC GFXON -#define GDISP_NEED_ARCSECTORS GFXON -#define GDISP_NEED_CONVEX_POLYGON GFXON -//#define GDISP_NEED_SCROLL GFXOFF -#define GDISP_NEED_PIXELREAD GFXON -#define GDISP_NEED_CONTROL GFXON -//#define GDISP_NEED_QUERY GFXOFF -//#define GDISP_NEED_MULTITHREAD GFXOFF -//#define GDISP_NEED_STREAMING GFXOFF -#define GDISP_NEED_TEXT GFXON -// #define GDISP_NEED_TEXT_WORDWRAP GFXOFF -// #define GDISP_NEED_TEXT_BOXPADLR 1 -// #define GDISP_NEED_TEXT_BOXPADTB 1 -// #define GDISP_NEED_ANTIALIAS GFXOFF -// #define GDISP_NEED_UTF8 GFXOFF -#define GDISP_NEED_TEXT_KERNING GFXON -// #define GDISP_INCLUDE_FONT_UI1 GFXOFF -// #define GDISP_INCLUDE_FONT_UI2 GFXOFF // The smallest preferred font. -// #define GDISP_INCLUDE_FONT_LARGENUMBERS GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS10 GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS12 GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS16 GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS20 GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS24 GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS32 GFXOFF -#define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12 GFXON -// #define GDISP_INCLUDE_FONT_FIXED_10X20 GFXOFF -// #define GDISP_INCLUDE_FONT_FIXED_7X14 GFXOFF -#define GDISP_INCLUDE_FONT_FIXED_5X8 GFXON -// #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS20_AA GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA GFXOFF -// #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA GFXOFF -// #define GDISP_INCLUDE_USER_FONTS GFXOFF - -//#define GDISP_NEED_IMAGE GFXOFF -// #define GDISP_NEED_IMAGE_NATIVE GFXOFF -// #define GDISP_NEED_IMAGE_GIF GFXOFF -// #define GDISP_IMAGE_GIF_BLIT_BUFFER_SIZE 32 -// #define GDISP_NEED_IMAGE_BMP GFXOFF -// #define GDISP_NEED_IMAGE_BMP_1 GFXON -// #define GDISP_NEED_IMAGE_BMP_4 GFXON -// #define GDISP_NEED_IMAGE_BMP_4_RLE GFXON -// #define GDISP_NEED_IMAGE_BMP_8 GFXON -// #define GDISP_NEED_IMAGE_BMP_8_RLE GFXON -// #define GDISP_NEED_IMAGE_BMP_16 GFXON -// #define GDISP_NEED_IMAGE_BMP_24 GFXON -// #define GDISP_NEED_IMAGE_BMP_32 GFXON -// #define GDISP_IMAGE_BMP_BLIT_BUFFER_SIZE 32 -// #define GDISP_NEED_IMAGE_JPG GFXOFF -// #define GDISP_NEED_IMAGE_PNG GFXOFF -// #define GDISP_NEED_IMAGE_PNG_INTERLACED GFXOFF -// #define GDISP_NEED_IMAGE_PNG_TRANSPARENCY GFXON -// #define GDISP_NEED_IMAGE_PNG_BACKGROUND GFXON -// #define GDISP_NEED_IMAGE_PNG_ALPHACLIFF 32 -// #define GDISP_NEED_IMAGE_PNG_PALETTE_124 GFXON -// #define GDISP_NEED_IMAGE_PNG_PALETTE_8 GFXON -// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 GFXON -// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 GFXON -// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 GFXON -// #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 GFXON -// #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 GFXON -// #define GDISP_NEED_IMAGE_PNG_RGB_8 GFXON -// #define GDISP_NEED_IMAGE_PNG_RGB_16 GFXON -// #define GDISP_NEED_IMAGE_PNG_RGBALPHA_8 GFXON -// #define GDISP_NEED_IMAGE_PNG_RGBALPHA_16 GFXON -// #define GDISP_IMAGE_PNG_BLIT_BUFFER_SIZE 32 -// #define GDISP_IMAGE_PNG_FILE_BUFFER_SIZE 8 -// #define GDISP_IMAGE_PNG_Z_BUFFER_SIZE 32768 -// #define GDISP_NEED_IMAGE_ACCOUNTING GFXOFF - -//#define GDISP_NEED_PIXMAP GFXOFF -// #define GDISP_NEED_PIXMAP_IMAGE GFXOFF - -//#define GDISP_DEFAULT_ORIENTATION gOrientationLandscape // If not defined the native hardware orientation is used. -//#define GDISP_LINEBUF_SIZE 128 -//#define GDISP_STARTUP_COLOR GFX_BLACK -#define GDISP_NEED_STARTUP_LOGO GFXOFF - -//#define GDISP_TOTAL_DISPLAYS 1 - -//#define GDISP_DRIVER_LIST GDISPVMT_Win32, GDISPVMT_Win32 -#ifdef GDISP_DRIVER_LIST -// // For code and speed optimization define as GFXON or GFXOFF if all controllers have the same capability -# define GDISP_HARDWARE_STREAM_WRITE GFXOFF -# define GDISP_HARDWARE_STREAM_READ GFXOFF -# define GDISP_HARDWARE_STREAM_POS GFXOFF -# define GDISP_HARDWARE_DRAWPIXEL GFXON -# define GDISP_HARDWARE_CLEARS GFXOFF -# define GDISP_HARDWARE_FILLS GFXOFF -//#define GDISP_HARDWARE_BITFILLS GFXOFF -# define GDISP_HARDWARE_SCROLL GFXOFF -# define GDISP_HARDWARE_PIXELREAD GFXON -# define GDISP_HARDWARE_CONTROL GFXON -# define GDISP_HARDWARE_QUERY GFXOFF -# define GDISP_HARDWARE_CLIP GFXOFF - -# define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 -#endif - -#define GDISP_USE_GFXNET GFXOFF -// #define GDISP_GFXNET_PORT 13001 -// #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP GFXOFF -// #define GDISP_DONT_WAIT_FOR_NET_DISPLAY GFXOFF -// #define GDISP_GFXNET_UNSAFE_SOCKETS GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GWIN // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GWIN GFXOFF - -//#define GWIN_NEED_WINDOWMANAGER GFXOFF -// #define GWIN_REDRAW_IMMEDIATE GFXOFF -// #define GWIN_REDRAW_SINGLEOP GFXOFF -// #define GWIN_NEED_FLASHING GFXOFF -// #define GWIN_FLASHING_PERIOD 250 - -//#define GWIN_NEED_CONSOLE GFXOFF -// #define GWIN_CONSOLE_USE_HISTORY GFXOFF -// #define GWIN_CONSOLE_HISTORY_AVERAGING GFXOFF -// #define GWIN_CONSOLE_HISTORY_ATCREATE GFXOFF -// #define GWIN_CONSOLE_ESCSEQ GFXOFF -// #define GWIN_CONSOLE_USE_BASESTREAM GFXOFF -// #define GWIN_CONSOLE_USE_FLOAT GFXOFF -//#define GWIN_NEED_GRAPH GFXOFF -//#define GWIN_NEED_GL3D GFXOFF - -//#define GWIN_NEED_WIDGET GFXOFF -//#define GWIN_FOCUS_HIGHLIGHT_WIDTH 1 -// #define GWIN_NEED_LABEL GFXOFF -// #define GWIN_LABEL_ATTRIBUTE GFXOFF -// #define GWIN_NEED_BUTTON GFXOFF -// #define GWIN_BUTTON_LAZY_RELEASE GFXOFF -// #define GWIN_NEED_SLIDER GFXOFF -// #define GWIN_SLIDER_NOSNAP GFXOFF -// #define GWIN_SLIDER_DEAD_BAND 5 -// #define GWIN_SLIDER_TOGGLE_INC 20 -// #define GWIN_NEED_CHECKBOX GFXOFF -// #define GWIN_NEED_IMAGE GFXOFF -// #define GWIN_NEED_IMAGE_ANIMATION GFXOFF -// #define GWIN_NEED_RADIO GFXOFF -// #define GWIN_NEED_LIST GFXOFF -// #define GWIN_NEED_LIST_IMAGES GFXOFF -// #define GWIN_NEED_PROGRESSBAR GFXOFF -// #define GWIN_PROGRESSBAR_AUTO GFXOFF -// #define GWIN_NEED_KEYBOARD GFXOFF -// #define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1 -// #define GWIN_NEED_KEYBOARD_ENGLISH1 GFXON -// #define GWIN_NEED_TEXTEDIT GFXOFF -// #define GWIN_FLAT_STYLING GFXOFF -// #define GWIN_WIDGET_TAGS GFXOFF - -//#define GWIN_NEED_CONTAINERS GFXOFF -// #define GWIN_NEED_CONTAINER GFXOFF -// #define GWIN_NEED_FRAME GFXOFF -// #define GWIN_NEED_TABSET GFXOFF -// #define GWIN_TABSET_TABHEIGHT 18 - -/////////////////////////////////////////////////////////////////////////// -// GTRANS // -/////////////////////////////////////////////////////////////////////////// -//#define GFX_USE_GTRANS GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GEVENT // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GEVENT GFXON - -//#define GEVENT_ASSERT_NO_RESOURCE GFXOFF -//#define GEVENT_MAXIMUM_SIZE 32 -//#define GEVENT_MAX_SOURCE_LISTENERS 32 - -/////////////////////////////////////////////////////////////////////////// -// GTIMER // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GTIMER GFXOFF - -//#define GTIMER_THREAD_PRIORITY gThreadpriorityHigh -//#define GTIMER_THREAD_WORKAREA_SIZE 2048 - -/////////////////////////////////////////////////////////////////////////// -// GQUEUE // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GQUEUE GFXOFF - -//#define GQUEUE_NEED_ASYNC GFXOFF -//#define GQUEUE_NEED_GSYNC GFXOFF -//#define GQUEUE_NEED_FSYNC GFXOFF -//#define GQUEUE_NEED_BUFFERS GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GINPUT // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GINPUT GFXOFF - -//#define GINPUT_NEED_MOUSE GFXOFF -// #define GINPUT_TOUCH_STARTRAW GFXOFF -// #define GINPUT_TOUCH_NOTOUCH GFXOFF -// #define GINPUT_TOUCH_NOCALIBRATE GFXOFF -// #define GINPUT_TOUCH_NOCALIBRATE_GUI GFXOFF -// #define GINPUT_MOUSE_POLL_PERIOD 25 -// #define GINPUT_MOUSE_CLICK_TIME 300 -// #define GINPUT_TOUCH_CXTCLICK_TIME 700 -// #define GINPUT_TOUCH_USER_CALIBRATION_LOAD GFXOFF -// #define GINPUT_TOUCH_USER_CALIBRATION_SAVE GFXOFF -// #define GMOUSE_DRIVER_LIST GMOUSEVMT_Win32, GMOUSEVMT_Win32 -// #define GINPUT_TOUCH_CALIBRATION_FONT1 "* Double" -// #define GINPUT_TOUCH_CALIBRATION_FONT2 "* Narrow" -// #define GINPUT_TOUCH_CALIBRATION_TITLE "Calibration" -// #define GINPUT_TOUCH_CALIBRATION_ERROR "Calibration Failed!" -//#define GINPUT_NEED_KEYBOARD GFXOFF -// #define GINPUT_KEYBOARD_POLL_PERIOD 200 -// #define GKEYBOARD_DRIVER_LIST GKEYBOARDVMT_Win32, GKEYBOARDVMT_Win32 -// #define GKEYBOARD_LAYOUT_OFF GFXOFF -// #define GKEYBOARD_LAYOUT_SCANCODE2_US GFXOFF -//#define GINPUT_NEED_TOGGLE GFXOFF -//#define GINPUT_NEED_DIAL GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GFILE // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GFILE GFXOFF - -//#define GFILE_NEED_PRINTG GFXOFF -//#define GFILE_NEED_SCANG GFXOFF -//#define GFILE_NEED_STRINGS GFXOFF -//#define GFILE_NEED_FILELISTS GFXOFF -//#define GFILE_NEED_STDIO GFXOFF -//#define GFILE_NEED_NOAUTOMOUNT GFXOFF -//#define GFILE_NEED_NOAUTOSYNC GFXOFF - -//#define GFILE_NEED_MEMFS GFXOFF -//#define GFILE_NEED_ROMFS GFXOFF -//#define GFILE_NEED_RAMFS GFXOFF -//#define GFILE_NEED_FATFS GFXOFF -//#define GFILE_NEED_NATIVEFS GFXOFF -//#define GFILE_NEED_CHBIOSFS GFXOFF -//#define GFILE_NEED_USERFS GFXOFF - -//#define GFILE_ALLOW_FLOATS GFXOFF -//#define GFILE_ALLOW_DEVICESPECIFIC GFXOFF -//#define GFILE_MAX_GFILES 3 - -/////////////////////////////////////////////////////////////////////////// -// GADC // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GADC GFXOFF -// #define GADC_MAX_LOWSPEED_DEVICES 4 - -/////////////////////////////////////////////////////////////////////////// -// GAUDIO // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GAUDIO GFXOFF -// #define GAUDIO_NEED_PLAY GFXOFF -// #define GAUDIO_NEED_RECORD GFXOFF - -/////////////////////////////////////////////////////////////////////////// -// GMISC // -/////////////////////////////////////////////////////////////////////////// -#define GFX_USE_GMISC GFXON - -//#define GMISC_NEED_ARRAYOPS GFXOFF -//#define GMISC_NEED_FASTTRIG GFXOFF -//#define GMISC_NEED_FIXEDTRIG GFXOFF -//#define GMISC_NEED_INVSQRT GFXOFF -// #define GMISC_INVSQRT_MIXED_ENDIAN GFXOFF -// #define GMISC_INVSQRT_REAL_SLOW GFXOFF -#define GMISC_NEED_MATRIXFLOAT2D GFXON -#define GMISC_NEED_MATRIXFIXED2D GFXOFF -//#define GMISC_NEED_HITTEST_POLY GFXOFF diff --git a/quantum/visualizer/default_animations.c b/quantum/visualizer/default_animations.c deleted file mode 100644 index 2f43c67cc8..0000000000 --- a/quantum/visualizer/default_animations.c +++ /dev/null @@ -1,177 +0,0 @@ -/* 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/>. - */ - -#if defined(VISUALIZER_ENABLE) - -# include "default_animations.h" -# include "visualizer.h" -# ifdef LCD_ENABLE -# include "lcd_keyframes.h" -# endif -# ifdef LCD_BACKLIGHT_ENABLE -# include "lcd_backlight_keyframes.h" -# endif - -# ifdef BACKLIGHT_ENABLE -# include "led_backlight_keyframes.h" -# endif - -# include "visualizer_keyframes.h" - -# if defined(LCD_ENABLE) || defined(LCD_BACKLIGHT_ENABLE) || defined(BACKLIGHT_ENABLE) - -static bool keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { -# ifdef LCD_ENABLE - lcd_keyframe_enable(animation, state); -# endif -# ifdef LCD_BACKLIGHT_ENABLE - lcd_backlight_keyframe_enable(animation, state); -# endif -# ifdef BACKLIGHT_ENABLE - led_backlight_keyframe_enable(animation, state); -# endif - return false; -} - -static bool keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { -# ifdef LCD_ENABLE - lcd_keyframe_disable(animation, state); -# endif -# ifdef LCD_BACKLIGHT_ENABLE - lcd_backlight_keyframe_disable(animation, state); -# endif -# ifdef BACKLIGHT_ENABLE - led_backlight_keyframe_disable(animation, state); -# endif - return false; -} - -static bool keyframe_fade_in(keyframe_animation_t* animation, visualizer_state_t* state) { - bool ret = false; -# ifdef LCD_BACKLIGHT_ENABLE - ret |= lcd_backlight_keyframe_animate_color(animation, state); -# endif -# ifdef BACKLIGHT_ENABLE - ret |= led_backlight_keyframe_fade_in_all(animation, state); -# endif - return ret; -} - -static bool keyframe_fade_out(keyframe_animation_t* animation, visualizer_state_t* state) { - bool ret = false; -# ifdef LCD_BACKLIGHT_ENABLE - ret |= lcd_backlight_keyframe_animate_color(animation, state); -# endif -# ifdef BACKLIGHT_ENABLE - ret |= led_backlight_keyframe_fade_out_all(animation, state); -# endif - return ret; -} - -// Don't worry, if the startup animation is long, you can use the keyboard like normal -// during that time -keyframe_animation_t default_startup_animation = { -# if LCD_ENABLE - .num_frames = 3, -# else - .num_frames = 2, -# endif - .loop = false, - .frame_lengths = {0, -# if LCD_ENABLE - 0, -# endif - gfxMillisecondsToTicks(5000)}, - .frame_functions = - { - keyframe_enable, -# if LCD_ENABLE - lcd_keyframe_draw_logo, -# endif - keyframe_fade_in, - }, -}; - -keyframe_animation_t default_suspend_animation = { -# if LCD_ENABLE - .num_frames = 3, -# else - .num_frames = 2, -# endif - .loop = false, - .frame_lengths = - { -# if LCD_ENABLE - 0, -# endif - gfxMillisecondsToTicks(1000), 0}, - .frame_functions = - { -# if LCD_ENABLE - lcd_keyframe_display_layer_text, -# endif - keyframe_fade_out, - keyframe_disable, - }, -}; -# endif - -# if defined(BACKLIGHT_ENABLE) -# define CROSSFADE_TIME 1000 -# define GRADIENT_TIME 3000 - -keyframe_animation_t led_test_animation = { - .num_frames = 14, - .loop = true, - .frame_lengths = - { - gfxMillisecondsToTicks(1000), // fade in - gfxMillisecondsToTicks(1000), // no op (leds on) - gfxMillisecondsToTicks(1000), // fade out - gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade - gfxMillisecondsToTicks(GRADIENT_TIME), // left to rigt (outside in) - gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade - gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom - 0, // mirror leds - gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade - gfxMillisecondsToTicks(GRADIENT_TIME), // left_to_right (mirrored, so inside out) - gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade - gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom - 0, // normal leds - gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade - - }, - .frame_functions = - { - led_backlight_keyframe_fade_in_all, - keyframe_no_operation, - led_backlight_keyframe_fade_out_all, - led_backlight_keyframe_crossfade, - led_backlight_keyframe_left_to_right_gradient, - led_backlight_keyframe_crossfade, - led_backlight_keyframe_top_to_bottom_gradient, - led_backlight_keyframe_mirror_orientation, - led_backlight_keyframe_crossfade, - led_backlight_keyframe_left_to_right_gradient, - led_backlight_keyframe_crossfade, - led_backlight_keyframe_top_to_bottom_gradient, - led_backlight_keyframe_normal_orientation, - led_backlight_keyframe_crossfade, - }, -}; -# endif - -#endif diff --git a/quantum/visualizer/default_animations.h b/quantum/visualizer/default_animations.h deleted file mode 100644 index 9accd89774..0000000000 --- a/quantum/visualizer/default_animations.h +++ /dev/null @@ -1,27 +0,0 @@ -/* 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/>. - */ - -#pragma once - -#include "visualizer.h" - -// You can use these default animations, but of course you can also write your own custom ones instead -extern keyframe_animation_t default_startup_animation; -extern keyframe_animation_t default_suspend_animation; - -// An animation for testing and demonstrating the led support, should probably not be used for real world -// cases -extern keyframe_animation_t led_test_animation; diff --git a/quantum/visualizer/lcd_backlight.c b/quantum/visualizer/lcd_backlight.c deleted file mode 100644 index 23978974e3..0000000000 --- a/quantum/visualizer/lcd_backlight.c +++ /dev/null @@ -1,87 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "lcd_backlight.h" -#include <math.h> - -static uint8_t current_hue = 0; -static uint8_t current_saturation = 0; -static uint8_t current_intensity = 0; -static uint8_t current_brightness = 0; - -void lcd_backlight_init(void) { - lcd_backlight_hal_init(); - lcd_backlight_color(current_hue, current_saturation, current_intensity); -} - -// This code is based on Brian Neltner's blogpost and example code -// "Why every LED light should be using HSI colorspace". -// http://blog.saikoled.com/post/43693602826/why-every-led-light-should-be-using-hsi -static void hsi_to_rgb(float h, float s, float i, uint16_t* r_out, uint16_t* g_out, uint16_t* b_out) { - unsigned int r, g, b; - h = fmodf(h, 360.0f); // cycle h around to 0-360 degrees - h = 3.14159f * h / 180.0f; // Convert to radians. - s = s > 0.0f ? (s < 1.0f ? s : 1.0f) : 0.0f; // clamp s and i to interval [0,1] - i = i > 0.0f ? (i < 1.0f ? i : 1.0f) : 0.0f; - - // Math! Thanks in part to Kyle Miller. - if (h < 2.09439f) { - r = 65535.0f * i / 3.0f * (1.0f + s * cos(h) / cosf(1.047196667f - h)); - g = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cos(1.047196667f - h))); - b = 65535.0f * i / 3.0f * (1.0f - s); - } else if (h < 4.188787) { - h = h - 2.09439; - g = 65535.0f * i / 3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h)); - b = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h))); - r = 65535.0f * i / 3.0f * (1.0f - s); - } else { - h = h - 4.188787; - b = 65535.0f * i / 3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h)); - r = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h))); - g = 65535.0f * i / 3.0f * (1.0f - s); - } - *r_out = r > 65535 ? 65535 : r; - *g_out = g > 65535 ? 65535 : g; - *b_out = b > 65535 ? 65535 : b; -} - -void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity) { - uint16_t r, g, b; - float hue_f = 360.0f * (float)hue / 255.0f; - float saturation_f = (float)saturation / 255.0f; - float intensity_f = (float)intensity / 255.0f; - intensity_f *= (float)current_brightness / 255.0f; - hsi_to_rgb(hue_f, saturation_f, intensity_f, &r, &g, &b); - current_hue = hue; - current_saturation = saturation; - current_intensity = intensity; - lcd_backlight_hal_color(r, g, b); -} - -void lcd_backlight_brightness(uint8_t b) { - current_brightness = b; - lcd_backlight_color(current_hue, current_saturation, current_intensity); -} - -uint8_t lcd_get_backlight_brightness(void) { return current_brightness; } diff --git a/quantum/visualizer/lcd_backlight.h b/quantum/visualizer/lcd_backlight.h deleted file mode 100644 index 4ea5b14639..0000000000 --- a/quantum/visualizer/lcd_backlight.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#pragma once - -#include <stdint.h> - -// Helper macros for storing hue, staturation and intensity as unsigned integers -#define LCD_COLOR(hue, saturation, intensity) (hue << 16 | saturation << 8 | intensity) -#define LCD_HUE(color) ((color >> 16) & 0xFF) -#define LCD_SAT(color) ((color >> 8) & 0xFF) -#define LCD_INT(color) (color & 0xFF) - -static inline uint32_t change_lcd_color_intensity(uint32_t color, uint8_t new_intensity) { return (color & 0xFFFFFF00) | new_intensity; } - -void lcd_backlight_init(void); -void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity); -void lcd_backlight_brightness(uint8_t b); -uint8_t lcd_get_backlight_brightness(void); - -void lcd_backlight_hal_init(void); -void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b); diff --git a/quantum/visualizer/lcd_backlight_keyframes.c b/quantum/visualizer/lcd_backlight_keyframes.c deleted file mode 100644 index c13cce311d..0000000000 --- a/quantum/visualizer/lcd_backlight_keyframes.c +++ /dev/null @@ -1,69 +0,0 @@ -/* 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 "lcd_backlight_keyframes.h" - -bool lcd_backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state) { - int frame_length = animation->frame_lengths[animation->current_frame]; - int current_pos = frame_length - animation->time_left_in_frame; - uint8_t t_h = LCD_HUE(state->target_lcd_color); - uint8_t t_s = LCD_SAT(state->target_lcd_color); - uint8_t t_i = LCD_INT(state->target_lcd_color); - uint8_t p_h = LCD_HUE(state->prev_lcd_color); - uint8_t p_s = LCD_SAT(state->prev_lcd_color); - uint8_t p_i = LCD_INT(state->prev_lcd_color); - - uint8_t d_h1 = t_h - p_h; // Modulo arithmetic since we want to wrap around - int d_h2 = t_h - p_h; - // Chose the shortest way around - int d_h = abs(d_h2) < d_h1 ? d_h2 : d_h1; - int d_s = t_s - p_s; - int d_i = t_i - p_i; - - int hue = (d_h * current_pos) / frame_length; - int sat = (d_s * current_pos) / frame_length; - int intensity = (d_i * current_pos) / frame_length; - // dprintf("%X -> %X = %X\n", p_h, t_h, hue); - hue += p_h; - sat += p_s; - intensity += p_i; - state->current_lcd_color = LCD_COLOR(hue, sat, intensity); - lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color)); - - return true; -} - -bool lcd_backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - state->prev_lcd_color = state->target_lcd_color; - state->current_lcd_color = state->target_lcd_color; - lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color)); - return false; -} - -bool lcd_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - (void)state; - lcd_backlight_hal_color(0, 0, 0); - return false; -} - -bool lcd_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - (void)state; - lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color)); - return false; -} diff --git a/quantum/visualizer/lcd_backlight_keyframes.h b/quantum/visualizer/lcd_backlight_keyframes.h deleted file mode 100644 index 88768dd4a5..0000000000 --- a/quantum/visualizer/lcd_backlight_keyframes.h +++ /dev/null @@ -1,27 +0,0 @@ -/* 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/>. - */ - -#pragma once - -#include "visualizer.h" - -// Animates the LCD backlight color between the current color and the target color (of the state) -bool lcd_backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state); -// Sets the backlight color to the target color -bool lcd_backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state); - -bool lcd_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); -bool lcd_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); diff --git a/quantum/visualizer/lcd_keyframes.c b/quantum/visualizer/lcd_keyframes.c deleted file mode 100644 index 1d6f3dca18..0000000000 --- a/quantum/visualizer/lcd_keyframes.c +++ /dev/null @@ -1,184 +0,0 @@ -/* 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 "lcd_keyframes.h" -#include <string.h> -#include "action_util.h" -#include "led.h" -#include "resources/resources.h" - -bool lcd_keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - gdispClear(White); - gdispDrawString(0, 10, state->layer_text, state->font_dejavusansbold12, Black); - return false; -} - -static void format_layer_bitmap_string(uint16_t default_layer, uint16_t layer, char* buffer) { - for (int i = 0; i < 16; i++) { - uint32_t mask = (1u << i); - if (default_layer & mask) { - if (layer & mask) { - *buffer = 'B'; - } else { - *buffer = 'D'; - } - } else if (layer & mask) { - *buffer = '1'; - } else { - *buffer = '0'; - } - ++buffer; - - if (i == 3 || i == 7 || i == 11) { - *buffer = ' '; - ++buffer; - } - } - *buffer = 0; -} - -bool lcd_keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - const char* layer_help = "1=On D=Default B=Both"; - char layer_buffer[16 + 4]; // 3 spaces and one null terminator - gdispClear(White); - gdispDrawString(0, 0, layer_help, state->font_fixed5x8, Black); - format_layer_bitmap_string(state->status.default_layer, state->status.layer, layer_buffer); - gdispDrawString(0, 10, layer_buffer, state->font_fixed5x8, Black); - format_layer_bitmap_string(state->status.default_layer >> 16, state->status.layer >> 16, layer_buffer); - gdispDrawString(0, 20, layer_buffer, state->font_fixed5x8, Black); - return false; -} - -static void format_mods_bitmap_string(uint8_t mods, char* buffer) { - *buffer = ' '; - ++buffer; - - for (int i = 0; i < 8; i++) { - uint32_t mask = (1u << i); - if (mods & mask) { - *buffer = '1'; - } else { - *buffer = '0'; - } - ++buffer; - - if (i == 3) { - *buffer = ' '; - ++buffer; - } - } - *buffer = 0; -} - -bool lcd_keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - - const char* title = "Modifier states"; - const char* mods_header = " CSAG CSAG "; - char status_buffer[12]; - - gdispClear(White); - gdispDrawString(0, 0, title, state->font_fixed5x8, Black); - gdispDrawString(0, 10, mods_header, state->font_fixed5x8, Black); - format_mods_bitmap_string(state->status.mods, status_buffer); - gdispDrawString(0, 20, status_buffer, state->font_fixed5x8, Black); - - return false; -} - -#define LED_STATE_STRING_SIZE sizeof("NUM CAPS SCRL COMP KANA") - -static void get_led_state_string(char* output, visualizer_state_t* state) { - uint8_t pos = 0; - - if (state->status.leds & (1u << USB_LED_NUM_LOCK)) { - memcpy(output + pos, "NUM ", 4); - pos += 4; - } - if (state->status.leds & (1u << USB_LED_CAPS_LOCK)) { - memcpy(output + pos, "CAPS ", 5); - pos += 5; - } - if (state->status.leds & (1u << USB_LED_SCROLL_LOCK)) { - memcpy(output + pos, "SCRL ", 5); - pos += 5; - } - if (state->status.leds & (1u << USB_LED_COMPOSE)) { - memcpy(output + pos, "COMP ", 5); - pos += 5; - } - if (state->status.leds & (1u << USB_LED_KANA)) { - memcpy(output + pos, "KANA", 4); - pos += 4; - } - output[pos] = 0; -} - -bool lcd_keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - char output[LED_STATE_STRING_SIZE]; - get_led_state_string(output, state); - gdispClear(White); - gdispDrawString(0, 10, output, state->font_dejavusansbold12, Black); - return false; -} - -bool lcd_keyframe_display_layer_and_led_states(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - gdispClear(White); - uint8_t y = 10; - if (state->status.leds) { - char output[LED_STATE_STRING_SIZE]; - get_led_state_string(output, state); - gdispDrawString(0, 1, output, state->font_dejavusansbold12, Black); - y = 17; - } - gdispDrawString(0, y, state->layer_text, state->font_dejavusansbold12, Black); - return false; -} - -bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - (void)animation; - // Read the uGFX documentation for information how to use the displays - // http://wiki.ugfx.org/index.php/Main_Page - gdispClear(Black); - - // You can use static variables for things that can't be found in the animation - // or state structs, here we use the image - - // gdispGBlitArea is a tricky function to use since it supports blitting part of the image - // if you have full screen image, then just use LCD_WIDTH and LCD_HEIGHT for both source and target dimensions - gdispGBlitArea(GDISP, 0, 0, 128, 32, 0, 0, LCD_WIDTH, (pixel_t*)resource_lcd_logo); - - return false; -} - -bool lcd_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - (void)state; - gdispSetPowerMode(powerOff); - return false; -} - -bool lcd_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - (void)state; - gdispSetPowerMode(powerOn); - return false; -} diff --git a/quantum/visualizer/lcd_keyframes.h b/quantum/visualizer/lcd_keyframes.h deleted file mode 100644 index b7125e8323..0000000000 --- a/quantum/visualizer/lcd_keyframes.h +++ /dev/null @@ -1,35 +0,0 @@ -/* 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/>. - */ - -#pragma once - -#include "visualizer.h" - -// Displays the layer text centered vertically on the screen -bool lcd_keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state); -// Displays a bitmap (0/1) of all the currently active layers -bool lcd_keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); -// Displays a bitmap (0/1) of all the currently active mods -bool lcd_keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); -// Displays the keyboard led states (CAPS (Caps lock), NUM (Num lock), SCRL (Scroll lock), COMP (Compose), KANA) -bool lcd_keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state); -// Displays both the layer text and the led states -bool lcd_keyframe_display_layer_and_led_states(keyframe_animation_t* animation, visualizer_state_t* state); -// Displays the QMK logo on the LCD screen -bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* state); - -bool lcd_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); -bool lcd_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); diff --git a/quantum/visualizer/led_backlight_keyframes.c b/quantum/visualizer/led_backlight_keyframes.c deleted file mode 100644 index 338ada5227..0000000000 --- a/quantum/visualizer/led_backlight_keyframes.c +++ /dev/null @@ -1,143 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ -#include "gfx.h" -#include <math.h> -#include "led_backlight_keyframes.h" - -static uint8_t fade_led_color(keyframe_animation_t* animation, int from, int to) { - int frame_length = animation->frame_lengths[animation->current_frame]; - int current_pos = frame_length - animation->time_left_in_frame; - int delta = to - from; - int luma = (delta * current_pos) / frame_length; - luma += from; - return luma; -} - -static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint8_t from, uint8_t to) { - uint8_t luma = fade_led_color(animation, from, to); - color_t color = LUMA2COLOR(luma); - gdispGClear(LED_DISPLAY, color); -} - -// TODO: Should be customizable per keyboard -#define NUM_ROWS LED_HEIGHT -#define NUM_COLS LED_WIDTH - -static uint8_t crossfade_start_frame[NUM_ROWS][NUM_COLS]; -static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS]; - -static uint8_t compute_gradient_color(float t, float index, float num) { - const float two_pi = M_PI * 2.0f; - float normalized_index = (1.0f - index / (num - 1.0f)) * two_pi; - float x = t * two_pi + normalized_index; - float v = 0.5 * (cosf(x) + 1.0f); - return (uint8_t)(255.0f * v); -} - -bool led_backlight_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - keyframe_fade_all_leds_from_to(animation, 0, 255); - return true; -} - -bool led_backlight_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - keyframe_fade_all_leds_from_to(animation, 255, 0); - return true; -} - -bool led_backlight_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - float frame_length = animation->frame_lengths[animation->current_frame]; - float current_pos = frame_length - animation->time_left_in_frame; - float t = current_pos / frame_length; - for (int i = 0; i < NUM_COLS; i++) { - uint8_t color = compute_gradient_color(t, i, NUM_COLS); - gdispGDrawLine(LED_DISPLAY, i, 0, i, NUM_ROWS - 1, LUMA2COLOR(color)); - } - return true; -} - -bool led_backlight_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - float frame_length = animation->frame_lengths[animation->current_frame]; - float current_pos = frame_length - animation->time_left_in_frame; - float t = current_pos / frame_length; - for (int i = 0; i < NUM_ROWS; i++) { - uint8_t color = compute_gradient_color(t, i, NUM_ROWS); - gdispGDrawLine(LED_DISPLAY, 0, i, NUM_COLS - 1, i, LUMA2COLOR(color)); - } - return true; -} - -static void copy_current_led_state(uint8_t* dest) { - for (int i = 0; i < NUM_ROWS; i++) { - for (int j = 0; j < NUM_COLS; j++) { - dest[i * NUM_COLS + j] = gdispGGetPixelColor(LED_DISPLAY, j, i); - } - } -} -bool led_backlight_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - if (animation->first_update_of_frame) { - copy_current_led_state(&crossfade_start_frame[0][0]); - run_next_keyframe(animation, state); - copy_current_led_state(&crossfade_end_frame[0][0]); - } - for (int i = 0; i < NUM_ROWS; i++) { - for (int j = 0; j < NUM_COLS; j++) { - color_t color = LUMA2COLOR(fade_led_color(animation, crossfade_start_frame[i][j], crossfade_end_frame[i][j])); - gdispGDrawPixel(LED_DISPLAY, j, i, color); - } - } - return true; -} - -bool led_backlight_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - (void)animation; - gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_180); - return false; -} - -bool led_backlight_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - (void)animation; - gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0); - return false; -} - -bool led_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - (void)animation; - gdispGSetPowerMode(LED_DISPLAY, powerOff); - return false; -} - -bool led_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; - (void)animation; - gdispGSetPowerMode(LED_DISPLAY, powerOn); - return false; -} diff --git a/quantum/visualizer/led_backlight_keyframes.h b/quantum/visualizer/led_backlight_keyframes.h deleted file mode 100644 index 90153be5eb..0000000000 --- a/quantum/visualizer/led_backlight_keyframes.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#pragma once - -#include "visualizer.h" - -bool led_backlight_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state); - -bool led_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); - -extern keyframe_animation_t led_test_animation; diff --git a/quantum/visualizer/readme.md b/quantum/visualizer/readme.md deleted file mode 100644 index 298efb742f..0000000000 --- a/quantum/visualizer/readme.md +++ /dev/null @@ -1,18 +0,0 @@ -# A visualization library for the TMK keyboard firmware - -This library is designed to work together with the [TMK keyboard firmware](https://github.com/tmk/tmk_keyboard). Currently it only works for [Chibios](http://www.chibios.org/) - flavors, but it would be possible to add support for other configurations as well. The LCD display functionality is provided by the [uGFX library](https://ugfx.io/). - -## To use this library as a user -You can and should modify the visualizer\_user.c file. Check the comments in the file for more information. - -## To add this library to custom keyboard projects - -1. Add tmk_visualizer as a submodule to your project -1. Set VISUALIZER_DIR in the main keyboard project makefile to point to the submodule -1. Define LCD\_ENABLE and/or LCD\_BACKLIGHT\_ENABLE, to enable support -1. Include the visualizer.mk make file -1. Copy the files in the example\_integration folder to your keyboard project -1. All other files than the callback.c file are included automatically, so you will need to add callback.c to your makefile manually. If you already have a similar file in your project, you can just copy the functions instead of the whole file. -1. Edit the files to match your hardware. You might might want to read the Chibios and UGfx documentation, for more information. -1. If you enable LCD support you might also have to write a custom uGFX display driver, check the uGFX documentation for that. You probably also want to enable SPI support in your Chibios configuration. diff --git a/quantum/visualizer/resources/lcd_logo.c b/quantum/visualizer/resources/lcd_logo.c deleted file mode 100644 index 13bf734cb3..0000000000 --- a/quantum/visualizer/resources/lcd_logo.c +++ /dev/null @@ -1,45 +0,0 @@ -/* 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 "resources.h" - -// clang-format off - -// To generate an image array like this -// Ensure the image is 128 x 32 or smaller -// Convert the bitmap to a C array using a program like http://www.riuson.com/lcd-image-converter/ -// Ensure the the conversion process produces a monochrome format array - 1 bit/pixel, left to right, top to bottom -// Update array in the source code with the C array produced by the conversion program - -// The image below is generated from lcd_logo.png -__attribute__((weak)) const uint8_t resource_lcd_logo[512] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFE, 0xEE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xEE, 0xF0, 0x01, 0xC6, 0x0D, 0x8C, 0x1F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFE, 0xEE, 0xFE, 0x03, 0xE7, 0x1D, 0x9C, 0x1F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x37, 0x1D, 0xB8, 0x18, 0x0B, 0x59, 0xC8, 0x09, 0xE5, 0x9E, 0x00, - 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x37, 0xBD, 0xF0, 0x18, 0x6F, 0x7F, 0xEC, 0x9B, 0x37, 0xB3, 0x00, 0x00, 0xFE, 0xEE, 0xFE, 0x06, 0x37, 0xBD, 0xE0, 0x1F, 0x6C, 0x66, 0x6D, 0xD8, 0x36, 0x33, 0x00, - 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x36, 0xED, 0xF0, 0x1F, 0x6C, 0x66, 0x6D, 0x59, 0xF6, 0x3E, 0x00, 0x00, 0x1F, 0x6D, 0xF0, 0x06, 0x36, 0xED, 0xB8, 0x18, 0x6C, 0x66, 0x67, 0x73, 0x36, 0x30, 0x00, - 0x00, 0xFF, 0x83, 0xFE, 0x03, 0xE6, 0x4D, 0x9C, 0x18, 0x6C, 0x66, 0x67, 0x73, 0x36, 0x1F, 0x00, 0x00, 0x1F, 0xEF, 0xF0, 0x01, 0xC6, 0x0D, 0x8C, 0x18, 0x6C, 0x66, 0x62, 0x21, 0xD6, 0x0E, 0x00, - 0x00, 0xFF, 0xEF, 0xFE, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; diff --git a/quantum/visualizer/resources/lcd_logo.png b/quantum/visualizer/resources/lcd_logo.png Binary files differdeleted file mode 100644 index 178ef65f15..0000000000 --- a/quantum/visualizer/resources/lcd_logo.png +++ /dev/null diff --git a/quantum/visualizer/resources/resources.h b/quantum/visualizer/resources/resources.h deleted file mode 100644 index 5178fbe55a..0000000000 --- a/quantum/visualizer/resources/resources.h +++ /dev/null @@ -1,23 +0,0 @@ -/* 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/>. - */ - -#pragma once - -#include <stdint.h> - -#ifdef LCD_ENABLE -extern const uint8_t resource_lcd_logo[]; -#endif diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c deleted file mode 100644 index 709affbb77..0000000000 --- a/quantum/visualizer/visualizer.c +++ /dev/null @@ -1,483 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#include "config.h" -#include "visualizer.h" -#include <string.h> -#ifdef PROTOCOL_CHIBIOS -# include <ch.h> -#endif - -#include "gfx.h" - -#ifdef LCD_BACKLIGHT_ENABLE -# include "lcd_backlight.h" -#endif - -//#define DEBUG_VISUALIZER - -#ifdef DEBUG_VISUALIZER -# include "debug.h" -#else -# include "nodebug.h" -#endif - -#ifdef SERIAL_LINK_ENABLE -# include "serial_link/protocol/transport.h" -# include "serial_link/system/serial_link.h" -#endif - -#include "action_util.h" - -// Define this in config.h -#ifndef VISUALIZER_THREAD_PRIORITY -// The visualizer needs gfx thread priorities -# define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2) -#endif - -static visualizer_keyboard_status_t current_status = {.layer = 0xFFFFFFFF, - .default_layer = 0xFFFFFFFF, - .leds = 0xFFFFFFFF, -#ifdef BACKLIGHT_ENABLE - .backlight_level = 0, -#endif - .mods = 0xFF, - .suspended = false, -#ifdef VISUALIZER_USER_DATA_SIZE - .user_data = {0} -#endif -}; - -static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) { - return status1->layer == status2->layer && status1->default_layer == status2->default_layer && status1->mods == status2->mods && status1->leds == status2->leds && status1->suspended == status2->suspended -#ifdef BACKLIGHT_ENABLE - && status1->backlight_level == status2->backlight_level -#endif -#ifdef VISUALIZER_USER_DATA_SIZE - && memcmp(status1->user_data, status2->user_data, VISUALIZER_USER_DATA_SIZE) == 0 -#endif - ; -} - -static bool visualizer_enabled = false; - -#ifdef VISUALIZER_USER_DATA_SIZE -static uint8_t user_data[VISUALIZER_USER_DATA_SIZE]; -#endif - -#define MAX_SIMULTANEOUS_ANIMATIONS 4 -static keyframe_animation_t* animations[MAX_SIMULTANEOUS_ANIMATIONS] = {}; - -#ifdef SERIAL_LINK_ENABLE -MASTER_TO_ALL_SLAVES_OBJECT(current_status, visualizer_keyboard_status_t); - -static remote_object_t* remote_objects[] = { - REMOTE_OBJECT(current_status), -}; - -#endif - -GDisplay* LCD_DISPLAY = 0; -GDisplay* LED_DISPLAY = 0; - -#ifdef LCD_DISPLAY_NUMBER -__attribute__((weak)) GDisplay* get_lcd_display(void) { return gdispGetDisplay(LCD_DISPLAY_NUMBER); } -#endif - -#ifdef LED_DISPLAY_NUMBER -__attribute__((weak)) GDisplay* get_led_display(void) { return gdispGetDisplay(LED_DISPLAY_NUMBER); } -#endif - -void start_keyframe_animation(keyframe_animation_t* animation) { - animation->current_frame = -1; - animation->time_left_in_frame = 0; - animation->need_update = true; - int free_index = -1; - for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) { - if (animations[i] == animation) { - return; - } - if (free_index == -1 && animations[i] == NULL) { - free_index = i; - } - } - if (free_index != -1) { - animations[free_index] = animation; - } -} - -void stop_keyframe_animation(keyframe_animation_t* animation) { - animation->current_frame = animation->num_frames; - animation->time_left_in_frame = 0; - animation->need_update = true; - animation->first_update_of_frame = false; - animation->last_update_of_frame = false; - for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) { - if (animations[i] == animation) { - animations[i] = NULL; - return; - } - } -} - -void stop_all_keyframe_animations(void) { - for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) { - if (animations[i]) { - animations[i]->current_frame = animations[i]->num_frames; - animations[i]->time_left_in_frame = 0; - animations[i]->need_update = true; - animations[i]->first_update_of_frame = false; - animations[i]->last_update_of_frame = false; - animations[i] = NULL; - } - } -} - -static uint8_t get_num_running_animations(void) { - uint8_t count = 0; - for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) { - count += animations[i] ? 1 : 0; - } - return count; -} - -static bool update_keyframe_animation(keyframe_animation_t* animation, visualizer_state_t* state, systemticks_t delta, systemticks_t* sleep_time) { - // TODO: Clean up this messy code - dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame, animation->time_left_in_frame, delta); - if (animation->current_frame == animation->num_frames) { - animation->need_update = false; - return false; - } - if (animation->current_frame == -1) { - animation->current_frame = 0; - animation->time_left_in_frame = animation->frame_lengths[0]; - animation->need_update = true; - animation->first_update_of_frame = true; - } else { - animation->time_left_in_frame -= delta; - while (animation->time_left_in_frame <= 0) { - int left = animation->time_left_in_frame; - if (animation->need_update) { - animation->time_left_in_frame = 0; - animation->last_update_of_frame = true; - (*animation->frame_functions[animation->current_frame])(animation, state); - animation->last_update_of_frame = false; - } - animation->current_frame++; - animation->need_update = true; - animation->first_update_of_frame = true; - if (animation->current_frame == animation->num_frames) { - if (animation->loop) { - animation->current_frame = 0; - } else { - stop_keyframe_animation(animation); - return false; - } - } - delta = -left; - animation->time_left_in_frame = animation->frame_lengths[animation->current_frame]; - animation->time_left_in_frame -= delta; - } - } - if (animation->need_update) { - animation->need_update = (*animation->frame_functions[animation->current_frame])(animation, state); - animation->first_update_of_frame = false; - } - - systemticks_t wanted_sleep = animation->need_update ? gfxMillisecondsToTicks(10) : (unsigned)animation->time_left_in_frame; - if (wanted_sleep < *sleep_time) { - *sleep_time = wanted_sleep; - } - - return true; -} - -void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state) { - int next_frame = animation->current_frame + 1; - if (next_frame == animation->num_frames) { - next_frame = 0; - } - keyframe_animation_t temp_animation = *animation; - temp_animation.current_frame = next_frame; - temp_animation.time_left_in_frame = animation->frame_lengths[next_frame]; - temp_animation.first_update_of_frame = true; - temp_animation.last_update_of_frame = false; - temp_animation.need_update = false; - visualizer_state_t temp_state = *state; - (*temp_animation.frame_functions[next_frame])(&temp_animation, &temp_state); -} - -// TODO: Optimize the stack size, this is probably way too big -static DECLARE_THREAD_STACK(visualizerThreadStack, 1024); -static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { - (void)arg; - - GListener event_listener; - geventListenerInit(&event_listener); - geventAttachSource(&event_listener, (GSourceHandle)¤t_status, 0); - - visualizer_keyboard_status_t initial_status = { - .default_layer = 0xFFFFFFFF, - .layer = 0xFFFFFFFF, - .mods = 0xFF, - .leds = 0xFFFFFFFF, - .suspended = false, -#ifdef BACKLIGHT_ENABLE - .backlight_level = 0, -#endif -#ifdef VISUALIZER_USER_DATA_SIZE - .user_data = {0}, -#endif - }; - - visualizer_state_t state = {.status = initial_status, - .current_lcd_color = 0, -#ifdef LCD_ENABLE - .font_fixed5x8 = gdispOpenFont("fixed_5x8"), - .font_dejavusansbold12 = gdispOpenFont("DejaVuSansBold12") -#endif - }; - initialize_user_visualizer(&state); - state.prev_lcd_color = state.current_lcd_color; - -#ifdef LCD_BACKLIGHT_ENABLE - lcd_backlight_color(LCD_HUE(state.current_lcd_color), LCD_SAT(state.current_lcd_color), LCD_INT(state.current_lcd_color)); -#endif - - systemticks_t sleep_time = TIME_INFINITE; - systemticks_t current_time = gfxSystemTicks(); - bool force_update = true; - - while (true) { - systemticks_t new_time = gfxSystemTicks(); - systemticks_t delta = new_time - current_time; - current_time = new_time; - bool enabled = visualizer_enabled; - if (force_update || !same_status(&state.status, ¤t_status)) { - force_update = false; -#if BACKLIGHT_ENABLE - if (current_status.backlight_level != state.status.backlight_level) { - if (current_status.backlight_level != 0) { - gdispGSetPowerMode(LED_DISPLAY, powerOn); - uint16_t percent = (uint16_t)current_status.backlight_level * 100 / BACKLIGHT_LEVELS; - gdispGSetBacklight(LED_DISPLAY, percent); - } else { - gdispGSetPowerMode(LED_DISPLAY, powerOff); - } - state.status.backlight_level = current_status.backlight_level; - } -#endif - if (visualizer_enabled) { - if (current_status.suspended) { - stop_all_keyframe_animations(); - visualizer_enabled = false; - state.status = current_status; - user_visualizer_suspend(&state); - } else { - visualizer_keyboard_status_t prev_status = state.status; - state.status = current_status; - update_user_visualizer_state(&state, &prev_status); - } - state.prev_lcd_color = state.current_lcd_color; - } - } - if (!enabled && state.status.suspended && current_status.suspended == false) { - // Setting the status to the initial status will force an update - // when the visualizer is enabled again - state.status = initial_status; - state.status.suspended = false; - stop_all_keyframe_animations(); - user_visualizer_resume(&state); - state.prev_lcd_color = state.current_lcd_color; - } - sleep_time = TIME_INFINITE; - for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) { - if (animations[i]) { - update_keyframe_animation(animations[i], &state, delta, &sleep_time); - } - } -#ifdef BACKLIGHT_ENABLE - gdispGFlush(LED_DISPLAY); -#endif - -#ifdef LCD_ENABLE - gdispGFlush(LCD_DISPLAY); -#endif - -#ifdef EMULATOR - draw_emulator(); -#endif - // Enable the visualizer when the startup or the suspend animation has finished - if (!visualizer_enabled && state.status.suspended == false && get_num_running_animations() == 0) { - visualizer_enabled = true; - force_update = true; - sleep_time = 0; - } - - systemticks_t after_update = gfxSystemTicks(); - unsigned update_delta = after_update - current_time; - if (sleep_time != TIME_INFINITE) { - if (sleep_time > update_delta) { - sleep_time -= update_delta; - } else { - sleep_time = 0; - } - } - dprintf("Update took %d, last delta %d, sleep_time %d\n", update_delta, delta, sleep_time); -#ifdef PROTOCOL_CHIBIOS - // The gEventWait function really takes milliseconds, even if the documentation says ticks. - // Unfortunately there's no generic ugfx conversion from system time to milliseconds, - // so let's do it in a platform dependent way. - - // On windows the system ticks is the same as milliseconds anyway - if (sleep_time != TIME_INFINITE) { - sleep_time = TIME_I2MS(sleep_time); - } -#endif - geventEventWait(&event_listener, sleep_time); - } -#ifdef LCD_ENABLE - gdispCloseFont(state.font_fixed5x8); - gdispCloseFont(state.font_dejavusansbold12); -#endif - - return 0; -} - -void visualizer_init(void) { - gfxInit(); - -#ifdef LCD_BACKLIGHT_ENABLE - lcd_backlight_init(); -#endif - -#ifdef SERIAL_LINK_ENABLE - add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*)); -#endif - -#ifdef LCD_ENABLE - LCD_DISPLAY = get_lcd_display(); -#endif - -#ifdef BACKLIGHT_ENABLE - LED_DISPLAY = get_led_display(); -#endif - - // We are using a low priority thread, the idea is to have it run only - // when the main thread is sleeping during the matrix scanning - gfxThreadCreate(visualizerThreadStack, sizeof(visualizerThreadStack), VISUALIZER_THREAD_PRIORITY, visualizerThread, NULL); -} - -void update_status(bool changed) { - if (changed) { - GSourceListener* listener = geventGetSourceListener((GSourceHandle)¤t_status, NULL); - if (listener) { - geventSendEvent(listener); - } - } -#ifdef SERIAL_LINK_ENABLE - static systime_t last_update = 0; - systime_t current_update = chVTGetSystemTimeX(); - systime_t delta = current_update - last_update; - if (changed || delta > TIME_MS2I(10)) { - last_update = current_update; - visualizer_keyboard_status_t* r = begin_write_current_status(); - *r = current_status; - end_write_current_status(); - } -#endif -} - -uint8_t visualizer_get_mods() { - uint8_t mods = get_mods(); - -#ifndef NO_ACTION_ONESHOT - if (!has_oneshot_mods_timed_out()) { - mods |= get_oneshot_mods(); - } -#endif - return mods; -} - -#ifdef VISUALIZER_USER_DATA_SIZE -void visualizer_set_user_data(void* u) { memcpy(user_data, u, VISUALIZER_USER_DATA_SIZE); } -#endif - -void visualizer_update(layer_state_t default_state, layer_state_t state, uint8_t mods, uint32_t leds) { - // Note that there's a small race condition here, the thread could read - // a state where one of these are set but not the other. But this should - // not really matter as it will be fixed during the next loop step. - // Alternatively a mutex could be used instead of the volatile variables - - bool changed = false; -#ifdef SERIAL_LINK_ENABLE - if (is_serial_link_connected()) { - visualizer_keyboard_status_t* new_status = read_current_status(); - if (new_status) { - if (!same_status(¤t_status, new_status)) { - changed = true; - current_status = *new_status; - } - } - } else { -#else - { -#endif - visualizer_keyboard_status_t new_status = { - .layer = state, - .default_layer = default_state, - .mods = mods, - .leds = leds, -#ifdef BACKLIGHT_ENABLE - .backlight_level = current_status.backlight_level, -#endif - .suspended = current_status.suspended, - }; -#ifdef VISUALIZER_USER_DATA_SIZE - memcpy(new_status.user_data, user_data, VISUALIZER_USER_DATA_SIZE); -#endif - if (!same_status(¤t_status, &new_status)) { - changed = true; - current_status = new_status; - } - } - update_status(changed); -} - -void visualizer_suspend(void) { - current_status.suspended = true; - update_status(true); -} - -void visualizer_resume(void) { - current_status.suspended = false; - update_status(true); -} - -#ifdef BACKLIGHT_ENABLE -void backlight_set(uint8_t level) { - current_status.backlight_level = level; - update_status(true); -} -#endif diff --git a/quantum/visualizer/visualizer.h b/quantum/visualizer/visualizer.h deleted file mode 100644 index 627c80a305..0000000000 --- a/quantum/visualizer/visualizer.h +++ /dev/null @@ -1,154 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2016 Fred Sundvik - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -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. -*/ - -#pragma once - -#include <stdlib.h> -#include <stdint.h> -#include <stdbool.h> - -#include "config.h" -#include "gfx.h" -#include "action_layer.h" - -#ifdef LCD_BACKLIGHT_ENABLE -# include "lcd_backlight.h" -#endif - -#ifdef BACKLIGHT_ENABLE -# include "backlight.h" -#endif - -// use this function to merge both real_mods and oneshot_mods in a uint16_t -uint8_t visualizer_get_mods(void); - -// This need to be called once at the start -void visualizer_init(void); -// This should be called at every matrix scan -void visualizer_update(layer_state_t default_state, layer_state_t state, uint8_t mods, uint32_t leds); - -// This should be called when the keyboard goes to suspend state -void visualizer_suspend(void); -// This should be called when the keyboard wakes up from suspend state -void visualizer_resume(void); - -// These functions are week, so they can be overridden by the keyboard -// if needed -GDisplay* get_lcd_display(void); -GDisplay* get_led_display(void); - -// For emulator builds, this function need to be implemented -#ifdef EMULATOR -void draw_emulator(void); -#endif - -// If you need support for more than 16 keyframes per animation, you can change this -#define MAX_VISUALIZER_KEY_FRAMES 16 - -struct keyframe_animation_t; - -typedef struct { - layer_state_t layer; - layer_state_t default_layer; - uint32_t leds; // See led.h for available statuses - uint8_t mods; - bool suspended; -#ifdef BACKLIGHT_ENABLE - uint8_t backlight_level; -#endif -#ifdef VISUALIZER_USER_DATA_SIZE - uint8_t user_data[VISUALIZER_USER_DATA_SIZE]; -#endif -} visualizer_keyboard_status_t; - -// The state struct is used by the various keyframe functions -// It's also used for setting the LCD color and layer text -// from the user customized code -typedef struct visualizer_state_t { - // The user code should primarily be modifying these - uint32_t target_lcd_color; - const char* layer_text; - - // The user visualizer(and animation functions) can read these - visualizer_keyboard_status_t status; - - // These are used by the animation functions - uint32_t current_lcd_color; - uint32_t prev_lcd_color; -#ifdef LCD_ENABLE - gFont font_fixed5x8; - gFont font_dejavusansbold12; -#endif -} visualizer_state_t; - -// Any custom keyframe function should have this signature -// return true to get continuous updates, otherwise you will only get one -// update per frame -typedef bool (*frame_func)(struct keyframe_animation_t*, visualizer_state_t*); - -// Represents a keyframe animation, so fields are internal to the system -// while others are meant to be initialized by the user code -typedef struct keyframe_animation_t { - // These should be initialized - int num_frames; - bool loop; - int frame_lengths[MAX_VISUALIZER_KEY_FRAMES]; - frame_func frame_functions[MAX_VISUALIZER_KEY_FRAMES]; - - // Used internally by the system, and can also be read by - // keyframe update functions - int current_frame; - int time_left_in_frame; - bool first_update_of_frame; - bool last_update_of_frame; - bool need_update; - -} keyframe_animation_t; - -extern GDisplay* LCD_DISPLAY; -extern GDisplay* LED_DISPLAY; - -void start_keyframe_animation(keyframe_animation_t* animation); -void stop_keyframe_animation(keyframe_animation_t* animation); -// This runs the next keyframe, but does not update the animation state -// Useful for crossfades for example -void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state); - -// The master can set userdata which will be transferred to the slave -#ifdef VISUALIZER_USER_DATA_SIZE -void visualizer_set_user_data(void* user_data); -#endif - -// These functions have to be implemented by the user -// Called regularly each time the state has changed (but not every scan loop) -void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status); -// Called when the computer goes to suspend, will also stop calling update_user_visualizer_state -void user_visualizer_suspend(visualizer_state_t* state); -// You have to start at least one animation as a response to the following two functions -// When the animation has finished the visualizer will resume normal operation and start calling the -// update_user_visualizer_state again -// Called when the keyboard boots up -void initialize_user_visualizer(visualizer_state_t* state); -// Called when the computer resumes from a suspend -void user_visualizer_resume(visualizer_state_t* state); diff --git a/quantum/visualizer/visualizer.mk b/quantum/visualizer/visualizer.mk deleted file mode 100644 index 4c961ac59d..0000000000 --- a/quantum/visualizer/visualizer.mk +++ /dev/null @@ -1,123 +0,0 @@ -# The MIT License (MIT) -# -# Copyright (c) 2016 Fred Sundvik -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# 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. - -define ADD_DRIVER - $(1)_DRIVER:=$(strip $($(1)_DRIVER)) - $(1)_WIDTH:=$(strip $($(1)_WIDTH)) - $(1)_HEIGHT:=$(strip $($(1)_HEIGHT)) - ifeq ($($(1)_DRIVER),) - $$(error $(1)_DRIVER is not defined) - endif - ifeq ($($(1)_WIDTH),) - $$(error $(1)_WIDTH is not defined) - endif - ifeq ($($(1)_HEIGHT),) - $$(error $(1)_HEIGHT is not defined) - endif - OPT_DEFS+=-D$(1)_WIDTH=$($(1)_WIDTH) - OPT_DEFS+=-D$(1)_HEIGHT=$($(1)_HEIGHT) - GFXDEFS+=-D$(1)_WIDTH=$($(1)_WIDTH) - GFXDEFS+=-D$(1)_HEIGHT=$($(1)_HEIGHT) - $(1)_DISPLAY_NUMBER:=$$(words $$(GDISP_DRIVER_LIST)) - OPT_DEFS+=-D$(1)_DISPLAY_NUMBER=$$($(1)_DISPLAY_NUMBER) - include $(TOP_DIR)/drivers/ugfx/gdisp/$($(1)_DRIVER)/driver.mk -endef - -GDISP_DRIVER_LIST:= - -SRC += $(VISUALIZER_DIR)/visualizer.c \ - $(VISUALIZER_DIR)/visualizer_keyframes.c -EXTRAINCDIRS += $(GFXINC) $(VISUALIZER_DIR) -GFXLIB = $(LIB_PATH)/ugfx -VPATH += $(VISUALIZER_PATH) - -OPT_DEFS += -DVISUALIZER_ENABLE - -ifdef LCD_ENABLE -OPT_DEFS += -DLCD_ENABLE -ULIBS += -lm -endif - -ifeq ($(strip $(LCD_ENABLE)), yes) - SRC += $(VISUALIZER_DIR)/lcd_keyframes.c - ifeq ($(strip $(LCD_BACKLIGHT_ENABLE)), yes) - OPT_DEFS += -DLCD_BACKLIGHT_ENABLE - SRC += $(VISUALIZER_DIR)/lcd_backlight.c - SRC += $(VISUALIZER_DIR)/lcd_backlight_keyframes.c - endif -# Note, that the linker will strip out any resources that are not actually in use -SRC += $(VISUALIZER_DIR)/resources/lcd_logo.c -$(eval $(call ADD_DRIVER,LCD)) -endif - -ifeq ($(strip $(BACKLIGHT_ENABLE)), yes) -SRC += $(VISUALIZER_DIR)/led_backlight_keyframes.c -$(eval $(call ADD_DRIVER,LED)) -endif - -SRC += $(VISUALIZER_DIR)/default_animations.c - -include $(GFXLIB)/gfx.mk -# For the common_gfxconf.h -GFXINC += quantum/visualizer - -GFXSRC := $(patsubst $(TOP_DIR)/%,%,$(GFXSRC)) -GFXDEFS := $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS))) - -GDISP_LIST_COMMA=, -GDISP_LIST_EMPTY= -GDISP_LIST_SPACE=$(GDISP_LIST_EMPTY) $(GDISP_LIST_EMPTY) - -GDISP_DRIVER_LIST := $(strip $(GDISP_DRIVER_LIST)) -GDISP_DRIVER_LIST := $(subst $(GDISP_LIST_SPACE),$(GDISP_LIST_COMMA),$(GDISP_DRIVER_LIST)) - -GFXDEFS +=-DGDISP_DRIVER_LIST="$(GDISP_DRIVER_LIST)" - -ifneq ("$(wildcard $(KEYMAP_PATH)/visualizer.c)","") - SRC += $(KEYMAP_PATH)/visualizer.c -else - VISUALIZER_1 := $(KEYBOARD_PATH_1)/visualizer.c - VISUALIZER_2 := $(KEYBOARD_PATH_2)/visualizer.c - VISUALIZER_3 := $(KEYBOARD_PATH_3)/visualizer.c - VISUALIZER_4 := $(KEYBOARD_PATH_4)/visualizer.c - VISUALIZER_5 := $(KEYBOARD_PATH_5)/visualizer.c - - ifneq ("$(wildcard $(VISUALIZER_5))","") - SRC += $(VISUALIZER_5) - endif - ifneq ("$(wildcard $(VISUALIZER_4))","") - SRC += $(VISUALIZER_4) - endif - ifneq ("$(wildcard $(VISUALIZER_3))","") - SRC += $(VISUALIZER_3) - endif - ifneq ("$(wildcard $(VISUALIZER_2))","") - SRC += $(VISUALIZER_2) - endif - ifneq ("$(wildcard $(VISUALIZER_1))","") - SRC += $(VISUALIZER_1) - endif -endif - -ifdef EMULATOR -UINCDIR += $(TMK_DIR)/common -endif diff --git a/quantum/visualizer/visualizer_keyframes.c b/quantum/visualizer/visualizer_keyframes.c deleted file mode 100644 index 8f6a7e15a4..0000000000 --- a/quantum/visualizer/visualizer_keyframes.c +++ /dev/null @@ -1,23 +0,0 @@ -/* 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 "visualizer_keyframes.h" - -bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)animation; - (void)state; - return false; -} diff --git a/quantum/visualizer/visualizer_keyframes.h b/quantum/visualizer/visualizer_keyframes.h deleted file mode 100644 index c92ff16113..0000000000 --- a/quantum/visualizer/visualizer_keyframes.h +++ /dev/null @@ -1,23 +0,0 @@ -/* 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/>. - */ - -#pragma once - -#include "visualizer.h" - -// Some predefined keyframe functions that can be used by the user code -// Does nothing, useful for adding delays -bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state); |