summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/avr/analog.c138
-rw-r--r--drivers/avr/analog.h53
-rw-r--r--drivers/avr/apa102.c96
-rw-r--r--drivers/avr/glcdfont.c23
-rw-r--r--drivers/avr/hd44780.c536
-rw-r--r--drivers/avr/hd44780.h348
-rw-r--r--drivers/avr/i2c_master.c224
-rw-r--r--drivers/avr/i2c_master.h43
-rw-r--r--drivers/avr/i2c_slave.c86
-rw-r--r--drivers/avr/i2c_slave.h30
-rw-r--r--drivers/avr/serial.c568
-rw-r--r--drivers/avr/serial.h62
-rw-r--r--drivers/avr/spi_master.c180
-rw-r--r--drivers/avr/spi_master.h59
-rw-r--r--drivers/avr/ssd1306.c319
-rw-r--r--drivers/avr/ssd1306.h87
-rw-r--r--drivers/avr/uart.c170
-rw-r--r--drivers/avr/uart.h35
-rw-r--r--drivers/avr/ws2812.c176
-rw-r--r--drivers/avr/ws2812_i2c.c27
-rw-r--r--drivers/chibios/analog.c321
-rw-r--r--drivers/chibios/i2c_master.c121
-rw-r--r--drivers/chibios/i2c_master.h113
-rw-r--r--drivers/chibios/serial.c290
-rw-r--r--drivers/chibios/serial.h62
-rw-r--r--drivers/chibios/serial_usart.c219
-rw-r--r--drivers/chibios/serial_usart.h90
-rw-r--r--drivers/chibios/serial_usart_duplex.c261
-rw-r--r--drivers/chibios/spi_master.c148
-rw-r--r--drivers/chibios/spi_master.h80
-rw-r--r--drivers/chibios/uart.c50
-rw-r--r--drivers/chibios/uart.h77
-rw-r--r--drivers/chibios/usbpd_stm32g4.c76
-rw-r--r--drivers/chibios/ws2812.c114
-rw-r--r--drivers/chibios/ws2812_pwm.c311
-rw-r--r--drivers/chibios/ws2812_spi.c159
-rw-r--r--drivers/chibios/wt_rgb_backlight.c3125
-rw-r--r--drivers/chibios/wt_rgb_backlight.h115
-rw-r--r--drivers/chibios/wt_rgb_backlight_api.h43
-rw-r--r--drivers/chibios/wt_rgb_backlight_keycodes.h34
-rw-r--r--drivers/eeprom/eeprom_i2c.c23
-rw-r--r--drivers/eeprom/eeprom_spi.c7
-rw-r--r--drivers/eeprom/eeprom_stm32_L0_L1.c96
-rw-r--r--drivers/eeprom/eeprom_stm32_L0_L1.h33
-rw-r--r--drivers/haptic/haptic.c395
-rw-r--r--drivers/haptic/haptic.h81
-rw-r--r--drivers/haptic/solenoid.c1
-rw-r--r--drivers/lcd/st7565.c496
-rw-r--r--drivers/lcd/st7565.h219
-rw-r--r--drivers/led/apa102.c (renamed from drivers/apa102/apa102.c)0
-rw-r--r--drivers/led/apa102.h (renamed from drivers/apa102/apa102.h)0
-rw-r--r--drivers/led/aw20216.c141
-rw-r--r--drivers/led/aw20216.h253
-rw-r--r--drivers/led/issi/is31fl3218.c (renamed from drivers/issi/is31fl3218.c)0
-rw-r--r--drivers/led/issi/is31fl3218.h (renamed from drivers/issi/is31fl3218.h)0
-rw-r--r--drivers/led/issi/is31fl3731-simple.c (renamed from drivers/issi/is31fl3731-simple.c)0
-rw-r--r--drivers/led/issi/is31fl3731-simple.h (renamed from drivers/issi/is31fl3731-simple.h)3
-rw-r--r--drivers/led/issi/is31fl3731.c (renamed from drivers/issi/is31fl3731.c)0
-rw-r--r--drivers/led/issi/is31fl3731.h (renamed from drivers/issi/is31fl3731.h)3
-rw-r--r--drivers/led/issi/is31fl3733.c (renamed from drivers/issi/is31fl3733.c)0
-rw-r--r--drivers/led/issi/is31fl3733.h (renamed from drivers/issi/is31fl3733.h)3
-rw-r--r--drivers/led/issi/is31fl3736.c (renamed from drivers/issi/is31fl3736.c)0
-rw-r--r--drivers/led/issi/is31fl3736.h (renamed from drivers/issi/is31fl3736.h)3
-rw-r--r--drivers/led/issi/is31fl3737.c (renamed from drivers/issi/is31fl3737.c)43
-rw-r--r--drivers/led/issi/is31fl3737.h (renamed from drivers/issi/is31fl3737.h)3
-rw-r--r--drivers/led/issi/is31fl3741.c (renamed from drivers/issi/is31fl3741.c)20
-rw-r--r--drivers/led/issi/is31fl3741.h (renamed from drivers/issi/is31fl3741.h)7
-rw-r--r--drivers/oled/oled_driver.h8
-rw-r--r--drivers/oled/ssd1306_sh1106.c (renamed from drivers/oled/oled_driver.c)28
-rw-r--r--drivers/qwiic/micro_oled.c27
-rw-r--r--drivers/sensors/adns5050.c193
-rw-r--r--drivers/sensors/adns5050.h79
-rw-r--r--drivers/sensors/adns9800.c219
-rw-r--r--drivers/sensors/adns9800.h (renamed from drivers/chibios/analog.h)32
-rw-r--r--drivers/sensors/adns9800_srom_A6.h3078
-rw-r--r--drivers/sensors/pimoroni_trackball.c201
-rw-r--r--drivers/sensors/pimoroni_trackball.h37
-rw-r--r--drivers/sensors/pmw3360.c271
-rw-r--r--drivers/sensors/pmw3360.h85
-rw-r--r--drivers/sensors/pmw3360_firmware.h300
-rw-r--r--drivers/serial.h46
81 files changed, 5753 insertions, 9750 deletions
diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c
deleted file mode 100644
index 8d299ffdb9..0000000000
--- a/drivers/avr/analog.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/* Copyright 2015 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 <avr/io.h>
-#include <avr/pgmspace.h>
-#include <stdint.h>
-#include "analog.h"
-
-static uint8_t aref = ADC_REF_POWER;
-
-void analogReference(uint8_t mode) { aref = mode & (_BV(REFS1) | _BV(REFS0)); }
-
-// Arduino compatible pin input
-int16_t analogRead(uint8_t pin) {
-#if defined(__AVR_ATmega32U4__)
- // clang-format off
- static const uint8_t PROGMEM pin_to_mux[] = {
- //A0 A1 A2 A3 A4 A5
- //F7 F6 F5 F4 F1 F0
- 0x07, 0x06, 0x05, 0x04, 0x01, 0x00,
- //A6 A7 A8 A9 A10 A11
- //D4 D7 B4 B5 B6 D6
- 0x20, 0x22, 0x23, 0x24, 0x25, 0x21
- };
- // clang-format on
- if (pin >= 12) return 0;
- return adc_read(pgm_read_byte(pin_to_mux + pin));
-#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
- if (pin >= 8) return 0;
- return adc_read(pin);
-#else
- return 0;
-#endif
-}
-
-int16_t analogReadPin(pin_t pin) { return adc_read(pinToMux(pin)); }
-
-uint8_t pinToMux(pin_t pin) {
- switch (pin) {
- // clang-format off
-#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
- case F0: return 0; // ADC0
- case F1: return _BV(MUX0); // ADC1
- case F2: return _BV(MUX1); // ADC2
- case F3: return _BV(MUX1) | _BV(MUX0); // ADC3
- case F4: return _BV(MUX2); // ADC4
- case F5: return _BV(MUX2) | _BV(MUX0); // ADC5
- case F6: return _BV(MUX2) | _BV(MUX1); // ADC6
- case F7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7
- default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V
-#elif defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)
- case F0: return 0; // ADC0
- case F1: return _BV(MUX0); // ADC1
- case F4: return _BV(MUX2); // ADC4
- case F5: return _BV(MUX2) | _BV(MUX0); // ADC5
- case F6: return _BV(MUX2) | _BV(MUX1); // ADC6
- case F7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7
- case D4: return _BV(MUX5); // ADC8
- case D6: return _BV(MUX5) | _BV(MUX0); // ADC9
- case D7: return _BV(MUX5) | _BV(MUX1); // ADC10
- case B4: return _BV(MUX5) | _BV(MUX1) | _BV(MUX0); // ADC11
- case B5: return _BV(MUX5) | _BV(MUX2); // ADC12
- case B6: return _BV(MUX5) | _BV(MUX2) | _BV(MUX0); // ADC13
- default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V
-#elif defined(__AVR_ATmega32A__)
- case A0: return 0; // ADC0
- case A1: return _BV(MUX0); // ADC1
- case A2: return _BV(MUX1); // ADC2
- case A3: return _BV(MUX1) | _BV(MUX0); // ADC3
- case A4: return _BV(MUX2); // ADC4
- case A5: return _BV(MUX2) | _BV(MUX0); // ADC5
- case A6: return _BV(MUX2) | _BV(MUX1); // ADC6
- case A7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7
- default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V
-#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
- case C0: return 0; // ADC0
- case C1: return _BV(MUX0); // ADC1
- case C2: return _BV(MUX1); // ADC2
- case C3: return _BV(MUX1) | _BV(MUX0); // ADC3
- case C4: return _BV(MUX2); // ADC4
- case C5: return _BV(MUX2) | _BV(MUX0); // ADC5
- // ADC7:6 not present in DIP package and not shared by GPIO pins
- default: return _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V
-#endif
- // clang-format on
- }
- return 0;
-}
-
-int16_t adc_read(uint8_t mux) {
- uint16_t low;
-
- // Enable ADC and configure prescaler
- ADCSRA = _BV(ADEN) | ADC_PRESCALER;
-
-#if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)
- // High speed mode and ADC8-13
- ADCSRB = _BV(ADHSM) | (mux & _BV(MUX5));
-#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
- // High speed mode only
- ADCSRB = _BV(ADHSM);
-#endif
-
- // Configure mux input
-#if defined(MUX4)
- ADMUX = aref | (mux & (_BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0)));
-#else
- ADMUX = aref | (mux & (_BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0)));
-#endif
-
- // Start the conversion
- ADCSRA |= _BV(ADSC);
- // Wait for result
- while (ADCSRA & _BV(ADSC))
- ;
- // Must read LSB first
- low = ADCL;
- // Must read MSB only once!
- low |= (ADCH << 8);
-
- // turn off the ADC
- ADCSRA &= ~(1 << ADEN);
-
- return low;
-}
diff --git a/drivers/avr/analog.h b/drivers/avr/analog.h
deleted file mode 100644
index 058882450d..0000000000
--- a/drivers/avr/analog.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright 2015 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 <stdint.h>
-#include "quantum.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-void analogReference(uint8_t mode);
-int16_t analogRead(uint8_t pin);
-
-int16_t analogReadPin(pin_t pin);
-uint8_t pinToMux(pin_t pin);
-
-int16_t adc_read(uint8_t mux);
-#ifdef __cplusplus
-}
-#endif
-
-#define ADC_REF_EXTERNAL 0 // AREF, Internal Vref turned off
-#define ADC_REF_POWER _BV(REFS0) // AVCC with external capacitor on AREF pin
-#define ADC_REF_INTERNAL (_BV(REFS1) | _BV(REFS0)) // Internal 2.56V Voltage Reference with external capacitor on AREF pin (1.1V for 328P)
-
-// These prescaler values are for high speed mode, ADHSM = 1
-#if F_CPU == 16000000L || F_CPU == 12000000L
-# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS1)) // /64
-#elif F_CPU == 8000000L
-# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS0)) // /32
-#elif F_CPU == 4000000L
-# define ADC_PRESCALER (_BV(ADPS2)) // /16
-#elif F_CPU == 2000000L
-# define ADC_PRESCALER (_BV(ADPS1) | _BV(ADPS0)) // /8
-#elif F_CPU == 1000000L
-# define ADC_PRESCALER _BV(ADPS1) // /4
-#else
-# define ADC_PRESCALER _BV(ADPS0) // /2
-#endif
diff --git a/drivers/avr/apa102.c b/drivers/avr/apa102.c
deleted file mode 100644
index 740acb5739..0000000000
--- a/drivers/avr/apa102.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * APA102 lib V1.0a
- *
- * Controls APA102 RGB-LEDs
- * Author: Mikkel (Duckle29 on GitHub)
- *
- * Dec 22th, 2017 v1.0a Initial Version
- *
- * 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 "apa102.h"
-#include <avr/interrupt.h>
-#include <avr/io.h>
-#include <util/delay.h>
-#include "debug.h"
-
-// Setleds for standard RGB
-void inline apa102_setleds(LED_TYPE *ledarray, uint16_t leds) { apa102_setleds_pin(ledarray, leds, _BV(RGB_DI_PIN & 0xF), _BV(RGB_CLK_PIN & 0xF)); }
-
-void static inline apa102_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask_DI, uint8_t pinmask_CLK) {
- setPinOutput(RGB_DI_PIN);
- setPinOutput(RGB_CLK_PIN);
-
- apa102_send_array((uint8_t *)ledarray, leds)
-}
-
-void apa102_send_array(uint8_t *data, uint16_t leds) { // Data is struct of 3 bytes. RGB - leds is number of leds in data
- apa102_start_frame();
- while (leds--) {
- apa102_send_frame(0xFF000000 | (data->b << 16) | (data->g << 8) | data->r);
- data++;
- }
- apa102_end_frame(leds);
-}
-
-void apa102_send_frame(uint32_t frame) {
- for (uint32_t i = 0xFF; i > 0;) {
- apa102_send_byte(frame & i);
- i = i << 8;
- }
-}
-
-void apa102_start_frame() { apa102_send_frame(0); }
-
-void apa102_end_frame(uint16_t leds) {
- // This function has been taken from: https://github.com/pololu/apa102-arduino/blob/master/APA102.h
- // and adapted. The code is MIT licensed. I think thats compatible?
-
- // We need to send some more bytes to ensure that all the LEDs in the
- // chain see their new color and start displaying it.
- //
- // The data stream seen by the last LED in the chain will be delayed by
- // (count - 1) clock edges, because each LED before it inverts the clock
- // line and delays the data by one clock edge. Therefore, to make sure
- // the last LED actually receives the data we wrote, the number of extra
- // edges we send at the end of the frame must be at least (count - 1).
- // For the APA102C, that is sufficient.
- //
- // The SK9822 only updates after it sees 32 zero bits followed by one more
- // rising edge. To avoid having the update time depend on the color of
- // the last LED, we send a dummy 0xFF byte. (Unfortunately, this means
- // that partial updates of the beginning of an LED strip are not possible;
- // the LED after the last one you are trying to update will be black.)
- // After that, to ensure that the last LED in the chain sees 32 zero bits
- // and a rising edge, we need to send at least 65 + (count - 1) edges. It
- // is sufficent and simpler to just send (5 + count/16) bytes of zeros.
- //
- // We are ignoring the specification for the end frame in the APA102/SK9822
- // datasheets because it does not actually ensure that all the LEDs will
- // start displaying their new colors right away.
-
- apa102_send_byte(0xFF);
- for (uint16_t i = 0; i < 5 + leds / 16; i++) {
- apa102_send_byte(0);
- }
-}
-
-void apa102_send_byte(uint8_t byte) {
- uint8_t i;
- for (i = 0; i < 8; i++) {
- writePin(RGB_DI_PIN, !!(byte & (1 << (7 - i))));
- writePinHigh(RGB_CLK_PIN);
- }
-}
diff --git a/drivers/avr/glcdfont.c b/drivers/avr/glcdfont.c
deleted file mode 100644
index 5e763b054f..0000000000
--- a/drivers/avr/glcdfont.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0.
-// See gfxfont.h for newer custom bitmap font info.
-
-#include "progmem.h"
-
-// Standard ASCII 5x7 font
-
-static const unsigned char font[] PROGMEM = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, 0x18, 0x3C, 0x18, 0x00, 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, 0x18, 0x24, 0x18, 0x00, 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x26, 0x29, 0x79, 0x29, 0x26, 0x40, 0x7F, 0x05, 0x05, 0x07, 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, 0x66, 0x89, 0x95, 0x6A, 0x60, 0x60, 0x60, 0x60, 0x60, 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x08, 0x04, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x20, 0x10, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
- 0x30, 0x38, 0x3E, 0x38, 0x30, 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62, 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x80, 0x70, 0x30, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x60, 0x60, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x72, 0x49, 0x49, 0x49, 0x46, 0x21, 0x41, 0x49, 0x4D, 0x33, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x27, 0x45, 0x45, 0x45, 0x39, 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x41, 0x21, 0x11, 0x09, 0x07, 0x36, 0x49, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00,
- 0x00, 0x08, 0x14, 0x22, 0x41, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59, 0x09, 0x06, 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x3E, 0x41, 0x41, 0x51, 0x73, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x41, 0x7F, 0x41, 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x26, 0x49, 0x49, 0x49, 0x32, 0x03, 0x01, 0x7F, 0x01, 0x03, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x63, 0x14, 0x08, 0x14, 0x63, 0x03, 0x04, 0x78, 0x04, 0x03,
- 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x41, 0x7F, 0x04, 0x02, 0x01, 0x02, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x03, 0x07, 0x08, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x7F, 0x28, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x28, 0x38, 0x44, 0x44, 0x28, 0x7F, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x08, 0x7E, 0x09, 0x02, 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x20, 0x40, 0x40, 0x3D, 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x7C, 0x04, 0x78, 0x04, 0x78, 0x7C, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xFC, 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x18, 0xFC, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x54, 0x24, 0x04, 0x04, 0x3F, 0x44, 0x24, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x3C, 0x40, 0x30, 0x40, 0x3C,
- 0x44, 0x28, 0x10, 0x28, 0x44, 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x1E, 0xA1, 0xA1, 0x61, 0x12, 0x3A, 0x40, 0x40, 0x20, 0x7A, 0x38, 0x54, 0x54, 0x55, 0x59, 0x21, 0x55, 0x55, 0x79, 0x41, 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
- 0x21, 0x55, 0x54, 0x78, 0x40, 0x20, 0x54, 0x55, 0x79, 0x40, 0x0C, 0x1E, 0x52, 0x72, 0x12, 0x39, 0x55, 0x55, 0x55, 0x59, 0x39, 0x54, 0x54, 0x54, 0x59, 0x39, 0x55, 0x54, 0x54, 0x58, 0x00, 0x00, 0x45, 0x7C, 0x41, 0x00, 0x02, 0x45, 0x7D, 0x42, 0x00, 0x01, 0x45, 0x7C, 0x40, 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
- 0xF0, 0x28, 0x25, 0x28, 0xF0, 0x7C, 0x54, 0x55, 0x45, 0x00, 0x20, 0x54, 0x54, 0x7C, 0x54, 0x7C, 0x0A, 0x09, 0x7F, 0x49, 0x32, 0x49, 0x49, 0x49, 0x32, 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
- 0x32, 0x4A, 0x48, 0x48, 0x30, 0x3A, 0x41, 0x41, 0x21, 0x7A, 0x3A, 0x42, 0x40, 0x20, 0x78, 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
- 0x3D, 0x40, 0x40, 0x40, 0x3D, 0x3C, 0x24, 0xFF, 0x24, 0x24, 0x48, 0x7E, 0x49, 0x43, 0x66, 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 0xFF, 0x09, 0x29, 0xF6, 0x20, 0xC0, 0x88, 0x7E, 0x09, 0x03, 0x20, 0x54, 0x54, 0x79, 0x41, 0x00, 0x00, 0x44, 0x7D, 0x41, 0x30, 0x48, 0x48, 0x4A, 0x32, 0x38, 0x40, 0x40, 0x22, 0x7A, 0x00, 0x7A, 0x0A, 0x0A, 0x72, 0x7D, 0x0D, 0x19, 0x31, 0x7D, 0x26, 0x29, 0x29, 0x2F, 0x28, 0x26, 0x29, 0x29, 0x29, 0x26, 0x30, 0x48, 0x4D, 0x40, 0x20, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 0x2F, 0x10, 0x28, 0x34, 0xFA, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x08, 0x14, 0x2A, 0x14, 0x22, 0x22, 0x14, 0x2A, 0x14, 0x08, 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
- 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
- 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0x10, 0x10, 0x10, 0xFF, 0x00, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x10, 0x10, 0xFF, 0x00, 0xFF, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x10, 0x10, 0x1F, 0x10, 0x1F, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x10, 0x10, 0x10, 0x10, 0xF0, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x17, 0x14, 0x10, 0x10, 0x1F, 0x10, 0x1F,
- 0x14, 0x14, 0x14, 0xF4, 0x14, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x00, 0x00, 0x1F, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, 0xF0, 0x10, 0xF0, 0x10, 0x10, 0xFF, 0x10, 0xFF, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x38, 0x44, 0x44, 0x38, 0x44, 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
- 0x7E, 0x02, 0x02, 0x06, 0x06, 0x02, 0x7E, 0x02, 0x7E, 0x02, 0x63, 0x55, 0x49, 0x41, 0x63, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x40, 0x7E, 0x20, 0x1E, 0x20, 0x06, 0x02, 0x7E, 0x02, 0x02, 0x99, 0xA5, 0xE7, 0xA5, 0x99, 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 0x4C, 0x72, 0x01, 0x72, 0x4C, 0x30, 0x4A, 0x4D, 0x4D, 0x30, 0x30, 0x48, 0x78, 0x48, 0x30, 0xBC, 0x62, 0x5A, 0x46, 0x3D, 0x3E, 0x49, 0x49, 0x49, 0x00, 0x7E, 0x01, 0x01, 0x01, 0x7E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x44, 0x44, 0x5F, 0x44, 0x44, 0x40, 0x51, 0x4A, 0x44, 0x40, 0x40, 0x44, 0x4A, 0x51, 0x40, 0x00, 0x00, 0xFF, 0x01, 0x03, 0xE0, 0x80, 0xFF, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x6B, 0x08, 0x36, 0x12, 0x36, 0x24, 0x36, 0x06, 0x0F, 0x09, 0x0F, 0x06, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x30, 0x40, 0xFF, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x01, 0x1E, 0x00, 0x19, 0x1D, 0x17, 0x12, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
-};
diff --git a/drivers/avr/hd44780.c b/drivers/avr/hd44780.c
deleted file mode 100644
index f71069dece..0000000000
--- a/drivers/avr/hd44780.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/****************************************************************************
- Title: HD44780U LCD library
- Author: Peter Fleury <pfleury@gmx.ch> http://tinyurl.com/peterfleury
- License: GNU General Public License Version 3
- File: $Id: lcd.c,v 1.15.2.2 2015/01/17 12:16:05 peter Exp $
- Software: AVR-GCC 3.3
- Target: any AVR device, memory mapped mode only for AT90S4414/8515/Mega
-
- DESCRIPTION
- Basic routines for interfacing a HD44780U-based text lcd display
-
- Originally based on Volker Oth's lcd library,
- changed lcd_init(), added additional constants for lcd_command(),
- added 4-bit I/O mode, improved and optimized code.
-
- Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in
- 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported.
-
- Memory mapped mode compatible with Kanda STK200, but supports also
- generation of R/W signal through A8 address line.
-
- USAGE
- See the C include lcd.h file for a description of each function
-
-*****************************************************************************/
-#include <inttypes.h>
-#include <avr/io.h>
-#include <avr/pgmspace.h>
-#include <util/delay.h>
-#include "hd44780.h"
-
-/*
-** constants/macros
-*/
-#define DDR(x) (*(&x - 1)) /* address of data direction register of port x */
-#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
-/* on ATmega64/128 PINF is on port 0x00 and not 0x60 */
-# define PIN(x) (&PORTF == &(x) ? _SFR_IO8(0x00) : (*(&x - 2)))
-#else
-# define PIN(x) (*(&x - 2)) /* address of input register of port x */
-#endif
-
-#if LCD_IO_MODE
-# define lcd_e_delay() _delay_us(LCD_DELAY_ENABLE_PULSE)
-# define lcd_e_high() LCD_E_PORT |= _BV(LCD_E_PIN);
-# define lcd_e_low() LCD_E_PORT &= ~_BV(LCD_E_PIN);
-# define lcd_e_toggle() toggle_e()
-# define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN)
-# define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN)
-# define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN)
-# define lcd_rs_low() LCD_RS_PORT &= ~_BV(LCD_RS_PIN)
-#endif
-
-#if LCD_IO_MODE
-# if LCD_LINES == 1
-# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE
-# else
-# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES
-# endif
-#else
-# if LCD_LINES == 1
-# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE
-# else
-# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES
-# endif
-#endif
-
-#if LCD_CONTROLLER_KS0073
-# if LCD_LINES == 4
-
-# define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x2C /* |0|010|1100 4-bit mode, extension-bit RE = 1 */
-# define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x28 /* |0|010|1000 4-bit mode, extension-bit RE = 0 */
-# define KS0073_4LINES_MODE 0x09 /* |0|000|1001 4 lines mode */
-
-# endif
-#endif
-
-/*
-** function prototypes
-*/
-#if LCD_IO_MODE
-static void toggle_e(void);
-#endif
-
-/*
-** local functions
-*/
-
-/*************************************************************************
-delay for a minimum of <us> microseconds
-the number of loops is calculated at compile-time from MCU clock frequency
-*************************************************************************/
-#define delay(us) _delay_us(us)
-
-#if LCD_IO_MODE
-/* toggle Enable Pin to initiate write */
-static void toggle_e(void) {
- lcd_e_high();
- lcd_e_delay();
- lcd_e_low();
-}
-#endif
-
-/*************************************************************************
-Low-level function to write byte to LCD controller
-Input: data byte to write to LCD
- rs 1: write data
- 0: write instruction
-Returns: none
-*************************************************************************/
-#if LCD_IO_MODE
-static void lcd_write(uint8_t data, uint8_t rs) {
- unsigned char dataBits;
-
- if (rs) { /* write data (RS=1, RW=0) */
- lcd_rs_high();
- } else { /* write instruction (RS=0, RW=0) */
- lcd_rs_low();
- }
- lcd_rw_low(); /* RW=0 write mode */
-
- if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) {
- /* configure data pins as output */
- DDR(LCD_DATA0_PORT) |= 0x0F;
-
- /* output high nibble first */
- dataBits = LCD_DATA0_PORT & 0xF0;
- LCD_DATA0_PORT = dataBits | ((data >> 4) & 0x0F);
- lcd_e_toggle();
-
- /* output low nibble */
- LCD_DATA0_PORT = dataBits | (data & 0x0F);
- lcd_e_toggle();
-
- /* all data pins high (inactive) */
- LCD_DATA0_PORT = dataBits | 0x0F;
- } else {
- /* configure data pins as output */
- DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
- DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
- DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
- DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
-
- /* output high nibble first */
- LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);
- LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);
- LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);
- LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
- if (data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
- if (data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
- if (data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
- if (data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
- lcd_e_toggle();
-
- /* output low nibble */
- LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);
- LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);
- LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);
- LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
- if (data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
- if (data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
- if (data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
- if (data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
- lcd_e_toggle();
-
- /* all data pins high (inactive) */
- LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
- LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
- LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
- LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
- }
-}
-#else
-# define lcd_write(d, rs) \
- if (rs) \
- *(volatile uint8_t *)(LCD_IO_DATA) = d; \
- else \
- *(volatile uint8_t *)(LCD_IO_FUNCTION) = d;
-/* rs==0 -> write instruction to LCD_IO_FUNCTION */
-/* rs==1 -> write data to LCD_IO_DATA */
-#endif
-
-/*************************************************************************
-Low-level function to read byte from LCD controller
-Input: rs 1: read data
- 0: read busy flag / address counter
-Returns: byte read from LCD controller
-*************************************************************************/
-#if LCD_IO_MODE
-static uint8_t lcd_read(uint8_t rs) {
- uint8_t data;
-
- if (rs)
- lcd_rs_high(); /* RS=1: read data */
- else
- lcd_rs_low(); /* RS=0: read busy flag */
- lcd_rw_high(); /* RW=1 read mode */
-
- if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) {
- DDR(LCD_DATA0_PORT) &= 0xF0; /* configure data pins as input */
-
- lcd_e_high();
- lcd_e_delay();
- data = PIN(LCD_DATA0_PORT) << 4; /* read high nibble first */
- lcd_e_low();
-
- lcd_e_delay(); /* Enable 500ns low */
-
- lcd_e_high();
- lcd_e_delay();
- data |= PIN(LCD_DATA0_PORT) & 0x0F; /* read low nibble */
- lcd_e_low();
- } else {
- /* configure data pins as input */
- DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN);
- DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN);
- DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN);
- DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN);
-
- /* read high nibble first */
- lcd_e_high();
- lcd_e_delay();
- data = 0;
- if (PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN)) data |= 0x10;
- if (PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN)) data |= 0x20;
- if (PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN)) data |= 0x40;
- if (PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN)) data |= 0x80;
- lcd_e_low();
-
- lcd_e_delay(); /* Enable 500ns low */
-
- /* read low nibble */
- lcd_e_high();
- lcd_e_delay();
- if (PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN)) data |= 0x01;
- if (PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN)) data |= 0x02;
- if (PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN)) data |= 0x04;
- if (PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN)) data |= 0x08;
- lcd_e_low();
- }
- return data;
-}
-#else
-# define lcd_read(rs) (rs) ? *(volatile uint8_t *)(LCD_IO_DATA + LCD_IO_READ) : *(volatile uint8_t *)(LCD_IO_FUNCTION + LCD_IO_READ)
-/* rs==0 -> read instruction from LCD_IO_FUNCTION */
-/* rs==1 -> read data from LCD_IO_DATA */
-#endif
-
-/*************************************************************************
-loops while lcd is busy, returns address counter
-*************************************************************************/
-static uint8_t lcd_waitbusy(void)
-
-{
- register uint8_t c;
-
- /* wait until busy flag is cleared */
- while ((c = lcd_read(0)) & (1 << LCD_BUSY)) {
- }
-
- /* the address counter is updated 4us after the busy flag is cleared */
- delay(LCD_DELAY_BUSY_FLAG);
-
- /* now read the address counter */
- return (lcd_read(0)); // return address counter
-
-} /* lcd_waitbusy */
-
-/*************************************************************************
-Move cursor to the start of next line or to the first line if the cursor
-is already on the last line.
-*************************************************************************/
-static inline void lcd_newline(uint8_t pos) {
- register uint8_t addressCounter;
-
-#if LCD_LINES == 1
- addressCounter = 0;
-#endif
-#if LCD_LINES == 2
- if (pos < (LCD_START_LINE2))
- addressCounter = LCD_START_LINE2;
- else
- addressCounter = LCD_START_LINE1;
-#endif
-#if LCD_LINES == 4
-# if KS0073_4LINES_MODE
- if (pos < LCD_START_LINE2)
- addressCounter = LCD_START_LINE2;
- else if ((pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3))
- addressCounter = LCD_START_LINE3;
- else if ((pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4))
- addressCounter = LCD_START_LINE4;
- else
- addressCounter = LCD_START_LINE1;
-# else
- if (pos < LCD_START_LINE3)
- addressCounter = LCD_START_LINE2;
- else if ((pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4))
- addressCounter = LCD_START_LINE3;
- else if ((pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2))
- addressCounter = LCD_START_LINE4;
- else
- addressCounter = LCD_START_LINE1;
-# endif
-#endif
- lcd_command((1 << LCD_DDRAM) + addressCounter);
-
-} /* lcd_newline */
-
-/*
-** PUBLIC FUNCTIONS
-*/
-
-/*************************************************************************
-Send LCD controller instruction command
-Input: instruction to send to LCD controller, see HD44780 data sheet
-Returns: none
-*************************************************************************/
-void lcd_command(uint8_t cmd) {
- lcd_waitbusy();
- lcd_write(cmd, 0);
-}
-
-/*************************************************************************
-Send data byte to LCD controller
-Input: data to send to LCD controller, see HD44780 data sheet
-Returns: none
-*************************************************************************/
-void lcd_data(uint8_t data) {
- lcd_waitbusy();
- lcd_write(data, 1);
-}
-
-/*************************************************************************
-Set cursor to specified position
-Input: x horizontal position (0: left most position)
- y vertical position (0: first line)
-Returns: none
-*************************************************************************/
-void lcd_gotoxy(uint8_t x, uint8_t y) {
-#if LCD_LINES == 1
- lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
-#endif
-#if LCD_LINES == 2
- if (y == 0)
- lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
- else
- lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
-#endif
-#if LCD_LINES == 4
- if (y == 0)
- lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
- else if (y == 1)
- lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
- else if (y == 2)
- lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x);
- else /* y==3 */
- lcd_command((1 << LCD_DDRAM) + LCD_START_LINE4 + x);
-#endif
-
-} /* lcd_gotoxy */
-
-/*************************************************************************
-*************************************************************************/
-int lcd_getxy(void) { return lcd_waitbusy(); }
-
-/*************************************************************************
-Clear display and set cursor to home position
-*************************************************************************/
-void lcd_clrscr(void) { lcd_command(1 << LCD_CLR); }
-
-/*************************************************************************
-Set cursor to home position
-*************************************************************************/
-void lcd_home(void) { lcd_command(1 << LCD_HOME); }
-
-/*************************************************************************
-Display character at current cursor position
-Input: character to be displayed
-Returns: none
-*************************************************************************/
-void lcd_putc(char c) {
- uint8_t pos;
-
- pos = lcd_waitbusy(); // read busy-flag and address counter
- if (c == '\n') {
- lcd_newline(pos);
- } else {
-#if LCD_WRAP_LINES == 1
-# if LCD_LINES == 1
- if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) {
- lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0);
- }
-# elif LCD_LINES == 2
- if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) {
- lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2, 0);
- } else if (pos == LCD_START_LINE2 + LCD_DISP_LENGTH) {
- lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0);
- }
-# elif LCD_LINES == 4
- if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) {
- lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2, 0);
- } else if (pos == LCD_START_LINE2 + LCD_DISP_LENGTH) {
- lcd_write((1 << LCD_DDRAM) + LCD_START_LINE3, 0);
- } else if (pos == LCD_START_LINE3 + LCD_DISP_LENGTH) {
- lcd_write((1 << LCD_DDRAM) + LCD_START_LINE4, 0);
- } else if (pos == LCD_START_LINE4 + LCD_DISP_LENGTH) {
- lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0);
- }
-# endif
- lcd_waitbusy();
-#endif
- lcd_write(c, 1);
- }
-
-} /* lcd_putc */
-
-/*************************************************************************
-Display string without auto linefeed
-Input: string to be displayed
-Returns: none
-*************************************************************************/
-void lcd_puts(const char *s)
-/* print string on lcd (no auto linefeed) */
-{
- register char c;
-
- while ((c = *s++)) {
- lcd_putc(c);
- }
-
-} /* lcd_puts */
-
-/*************************************************************************
-Display string from program memory without auto linefeed
-Input: string from program memory be be displayed
-Returns: none
-*************************************************************************/
-void lcd_puts_p(const char *progmem_s)
-/* print string from program memory on lcd (no auto linefeed) */
-{
- register char c;
-
- while ((c = pgm_read_byte(progmem_s++))) {
- lcd_putc(c);
- }
-
-} /* lcd_puts_p */
-
-/*************************************************************************
-Initialize display and select type of cursor
-Input: dispAttr LCD_DISP_OFF display off
- LCD_DISP_ON display on, cursor off
- LCD_DISP_ON_CURSOR display on, cursor on
- LCD_DISP_CURSOR_BLINK display on, cursor on flashing
-Returns: none
-*************************************************************************/
-void lcd_init(uint8_t dispAttr) {
-#if LCD_IO_MODE
- /*
- * Initialize LCD to 4 bit I/O mode
- */
-
- if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (&LCD_RS_PORT == &LCD_DATA0_PORT) && (&LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) && (LCD_RS_PIN == 4) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6)) {
- /* configure all port bits as output (all LCD lines on same port) */
- DDR(LCD_DATA0_PORT) |= 0x7F;
- } else if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) {
- /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */
- DDR(LCD_DATA0_PORT) |= 0x0F;
- DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN);
- DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN);
- DDR(LCD_E_PORT) |= _BV(LCD_E_PIN);
- } else {
- /* configure all port bits as output (LCD data and control lines on different ports */
- DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN);
- DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN);
- DDR(LCD_E_PORT) |= _BV(LCD_E_PIN);
- DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
- DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
- DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
- DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
- }
- delay(LCD_DELAY_BOOTUP); /* wait 16ms or more after power-on */
-
- /* initial write to lcd is 8bit */
- LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); // LCD_FUNCTION>>4;
- LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // LCD_FUNCTION_8BIT>>4;
- lcd_e_toggle();
- delay(LCD_DELAY_INIT); /* delay, busy flag can't be checked here */
-
- /* repeat last command */
- lcd_e_toggle();
- delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */
-
- /* repeat last command a third time */
- lcd_e_toggle();
- delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */
-
- /* now configure for 4bit mode */
- LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4
- lcd_e_toggle();
- delay(LCD_DELAY_INIT_4BIT); /* some displays need this additional delay */
-
- /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */
-#else
- /*
- * Initialize LCD to 8 bit memory mapped mode
- */
-
- /* enable external SRAM (memory mapped lcd) and one wait state */
- MCUCR = _BV(SRE) | _BV(SRW);
-
- /* reset LCD */
- delay(LCD_DELAY_BOOTUP); /* wait 16ms after power-on */
- lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */
- delay(LCD_DELAY_INIT); /* wait 5ms */
- lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */
- delay(LCD_DELAY_INIT_REP); /* wait 64us */
- lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */
- delay(LCD_DELAY_INIT_REP); /* wait 64us */
-#endif
-
-#if KS0073_4LINES_MODE
- /* Display with KS0073 controller requires special commands for enabling 4 line mode */
- lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON);
- lcd_command(KS0073_4LINES_MODE);
- lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF);
-#else
- lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */
-#endif
- lcd_command(LCD_DISP_OFF); /* display off */
- lcd_clrscr(); /* display clear */
- lcd_command(LCD_MODE_DEFAULT); /* set entry mode */
- lcd_command(dispAttr); /* display/cursor control */
-
-} /* lcd_init */
diff --git a/drivers/avr/hd44780.h b/drivers/avr/hd44780.h
deleted file mode 100644
index 08e60f8a44..0000000000
--- a/drivers/avr/hd44780.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/*************************************************************************
- Title : C include file for the HD44780U LCD library (lcd.c)
- Author: Peter Fleury <pfleury@gmx.ch> http://tinyurl.com/peterfleury
- License: GNU General Public License Version 3
- File: $Id: lcd.h,v 1.14.2.4 2015/01/20 17:16:07 peter Exp $
- Software: AVR-GCC 4.x
- Hardware: any AVR device, memory mapped mode only for AVR with
- memory mapped interface (AT90S8515/ATmega8515/ATmega128)
-***************************************************************************/
-
-/**
- @mainpage
- Collection of libraries for AVR-GCC
- @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury
- @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3
-
- @file
- @defgroup pfleury_lcd LCD library <lcd.h>
- @code #include <lcd.h> @endcode
-
- @brief Basic routines for interfacing a HD44780U-based character LCD display
-
- LCD character displays can be found in many devices, like espresso machines, laser printers.
- The Hitachi HD44780 controller and its compatible controllers like Samsung KS0066U have become an industry standard for these types of displays.
-
- This library allows easy interfacing with a HD44780 compatible display and can be
- operated in memory mapped mode (LCD_IO_MODE defined as 0 in the include file lcd.h.) or in
- 4-bit IO port mode (LCD_IO_MODE defined as 1). 8-bit IO port mode is not supported.
-
- Memory mapped mode is compatible with old Kanda STK200 starter kit, but also supports
- generation of R/W signal through A8 address line.
-
- @see The chapter <a href=" http://homepage.hispeed.ch/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a>
- on my home page, which shows example circuits how to connect an LCD to an AVR controller.
-
- @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury
-
- @version 2.0
-
- @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3
-
-*/
-
-#pragma once
-
-#include <inttypes.h>
-#include <avr/pgmspace.h>
-
-#if (__GNUC__ * 100 + __GNUC_MINOR__) < 405
-# error "This library requires AVR-GCC 4.5 or later, update to newer AVR-GCC compiler !"
-#endif
-
-/**@{*/
-
-/*
- * LCD and target specific definitions below can be defined in a separate include file with name lcd_definitions.h instead modifying this file
- * by adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile
- * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h
- */
-#ifdef _LCD_DEFINITIONS_FILE
-# include "lcd_definitions.h"
-#endif
-
-/**
- * @name Definition for LCD controller type
- * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller.
- */
-#ifndef LCD_CONTROLLER_KS0073
-# define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */
-#endif
-
-/**
- * @name Definitions for Display Size
- * Change these definitions to adapt setting to your display
- *
- * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by
- * adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile.
- * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h
- *
- */
-#ifndef LCD_LINES
-# define LCD_LINES 2 /**< number of visible lines of the display */
-#endif
-#ifndef LCD_DISP_LENGTH
-# define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */
-#endif
-#ifndef LCD_LINE_LENGTH
-# define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */
-#endif
-#ifndef LCD_START_LINE1
-# define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */
-#endif
-#ifndef LCD_START_LINE2
-# define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */
-#endif
-#ifndef LCD_START_LINE3
-# define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */
-#endif
-#ifndef LCD_START_LINE4
-# define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */
-#endif
-#ifndef LCD_WRAP_LINES
-# define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */
-#endif
-
-/**
- * @name Definitions for 4-bit IO mode
- *
- * The four LCD data lines and the three control lines RS, RW, E can be on the
- * same port or on different ports.
- * Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on
- * different ports.
- *
- * Normally the four data lines should be mapped to bit 0..3 on one port, but it
- * is possible to connect these data lines in different order or even on different
- * ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions.
- *
- * Adjust these definitions to your target.\n
- * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by
- * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile.
- * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h
- *
- */
-#define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */
-
-#if LCD_IO_MODE
-
-# ifndef LCD_PORT
-# define LCD_PORT PORTA /**< port for the LCD lines */
-# endif
-# ifndef LCD_DATA0_PORT
-# define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */
-# endif
-# ifndef LCD_DATA1_PORT
-# define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */
-# endif
-# ifndef LCD_DATA2_PORT
-# define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */
-# endif
-# ifndef LCD_DATA3_PORT
-# define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */
-# endif
-# ifndef LCD_DATA0_PIN
-# define LCD_DATA0_PIN 4 /**< pin for 4bit data bit 0 */
-# endif
-# ifndef LCD_DATA1_PIN
-# define LCD_DATA1_PIN 5 /**< pin for 4bit data bit 1 */
-# endif
-# ifndef LCD_DATA2_PIN
-# define LCD_DATA2_PIN 6 /**< pin for 4bit data bit 2 */
-# endif
-# ifndef LCD_DATA3_PIN
-# define LCD_DATA3_PIN 7 /**< pin for 4bit data bit 3 */
-# endif
-# ifndef LCD_RS_PORT
-# define LCD_RS_PORT LCD_PORT /**< port for RS line */
-# endif
-# ifndef LCD_RS_PIN
-# define LCD_RS_PIN 3 /**< pin for RS line */
-# endif
-# ifndef LCD_RW_PORT
-# define LCD_RW_PORT LCD_PORT /**< port for RW line */
-# endif
-# ifndef LCD_RW_PIN
-# define LCD_RW_PIN 2 /**< pin for RW line */
-# endif
-# ifndef LCD_E_PORT
-# define LCD_E_PORT LCD_PORT /**< port for Enable line */
-# endif
-# ifndef LCD_E_PIN
-# define LCD_E_PIN 1 /**< pin for Enable line */
-# endif
-
-#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__)
-/*
- * memory mapped mode is only supported when the device has an external data memory interface
- */
-# define LCD_IO_DATA 0xC000 /* A15=E=1, A14=RS=1 */
-# define LCD_IO_FUNCTION 0x8000 /* A15=E=1, A14=RS=0 */
-# define LCD_IO_READ 0x0100 /* A8 =R/W=1 (R/W: 1=Read, 0=Write */
-
-#else
-# error "external data memory interface not available for this device, use 4-bit IO port mode"
-
-#endif
-
-/**
- * @name Definitions of delays
- * Used to calculate delay timers.
- * Adapt the F_CPU define in the Makefile to the clock frequency in Hz of your target
- *
- * These delay times can be adjusted, if some displays require different delays.\n
- * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by
- * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile.
- * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h
- */
-#ifndef LCD_DELAY_BOOTUP
-# define LCD_DELAY_BOOTUP 16000 /**< delay in micro seconds after power-on */
-#endif
-#ifndef LCD_DELAY_INIT
-# define LCD_DELAY_INIT 5000 /**< delay in micro seconds after initialization command sent */
-#endif
-#ifndef LCD_DELAY_INIT_REP
-# define LCD_DELAY_INIT_REP 64 /**< delay in micro seconds after initialization command repeated */
-#endif
-#ifndef LCD_DELAY_INIT_4BIT
-# define LCD_DELAY_INIT_4BIT 64 /**< delay in micro seconds after setting 4-bit mode */
-#endif
-#ifndef LCD_DELAY_BUSY_FLAG
-# define LCD_DELAY_BUSY_FLAG 4 /**< time in micro seconds the address counter is updated after busy flag is cleared */
-#endif
-#ifndef LCD_DELAY_ENABLE_PULSE
-# define LCD_DELAY_ENABLE_PULSE 1 /**< enable signal pulse width in micro seconds */
-#endif
-
-/**
- * @name Definitions for LCD command instructions
- * The constants define the various LCD controller instructions which can be passed to the
- * function lcd_command(), see HD44780 data sheet for a complete description.
- */
-
-/* instruction register bit positions, see HD44780U data sheet */
-#define LCD_CLR 0 /* DB0: clear display */
-#define LCD_HOME 1 /* DB1: return to home position */
-#define LCD_ENTRY_MODE 2 /* DB2: set entry mode */
-#define LCD_ENTRY_INC 1 /* DB1: 1=increment, 0=decrement */
-#define LCD_ENTRY_SHIFT 0 /* DB2: 1=display shift on */
-#define LCD_ON 3 /* DB3: turn lcd/cursor on */
-#define LCD_ON_DISPLAY 2 /* DB2: turn display on */
-#define LCD_ON_CURSOR 1 /* DB1: turn cursor on */
-#define LCD_ON_BLINK 0 /* DB0: blinking cursor ? */
-#define LCD_MOVE 4 /* DB4: move cursor/display */
-#define LCD_MOVE_DISP 3 /* DB3: move display (0-> cursor) ? */
-#define LCD_MOVE_RIGHT 2 /* DB2: move right (0-> left) ? */
-#define LCD_FUNCTION 5 /* DB5: function set */
-#define LCD_FUNCTION_8BIT 4 /* DB4: set 8BIT mode (0->4BIT mode) */
-#define LCD_FUNCTION_2LINES 3 /* DB3: two lines (0->one line) */
-#define LCD_FUNCTION_10DOTS 2 /* DB2: 5x10 font (0->5x7 font) */
-#define LCD_CGRAM 6 /* DB6: set CG RAM address */
-#define LCD_DDRAM 7 /* DB7: set DD RAM address */
-#define LCD_BUSY 7 /* DB7: LCD is busy */
-
-/* set entry mode: display shift on/off, dec/inc cursor move direction */
-#define LCD_ENTRY_DEC 0x04 /* display shift off, dec cursor move dir */
-#define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on, dec cursor move dir */
-#define LCD_ENTRY_INC_ 0x06 /* display shift off, inc cursor move dir */
-#define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on, inc cursor move dir */
-
-/* display on/off, cursor on/off, blinking char at cursor position */
-#define LCD_DISP_OFF 0x08 /* display off */
-#define LCD_DISP_ON 0x0C /* display on, cursor off */
-#define LCD_DISP_ON_BLINK 0x0D /* display on, cursor off, blink char */
-#define LCD_DISP_ON_CURSOR 0x0E /* display on, cursor on */
-#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */
-
-/* move cursor/shift display */
-#define LCD_MOVE_CURSOR_LEFT 0x10 /* move cursor left (decrement) */
-#define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment) */
-#define LCD_MOVE_DISP_LEFT 0x18 /* shift display left */
-#define LCD_MOVE_DISP_RIGHT 0x1C /* shift display right */
-
-/* function set: set interface data length and number of display lines */
-#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */
-#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */
-#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */
-#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */
-
-#define LCD_MODE_DEFAULT ((1 << LCD_ENTRY_MODE) | (1 << LCD_ENTRY_INC))
-
-/**
- * @name Functions
- */
-
-/**
- @brief Initialize display and select type of cursor
- @param dispAttr \b LCD_DISP_OFF display off\n
- \b LCD_DISP_ON display on, cursor off\n
- \b LCD_DISP_ON_CURSOR display on, cursor on\n
- \b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing
- @return none
-*/
-extern void lcd_init(uint8_t dispAttr);
-
-/**
- @brief Clear display and set cursor to home position
- @return none
-*/
-extern void lcd_clrscr(void);
-
-/**
- @brief Set cursor to home position
- @return none
-*/
-extern void lcd_home(void);
-
-/**
- @brief Set cursor to specified position
-
- @param x horizontal position\n (0: left most position)
- @param y vertical position\n (0: first line)
- @return none
-*/
-extern void lcd_gotoxy(uint8_t x, uint8_t y);
-
-/**
- @brief Display character at current cursor position
- @param c character to be displayed
- @return none
-*/
-extern void lcd_putc(char c);
-
-/**
- @brief Display string without auto linefeed
- @param s string to be displayed
- @return none
-*/
-extern void lcd_puts(const char *s);
-
-/**
- @brief Display string from program memory without auto linefeed
- @param progmem_s string from program memory be be displayed
- @return none
- @see lcd_puts_P
-*/
-extern void lcd_puts_p(const char *progmem_s);
-
-/**
- @brief Send LCD controller instruction command
- @param cmd instruction to send to LCD controller, see HD44780 data sheet
- @return none
-*/
-extern void lcd_command(uint8_t cmd);
-
-/**
- @brief Send data byte to LCD controller
-
- Similar to lcd_putc(), but without interpreting LF
- @param data byte to send to LCD controller, see HD44780 data sheet
- @return none
-*/
-extern void lcd_data(uint8_t data);
-
-/**
- @brief macros for automatically storing string constant in program memory
-*/
-#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))
-
-/**@}*/
diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c
deleted file mode 100644
index b1e4885298..0000000000
--- a/drivers/avr/i2c_master.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/* Copyright (C) 2019 Elia Ritterbusch
- +
- * 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 3 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 <https://www.gnu.org/licenses/>.
- */
-/* Library made by: g4lvanix
- * GitHub repository: https://github.com/g4lvanix/I2C-master-lib
- */
-
-#include <avr/io.h>
-#include <util/twi.h>
-
-#include "i2c_master.h"
-#include "timer.h"
-#include "wait.h"
-
-#ifndef F_SCL
-# define F_SCL 400000UL // SCL frequency
-#endif
-
-#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
-
-void i2c_init(void) {
- TWSR = 0; /* no prescaler */
- TWBR = (uint8_t)TWBR_val;
-
-#ifdef __AVR_ATmega32A__
- // set pull-up resistors on I2C bus pins
- PORTC |= 0b11;
-
- // enable TWI (two-wire interface)
- TWCR |= (1 << TWEN);
-
- // enable TWI interrupt and slave address ACK
- TWCR |= (1 << TWIE);
- TWCR |= (1 << TWEA);
-#endif
-}
-
-i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
- // reset TWI control register
- TWCR = 0;
- // transmit START condition
- TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
-
- uint16_t timeout_timer = timer_read();
- while (!(TWCR & (1 << TWINT))) {
- if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
- return I2C_STATUS_TIMEOUT;
- }
- }
-
- // check if the start condition was successfully transmitted
- if (((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)) {
- return I2C_STATUS_ERROR;
- }
-
- // load slave address into data register
- TWDR = address;
- // start transmission of address
- TWCR = (1 << TWINT) | (1 << TWEN);
-
- timeout_timer = timer_read();
- while (!(TWCR & (1 << TWINT))) {
- if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
- return I2C_STATUS_TIMEOUT;
- }
- }
-
- // check if the device has acknowledged the READ / WRITE mode
- uint8_t twst = TW_STATUS & 0xF8;
- if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) {
- return I2C_STATUS_ERROR;
- }
-
- return I2C_STATUS_SUCCESS;
-}
-
-i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
- // load data into data register
- TWDR = data;
- // start transmission of data
- TWCR = (1 << TWINT) | (1 << TWEN);
-
- uint16_t timeout_timer = timer_read();
- while (!(TWCR & (1 << TWINT))) {
- if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
- return I2C_STATUS_TIMEOUT;
- }
- }
-
- if ((TW_STATUS & 0xF8) != TW_MT_DATA_ACK) {
- return I2C_STATUS_ERROR;
- }
-
- return I2C_STATUS_SUCCESS;
-}
-
-int16_t i2c_read_ack(uint16_t timeout) {
- // start TWI module and acknowledge data after reception
- TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
-
- uint16_t timeout_timer = timer_read();
- while (!(TWCR & (1 << TWINT))) {
- if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
- return I2C_STATUS_TIMEOUT;
- }
- }
-
- // return received data from TWDR
- return TWDR;
-}
-
-int16_t i2c_read_nack(uint16_t timeout) {
- // start receiving without acknowledging reception
- TWCR = (1 << TWINT) | (1 << TWEN);
-
- uint16_t timeout_timer = timer_read();
- while (!(TWCR & (1 << TWINT))) {
- if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
- return I2C_STATUS_TIMEOUT;
- }
- }
-
- // return received data from TWDR
- return TWDR;
-}
-
-i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_status_t status = i2c_start(address | I2C_WRITE, timeout);
-
- for (uint16_t i = 0; i < length && status >= 0; i++) {
- status = i2c_write(data[i], timeout);
- }
-
- i2c_stop();
-
- return status;
-}
-
-i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_status_t status = i2c_start(address | I2C_READ, timeout);
-
- for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) {
- status = i2c_read_ack(timeout);
- if (status >= 0) {
- data[i] = status;
- }
- }
-
- if (status >= 0) {
- status = i2c_read_nack(timeout);
- if (status >= 0) {
- data[(length - 1)] = status;
- }
- }
-
- i2c_stop();
-
- return (status < 0) ? status : I2C_STATUS_SUCCESS;
-}
-
-i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_status_t status = i2c_start(devaddr | 0x00, timeout);
- if (status >= 0) {
- status = i2c_write(regaddr, timeout);
-
- for (uint16_t i = 0; i < length && status >= 0; i++) {
- status = i2c_write(data[i], timeout);
- }
- }
-
- i2c_stop();
-
- return status;
-}
-
-i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_status_t status = i2c_start(devaddr, timeout);
- if (status < 0) {
- goto error;
- }
-
- status = i2c_write(regaddr, timeout);
- if (status < 0) {
- goto error;
- }
-
- status = i2c_start(devaddr | 0x01, timeout);
-
- for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) {
- status = i2c_read_ack(timeout);
- if (status >= 0) {
- data[i] = status;
- }
- }
-
- if (status >= 0) {
- status = i2c_read_nack(timeout);
- if (status >= 0) {
- data[(length - 1)] = status;
- }
- }
-
-error:
- i2c_stop();
-
- return (status < 0) ? status : I2C_STATUS_SUCCESS;
-}
-
-void i2c_stop(void) {
- // transmit STOP condition
- TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
-}
diff --git a/drivers/avr/i2c_master.h b/drivers/avr/i2c_master.h
deleted file mode 100644
index e5af73364b..0000000000
--- a/drivers/avr/i2c_master.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright (C) 2019 Elia Ritterbusch
- +
- * 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 3 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 <https://www.gnu.org/licenses/>.
- */
-/* Library made by: g4lvanix
- * GitHub repository: https://github.com/g4lvanix/I2C-master-lib
- */
-
-#pragma once
-
-#define I2C_READ 0x01
-#define I2C_WRITE 0x00
-
-typedef int16_t i2c_status_t;
-
-#define I2C_STATUS_SUCCESS (0)
-#define I2C_STATUS_ERROR (-1)
-#define I2C_STATUS_TIMEOUT (-2)
-
-#define I2C_TIMEOUT_IMMEDIATE (0)
-#define I2C_TIMEOUT_INFINITE (0xFFFF)
-
-void i2c_init(void);
-i2c_status_t i2c_start(uint8_t address, uint16_t timeout);
-i2c_status_t i2c_write(uint8_t data, uint16_t timeout);
-int16_t i2c_read_ack(uint16_t timeout);
-int16_t i2c_read_nack(uint16_t timeout);
-i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
-void i2c_stop(void);
diff --git a/drivers/avr/i2c_slave.c b/drivers/avr/i2c_slave.c
deleted file mode 100644
index 62a378165a..0000000000
--- a/drivers/avr/i2c_slave.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Copyright (C) 2019 Elia Ritterbusch
- +
- * 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 3 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 <https://www.gnu.org/licenses/>.
- */
-/* Library made by: g4lvanix
- * GitHub repository: https://github.com/g4lvanix/I2C-slave-lib
- */
-
-#include <avr/io.h>
-#include <util/twi.h>
-#include <avr/interrupt.h>
-#include <stdbool.h>
-
-#include "i2c_slave.h"
-
-volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
-
-static volatile uint8_t buffer_address;
-static volatile bool slave_has_register_set = false;
-
-void i2c_slave_init(uint8_t address) {
- // load address into TWI address register
- TWAR = address;
- // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
- TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN);
-}
-
-void i2c_slave_stop(void) {
- // clear acknowledge and enable bits
- TWCR &= ~((1 << TWEA) | (1 << TWEN));
-}
-
-ISR(TWI_vect) {
- uint8_t ack = 1;
-
- switch (TW_STATUS) {
- case TW_SR_SLA_ACK:
- // The device is now a slave receiver
- slave_has_register_set = false;
- break;
-
- case TW_SR_DATA_ACK:
- // This device is a slave receiver and has received data
- // First byte is the location then the bytes will be writen in buffer with auto-incriment
- if (!slave_has_register_set) {
- buffer_address = TWDR;
-
- if (buffer_address >= I2C_SLAVE_REG_COUNT) { // address out of bounds dont ack
- ack = 0;
- buffer_address = 0;
- }
- slave_has_register_set = true; // address has been receaved now fill in buffer
- } else {
- i2c_slave_reg[buffer_address] = TWDR;
- buffer_address++;
- }
- break;
-
- case TW_ST_SLA_ACK:
- case TW_ST_DATA_ACK:
- // This device is a slave transmitter and master has requested data
- TWDR = i2c_slave_reg[buffer_address];
- buffer_address++;
- break;
-
- case TW_BUS_ERROR:
- // We got an error, reset i2c
- TWCR = 0;
- default:
- break;
- }
-
- // Reset i2c state machine to be ready for next interrupt
- TWCR |= (1 << TWIE) | (1 << TWINT) | (ack << TWEA) | (1 << TWEN);
-}
diff --git a/drivers/avr/i2c_slave.h b/drivers/avr/i2c_slave.h
deleted file mode 100644
index 1cd0625ef4..0000000000
--- a/drivers/avr/i2c_slave.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2019 Elia Ritterbusch
- +
- * 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 3 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 <https://www.gnu.org/licenses/>.
- */
-/* Library made by: g4lvanix
- * GitHub repository: https://github.com/g4lvanix/I2C-slave-lib
-
- Info: Inititate the library by giving the required address.
- Read or write to the necessary buffer according to the opperation.
- */
-
-#pragma once
-
-#define I2C_SLAVE_REG_COUNT 30
-
-extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
-
-void i2c_slave_init(uint8_t address);
-void i2c_slave_stop(void);
diff --git a/drivers/avr/serial.c b/drivers/avr/serial.c
deleted file mode 100644
index 84365fe8f4..0000000000
--- a/drivers/avr/serial.c
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * WARNING: be careful changing this code, it is very timing dependent
- *
- * 2018-10-28 checked
- * avr-gcc 4.9.2
- * avr-gcc 5.4.0
- * avr-gcc 7.3.0
- */
-
-#ifndef F_CPU
-# define F_CPU 16000000
-#endif
-
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <util/delay.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include "serial.h"
-
-#ifdef SOFT_SERIAL_PIN
-
-# if !(defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
-# error serial.c is not supported for the currently selected MCU
-# endif
-// if using ATmega32U4/2, AT90USBxxx I2C, can not use PD0 and PD1 in soft serial.
-# if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
-# if defined(USE_AVR_I2C) && (SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1)
-# error Using I2C, so can not use PD0, PD1
-# endif
-# endif
-// PD0..PD3, common config
-# if SOFT_SERIAL_PIN == D0
-# define EIMSK_BIT _BV(INT0)
-# define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01)))
-# define SERIAL_PIN_INTERRUPT INT0_vect
-# define EICRx EICRA
-# elif SOFT_SERIAL_PIN == D1
-# define EIMSK_BIT _BV(INT1)
-# define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11)))
-# define SERIAL_PIN_INTERRUPT INT1_vect
-# define EICRx EICRA
-# elif SOFT_SERIAL_PIN == D2
-# define EIMSK_BIT _BV(INT2)
-# define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21)))
-# define SERIAL_PIN_INTERRUPT INT2_vect
-# define EICRx EICRA
-# elif SOFT_SERIAL_PIN == D3
-# define EIMSK_BIT _BV(INT3)
-# define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31)))
-# define SERIAL_PIN_INTERRUPT INT3_vect
-# define EICRx EICRA
-# endif
-
-<<<<<<< HEAD
-// ATmegaxxU2 specific config
-# if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__)
-=======
-// ATmegaxxU2/AT90USB162 specific config
-# if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB162__)
->>>>>>> 0.12.52~1
-// PD4(INT5), PD6(INT6), PD7(INT7), PC7(INT4)
-# if SOFT_SERIAL_PIN == D4
-# define EIMSK_BIT _BV(INT5)
-# define EICRx_BIT (~(_BV(ISC50) | _BV(ISC51)))
-# define SERIAL_PIN_INTERRUPT INT5_vect
-# define EICRx EICRB
-# elif SOFT_SERIAL_PIN == D6
-# define EIMSK_BIT _BV(INT6)
-# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61)))
-# define SERIAL_PIN_INTERRUPT INT6_vect
-# define EICRx EICRB
-# elif SOFT_SERIAL_PIN == D7
-# define EIMSK_BIT _BV(INT7)
-# define EICRx_BIT (~(_BV(ISC70) | _BV(ISC71)))
-# define SERIAL_PIN_INTERRUPT INT7_vect
-# define EICRx EICRB
-# elif SOFT_SERIAL_PIN == C7
-# define EIMSK_BIT _BV(INT4)
-# define EICRx_BIT (~(_BV(ISC40) | _BV(ISC41)))
-# define SERIAL_PIN_INTERRUPT INT4_vect
-# define EICRx EICRB
-# endif
-# endif
-
-// ATmegaxxU4 specific config
-# if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)
-// PE6(INT6)
-# if SOFT_SERIAL_PIN == E6
-# define EIMSK_BIT _BV(INT6)
-# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61)))
-# define SERIAL_PIN_INTERRUPT INT6_vect
-# define EICRx EICRB
-# endif
-# endif
-
-// AT90USBxxx specific config
-# if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
-// PE4..PE7(INT4..INT7)
-# if SOFT_SERIAL_PIN == E4
-# define EIMSK_BIT _BV(INT4)
-# define EICRx_BIT (~(_BV(ISC40) | _BV(ISC41)))
-# define SERIAL_PIN_INTERRUPT INT4_vect
-# define EICRx EICRB
-# elif SOFT_SERIAL_PIN == E5
-# define EIMSK_BIT _BV(INT5)
-# define EICRx_BIT (~(_BV(ISC50) | _BV(ISC51)))
-# define SERIAL_PIN_INTERRUPT INT5_vect
-# define EICRx EICRB
-# elif SOFT_SERIAL_PIN == E6
-# define EIMSK_BIT _BV(INT6)
-# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61)))
-# define SERIAL_PIN_INTERRUPT INT6_vect
-# define EICRx EICRB
-# elif SOFT_SERIAL_PIN == E7
-# define EIMSK_BIT _BV(INT7)
-# define EICRx_BIT (~(_BV(ISC70) | _BV(ISC71)))
-# define SERIAL_PIN_INTERRUPT INT7_vect
-# define EICRx EICRB
-# endif
-# endif
-
-# ifndef SERIAL_PIN_INTERRUPT
-# error invalid SOFT_SERIAL_PIN value
-# endif
-
-# define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
-# define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
-# define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
-# define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
-# define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))
-
-# define ALWAYS_INLINE __attribute__((always_inline))
-# define NO_INLINE __attribute__((noinline))
-# define _delay_sub_us(x) __builtin_avr_delay_cycles(x)
-
-// parity check
-# define ODD_PARITY 1
-# define EVEN_PARITY 0
-# define PARITY EVEN_PARITY
-
-# ifdef SERIAL_DELAY
-// custom setup in config.h
-// #define TID_SEND_ADJUST 2
-// #define SERIAL_DELAY 6 // micro sec
-// #define READ_WRITE_START_ADJUST 30 // cycles
-// #define READ_WRITE_WIDTH_ADJUST 8 // cycles
-# else
-// ============ Standard setups ============
-
-# ifndef SELECT_SOFT_SERIAL_SPEED
-# define SELECT_SOFT_SERIAL_SPEED 1
-// 0: about 189kbps (Experimental only)
-// 1: about 137kbps (default)
-// 2: about 75kbps
-// 3: about 39kbps
-// 4: about 26kbps
-// 5: about 20kbps
-# endif
-
-# if __GNUC__ < 6
-# define TID_SEND_ADJUST 14
-# else
-# define TID_SEND_ADJUST 2
-# endif
-
-# if SELECT_SOFT_SERIAL_SPEED == 0
-// Very High speed
-# define SERIAL_DELAY 4 // micro sec
-# if __GNUC__ < 6
-# define READ_WRITE_START_ADJUST 33 // cycles
-# define READ_WRITE_WIDTH_ADJUST 3 // cycles
-# else
-# define READ_WRITE_START_ADJUST 34 // cycles
-# define READ_WRITE_WIDTH_ADJUST 7 // cycles
-# endif
-# elif SELECT_SOFT_SERIAL_SPEED == 1
-// High speed
-# define SERIAL_DELAY 6 // micro sec
-# if __GNUC__ < 6
-# define READ_WRITE_START_ADJUST 30 // cycles
-# define READ_WRITE_WIDTH_ADJUST 3 // cycles
-# else
-# define READ_WRITE_START_ADJUST 33 // cycles
-# define READ_WRITE_WIDTH_ADJUST 7 // cycles
-# endif
-# elif SELECT_SOFT_SERIAL_SPEED == 2
-// Middle speed
-# define SERIAL_DELAY 12 // micro sec
-# define READ_WRITE_START_ADJUST 30 // cycles
-# if __GNUC__ < 6
-# define READ_WRITE_WIDTH_ADJUST 3 // cycles
-# else
-# define READ_WRITE_WIDTH_ADJUST 7 // cycles
-# endif
-# elif SELECT_SOFT_SERIAL_SPEED == 3
-// Low speed
-# define SERIAL_DELAY 24 // micro sec
-# define READ_WRITE_START_ADJUST 30 // cycles
-# if __GNUC__ < 6
-# define READ_WRITE_WIDTH_ADJUST 3 // cycles
-# else
-# define READ_WRITE_WIDTH_ADJUST 7 // cycles
-# endif
-# elif SELECT_SOFT_SERIAL_SPEED == 4
-// Very Low speed
-# define SERIAL_DELAY 36 // micro sec
-# define READ_WRITE_START_ADJUST 30 // cycles
-# if __GNUC__ < 6
-# define READ_WRITE_WIDTH_ADJUST 3 // cycles
-# else
-# define READ_WRITE_WIDTH_ADJUST 7 // cycles
-# endif
-# elif SELECT_SOFT_SERIAL_SPEED == 5
-// Ultra Low speed
-# define SERIAL_DELAY 48 // micro sec
-# define READ_WRITE_START_ADJUST 30 // cycles
-# if __GNUC__ < 6
-# define READ_WRITE_WIDTH_ADJUST 3 // cycles
-# else
-# define READ_WRITE_WIDTH_ADJUST 7 // cycles
-# endif
-# else
-# error invalid SELECT_SOFT_SERIAL_SPEED value
-# endif /* SELECT_SOFT_SERIAL_SPEED */
-# endif /* SERIAL_DELAY */
-
-# define SERIAL_DELAY_HALF1 (SERIAL_DELAY / 2)
-# define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY / 2)
-
-# define SLAVE_INT_WIDTH_US 1
-# ifndef SERIAL_USE_MULTI_TRANSACTION
-# define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY
-# else
-# define SLAVE_INT_ACK_WIDTH_UNIT 2
-# define SLAVE_INT_ACK_WIDTH 4
-# endif
-
-static SSTD_t *Transaction_table = NULL;
-static uint8_t Transaction_table_size = 0;
-
-inline static void serial_delay(void) ALWAYS_INLINE;
-inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); }
-
-inline static void serial_delay_half1(void) ALWAYS_INLINE;
-inline static void serial_delay_half1(void) { _delay_us(SERIAL_DELAY_HALF1); }
-
-inline static void serial_delay_half2(void) ALWAYS_INLINE;
-inline static void serial_delay_half2(void) { _delay_us(SERIAL_DELAY_HALF2); }
-
-inline static void serial_output(void) ALWAYS_INLINE;
-inline static void serial_output(void) { setPinOutput(SOFT_SERIAL_PIN); }
-
-// make the serial pin an input with pull-up resistor
-inline static void serial_input_with_pullup(void) ALWAYS_INLINE;
-inline static void serial_input_with_pullup(void) { setPinInputHigh(SOFT_SERIAL_PIN); }
-
-inline static uint8_t serial_read_pin(void) ALWAYS_INLINE;
-inline static uint8_t serial_read_pin(void) { return !!readPin(SOFT_SERIAL_PIN); }
-
-inline static void serial_low(void) ALWAYS_INLINE;
-inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); }
-
-inline static void serial_high(void) ALWAYS_INLINE;
-inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); }
-
-void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) {
- Transaction_table = sstd_table;
- Transaction_table_size = (uint8_t)sstd_table_size;
- serial_output();
- serial_high();
-}
-
-void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) {
- Transaction_table = sstd_table;
- Transaction_table_size = (uint8_t)sstd_table_size;
- serial_input_with_pullup();
-
- // Enable INT0-INT7
- EIMSK |= EIMSK_BIT;
- EICRx &= EICRx_BIT;
-}
-
-// Used by the sender to synchronize timing with the reciver.
-static void sync_recv(void) NO_INLINE;
-static void sync_recv(void) {
- for (uint8_t i = 0; i < SERIAL_DELAY * 5 && serial_read_pin(); i++) {
- }
- // This shouldn't hang if the target disconnects because the
- // serial line will float to high if the target does disconnect.
- while (!serial_read_pin())
- ;
-}
-
-// Used by the reciver to send a synchronization signal to the sender.
-static void sync_send(void) NO_INLINE;
-static void sync_send(void) {
- serial_low();
- serial_delay();
- serial_high();
-}
-
-// Reads a byte from the serial line
-static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) NO_INLINE;
-static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) {
- uint8_t byte, i, p, pb;
-
- _delay_sub_us(READ_WRITE_START_ADJUST);
- for (i = 0, byte = 0, p = PARITY; i < bit; i++) {
- serial_delay_half1(); // read the middle of pulses
- if (serial_read_pin()) {
- byte = (byte << 1) | 1;
- p ^= 1;
- } else {
- byte = (byte << 1) | 0;
- p ^= 0;
- }
- _delay_sub_us(READ_WRITE_WIDTH_ADJUST);
- serial_delay_half2();
- }
- /* recive parity bit */
- serial_delay_half1(); // read the middle of pulses
- pb = serial_read_pin();
- _delay_sub_us(READ_WRITE_WIDTH_ADJUST);
- serial_delay_half2();
-
- *pterrcount += (p != pb) ? 1 : 0;
-
- return byte;
-}
-
-// Sends a byte with MSB ordering
-void serial_write_chunk(uint8_t data, uint8_t bit) NO_INLINE;
-void serial_write_chunk(uint8_t data, uint8_t bit) {
- uint8_t b, p;
- for (p = PARITY, b = 1 << (bit - 1); b; b >>= 1) {
- if (data & b) {
- serial_high();
- p ^= 1;
- } else {
- serial_low();
- p ^= 0;
- }
- serial_delay();
- }
- /* send parity bit */
- if (p & 1) {
- serial_high();
- } else {
- serial_low();
- }
- serial_delay();
-
- serial_low(); // sync_send() / senc_recv() need raise edge
-}
-
-static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
-static void serial_send_packet(uint8_t *buffer, uint8_t size) {
- for (uint8_t i = 0; i < size; ++i) {
- uint8_t data;
- data = buffer[i];
- sync_send();
- serial_write_chunk(data, 8);
- }
-}
-
-static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
-static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) {
- uint8_t pecount = 0;
- for (uint8_t i = 0; i < size; ++i) {
- uint8_t data;
- sync_recv();
- data = serial_read_chunk(&pecount, 8);
- buffer[i] = data;
- }
- return pecount == 0;
-}
-
-inline static void change_sender2reciver(void) {
- sync_send(); // 0
- serial_delay_half1(); // 1
- serial_low(); // 2
- serial_input_with_pullup(); // 2
- serial_delay_half1(); // 3
-}
-
-inline static void change_reciver2sender(void) {
- sync_recv(); // 0
- serial_delay(); // 1
- serial_low(); // 3
- serial_output(); // 3
- serial_delay_half1(); // 4
-}
-
-static inline uint8_t nibble_bits_count(uint8_t bits) {
- bits = (bits & 0x5) + (bits >> 1 & 0x5);
- bits = (bits & 0x3) + (bits >> 2 & 0x3);
- return bits;
-}
-
-// interrupt handle to be used by the target device
-ISR(SERIAL_PIN_INTERRUPT) {
-# ifndef SERIAL_USE_MULTI_TRANSACTION
- serial_low();
- serial_output();
- SSTD_t *trans = Transaction_table;
-# else
- // recive transaction table index
- uint8_t tid, bits;
- uint8_t pecount = 0;
- sync_recv();
- bits = serial_read_chunk(&pecount, 7);
- tid = bits >> 3;
- bits = (bits & 7) != nibble_bits_count(tid);
- if (bits || pecount > 0 || tid > Transaction_table_size) {
- return;
- }
- serial_delay_half1();
-
- serial_high(); // response step1 low->high
- serial_output();
- _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT * SLAVE_INT_ACK_WIDTH);
- SSTD_t *trans = &Transaction_table[tid];
- serial_low(); // response step2 ack high->low
-# endif
-
- // target send phase
- if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size);
- // target switch to input
- change_sender2reciver();
-
- // target recive phase
- if (trans->initiator2target_buffer_size > 0) {
- if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size)) {
- *trans->status = TRANSACTION_ACCEPTED;
- } else {
- *trans->status = TRANSACTION_DATA_ERROR;
- }
- } else {
- *trans->status = TRANSACTION_ACCEPTED;
- }
-
- sync_recv(); // weit initiator output to high
-}
-
-/////////
-// start transaction by initiator
-//
-// int soft_serial_transaction(int sstd_index)
-//
-// Returns:
-// TRANSACTION_END
-// TRANSACTION_NO_RESPONSE
-// TRANSACTION_DATA_ERROR
-// this code is very time dependent, so we need to disable interrupts
-# ifndef SERIAL_USE_MULTI_TRANSACTION
-int soft_serial_transaction(void) {
- SSTD_t *trans = Transaction_table;
-# else
-int soft_serial_transaction(int sstd_index) {
- if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR;
- SSTD_t *trans = &Transaction_table[sstd_index];
-# endif
- cli();
-
- // signal to the target that we want to start a transaction
- serial_output();
- serial_low();
- _delay_us(SLAVE_INT_WIDTH_US);
-
-# ifndef SERIAL_USE_MULTI_TRANSACTION
- // wait for the target response
- serial_input_with_pullup();
- _delay_us(SLAVE_INT_RESPONSE_TIME);
-
- // check if the target is present
- if (serial_read_pin()) {
- // target failed to pull the line low, assume not present
- serial_output();
- serial_high();
- *trans->status = TRANSACTION_NO_RESPONSE;
- sei();
- return TRANSACTION_NO_RESPONSE;
- }
-
-# else
- // send transaction table index
- int tid = (sstd_index << 3) | (7 & nibble_bits_count(sstd_index));
- sync_send();
- _delay_sub_us(TID_SEND_ADJUST);
- serial_write_chunk(tid, 7);
- serial_delay_half1();
-
- // wait for the target response (step1 low->high)
- serial_input_with_pullup();
- while (!serial_read_pin()) {
- _delay_sub_us(2);
- }
-
- // check if the target is present (step2 high->low)
- for (int i = 0; serial_read_pin(); i++) {
- if (i > SLAVE_INT_ACK_WIDTH + 1) {
- // slave failed to pull the line low, assume not present
- serial_output();
- serial_high();
- *trans->status = TRANSACTION_NO_RESPONSE;
- sei();
- return TRANSACTION_NO_RESPONSE;
- }
- _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT);
- }
-# endif
-
- // initiator recive phase
- // if the target is present syncronize with it
- if (trans->target2initiator_buffer_size > 0) {
- if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size)) {
- serial_output();
- serial_high();
- *trans->status = TRANSACTION_DATA_ERROR;
- sei();
- return TRANSACTION_DATA_ERROR;
- }
- }
-
- // initiator switch to output
- change_reciver2sender();
-
- // initiator send phase
- if (trans->initiator2target_buffer_size > 0) {
- serial_send_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size);
- }
-
- // always, release the line when not in use
- sync_send();
-
- *trans->status = TRANSACTION_END;
- sei();
- return TRANSACTION_END;
-}
-
-# ifdef SERIAL_USE_MULTI_TRANSACTION
-int soft_serial_get_and_clean_status(int sstd_index) {
- SSTD_t *trans = &Transaction_table[sstd_index];
- cli();
- int retval = *trans->status;
- *trans->status = 0;
- ;
- sei();
- return retval;
-}
-# endif
-
-#endif
-
-// Helix serial.c history
-// 2018-1-29 fork from let's split and add PD2, modify sync_recv() (#2308, bceffdefc)
-// 2018-6-28 bug fix master to slave comm and speed up (#3255, 1038bbef4)
-// (adjusted with avr-gcc 4.9.2)
-// 2018-7-13 remove USE_SERIAL_PD2 macro (#3374, f30d6dd78)
-// (adjusted with avr-gcc 4.9.2)
-// 2018-8-11 add support multi-type transaction (#3608, feb5e4aae)
-// (adjusted with avr-gcc 4.9.2)
-// 2018-10-21 fix serial and RGB animation conflict (#4191, 4665e4fff)
-// (adjusted with avr-gcc 7.3.0)
-// 2018-10-28 re-adjust compiler depend value of delay (#4269, 8517f8a66)
-// (adjusted with avr-gcc 5.4.0, 7.3.0)
-// 2018-12-17 copy to TOP/quantum/split_common/ and remove backward compatibility code (#4669)
diff --git a/drivers/avr/serial.h b/drivers/avr/serial.h
deleted file mode 100644
index 53e66cf905..0000000000
--- a/drivers/avr/serial.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#pragma once
-
-#include <stdbool.h>
-
-// /////////////////////////////////////////////////////////////////
-// Need Soft Serial defines in config.h
-// /////////////////////////////////////////////////////////////////
-// ex.
-// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6
-// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5
-// // 1: about 137kbps (default)
-// // 2: about 75kbps
-// // 3: about 39kbps
-// // 4: about 26kbps
-// // 5: about 20kbps
-//
-// //// USE simple API (using signle-type transaction function)
-// /* nothing */
-// //// USE flexible API (using multi-type transaction function)
-// #define SERIAL_USE_MULTI_TRANSACTION
-//
-// /////////////////////////////////////////////////////////////////
-
-// Soft Serial Transaction Descriptor
-typedef struct _SSTD_t {
- uint8_t *status;
- uint8_t initiator2target_buffer_size;
- uint8_t *initiator2target_buffer;
- uint8_t target2initiator_buffer_size;
- uint8_t *target2initiator_buffer;
-} SSTD_t;
-#define TID_LIMIT(table) (sizeof(table) / sizeof(SSTD_t))
-
-// initiator is transaction start side
-void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size);
-// target is interrupt accept side
-void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size);
-
-// initiator resullt
-#define TRANSACTION_END 0
-#define TRANSACTION_NO_RESPONSE 0x1
-#define TRANSACTION_DATA_ERROR 0x2
-#define TRANSACTION_TYPE_ERROR 0x4
-#ifndef SERIAL_USE_MULTI_TRANSACTION
-int soft_serial_transaction(void);
-#else
-int soft_serial_transaction(int sstd_index);
-#endif
-
-// target status
-// *SSTD_t.status has
-// initiator:
-// TRANSACTION_END
-// or TRANSACTION_NO_RESPONSE
-// or TRANSACTION_DATA_ERROR
-// target:
-// TRANSACTION_DATA_ERROR
-// or TRANSACTION_ACCEPTED
-#define TRANSACTION_ACCEPTED 0x8
-#ifdef SERIAL_USE_MULTI_TRANSACTION
-int soft_serial_get_and_clean_status(int sstd_index);
-#endif
diff --git a/drivers/avr/spi_master.c b/drivers/avr/spi_master.c
deleted file mode 100644
index 4e8fd3bcdf..0000000000
--- a/drivers/avr/spi_master.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Copyright 2020
- *
- * 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 3 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 <https://www.gnu.org/licenses/>.
- */
-
-#include "spi_master.h"
-
-#include "timer.h"
-
-#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
-# define SPI_SCK_PIN B1
-# define SPI_MOSI_PIN B2
-# define SPI_MISO_PIN B3
-#elif defined(__AVR_ATmega32A__)
-# define SPI_SCK_PIN B7
-# define SPI_MOSI_PIN B5
-# define SPI_MISO_PIN B6
-#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
-# define SPI_SCK_PIN B5
-# define SPI_MOSI_PIN B3
-# define SPI_MISO_PIN B4
-#endif
-
-#ifndef SPI_TIMEOUT
-# define SPI_TIMEOUT 100
-#endif
-
-static pin_t currentSlavePin = NO_PIN;
-static uint8_t currentSlaveConfig = 0;
-static bool currentSlave2X = false;
-
-void spi_init(void) {
- writePinHigh(SPI_SS_PIN);
- setPinOutput(SPI_SCK_PIN);
- setPinOutput(SPI_MOSI_PIN);
- setPinInput(SPI_MISO_PIN);
-
- SPCR = (_BV(SPE) | _BV(MSTR));
-}
-
-bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
- if (currentSlavePin != NO_PIN || slavePin == NO_PIN) {
- return false;
- }
-
- currentSlaveConfig = 0;
-
- if (lsbFirst) {
- currentSlaveConfig |= _BV(DORD);
- }
-
- switch (mode) {
- case 1:
- currentSlaveConfig |= _BV(CPHA);
- break;
- case 2:
- currentSlaveConfig |= _BV(CPOL);
- break;
- case 3:
- currentSlaveConfig |= (_BV(CPOL) | _BV(CPHA));
- break;
- }
-
- uint16_t roundedDivisor = 1;
- while (roundedDivisor < divisor) {
- roundedDivisor <<= 1;
- }
-
- switch (roundedDivisor) {
- case 16:
- currentSlaveConfig |= _BV(SPR0);
- break;
- case 64:
- currentSlaveConfig |= _BV(SPR1);
- break;
- case 128:
- currentSlaveConfig |= (_BV(SPR1) | _BV(SPR0));
- break;
- case 2:
- currentSlave2X = true;
- break;
- case 8:
- currentSlave2X = true;
- currentSlaveConfig |= _BV(SPR0);
- break;
- case 32:
- currentSlave2X = true;
- currentSlaveConfig |= _BV(SPR1);
- break;
- }
-
- SPCR |= currentSlaveConfig;
- if (currentSlave2X) {
- SPSR |= _BV(SPI2X);
- }
- currentSlavePin = slavePin;
- setPinOutput(currentSlavePin);
- writePinLow(currentSlavePin);
-
- return true;
-}
-
-spi_status_t spi_write(uint8_t data) {
- SPDR = data;
-
- uint16_t timeout_timer = timer_read();
- while (!(SPSR & _BV(SPIF))) {
- if ((timer_read() - timeout_timer) >= SPI_TIMEOUT) {
- return SPI_STATUS_TIMEOUT;
- }
- }
-
- return SPDR;
-}
-
-spi_status_t spi_read() {
- SPDR = 0x00; // Dummy
-
- uint16_t timeout_timer = timer_read();
- while (!(SPSR & _BV(SPIF))) {
- if ((timer_read() - timeout_timer) >= SPI_TIMEOUT) {
- return SPI_STATUS_TIMEOUT;
- }
- }
-
- return SPDR;
-}
-
-spi_status_t spi_transmit(const uint8_t *data, uint16_t length) {
- spi_status_t status;
-
- for (uint16_t i = 0; i < length; i++) {
- status = spi_write(data[i]);
-
- if (status < 0) {
- return status;
- }
- }
-
- return SPI_STATUS_SUCCESS;
-}
-
-spi_status_t spi_receive(uint8_t *data, uint16_t length) {
- spi_status_t status;
-
- for (uint16_t i = 0; i < length; i++) {
- status = spi_read();
-
- if (status >= 0) {
- data[i] = status;
- } else {
- return status;
- }
- }
-
- return SPI_STATUS_SUCCESS;
-}
-
-void spi_stop(void) {
- if (currentSlavePin != NO_PIN) {
- setPinOutput(currentSlavePin);
- writePinHigh(currentSlavePin);
- currentSlavePin = NO_PIN;
- SPSR &= ~(_BV(SPI2X));
- SPCR &= ~(currentSlaveConfig);
- currentSlaveConfig = 0;
- currentSlave2X = false;
- }
-}
diff --git a/drivers/avr/spi_master.h b/drivers/avr/spi_master.h
deleted file mode 100644
index 8a30f47ae4..0000000000
--- a/drivers/avr/spi_master.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright 2020
- *
- * 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 3 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 <https://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <stdbool.h>
-
-#include "gpio.h"
-
-typedef int16_t spi_status_t;
-
-// Hardware SS pin is defined in the header so that user code can refer to it
-#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
-# define SPI_SS_PIN B0
-#elif defined(__AVR_ATmega32A__)
-# define SPI_SS_PIN B4
-#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
-# define SPI_SS_PIN B2
-#endif
-
-#define SPI_STATUS_SUCCESS (0)
-#define SPI_STATUS_ERROR (-1)
-#define SPI_STATUS_TIMEOUT (-2)
-
-#define SPI_TIMEOUT_IMMEDIATE (0)
-#define SPI_TIMEOUT_INFINITE (0xFFFF)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-void spi_init(void);
-
-bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor);
-
-spi_status_t spi_write(uint8_t data);
-
-spi_status_t spi_read(void);
-
-spi_status_t spi_transmit(const uint8_t *data, uint16_t length);
-
-spi_status_t spi_receive(uint8_t *data, uint16_t length);
-
-void spi_stop(void);
-#ifdef __cplusplus
-}
-#endif
diff --git a/drivers/avr/ssd1306.c b/drivers/avr/ssd1306.c
deleted file mode 100644
index 1a09a2bcb7..0000000000
--- a/drivers/avr/ssd1306.c
+++ /dev/null
@@ -1,319 +0,0 @@
-#ifdef SSD1306OLED
-
-# include "ssd1306.h"
-# include "i2c.h"
-# include <string.h>
-# include "print.h"
-# include "glcdfont.c"
-# ifdef PROTOCOL_LUFA
-# include "lufa.h"
-# endif
-# include "sendchar.h"
-# include "timer.h"
-
-struct CharacterMatrix display;
-
-// Set this to 1 to help diagnose early startup problems
-// when testing power-on with ble. Turn it off otherwise,
-// as the latency of printing most of the debug info messes
-// with the matrix scan, causing keys to drop.
-# define DEBUG_TO_SCREEN 0
-
-// static uint16_t last_battery_update;
-// static uint32_t vbat;
-//#define BatteryUpdateInterval 10000 /* milliseconds */
-# define ScreenOffInterval 300000 /* milliseconds */
-# if DEBUG_TO_SCREEN
-static uint8_t displaying;
-# endif
-static uint16_t last_flush;
-
-// Write command sequence.
-// Returns true on success.
-static inline bool _send_cmd1(uint8_t cmd) {
- bool res = false;
-
- if (i2c_start_write(SSD1306_ADDRESS)) {
- xprintf("failed to start write to %d\n", SSD1306_ADDRESS);
- goto done;
- }
-
- if (i2c_master_write(0x0 /* command byte follows */)) {
- print("failed to write control byte\n");
-
- goto done;
- }
-
- if (i2c_master_write(cmd)) {
- xprintf("failed to write command %d\n", cmd);
- goto done;
- }
- res = true;
-done:
- i2c_master_stop();
- return res;
-}
-
-// Write 2-byte command sequence.
-// Returns true on success
-static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) {
- if (!_send_cmd1(cmd)) {
- return false;
- }
- return _send_cmd1(opr);
-}
-
-// Write 3-byte command sequence.
-// Returns true on success
-static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) {
- if (!_send_cmd1(cmd)) {
- return false;
- }
- if (!_send_cmd1(opr1)) {
- return false;
- }
- return _send_cmd1(opr2);
-}
-
-# define send_cmd1(c) \
- if (!_send_cmd1(c)) { \
- goto done; \
- }
-# define send_cmd2(c, o) \
- if (!_send_cmd2(c, o)) { \
- goto done; \
- }
-# define send_cmd3(c, o1, o2) \
- if (!_send_cmd3(c, o1, o2)) { \
- goto done; \
- }
-
-static void clear_display(void) {
- matrix_clear(&display);
-
- // Clear all of the display bits (there can be random noise
- // in the RAM on startup)
- send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1);
- send_cmd3(ColumnAddr, 0, DisplayWidth - 1);
-
- if (i2c_start_write(SSD1306_ADDRESS)) {
- goto done;
- }
- if (i2c_master_write(0x40)) {
- // Data mode
- goto done;
- }
- for (uint8_t row = 0; row < MatrixRows; ++row) {
- for (uint8_t col = 0; col < DisplayWidth; ++col) {
- i2c_master_write(0);
- }
- }
-
- display.dirty = false;
-
-done:
- i2c_master_stop();
-}
-
-# if DEBUG_TO_SCREEN
-# undef sendchar
-static int8_t capture_sendchar(uint8_t c) {
- sendchar(c);
- iota_gfx_write_char(c);
-
- if (!displaying) {
- iota_gfx_flush();
- }
- return 0;
-}
-# endif
-
-bool iota_gfx_init(void) {
- bool success = false;
-
- send_cmd1(DisplayOff);
- send_cmd2(SetDisplayClockDiv, 0x80);
- send_cmd2(SetMultiPlex, DisplayHeight - 1);
-
- send_cmd2(SetDisplayOffset, 0);
-
- send_cmd1(SetStartLine | 0x0);
- send_cmd2(SetChargePump, 0x14 /* Enable */);
- send_cmd2(SetMemoryMode, 0 /* horizontal addressing */);
-
-# ifdef OLED_ROTATE180
- // the following Flip the display orientation 180 degrees
- send_cmd1(SegRemap);
- send_cmd1(ComScanInc);
-# endif
-# ifndef OLED_ROTATE180
- // Flips the display orientation 0 degrees
- send_cmd1(SegRemap | 0x1);
- send_cmd1(ComScanDec);
-# endif
-
- send_cmd2(SetComPins, 0x2);
- send_cmd2(SetContrast, 0x8f);
- send_cmd2(SetPreCharge, 0xf1);
- send_cmd2(SetVComDetect, 0x40);
- send_cmd1(DisplayAllOnResume);
- send_cmd1(NormalDisplay);
- send_cmd1(DeActivateScroll);
- send_cmd1(DisplayOn);
-
- send_cmd2(SetContrast, 0); // Dim
-
- clear_display();
-
- success = true;
-
- iota_gfx_flush();
-
-# if DEBUG_TO_SCREEN
- print_set_sendchar(capture_sendchar);
-# endif
-
-done:
- return success;
-}
-
-bool iota_gfx_off(void) {
- bool success = false;
-
- send_cmd1(DisplayOff);
- success = true;
-
-done:
- return success;
-}
-
-bool iota_gfx_on(void) {
- bool success = false;
-
- send_cmd1(DisplayOn);
- success = true;
-
-done:
- return success;
-}
-
-void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) {
- *matrix->cursor = c;
- ++matrix->cursor;
-
- if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) {
- // We went off the end; scroll the display upwards by one line
- memmove(&matrix->display[0], &matrix->display[1], MatrixCols * (MatrixRows - 1));
- matrix->cursor = &matrix->display[MatrixRows - 1][0];
- memset(matrix->cursor, ' ', MatrixCols);
- }
-}
-
-void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) {
- matrix->dirty = true;
-
- if (c == '\n') {
- // Clear to end of line from the cursor and then move to the
- // start of the next line
- uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols;
-
- while (cursor_col++ < MatrixCols) {
- matrix_write_char_inner(matrix, ' ');
- }
- return;
- }
-
- matrix_write_char_inner(matrix, c);
-}
-
-void iota_gfx_write_char(uint8_t c) { matrix_write_char(&display, c); }
-
-void matrix_write(struct CharacterMatrix *matrix, const char *data) {
- const char *end = data + strlen(data);
- while (data < end) {
- matrix_write_char(matrix, *data);
- ++data;
- }
-}
-
-void iota_gfx_write(const char *data) { matrix_write(&display, data); }
-
-void matrix_write_P(struct CharacterMatrix *matrix, const char *data) {
- while (true) {
- uint8_t c = pgm_read_byte(data);
- if (c == 0) {
- return;
- }
- matrix_write_char(matrix, c);
- ++data;
- }
-}
-
-void iota_gfx_write_P(const char *data) { matrix_write_P(&display, data); }
-
-void matrix_clear(struct CharacterMatrix *matrix) {
- memset(matrix->display, ' ', sizeof(matrix->display));
- matrix->cursor = &matrix->display[0][0];
- matrix->dirty = true;
-}
-
-void iota_gfx_clear_screen(void) { matrix_clear(&display); }
-
-void matrix_render(struct CharacterMatrix *matrix) {
- last_flush = timer_read();
- iota_gfx_on();
-# if DEBUG_TO_SCREEN
- ++displaying;
-# endif
-
- // Move to the home position
- send_cmd3(PageAddr, 0, MatrixRows - 1);
- send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1);
-
- if (i2c_start_write(SSD1306_ADDRESS)) {
- goto done;
- }
- if (i2c_master_write(0x40)) {
- // Data mode
- goto done;
- }
-
- for (uint8_t row = 0; row < MatrixRows; ++row) {
- for (uint8_t col = 0; col < MatrixCols; ++col) {
- const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1));
-
- for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) {
- uint8_t colBits = pgm_read_byte(glyph + glyphCol);
- i2c_master_write(colBits);
- }
-
- // 1 column of space between chars (it's not included in the glyph)
- i2c_master_write(0);
- }
- }
-
- matrix->dirty = false;
-
-done:
- i2c_master_stop();
-# if DEBUG_TO_SCREEN
- --displaying;
-# endif
-}
-
-void iota_gfx_flush(void) { matrix_render(&display); }
-
-__attribute__((weak)) void iota_gfx_task_user(void) {}
-
-void iota_gfx_task(void) {
- iota_gfx_task_user();
-
- if (display.dirty) {
- iota_gfx_flush();
- }
-
- if (timer_elapsed(last_flush) > ScreenOffInterval) {
- iota_gfx_off();
- }
-}
-#endif
diff --git a/drivers/avr/ssd1306.h b/drivers/avr/ssd1306.h
deleted file mode 100644
index 6eecdcfaa4..0000000000
--- a/drivers/avr/ssd1306.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#pragma once
-
-#include <stdbool.h>
-#include <stdio.h>
-#include "config.h"
-
-enum ssd1306_cmds {
- DisplayOff = 0xAE,
- DisplayOn = 0xAF,
-
- SetContrast = 0x81,
- DisplayAllOnResume = 0xA4,
-
- DisplayAllOn = 0xA5,
- NormalDisplay = 0xA6,
- InvertDisplay = 0xA7,
- SetDisplayOffset = 0xD3,
- SetComPins = 0xda,
- SetVComDetect = 0xdb,
- SetDisplayClockDiv = 0xD5,
- SetPreCharge = 0xd9,
- SetMultiPlex = 0xa8,
- SetLowColumn = 0x00,
- SetHighColumn = 0x10,
- SetStartLine = 0x40,
-
- SetMemoryMode = 0x20,
- ColumnAddr = 0x21,
- PageAddr = 0x22,
-
- ComScanInc = 0xc0,
- ComScanDec = 0xc8,
- SegRemap = 0xa0,
- SetChargePump = 0x8d,
- ExternalVcc = 0x01,
- SwitchCapVcc = 0x02,
-
- ActivateScroll = 0x2f,
- DeActivateScroll = 0x2e,
- SetVerticalScrollArea = 0xa3,
- RightHorizontalScroll = 0x26,
- LeftHorizontalScroll = 0x27,
- VerticalAndRightHorizontalScroll = 0x29,
- VerticalAndLeftHorizontalScroll = 0x2a,
-};
-
-// Controls the SSD1306 128x32 OLED display via i2c
-
-#ifndef SSD1306_ADDRESS
-# define SSD1306_ADDRESS 0x3C
-#endif
-
-#define DisplayHeight 32
-#define DisplayWidth 128
-
-#define FontHeight 8
-#define FontWidth 6
-
-#define MatrixRows (DisplayHeight / FontHeight)
-#define MatrixCols (DisplayWidth / FontWidth)
-
-struct CharacterMatrix {
- uint8_t display[MatrixRows][MatrixCols];
- uint8_t *cursor;
- bool dirty;
-};
-
-extern struct CharacterMatrix display;
-
-bool iota_gfx_init(void);
-void iota_gfx_task(void);
-bool iota_gfx_off(void);
-bool iota_gfx_on(void);
-void iota_gfx_flush(void);
-void iota_gfx_write_char(uint8_t c);
-void iota_gfx_write(const char *data);
-void iota_gfx_write_P(const char *data);
-void iota_gfx_clear_screen(void);
-
-void iota_gfx_task_user(void);
-
-void matrix_clear(struct CharacterMatrix *matrix);
-void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c);
-void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c);
-void matrix_write(struct CharacterMatrix *matrix, const char *data);
-void matrix_write_P(struct CharacterMatrix *matrix, const char *data);
-void matrix_render(struct CharacterMatrix *matrix);
diff --git a/drivers/avr/uart.c b/drivers/avr/uart.c
deleted file mode 100644
index c6abcb6fe0..0000000000
--- a/drivers/avr/uart.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* UART Example for Teensy USB Development Board
- * http://www.pjrc.com/teensy/
- * Copyright (c) 2009 PJRC.COM, LLC
- *
- * 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.
- */
-
-// Version 1.0: Initial Release
-// Version 1.1: Add support for Teensy 2.0, minor optimizations
-
-#include <avr/io.h>
-#include <avr/interrupt.h>
-
-#include "uart.h"
-
-#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
-# define UDRn UDR1
-# define UBRRnL UBRR1L
-# define UCSRnA UCSR1A
-# define UCSRnB UCSR1B
-# define UCSRnC UCSR1C
-# define U2Xn U2X1
-# define RXENn RXEN1
-# define TXENn TXEN1
-# define RXCIEn RXCIE1
-# define UCSZn1 UCSZ11
-# define UCSZn0 UCSZ10
-# define UDRIEn UDRIE1
-# define USARTn_UDRE_vect USART1_UDRE_vect
-# define USARTn_RX_vect USART1_RX_vect
-#elif defined(__AVR_ATmega32A__)
-# define UDRn UDR
-# define UBRRnL UBRRL
-# define UCSRnA UCSRA
-# define UCSRnB UCSRB
-# define UCSRnC UCSRC
-# define U2Xn U2X
-# define RXENn RXEN
-# define TXENn TXEN
-# define RXCIEn RXCIE
-# define UCSZn1 UCSZ1
-# define UCSZn0 UCSZ0
-# define UDRIEn UDRIE
-# define USARTn_UDRE_vect USART_UDRE_vect
-# define USARTn_RX_vect USART_RX_vect
-#elif defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
-# define UDRn UDR0
-# define UBRRnL UBRR0L
-# define UCSRnA UCSR0A
-# define UCSRnB UCSR0B
-# define UCSRnC UCSR0C
-# define U2Xn U2X0
-# define RXENn RXEN0
-# define TXENn TXEN0
-# define RXCIEn RXCIE0
-# define UCSZn1 UCSZ01
-# define UCSZn0 UCSZ00
-# define UDRIEn UDRIE0
-# define USARTn_UDRE_vect USART_UDRE_vect
-# define USARTn_RX_vect USART_RX_vect
-#endif
-
-// These buffers may be any size from 2 to 256 bytes.
-#define RX_BUFFER_SIZE 64
-#define TX_BUFFER_SIZE 256
-
-static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
-static volatile uint8_t tx_buffer_head;
-static volatile uint8_t tx_buffer_tail;
-static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
-static volatile uint8_t rx_buffer_head;
-static volatile uint8_t rx_buffer_tail;
-
-// Initialize the UART
-void uart_init(uint32_t baud) {
- cli();
- UBRRnL = (F_CPU / 4 / baud - 1) / 2;
- UCSRnA = (1 << U2Xn);
- UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
- UCSRnC = (1 << UCSZn1) | (1 << UCSZn0);
- tx_buffer_head = tx_buffer_tail = 0;
- rx_buffer_head = rx_buffer_tail = 0;
- sei();
-}
-
-// Transmit a byte
-void uart_putchar(uint8_t c) {
- uint8_t i;
-
- i = tx_buffer_head + 1;
- if (i >= TX_BUFFER_SIZE) i = 0;
- // return immediately to avoid deadlock when interrupt is disabled(called from ISR)
- if (tx_buffer_tail == i && (SREG & (1 << SREG_I)) == 0) return;
- while (tx_buffer_tail == i)
- ; // wait until space in buffer
- // cli();
- tx_buffer[i] = c;
- tx_buffer_head = i;
- UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn) | (1 << UDRIEn);
- // sei();
-}
-
-// Receive a byte
-uint8_t uart_getchar(void) {
- uint8_t c, i;
-
- while (rx_buffer_head == rx_buffer_tail)
- ; // wait for character
- i = rx_buffer_tail + 1;
- if (i >= RX_BUFFER_SIZE) i = 0;
- c = rx_buffer[i];
- rx_buffer_tail = i;
- return c;
-}
-
-// Return whether the number of bytes waiting in the receive buffer is nonzero.
-// Call this before uart_getchar() to check if it will need
-// to wait for a byte to arrive.
-bool uart_available(void) {
- uint8_t head, tail;
-
- head = rx_buffer_head;
- tail = rx_buffer_tail;
- if (head >= tail) return (head - tail) > 0;
- return (RX_BUFFER_SIZE + head - tail) > 0;
-}
-
-// Transmit Interrupt
-ISR(USARTn_UDRE_vect) {
- uint8_t i;
-
- if (tx_buffer_head == tx_buffer_tail) {
- // buffer is empty, disable transmit interrupt
- UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
- } else {
- i = tx_buffer_tail + 1;
- if (i >= TX_BUFFER_SIZE) i = 0;
- UDRn = tx_buffer[i];
- tx_buffer_tail = i;
- }
-}
-
-// Receive Interrupt
-ISR(USARTn_RX_vect) {
- uint8_t c, i;
-
- c = UDRn;
- i = rx_buffer_head + 1;
- if (i >= RX_BUFFER_SIZE) i = 0;
- if (i != rx_buffer_tail) {
- rx_buffer[i] = c;
- rx_buffer_head = i;
- }
-}
diff --git a/drivers/avr/uart.h b/drivers/avr/uart.h
deleted file mode 100644
index 602eb3d8b0..0000000000
--- a/drivers/avr/uart.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* UART Example for Teensy USB Development Board
- * http://www.pjrc.com/teensy/
- * Copyright (c) 2009 PJRC.COM, LLC
- *
- * 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>
-
-void uart_init(uint32_t baud);
-
-void uart_putchar(uint8_t c);
-
-uint8_t uart_getchar(void);
-
-bool uart_available(void);
diff --git a/drivers/avr/ws2812.c b/drivers/avr/ws2812.c
deleted file mode 100644
index 77c492cd4c..0000000000
--- a/drivers/avr/ws2812.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * light weight WS2812 lib V2.0b
- *
- * Controls WS2811/WS2812/WS2812B RGB-LEDs
- * Author: Tim (cpldcpu@gmail.com)
- *
- * Jan 18th, 2014 v2.0b Initial Version
- * Nov 29th, 2015 v2.3 Added SK6812RGBW support
- *
- * 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 "ws2812.h"
-#include <avr/interrupt.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-#define pinmask(pin) (_BV((pin)&0xF))
-
-/*
- * Forward declare internal functions
- *
- * The functions take a byte-array and send to the data output as WS2812 bitstream.
- * The length is the number of bytes to send - three per LED.
- */
-
-static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi);
-
-void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) {
- DDRx_ADDRESS(RGB_DI_PIN) |= pinmask(RGB_DI_PIN);
-
- uint8_t masklo = ~(pinmask(RGB_DI_PIN)) & PORTx_ADDRESS(RGB_DI_PIN);
- uint8_t maskhi = pinmask(RGB_DI_PIN) | PORTx_ADDRESS(RGB_DI_PIN);
-
- ws2812_sendarray_mask((uint8_t *)ledarray, number_of_leds * sizeof(LED_TYPE), masklo, maskhi);
-
- _delay_us(WS2812_TRST_US);
-}
-
-/*
- This routine writes an array of bytes with RGB values to the Dataout pin
- using the fast 800kHz clockless WS2811/2812 protocol.
-*/
-
-// Timing in ns
-#define w_zeropulse 350
-#define w_onepulse 900
-#define w_totalperiod 1250
-
-// Fixed cycles used by the inner loop
-#define w_fixedlow 2
-#define w_fixedhigh 4
-#define w_fixedtotal 8
-
-// Insert NOPs to match the timing, if possible
-#define w_zerocycles (((F_CPU / 1000) * w_zeropulse) / 1000000)
-#define w_onecycles (((F_CPU / 1000) * w_onepulse + 500000) / 1000000)
-#define w_totalcycles (((F_CPU / 1000) * w_totalperiod + 500000) / 1000000)
-
-// w1_nops - nops between rising edge and falling edge - low
-#if w_zerocycles >= w_fixedlow
-# define w1_nops (w_zerocycles - w_fixedlow)
-#else
-# define w1_nops 0
-#endif
-
-// w2_nops - nops between fe low and fe high
-#if w_onecycles >= (w_fixedhigh + w1_nops)
-# define w2_nops (w_onecycles - w_fixedhigh - w1_nops)
-#else
-# define w2_nops 0
-#endif
-
-// w3_nops - nops to complete loop
-#if w_totalcycles >= (w_fixedtotal + w1_nops + w2_nops)
-# define w3_nops (w_totalcycles - w_fixedtotal - w1_nops - w2_nops)
-#else
-# define w3_nops 0
-#endif
-
-// The only critical timing parameter is the minimum pulse length of the "0"
-// Warn or throw error if this timing can not be met with current F_CPU settings.
-#define w_lowtime ((w1_nops + w_fixedlow) * 1000000) / (F_CPU / 1000)
-#if w_lowtime > 550
-# error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?"
-#elif w_lowtime > 450
-# warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)."
-# warning "Please consider a higher clockspeed, if possible"
-#endif
-
-#define w_nop1 "nop \n\t"
-#define w_nop2 "rjmp .+0 \n\t"
-#define w_nop4 w_nop2 w_nop2
-#define w_nop8 w_nop4 w_nop4
-#define w_nop16 w_nop8 w_nop8
-
-static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi) {
- uint8_t curbyte, ctr, sreg_prev;
-
- sreg_prev = SREG;
- cli();
-
- while (datlen--) {
- curbyte = (*data++);
-
- asm volatile(" ldi %0,8 \n\t"
- "loop%=: \n\t"
- " out %2,%3 \n\t" // '1' [01] '0' [01] - re
-#if (w1_nops & 1)
- w_nop1
-#endif
-#if (w1_nops & 2)
- w_nop2
-#endif
-#if (w1_nops & 4)
- w_nop4
-#endif
-#if (w1_nops & 8)
- w_nop8
-#endif
-#if (w1_nops & 16)
- w_nop16
-#endif
- " sbrs %1,7 \n\t" // '1' [03] '0' [02]
- " out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low
- " lsl %1 \n\t" // '1' [04] '0' [04]
-#if (w2_nops & 1)
- w_nop1
-#endif
-#if (w2_nops & 2)
- w_nop2
-#endif
-#if (w2_nops & 4)
- w_nop4
-#endif
-#if (w2_nops & 8)
- w_nop8
-#endif
-#if (w2_nops & 16)
- w_nop16
-#endif
- " out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high
-#if (w3_nops & 1)
- w_nop1
-#endif
-#if (w3_nops & 2)
- w_nop2
-#endif
-#if (w3_nops & 4)
- w_nop4
-#endif
-#if (w3_nops & 8)
- w_nop8
-#endif
-#if (w3_nops & 16)
- w_nop16
-#endif
-
- " dec %0 \n\t" // '1' [+2] '0' [+2]
- " brne loop%=\n\t" // '1' [+3] '0' [+4]
- : "=&d"(ctr)
- : "r"(curbyte), "I"(_SFR_IO_ADDR(PORTx_ADDRESS(RGB_DI_PIN))), "r"(maskhi), "r"(masklo));
- }
-
- SREG = sreg_prev;
-}
diff --git a/drivers/avr/ws2812_i2c.c b/drivers/avr/ws2812_i2c.c
deleted file mode 100644
index 1c332e24b6..0000000000
--- a/drivers/avr/ws2812_i2c.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "ws2812.h"
-#include "i2c_master.h"
-
-#ifdef RGBW
-# error "RGBW not supported"
-#endif
-
-#ifndef WS2812_ADDRESS
-# define WS2812_ADDRESS 0xb0
-#endif
-
-#ifndef WS2812_TIMEOUT
-# define WS2812_TIMEOUT 100
-#endif
-
-void ws2812_init(void) { i2c_init(); }
-
-// Setleds for standard RGB
-void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
- static bool s_init = false;
- if (!s_init) {
- ws2812_init();
- s_init = true;
- }
-
- i2c_transmit(WS2812_ADDRESS, (uint8_t *)ledarray, sizeof(LED_TYPE) * leds, WS2812_TIMEOUT);
-}
diff --git a/drivers/chibios/analog.c b/drivers/chibios/analog.c
deleted file mode 100644
index 8c476fcac2..0000000000
--- a/drivers/chibios/analog.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/* Copyright 2019 Drew Mills
- *
- * 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 "quantum.h"
-#include "analog.h"
-#include <ch.h>
-#include <hal.h>
-
-#if !HAL_USE_ADC
-# error "You need to set HAL_USE_ADC to TRUE in your halconf.h to use the ADC."
-#endif
-
-#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 && !STM32_ADC_USE_ADC4
-# error "You need to set one of the 'STM32_ADC_USE_ADCx' settings to TRUE in your mcuconf.h to use the ADC."
-#endif
-
-#if STM32_ADC_DUAL_MODE
-# error "STM32 ADC Dual Mode is not supported at this time."
-#endif
-
-#if STM32_ADCV3_OVERSAMPLING
-# error "STM32 ADCV3 Oversampling is not supported at this time."
-#endif
-
-// Otherwise assume V3
-#if defined(STM32F0XX) || defined(STM32L0XX)
-# define USE_ADCV1
-#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX)
-# define USE_ADCV2
-#endif
-
-// BODGE to make v2 look like v1,3 and 4
-#ifdef USE_ADCV2
-# if !defined(ADC_SMPR_SMP_1P5) && defined(ADC_SAMPLE_3)
-# define ADC_SMPR_SMP_1P5 ADC_SAMPLE_3
-# define ADC_SMPR_SMP_7P5 ADC_SAMPLE_15
-# define ADC_SMPR_SMP_13P5 ADC_SAMPLE_28
-# define ADC_SMPR_SMP_28P5 ADC_SAMPLE_56
-# define ADC_SMPR_SMP_41P5 ADC_SAMPLE_84
-# define ADC_SMPR_SMP_55P5 ADC_SAMPLE_112
-# define ADC_SMPR_SMP_71P5 ADC_SAMPLE_144
-# define ADC_SMPR_SMP_239P5 ADC_SAMPLE_480
-# endif
-
-# if !defined(ADC_SMPR_SMP_1P5) && defined(ADC_SAMPLE_1P5)
-# define ADC_SMPR_SMP_1P5 ADC_SAMPLE_1P5
-# define ADC_SMPR_SMP_7P5 ADC_SAMPLE_7P5
-# define ADC_SMPR_SMP_13P5 ADC_SAMPLE_13P5
-# define ADC_SMPR_SMP_28P5 ADC_SAMPLE_28P5
-# define ADC_SMPR_SMP_41P5 ADC_SAMPLE_41P5
-# define ADC_SMPR_SMP_55P5 ADC_SAMPLE_55P5
-# define ADC_SMPR_SMP_71P5 ADC_SAMPLE_71P5
-# define ADC_SMPR_SMP_239P5 ADC_SAMPLE_239P5
-# endif
-
-// we still sample at 12bit, but scale down to the requested bit range
-# define ADC_CFGR1_RES_12BIT 12
-# define ADC_CFGR1_RES_10BIT 10
-# define ADC_CFGR1_RES_8BIT 8
-# define ADC_CFGR1_RES_6BIT 6
-#endif
-
-/* User configurable ADC options */
-#ifndef ADC_COUNT
-# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX)
-# define ADC_COUNT 1
-# elif defined(STM32F3XX)
-# define ADC_COUNT 4
-# else
-# error "ADC_COUNT has not been set for this ARM microcontroller."
-# endif
-#endif
-
-#ifndef ADC_NUM_CHANNELS
-# define ADC_NUM_CHANNELS 1
-#elif ADC_NUM_CHANNELS != 1
-# error "The ARM ADC implementation currently only supports reading one channel at a time."
-#endif
-
-#ifndef ADC_BUFFER_DEPTH
-# define ADC_BUFFER_DEPTH 1
-#endif
-
-// For more sampling rate options, look at hal_adc_lld.h in ChibiOS
-#ifndef ADC_SAMPLING_RATE
-# define ADC_SAMPLING_RATE ADC_SMPR_SMP_1P5
-#endif
-
-// Options are 12, 10, 8, and 6 bit.
-#ifndef ADC_RESOLUTION
-# ifdef ADC_CFGR_RES_10BITS // ADCv3, ADCv4
-# define ADC_RESOLUTION ADC_CFGR_RES_10BITS
-# else // ADCv1, ADCv5, or the bodge for ADCv2 above
-# define ADC_RESOLUTION ADC_CFGR1_RES_10BIT
-# endif
-#endif
-
-static ADCConfig adcCfg = {};
-static adcsample_t sampleBuffer[ADC_NUM_CHANNELS * ADC_BUFFER_DEPTH];
-
-// Initialize to max number of ADCs, set to empty object to initialize all to false.
-static bool adcInitialized[ADC_COUNT] = {};
-
-// TODO: add back TR handling???
-static ADCConversionGroup adcConversionGroup = {
- .circular = FALSE,
- .num_channels = (uint16_t)(ADC_NUM_CHANNELS),
-#if defined(USE_ADCV1)
- .cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION,
- .smpr = ADC_SAMPLING_RATE,
-#elif defined(USE_ADCV2)
-# if !defined(STM32F1XX)
- .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without...
-# endif
- .smpr2 = ADC_SMPR2_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN9(ADC_SAMPLING_RATE),
- .smpr1 = ADC_SMPR1_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN15(ADC_SAMPLING_RATE),
-#else
- .cfgr = ADC_CFGR_CONT | ADC_RESOLUTION,
- .smpr = {ADC_SMPR1_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN9(ADC_SAMPLING_RATE), ADC_SMPR2_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN15(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN16(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN17(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN18(ADC_SAMPLING_RATE)},
-#endif
-};
-
-// clang-format off
-__attribute__((weak)) adc_mux pinToMux(pin_t pin) {
- switch (pin) {
-#if defined(STM32F0XX)
- case A0: return TO_MUX( ADC_CHSELR_CHSEL0, 0 );
- case A1: return TO_MUX( ADC_CHSELR_CHSEL1, 0 );
- case A2: return TO_MUX( ADC_CHSELR_CHSEL2, 0 );
- case A3: return TO_MUX( ADC_CHSELR_CHSEL3, 0 );
- case A4: return TO_MUX( ADC_CHSELR_CHSEL4, 0 );
- case A5: return TO_MUX( ADC_CHSELR_CHSEL5, 0 );
- case A6: return TO_MUX( ADC_CHSELR_CHSEL6, 0 );
- case A7: return TO_MUX( ADC_CHSELR_CHSEL7, 0 );
- case B0: return TO_MUX( ADC_CHSELR_CHSEL8, 0 );
- case B1: return TO_MUX( ADC_CHSELR_CHSEL9, 0 );
- case C0: return TO_MUX( ADC_CHSELR_CHSEL10, 0 );
- case C1: return TO_MUX( ADC_CHSELR_CHSEL11, 0 );
- case C2: return TO_MUX( ADC_CHSELR_CHSEL12, 0 );
- case C3: return TO_MUX( ADC_CHSELR_CHSEL13, 0 );
- case C4: return TO_MUX( ADC_CHSELR_CHSEL14, 0 );
- case C5: return TO_MUX( ADC_CHSELR_CHSEL15, 0 );
-#elif defined(STM32F3XX)
- case A0: return TO_MUX( ADC_CHANNEL_IN1, 0 );
- case A1: return TO_MUX( ADC_CHANNEL_IN2, 0 );
- case A2: return TO_MUX( ADC_CHANNEL_IN3, 0 );
- case A3: return TO_MUX( ADC_CHANNEL_IN4, 0 );
- case A4: return TO_MUX( ADC_CHANNEL_IN1, 1 );
- case A5: return TO_MUX( ADC_CHANNEL_IN2, 1 );
- case A6: return TO_MUX( ADC_CHANNEL_IN3, 1 );
- case A7: return TO_MUX( ADC_CHANNEL_IN4, 1 );
- case B0: return TO_MUX( ADC_CHANNEL_IN12, 2 );
- case B1: return TO_MUX( ADC_CHANNEL_IN1, 2 );
- case B2: return TO_MUX( ADC_CHANNEL_IN12, 1 );
- case B12: return TO_MUX( ADC_CHANNEL_IN3, 3 );
- case B13: return TO_MUX( ADC_CHANNEL_IN5, 2 );
- case B14: return TO_MUX( ADC_CHANNEL_IN4, 3 );
- case B15: return TO_MUX( ADC_CHANNEL_IN5, 3 );
- case C0: return TO_MUX( ADC_CHANNEL_IN6, 0 ); // Can also be ADC2
- case C1: return TO_MUX( ADC_CHANNEL_IN7, 0 ); // Can also be ADC2
- case C2: return TO_MUX( ADC_CHANNEL_IN8, 0 ); // Can also be ADC2
- case C3: return TO_MUX( ADC_CHANNEL_IN9, 0 ); // Can also be ADC2
- case C4: return TO_MUX( ADC_CHANNEL_IN5, 1 );
- case C5: return TO_MUX( ADC_CHANNEL_IN11, 1 );
- case D8: return TO_MUX( ADC_CHANNEL_IN12, 3 );
- case D9: return TO_MUX( ADC_CHANNEL_IN13, 3 );
- case D10: return TO_MUX( ADC_CHANNEL_IN7, 2 ); // Can also be ADC4
- case D11: return TO_MUX( ADC_CHANNEL_IN8, 2 ); // Can also be ADC4
- case D12: return TO_MUX( ADC_CHANNEL_IN9, 2 ); // Can also be ADC4
- case D13: return TO_MUX( ADC_CHANNEL_IN10, 2 ); // Can also be ADC4
- case D14: return TO_MUX( ADC_CHANNEL_IN11, 2 ); // Can also be ADC4
- case E7: return TO_MUX( ADC_CHANNEL_IN13, 2 );
- case E8: return TO_MUX( ADC_CHANNEL_IN6, 2 ); // Can also be ADC4
- case E9: return TO_MUX( ADC_CHANNEL_IN2, 2 );
- case E10: return TO_MUX( ADC_CHANNEL_IN14, 2 );
- case E11: return TO_MUX( ADC_CHANNEL_IN15, 2 );
- case E12: return TO_MUX( ADC_CHANNEL_IN16, 2 );
- case E13: return TO_MUX( ADC_CHANNEL_IN3, 2 );
- case E14: return TO_MUX( ADC_CHANNEL_IN1, 3 );
- case E15: return TO_MUX( ADC_CHANNEL_IN2, 3 );
- case F2: return TO_MUX( ADC_CHANNEL_IN10, 0 ); // Can also be ADC2
- case F4: return TO_MUX( ADC_CHANNEL_IN5, 0 );
-#elif defined(STM32F4XX)
- case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 );
- case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 );
- case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 );
- case A3: return TO_MUX( ADC_CHANNEL_IN3, 0 );
- case A4: return TO_MUX( ADC_CHANNEL_IN4, 0 );
- case A5: return TO_MUX( ADC_CHANNEL_IN5, 0 );
- case A6: return TO_MUX( ADC_CHANNEL_IN6, 0 );
- case A7: return TO_MUX( ADC_CHANNEL_IN7, 0 );
- case B0: return TO_MUX( ADC_CHANNEL_IN8, 0 );
- case B1: return TO_MUX( ADC_CHANNEL_IN9, 0 );
- case C0: return TO_MUX( ADC_CHANNEL_IN10, 0 );
- case C1: return TO_MUX( ADC_CHANNEL_IN11, 0 );
- case C2: return TO_MUX( ADC_CHANNEL_IN12, 0 );
- case C3: return TO_MUX( ADC_CHANNEL_IN13, 0 );
- case C4: return TO_MUX( ADC_CHANNEL_IN14, 0 );
- case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 );
-# if STM32_ADC_USE_ADC3
- case F3: return TO_MUX( ADC_CHANNEL_IN9, 2 );
- case F4: return TO_MUX( ADC_CHANNEL_IN14, 2 );
- case F5: return TO_MUX( ADC_CHANNEL_IN15, 2 );
- case F6: return TO_MUX( ADC_CHANNEL_IN4, 2 );
- case F7: return TO_MUX( ADC_CHANNEL_IN5, 2 );
- case F8: return TO_MUX( ADC_CHANNEL_IN6, 2 );
- case F9: return TO_MUX( ADC_CHANNEL_IN7, 2 );
- case F10: return TO_MUX( ADC_CHANNEL_IN8, 2 );
-# endif
-#elif defined(STM32F1XX)
- case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 );
- case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 );
- case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 );
- case A3: return TO_MUX( ADC_CHANNEL_IN3, 0 );
- case A4: return TO_MUX( ADC_CHANNEL_IN4, 0 );
- case A5: return TO_MUX( ADC_CHANNEL_IN5, 0 );
- case A6: return TO_MUX( ADC_CHANNEL_IN6, 0 );
- case A7: return TO_MUX( ADC_CHANNEL_IN7, 0 );
- case B0: return TO_MUX( ADC_CHANNEL_IN8, 0 );
- case B1: return TO_MUX( ADC_CHANNEL_IN9, 0 );
- case C0: return TO_MUX( ADC_CHANNEL_IN10, 0 );
- case C1: return TO_MUX( ADC_CHANNEL_IN11, 0 );
- case C2: return TO_MUX( ADC_CHANNEL_IN12, 0 );
- case C3: return TO_MUX( ADC_CHANNEL_IN13, 0 );
- case C4: return TO_MUX( ADC_CHANNEL_IN14, 0 );
- case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 );
- // STM32F103x[C-G] in 144-pin packages also have analog inputs on F6...F10, but they are on ADC3, and the
- // ChibiOS ADC driver for STM32F1xx currently supports only ADC1, therefore these pins are not usable.
-#endif
- }
-
- // return an adc that would never be used so intToADCDriver will bail out
- return TO_MUX(0, 0xFF);
-}
-// clang-format on
-
-static inline ADCDriver* intToADCDriver(uint8_t adcInt) {
- switch (adcInt) {
-#if STM32_ADC_USE_ADC1
- case 0:
- return &ADCD1;
-#endif
-#if STM32_ADC_USE_ADC2
- case 1:
- return &ADCD2;
-#endif
-#if STM32_ADC_USE_ADC3
- case 2:
- return &ADCD3;
-#endif
-#if STM32_ADC_USE_ADC4
- case 3:
- return &ADCD4;
-#endif
- }
-
- return NULL;
-}
-
-static inline void manageAdcInitializationDriver(uint8_t adc, ADCDriver* adcDriver) {
- if (!adcInitialized[adc]) {
- adcStart(adcDriver, &adcCfg);
- adcInitialized[adc] = true;
- }
-}
-
-int16_t analogReadPin(pin_t pin) {
- palSetLineMode(pin, PAL_MODE_INPUT_ANALOG);
-
- return adc_read(pinToMux(pin));
-}
-
-int16_t analogReadPinAdc(pin_t pin, uint8_t adc) {
- palSetLineMode(pin, PAL_MODE_INPUT_ANALOG);
-
- adc_mux target = pinToMux(pin);
- target.adc = adc;
- return adc_read(target);
-}
-
-int16_t adc_read(adc_mux mux) {
-#if defined(USE_ADCV1)
- // TODO: fix previous assumption of only 1 input...
- adcConversionGroup.chselr = 1 << mux.input; /*no macro to convert N to ADC_CHSELR_CHSEL1*/
-#elif defined(USE_ADCV2)
- adcConversionGroup.sqr3 = ADC_SQR3_SQ1_N(mux.input);
-#else
- adcConversionGroup.sqr[0] = ADC_SQR1_SQ1_N(mux.input);
-#endif
-
- ADCDriver* targetDriver = intToADCDriver(mux.adc);
- if (!targetDriver) {
- return 0;
- }
-
- manageAdcInitializationDriver(mux.adc, targetDriver);
- if (adcConvert(targetDriver, &adcConversionGroup, &sampleBuffer[0], ADC_BUFFER_DEPTH) != MSG_OK) {
- return 0;
- }
-
-#ifdef USE_ADCV2
- // fake 12-bit -> N-bit scale
- return (*sampleBuffer) >> (12 - ADC_RESOLUTION);
-#else
- // already handled as part of adcConvert
- return *sampleBuffer;
-#endif
-}
diff --git a/drivers/chibios/i2c_master.c b/drivers/chibios/i2c_master.c
deleted file mode 100644
index fc4bb2ab37..0000000000
--- a/drivers/chibios/i2c_master.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* Copyright 2018 Jack Humbert
- * Copyright 2018 Yiancar
- *
- * 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/>.
- */
-
-/* This library is only valid for STM32 processors.
- * This library follows the convention of the AVR i2c_master library.
- * As a result addresses are expected to be already shifted (addr << 1).
- * I2CD1 is the default driver which corresponds to pins B6 and B7. This
- * can be changed.
- * Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that
- * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. Pins B6 and B7 are used
- * but using any other I2C pins should be trivial.
- */
-#include "quantum.h"
-#include "i2c_master.h"
-#include <string.h>
-#include <hal.h>
-
-static uint8_t i2c_address;
-
-static const I2CConfig i2cconfig = {
-#if defined(USE_I2CV1_CONTRIB)
- I2C1_CLOCK_SPEED,
-#elif defined(USE_I2CV1)
- I2C1_OPMODE,
- I2C1_CLOCK_SPEED,
- I2C1_DUTY_CYCLE,
-#else
- // This configures the I2C clock to 400khz assuming a 72Mhz clock
- // For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
- STM32_TIMINGR_PRESC(I2C1_TIMINGR_PRESC) | STM32_TIMINGR_SCLDEL(I2C1_TIMINGR_SCLDEL) | STM32_TIMINGR_SDADEL(I2C1_TIMINGR_SDADEL) | STM32_TIMINGR_SCLH(I2C1_TIMINGR_SCLH) | STM32_TIMINGR_SCLL(I2C1_TIMINGR_SCLL), 0, 0
-#endif
-};
-
-static i2c_status_t chibios_to_qmk(const msg_t* status) {
- switch (*status) {
- case I2C_NO_ERROR:
- return I2C_STATUS_SUCCESS;
- case I2C_TIMEOUT:
- return I2C_STATUS_TIMEOUT;
- // I2C_BUS_ERROR, I2C_ARBITRATION_LOST, I2C_ACK_FAILURE, I2C_OVERRUN, I2C_PEC_ERROR, I2C_SMB_ALERT
- default:
- return I2C_STATUS_ERROR;
- }
-}
-
-__attribute__((weak)) void i2c_init(void) {
- static bool is_initialised = false;
- if (!is_initialised) {
- is_initialised = true;
-
- // Try releasing special pins for a short time
- palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_INPUT);
- palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT);
-
- chThdSleepMilliseconds(10);
-#if defined(USE_GPIOV1)
- palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, I2C1_SCL_PAL_MODE);
- palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, I2C1_SDA_PAL_MODE);
-#else
- palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
- palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
-#endif
- }
-}
-
-i2c_status_t i2c_start(uint8_t address) {
- i2c_address = address;
- i2cStart(&I2C_DRIVER, &i2cconfig);
- return I2C_STATUS_SUCCESS;
-}
-
-i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_address = address;
- i2cStart(&I2C_DRIVER, &i2cconfig);
- msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout));
- return chibios_to_qmk(&status);
-}
-
-i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_address = address;
- i2cStart(&I2C_DRIVER, &i2cconfig);
- msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, TIME_MS2I(timeout));
- return chibios_to_qmk(&status);
-}
-
-i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_address = devaddr;
- i2cStart(&I2C_DRIVER, &i2cconfig);
-
- uint8_t complete_packet[length + 1];
- for (uint8_t i = 0; i < length; i++) {
- complete_packet[i + 1] = data[i];
- }
- complete_packet[0] = regaddr;
-
- msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout));
- return chibios_to_qmk(&status);
-}
-
-i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
- i2c_address = devaddr;
- i2cStart(&I2C_DRIVER, &i2cconfig);
- msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), &regaddr, 1, data, length, TIME_MS2I(timeout));
- return chibios_to_qmk(&status);
-}
-
-void i2c_stop(void) { i2cStop(&I2C_DRIVER); }
diff --git a/drivers/chibios/i2c_master.h b/drivers/chibios/i2c_master.h
deleted file mode 100644
index c68109acbd..0000000000
--- a/drivers/chibios/i2c_master.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Copyright 2018 Jack Humbert
- * Copyright 2018 Yiancar
- *
- * 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/>.
- */
-
-/* This library follows the convention of the AVR i2c_master library.
- * As a result addresses are expected to be already shifted (addr << 1).
- * I2CD1 is the default driver which corresponds to pins B6 and B7. This
- * can be changed.
- * Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that
- * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file.
- */
-#pragma once
-
-#include <ch.h>
-#include <hal.h>
-
-#ifdef I2C1_BANK
-# define I2C1_SCL_BANK I2C1_BANK
-# define I2C1_SDA_BANK I2C1_BANK
-#endif
-
-#ifndef I2C1_SCL_BANK
-# define I2C1_SCL_BANK GPIOB
-#endif
-
-#ifndef I2C1_SDA_BANK
-# define I2C1_SDA_BANK GPIOB
-#endif
-
-#ifndef I2C1_SCL
-# define I2C1_SCL 6
-#endif
-#ifndef I2C1_SDA
-# define I2C1_SDA 7
-#endif
-
-#ifdef USE_I2CV1
-# ifndef I2C1_OPMODE
-# define I2C1_OPMODE OPMODE_I2C
-# endif
-# ifndef I2C1_CLOCK_SPEED
-# define I2C1_CLOCK_SPEED 100000 /* 400000 */
-# endif
-# ifndef I2C1_DUTY_CYCLE
-# define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */
-# endif
-#else
-// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock
-// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
-# ifndef I2C1_TIMINGR_PRESC
-# define I2C1_TIMINGR_PRESC 0U
-# endif
-# ifndef I2C1_TIMINGR_SCLDEL
-# define I2C1_TIMINGR_SCLDEL 7U
-# endif
-# ifndef I2C1_TIMINGR_SDADEL
-# define I2C1_TIMINGR_SDADEL 0U
-# endif
-# ifndef I2C1_TIMINGR_SCLH
-# define I2C1_TIMINGR_SCLH 38U
-# endif
-# ifndef I2C1_TIMINGR_SCLL
-# define I2C1_TIMINGR_SCLL 129U
-# endif
-#endif
-
-#ifndef I2C_DRIVER
-# define I2C_DRIVER I2CD1
-#endif
-
-#ifdef USE_GPIOV1
-# ifndef I2C1_SCL_PAL_MODE
-# define I2C1_SCL_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
-# endif
-# ifndef I2C1_SDA_PAL_MODE
-# define I2C1_SDA_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
-# endif
-#else
-// The default PAL alternate modes are used to signal that the pins are used for I2C
-# ifndef I2C1_SCL_PAL_MODE
-# define I2C1_SCL_PAL_MODE 4
-# endif
-# ifndef I2C1_SDA_PAL_MODE
-# define I2C1_SDA_PAL_MODE 4
-# endif
-#endif
-
-typedef int16_t i2c_status_t;
-
-#define I2C_STATUS_SUCCESS (0)
-#define I2C_STATUS_ERROR (-1)
-#define I2C_STATUS_TIMEOUT (-2)
-
-void i2c_init(void);
-i2c_status_t i2c_start(uint8_t address);
-i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
-i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
-void i2c_stop(void);
diff --git a/drivers/chibios/serial.c b/drivers/chibios/serial.c
deleted file mode 100644
index 54f7e1321f..0000000000
--- a/drivers/chibios/serial.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * WARNING: be careful changing this code, it is very timing dependent
- */
-
-#include "quantum.h"
-#include "serial.h"
-#include "wait.h"
-
-#include <hal.h>
-
-// TODO: resolve/remove build warnings
-#if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) && defined(PROTOCOL_CHIBIOS) && defined(WS2812_DRIVER_BITBANG)
-# warning "RGBLED_SPLIT not supported with bitbang WS2812 driver"
-#endif
-
-// default wait implementation cannot be called within interrupt
-// this method seems to be more accurate than GPT timers
-#if PORT_SUPPORTS_RT == FALSE
-# error "chSysPolledDelayX method not supported on this platform"
-#else
-# undef wait_us
-# define wait_us(x) chSysPolledDelayX(US2RTC(STM32_SYSCLK, x))
-#endif
-
-#ifndef SELECT_SOFT_SERIAL_SPEED
-# define SELECT_SOFT_SERIAL_SPEED 1
-// TODO: correct speeds...
-// 0: about 189kbps (Experimental only)
-// 1: about 137kbps (default)
-// 2: about 75kbps
-// 3: about 39kbps
-// 4: about 26kbps
-// 5: about 20kbps
-#endif
-
-// Serial pulse period in microseconds. At the moment, going lower than 12 causes communication failure
-#if SELECT_SOFT_SERIAL_SPEED == 0
-# define SERIAL_DELAY 12
-#elif SELECT_SOFT_SERIAL_SPEED == 1
-# define SERIAL_DELAY 16
-#elif SELECT_SOFT_SERIAL_SPEED == 2
-# define SERIAL_DELAY 24
-#elif SELECT_SOFT_SERIAL_SPEED == 3
-# define SERIAL_DELAY 32
-#elif SELECT_SOFT_SERIAL_SPEED == 4
-# define SERIAL_DELAY 48
-#elif SELECT_SOFT_SERIAL_SPEED == 5
-# define SERIAL_DELAY 64
-#else
-# error invalid SELECT_SOFT_SERIAL_SPEED value
-#endif
-
-inline static void serial_delay(void) { wait_us(SERIAL_DELAY); }
-inline static void serial_delay_half(void) { wait_us(SERIAL_DELAY / 2); }
-inline static void serial_delay_blip(void) { wait_us(1); }
-inline static void serial_output(void) { setPinOutput(SOFT_SERIAL_PIN); }
-inline static void serial_input(void) { setPinInputHigh(SOFT_SERIAL_PIN); }
-inline static bool serial_read_pin(void) { return !!readPin(SOFT_SERIAL_PIN); }
-inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); }
-inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); }
-
-void interrupt_handler(void *arg);
-
-// Use thread + palWaitLineTimeout instead of palSetLineCallback
-// - Methods like setPinOutput and palEnableLineEvent/palDisableLineEvent
-// cause the interrupt to lock up, which would limit to only receiving data...
-static THD_WORKING_AREA(waThread1, 128);
-static THD_FUNCTION(Thread1, arg) {
- (void)arg;
- chRegSetThreadName("blinker");
- while (true) {
- palWaitLineTimeout(SOFT_SERIAL_PIN, TIME_INFINITE);
- interrupt_handler(NULL);
- }
-}
-
-static SSTD_t *Transaction_table = NULL;
-static uint8_t Transaction_table_size = 0;
-
-void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) {
- Transaction_table = sstd_table;
- Transaction_table_size = (uint8_t)sstd_table_size;
-
- serial_output();
- serial_high();
-}
-
-void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) {
- Transaction_table = sstd_table;
- Transaction_table_size = (uint8_t)sstd_table_size;
-
- serial_input();
-
- palEnablePadEvent(PAL_PORT(SOFT_SERIAL_PIN), PAL_PAD(SOFT_SERIAL_PIN), PAL_EVENT_MODE_FALLING_EDGE);
- chThdCreateStatic(waThread1, sizeof(waThread1), HIGHPRIO, Thread1, NULL);
-}
-
-// Used by the master to synchronize timing with the slave.
-static void __attribute__((noinline)) sync_recv(void) {
- serial_input();
- // This shouldn't hang if the slave disconnects because the
- // serial line will float to high if the slave does disconnect.
- while (!serial_read_pin()) {
- }
-
- serial_delay();
-}
-
-// Used by the slave to send a synchronization signal to the master.
-static void __attribute__((noinline)) sync_send(void) {
- serial_output();
-
- serial_low();
- serial_delay();
-
- serial_high();
-}
-
-// Reads a byte from the serial line
-static uint8_t __attribute__((noinline)) serial_read_byte(void) {
- uint8_t byte = 0;
- serial_input();
- for (uint8_t i = 0; i < 8; ++i) {
- byte = (byte << 1) | serial_read_pin();
- serial_delay();
- }
-
- return byte;
-}
-
-// Sends a byte with MSB ordering
-static void __attribute__((noinline)) serial_write_byte(uint8_t data) {
- uint8_t b = 8;
- serial_output();
- while (b--) {
- if (data & (1 << b)) {
- serial_high();
- } else {
- serial_low();
- }
- serial_delay();
- }
-}
-
-// interrupt handle to be used by the slave device
-void interrupt_handler(void *arg) {
- chSysLockFromISR();
-
- sync_send();
-
- // read mid pulses
- serial_delay_blip();
-
- uint8_t checksum_computed = 0;
- int sstd_index = 0;
-
-#ifdef SERIAL_USE_MULTI_TRANSACTION
- sstd_index = serial_read_byte();
- sync_send();
-#endif
-
- SSTD_t *trans = &Transaction_table[sstd_index];
- for (int i = 0; i < trans->initiator2target_buffer_size; ++i) {
- trans->initiator2target_buffer[i] = serial_read_byte();
- sync_send();
- checksum_computed += trans->initiator2target_buffer[i];
- }
- checksum_computed ^= 7;
- uint8_t checksum_received = serial_read_byte();
- sync_send();
-
- // wait for the sync to finish sending
- serial_delay();
-
- uint8_t checksum = 0;
- for (int i = 0; i < trans->target2initiator_buffer_size; ++i) {
- serial_write_byte(trans->target2initiator_buffer[i]);
- sync_send();
- serial_delay_half();
- checksum += trans->target2initiator_buffer[i];
- }
- serial_write_byte(checksum ^ 7);
- sync_send();
-
- // wait for the sync to finish sending
- serial_delay();
-
- *trans->status = (checksum_computed == checksum_received) ? TRANSACTION_ACCEPTED : TRANSACTION_DATA_ERROR;
-
- // end transaction
- serial_input();
-
- // TODO: remove extra delay between transactions
- serial_delay();
-
- chSysUnlockFromISR();
-}
-
-/////////
-// start transaction by initiator
-//
-// int soft_serial_transaction(int sstd_index)
-//
-// Returns:
-// TRANSACTION_END
-// TRANSACTION_NO_RESPONSE
-// TRANSACTION_DATA_ERROR
-// this code is very time dependent, so we need to disable interrupts
-#ifndef SERIAL_USE_MULTI_TRANSACTION
-int soft_serial_transaction(void) {
- int sstd_index = 0;
-#else
-int soft_serial_transaction(int sstd_index) {
-#endif
-
- if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR;
- SSTD_t *trans = &Transaction_table[sstd_index];
-
- // TODO: remove extra delay between transactions
- serial_delay();
-
- // this code is very time dependent, so we need to disable interrupts
- chSysLock();
-
- // signal to the slave that we want to start a transaction
- serial_output();
- serial_low();
- serial_delay_blip();
-
- // wait for the slaves response
- serial_input();
- serial_high();
- serial_delay();
-
- // check if the slave is present
- if (serial_read_pin()) {
- // slave failed to pull the line low, assume not present
- dprintf("serial::NO_RESPONSE\n");
- chSysUnlock();
- return TRANSACTION_NO_RESPONSE;
- }
-
- // if the slave is present syncronize with it
-
- uint8_t checksum = 0;
- // send data to the slave
-#ifdef SERIAL_USE_MULTI_TRANSACTION
- serial_write_byte(sstd_index); // first chunk is transaction id
- sync_recv();
-#endif
- for (int i = 0; i < trans->initiator2target_buffer_size; ++i) {
- serial_write_byte(trans->initiator2target_buffer[i]);
- sync_recv();
- checksum += trans->initiator2target_buffer[i];
- }
- serial_write_byte(checksum ^ 7);
- sync_recv();
-
- serial_delay();
- serial_delay(); // read mid pulses
-
- // receive data from the slave
- uint8_t checksum_computed = 0;
- for (int i = 0; i < trans->target2initiator_buffer_size; ++i) {
- trans->target2initiator_buffer[i] = serial_read_byte();
- sync_recv();
- checksum_computed += trans->target2initiator_buffer[i];
- }
- checksum_computed ^= 7;
- uint8_t checksum_received = serial_read_byte();
-
- sync_recv();
- serial_delay();
-
- if ((checksum_computed) != (checksum_received)) {
- dprintf("serial::FAIL[%u,%u,%u]\n", checksum_computed, checksum_received, sstd_index);
- serial_output();
- serial_high();
-
- chSysUnlock();
- return TRANSACTION_DATA_ERROR;
- }
-
- // always, release the line when not in use
- serial_high();
- serial_output();
-
- chSysUnlock();
- return TRANSACTION_END;
-}
diff --git a/drivers/chibios/serial.h b/drivers/chibios/serial.h
deleted file mode 100644
index 0c1857d52e..0000000000
--- a/drivers/chibios/serial.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#pragma once
-
-#include <stdbool.h>
-
-// /////////////////////////////////////////////////////////////////
-// Need Soft Serial defines in config.h
-// /////////////////////////////////////////////////////////////////
-// ex.
-// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6
-// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5
-// // 1: about 137kbps (default)
-// // 2: about 75kbps
-// // 3: about 39kbps
-// // 4: about 26kbps
-// // 5: about 20kbps
-//
-// //// USE simple API (using signle-type transaction function)
-// /* nothing */
-// //// USE flexible API (using multi-type transaction function)
-// #define SERIAL_USE_MULTI_TRANSACTION
-//
-// /////////////////////////////////////////////////////////////////
-
-// Soft Serial Transaction Descriptor
-typedef struct _SSTD_t {
- uint8_t *status;
- uint8_t initiator2target_buffer_size;
- uint8_t *initiator2target_buffer;
- uint8_t target2initiator_buffer_size;
- uint8_t *target2initiator_buffer;
-} SSTD_t;
-#define TID_LIMIT(table) (sizeof(table) / sizeof(SSTD_t))
-
-// initiator is transaction start side
-void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size);
-// target is interrupt accept side
-void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size);
-
-// initiator result
-#define TRANSACTION_END 0
-#define TRANSACTION_NO_RESPONSE 0x1
-#define TRANSACTION_DATA_ERROR 0x2
-#define TRANSACTION_TYPE_ERROR 0x4
-#ifndef SERIAL_USE_MULTI_TRANSACTION
-int soft_serial_transaction(void);
-#else
-int soft_serial_transaction(int sstd_index);
-#endif
-
-// target status
-// *SSTD_t.status has
-// initiator:
-// TRANSACTION_END
-// or TRANSACTION_NO_RESPONSE
-// or TRANSACTION_DATA_ERROR
-// target:
-// TRANSACTION_DATA_ERROR
-// or TRANSACTION_ACCEPTED
-#define TRANSACTION_ACCEPTED 0x8
-#ifdef SERIAL_USE_MULTI_TRANSACTION
-int soft_serial_get_and_clean_status(int sstd_index);
-#endif
diff --git a/drivers/chibios/serial_usart.c b/drivers/chibios/serial_usart.c
deleted file mode 100644
index 63ba83a801..0000000000
--- a/drivers/chibios/serial_usart.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/* Copyright 2021 QMK
- *
- * 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 3 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 "serial_usart.h"
-
-#ifndef USE_GPIOV1
-// The default PAL alternate modes are used to signal that the pins are used for USART
-# ifndef SERIAL_USART_TX_PAL_MODE
-# define SERIAL_USART_TX_PAL_MODE 7
-# endif
-#endif
-
-#ifndef SERIAL_USART_DRIVER
-# define SERIAL_USART_DRIVER SD1
-#endif
-
-#ifdef SOFT_SERIAL_PIN
-# define SERIAL_USART_TX_PIN SOFT_SERIAL_PIN
-#endif
-
-static inline msg_t sdWriteHalfDuplex(SerialDriver* driver, uint8_t* data, uint8_t size) {
- msg_t ret = sdWrite(driver, data, size);
-
- // Half duplex requires us to read back the data we just wrote - just throw it away
- uint8_t dump[size];
- sdRead(driver, dump, size);
-
- return ret;
-}
-#undef sdWrite
-#define sdWrite sdWriteHalfDuplex
-
-static inline msg_t sdWriteTimeoutHalfDuplex(SerialDriver* driver, uint8_t* data, uint8_t size, uint32_t timeout) {
- msg_t ret = sdWriteTimeout(driver, data, size, timeout);
-
- // Half duplex requires us to read back the data we just wrote - just throw it away
- uint8_t dump[size];
- sdReadTimeout(driver, dump, size, timeout);
-
- return ret;
-}
-#undef sdWriteTimeout
-#define sdWriteTimeout sdWriteTimeoutHalfDuplex
-
-static inline void sdClear(SerialDriver* driver) {
- while (sdGetTimeout(driver, TIME_IMMEDIATE) != MSG_TIMEOUT) {
- // Do nothing with the data
- }
-}
-
-static SerialConfig sdcfg = {
- (SERIAL_USART_SPEED), // speed - mandatory
- (SERIAL_USART_CR1), // CR1
- (SERIAL_USART_CR2), // CR2
- (SERIAL_USART_CR3) // CR3
-};
-
-void handle_soft_serial_slave(void);
-
-/*
- * This thread runs on the slave and responds to transactions initiated
- * by the master
- */
-static THD_WORKING_AREA(waSlaveThread, 2048);
-static THD_FUNCTION(SlaveThread, arg) {
- (void)arg;
- chRegSetThreadName("slave_transport");
-
- while (true) {
- handle_soft_serial_slave();
- }
-}
-
-__attribute__((weak)) void usart_init(void) {
-#if defined(USE_GPIOV1)
- palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
-#else
- palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
-#endif
-
-#if defined(USART_REMAP)
- USART_REMAP;
-#endif
-}
-
-void usart_master_init(void) {
- usart_init();
-
- sdcfg.cr3 |= USART_CR3_HDSEL;
- sdStart(&SERIAL_USART_DRIVER, &sdcfg);
-}
-
-void usart_slave_init(void) {
- usart_init();
-
- sdcfg.cr3 |= USART_CR3_HDSEL;
- sdStart(&SERIAL_USART_DRIVER, &sdcfg);
-
- // Start transport thread
- chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL);
-}
-
-static SSTD_t* Transaction_table = NULL;
-static uint8_t Transaction_table_size = 0;
-
-void soft_serial_initiator_init(SSTD_t* sstd_table, int sstd_table_size) {
- Transaction_table = sstd_table;
- Transaction_table_size = (uint8_t)sstd_table_size;
-
- usart_master_init();
-}
-
-void soft_serial_target_init(SSTD_t* sstd_table, int sstd_table_size) {
- Transaction_table = sstd_table;
- Transaction_table_size = (uint8_t)sstd_table_size;
-
- usart_slave_init();
-}
-
-void handle_soft_serial_slave(void) {
- uint8_t sstd_index = sdGet(&SERIAL_USART_DRIVER); // first chunk is always transaction id
- SSTD_t* trans = &Transaction_table[sstd_index];
-
- // Always write back the sstd_index as part of a basic handshake
- sstd_index ^= HANDSHAKE_MAGIC;
- sdWrite(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index));
-
- if (trans->initiator2target_buffer_size) {
- sdRead(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size);
- }
-
- if (trans->target2initiator_buffer_size) {
- sdWrite(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size);
- }
-
- if (trans->status) {
- *trans->status = TRANSACTION_ACCEPTED;
- }
-}
-
-/////////
-// start transaction by initiator
-//
-// int soft_serial_transaction(int sstd_index)
-//
-// Returns:
-// TRANSACTION_END
-// TRANSACTION_NO_RESPONSE
-// TRANSACTION_DATA_ERROR
-#ifndef SERIAL_USE_MULTI_TRANSACTION
-int soft_serial_transaction(void) {
- uint8_t sstd_index = 0;
-#else
-int soft_serial_transaction(int index) {
- uint8_t sstd_index = index;
-#endif
-
- if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR;
- SSTD_t* trans = &Transaction_table[sstd_index];
- msg_t res = 0;
-
- sdClear(&SERIAL_USART_DRIVER);
-
- // First chunk is always transaction id
-<<<<<<< HEAD
- sdWriteTimeout(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index), TIME_MS2I(TIMEOUT));
-=======
- sdWriteTimeout(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index), TIME_MS2I(SERIAL_USART_TIMEOUT));
- // - due to the half duplex limitations on return codes, we always have to read *something*
- // - without the read, write only transactions *always* succeed, even during the boot process where the slave is not ready
-<<<<<<< HEAD
- res = sdReadTimeout(&SERIAL_USART_DRIVER, &sstd_index_shake, sizeof(sstd_index_shake), TIME_MS2I(TIMEOUT));
-=======
- res = sdReadTimeout(&SERIAL_USART_DRIVER, &sstd_index_shake, sizeof(sstd_index_shake), TIME_MS2I(SERIAL_USART_TIMEOUT));
->>>>>>> 0.12.52~1
- if (res < 0 || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) {
- dprintf("serial::usart_shake NO_RESPONSE\n");
- return TRANSACTION_NO_RESPONSE;
- }
-
- if (trans->initiator2target_buffer_size) {
-<<<<<<< HEAD
- res = sdWriteTimeout(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size, TIME_MS2I(TIMEOUT));
-=======
- res = sdWriteTimeout(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT));
->>>>>>> 0.12.52~1
- if (res < 0) {
- dprintf("serial::usart_transmit NO_RESPONSE\n");
- return TRANSACTION_NO_RESPONSE;
- }
- }
-
- if (trans->target2initiator_buffer_size) {
-<<<<<<< HEAD
- res = sdReadTimeout(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size, TIME_MS2I(TIMEOUT));
-=======
- res = sdReadTimeout(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT));
->>>>>>> 0.12.52~1
- if (res < 0) {
- dprintf("serial::usart_receive NO_RESPONSE\n");
- return TRANSACTION_NO_RESPONSE;
- }
- }
-
- return TRANSACTION_END;
-}
diff --git a/drivers/chibios/serial_usart.h b/drivers/chibios/serial_usart.h
deleted file mode 100644
index fee7b4d159..0000000000
--- a/drivers/chibios/serial_usart.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Copyright 2021 QMK
- *
- * 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 3 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 "quantum.h"
-#include "serial.h"
-#include "printf.h"
-
-#include <ch.h>
-#include <hal.h>
-
-#ifndef USART_CR1_M0
-# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so
-#endif
-
-#ifndef SERIAL_USART_CR1
-# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length
-#endif
-
-#ifndef SERIAL_USART_CR2
-# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits
-#endif
-
-#ifndef SERIAL_USART_CR3
-# define SERIAL_USART_CR3 0
-#endif
-
-#if defined(USART1_REMAP)
-# define USART_REMAP \
- do { \
- (AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); \
- } while (0)
-#elif defined(USART2_REMAP)
-# define USART_REMAP \
- do { \
- (AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); \
- } while (0)
-#elif defined(USART3_PARTIALREMAP)
-# define USART_REMAP \
- do { \
- (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); \
- } while (0)
-#elif defined(USART3_FULLREMAP)
-# define USART_REMAP \
- do { \
- (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \
- } while (0)
-#endif
-
-#ifndef SELECT_SOFT_SERIAL_SPEED
-# define SELECT_SOFT_SERIAL_SPEED 1
-#endif
-
-#ifdef SERIAL_USART_SPEED
-// Allow advanced users to directly set SERIAL_USART_SPEED
-#elif SELECT_SOFT_SERIAL_SPEED == 0
-# define SERIAL_USART_SPEED 460800
-#elif SELECT_SOFT_SERIAL_SPEED == 1
-# define SERIAL_USART_SPEED 230400
-#elif SELECT_SOFT_SERIAL_SPEED == 2
-# define SERIAL_USART_SPEED 115200
-#elif SELECT_SOFT_SERIAL_SPEED == 3
-# define SERIAL_USART_SPEED 57600
-#elif SELECT_SOFT_SERIAL_SPEED == 4
-# define SERIAL_USART_SPEED 38400
-#elif SELECT_SOFT_SERIAL_SPEED == 5
-# define SERIAL_USART_SPEED 19200
-#else
-# error invalid SELECT_SOFT_SERIAL_SPEED value
-#endif
-
-#ifndef SERIAL_USART_TIMEOUT
-# define SERIAL_USART_TIMEOUT 100
-#endif
-
-#define HANDSHAKE_MAGIC 7
diff --git a/drivers/chibios/serial_usart_duplex.c b/drivers/chibios/serial_usart_duplex.c
deleted file mode 100644
index cc9b889ac2..0000000000
--- a/drivers/chibios/serial_usart_duplex.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/* Copyright 2021 QMK
- *
- * 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 3 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 "serial_usart.h"
-
-#include <stdatomic.h>
-
-#if !defined(USE_GPIOV1)
-// The default PAL alternate modes are used to signal that the pins are used for USART
-# if !defined(SERIAL_USART_TX_PAL_MODE)
-# define SERIAL_USART_TX_PAL_MODE 7
-# endif
-# if !defined(SERIAL_USART_RX_PAL_MODE)
-# define SERIAL_USART_RX_PAL_MODE 7
-# endif
-#endif
-
-#if !defined(SERIAL_USART_DRIVER)
-# define SERIAL_USART_DRIVER UARTD1
-#endif
-
-#if !defined(SERIAL_USART_TX_PIN)
-# define SERIAL_USART_TX_PIN A9
-#endif
-
-#if !defined(SERIAL_USART_RX_PIN)
-# define SERIAL_USART_RX_PIN A10
-#endif
-
-#define SIGNAL_HANDSHAKE_RECEIVED 0x1
-
-void handle_transactions_slave(uint8_t sstd_index);
-static void receive_transaction_handshake(UARTDriver* uartp, uint16_t received_handshake);
-
-/*
- * UART driver configuration structure. We use the blocking DMA enabled API and
- * the rxchar callback to receive handshake tokens but only on the slave halve.
- */
-// clang-format off
-static UARTConfig uart_config = {
- .txend1_cb = NULL,
- .txend2_cb = NULL,
- .rxend_cb = NULL,
- .rxchar_cb = NULL,
- .rxerr_cb = NULL,
- .timeout_cb = NULL,
- .speed = (SERIAL_USART_SPEED),
- .cr1 = (SERIAL_USART_CR1),
- .cr2 = (SERIAL_USART_CR2),
- .cr3 = (SERIAL_USART_CR3)
-};
-// clang-format on
-
-static SSTD_t* Transaction_table = NULL;
-static uint8_t Transaction_table_size = 0;
-static atomic_uint_least8_t handshake = 0xFF;
-static thread_reference_t tp_target = NULL;
-
-/*
- * This callback is invoked when a character is received but the application
- * was not ready to receive it, the character is passed as parameter.
- * Receive transaction table index from initiator, which doubles as basic handshake token. */
-static void receive_transaction_handshake(UARTDriver* uartp, uint16_t received_handshake) {
- /* Check if received handshake is not a valid transaction id.
- * Please note that we can still catch a seemingly valid handshake
- * i.e. a byte from a ongoing transfer which is in the allowed range.
- * So this check mainly prevents any obviously wrong handshakes and
- * subsequent wakeups of the receiving thread, which is a costly operation. */
- if (received_handshake > Transaction_table_size) {
- return;
- }
-
- handshake = (uint8_t)received_handshake;
- chSysLockFromISR();
- /* Wakeup receiving thread to start a transaction. */
- chEvtSignalI(tp_target, (eventmask_t)SIGNAL_HANDSHAKE_RECEIVED);
- chSysUnlockFromISR();
-}
-
-__attribute__((weak)) void usart_init(void) {
-#if defined(USE_GPIOV1)
- palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
- palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT);
-#else
- palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
- palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_RX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
-#endif
-}
-
-/*
- * This thread runs on the slave half and reacts to transactions initiated from the master.
- */
-static THD_WORKING_AREA(waSlaveThread, 1024);
-static THD_FUNCTION(SlaveThread, arg) {
- (void)arg;
- chRegSetThreadName("slave_usart_tx_rx");
-
- while (true) {
- /* We sleep as long as there is no handshake waiting for us. */
- chEvtWaitAny((eventmask_t)SIGNAL_HANDSHAKE_RECEIVED);
- handle_transactions_slave(handshake);
- }
-}
-
-void soft_serial_target_init(SSTD_t* const sstd_table, int sstd_table_size) {
- Transaction_table = sstd_table;
- Transaction_table_size = (uint8_t)sstd_table_size;
- usart_init();
-
-#if defined(USART_REMAP)
- USART_REMAP;
-#endif
-
- tp_target = chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL);
-
- // Start receiving handshake tokens on slave halve
- uart_config.rxchar_cb = receive_transaction_handshake;
- uartStart(&SERIAL_USART_DRIVER, &uart_config);
-}
-
-/**
- * @brief React to transactions started by the master.
- * This version uses duplex send and receive usart pheriphals and DMA backed transfers.
- */
-void inline handle_transactions_slave(uint8_t sstd_index) {
- size_t buffer_size = 0;
- msg_t msg = 0;
- SSTD_t* trans = &Transaction_table[sstd_index];
-
- /* Send back the handshake which is XORed as a simple checksum,
- to signal that the slave is ready to receive possible transaction buffers */
- sstd_index ^= HANDSHAKE_MAGIC;
- buffer_size = (size_t)sizeof(sstd_index);
- msg = uartSendTimeout(&SERIAL_USART_DRIVER, &buffer_size, &sstd_index, TIME_MS2I(SERIAL_USART_TIMEOUT));
-
- if (msg != MSG_OK) {
- if (trans->status) {
- *trans->status = TRANSACTION_NO_RESPONSE;
- }
- return;
- }
-
- /* Receive transaction buffer from the master. If this transaction requires it.*/
- buffer_size = (size_t)trans->initiator2target_buffer_size;
- if (buffer_size) {
- msg = uartReceiveTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->initiator2target_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT));
- if (msg != MSG_OK) {
- if (trans->status) {
- *trans->status = TRANSACTION_NO_RESPONSE;
- }
- return;
- }
- }
-
- /* Send transaction buffer to the master. If this transaction requires it. */
- buffer_size = (size_t)trans->target2initiator_buffer_size;
- if (buffer_size) {
- msg = uartSendFullTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->target2initiator_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT));
- if (msg != MSG_OK) {
- if (trans->status) {
- *trans->status = TRANSACTION_NO_RESPONSE;
- }
- return;
- }
- }
-
- if (trans->status) {
- *trans->status = TRANSACTION_ACCEPTED;
- }
-}
-
-void soft_serial_initiator_init(SSTD_t* const sstd_table, int sstd_table_size) {
- Transaction_table = sstd_table;
- Transaction_table_size = (uint8_t)sstd_table_size;
- usart_init();
-
-#if defined(SERIAL_USART_PIN_SWAP)
- uart_config.cr2 |= USART_CR2_SWAP; // master has swapped TX/RX pins
-#endif
-
-#if defined(USART_REMAP)
- USART_REMAP;
-#endif
-
- uartStart(&SERIAL_USART_DRIVER, &uart_config);
-}
-
-/**
- * @brief Start transaction from the master to the slave.
- * This version uses duplex send and receive usart pheriphals and DMA backed transfers.
- *
- * @param index Transaction Table index of the transaction to start.
- * @return int TRANSACTION_NO_RESPONSE in case of Timeout.
- * TRANSACTION_TYPE_ERROR in case of invalid transaction index.
- * TRANSACTION_END in case of success.
- */
-#if !defined(SERIAL_USE_MULTI_TRANSACTION)
-int soft_serial_transaction(void) {
- uint8_t sstd_index = 0;
-#else
-int soft_serial_transaction(int index) {
- uint8_t sstd_index = index;
-#endif
-
- if (sstd_index > Transaction_table_size) {
- return TRANSACTION_TYPE_ERROR;
- }
-
- SSTD_t* const trans = &Transaction_table[sstd_index];
- msg_t msg = 0;
- size_t buffer_size = (size_t)sizeof(sstd_index);
-
- /* Send transaction table index to the slave, which doubles as basic handshake token. */
- uartSendFullTimeout(&SERIAL_USART_DRIVER, &buffer_size, &sstd_index, TIME_MS2I(SERIAL_USART_TIMEOUT));
-
- uint8_t sstd_index_shake = 0xFF;
- buffer_size = (size_t)sizeof(sstd_index_shake);
-
- /* Receive the handshake token from the slave. The token was XORed by the slave as a simple checksum.
- If the tokens match, the master will start to send and receive possible transaction buffers. */
- msg = uartReceiveTimeout(&SERIAL_USART_DRIVER, &buffer_size, &sstd_index_shake, TIME_MS2I(SERIAL_USART_TIMEOUT));
- if (msg != MSG_OK || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) {
- dprintln("USART: Handshake Failed");
- return TRANSACTION_NO_RESPONSE;
- }
-
- /* Send transaction buffer to the slave. If this transaction requires it. */
- buffer_size = (size_t)trans->initiator2target_buffer_size;
- if (buffer_size) {
- msg = uartSendFullTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->initiator2target_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT));
- if (msg != MSG_OK) {
- dprintln("USART: Send Failed");
- return TRANSACTION_NO_RESPONSE;
- }
- }
-
- /* Receive transaction buffer from the slave. If this transaction requires it. */
- buffer_size = (size_t)trans->target2initiator_buffer_size;
- if (buffer_size) {
- msg = uartReceiveTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->target2initiator_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT));
- if (msg != MSG_OK) {
- dprintln("USART: Receive Failed");
- return TRANSACTION_NO_RESPONSE;
- }
- }
-
- return TRANSACTION_END;
-}
diff --git a/drivers/chibios/spi_master.c b/drivers/chibios/spi_master.c
deleted file mode 100644
index 4852a6eba4..0000000000
--- a/drivers/chibios/spi_master.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Copyright 2020 Nick Brassel (tzarc)
- *
- * 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 3 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 <https://www.gnu.org/licenses/>.
- */
-
-#include "spi_master.h"
-
-#include "timer.h"
-
-static pin_t currentSlavePin = NO_PIN;
-static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0};
-
-__attribute__((weak)) void spi_init(void) {
- static bool is_initialised = false;
- if (!is_initialised) {
- is_initialised = true;
-
- // Try releasing special pins for a short time
- palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_INPUT);
- palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_INPUT);
- palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_INPUT);
-
- chThdSleepMilliseconds(10);
-#if defined(USE_GPIOV1)
- palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
- palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
- palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
-#else
- palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
- palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
- palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
-#endif
- }
-}
-
-bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
- if (currentSlavePin != NO_PIN || slavePin == NO_PIN) {
- return false;
- }
-
- uint16_t roundedDivisor = 2;
- while (roundedDivisor < divisor) {
- roundedDivisor <<= 1;
- }
-
- if (roundedDivisor < 2 || roundedDivisor > 256) {
- return false;
- }
-
- spiConfig.cr1 = 0;
-
- if (lsbFirst) {
- spiConfig.cr1 |= SPI_CR1_LSBFIRST;
- }
-
- switch (mode) {
- case 0:
- break;
- case 1:
- spiConfig.cr1 |= SPI_CR1_CPHA;
- break;
- case 2:
- spiConfig.cr1 |= SPI_CR1_CPOL;
- break;
- case 3:
- spiConfig.cr1 |= SPI_CR1_CPHA | SPI_CR1_CPOL;
- break;
- }
-
- switch (roundedDivisor) {
- case 2:
- break;
- case 4:
- spiConfig.cr1 |= SPI_CR1_BR_0;
- break;
- case 8:
- spiConfig.cr1 |= SPI_CR1_BR_1;
- break;
- case 16:
- spiConfig.cr1 |= SPI_CR1_BR_1 | SPI_CR1_BR_0;
- break;
- case 32:
- spiConfig.cr1 |= SPI_CR1_BR_2;
- break;
- case 64:
- spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_0;
- break;
- case 128:
- spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1;
- break;
- case 256:
- spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0;
- break;
- }
-
- currentSlavePin = slavePin;
- spiConfig.ssport = PAL_PORT(slavePin);
- spiConfig.sspad = PAL_PAD(slavePin);
-
- setPinOutput(slavePin);
- spiStart(&SPI_DRIVER, &spiConfig);
- spiSelect(&SPI_DRIVER);
-
- return true;
-}
-
-spi_status_t spi_write(uint8_t data) {
- uint8_t rxData;
- spiExchange(&SPI_DRIVER, 1, &data, &rxData);
-
- return rxData;
-}
-
-spi_status_t spi_read(void) {
- uint8_t data = 0;
- spiReceive(&SPI_DRIVER, 1, &data);
-
- return data;
-}
-
-spi_status_t spi_transmit(const uint8_t *data, uint16_t length) {
- spiSend(&SPI_DRIVER, length, data);
- return SPI_STATUS_SUCCESS;
-}
-
-spi_status_t spi_receive(uint8_t *data, uint16_t length) {
- spiReceive(&SPI_DRIVER, length, data);
- return SPI_STATUS_SUCCESS;
-}
-
-void spi_stop(void) {
- if (currentSlavePin != NO_PIN) {
- spiUnselect(&SPI_DRIVER);
- spiStop(&SPI_DRIVER);
- currentSlavePin = NO_PIN;
- }
-}
diff --git a/drivers/chibios/spi_master.h b/drivers/chibios/spi_master.h
deleted file mode 100644
index e93580e319..0000000000
--- a/drivers/chibios/spi_master.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Copyright 2020 Nick Brassel (tzarc)
- *
- * 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 3 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 <https://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <ch.h>
-#include <hal.h>
-#include <stdbool.h>
-
-#include "gpio.h"
-
-#ifndef SPI_DRIVER
-# define SPI_DRIVER SPID2
-#endif
-
-#ifndef SPI_SCK_PIN
-# define SPI_SCK_PIN B13
-#endif
-
-#ifndef SPI_SCK_PAL_MODE
-# define SPI_SCK_PAL_MODE 5
-#endif
-
-#ifndef SPI_MOSI_PIN
-# define SPI_MOSI_PIN B15
-#endif
-
-#ifndef SPI_MOSI_PAL_MODE
-# define SPI_MOSI_PAL_MODE 5
-#endif
-
-#ifndef SPI_MISO_PIN
-# define SPI_MISO_PIN B14
-#endif
-
-#ifndef SPI_MISO_PAL_MODE
-# define SPI_MISO_PAL_MODE 5
-#endif
-
-typedef int16_t spi_status_t;
-
-#define SPI_STATUS_SUCCESS (0)
-#define SPI_STATUS_ERROR (-1)
-#define SPI_STATUS_TIMEOUT (-2)
-
-#define SPI_TIMEOUT_IMMEDIATE (0)
-#define SPI_TIMEOUT_INFINITE (0xFFFF)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-void spi_init(void);
-
-bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor);
-
-spi_status_t spi_write(uint8_t data);
-
-spi_status_t spi_read(void);
-
-spi_status_t spi_transmit(const uint8_t *data, uint16_t length);
-
-spi_status_t spi_receive(uint8_t *data, uint16_t length);
-
-void spi_stop(void);
-#ifdef __cplusplus
-}
-#endif
diff --git a/drivers/chibios/uart.c b/drivers/chibios/uart.c
deleted file mode 100644
index 030335b342..0000000000
--- a/drivers/chibios/uart.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright 2021
- *
- * 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 3 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 <https://www.gnu.org/licenses/>.
- */
-
-#include "uart.h"
-
-#include "quantum.h"
-
-static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE, SD1_CR1, SD1_CR2, SD1_CR3};
-
-void uart_init(uint32_t baud) {
- static bool is_initialised = false;
-
- if (!is_initialised) {
- is_initialised = true;
-
- serialConfig.speed = baud;
-
-#if defined(USE_GPIOV1)
- palSetLineMode(SD1_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
- palSetLineMode(SD1_RX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
-#else
- palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE(SD1_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
- palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE(SD1_RX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
-#endif
- sdStart(&SERIAL_DRIVER, &serialConfig);
- }
-}
-
-void uart_putchar(uint8_t c) { sdPut(&SERIAL_DRIVER, c); }
-
-uint8_t uart_getchar(void) {
- msg_t res = sdGet(&SERIAL_DRIVER);
-
- return (uint8_t)res;
-}
-
-bool uart_available(void) { return !sdGetWouldBlock(&SERIAL_DRIVER); }
diff --git a/drivers/chibios/uart.h b/drivers/chibios/uart.h
deleted file mode 100644
index b4e20e9fd3..0000000000
--- a/drivers/chibios/uart.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Copyright 2021
- *
- * 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 3 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 <https://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <stdint.h>
-
-#include <hal.h>
-
-#ifndef SERIAL_DRIVER
-# define SERIAL_DRIVER SD1
-#endif
-
-#ifndef SD1_TX_PIN
-# define SD1_TX_PIN A9
-#endif
-
-#ifndef SD1_TX_PAL_MODE
-# define SD1_TX_PAL_MODE 7
-#endif
-
-#ifndef SD1_RX_PIN
-# define SD1_RX_PIN A10
-#endif
-
-#ifndef SD1_RX_PAL_MODE
-# define SD1_RX_PAL_MODE 7
-#endif
-
-#ifndef SD1_CTS_PIN
-# define SD1_CTS_PIN A11
-#endif
-
-#ifndef SD1_CTS_PAL_MODE
-# define SD1_CTS_PAL_MODE 7
-#endif
-
-#ifndef SD1_RTS_PIN
-# define SD1_RTS_PIN A12
-#endif
-
-#ifndef SD1_RTS_PAL_MODE
-# define SD1_RTS_PAL_MODE 7
-#endif
-
-#ifndef SD1_CR1
-# define SD1_CR1 0
-#endif
-
-#ifndef SD1_CR2
-# define SD1_CR2 0
-#endif
-
-#ifndef SD1_CR3
-# define SD1_CR3 0
-#endif
-
-void uart_init(uint32_t baud);
-
-void uart_putchar(uint8_t c);
-
-uint8_t uart_getchar(void);
-
-bool uart_available(void);
diff --git a/drivers/chibios/usbpd_stm32g4.c b/drivers/chibios/usbpd_stm32g4.c
deleted file mode 100644
index f16ca8aeae..0000000000
--- a/drivers/chibios/usbpd_stm32g4.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Copyright 2021 Nick Brassel (@tzarc)
- *
- * 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 <quantum.h>
-
-#ifndef USBPD_UCPD1_CFG1
-# define USBPD_UCPD1_CFG1 (UCPD_CFG1_PSC_UCPDCLK_0 | UCPD_CFG1_TRANSWIN_3 | UCPD_CFG1_IFRGAP_4 | UCPD_CFG1_HBITCLKDIV_4)
-#endif // USBPD_UCPD1_CFG1
-
-// Initialises the USBPD subsystem
-__attribute__((weak)) void usbpd_init(void) {
- // Disable dead-battery signals
- PWR->CR3 |= PWR_CR3_UCPD_DBDIS;
- // Enable the clock for the UCPD1 peripheral
- RCC->APB1ENR2 |= RCC_APB1ENR2_UCPD1EN;
-
- // Copy the existing value
- uint32_t CFG1 = UCPD1->CFG1;
- // Force-disable UCPD1 before configuring
- CFG1 &= ~UCPD_CFG1_UCPDEN;
- // Configure UCPD1
- CFG1 = USBPD_UCPD1_CFG1;
- // Apply the changes
- UCPD1->CFG1 = CFG1;
- // Enable UCPD1
- UCPD1->CFG1 |= UCPD_CFG1_UCPDEN;
-
- // Copy the existing value
- uint32_t CR = UCPD1->CR;
- // Clear out ANASUBMODE (irrelevant as a sink device)
- CR &= ~UCPD_CR_ANASUBMODE_Msk;
- // Advertise our capabilities as a sink, with both CC lines enabled
- CR |= UCPD_CR_ANAMODE | UCPD_CR_CCENABLE_Msk;
- // Apply the changes
- UCPD1->CR = CR;
-}
-
-// Gets the current state of the USBPD allowance
-__attribute__((weak)) usbpd_allowance_t usbpd_get_allowance(void) {
- uint32_t CR = UCPD1->CR;
-
- int ucpd_enabled = (UCPD1->CFG1 & UCPD_CFG1_UCPDEN_Msk) >> UCPD_CFG1_UCPDEN_Pos;
- int anamode = (CR & UCPD_CR_ANAMODE_Msk) >> UCPD_CR_ANAMODE_Pos;
- int cc_enabled = (CR & UCPD_CR_CCENABLE_Msk) >> UCPD_CR_CCENABLE_Pos;
-
- if (ucpd_enabled && anamode && cc_enabled) {
- uint32_t SR = UCPD1->SR;
- int vstate_cc1 = (SR & UCPD_SR_TYPEC_VSTATE_CC1_Msk) >> UCPD_SR_TYPEC_VSTATE_CC1_Pos;
- int vstate_cc2 = (SR & UCPD_SR_TYPEC_VSTATE_CC2_Msk) >> UCPD_SR_TYPEC_VSTATE_CC2_Pos;
- int vstate_max = vstate_cc1 > vstate_cc2 ? vstate_cc1 : vstate_cc2;
- switch (vstate_max) {
- case 0:
- case 1:
- return USBPD_500MA; // Note that this is 500mA (i.e. max USB 2.0), not 900mA, as we're not using USB 3.1 as a sink device.
- case 2:
- return USBPD_1500MA;
- case 3:
- return USBPD_3000MA;
- }
- }
-
- return USBPD_500MA;
-} \ No newline at end of file
diff --git a/drivers/chibios/ws2812.c b/drivers/chibios/ws2812.c
deleted file mode 100644
index 0d12e2fb79..0000000000
--- a/drivers/chibios/ws2812.c
+++ /dev/null
@@ -1,114 +0,0 @@
-#include "quantum.h"
-#include "ws2812.h"
-#include <ch.h>
-#include <hal.h>
-
-/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
-
-#ifndef NOP_FUDGE
-# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
-# define NOP_FUDGE 0.4
-# else
-# error("NOP_FUDGE configuration required")
-# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot
-# endif
-#endif
-
-// Push Pull or Open Drain Configuration
-// Default Push Pull
-#ifndef WS2812_EXTERNAL_PULLUP
-# define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_PUSHPULL
-#else
-# define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_OPENDRAIN
-#endif
-
-#define NUMBER_NOPS 6
-#define CYCLES_PER_SEC (STM32_SYSCLK / NUMBER_NOPS * NOP_FUDGE)
-#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives
-#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC)
-#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE)
-
-#define wait_ns(x) \
- do { \
- for (int i = 0; i < NS_TO_CYCLES(x); i++) { \
- __asm__ volatile("nop\n\t" \
- "nop\n\t" \
- "nop\n\t" \
- "nop\n\t" \
- "nop\n\t" \
- "nop\n\t"); \
- } \
- } while (0)
-
-// These are the timing constraints taken mostly from the WS2812 datasheets
-// These are chosen to be conservative and avoid problems rather than for maximum throughput
-
-#define T1H 900 // Width of a 1 bit in ns
-#define T1L (1250 - T1H) // Width of a 1 bit in ns
-
-#define T0H 350 // Width of a 0 bit in ns
-#define T0L (1250 - T0H) // Width of a 0 bit in ns
-
-// The reset gap can be 6000 ns, but depending on the LED strip it may have to be increased
-// to values like 600000 ns. If it is too small, the pixels will show nothing most of the time.
-#define RES (1000 * WS2812_TRST_US) // Width of the low gap between bits to cause a frame to latch
-
-void sendByte(uint8_t byte) {
- // WS2812 protocol wants most significant bits first
- for (unsigned char bit = 0; bit < 8; bit++) {
- bool is_one = byte & (1 << (7 - bit));
- // using something like wait_ns(is_one ? T1L : T0L) here throws off timings
- if (is_one) {
- // 1
- writePinHigh(RGB_DI_PIN);
- wait_ns(T1H);
- writePinLow(RGB_DI_PIN);
- wait_ns(T1L);
- } else {
- // 0
- writePinHigh(RGB_DI_PIN);
- wait_ns(T0H);
- writePinLow(RGB_DI_PIN);
- wait_ns(T0L);
- }
- }
-}
-
-void ws2812_init(void) { palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE); }
-
-// Setleds for standard RGB
-void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
- static bool s_init = false;
- if (!s_init) {
- ws2812_init();
- s_init = true;
- }
-
- // this code is very time dependent, so we need to disable interrupts
- chSysLock();
-
- for (uint8_t i = 0; i < leds; i++) {
- // WS2812 protocol dictates grb order
-#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
- sendByte(ledarray[i].g);
- sendByte(ledarray[i].r);
- sendByte(ledarray[i].b);
-#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
- sendByte(ledarray[i].r);
- sendByte(ledarray[i].g);
- sendByte(ledarray[i].b);
-#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR)
- sendByte(ledarray[i].b);
- sendByte(ledarray[i].g);
- sendByte(ledarray[i].r);
-#endif
-
-#ifdef RGBW
- sendByte(ledarray[i].w);
-#endif
- }
-
- wait_ns(RES);
-
- chSysUnlock();
-}
diff --git a/drivers/chibios/ws2812_pwm.c b/drivers/chibios/ws2812_pwm.c
deleted file mode 100644
index e6af55b6b3..0000000000
--- a/drivers/chibios/ws2812_pwm.c
+++ /dev/null
@@ -1,311 +0,0 @@
-#include "ws2812.h"
-#include "quantum.h"
-#include <hal.h>
-
-/* Adapted from https://github.com/joewa/WS2812-LED-Driver_ChibiOS/ */
-
-#ifdef RGBW
-# error "RGBW not supported"
-#endif
-
-#ifndef WS2812_PWM_DRIVER
-# define WS2812_PWM_DRIVER PWMD2 // TIMx
-#endif
-#ifndef WS2812_PWM_CHANNEL
-# define WS2812_PWM_CHANNEL 2 // Channel
-#endif
-#ifndef WS2812_PWM_PAL_MODE
-# define WS2812_PWM_PAL_MODE 2 // DI Pin's alternate function value
-#endif
-#ifndef WS2812_DMA_STREAM
-# define WS2812_DMA_STREAM STM32_DMA1_STREAM2 // DMA Stream for TIMx_UP
-#endif
-#ifndef WS2812_DMA_CHANNEL
-# define WS2812_DMA_CHANNEL 2 // DMA Channel for TIMx_UP
-#endif
-#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && !defined(WS2812_DMAMUX_ID)
-# error "please consult your MCU's datasheet and specify in your config.h: #define WS2812_DMAMUX_ID STM32_DMAMUX1_TIM?_UP"
-#endif
-
-#ifndef WS2812_PWM_COMPLEMENTARY_OUTPUT
-# define WS2812_PWM_OUTPUT_MODE PWM_OUTPUT_ACTIVE_HIGH
-#else
-# if !STM32_PWM_USE_ADVANCED
-# error "WS2812_PWM_COMPLEMENTARY_OUTPUT requires STM32_PWM_USE_ADVANCED == TRUE"
-# endif
-# define WS2812_PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH
-#endif
-
-// Push Pull or Open Drain Configuration
-// Default Push Pull
-#ifndef WS2812_EXTERNAL_PULLUP
-# if defined(USE_GPIOV1)
-# define WS2812_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
-# else
-# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_PWM_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING
-# endif
-#else
-# if defined(USE_GPIOV1)
-# define WS2812_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
-# else
-# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_PWM_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING
-# endif
-#endif
-
-#ifndef WS2812_PWM_TARGET_PERIOD
-//# define WS2812_PWM_TARGET_PERIOD 800000 // Original code is 800k...?
-# define WS2812_PWM_TARGET_PERIOD 80000 // TODO: work out why 10x less on f303/f4x1
-#endif
-
-/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
-
-#define WS2812_PWM_FREQUENCY (STM32_SYSCLK / 2) /**< Clock frequency of PWM, must be valid with respect to system clock! */
-#define WS2812_PWM_PERIOD (WS2812_PWM_FREQUENCY / WS2812_PWM_TARGET_PERIOD) /**< Clock period in ticks. 1 / 800kHz = 1.25 uS (as per datasheet) */
-
-/**
- * @brief Number of bit-periods to hold the data line low at the end of a frame
- *
- * The reset period for each frame is defined in WS2812_TRST_US.
- * Calculate the number of zeroes to add at the end assuming 1.25 uS/bit:
- */
-#define WS2812_RESET_BIT_N (1000 * WS2812_TRST_US / 1250)
-#define WS2812_COLOR_BIT_N (RGBLED_NUM * 24) /**< Number of data bits */
-#define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */
-
-/**
- * @brief High period for a zero, in ticks
- *
- * Per the datasheet:
- * WS2812:
- * - T0H: 200 nS to 500 nS, inclusive
- * - T0L: 650 nS to 950 nS, inclusive
- * WS2812B:
- * - T0H: 200 nS to 500 nS, inclusive
- * - T0L: 750 nS to 1050 nS, inclusive
- *
- * The duty cycle is calculated for a high period of 350 nS.
- */
-#define WS2812_DUTYCYCLE_0 (WS2812_PWM_FREQUENCY / (1000000000 / 350))
-
-/**
- * @brief High period for a one, in ticks
- *
- * Per the datasheet:
- * WS2812:
- * - T1H: 550 nS to 850 nS, inclusive
- * - T1L: 450 nS to 750 nS, inclusive
- * WS2812B:
- * - T1H: 750 nS to 1050 nS, inclusive
- * - T1L: 200 nS to 500 nS, inclusive
- *
- * The duty cycle is calculated for a high period of 800 nS.
- * This is in the middle of the specifications of the WS2812 and WS2812B.
- */
-#define WS2812_DUTYCYCLE_1 (WS2812_PWM_FREQUENCY / (1000000000 / 800))
-
-/* --- PRIVATE MACROS ------------------------------------------------------- */
-
-/**
- * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given bit
- *
- * @param[in] led: The led index [0, @ref RGBLED_NUM)
- * @param[in] byte: The byte number [0, 2]
- * @param[in] bit: The bit number [0, 7]
- *
- * @return The bit index
- */
-#define WS2812_BIT(led, byte, bit) (24 * (led) + 8 * (byte) + (7 - (bit)))
-
-#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
-/**
- * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit
- *
- * @note The red byte is the middle byte in the color packet
- *
- * @param[in] led: The led index [0, @ref RGBLED_NUM)
- * @param[in] bit: The bit number [0, 7]
- *
- * @return The bit index
- */
-# define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 1, (bit))
-
-/**
- * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit
- *
- * @note The red byte is the first byte in the color packet
- *
- * @param[in] led: The led index [0, @ref RGBLED_NUM)
- * @param[in] bit: The bit number [0, 7]
- *
- * @return The bit index
- */
-# define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 0, (bit))
-
-/**
- * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit
- *
- * @note The red byte is the last byte in the color packet
- *
- * @param[in] led: The led index [0, @ref RGBLED_NUM)
- * @param[in] bit: The bit index [0, 7]
- *
- * @return The bit index
- */
-# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit))
-
-#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
-/**
- * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit
- *
- * @note The red byte is the middle byte in the color packet
- *
- * @param[in] led: The led index [0, @ref RGBLED_NUM)
- * @param[in] bit: The bit number [0, 7]
- *
- * @return The bit index
- */
-# define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 0, (bit))
-
-/**
- * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit
- *
- * @note The red byte is the first byte in the color packet
- *
- * @param[in] led: The led index [0, @ref RGBLED_NUM)
- * @param[in] bit: The bit number [0, 7]
- *
- * @return The bit index
- */
-# define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 1, (bit))
-
-/**
- * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit
- *
- * @note The red byte is the last byte in the color packet
- *
- * @param[in] led: The led index [0, @ref RGBLED_NUM)
- * @param[in] bit: The bit index [0, 7]
- *
- * @return The bit index
- */
-# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit))
-
-#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR)
-/**
- * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit
- *
- * @note The red byte is the middle byte in the color packet
- *
- * @param[in] led: The led index [0, @ref RGBLED_NUM)
- * @param[in] bit: The bit number [0, 7]
- *
- * @return The bit index
- */
-# define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 2, (bit))
-
-/**
- * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit
- *
- * @note The red byte is the first byte in the color packet
- *
- * @param[in] led: The led index [0, @ref RGBLED_NUM)
- * @param[in] bit: The bit number [0, 7]
- *
- * @return The bit index
- */
-# define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 1, (bit))
-
-/**
- * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit
- *
- * @note The red byte is the last byte in the color packet
- *
- * @param[in] led: The led index [0, @ref RGBLED_NUM)
- * @param[in] bit: The bit index [0, 7]
- *
- * @return The bit index
- */
-# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 0, (bit))
-#endif
-
-/* --- PRIVATE VARIABLES ---------------------------------------------------- */
-
-static uint32_t ws2812_frame_buffer[WS2812_BIT_N + 1]; /**< Buffer for a frame */
-
-/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */
-/*
- * Gedanke: Double-buffer type transactions: double buffer transfers using two memory pointers for
-the memory (while the DMA is reading/writing from/to a buffer, the application can
-write/read to/from the other buffer).
- */
-
-void ws2812_init(void) {
- // Initialize led frame buffer
- uint32_t i;
- for (i = 0; i < WS2812_COLOR_BIT_N; i++) ws2812_frame_buffer[i] = WS2812_DUTYCYCLE_0; // All color bits are zero duty cycle
- for (i = 0; i < WS2812_RESET_BIT_N; i++) ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = 0; // All reset bits are zero
-
- palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE);
-
- // PWM Configuration
- //#pragma GCC diagnostic ignored "-Woverride-init" // Turn off override-init warning for this struct. We use the overriding ability to set a "default" channel config
- static const PWMConfig ws2812_pwm_config = {
- .frequency = WS2812_PWM_FREQUENCY,
- .period = WS2812_PWM_PERIOD, // Mit dieser Periode wird UDE-Event erzeugt und ein neuer Wert (Länge WS2812_BIT_N) vom DMA ins CCR geschrieben
- .callback = NULL,
- .channels =
- {
- [0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled
- [WS2812_PWM_CHANNEL - 1] = {.mode = WS2812_PWM_OUTPUT_MODE, .callback = NULL}, // Turn on the channel we care about
- },
- .cr2 = 0,
- .dier = TIM_DIER_UDE, // DMA on update event for next period
- };
- //#pragma GCC diagnostic pop // Restore command-line warning options
-
- // Configure DMA
- // dmaInit(); // Joe added this
- dmaStreamAlloc(WS2812_DMA_STREAM - STM32_DMA_STREAM(0), 10, NULL, NULL);
- dmaStreamSetPeripheral(WS2812_DMA_STREAM, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register
- dmaStreamSetMemory0(WS2812_DMA_STREAM, ws2812_frame_buffer);
- dmaStreamSetTransactionSize(WS2812_DMA_STREAM, WS2812_BIT_N);
- dmaStreamSetMode(WS2812_DMA_STREAM, STM32_DMA_CR_CHSEL(WS2812_DMA_CHANNEL) | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3));
- // M2P: Memory 2 Periph; PL: Priority Level
-
-#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE)
- // If the MCU has a DMAMUX we need to assign the correct resource
- dmaSetRequestSource(WS2812_DMA_STREAM, WS2812_DMAMUX_ID);
-#endif
-
- // Start DMA
- dmaStreamEnable(WS2812_DMA_STREAM);
-
- // Configure PWM
- // NOTE: It's required that preload be enabled on the timer channel CCR register. This is currently enabled in the
- // ChibiOS driver code, so we don't have to do anything special to the timer. If we did, we'd have to start the timer,
- // disable counting, enable the channel, and then make whatever configuration changes we need.
- pwmStart(&WS2812_PWM_DRIVER, &ws2812_pwm_config);
- pwmEnableChannel(&WS2812_PWM_DRIVER, WS2812_PWM_CHANNEL - 1, 0); // Initial period is 0; output will be low until first duty cycle is DMA'd in
-}
-
-void ws2812_write_led(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b) {
- // Write color to frame buffer
- for (uint8_t bit = 0; bit < 8; bit++) {
- ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
- ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
- ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
- }
-}
-
-// Setleds for standard RGB
-void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {
- static bool s_init = false;
- if (!s_init) {
- ws2812_init();
- s_init = true;
- }
-
- for (uint16_t i = 0; i < leds; i++) {
- ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b);
- }
-}
diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c
deleted file mode 100644
index 377a929b94..0000000000
--- a/drivers/chibios/ws2812_spi.c
+++ /dev/null
@@ -1,159 +0,0 @@
-#include "quantum.h"
-#include "ws2812.h"
-
-/* Adapted from https://github.com/gamazeps/ws2812b-chibios-SPIDMA/ */
-
-#ifdef RGBW
-# error "RGBW not supported"
-#endif
-
-// Define the spi your LEDs are plugged to here
-#ifndef WS2812_SPI
-# define WS2812_SPI SPID1
-#endif
-
-#ifndef WS2812_SPI_MOSI_PAL_MODE
-# define WS2812_SPI_MOSI_PAL_MODE 5
-#endif
-
-#ifndef WS2812_SPI_SCK_PAL_MODE
-# define WS2812_SPI_SCK_PAL_MODE 5
-#endif
-
-// Push Pull or Open Drain Configuration
-// Default Push Pull
-#ifndef WS2812_EXTERNAL_PULLUP
-# if defined(USE_GPIOV1)
-# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
-# else
-# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL
-# endif
-#else
-# if defined(USE_GPIOV1)
-# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
-# else
-# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN
-# endif
-#endif
-
-// Define SPI config speed
-// baudrate should target 3.2MHz
-// F072 fpclk = 48MHz
-// 48/16 = 3Mhz
-#if WS2812_SPI_DIVISOR == 2
-# define WS2812_SPI_DIVISOR (0)
-#elif WS2812_SPI_DIVISOR == 4
-# define WS2812_SPI_DIVISOR (SPI_CR1_BR_0)
-#elif WS2812_SPI_DIVISOR == 8
-# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1)
-#elif WS2812_SPI_DIVISOR == 16 // same as default
-# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0)
-#elif WS2812_SPI_DIVISOR == 32
-# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2)
-#elif WS2812_SPI_DIVISOR == 64
-# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_0)
-#elif WS2812_SPI_DIVISOR == 128
-# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1)
-#elif WS2812_SPI_DIVISOR == 256
-# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0)
-#else
-# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) // default
-#endif
-
-// Use SPI circular buffer
-#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER
-# define WS2812_SPI_BUFFER_MODE 1 // circular buffer
-#else
-# define WS2812_SPI_BUFFER_MODE 0 // normal buffer
-#endif
-
-#if defined(USE_GPIOV1)
-# define WS2812_SCK_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
-#else
-# define WS2812_SCK_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL
-#endif
-
-#define BYTES_FOR_LED_BYTE 4
-#define NB_COLORS 3
-#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS)
-#define DATA_SIZE (BYTES_FOR_LED * RGBLED_NUM)
-#define RESET_SIZE (1000 * WS2812_TRST_US / (2 * 1250))
-#define PREAMBLE_SIZE 4
-
-static uint8_t txbuf[PREAMBLE_SIZE + DATA_SIZE + RESET_SIZE] = {0};
-
-/*
- * As the trick here is to use the SPI to send a huge pattern of 0 and 1 to
- * the ws2812b protocol, we use this helper function to translate bytes into
- * 0s and 1s for the LED (with the appropriate timing).
- */
-static uint8_t get_protocol_eq(uint8_t data, int pos) {
- uint8_t eq = 0;
- if (data & (1 << (2 * (3 - pos))))
- eq = 0b1110;
- else
- eq = 0b1000;
- if (data & (2 << (2 * (3 - pos))))
- eq += 0b11100000;
- else
- eq += 0b10000000;
- return eq;
-}
-
-static void set_led_color_rgb(LED_TYPE color, int pos) {
- uint8_t* tx_start = &txbuf[PREAMBLE_SIZE];
-
-#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
- for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.g, j);
- for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.r, j);
- for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j);
-#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
- for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.r, j);
- for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j);
- for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j);
-#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR)
- for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.b, j);
- for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j);
- for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.r, j);
-#endif
-}
-
-void ws2812_init(void) {
- palSetLineMode(RGB_DI_PIN, WS2812_MOSI_OUTPUT_MODE);
-
-#ifdef WS2812_SPI_SCK_PIN
- palSetLineMode(WS2812_SPI_SCK_PIN, WS2812_SCK_OUTPUT_MODE);
-#endif // WS2812_SPI_SCK_PIN
-
- // TODO: more dynamic baudrate
- static const SPIConfig spicfg = {WS2812_SPI_BUFFER_MODE, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), WS2812_SPI_DIVISOR};
-
- spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */
- spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters. */
- spiSelect(&WS2812_SPI); /* Slave Select assertion. */
-#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER
- spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf);
-#endif
-}
-
-void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {
- static bool s_init = false;
- if (!s_init) {
- ws2812_init();
- s_init = true;
- }
-
- for (uint8_t i = 0; i < leds; i++) {
- set_led_color_rgb(ledarray[i], i);
- }
-
- // Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues.
- // Instead spiSend can be used to send synchronously (or the thread logic can be added back).
-#ifndef WS2812_SPI_USE_CIRCULAR_BUFFER
-# ifdef WS2812_SPI_SYNC
- spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf);
-# else
- spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf);
-# endif
-#endif
-}
diff --git a/drivers/chibios/wt_rgb_backlight.c b/drivers/chibios/wt_rgb_backlight.c
deleted file mode 100644
index 306f8186e0..0000000000
--- a/drivers/chibios/wt_rgb_backlight.c
+++ /dev/null
@@ -1,3125 +0,0 @@
-/* Copyright 2017 Jason Williams (Wilba)
- *
- * 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(RGB_BACKLIGHT_ZEAL60) || \
- defined(RGB_BACKLIGHT_ZEAL65) || \
- defined(RGB_BACKLIGHT_M60_A) || \
- defined(RGB_BACKLIGHT_M6_B) || \
- defined(RGB_BACKLIGHT_M10_C) || \
- defined(RGB_BACKLIGHT_KOYU) || \
- defined(RGB_BACKLIGHT_M65_B) || \
- defined(RGB_BACKLIGHT_M65_BX) || \
- defined(RGB_BACKLIGHT_HS60) || \
- defined(RGB_BACKLIGHT_NK65) || \
- defined(RGB_BACKLIGHT_NK87) || \
- defined(RGB_BACKLIGHT_KW_MEGA) || \
- defined(RGB_BACKLIGHT_NEBULA12) || \
- defined(RGB_BACKLIGHT_NEBULA68) || \
- defined(RGB_BACKLIGHT_U80_A) || \
- defined(RGB_BACKLIGHT_DAWN60) || \
- defined(RGB_BACKLIGHT_WT60_B) || \
- defined(RGB_BACKLIGHT_WT60_BX) || \
- defined(RGB_BACKLIGHT_WT60_C) || \
- defined(RGB_BACKLIGHT_M50_A)
-#else
-#error wt_rgb_backlight.c compiled without setting configuration symbol
-#endif
-
-#ifndef MAX
- #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
-#endif
-
-#ifndef MIN
- #define MIN(a,b) ((a) < (b)? (a): (b))
-#endif
-
-#include "quantum.h"
-#include "wt_rgb_backlight.h"
-#include "wt_rgb_backlight_api.h"
-#include "wt_rgb_backlight_keycodes.h"
-
-#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65) && !defined(RGB_BACKLIGHT_NK87) && !defined(RGB_BACKLIGHT_NEBULA68) && !defined(RGB_BACKLIGHT_NEBULA12) && !defined (RGB_BACKLIGHT_KW_MEGA)
-#include <avr/interrupt.h>
-#include "drivers/avr/i2c_master.h"
-#else
-#include <ch.h>
-#include <hal.h>
-#include "drivers/chibios/i2c_master.h"
-#endif
-
-#if defined(RGB_BACKLIGHT_DAWN60)
-#include "ws2812.h"
-LED_TYPE g_ws2812_leds[WS2812_LED_TOTAL];
-#endif
-
-#include "progmem.h"
-#include "quantum/color.h"
-#include "tmk_core/common/eeprom.h"
-
-#include "via.h" // uses EEPROM address, lighting value IDs
-#define RGB_BACKLIGHT_CONFIG_EEPROM_ADDR (VIA_EEPROM_CUSTOM_CONFIG_ADDR)
-
-#if VIA_EEPROM_CUSTOM_CONFIG_SIZE == 0
-#error VIA_EEPROM_CUSTOM_CONFIG_SIZE was not defined to store backlight_config struct
-#endif
-
-#if defined(RGB_BACKLIGHT_M6_B)
-#include "drivers/issi/is31fl3218.h"
-#define BACKLIGHT_LED_COUNT 6
-#elif defined(RGB_BACKLIGHT_HS60)
-#include "drivers/issi/is31fl3733.h"
-#define BACKLIGHT_LED_COUNT 64
-#elif defined(RGB_BACKLIGHT_NK65) || defined(RGB_BACKLIGHT_NEBULA68) || defined(RGB_BACKLIGHT_KW_MEGA)
-#include "drivers/issi/is31fl3733.h"
-#define BACKLIGHT_LED_COUNT 69
-#elif defined(RGB_BACKLIGHT_NK87)
-#include "drivers/issi/is31fl3733.h"
-#define BACKLIGHT_LED_COUNT 128
-#else
-#include "drivers/issi/is31fl3731.h"
-#if defined(RGB_BACKLIGHT_U80_A)
-#define BACKLIGHT_LED_COUNT 108
-#elif defined(RGB_BACKLIGHT_DAWN60)
-#define BACKLIGHT_LED_COUNT 84 //64 + 20
-#elif defined(RGB_BACKLIGHT_NEBULA12)
-#define BACKLIGHT_LED_COUNT 16
-#elif defined(RGB_BACKLIGHT_M10_C)
-#define BACKLIGHT_LED_COUNT 12
-#else
-#define BACKLIGHT_LED_COUNT 72
-#endif
-#endif
-
-#define BACKLIGHT_EFFECT_MAX 10
-
-backlight_config g_config = {
- .use_split_backspace = RGB_BACKLIGHT_USE_SPLIT_BACKSPACE,
- .use_split_left_shift = RGB_BACKLIGHT_USE_SPLIT_LEFT_SHIFT,
- .use_split_right_shift = RGB_BACKLIGHT_USE_SPLIT_RIGHT_SHIFT,
- .use_7u_spacebar = RGB_BACKLIGHT_USE_7U_SPACEBAR,
- .use_iso_enter = RGB_BACKLIGHT_USE_ISO_ENTER,
- .disable_hhkb_blocker_leds = RGB_BACKLIGHT_DISABLE_HHKB_BLOCKER_LEDS,
- .disable_when_usb_suspended = RGB_BACKLIGHT_DISABLE_WHEN_USB_SUSPENDED,
- .disable_after_timeout = RGB_BACKLIGHT_DISABLE_AFTER_TIMEOUT,
- .brightness = RGB_BACKLIGHT_BRIGHTNESS,
- .effect = RGB_BACKLIGHT_EFFECT,
- .effect_speed = RGB_BACKLIGHT_EFFECT_SPEED,
- .color_1 = RGB_BACKLIGHT_COLOR_1,
- .color_2 = RGB_BACKLIGHT_COLOR_2,
- .caps_lock_indicator = RGB_BACKLIGHT_CAPS_LOCK_INDICATOR,
- .layer_1_indicator = RGB_BACKLIGHT_LAYER_1_INDICATOR,
- .layer_2_indicator = RGB_BACKLIGHT_LAYER_2_INDICATOR,
- .layer_3_indicator = RGB_BACKLIGHT_LAYER_3_INDICATOR,
- .alphas_mods = {
- RGB_BACKLIGHT_ALPHAS_MODS_ROW_0,
- RGB_BACKLIGHT_ALPHAS_MODS_ROW_1,
- RGB_BACKLIGHT_ALPHAS_MODS_ROW_2,
- RGB_BACKLIGHT_ALPHAS_MODS_ROW_3,
- RGB_BACKLIGHT_ALPHAS_MODS_ROW_4 },
-#if defined(RGB_BACKLIGHT_M6_B)
- .custom_color = { { 0, 255 }, { 43, 255 }, { 85, 255 }, { 128, 255 }, { 171, 255 }, { 213, 255 } }
-#elif defined(RGB_BACKLIGHT_M10_C)
- .custom_color = { { 0, 255 }, { 43, 255 }, { 85, 255 }, { 128, 255 }, { 171, 255 }, { 213, 255 }, { 0, 255 }, { 43, 255 }, { 85, 255 }, { 128, 255 } }
-#endif
-};
-
-bool g_suspend_state = false;
-uint8_t g_indicator_state = 0;
-
-// Global tick at 20 Hz
-uint32_t g_tick = 0;
-
-// Ticks since this key was last hit.
-uint8_t g_key_hit[BACKLIGHT_LED_COUNT];
-
-// Ticks since any key was last hit.
-uint32_t g_any_key_hit = 0;
-
-#if defined(RGB_BACKLIGHT_HS60)
-
-// This is a 7-bit address, that gets left-shifted and bit 0
-// set to 0 for write, 1 for read (as per I2C protocol)
-// ADDR_2 is not needed. it is here as a dummy
-#define ISSI_ADDR_1 0x50
-
-const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
-/* Refer to IS31 manual for these locations
- * driver
- * | R location
- * | | G location
- * | | | B location
- * | | | | */
- {0, B_1, A_1, C_1}, //LA1
- {0, E_1, D_1, F_1}, //LA2
- {0, H_1, G_1, I_1}, //LA3
- {0, K_1, J_1, L_1}, //LA4
- {0, B_2, A_2, C_2}, //LA5
- {0, E_2, D_2, F_2}, //LA6
- {0, H_2, G_2, I_2}, //LA7
- {0, K_2, J_2, L_2}, //LA8
- {0, B_3, A_3, C_3}, //LA9
- {0, E_3, D_3, F_3}, //LA10
- {0, H_3, G_3, I_3}, //LA11
- {0, K_3, J_3, L_3}, //LA12
- {0, B_4, A_4, C_4}, //LA13
- {0, E_4, D_4, F_4}, //LA14
- {0, H_4, G_4, I_4}, //LA15
- {0, K_4, J_4, L_4}, //LA16
- {0, B_5, A_5, C_5}, //LA17
- {0, E_5, D_5, F_5}, //LA18
- {0, H_5, G_5, I_5}, //LA19
- {0, K_5, J_5, L_5}, //LA20
- {0, B_6, A_6, C_6}, //LA21
- {0, E_6, D_6, F_6}, //LA22
- {0, H_6, G_6, I_6}, //LA23
- {0, K_6, J_6, L_6}, //LA24
- {0, B_7, A_7, C_7}, //LA25
- {0, E_7, D_7, F_7}, //LA26
- {0, H_7, G_7, I_7}, //LA27
- {0, K_7, J_7, L_7}, //LA28
- {0, B_8, A_8, C_8}, //LA29
- {0, E_8, D_8, F_8}, //LA30
- {0, H_8, G_8, I_8}, //LA31
- {0, K_8, J_8, L_8}, //LA32
- {0, B_9, A_9, C_9}, //LA33
- {0, E_9, D_9, F_9}, //LA34
- {0, H_9, G_9, I_9}, //LA35
- {0, K_9, J_9, L_9}, //LA36
- {0, B_10, A_10, C_10}, //LA37
- {0, E_10, D_10, F_10}, //LA38
- {0, H_10, G_10, I_10}, //LA39
- {0, K_10, J_10, L_10}, //LA40
- {0, B_11, A_11, C_11}, //LA41
- {0, E_11, D_11, F_11}, //LA42
- {0, H_11, G_11, I_11}, //LA43
- {0, K_11, J_11, L_11}, //LA44
- {0, B_12, A_12, C_12}, //LA45
- {0, E_12, D_12, F_12}, //LA46
- {0, H_12, G_12, I_12}, //LA47
- {0, K_12, J_12, L_12}, //LA48
- {0, B_13, A_13, C_13}, //LA49
- {0, E_13, D_13, F_13}, //LA50
- {0, H_13, G_13, I_13}, //LA51
- {0, K_13, J_13, L_13}, //LA52
- {0, B_14, A_14, C_14}, //LA53
- {0, E_14, D_14, F_14}, //LA54
- {0, H_14, G_14, I_14}, //LA55
- {0, K_14, J_14, L_14}, //LA56
- {0, B_15, A_15, C_15}, //LA57
- {0, E_15, D_15, F_15}, //LA58
- {0, H_15, G_15, I_15}, //LA59
- {0, K_15, J_15, L_15}, //LA60
- {0, B_16, A_16, C_16}, //LA61
- {0, E_16, D_16, F_16}, //LA62
- {0, H_16, G_16, I_16}, //LA63
- {0, K_16, J_16, L_16}, //LA64
-};
-
-#elif defined(RGB_BACKLIGHT_NK65) || defined(RGB_BACKLIGHT_NEBULA68) || defined(RGB_BACKLIGHT_NK87) || defined(RGB_BACKLIGHT_KW_MEGA)
-
-// This is a 7-bit address, that gets left-shifted and bit 0
-// set to 0 for write, 1 for read (as per I2C protocol)
-// ADDR_2 is not needed. it is here as a dummy
-#define ISSI_ADDR_1 0x50
-#define ISSI_ADDR_2 0x52
-
-const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
-/* Refer to IS31 manual for these locations
- * driver
- * | R location
- * | | G location
- * | | | B location
- * | | | | */
- {0, B_1, A_1, C_1}, //LA1
- {0, E_1, D_1, F_1}, //LA2
- {0, H_1, G_1, I_1}, //LA3
- {0, K_1, J_1, L_1}, //LA4
- {0, B_2, A_2, C_2}, //LA5
- {0, E_2, D_2, F_2}, //LA6
- {0, H_2, G_2, I_2}, //LA7
- {0, K_2, J_2, L_2}, //LA8
- {0, B_3, A_3, C_3}, //LA9
- {0, E_3, D_3, F_3}, //LA10
- {0, H_3, G_3, I_3}, //LA11
- {0, K_3, J_3, L_3}, //LA12
- {0, B_4, A_4, C_4}, //LA13
- {0, E_4, D_4, F_4}, //LA14
- {0, H_4, G_4, I_4}, //LA15
- {0, K_4, J_4, L_4}, //LA16
- {0, B_5, A_5, C_5}, //LA17
- {0, E_5, D_5, F_5}, //LA18
- {0, H_5, G_5, I_5}, //LA19
- {0, K_5, J_5, L_5}, //LA20
- {0, B_6, A_6, C_6}, //LA21
- {0, E_6, D_6, F_6}, //LA22
- {0, H_6, G_6, I_6}, //LA23
- {0, K_6, J_6, L_6}, //LA24
- {0, B_7, A_7, C_7}, //LA25
- {0, E_7, D_7, F_7}, //LA26
- {0, H_7, G_7, I_7}, //LA27
- {0, K_7, J_7, L_7}, //LA28
- {0, B_8, A_8, C_8}, //LA29
- {0, E_8, D_8, F_8}, //LA30
- {0, H_8, G_8, I_8}, //LA31
- {0, K_8, J_8, L_8}, //LA32
- {0, B_9, A_9, C_9}, //LA33
- {0, E_9, D_9, F_9}, //LA34
- {0, H_9, G_9, I_9}, //LA35
- {0, K_9, J_9, L_9}, //LA36
- {0, B_10, A_10, C_10}, //LA37
- {0, E_10, D_10, F_10}, //LA38
- {0, H_10, G_10, I_10}, //LA39
- {0, K_10, J_10, L_10}, //LA40
- {0, B_11, A_11, C_11}, //LA41
- {0, E_11, D_11, F_11}, //LA42
- {0, H_11, G_11, I_11}, //LA43
- {0, K_11, J_11, L_11}, //LA44
- {0, B_12, A_12, C_12}, //LA45
- {0, E_12, D_12, F_12}, //LA46
- {0, H_12, G_12, I_12}, //LA47
- {0, K_12, J_12, L_12}, //LA48
- {0, B_13, A_13, C_13}, //LA49
- {0, E_13, D_13, F_13}, //LA50
- {0, H_13, G_13, I_13}, //LA51
- {0, K_13, J_13, L_13}, //LA52
- {0, B_14, A_14, C_14}, //LA53
- {0, E_14, D_14, F_14}, //LA54
- {0, H_14, G_14, I_14}, //LA55
- {0, K_14, J_14, L_14}, //LA56
- {0, B_15, A_15, C_15}, //LA57
- {0, E_15, D_15, F_15}, //LA58
- {0, H_15, G_15, I_15}, //LA59
- {0, K_15, J_15, L_15}, //LA60
- {0, B_16, A_16, C_16}, //LA61
- {0, E_16, D_16, F_16}, //LA62
- {0, H_16, G_16, I_16}, //LA63
- {0, K_16, J_16, L_16}, //LA64
-
- {1, B_1, A_1, C_1}, //LB1
- {1, E_1, D_1, F_1}, //LB2
- {1, H_1, G_1, I_1}, //LB3
- {1, K_1, J_1, L_1}, //LB4
- {1, B_2, A_2, C_2}, //LB5
- {1, E_2, D_2, F_2}, //LB6
- {1, H_2, G_2, I_2}, //LB7
- {1, K_2, J_2, L_2}, //LB8
- {1, B_3, A_3, C_3}, //LB9
- {1, E_3, D_3, F_3}, //LB10
- {1, H_3, G_3, I_3}, //LB11
- {1, K_3, J_3, L_3}, //LB12
- {1, B_4, A_4, C_4}, //LB13
- {1, E_4, D_4, F_4}, //LB14
- {1, H_4, G_4, I_4}, //LB15
- {1, K_4, J_4, L_4}, //LB16
- {1, B_5, A_5, C_5}, //LB17
- {1, E_5, D_5, F_5}, //LB18
- {1, H_5, G_5, I_5}, //LB19
- {1, K_5, J_5, L_5}, //LB20
- {1, B_6, A_6, C_6}, //LB21
- {1, E_6, D_6, F_6}, //LB22
- {1, H_6, G_6, I_6}, //LB23
- {1, K_6, J_6, L_6}, //LB24
- {1, B_7, A_7, C_7}, //LB25
- {1, E_7, D_7, F_7}, //LB26
- {1, H_7, G_7, I_7}, //LB27
- {1, K_7, J_7, L_7}, //LB28
- {1, B_8, A_8, C_8}, //LB29
- {1, E_8, D_8, F_8}, //LB30
- {1, H_8, G_8, I_8}, //LB31
- {1, K_8, J_8, L_8}, //LB32
- {1, B_9, A_9, C_9}, //LB33
- {1, E_9, D_9, F_9}, //LB34
- {1, H_9, G_9, I_9}, //LB35
- {1, K_9, J_9, L_9}, //LB36
- {1, B_10, A_10, C_10}, //LB37
- {1, E_10, D_10, F_10}, //LB38
- {1, H_10, G_10, I_10}, //LB39
- {1, K_10, J_10, L_10}, //LB40
- {1, B_11, A_11, C_11}, //LB41
- {1, E_11, D_11, F_11}, //LB42
- {1, H_11, G_11, I_11}, //LB43
- {1, K_11, J_11, L_11}, //LB44
- {1, B_12, A_12, C_12}, //LB45
- {1, E_12, D_12, F_12}, //LB46
- {1, H_12, G_12, I_12}, //LB47
- {1, K_12, J_12, L_12}, //LB48
- {1, B_13, A_13, C_13}, //LB49
- {1, E_13, D_13, F_13}, //LB50
- {1, H_13, G_13, I_13}, //LB51
- {1, K_13, J_13, L_13}, //LB52
- {1, B_14, A_14, C_14}, //LB53
- {1, E_14, D_14, F_14}, //LB54
- {1, H_14, G_14, I_14}, //LB55
- {1, K_14, J_14, L_14}, //LB56
- {1, B_15, A_15, C_15}, //LB57
- {1, E_15, D_15, F_15}, //LB58
- {1, H_15, G_15, I_15}, //LB59
- {1, K_15, J_15, L_15}, //LB60
- {1, B_16, A_16, C_16}, //LB61
- {1, E_16, D_16, F_16}, //LB62
- {1, H_16, G_16, I_16}, //LB63
- {1, K_16, J_16, L_16}, //LB64
-};
-
-#elif defined(RGB_BACKLIGHT_NEBULA12)
-// This is a 7-bit address, that gets left-shifted and bit 0
-// set to 0 for write, 1 for read (as per I2C protocol)
-#define ISSI_ADDR_1 0x74
-
-const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
-/* Refer to IS31 manual for these locations
- * driver
- * | R location
- * | | G location
- * | | | B location
- * | | | | */
- {0, C1_1, C3_2, C4_2}, //A1
- {0, C1_2, C2_2, C4_3}, //A2
- {0, C1_3, C2_3, C3_3}, //A3
- {0, C1_4, C2_4, C3_4}, //A4
- {0, C1_5, C2_5, C3_5}, //A5
- {0, C1_6, C2_6, C3_6}, //A6
- {0, C1_7, C2_7, C3_7}, //A7
- {0, C1_8, C2_8, C3_8}, //A8
- {0, C9_1, C8_1, C7_1}, //A9
- {0, C9_2, C8_2, C7_2}, //A10
- {0, C9_3, C8_3, C7_3}, //A11
- {0, C9_4, C8_4, C7_4}, //A12
- {0, C9_5, C8_5, C7_5}, //A13
- {0, C9_6, C8_6, C7_6}, //A14
- {0, C9_7, C8_7, C6_6}, //A15
- {0, C9_8, C7_7, C6_7}, //A16
-};
-
-#elif defined(RGB_BACKLIGHT_U80_A)
-
-// U80-A prototype uses 3 ISSI drivers
-#define ISSI_ADDR_1 0x74 // 11101[00] <- GND
-#define ISSI_ADDR_2 0x76 // 11101[10] <- SDA
-#define ISSI_ADDR_3 0x75 // 11101[01] <- SCL
-
-const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
-/* Refer to IS31 manual for these locations
- * driver
- * | R location
- * | | G location
- * | | | B location
- * | | | | */
- {0, C2_1, C3_1, C4_1}, // LA0
- {0, C1_1, C3_2, C4_2}, // LA1
- {0, C1_2, C2_2, C4_3}, // LA2
- {0, C1_3, C2_3, C3_3}, // LA3
- {0, C1_4, C2_4, C3_4}, // LA4
- {0, C1_5, C2_5, C3_5}, // LA5
- {0, C1_6, C2_6, C3_6}, // LA6
- {0, C1_7, C2_7, C3_7}, // LA7
- {0, C1_8, C2_8, C3_8}, // LA8
- {0, C9_1, C8_1, C7_1}, // LA9
- {0, C9_2, C8_2, C7_2}, // LA10
- {0, C9_3, C8_3, C7_3}, // LA11
- {0, C9_4, C8_4, C7_4}, // LA12
- {0, C9_5, C8_5, C7_5}, // LA13
- {0, C9_6, C8_6, C7_6}, // LA14
- {0, C9_7, C8_7, C6_6}, // LA15
- {0, C9_8, C7_7, C6_7}, // LA16
- {0, C8_8, C7_8, C6_8}, // LA17
-
- {0, C2_9, C3_9, C4_9}, // LB0
- {0, C1_9, C3_10, C4_10}, // LB1
- {0, C1_10, C2_10, C4_11}, // LB2
- {0, C1_11, C2_11, C3_11}, // LB3
- {0, C1_12, C2_12, C3_12}, // LB4
- {0, C1_13, C2_13, C3_13}, // LB5
- {0, C1_14, C2_14, C3_14}, // LB6
- {0, C1_15, C2_15, C3_15}, // LB7
- {0, C1_16, C2_16, C3_16}, // LB8
- {0, C9_9, C8_9, C7_9}, // LB9
- {0, C9_10, C8_10, C7_10}, // LB10
- {0, C9_11, C8_11, C7_11}, // LB11
- {0, C9_12, C8_12, C7_12}, // LB12
- {0, C9_13, C8_13, C7_13}, // LB13
- {0, C9_14, C8_14, C7_14}, // LB14
- {0, C9_15, C8_15, C6_14}, // LB15
- {0, C9_16, C7_15, C6_15}, // LB16
- {0, C8_16, C7_16, C6_16}, // LB17
-
- {1, C2_1, C3_1, C4_1}, // LC0
- {1, C1_1, C3_2, C4_2}, // LC1
- {1, C1_2, C2_2, C4_3}, // LC2
- {1, C1_3, C2_3, C3_3}, // LC3
- {1, C1_4, C2_4, C3_4}, // LC4
- {1, C1_5, C2_5, C3_5}, // LC5
- {1, C1_6, C2_6, C3_6}, // LC6
- {1, C1_7, C2_7, C3_7}, // LC7
- {1, C1_8, C2_8, C3_8}, // LC8
- {1, C9_1, C8_1, C7_1}, // LC9
- {1, C9_2, C8_2, C7_2}, // LC10
- {1, C9_3, C8_3, C7_3}, // LC11
- {1, C9_4, C8_4, C7_4}, // LC12
- {1, C9_5, C8_5, C7_5}, // LC13
- {1, C9_6, C8_6, C7_6}, // LC14
- {1, C9_7, C8_7, C6_6}, // LC15
- {1, C9_8, C7_7, C6_7}, // LC16
- {1, C8_8, C7_8, C6_8}, // LC17
-
- {1, C2_9, C3_9, C4_9}, // LD0
- {1, C1_9, C3_10, C4_10}, // LD1
- {1, C1_10, C2_10, C4_11}, // LD2
- {1, C1_11, C2_11, C3_11}, // LD3
- {1, C1_12, C2_12, C3_12}, // LD4
- {1, C1_13, C2_13, C3_13}, // LD5
- {1, C1_14, C2_14, C3_14}, // LD6
- {1, C1_15, C2_15, C3_15}, // LD7
- {1, C1_16, C2_16, C3_16}, // LD8
- {1, C9_9, C8_9, C7_9}, // LD9
- {1, C9_10, C8_10, C7_10}, // LD10
- {1, C9_11, C8_11, C7_11}, // LD11
- {1, C9_12, C8_12, C7_12}, // LD12
- {1, C9_13, C8_13, C7_13}, // LD13
- {1, C9_14, C8_14, C7_14}, // LD14
- {1, C9_15, C8_15, C6_14}, // LD15
- {1, C9_16, C7_15, C6_15}, // LD16
- {1, C8_16, C7_16, C6_16}, // LD17
-
- {2, C2_1, C3_1, C4_1}, // LE0
- {2, C1_1, C3_2, C4_2}, // LE1
- {2, C1_2, C2_2, C4_3}, // LE2
- {2, C1_3, C2_3, C3_3}, // LE3
- {2, C1_4, C2_4, C3_4}, // LE4
- {2, C1_5, C2_5, C3_5}, // LE5
- {2, C1_6, C2_6, C3_6}, // LE6
- {2, C1_7, C2_7, C3_7}, // LE7
- {2, C1_8, C2_8, C3_8}, // LE8
- {2, C9_1, C8_1, C7_1}, // LE9
- {2, C9_2, C8_2, C7_2}, // LE10
- {2, C9_3, C8_3, C7_3}, // LE11
- {2, C9_4, C8_4, C7_4}, // LE12
- {2, C9_5, C8_5, C7_5}, // LE13
- {2, C9_6, C8_6, C7_6}, // LE14
- {2, C9_7, C8_7, C6_6}, // LE15
- {2, C9_8, C7_7, C6_7}, // LE16
- {2, C8_8, C7_8, C6_8}, // LE17
-
- {2, C2_9, C3_9, C4_9}, // LF0
- {2, C1_9, C3_10, C4_10}, // LF1
- {2, C1_10, C2_10, C4_11}, // LF2
- {2, C1_11, C2_11, C3_11}, // LF3
- {2, C1_12, C2_12, C3_12}, // LF4
- {2, C1_13, C2_13, C3_13}, // LF5
- {2, C1_14, C2_14, C3_14}, // LF6
- {2, C1_15, C2_15, C3_15}, // LF7
- {2, C1_16, C2_16, C3_16}, // LF8
- {2, C9_9, C8_9, C7_9}, // LF9
- {2, C9_10, C8_10, C7_10}, // LF10
- {2, C9_11, C8_11, C7_11}, // LF11
- {2, C9_12, C8_12, C7_12}, // LF12
- {2, C9_13, C8_13, C7_13}, // LF13
- {2, C9_14, C8_14, C7_14}, // LF14
- {2, C9_15, C8_15, C6_14}, // LF15
- {2, C9_16, C7_15, C6_15}, // LF16
- {2, C8_16, C7_16, C6_16}, // LF17
-};
-#elif defined(RGB_BACKLIGHT_DAWN60)
-// This is a 7-bit address, that gets left-shifted and bit 0
-// set to 0 for write, 1 for read (as per I2C protocol)
-#define ISSI_ADDR_1 0x74
-#define ISSI_ADDR_2 0x76
-
-const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
-/* Refer to IS31 manual for these locations
- * driver
- * | R location
- * | | G location
- * | | | B location
- * | | | | */
- {0, C1_1, C3_2, C4_2}, //A1
- {0, C1_2, C2_2, C4_3}, //A2
- {0, C1_3, C2_3, C3_3}, //A3
- {0, C1_4, C2_4, C3_4}, //A4
- {0, C1_5, C2_5, C3_5}, //A5
- {0, C1_6, C2_6, C3_6}, //A6
- {0, C1_7, C2_7, C3_7}, //A7
- {0, C1_8, C2_8, C3_8}, //A8
- {0, C9_1, C8_1, C7_1}, //A9
- {0, C9_2, C8_2, C7_2}, //A10
- {0, C9_3, C8_3, C7_3}, //A11
- {0, C9_4, C8_4, C7_4}, //A12
- {0, C9_5, C8_5, C7_5}, //A13
- {0, C9_6, C8_6, C7_6}, //A14
- {0, C9_7, C8_7, C6_6}, //A15
- {0, C9_8, C7_7, C6_7}, //A16
-
- {0, C1_9, C3_10, C4_10}, //B1
- {0, C1_10, C2_10, C4_11}, //B2
- {0, C1_11, C2_11, C3_11}, //B3
- {0, C1_12, C2_12, C3_12}, //B4
- {0, C1_13, C2_13, C3_13}, //B5
- {0, C1_14, C2_14, C3_14}, //B6
- {0, C1_15, C2_15, C3_15}, //B7
- {0, C1_16, C2_16, C3_16}, //B8
- {0, C9_9, C8_9, C7_9}, //B9
- {0, C9_10, C8_10, C7_10}, //B10
- {0, C9_11, C8_11, C7_11}, //B11
- {0, C9_12, C8_12, C7_12}, //B12
- {0, C9_13, C8_13, C7_13}, //B13
- {0, C9_14, C8_14, C7_14}, //B14
- {0, C9_15, C8_15, C6_14}, //B15
- {0, C9_16, C7_15, C6_15}, //B16
-
- {1, C1_1, C3_2, C4_2}, //C1
- {1, C1_2, C2_2, C4_3}, //C2
- {1, C1_3, C2_3, C3_3}, //C3
- {1, C1_4, C2_4, C3_4}, //C4
- {1, C1_5, C2_5, C3_5}, //C5
- {1, C1_6, C2_6, C3_6}, //C6
- {1, C1_7, C2_7, C3_7}, //C7
- {1, C1_8, C2_8, C3_8}, //C8
- {1, C9_1, C8_1, C7_1}, //C9
- {1, C9_2, C8_2, C7_2}, //C10
- {1, C9_3, C8_3, C7_3}, //C11
- {1, C9_4, C8_4, C7_4}, //C12
- {1, C9_5, C8_5, C7_5}, //C13
- {1, C9_6, C8_6, C7_6}, //C14
- {1, C9_7, C8_7, C6_6}, //C15
- {1, C9_8, C7_7, C6_7}, //C16
-
- {1, C1_9, C3_10, C4_10}, //D1
- {1, C1_10, C2_10, C4_11}, //D2
- {1, C1_11, C2_11, C3_11}, //D3
- {1, C1_12, C2_12, C3_12}, //D4
- {1, C1_13, C2_13, C3_13}, //D5
- {1, C1_14, C2_14, C3_14}, //D6
- {1, C1_15, C2_15, C3_15}, //D7
- {1, C1_16, C2_16, C3_16}, //D8
- {1, C9_9, C8_9, C7_9}, //D9
- {1, C9_10, C8_10, C7_10}, //D10
- {1, C9_11, C8_11, C7_11}, //D11
- {1, C9_12, C8_12, C7_12}, //D12
- {1, C9_13, C8_13, C7_13}, //D13
- {1, C9_14, C8_14, C7_14}, //D14
- {1, C9_15, C8_15, C6_14}, //D15
- {1, C9_16, C7_15, C6_15} //D16
-};
-#elif defined(RGB_BACKLIGHT_M6_B)
- // Driver has fixed mapping of index to the red, green and blue LEDs
-#elif defined(RGB_BACKLIGHT_M10_C)
-// This is a 7-bit address, that gets left-shifted and bit 0
-// set to 0 for write, 1 for read (as per I2C protocol)
-#define ISSI_ADDR_1 0x74
-#define ISSI_ADDR_2
-
-const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
- {0, C1_9, C3_10, C4_10}, // LB1
- {0, C1_10, C2_10, C4_11}, // LB2
- {0, C1_11, C2_11, C3_11}, // LB3
- {0, C1_12, C2_12, C3_12}, // LB4
- {0, C1_13, C2_13, C3_13}, // LB5
- {0, C1_14, C2_14, C3_14}, // LB6
- {0, C9_11, C8_11, C7_11}, // LB11
- {0, C9_12, C8_12, C7_12}, // LB12
- {0, C9_13, C8_13, C7_13}, // LB13
- {0, C9_14, C8_14, C7_14}, // LB14
- {0, C9_15, C8_15, C6_14}, // LB15
- {0, C9_16, C7_15, C6_15} // LB16
-};
-#else
-// This is a 7-bit address, that gets left-shifted and bit 0
-// set to 0 for write, 1 for read (as per I2C protocol)
-#define ISSI_ADDR_1 0x74
-#define ISSI_ADDR_2 0x76
-
-const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
-/* Refer to IS31 manual for these locations
- * driver
- * | R location
- * | | G location
- * | | | B location
- * | | | | */
- {0, C2_1, C3_1, C4_1}, // LA0
- {0, C1_1, C3_2, C4_2}, // LA1
- {0, C1_2, C2_2, C4_3}, // LA2
- {0, C1_3, C2_3, C3_3}, // LA3
- {0, C1_4, C2_4, C3_4}, // LA4
- {0, C1_5, C2_5, C3_5}, // LA5
- {0, C1_6, C2_6, C3_6}, // LA6
- {0, C1_7, C2_7, C3_7}, // LA7
- {0, C1_8, C2_8, C3_8}, // LA8
- {0, C9_1, C8_1, C7_1}, // LA9
- {0, C9_2, C8_2, C7_2}, // LA10
- {0, C9_3, C8_3, C7_3}, // LA11
- {0, C9_4, C8_4, C7_4}, // LA12
- {0, C9_5, C8_5, C7_5}, // LA13
- {0, C9_6, C8_6, C7_6}, // LA14
- {0, C9_7, C8_7, C6_6}, // LA15
- {0, C9_8, C7_7, C6_7}, // LA16
- {0, C8_8, C7_8, C6_8}, // LA17
-
- {0, C2_9, C3_9, C4_9}, // LB0
- {0, C1_9, C3_10, C4_10}, // LB1
- {0, C1_10, C2_10, C4_11}, // LB2
- {0, C1_11, C2_11, C3_11}, // LB3
- {0, C1_12, C2_12, C3_12}, // LB4
- {0, C1_13, C2_13, C3_13}, // LB5
- {0, C1_14, C2_14, C3_14}, // LB6
- {0, C1_15, C2_15, C3_15}, // LB7
- {0, C1_16, C2_16, C3_16}, // LB8
- {0, C9_9, C8_9, C7_9}, // LB9
- {0, C9_10, C8_10, C7_10}, // LB10
- {0, C9_11, C8_11, C7_11}, // LB11
- {0, C9_12, C8_12, C7_12}, // LB12
- {0, C9_13, C8_13, C7_13}, // LB13
- {0, C9_14, C8_14, C7_14}, // LB14
- {0, C9_15, C8_15, C6_14}, // LB15
- {0, C9_16, C7_15, C6_15}, // LB16
- {0, C8_16, C7_16, C6_16}, // LB17
-
- {1, C2_1, C3_1, C4_1}, // LC0
- {1, C1_1, C3_2, C4_2}, // LC1
- {1, C1_2, C2_2, C4_3}, // LC2
- {1, C1_3, C2_3, C3_3}, // LC3
- {1, C1_4, C2_4, C3_4}, // LC4
- {1, C1_5, C2_5, C3_5}, // LC5
- {1, C1_6, C2_6, C3_6}, // LC6
- {1, C1_7, C2_7, C3_7}, // LC7
- {1, C1_8, C2_8, C3_8}, // LC8
- {1, C9_1, C8_1, C7_1}, // LC9
- {1, C9_2, C8_2, C7_2}, // LC10
- {1, C9_3, C8_3, C7_3}, // LC11
- {1, C9_4, C8_4, C7_4}, // LC12
- {1, C9_5, C8_5, C7_5}, // LC13
- {1, C9_6, C8_6, C7_6}, // LC14
- {1, C9_7, C8_7, C6_6}, // LC15
- {1, C9_8, C7_7, C6_7}, // LC16
- {1, C8_8, C7_8, C6_8}, // LC17
-
- {1, C2_9, C3_9, C4_9}, // LD0
- {1, C1_9, C3_10, C4_10}, // LD1
- {1, C1_10, C2_10, C4_11}, // LD2
- {1, C1_11, C2_11, C3_11}, // LD3
- {1, C1_12, C2_12, C3_12}, // LD4
- {1, C1_13, C2_13, C3_13}, // LD5
- {1, C1_14, C2_14, C3_14}, // LD6
- {1, C1_15, C2_15, C3_15}, // LD7
- {1, C1_16, C2_16, C3_16}, // LD8
- {1, C9_9, C8_9, C7_9}, // LD9
- {1, C9_10, C8_10, C7_10}, // LD10
- {1, C9_11, C8_11, C7_11}, // LD11
- {1, C9_12, C8_12, C7_12}, // LD12
- {1, C9_13, C8_13, C7_13}, // LD13
- {1, C9_14, C8_14, C7_14}, // LD14
- {1, C9_15, C8_15, C6_14}, // LD15
- {1, C9_16, C7_15, C6_15}, // LD16
- {1, C8_16, C7_16, C6_16}, // LD17
-};
-#endif
-
-
-typedef struct Point {
- uint8_t x;
- uint8_t y;
-} Point;
-
-
-// index in range 0..71 (LA0..LA17, LB0..LB17, LC0..LC17, LD0..LD17)
-// point values in range x=0..224 y=0..64
-// origin is center of top-left key (i.e Esc)
-#if defined(RGB_BACKLIGHT_ZEAL65)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
- {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
- // LB0..LB17
- {144,0}, {160,0}, {176,0}, {192,0}, {216,0}, {224,0}, {240,0}, {240,16}, {240,32},
- {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {240,48}, {240,64}, {224,64},
- // LC0..LC17
- {96,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {255,255}, {48,60}, {28,64},
- {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {20,44}, {10,48}, {4,64},
- // LD0..LD17
- {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
- {116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {144,60}, {164,64}, {188,64}, {208,64}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {64,128}, {75,132}, {84,145}, {91,164}, {97,187}, {102,213}, {105,242}, {109,255}, {128,243},
- {61,255}, {67,255}, {72,255}, {77,255}, {82,255}, {86,255}, {90,255}, {93,255}, {96,255},
- // LB0..LB17
- {56,255}, {51,255}, {46,255}, {42,255}, {37,255}, {35,255}, {32,255}, {19,255}, {0,255},
- {53,132}, {44,145}, {37,164}, {31,187}, {26,213}, {22,249}, {237,255}, {224,255}, {221,255},
- // LC0..LC17
- {184,255}, {179,135}, {170,149}, {163,169}, {157,193}, {153,220}, {255,255}, {167,255}, {165,255},
- {128,26}, {128,60}, {128,94}, {128,128}, {128,162}, {128,196}, {145,233}, {148,255}, {161,255},
- // LD0..LD17
- {0,9}, {0,43}, {0,77}, {0,111}, {0,145}, {0,201}, {224,181}, {230,217}, {235,255},
- {189,128}, {200,131}, {210,141}, {218,159}, {255,255}, {201,228}, {206,255}, {213,255}, {218,255}
-};
-#elif defined(RGB_BACKLIGHT_KOYU)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
- {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
- // LB0..LB17
- {144,0}, {160,0}, {176,0}, {192,0}, {208,0}, {224,0}, {240,0}, {240,16}, {240,32},
- {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {240,48}, {240,64}, {224,64},
- // LC0..LC17
- {112,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {64,60}, {44,60}, {24,64},
- {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {255,255}, {10,48}, {4,64},
- // LD0..LD17
- {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
- {116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {160,60}, {180,64}, {208,64}, {255,255}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {64,128}, {75,132}, {84,145}, {91,164}, {97,187}, {102,213}, {105,242}, {109,255}, {128,243},
- {61,255}, {67,255}, {72,255}, {77,255}, {82,255}, {86,255}, {90,255}, {93,255}, {96,255},
- // LB0..LB17
- {56,255}, {51,255}, {46,255}, {42,255}, {38,255}, {35,255}, {32,255}, {19,255}, {0,255},
- {53,132}, {44,145}, {37,164}, {31,187}, {26,213}, {22,249}, {237,255}, {224,255}, {221,255},
- // LC0..LC17
- {189,255}, {179,135}, {170,149}, {163,169}, {157,193}, {153,220}, {172,252}, {169,255}, {165,255},
- {128,26}, {128,60}, {128,94}, {128,128}, {128,162}, {128,196}, {255,255}, {148,255}, {161,255},
- // LD0..LD17
- {0,9}, {0,43}, {0,77}, {0,111}, {0,145}, {0,201}, {224,181}, {230,217}, {235,255},
- {189,128}, {200,131}, {210,141}, {218,159}, {255,255}, {207,238}, {211,255}, {218,255}, {255,255}
-};
-#elif defined(RGB_BACKLIGHT_M65_B) || defined(RGB_BACKLIGHT_M65_BX)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
- {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
- // LB0..LB17
- {144,0}, {160,0}, {176,0}, {192,0}, {208,0}, {224,0}, {216,0}, {240,0}, {240,16},
- {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {240,32}, {240,48}, {240,64},
- // LC0..LC17
- {112,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {64,60}, {44,60}, {24,64},
- {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {255,255}, {10,48}, {4,64},
- // LD0..LD17
- {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
- {116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {160,60}, {180,64}, {208,64}, {224,64}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {64,128}, {75,132}, {84,145}, {91,164}, {97,187}, {102,213}, {105,242}, {109,255}, {128,243},
- {61,255}, {67,255}, {72,255}, {77,255}, {82,255}, {86,255}, {90,255}, {93,255}, {96,255},
- // LB0..LB17
- {56,255}, {51,255}, {46,255}, {42,255}, {38,255}, {35,255}, {37,255}, {32,255}, {19,255},
- {53,132}, {44,145}, {37,164}, {31,187}, {26,213}, {22,249}, {0,255}, {237,255}, {224,255},
- // LC0..LC17
- {189,255}, {179,135}, {170,149}, {163,169}, {157,193}, {153,220}, {172,252}, {169,255}, {165,255},
- {128,26}, {128,60}, {128,94}, {128,128}, {128,162}, {128,196}, {255,255}, {148,255}, {161,255},
- // LD0..LD17
- {0,9}, {0,43}, {0,77}, {0,111}, {0,145}, {0,201}, {224,181}, {230,217}, {235,255},
- {189,128}, {200,131}, {210,141}, {218,159}, {255,255}, {207,238}, {211,255}, {218,255}, {221,255}
-};
-#elif defined(RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_M60_A)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
- {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
- // LB0..LB17
- {144,0}, {160,0}, {176,0}, {192,0}, {216,0}, {224,0}, {255,255}, {255,255}, {255,255},
- {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {255,255}, {255,255}, {255,255},
- // LC0..LC17
- {102,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {60,64}, {43,64}, {23,64},
- {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {20,48}, {2,48}, {3,64},
- // LD0..LD17
- {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {210,48}, {224,48},
- {116,48}, {132,48}, {148,48}, {164,48}, {144,64}, {161,64}, {181,64}, {201,64}, {221,64}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {58,129}, {70,129}, {80,139}, {89,157}, {96,181}, {101,208}, {105,238}, {109,255}, {128,247},
- {58,255}, {64,255}, {70,255}, {75,255}, {80,255}, {85,255}, {89,255}, {93,255}, {96,255},
- // LB0..LB17
- {53,255}, {48,255}, {43,255}, {39,255}, {34,255}, {32,255}, {255,255}, {255,255}, {255,255},
- {48,139}, {39,157}, {32,181}, {27,208}, {23,238}, {19,255}, {255,255}, {255,255}, {255,255},
- // LC0..LC17
- {188,255}, {183,131}, {173,143}, {165,163}, {159,188}, {154,216}, {172,252}, {170,255}, {165,255},
- {128,9}, {128,46}, {128,82}, {128,119}, {128,155}, {128,192}, {150,244}, {147,255}, {161,255},
- // LD0..LD17
- {0,27}, {0,64}, {0,101}, {0,137}, {0,174}, {255,233}, {228,201}, {235,255}, {237,255},
- {195,128}, {206,136}, {215,152}, {222,175}, {205,234}, {209,255}, {214,255}, {219,255}, {223,255}
-};
-#elif defined(RGB_BACKLIGHT_WT60_B) || defined(RGB_BACKLIGHT_WT60_BX) || defined(RGB_BACKLIGHT_WT60_C)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
- {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
- // LB0..LB17
- {144,0}, {160,0}, {176,0}, {192,0}, {208,0}, {224,0}, {216,0}, {255,255}, {255,255},
- {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {255,255}, {255,255}, {255,255},
- // LC0..LC17
- {112,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {64,60}, {44,64}, {24,64},
- {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {255,255}, {10,48}, {4,64},
- // LD0..LD17
- {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
- {116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {160,60}, {180,64}, {200,64}, {220,64}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {58,129}, {70,129}, {80,139}, {89,157}, {96,181}, {101,208}, {105,238}, {109,255}, {128,247},
- {58,255}, {64,255}, {70,255}, {75,255}, {80,255}, {85,255}, {89,255}, {93,255}, {96,255},
- // LB0..LB17
- {53,255}, {48,255}, {43,255}, {39,255}, {35,255}, {32,255}, {34,255}, {255,255}, {255,255},
- {48,139}, {39,157}, {32,181}, {27,208}, {23,238}, {19,255}, {255,255}, {255,255}, {255,255},
- // LC0..LC17
- {192,255}, {183,131}, {173,143}, {165,163}, {159,188}, {154,216}, {173,248}, {170,255}, {165,255},
- {128,9}, {128,46}, {128,82}, {128,119}, {128,155}, {128,192}, {255,255}, {148,255}, {161,255},
- // LD0..LD17
- {0,27}, {0,64}, {0,101}, {0,137}, {0,174}, {0,233}, {228,201}, {235,242}, {237,255},
- {195,128}, {206,136}, {215,152}, {222,175}, {255,255}, {211,248}, {214,255}, {219,255}, {223,255}
-};
-#elif defined(RGB_BACKLIGHT_U80_A)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // Thse are scaled by 14.5 per U
- // LA0..LA17
- {109,36}, {94,36}, {80,36}, {65,36}, {51,36}, {36,36}, {22,36}, {4,36}, {5,51},
- {116,22}, {102,22}, {87,22}, {73,22}, {58,22}, {44,22}, {29,22}, {15,22}, {0,22},
- // LB0..LB17
- {131,22}, {145,22}, {160,22}, {174,22}, {196,22}, {0,0}, {0,0}, {0,0}, {0,0},
- {123,36}, {138,36}, {152,36}, {167,36}, {181,36}, {199,36}, {0,0}, {0,0}, {0,0},
- // LC0..LC17
- {102,80}, {91,65}, {76,65}, {62,65}, {47,65}, {33,65}, {58,76}, {40,80}, {22,80},
- {98,51}, {83,51}, {69,51}, {54,51}, {40,51}, {25,51}, {0,0}, {9,65}, {4,80},
- // LD0..LD17
- {112,51}, {127,51}, {141,51}, {156,51}, {170,51}, {194,51}, {163,65}, {190,65}, {0,0},
- {105,65}, {120,65}, {134,65}, {149,65}, {0,0}, {145,76}, {163,80}, {181,80}, {199,80},
- // LE0..LE17
- {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
- {73,0}, {94,0}, {109,0}, {123,0}, {138,0}, {58,0}, {44,0}, {29,0}, {0,0},
- // LF0..LF17
- {160,0}, {174,0}, {189,0}, {203,0}, {225,0}, {239,0}, {254,0}, {254,22}, {254,36},
- {239,22}, {239,36}, {225,22}, {225,36}, {0,0}, {239,65}, {225,80}, {239,80}, {254,80}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {59,129}, {69,129}, {80,138}, {88,154}, {95,175}, {100,200}, {104,227}, {107,255}, {128,226},
- {59,255}, {64,255}, {69,255}, {75,255}, {80,255}, {84,255}, {88,255}, {91,255}, {95,255},
- // LB0..LB17
- {53,255}, {48,255}, {44,255}, {40,255}, {35,255}, {255,255}, {255,255}, {255,255}, {255,255},
- {48,138}, {40,154}, {33,175}, {28,200}, {24,227}, {21,255}, {255,255}, {255,255}, {255,255},
- // LC0..LC17
- {192,255}, {184,131}, {174,141}, {166,159}, {160,181}, {155,207}, {174,244}, {171,255}, {166,255},
- {128,9}, {128,43}, {128,77}, {128,111}, {128,145}, {128,179}, {255,255}, {150,252}, {162,255},
- // LD0..LD17
- {0,26}, {0,60}, {0,94}, {0,128}, {0,162}, {0,218}, {227,193}, {234,245}, {255,255},
- {195,128}, {205,135}, {214,149}, {221,169}, {255,255}, {210,244}, {213,255}, {218,255}, {222,255},
- // LE0..LE17
- {255,255}, {255,255}, {255,255}, {255,255}, {255,255}, {255,255}, {255,255}, {255,255}, {255,255},
- {70,255}, {66,255}, {62,255}, {59,255}, {56,255}, {73,255}, {76,255}, {79,255}, {84,255},
- // LF0..LF17
- {52,255}, {49,255}, {47,255}, {44,255}, {41,255}, {38,255}, {37,255}, {25,255}, {14,255},
- {27,255}, {15,255}, {29,255}, {17,255}, {255,255}, {241,255}, {227,255}, {229,255}, {231,255}
-};
-#elif defined(RGB_BACKLIGHT_HS60) && defined(HS60_ANSI)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA47
- {0,0}, {4,16}, {6,32}, {10,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48},
- {48,0}, {56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48},
- {96,0}, {104,16}, {108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32},
- {148,48}, {144,0}, {152,16}, {156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32},
- {255,255},// LA48 does not exist, dummy
- // LA49..LA50
- {192,0}, {200,16},
- {255,255},// LA51 does not exit, dummy
- // LA52..LA60
- {210,48}, {216,0}, {220,16}, {214,32}, {222,64}, {2,64}, {22,64}, {42,64}, {102,64},
- {255,255},// LA61 does not exit, dummy
- {162,64}, {182,64}, {202,64}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA47
- {96,255}, {109,255}, {128,242}, {148,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188},
- {85,255}, {96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131},
- {70,255}, {70,129}, {129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152},
- {53,255}, {39,157}, {255,101}, {222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174},
- {255,255},// LA48 does not exist, dummy
- // LA49..LA50
- {39,255}, {23,238},
- {255,255},// LA51 does not exit, dummy
- // LA52..LA60
- {235,255}, {33,255}, {19,255}, {255,233}, {224,255}, {160,255}, {164,255}, {169,255}, {188,255},
- {255,255},// LA61 does not exit, dummy
- {209,255}, {215,255}, {220,255}
-};
-#elif defined(RGB_BACKLIGHT_HS60) && defined(HS60_HHKB)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA60
- {0,0}, {4,16}, {6,32}, {10,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48},
- {48,0}, {56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48},
- {96,0}, {104,16}, {108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32},
- {148,48}, {144,0}, {152,16}, {156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32},
- {224,0}, {192,0}, {200,16}, {202,48}, {224,48}, {208,0}, {220,16}, {214,32}, {220,64}, {4,64}, {24,64}, {44,64}, {112,64},
- {255,255}, {255,255}, // LA61..LA62 does not exit, dummy
- // LA63..LA64
- {180,64}, {200,64}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA60
- {96,255}, {109,255}, {128,242}, {148,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188},
- {85,255}, {96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131},
- {70,255}, {70,129}, {129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152},
- {53,255}, {39,157}, {255,101}, {222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174}, {32,255},
- {39,255}, {23,238}, {233,242}, {237,255}, {35,255}, {19,255}, {255,233}, {223,255}, {161,255}, {165,255}, {170,255}, {192,255},
- {255,255}, {255,255}, // LA61..LA62 does not exit, dummy
- // LA63..LA64
- {214,255}, {219,255}
-};
-#elif defined(RGB_BACKLIGHT_HS60) //HS60_ISO
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA50
- {0,0}, {4,16}, {6,32}, {2,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48}, {48,0},
- {56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48}, {96,0}, {104,16},
- {108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32}, {148,48}, {144,0}, {152,16},
- {156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32}, {20,48}, {192,0}, {200,16},
- {255,255},// LA51 does not exit, dummy
- // LA52..LA60
- {210,48}, {216,0}, {220,16}, {222,24}, {222,64}, {2,64}, {22,64}, {42,64}, {102,64},
- {255,255},// LA61 does not exit, dummy
- {162,64}, {182,64}, {202,64}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA50
- {96,255}, {109,255}, {128,242}, {147,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188}, {85,255},
- {96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131}, {70,255}, {70,129},
- {129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152}, {53,255}, {39,157}, {255,101},
- {222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174}, {150,246}, {39,255}, {23,238},
- {255,255},// LA51 does not exit, dummy
- // LA52..LA60
- {235,255}, {33,255}, {19,255}, {10,255}, {224,255}, {160,255}, {164,255}, {169,255}, {188,255},
- {255,255},// LA61 does not exit, dummy
- {209,255}, {215,255}, {220,255}
-};
-#elif defined(RGB_BACKLIGHT_NK65) || defined(RGB_BACKLIGHT_KW_MEGA)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA60
- {0,0}, {4,16}, {6,32}, {10,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48},
- {48,0}, {56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48},
- {96,0}, {104,16}, {108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32},
- {148,48}, {144,0}, {152,16}, {156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32},
- {160,64}, {192,0}, {200,16}, {210,48}, {224,48}, {216,0}, {220,16}, {214,32}, {224,64}, {2,64}, {22,64}, {42,64}, {102,64},
- {255,255},// LA61 does not exit, dummy
- //LA62..LB5
- {176,64}, {192,64}, {208,64}, {240,0}, {240,16}, {240,48}, {240,64}, {240,32}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA60
- {96,255}, {109,255}, {128,242}, {148,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188},
- {85,255}, {96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131},
- {70,255}, {70,129}, {129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152},
- {53,255}, {39,157}, {255,101}, {222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174},
- {208,255}, {39,255}, {23,238}, {235,255}, {235,255}, {33,255}, {19,255}, {255,233}, {224,255}, {160,255}, {164,255}, {169,255}, {188,255},
- {255,255},// LA61 does not exit, dummy
- //LA62..LB5
- {221,255}, {225,255}, {229,255}, {22,255}, {12,255}, {244,255}, {234,255}, {255,255}
-};
-#elif defined(RGB_BACKLIGHT_NK87)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- {0,19}, {4,33}, {6,48}, {9,63}, {15,19}, {22,33}, {26,48}, {33,63}, {30,19}, {37,33}, {41,48}, {48,63}, {44,19}, {52,33}, {56,48}, {63,63},
- {59,19}, {67,33}, {70,48}, {78,63}, {74,19}, {81,33}, {85,48}, {93,63}, {89,19}, {96,33}, {100,48}, {107,63}, {104,19}, {111,33}, {115,48},
- {122,63}, {118,19}, {126,33}, {130,48}, {137,63}, {133,19}, {141,33}, {144,48}, {152,63}, {148,19}, {155,33}, {159,48}, {167,63}, {163,19},
- {170,33}, {174,48}, {226,78}, {178,19}, {185,33}, {194,63}, {241,63}, {200,19}, {204,33}, {198,48}, {241,78}, {4,78}, {22,78}, {41,78}, {104,78},
- {255,255}, {167,78}, {185,78}, {204,78}, {0,0}, {255,255}, {255,255}, {255,255}, {19,0}, {255,255}, {255,255}, {255,255}, {33,0}, {255,255},
- {255,255}, {255,78}, {48,0}, {255,255}, {255,255}, {255,255}, {63,0}, {255,255}, {255,255}, {255,255}, {81,0}, {255,255}, {255,255}, {255,255},
- {96,0}, {255,255}, {255,255}, {255,255}, {111,0}, {255,255}, {255,255}, {255,255}, {126,0}, {255,255}, {255,255}, {255,255}, {144,0}, {255,255},
- {255,255}, {255,255}, {159,0}, {255,255}, {255,255}, {255,255}, {174,0}, {255,255}, {255,255}, {255,255}, {189,0}, {255,255}, {226,33}, {226,19},
- {207,0}, {255,255}, {241,33}, {241,19}, {226,0}, {255,255}, {255,33}, {255,19}, {241,0}, {255,255}, {255,255}, {255,0}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- {104,255}, {120,242}, {141,246}, {157,255}, {101,255}, {119,208}, {143,210}, {162,255}, {99,251}, {118,180}, {145,183}, {165,248}, {95,230},
- {116,153}, {148,158}, {169,232}, {91,212}, {113,126}, {152,133}, {173,218}, {87,195}, {109,100}, {158,111}, {178,207}, {81,182}, {102,75},
- {167,92}, {184,200}, {75,172}, {89,55}, {179,79}, {190,196}, {68,167}, {67,45}, {194,75}, {196,197}, {61,166}, {43,52}, {208,82}, {201,201},
- {55,170}, {29,70}, {220,97}, {207,210}, {48,179}, {21,93}, {227,116}, {214,255}, {43,191}, {16,119}, {216,234}, {226,255}, {36,216}, {12,153},
- {235,155}, {216,255}, {166,255}, {169,255}, {172,255}, {186,255}, {255,255}, {201,255}, {206,255}, {210,255}, {91,255}, {255,255}, {255,255},
- {255,255}, {88,255}, {255,255}, {255,255}, {255,255}, {85,255}, {255,255}, {255,255}, {219,255}, {82,255}, {255,255}, {255,255}, {255,255},
- {79,255}, {255,255}, {255,255}, {255,255}, {75,255}, {255,255}, {255,255}, {255,255}, {72,255}, {255,255}, {255,255}, {255,255}, {68,255},
- {255,255}, {255,255}, {255,255}, {64,255}, {255,255}, {255,255}, {255,255}, {60,255}, {255,255}, {255,255}, {255,255}, {56,255}, {255,255},
- {255,255}, {255,255}, {53,255}, {255,255}, {255,255}, {255,255}, {50,255}, {255,255}, {10,194}, {29,251}, {46,255}, {255,255}, {8,222}, {27,255},
- {42,255}, {255,255}, {7,249}, {24,255}, {40,255}, {255,255}, {255,255}, {37,255}
-};
-#elif defined(RGB_BACKLIGHT_NEBULA12)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // A1..A16
- {0,0}, {16,0}, {32,0}, {0,16}, {16,16}, {32,16}, {0,32}, {16,32},
- {255,255}, {255,255}, {255,255}, {255,255},
- {32,48}, {16,48}, {0,48}, {32,32}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // A1..A16
- {72,197}, {64,194}, {56,197}, {85,74}, {64,64}, {43,74}, {171,74}, {192,64},
- {255,255}, {255,255}, {255,255}, {255,255},
- {200,196}, {192,192}, {184,196}, {213,74}
-};
-#elif defined(RGB_BACKLIGHT_NEBULA68)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA60
- {0,0}, {4,16}, {6,31}, {10,47}, {16,0}, {24,16}, {27,31}, {35,47}, {31,0}, {39,16}, {43,31}, {51,47},
- {47,0}, {55,16}, {59,31}, {67,47}, {63,0}, {71,16}, {75,31}, {82,47}, {79,0}, {86,16}, {90,31}, {98,47},
- {94,0}, {102,16}, {106,31}, {114,47}, {110,0}, {118,16}, {122,31}, {130,47}, {126,0}, {133,16}, {137,31},
- {145,47}, {141,0}, {149,16}, {153,31}, {161,47}, {157,0}, {165,16}, {169,31}, {177,47}, {173,0}, {181, 16}, {184,31},
- {159,63}, {188,0}, {196,16}, {206,47}, {220,47}, {212,0}, {216,16}, {210,31}, {220,63}, {2,63}, {22,63}, {41,63}, {100,63},
- {255,255},// LA61 does not exit, dummy
- //LA62..LB5
- {179,63}, {198,63}, {224,63}, {239,0}, {239,16}, {255,16}, {255,63}, {255,0}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA60
- {96,255}, {109,255}, {128,244}, {148,255}, {93,255}, {106,245}, {128,201}, {153,225}, {80,255}, {103,219}, {128,169}, {156,200},
- {87,255}, {99,194}, {128,138}, {161,177}, {83,255}, {94,171}, {128,106}, {167,157}, {79,255}, {87,152}, {128,75}, {174,141}, {74,255},
- {80,138}, {128,43}, {183,131}, {70,255}, {70,129}, {129,12}, {193,128}, {65,255}, {60,128}, {255,20}, {203,133}, {60,255},
- {51,135}, {255,51}, {212,145}, {55,255}, {42,148}, {255,83}, {219,162}, {50,255}, {36,166}, {255,114},
- {202,255}, {46,255}, {30,188}, {228,203}, {231,225}, {40,255}, {25,219}, {255,165}, {217,255}, {160,255}, {164,255}, {168,255}, {183,255},
- {255,255},// LA61 does not exit, dummy
- //LA62..LB5
- {207,255}, {213,255}, {218,255}, {35,255}, {21,255}, {19,255}, {224,255}, {32,255}
-};
-#elif defined(RGB_BACKLIGHT_M6_B)
-// M6-B is really simple:
-// 0 3 5
-// 1 2 4
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- {0,0}, {0,16}, {16,16}, {16,0}, {32,16}, {32,0}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- {160,255}, {96,255}, {77,255}, {179,255}, {51,255}, {205,255}
-};
-#elif defined(RGB_BACKLIGHT_M10_C)
-// M10-C is really simple:
-// 0 1 2
-// 3 4 5
-// 8 7 6
-// 11 10 9
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- {0,0}, {16,0}, {32,0},
- {0,16}, {16,16}, {32,16},
- {32,32}, {16,32}, {0,32},
- {32,48}, {24,48}, {16,48}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- {160,255}, {192,255}, {224,255},
- {128,255}, {0,0}, {0,255},
- {32,255}, {64,255}, {96,255},
- {45,255}, {54,255}, {64,255}
-};
-#elif defined(RGB_BACKLIGHT_DAWN60)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA1..LA16
- {104, 16}, {88 , 16}, {72 , 16}, {56 , 16}, {40 , 16}, {24 , 16}, {4 , 16}, {6 , 32},
- {112, 0}, {96 , 0}, {80 , 0}, {64 , 0}, {48 , 0}, {32 , 0}, {16 , 0}, {0 , 0},
-
- // LB1..LB16
- {128, 0}, {144, 0}, {160, 0}, {176, 0}, {192, 0}, {208, 0}, {224, 0}, {214, 32},
- {120, 16}, {136, 16}, {152, 16}, {168, 16}, {184, 16}, {200, 16}, {220, 16}, {224, 48},
-
- // LC1..LC16
- {100, 48}, {84 , 48}, {68 , 48}, {52 , 48}, {36 , 48}, {102, 64}, {42 , 64}, {22 , 64},
- {108, 32}, {92 , 32}, {76 , 32}, {60 , 32}, {44 , 32}, {28 , 32}, {10 , 48}, {2 , 64},
-
- // LD1..LD16
- {124, 32}, {140, 32}, {156, 32}, {172, 32}, {188, 32}, {180, 48}, {202, 48}, {224, 64},
- {116, 48}, {132, 48}, {148, 48}, {164, 48}, {160, 64}, {176, 64}, {192, 64}, {208, 64},
-
- //RGB UNDERGLOW
- {27 , 3}, {64 , 3}, {100, 3}, {137, 3}, {173, 3}, {209, 3}, {242, 4}, {255, 8}, {255,32}, {255,64},
- {241,64}, {212,64}, {173,64}, {137,64}, {100,64}, {63 ,64}, {28 ,64}, {0 ,64}, {0 ,32}, {0 , 8}, //20
-};
-
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- //LA1..LA16
- {70,129}, {80,139}, {89,157}, {96,181}, {101,208}, {105,238}, {109,255}, {128,247},
- {64,255}, {70,255}, {75,255}, {80,255}, {85,255}, {89,255}, {93,255}, {96,255},
- //LB1..LB16
- {58,255}, {53,255}, {48,255}, {43,255}, {39,255}, {34,255}, {32,255}, {255,233},
- {58,129}, {48,139}, {39,157}, {32,181}, {27,208}, {23,238}, {19,255}, {237,255},
- //LC1..LC16
- {183,131}, {173,143}, {165,163}, {159,188}, {154,216}, {188,255}, {170,255}, {165,255},
- {128,9}, {128,46}, {128,82}, {128,119}, {128,155}, {128,192}, {147,255}, {161,255},
- //LD1..LD16
- {0,27}, {0,64}, {0,101}, {0,137}, {0,174}, {228,201}, {235,255}, {224,255},
- {195,128}, {206,136}, {215,152}, {222,175}, {208,255}, {213,255}, {217, 255}, {222,225},
-
- //UNDERGLOW, {A,D}
- //1 - 10
- {91,255}, {84,255}, {74,255}, {60,255}, {48,255}, {39,255}, {32,255}, {27,255}, {0,255}, {236,255},
- //11 - 20
- {234,255}, {222,255}, {213,255}, {197,255}, {180,255}, {167,255}, {152,255}, {147,255}, {128,255}, {101,255}
-};
-#elif defined(RGB_BACKLIGHT_M50_A)
-const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {255,255}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {255,255}, {255,255},
- {104,0}, {88,0}, {72,0}, {56,0}, {40,0}, {24,0}, {0,0}, {0,16}, {255,255},
- // LB0..LB17
- {255,255}, {120,0}, {136,0}, {152,0}, {168,0}, {184,0}, {200,0}, {255,255}, {255,255},
- {120,16}, {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {255,255}, {255,255}, {255,255},
- // LC0..LC17
- {255,255}, {112,48}, {88,48}, {72,48}, {56,48}, {40,48}, {24,48}, {0,48}, {255,255},
- {104,32}, {88,32}, {72,32}, {56,32}, {40,32}, {24,32}, {0,32}, {255,255}, {255,255},
- // LD0..LD17
- {255,255}, {120,32}, {136,32}, {152,32}, {168,32}, {184,32}, {200,32}, {255,255}, {255,255},
- {255,255}, {136,48}, {152,48}, {168,48}, {184,48}, {200,48}, {255,255}, {255,255}, {255,255}
-};
-const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
- // LA0..LA17
- {255,255}, {73,88}, {89,104}, {99,130}, {105,162}, {110,197}, {113,233}, {255,255}, {255,255},
- {67,255}, {73,255}, {79,255}, {84,255}, {89,255}, {93,255}, {98,255}, {116,255}, {255,255},
- // LB0..LB17
- {0,0}, {61,255}, {55,255}, {49,255}, {44,255}, {39,255}, {35,255}, {255,255}, {255,255},
- {55,88}, {39,104}, {29,130}, {23,162}, {18,197}, {15,233}, {255,255}, {255,255}, {255,255},
- // LC0..LC17
- {255,255}, {192,255}, {183,255}, {177,255}, {172,255}, {167,255}, {163,255}, {158,255}, {255,255},
- {183,88}, {167,104}, {157,130}, {151,162}, {146,197}, {143,233}, {140,255}, {255,255}, {255,255},
- // LD0..LD17
- {255,255}, {201,88}, {217,104}, {227,130}, {233,162}, {238,197}, {241,233}, {255,255}, {255,255},
- {255,255}, {201,255}, {207,255}, {212,255}, {217,255}, {221,255}, {255,255}, {255,255}, {255,255}
-};
-#endif
-
-// This may seem counter-intuitive, but it's quite flexible.
-// For each LED, get it's position to decide what color to make it.
-// This solves the issue of LEDs (and switches) not aligning to a grid,
-// or having a large "bitmap" and sampling them.
-void map_led_to_point( uint8_t index, Point *point )
-{
- // Slightly messy way to get Point structs out of progmem.
- uint8_t *addr = (uint8_t*)&g_map_led_to_point[index];
- point->x = pgm_read_byte(addr);
- point->y = pgm_read_byte(addr+1);
-
-#if defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_M10_C) || defined(RGB_BACKLIGHT_HS60) || defined(RGB_BACKLIGHT_NK65) || \
- defined(RGB_BACKLIGHT_NK87) || defined(RGB_BACKLIGHT_NEBULA68) || defined(RGB_BACKLIGHT_NEBULA12) || defined(RGB_BACKLIGHT_KW_MEGA)
- return;
-#endif
-
- switch (index)
- {
-#if !defined(RGB_BACKLIGHT_DAWN60)
- case 18+4: // LB4A
- if ( g_config.use_split_backspace )
- point->x -= 8;
- break;
-#endif
-#if defined(RGB_BACKLIGHT_ZEAL60)
- case 18+14: // LB14A
- if ( g_config.use_iso_enter )
- point->y += 8; // extremely pedantic
- break;
- case 54+5: // LD5A
- if ( !g_config.use_iso_enter )
- point->x -= 10;
- break;
- case 36+16: // LC16A
- if ( !g_config.use_split_left_shift )
- point->x += 8;
- break;
-#endif
-#if defined(RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_M60_A)
- case 36+0: // LC0A
- if ( g_config.use_7u_spacebar )
- point->x += 10;
- break;
- case 36+6: // LC6A
- if ( g_config.use_7u_spacebar )
- point->x += 4;
- break;
- case 54+7: // LD7A
- if ( !g_config.use_split_right_shift )
- point->x -= 8;
- break;
-#endif
-#if defined(RGB_BACKLIGHT_DAWN60)
- case 15+6: // LB6A
- if ( !g_config.use_split_backspace )
- point->x += 8;
- break;
- case 31+6: // LC6A
- if ( g_config.use_7u_spacebar )
- point->x = 112;
- break;
- case 47+16: // LD16A
- if ( g_config.use_7u_spacebar )
- point->x -= 8;
- break;
- case 47+6: // LD6A
- if ( g_config.use_split_right_shift )
- point->x += 6;
- break;
- case 47+7: // LD7A
- if ( g_config.use_split_right_shift )
- point->x += 6;
- break;
-#endif
- }
-}
-
-void map_led_to_point_polar( uint8_t index, Point *point )
-{
- // Slightly messy way to get Point structs out of progmem.
- uint8_t *addr = (uint8_t*)&g_map_led_to_point_polar[index];
- point->x = pgm_read_byte(addr);
- point->y = pgm_read_byte(addr+1);
-}
-
-//
-// Maps switch matrix coordinate (row,col) to LED index
-//
-
-
-#if defined(RGB_BACKLIGHT_ZEAL65)
-// Note: Left spacebar stab is at 4,2 (LC7)
-// Right spacebar stab is at 4,9 (D14)
-//
-// A17, A16, A15, A14, A13, A12, A11, A10, A9, B0, B1, B2, B3, B4, B6
-// A7, A6, A5, A4, A3, A2, A1, A0, B9, B10, B11, B12, B13, B14, B7
-// A8, C14, C13, C12, C11, C10, C9, D0, D1, D2, D3, D4, D5, B5, B8
-// C16, C15, C5, C4, C3, C2, C1, D9, D10, D11, D12, D6, D7, D8, B15
-// C17, C8, C7, ---, ---, ---, ---, C0, ---, D14, D15, D16, D17, B17, B16
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 0+17, 0+16, 0+15, 0+14, 0+13, 0+12, 0+11, 0+10, 0+9, 18+0, 18+1, 18+2, 18+3, 18+4, 18+6 },
- { 0+7, 0+6, 0+5, 0+4, 0+3, 0+2, 0+1, 0+0, 18+9, 18+10, 18+11, 18+12, 18+13, 18+14, 18+7 },
- { 0+8, 36+14, 36+13, 36+12, 36+11, 36+10, 36+9, 54+0, 54+1, 54+2, 54+3, 54+4, 54+5, 18+5, 18+8 },
- { 36+16, 36+15, 36+5, 36+4, 36+3, 36+2, 36+1, 54+9, 54+10, 54+11, 54+12, 54+6, 54+7, 54+8, 18+15 },
- { 36+17, 36+8, 36+7, 255, 255, 255, 255, 36+0, 255, 54+14, 54+15, 54+16, 54+17, 18+17, 18+16 }
-};
-#elif defined(RGB_BACKLIGHT_KOYU)
-// Note: Left spacebar stab is at 4,4 (LC6)
-// Right spacebar stab is at 4,10 (D14)
-//
-// A17, A16, A15, A14, A13, A12, A11, A10, A9, B0, B1, B2, B3, B4, B6
-// A7, A6, A5, A4, A3, A2, A1, A0, B9, B10, B11, B12, B13, B14, B7
-// A8, C14, C13, C12, C11, C10, C9, D0, D1, D2, D3, D4, D5, B5, B8
-// C16, C15, C5, C4, C3, C2, C1, D9, D10, D11, D12, D6, D7, D8, B15
-// C17, C8, C7, C6, ---, ---, ---, C0, ---, ---, D14, D15, D16, B17, B16
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 0+17, 0+16, 0+15, 0+14, 0+13, 0+12, 0+11, 0+10, 0+9, 18+0, 18+1, 18+2, 18+3, 18+4, 18+6 },
- { 0+7, 0+6, 0+5, 0+4, 0+3, 0+2, 0+1, 0+0, 18+9, 18+10, 18+11, 18+12, 18+13, 18+14, 18+7 },
- { 0+8, 36+14, 36+13, 36+12, 36+11, 36+10, 36+9, 54+0, 54+1, 54+2, 54+3, 54+4, 54+5, 18+5, 18+8 },
- { 36+16, 36+15, 36+5, 36+4, 36+3, 36+2, 36+1, 54+9, 54+10, 54+11, 54+12, 54+6, 54+7, 54+8, 18+15 },
- { 36+17, 36+8, 36+7, 36+6, 255, 255, 255, 36+0, 255, 255, 54+14, 54+15, 54+16, 18+17, 18+16 }
-};
-#elif defined(RGB_BACKLIGHT_M65_B) || defined(RGB_BACKLIGHT_M65_BX)
-// Note: Left spacebar stab is at 4,4 (LC6)
-// Right spacebar stab is at 4,10 (D14)
-// (B6)
-// A17, A16, A15, A14, A13, A12, A11, A10, A9, B0, B1, B2, B3, B4, B7
-// A7, A6, A5, A4, A3, A2, A1, A0, B9, B10, B11, B12, B13, B14, B8
-// A8, C14, C13, C12, C11, C10, C9, D0, D1, D2, D3, D4, D5, B5, B15
-// C16, C15, C5, C4, C3, C2, C1, D9, D10, D11, D12, D6, D7, D8, B16
-// C17, C8, C7, C6, ---, ---, ---, C0, ---, ---, D14, D15, D16, D17, B17
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 0+17, 0+16, 0+15, 0+14, 0+13, 0+12, 0+11, 0+10, 0+9, 18+0, 18+1, 18+2, 18+3, 18+4, 18+7 },
- { 0+7, 0+6, 0+5, 0+4, 0+3, 0+2, 0+1, 0+0, 18+9, 18+10, 18+11, 18+12, 18+13, 18+14, 18+8 },
- { 0+8, 36+14, 36+13, 36+12, 36+11, 36+10, 36+9, 54+0, 54+1, 54+2, 54+3, 54+4, 54+5, 18+5, 18+15 },
- { 36+16, 36+15, 36+5, 36+4, 36+3, 36+2, 36+1, 54+9, 54+10, 54+11, 54+12, 54+6, 54+7, 54+8, 18+16 },
- { 36+17, 36+8, 36+7, 36+6, 255, 255, 255, 36+0, 255, 255, 54+14, 54+15, 54+16, 54+17, 18+17 }
-};
-#elif defined(RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_M60_A)
-// Note: Left spacebar stab is at 4,3 (LC6)
-// Right spacebar stab is at 4,9 (LD13) or 4,10 (LD14)
-//
-// A17, A16, A15, A14, A13, A12, A11, A10, A9, B0, B1, B2, B3, B4,
-// A7, A6, A5, A4, A3, A2, A1, A0, B9, B10, B11, B12, B13, B14,
-// A8, C14, C13, C12, C11, C10, C9, D0, D1, D2, D3, D4, D5, B5,
-// C16, C15, C5, C4, C3, C2, C1, D9, D10, D11, D12, D6, D7, D8,
-// C17, C8, C7, C6, ---, ---, ---, C0, ---, D13, D14, D15, D16, D17,
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 0+17, 0+16, 0+15, 0+14, 0+13, 0+12, 0+11, 0+10, 0+9, 18+0, 18+1, 18+2, 18+3, 18+4 },
- { 0+7, 0+6, 0+5, 0+4, 0+3, 0+2, 0+1, 0+0, 18+9, 18+10, 18+11, 18+12, 18+13, 18+14 },
- { 0+8, 36+14, 36+13, 36+12, 36+11, 36+10, 36+9, 54+0, 54+1, 54+2, 54+3, 54+4, 54+5, 18+5 },
- { 36+16, 36+15, 36+5, 36+4, 36+3, 36+2, 36+1, 54+9, 54+10, 54+11, 54+12, 54+6, 54+7, 54+8 },
- { 36+17, 36+8, 36+7, 36+6, 255, 255, 255, 36+0, 255, 54+13, 54+14, 54+15, 54+16, 54+17 }
-};
-#elif defined(RGB_BACKLIGHT_WT60_B) || defined(RGB_BACKLIGHT_WT60_BX) || defined(RGB_BACKLIGHT_WT60_C)
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 0+17, 0+16, 0+15, 0+14, 0+13, 0+12, 0+11, 0+10, 0+9, 18+0, 18+1, 18+2, 18+3, 18+4 },
- { 0+7, 0+6, 0+5, 0+4, 0+3, 0+2, 0+1, 0+0, 18+9, 18+10, 18+11, 18+12, 18+13, 18+14 },
- { 0+8, 36+14, 36+13, 36+12, 36+11, 36+10, 36+9, 54+0, 54+1, 54+2, 54+3, 54+4, 54+5, 18+5 },
- { 36+16, 255, 36+5, 36+4, 36+3, 36+2, 36+1, 54+9, 54+10, 54+11, 54+12, 54+6, 54+7, 54+8 },
- { 36+17, 36+8, 36+7, 36+6, 255, 255, 255, 36+0, 255, 255, 54+14, 54+15, 54+16, 54+17 }
-};
-#elif defined(RGB_BACKLIGHT_U80_A)
-// Note: Left spacebar stab is at 5,3 (LC6)
-// Right spacebar stab is at 5,10 (LD14)
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 72+17, 72+16, 72+15, 72+14, 72+9, 72+10, 72+11, 72+12, 72+13, 90+0, 90+1, 90+2, 90+3, 255, 90+4, 90+5, 90+6 },
- { 0+17, 0+16, 0+15, 0+14, 0+13, 0+12, 0+11, 0+10, 0+9, 18+0, 18+1, 18+2, 18+3, 18+4, 90+11, 90+9, 90+7 },
- { 0+7, 0+6, 0+5, 0+4, 0+3, 0+2, 0+1, 0+0, 18+9, 18+10, 18+11, 18+12, 18+13, 18+14, 90+12, 90+10, 90+8 },
- { 0+8, 36+14, 36+13, 36+12, 36+11, 36+10, 36+9, 54+0, 54+1, 54+2, 54+3, 54+4, 54+5, 255, 255, 255, 255 },
- { 36+16, 255, 36+5, 36+4, 36+3, 36+2, 36+1, 54+9, 54+10, 54+11, 54+12, 54+6, 54+7, 255, 255, 90+14, 255 },
- { 36+17, 36+8, 36+7, 36+6, 255, 255, 255, 36+0, 255, 255, 54+14, 54+15, 54+16, 54+17, 90+15, 90+16, 90+17 }
-};
-#elif defined(RGB_BACKLIGHT_HS60) && defined(HS60_ANSI)
-//
-// LA1, LA5, LA9, LA13, LA17, LA21, LA25, LA29, LA33, LA37, LA41, LA45, LA49, LA53,
-// LA2, LA6, LA10, LA14, LA18, LA22, LA26, LA30, LA34, LA38, LA42, LA46, LA50, ---,
-// LA3, LA7, LA11, LA15, LA19, LA23, LA27, LA31, LA35, LA39, LA43, LA47, LA54, LA55,
-// LA4, ---, LA8, LA12, LA16, LA20, LA24, LA28, LA32, LA36, LA40, LA44, ---, LA52,
-// LA57, LA58, LA59, ---, ---, ---, LA60, ---, ---, ---, LA62, LA63, LA64, LA56
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 1-1, 5-1, 9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1 },
- { 2-1, 6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1, 255 },
- { 3-1, 7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1 },
- { 4-1, 255, 8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1, 255, 52-1 },
- { 57-1, 58-1, 59-1, 255, 255, 255, 60-1, 255, 255, 255, 62-1, 63-1, 64-1, 56-1 }
-};
-#elif defined(RGB_BACKLIGHT_HS60) && defined(HS60_HHKB)
-//
-// LA1, LA5, LA9, LA13, LA17, LA21, LA25, LA29, LA33, LA37, LA41, LA45, LA49, LA53,
-// LA2, LA6, LA10, LA14, LA18, LA22, LA26, LA30, LA34, LA38, LA42, LA46, LA50, LA48,
-// LA3, LA7, LA11, LA15, LA19, LA23, LA27, LA31, LA35, LA39, LA43, LA47, LA54, LA55,
-// LA4, ---, LA8, LA12, LA16, LA20, LA24, LA28, LA32, LA36, LA40, LA44, LA51, LA52,
-// LA57, LA58, LA59, ---, ---, ---, LA60, ---, ---, ---, ---, LA63, LA64, LA56
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 1-1, 5-1, 9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1 },
- { 2-1, 6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1, 48-1 },
- { 3-1, 7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1 },
- { 4-1, 255, 8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1, 51-1, 52-1 },
- { 57-1, 58-1, 59-1, 255, 255, 255, 60-1, 255, 255, 255, 255, 63-1, 64-1, 56-1 }
-};
-#elif defined(RGB_BACKLIGHT_HS60) //HS60_ISO
-//
-// LA1, LA5, LA9, LA13, LA17, LA21, LA25, LA29, LA33, LA37, LA41, LA45, LA49, LA53,
-// LA2, LA6, LA10, LA14, LA18, LA22, LA26, LA30, LA34, LA38, LA42, LA46, LA50, ---,
-// LA3, LA7, LA11, LA15, LA19, LA23, LA27, LA31, LA35, LA39, LA43, LA47, LA54, LA55,
-// LA4, LA48, LA8, LA12, LA16, LA20, LA24, LA28, LA32, LA36, LA40, LA44, ---, LA52,
-// LA57, LA58, LA59, ---, ---, ---, LA60, ---, ---, ---, LA62, LA63, LA64, LA56
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 1-1, 5-1, 9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1 },
- { 2-1, 6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1, 255 },
- { 3-1, 7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1 },
- { 4-1, 48-1, 8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1, 255, 52-1 },
- { 57-1, 58-1, 59-1, 255, 255, 255, 60-1, 255, 255, 255, 62-1, 63-1, 64-1, 56-1 }
-};
-#elif defined(RGB_BACKLIGHT_NK65) || defined(RGB_BACKLIGHT_NEBULA68) || defined(RGB_BACKLIGHT_KW_MEGA)
-//
-// LA1, LA5, LA9, LA13, LA17, LA21, LA25, LA29, LA33, LA37, LA41, LA45, LA49, LA53, LB1,
-// LA2, LA6, LA10, LA14, LA18, LA22, LA26, LA30, LA34, LA38, LA42, LA46, LA50, ---, LB2,
-// LA3, LA7, LA11, LA15, LA19, LA23, LA27, LA31, LA35, LA39, LA43, LA47, LA54, LA55, LB5,
-// LA4, ---, LA8, LA12, LA16, LA20, LA24, LA28, LA32, LA36, LA40, LA44, LA51, LA52, LB3,
-// LA57, LA58, LA59, ---, ---, ---, LA60, ---, ---, LA48, LA62, LA63, LA64, LA56, LB4
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 1-1, 5-1, 9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1, 1+64-1 },
- { 2-1, 6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1, 255, 2+64-1 },
- { 3-1, 7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1, 5+64-1 },
- { 4-1, 255, 8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1, 51-1, 52-1, 3+64-1 },
- { 57-1, 58-1, 59-1, 255, 255, 255, 60-1, 255, 255, 48-1, 62-1, 63-1, 64-1, 56-1, 4+64-1 }
-};
-#elif defined(RGB_BACKLIGHT_NK87)
-//
-// LB1, LB5, LB9, LB13, LB17, LB21, LB25, LB29, LB33, LB37, LB41, LB45, LB49, LB53, LB57, LB61, LB64,
-// LA1, LA5, LA9, LA13, LA17, LA21, LA25, LA29, LA33, LA37, LA41, LA45, LA49, LA53, LB52, LB56, LB60,
-// LA2, LA6, LA10, LA14, LA18, LA22, LA26, LA30, LA34, LA38, LA42, LA46, LA50, ---, LB51, LB55, LB59,
-// LA3, LA7, LA11, LA15, LA19, LA23, LA27, LA31, LA35, LA39, LA43, LA47, LA54, LA55, ---, ---, ---,
-// LA4, ---, LA8, LA12, LA16, LA20, LA24, LA28, LA32, LA36, LA40, LA44, LA51, ---, ---, LA52, ---,
-// LA57, LA58, LA59, ---, ---, ---, LA60, ---, ---, ---, ---, LA62, LA63, LA64, LA48, LA56, LB12
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 1+64-1, 5+64-1, 9+64-1, 13+64-1, 17+64-1, 21+64-1, 25+64-1, 29+64-1, 33+64-1, 37+64-1, 41+64-1, 45+64-1, 49+64-1, 53+64-1, 57+64-1, 61+64-1, 64+64-1 },
- { 1-1, 5-1, 9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1, 52+64-1, 56+64-1, 60+64-1 },
- { 2-1, 6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1, 255, 51+64-1, 55+64-1, 59+64-1 },
- { 3-1, 7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1, 255, 255, 255 },
- { 4-1, 255, 8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1, 51-1, 255, 255, 52-1, 255 },
- { 57-1, 58-1, 59-1, 255, 255, 255, 60-1, 255, 255, 255, 255, 62-1, 63-1, 64-1, 48-1, 56-1, 12+64-1 }
-};
-#elif defined(RGB_BACKLIGHT_NEBULA12)
-//
-// A1, A2, A3,
-// A4, A5, A6,
-// A7, A8, A16,
-// A15, A14, A13,
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 1-1, 2-1, 3-1 },
- { 4-1, 5-1, 6-1 },
- { 7-1, 8-1, 16-1 },
- { 15-1, 14-1, 13-1 }
-};
-#elif defined(RGB_BACKLIGHT_M6_B)
-// M6-B is really simple:
-// 0 3 5
-// 1 2 4
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 0, 3, 5, 1, 2, 4 }
-};
-#elif defined(RGB_BACKLIGHT_M10_C)
-// M10-C is really simple:
-// 0 1 2
-// 3 4 5
-// 8 7 6
-// 11 10 9
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 0, 1, 2, 3, 4, 5, 8, 7, 6, 10 }
-};
-#elif defined(RGB_BACKLIGHT_DAWN60)
-//Dawn60
-// A16, A15, A14, A13, A12, A11, A10, A9, B1, B2, B3, B4, B5, B6,
-// A7, A6, A5, A4, A3, A2, A1, B9, B10, B11, B12, B13, B14, B15,
-// A8, C14, C13, C12, C11, C10, C9, D1, D2, D3, D4, D5, B8, B7,
-// C15, C5, C4, C3, C2, C1, D9, D10, D11, D12, ---, D6, D7, B16,
-// C16, C8, C7, ---, ---, C6, ---, ---, ---, D13, D14, D15, D16, D8,
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { -1+16, -1+15, -1+14, -1+13, -1+12, -1+11, -1+10, -1+9 , 15+1 , 15+2 , 15+3 , 15+4 , 15+5 , 15+6 },
- { -1+7 , -1+6 , -1+5 , -1+4 , -1+3 , -1+2 , -1 +1, 15+9 , 15+10, 15+11, 15+12, 15+13, 15+14, 15+15},
- { -1+8 , 31+14, 31+13, 31+12, 31+11, 31+10, 31+9 , 47+1 , 47+2 , 47+3 , 47+4 , 47+5 , 15+8 , 15+7 },
- { 31+15, 31+5 , 31+4 , 31+3 , 31+2 , 31+1 , 47+9 , 47+10, 47+11, 47+12, 255 ,47+6 , 47+7 , 15+16},
- { 31+16, 31+8 , 31+7 , 255 , 255 , 31+6 , 255 , 255 , 255 , 47+13, 47+14, 47+15, 47+16, 47+8 }
-};
-#elif defined(RGB_BACKLIGHT_M50_A)
-// LA15, LA14, LA13, LA12, LA11, LA10, LA9, LB1, LB2, LB3, LB4, LB5, LB6
-// LA16, LA6, LA5, LA4, LA3, LA2, LA1, LB9, LB10, LB11, LB12, LB13, LB14
-// LC15, LC14, LC13, LC12, LC11, LC10, LC9, LD1, LD2, LD3, LD4, LD5, LD6
-// LC7, LC6, LC5, LC4, LC3, LC2, LC1, ----, LD10, LD11, LD12, LD13, LD14
-const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
- { 0+15, 0+14, 0+13, 0+12, 0+11, 0+10, 0+9, 18+1, 18+2, 18+3, 18+4, 18+5, 18+6 },
- { 0+16, 0+6, 0+5, 0+4, 0+3, 0+2, 0+1, 18+9, 18+10, 18+11, 18+12, 18+13, 18+14 },
- { 36+15, 36+14, 36+13, 36+12, 36+11, 36+10, 36+9, 54+1, 54+2, 54+3, 54+4, 54+5, 54+6 },
- { 36+7, 36+6, 36+5, 36+4, 36+3, 36+2, 36+1, 255, 54+10, 54+11, 54+12, 54+13, 54+14 },
-};
-#endif
-
-void map_row_column_to_led( uint8_t row, uint8_t column, uint8_t *led )
-{
- *led = 255;
- if ( row < MATRIX_ROWS && column < MATRIX_COLS )
- {
- *led = pgm_read_byte(&g_map_row_column_to_led[row][column]);
- }
-}
-
-void backlight_update_pwm_buffers(void)
-{
-#if defined(RGB_BACKLIGHT_M6_B)
- IS31FL3218_update_pwm_buffers();
-#elif defined(RGB_BACKLIGHT_M10_C)
- IS31FL3731_update_pwm_buffers( ISSI_ADDR_1, 0 );
- IS31FL3731_update_led_control_registers( ISSI_ADDR_1, 0 );
-#elif defined(RGB_BACKLIGHT_HS60)
- IS31FL3733_update_pwm_buffers( ISSI_ADDR_1, 0 );
- IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
-#elif defined(RGB_BACKLIGHT_NK65) || defined(RGB_BACKLIGHT_NEBULA68) || defined(RGB_BACKLIGHT_NK87) || defined(RGB_BACKLIGHT_KW_MEGA)
- IS31FL3733_update_pwm_buffers( ISSI_ADDR_1, 0 );
- IS31FL3733_update_pwm_buffers( ISSI_ADDR_2, 1 );
- IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
- IS31FL3733_update_led_control_registers( ISSI_ADDR_2, 1 );
-#elif defined(RGB_BACKLIGHT_NEBULA12)
- IS31FL3731_update_pwm_buffers( ISSI_ADDR_1, 0 );
- IS31FL3731_update_led_control_registers( ISSI_ADDR_1, 0 );
-#elif defined(RGB_BACKLIGHT_U80_A)
- static uint8_t driver = 0;
- switch ( driver )
- {
- case 0:
- IS31FL3731_update_pwm_buffers( ISSI_ADDR_1, 0 );
- break;
- case 1:
- IS31FL3731_update_pwm_buffers( ISSI_ADDR_2, 1 );
- break;
- case 2:
- IS31FL3731_update_pwm_buffers( ISSI_ADDR_3, 2 );
- break;
- }
- if ( ++driver > 2 )
- {
- driver = 0;
- }
-#else
- IS31FL3731_update_pwm_buffers( ISSI_ADDR_1, 0 );
- IS31FL3731_update_pwm_buffers( ISSI_ADDR_2, 1 );
- IS31FL3731_update_led_control_registers( ISSI_ADDR_1, 0 );
- IS31FL3731_update_led_control_registers( ISSI_ADDR_2, 1 );
-#endif
-}
-
-void backlight_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
-{
-#if defined(RGB_BACKLIGHT_M6_B)
- IS31FL3218_set_color( index, red, green, blue );
-#elif defined(RGB_BACKLIGHT_HS60) || defined(RGB_BACKLIGHT_NK65) || defined(RGB_BACKLIGHT_NEBULA68) || defined(RGB_BACKLIGHT_KW_MEGA)
- IS31FL3733_set_color( index, red, green, blue );
-#elif defined(RGB_BACKLIGHT_NK87)
- // This is done to avoid indicator LEDs being set
- if (( index != 63+64-1 ) && ( index != 48+64-1 )) {
- IS31FL3733_set_color( index, red, green, blue );
- }
-#elif defined(RGB_BACKLIGHT_DAWN60)
- if( index < DRIVER_LED_TOTAL ) {
- IS31FL3731_set_color( index, red, green, blue );
- } else {
- g_ws2812_leds[index - DRIVER_LED_TOTAL].r = red;
- g_ws2812_leds[index - DRIVER_LED_TOTAL].g = green;
- g_ws2812_leds[index - DRIVER_LED_TOTAL].b = blue;
- ws2812_setleds(g_ws2812_leds, WS2812_LED_TOTAL);
- }
-#else
- IS31FL3731_set_color( index, red, green, blue );
-#endif
-}
-
-void backlight_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
-{
-#if defined(RGB_BACKLIGHT_M6_B)
- IS31FL3218_set_color_all( red, green, blue );
-#elif defined(RGB_BACKLIGHT_HS60) || defined(RGB_BACKLIGHT_NK65) || defined(RGB_BACKLIGHT_NEBULA68) || defined(RGB_BACKLIGHT_KW_MEGA)
- // This is done to avoid indicator LEDs being set
- for (int i = 0; i < BACKLIGHT_LED_COUNT; i++) {
- IS31FL3733_set_color(i, red, green, blue);
- }
-#elif defined(RGB_BACKLIGHT_NK87)
- // This is done to avoid indicator LEDs being set
- for (int i = 0; i < BACKLIGHT_LED_COUNT; i++) {
- if (( i != 63+64-1 ) && ( i != 48+64-1 )) {
- IS31FL3733_set_color(i, red, green, blue);
- }
- }
-#elif defined(RGB_BACKLIGHT_DAWN60)
- IS31FL3731_set_color_all( red, green, blue );
- for (uint8_t i = 0; i < WS2812_LED_TOTAL; i++) {
- g_ws2812_leds[i].r = red;
- g_ws2812_leds[i].g = green;
- g_ws2812_leds[i].b = blue;
- }
- ws2812_setleds(g_ws2812_leds, WS2812_LED_TOTAL);
-#else
- IS31FL3731_set_color_all( red, green, blue );
-#endif
-}
-
-void backlight_set_key_hit(uint8_t row, uint8_t column)
-{
- uint8_t led;
- map_row_column_to_led(row,column,&led);
- g_key_hit[led] = 0;
-
- g_any_key_hit = 0;
-}
-
-#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65) && !defined(RGB_BACKLIGHT_NEBULA68) && !defined(RGB_BACKLIGHT_NEBULA12) && !defined(RGB_BACKLIGHT_NK87) && !defined(RGB_BACKLIGHT_KW_MEGA)
-// This is (F_CPU/1024) / 20 Hz
-// = 15625 Hz / 20 Hz
-// = 781
-#define TIMER3_TOP 781
-
-void backlight_timer_init(void)
-{
- static uint8_t backlight_timer_is_init = 0;
- if ( backlight_timer_is_init )
- {
- return;
- }
- backlight_timer_is_init = 1;
-
- // Timer 3 setup
- TCCR3B = _BV(WGM32) | // CTC mode OCR3A as TOP
- _BV(CS32) | _BV(CS30); // prescale by /1024
- // Set TOP value
- uint8_t sreg = SREG;
- cli();
-
- OCR3AH = (TIMER3_TOP >> 8) & 0xff;
- OCR3AL = TIMER3_TOP & 0xff;
- SREG = sreg;
-}
-
-void backlight_timer_enable(void)
-{
- TIMSK3 |= _BV(OCIE3A);
-}
-
-void backlight_timer_disable(void)
-{
- TIMSK3 &= ~_BV(OCIE3A);
-}
-#elif defined(RGB_BACKLIGHT_NEBULA12) //STM32, use GPT with TIM3. Enable in halconf.h
-static void gpt_backlight_timer_task(GPTDriver *gptp);
-// Timer setup at 200Khz, callback at 10k ticks = 20Hz
-static GPTConfig gpt3cfg1 = {
- .frequency = 200000U,
- .callback = gpt_backlight_timer_task
-};
-
-void backlight_timer_init(void)
-{
- gptStart(&GPTD3, &gpt3cfg1);
-}
-
-void backlight_timer_enable(void)
-{
- gptStartContinuous(&GPTD3, 10000);
-}
-
-void backlight_timer_disable(void)
-{
- gptStopTimer(&GPTD3);
-}
-#else //STM32, use GPT with TIM4. Enable in halconf.h
-static void gpt_backlight_timer_task(GPTDriver *gptp);
-// Timer setup at 200Khz, callback at 10k ticks = 20Hz
-static GPTConfig gpt4cfg1 = {
- .frequency = 200000U,
- .callback = gpt_backlight_timer_task
-};
-
-void backlight_timer_init(void)
-{
- gptStart(&GPTD4, &gpt4cfg1);
-}
-
-void backlight_timer_enable(void)
-{
- gptStartContinuous(&GPTD4, 10000);
-}
-
-void backlight_timer_disable(void)
-{
- gptStopTimer(&GPTD4);
-}
-#endif //!defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65) && !defined(RGB_BACKLIGHT_NEBULA68) && !defined(RGB_BACKLIGHT_NEBULA12) && !defined(RGB_BACKLIGHT_NK87) && !defined(RGB_BACKLIGHT_KW_MEGA)
-
-void backlight_set_suspend_state(bool state)
-{
- g_suspend_state = state;
-}
-
-void backlight_set_indicator_state(uint8_t state)
-{
- g_indicator_state = state;
-}
-
-void backlight_effect_rgb_test(void)
-{
- // Mask out bits 4 and 5
- // This 2-bit value will stay the same for 16 ticks.
- switch ( (g_tick & 0x30) >> 4 )
- {
- case 0:
- {
- backlight_set_color_all( 255, 0, 0 );
- break;
- }
- case 1:
- {
- backlight_set_color_all( 0, 255, 0 );
- break;
- }
- case 2:
- {
- backlight_set_color_all( 0, 0, 255 );
- break;
- }
- case 3:
- {
- backlight_set_color_all( 255, 255, 255 );
- break;
- }
- }
-}
-
-#if defined(RGB_DEBUGGING_ONLY)
-// This tests the LEDs
-// Note that it will change the LED control registers
-// in the LED drivers, and leave them in an invalid
-// state for other backlight effects.
-// ONLY USE THIS FOR TESTING LEDS!
-void backlight_effect_single_LED_test(void)
-{
- static uint8_t color = 0; // 0,1,2 for R,G,B
- static uint8_t row = 0;
- static uint8_t column = 0;
-
- static uint8_t tick = 0;
- tick++;
-
- if ( tick > 2 )
- {
- tick = 0;
- column++;
- }
- if ( column > 14 )
- {
- column = 0;
- row++;
- }
- if ( row > 4 )
- {
- row = 0;
- color++;
- }
- if ( color > 2 )
- {
- color = 0;
- }
-
- uint8_t led;
- map_row_column_to_led( row, column, &led );
- backlight_set_color_all( 255, 255, 255 );
- backlight_test_led( led, color==0, color==1, color==2 );
-}
-#endif // defined(RGB_DEBUGGING_ONLY)
-
-// All LEDs off
-void backlight_effect_all_off(void)
-{
- backlight_set_color_all( 0, 0, 0 );
-}
-
-// Solid color
-void backlight_effect_solid_color(void)
-{
- HSV hsv = { .h = g_config.color_1.h, .s = g_config.color_1.s, .v = g_config.brightness };
- RGB rgb = hsv_to_rgb( hsv );
- backlight_set_color_all( rgb.r, rgb.g, rgb.b );
-}
-
-// alphas = color1, mods = color2
-void backlight_effect_alphas_mods(void)
-{
- RGB rgb1 = hsv_to_rgb( (HSV){ .h = g_config.color_1.h, .s = g_config.color_1.s, .v = g_config.brightness } );
- RGB rgb2 = hsv_to_rgb( (HSV){ .h = g_config.color_2.h, .s = g_config.color_2.s, .v = g_config.brightness } );
- bool is_alpha = false;
- for ( int row = 0; row < MATRIX_ROWS; row++ )
- {
- for ( int column = 0; column < MATRIX_COLS; column++ )
- {
- uint8_t index;
- map_row_column_to_led( row, column, &index );
- if ( index < BACKLIGHT_LED_COUNT )
- {
-#if defined(RGB_BACKLIGHT_U80_A)
- if ( row == 0 )
- {
- is_alpha = ( column < 16 ) && (( 0b1110000111100001 & (1<<column) ) == 0);
- }
- else
- {
- is_alpha = ( column < 16 ) && (( g_config.alphas_mods[row-1] & (1<<column) ) == 0);
- }
-#elif defined(RGB_BACKLIGHT_NK87)
- if ( row == 0 )
- {
- is_alpha = ( ( 0b11100000111100001 & (1<<column) ) == 0);
- }
- else
- {
- is_alpha = ( column < 16 ) && (( g_config.alphas_mods[row-1] & (1<<column) ) == 0);
- }
-#else
- is_alpha = ( g_config.alphas_mods[row] & (1<<column) ) == 0;
-#endif
- if ( is_alpha )
- {
- backlight_set_color( index, rgb1.r, rgb1.g, rgb1.b );
- }
- else
- {
- backlight_set_color( index, rgb2.r, rgb2.g, rgb2.b );
- }
- }
- }
- }
-#if defined(RGB_BACKLIGHT_DAWN60)
- for (int i = 0; i < WS2812_LED_TOTAL; i++) {
- if ((RGB_UNDERGLOW_ALPHA_TOP_START <= i && i <= RGB_UNDERGLOW_ALPHA_TOP_END) ||
- (RGB_UNDERGLOW_ALPHA_BOT_START <= i && i <= RGB_UNDERGLOW_ALPHA_BOT_END)) {
- backlight_set_color(i + DRIVER_LED_TOTAL, rgb1.r, rgb1.g, rgb1.b);
- } else {
- backlight_set_color(i + DRIVER_LED_TOTAL, rgb2.r, rgb2.g, rgb2.b);
- }
- }
-#endif
-}
-
-void backlight_effect_gradient_up_down(void)
-{
- int16_t h1 = g_config.color_1.h;
- int16_t h2 = g_config.color_2.h;
- int16_t deltaH = h2 - h1;
-
- // Take the shortest path between hues
- if ( deltaH > 127 )
- {
- deltaH -= 256;
- }
- else if ( deltaH < -127 )
- {
- deltaH += 256;
- }
- // Divide delta by 4, this gives the delta per row
- deltaH /= 4;
-
- int16_t s1 = g_config.color_1.s;
- int16_t s2 = g_config.color_2.s;
- int16_t deltaS = ( s2 - s1 ) / 4;
-
- HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
- RGB rgb;
- Point point;
- for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
- {
- map_led_to_point( i, &point );
- // The y range will be 0..64, map this to 0..4
- uint8_t y = (point.y>>4);
- // Relies on hue being 8-bit and wrapping
- hsv.h = g_config.color_1.h + ( deltaH * y );
- hsv.s = g_config.color_1.s + ( deltaS * y );
- rgb = hsv_to_rgb( hsv );
-
- backlight_set_color( i, rgb.r, rgb.g, rgb.b );
- }
-}
-
-void backlight_effect_raindrops(bool initialize)
-{
- int16_t h1 = g_config.color_1.h;
- int16_t h2 = g_config.color_2.h;
- int16_t deltaH = h2 - h1;
- deltaH /= 4;
-
- // Take the shortest path between hues
- if ( deltaH > 127 )
- {
- deltaH -= 256;
- }
- else if ( deltaH < -127 )
- {
- deltaH += 256;
- }
-
- int16_t s1 = g_config.color_1.s;
- int16_t s2 = g_config.color_2.s;
- int16_t deltaS = ( s2 - s1 ) / 4;
-
- HSV hsv;
- RGB rgb;
-
- // Change one LED every tick
- uint8_t led_to_change = ( g_tick & 0x000 ) == 0 ? rand() % BACKLIGHT_LED_COUNT : 255;
-
- for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
- {
- // If initialize, all get set to random colors
- // If not, all but one will stay the same as before.
- if ( initialize || i == led_to_change )
- {
- hsv.h = h1 + ( deltaH * ( rand() & 0x03 ) );
- hsv.s = s1 + ( deltaS * ( rand() & 0x03 ) );
- // Override brightness with global brightness control
- hsv.v = g_config.brightness;
-
- rgb = hsv_to_rgb( hsv );
- backlight_set_color( i, rgb.r, rgb.g, rgb.b );
- }
- }
-}
-
-void backlight_effect_cycle_all(void)
-{
- uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
-
- // Relies on hue being 8-bit and wrapping
- for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
- {
- uint16_t offset2 = g_key_hit[i]<<2;
-#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65) && !defined(RGB_BACKLIGHT_DAWN60) && !defined(RGB_BACKLIGHT_NEBULA68) && !defined(RGB_BACKLIGHT_NEBULA12) && !defined(RGB_BACKLIGHT_NK87) && !defined(RGB_BACKLIGHT_KW_MEGA)
- // stabilizer LEDs use spacebar hits
- if ( i == 36+6 || i == 54+13 || // LC6, LD13
- ( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
- {
- offset2 = g_key_hit[36+0]<<2;
- }
-#endif
- offset2 = (offset2<=63) ? (63-offset2) : 0;
-
- HSV hsv = { .h = offset+offset2, .s = 255, .v = g_config.brightness };
- RGB rgb = hsv_to_rgb( hsv );
- backlight_set_color( i, rgb.r, rgb.g, rgb.b );
- }
-}
-
-void backlight_effect_cycle_left_right(void)
-{
- uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
- HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
- RGB rgb;
- Point point;
- for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
- {
- uint16_t offset2 = g_key_hit[i]<<2;
-#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65) && !defined(RGB_BACKLIGHT_DAWN60) && !defined(RGB_BACKLIGHT_NEBULA68) && !defined(RGB_BACKLIGHT_NEBULA12) && !defined(RGB_BACKLIGHT_NK87) && !defined(RGB_BACKLIGHT_KW_MEGA)
- // stabilizer LEDs use spacebar hits
- if ( i == 36+6 || i == 54+13 || // LC6, LD13
- ( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
- {
- offset2 = g_key_hit[36+0]<<2;
- }
-#endif
- offset2 = (offset2<=63) ? (63-offset2) : 0;
-
- map_led_to_point( i, &point );
- // Relies on hue being 8-bit and wrapping
- hsv.h = point.x + offset + offset2;
- rgb = hsv_to_rgb( hsv );
- backlight_set_color( i, rgb.r, rgb.g, rgb.b );
- }
-}
-
-void backlight_effect_cycle_up_down(void)
-{
- uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
- HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
- RGB rgb;
- Point point;
- for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
- {
- uint16_t offset2 = g_key_hit[i]<<2;
-#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65) && !defined(RGB_BACKLIGHT_DAWN60) && !defined(RGB_BACKLIGHT_NEBULA68) && !defined(RGB_BACKLIGHT_NEBULA12) && !defined(RGB_BACKLIGHT_NK87) && !defined(RGB_BACKLIGHT_KW_MEGA)
- // stabilizer LEDs use spacebar hits
- if ( i == 36+6 || i == 54+13 || // LC6, LD13
- ( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
- {
- offset2 = g_key_hit[36+0]<<2;
- }
-#endif
- offset2 = (offset2<=63) ? (63-offset2) : 0;
-
- map_led_to_point( i, &point );
- // Relies on hue being 8-bit and wrapping
- hsv.h = point.y + offset + offset2;
- rgb = hsv_to_rgb( hsv );
- backlight_set_color( i, rgb.r, rgb.g, rgb.b );
- }
-}
-
-void backlight_effect_jellybean_raindrops( bool initialize )
-{
- HSV hsv;
- RGB rgb;
-
- // Change one LED every tick
- uint8_t led_to_change = ( g_tick & 0x000 ) == 0 ? rand() % BACKLIGHT_LED_COUNT : 255;
-
- for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
- {
- // If initialize, all get set to random colors
- // If not, all but one will stay the same as before.
- if ( initialize || i == led_to_change )
- {
- hsv.h = rand() & 0xFF;
- hsv.s = rand() & 0xFF;
- // Override brightness with global brightness control
- hsv.v = g_config.brightness;;
-
- rgb = hsv_to_rgb( hsv );
- backlight_set_color( i, rgb.r, rgb.g, rgb.b );
- }
- }
-}
-
-void backlight_effect_cycle_radial1(void)
-{
- uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
- HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
- RGB rgb;
- Point point;
- for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
- {
- map_led_to_point_polar( i, &point );
- // Relies on hue being 8-bit and wrapping
- hsv.h = point.x + offset;
- hsv.s = point.y;
- rgb = hsv_to_rgb( hsv );
- backlight_set_color( i, rgb.r, rgb.g, rgb.b );
- }
-}
-
-void backlight_effect_cycle_radial2(void)
-{
- uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
-
- HSV hsv = { .h = 0, .s = g_config.color_1.s, .v = g_config.brightness };
- RGB rgb;
- Point point;
- for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
- {
- map_led_to_point_polar( i, &point );
- uint8_t offset2 = offset + point.x;
- if ( offset2 & 0x80 )
- {
- offset2 = ~offset2;
- }
- offset2 = offset2 >> 2;
- hsv.h = g_config.color_1.h + offset2;
- hsv.s = 127 + ( point.y >> 1 );
- rgb = hsv_to_rgb( hsv );
- backlight_set_color( i, rgb.r, rgb.g, rgb.b );
- }
-}
-
-#if defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_M10_C)
-void backlight_effect_custom_colors(void)
-{
- RGB rgb;
- for ( uint8_t i = 0; i < RGB_BACKLIGHT_CUSTOM_COLORS_COUNT; i++ )
- {
- HSV hsv = { .h = g_config.custom_color[i].h, .s = g_config.custom_color[i].s, .v = g_config.brightness };
- rgb = hsv_to_rgb( hsv );
- uint8_t led;
- map_row_column_to_led( 0, i, &led );
- backlight_set_color( led, rgb.r, rgb.g, rgb.b );
-#if defined(RGB_BACKLIGHT_M10_C)
- // Set stab LEDs with the same color
- if ( led == 10 ) {
- backlight_set_color( 9, rgb.r, rgb.g, rgb.b );
- backlight_set_color( 11, rgb.r, rgb.g, rgb.b );
- }
-#endif
- }
-}
-#endif
-
-void backlight_effect_indicators_set_colors( uint8_t index, HS color )
-{
- HSV hsv = { .h = color.h, .s = color.s, .v = g_config.brightness };
- RGB rgb = hsv_to_rgb( hsv );
- if ( index == 254 )
- {
- backlight_set_color_all( rgb.r, rgb.g, rgb.b );
- }
- else
- {
- backlight_set_color( index, rgb.r, rgb.g, rgb.b );
-
- // If the spacebar LED is the indicator,
- // do the same for the spacebar stabilizers
- if ( index == 36+0 ) // LC0
- {
-#if defined(RGB_BACKLIGHT_ZEAL65)
- backlight_set_color( 36+7, rgb.r, rgb.g, rgb.b ); // LC7
- backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
-#elif defined(RGB_BACKLIGHT_KOYU) || defined(RGB_BACKLIGHT_M65_B) || defined(RGB_BACKLIGHT_M65_BX)
- backlight_set_color( 36+6, rgb.r, rgb.g, rgb.b ); // LC6
- backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
-#elif defined(RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_M60_A)
- backlight_set_color( 36+6, rgb.r, rgb.g, rgb.b ); // LC6
- backlight_set_color( 54+13, rgb.r, rgb.g, rgb.b ); // LD13
- if ( g_config.use_7u_spacebar )
- {
- backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
- }
-#endif
- }
- }
-}
-
-// This runs after another backlight effect and replaces
-// colors already set
-void backlight_effect_indicators(void)
-{
- if ( g_config.caps_lock_indicator.index != 255 &&
- ( g_indicator_state & (1<<USB_LED_CAPS_LOCK) ) )
- {
- backlight_effect_indicators_set_colors( g_config.caps_lock_indicator.index, g_config.caps_lock_indicator.color );
- }
- // This if/else if structure allows higher layers to
- // override lower ones. If we set layer 3's indicator
- // to none, then it will NOT show layer 2 or layer 1
- // indicators, even if those layers are on via the
- // MO13/MO23 Fn combo magic.
- //
- // Basically we want to handle the case where layer 3 is
- // still the backlight configuration layer and we don't
- // want "all LEDs" indicators hiding the backlight effect,
- // but still allow end users to do whatever they want.
- if ( IS_LAYER_ON(3) )
- {
- if ( g_config.layer_3_indicator.index != 255 )
- {
- backlight_effect_indicators_set_colors( g_config.layer_3_indicator.index, g_config.layer_3_indicator.color );
- }
- }
- else if ( IS_LAYER_ON(2) )
- {
- if ( g_config.layer_2_indicator.index != 255 )
- {
- backlight_effect_indicators_set_colors( g_config.layer_2_indicator.index, g_config.layer_2_indicator.color );
- }
- }
- else if ( IS_LAYER_ON(1) )
- {
- if ( g_config.layer_1_indicator.index != 255 )
- {
- backlight_effect_indicators_set_colors( g_config.layer_1_indicator.index, g_config.layer_1_indicator.color );
- }
- }
-}
-
-#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65) && !defined(RGB_BACKLIGHT_NEBULA68) && !defined(RGB_BACKLIGHT_NEBULA12) && !defined(RGB_BACKLIGHT_NK87) && !defined(RGB_BACKLIGHT_KW_MEGA)
-ISR(TIMER3_COMPA_vect)
-#else //STM32 interrupt
-static void gpt_backlight_timer_task(GPTDriver *gptp)
-#endif
-{
- // delay 1 second before driving LEDs or doing anything else
- static uint8_t startup_tick = 0;
- if ( startup_tick < 20 )
- {
- startup_tick++;
- return;
- }
-
- g_tick++;
-
- if ( g_any_key_hit < 0xFFFFFFFF )
- {
- g_any_key_hit++;
- }
-
- for ( int led = 0; led < BACKLIGHT_LED_COUNT; led++ )
- {
- if ( g_key_hit[led] < 255 )
- {
- g_key_hit[led]++;
- }
- }
-
- // Factory default magic value
- if ( g_config.effect == 255 )
- {
- backlight_effect_rgb_test();
- return;
- }
-
- // Ideally we would also stop sending zeros to the LED driver PWM buffers
- // while suspended and just do a software shutdown. This is a cheap hack for now.
- bool suspend_backlight = ((g_suspend_state && g_config.disable_when_usb_suspended) ||
- (g_config.disable_after_timeout > 0 && g_any_key_hit > g_config.disable_after_timeout * 60 * 20));
- uint8_t effect = suspend_backlight ? 0 : g_config.effect;
-
- // Keep track of the effect used last time,
- // detect change in effect, so each effect can
- // have an optional initialization.
- static uint8_t effect_last = 255;
- bool initialize = effect != effect_last;
- effect_last = effect;
-
- // this gets ticked at 20 Hz.
- // each effect can opt to do calculations
- // and/or request PWM buffer updates.
- switch ( effect )
- {
- case 0:
- backlight_effect_all_off();
- break;
- case 1:
- backlight_effect_solid_color();
- break;
- case 2:
-#if defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_M10_C)
- backlight_effect_custom_colors();
-#else
- backlight_effect_alphas_mods();
-#endif
- break;
- case 3:
- backlight_effect_gradient_up_down();
- break;
- case 4:
- backlight_effect_raindrops( initialize );
- break;
- case 5:
- backlight_effect_cycle_all();
- break;
- case 6:
- backlight_effect_cycle_left_right();
- break;
- case 7:
- backlight_effect_cycle_up_down();
- break;
- case 8:
- backlight_effect_jellybean_raindrops( initialize );
- break;
- case 9:
- backlight_effect_cycle_radial1();
- break;
- case 10:
- backlight_effect_cycle_radial2();
- break;
- default:
- backlight_effect_all_off();
- break;
- }
-
- if ( ! suspend_backlight )
- {
-#if !defined(RGB_BACKLIGHT_M6_B) && !defined(RGB_BACKLIGHT_M10_C)
- backlight_effect_indicators();
-#endif
- }
-}
-
-void backlight_set_indicator_index( uint8_t *index, uint8_t row, uint8_t column )
-{
- if ( row >= MATRIX_ROWS )
- {
- // Special value, 255=none, 254=all
- *index = row;
- }
- else
- {
- map_row_column_to_led( row, column, index );
- }
-}
-
-void backlight_get_indicator_row_col( uint8_t index, uint8_t *row, uint8_t *column )
-{
- if ( index == 255 || index == 254 )
- {
- // Special value, 255=none, 254=all
- *row = index;
- *column = 0;
- return;
- }
- for ( uint8_t r = 0; r < MATRIX_ROWS; r++ )
- {
- for ( uint8_t c = 0; c < MATRIX_COLS; c++ )
- {
- uint8_t i = 255;
- map_row_column_to_led( r, c, &i );
- if ( i == index )
- {
- *row = r;
- *column = c;
- return;
- }
- }
- }
-}
-
-// Some helpers for setting/getting HSV
-void _set_color( HS *color, uint8_t *data )
-{
- color->h = data[0];
- color->s = data[1];
-}
-
-void _get_color( HS *color, uint8_t *data )
-{
- data[0] = color->h;
- data[1] = color->s;
-}
-
-void backlight_config_set_value( uint8_t *data )
-{
- bool reinitialize = false;
- uint8_t *value_id = &(data[0]);
- uint8_t *value_data = &(data[1]);
- switch ( *value_id )
- {
-#if defined (RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_ZEAL65)
- case id_use_split_backspace:
- {
- g_config.use_split_backspace = (bool)*value_data;
- reinitialize = true;
- break;
- }
-#endif
-#if defined (RGB_BACKLIGHT_ZEAL60)
- case id_use_split_left_shift:
- {
- g_config.use_split_left_shift = (bool)*value_data;
- reinitialize = true;
- break;
- }
- case id_use_split_right_shift:
- {
- g_config.use_split_right_shift = (bool)*value_data;
- reinitialize = true;
- break;
- }
- case id_use_7u_spacebar:
- {
- g_config.use_7u_spacebar = (bool)*value_data;
- reinitialize = true;
- break;
- }
- case id_use_iso_enter:
- {
- g_config.use_iso_enter = (bool)*value_data;
- reinitialize = true;
- break;
- }
- case id_disable_hhkb_blocker_leds:
- {
- g_config.disable_hhkb_blocker_leds = (bool)*value_data;
- reinitialize = true;
- break;
- }
-#endif
- case id_disable_when_usb_suspended:
- {
- g_config.disable_when_usb_suspended = (bool)*value_data;
- break;
- }
- case id_disable_after_timeout:
- {
- g_config.disable_after_timeout = *value_data;
- break;
- }
- case id_brightness:
- {
- g_config.brightness = *value_data;
- break;
- }
- case id_effect:
- {
- g_config.effect = *value_data;
- break;
- }
- case id_effect_speed:
- {
- g_config.effect_speed = *value_data;
- break;
- }
- case id_color_1:
- {
- _set_color( &(g_config.color_1), value_data );
- break;
- }
- case id_color_2:
- {
- _set_color( &(g_config.color_2), value_data );
- break;
- }
- case id_caps_lock_indicator_color:
- {
- _set_color( &(g_config.caps_lock_indicator.color), value_data );
- break;
- }
- case id_caps_lock_indicator_row_col:
- {
- backlight_set_indicator_index( &(g_config.caps_lock_indicator.index), value_data[0], value_data[1] );
- break;
- }
- case id_layer_1_indicator_color:
- {
- _set_color( &(g_config.layer_1_indicator.color), value_data );
- break;
- }
- case id_layer_1_indicator_row_col:
- {
- backlight_set_indicator_index( &(g_config.layer_1_indicator.index), value_data[0], value_data[1] );
- break;
- }
- case id_layer_2_indicator_color:
- {
- _set_color( &(g_config.layer_2_indicator.color), value_data );
- break;
- }
- case id_layer_2_indicator_row_col:
- {
- backlight_set_indicator_index( &(g_config.layer_2_indicator.index), value_data[0], value_data[1] );
- break;
- }
- case id_layer_3_indicator_color:
- {
- _set_color( &(g_config.layer_3_indicator.color), value_data );
- break;
- }
- case id_layer_3_indicator_row_col:
- {
- backlight_set_indicator_index( &(g_config.layer_3_indicator.index), value_data[0], value_data[1] );
- break;
- }
- case id_alphas_mods:
- {
- for ( int i=0; i<5; i++ )
- {
- g_config.alphas_mods[i] = ( *(value_data+i*2) << 8 ) | ( *(value_data+i*2+1) );
- }
- }
-#if defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_M10_C)
- case id_custom_color:
- {
- uint8_t index = value_data[0];
- if ( index >= 0 && index < RGB_BACKLIGHT_CUSTOM_COLORS_COUNT )
- {
- _set_color( &(g_config.custom_color[index]), &(value_data[1]) );
- }
- }
-#endif
- }
-
- if ( reinitialize )
- {
- backlight_init_drivers();
- }
-}
-
-void backlight_config_get_value( uint8_t *data )
-{
- uint8_t *value_id = &(data[0]);
- uint8_t *value_data = &(data[1]);
- switch ( *value_id )
- {
- case id_use_split_backspace:
- {
- *value_data = ( g_config.use_split_backspace ? 1 : 0 );
- break;
- }
- case id_use_split_left_shift:
- {
- *value_data = ( g_config.use_split_left_shift ? 1 : 0 );
- break;
- }
- case id_use_split_right_shift:
- {
- *value_data = ( g_config.use_split_right_shift ? 1 : 0 );
- break;
- }
- case id_use_7u_spacebar:
- {
- *value_data = ( g_config.use_7u_spacebar ? 1 : 0 );
- break;
- }
- case id_use_iso_enter:
- {
- *value_data = ( g_config.use_iso_enter ? 1 : 0 );
- break;
- }
- case id_disable_when_usb_suspended:
- {
- *value_data = ( g_config.disable_when_usb_suspended ? 1 : 0 );
- break;
- }
- case id_disable_hhkb_blocker_leds:
- {
- *value_data = ( g_config.disable_hhkb_blocker_leds ? 1 : 0 );
- break;
- }
- case id_disable_after_timeout:
- {
- *value_data = g_config.disable_after_timeout;
- break;
- }
- case id_brightness:
- {
- *value_data = g_config.brightness;
- break;
- }
- case id_effect:
- {
- *value_data = g_config.effect;
- break;
- }
- case id_effect_speed:
- {
- *value_data = g_config.effect_speed;
- break;
- }
- case id_color_1:
- {
- _get_color( &(g_config.color_1), value_data );
- break;
- }
- case id_color_2:
- {
- _get_color( &(g_config.color_2), value_data );
- break;
- }
- case id_caps_lock_indicator_color:
- {
- _get_color( &(g_config.caps_lock_indicator.color), value_data );
- break;
- }
- case id_caps_lock_indicator_row_col:
- {
- backlight_get_indicator_row_col( g_config.caps_lock_indicator.index, &(value_data[0]), &(value_data[1]) );
- break;
- }
- case id_layer_1_indicator_color:
- {
- _get_color( &(g_config.layer_1_indicator.color), value_data );
- break;
- }
- case id_layer_1_indicator_row_col:
- {
- backlight_get_indicator_row_col( g_config.layer_1_indicator.index, &(value_data[0]), &(value_data[1]) );
- break;
- }
- case id_layer_2_indicator_color:
- {
- _get_color( &(g_config.layer_2_indicator.color), value_data );
- break;
- }
- case id_layer_2_indicator_row_col:
- {
- backlight_get_indicator_row_col( g_config.layer_2_indicator.index, &(value_data[0]), &(value_data[1]) );
- break;
- }
- case id_layer_3_indicator_color:
- {
- _get_color( &(g_config.layer_3_indicator.color), value_data );
- break;
- }
- case id_layer_3_indicator_row_col:
- {
- backlight_get_indicator_row_col( g_config.layer_3_indicator.index, &(value_data[0]), &(value_data[1]) );
- break;
- }
- case id_alphas_mods:
- {
- for ( int i=0; i<5; i++ )
- {
- *(value_data+i*2) = g_config.alphas_mods[i] >> 8;
- *(value_data+i*2+1) = g_config.alphas_mods[i] & 0xFF;
- }
- }
-#if defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_M10_C)
- case id_custom_color:
- {
- uint8_t index = value_data[0];
- if ( index >= 0 && index < RGB_BACKLIGHT_CUSTOM_COLORS_COUNT )
- {
- _get_color( &(g_config.custom_color[index]), &(value_data[1]) );
- }
- }
-#endif
- }
-}
-
-void backlight_config_set_alphas_mods( uint16_t *alphas_mods )
-{
- for ( int i=0; i<5; i++ )
- {
- g_config.alphas_mods[i] = alphas_mods[i];
- }
-
- backlight_config_save();
-}
-
-void backlight_config_load(void)
-{
- eeprom_read_block( &g_config, ((void*)RGB_BACKLIGHT_CONFIG_EEPROM_ADDR), sizeof(backlight_config) );
-}
-
-void backlight_config_save(void)
-{
- eeprom_update_block( &g_config, ((void*)RGB_BACKLIGHT_CONFIG_EEPROM_ADDR), sizeof(backlight_config) );
-}
-
-void backlight_init_drivers(void)
-{
- // Initialize I2C
- i2c_init();
-
-#if defined(RGB_BACKLIGHT_M6_B)
- IS31FL3218_init();
-#elif defined(RGB_BACKLIGHT_HS60)
- IS31FL3733_init( ISSI_ADDR_1, 0 );
-
- for ( int index = 0; index < DRIVER_LED_TOTAL; index++ )
- {
-#if defined(HS60_ANSI)
- bool enabled = !( ( index == 48-1 ) || //LA48
- ( index == 51-1 ) || //LA51
- ( index == 61-1 ) ); //LA61
-#elif defined(HS60_HHKB)
- bool enabled = !( ( index == 61-1 ) || //LA61
- ( index == 62-1 ) ); //LA62
-#else //HS60_ISO
- bool enabled = !( ( index == 51-1 ) || //LA51
- ( index == 61-1 ) ); //LA61
-#endif
- // This only caches it for later
- IS31FL3733_set_led_control_register( index, enabled, enabled, enabled );
- }
- // This actually updates the LED drivers
- IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
-#elif defined(RGB_BACKLIGHT_NK65)
- IS31FL3733_init( ISSI_ADDR_1, 0 );
- IS31FL3733_init( ISSI_ADDR_2, 0 );
-
- for ( int index = 0; index < DRIVER_LED_TOTAL; index++ )
- {
- bool enabled = !( ( index == 61-1 ) || //LA61
- ( index > 6+64-1 ) ); //LB7-LB64
- // This only caches it for later
- IS31FL3733_set_led_control_register( index, enabled, enabled, enabled );
- }
- IS31FL3733_set_led_control_register( 7+64-1, 0, 1, 0 ); //Enable LB7 green enable for indicators
- // This actually updates the LED drivers
- IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
- IS31FL3733_update_led_control_registers( ISSI_ADDR_2, 1 );
-#elif defined(RGB_BACKLIGHT_NK87)
- IS31FL3733_init( ISSI_ADDR_1, 0 );
- IS31FL3733_init( ISSI_ADDR_2, 0 );
-
- for ( int index = 0; index < DRIVER_LED_TOTAL; index++ )
- {
- bool enabled = !( ( index == 61-1 ) || //LA61
- ( (index >= 2+64-1) && (index <= 4+64-1) ) ||
- ( (index >= 6+64-1) && (index <= 8+64-1) ) ||
- ( index == 10+64-1 ) || ( index == 11+64-1 ) ||
- ( (index >= 14+64-1) && (index <= 16+64-1) ) ||
- ( (index >= 18+64-1) && (index <= 20+64-1) ) ||
- ( (index >= 22+64-1) && (index <= 24+64-1) ) ||
- ( (index >= 26+64-1) && (index <= 28+64-1) ) ||
- ( (index >= 30+64-1) && (index <= 32+64-1) ) ||
- ( (index >= 34+64-1) && (index <= 36+64-1) ) ||
- ( (index >= 38+64-1) && (index <= 40+64-1) ) ||
- ( (index >= 42+64-1) && (index <= 44+64-1) ) ||
- ( (index >= 46+64-1) && (index <= 48+64-1) ) ||
- ( index == 50+64-1 ) ||
- ( index == 54+64-1 ) ||
- ( index == 58+64-1 ) ||
- ( index == 62+64-1 ) );
- // This only caches it for later
- IS31FL3733_set_led_control_register( index, enabled, enabled, enabled );
- }
- IS31FL3733_set_led_control_register( 48+64-1, 0, 0, 1 ); //Enable LB48 blue enable for indicators
- // This actually updates the LED drivers
- IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
- IS31FL3733_update_led_control_registers( ISSI_ADDR_2, 1 );
-#elif defined(RGB_BACKLIGHT_NEBULA68)
- IS31FL3733_init( ISSI_ADDR_1, 0 );
- IS31FL3733_init( ISSI_ADDR_2, 0 );
-
- for ( int index = 0; index < DRIVER_LED_TOTAL; index++ )
- {
- bool enabled = !( ( index == 61-1 ) || //LA61
- ( index > 5+64-1 ) ); //LB6-LB64
- // This only caches it for later
- IS31FL3733_set_led_control_register( index, enabled, enabled, enabled );
- }
- // This actually updates the LED drivers
- IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
- IS31FL3733_update_led_control_registers( ISSI_ADDR_2, 1 );
-#elif defined(RGB_BACKLIGHT_KW_MEGA)
- IS31FL3733_init( ISSI_ADDR_1, 0 );
- IS31FL3733_init( ISSI_ADDR_2, 0 );
-
- for ( int index = 0; index < DRIVER_LED_TOTAL; index++ )
- {
- bool enabled = !( ( index == 61-1 ) || //LA61
- ( index > 6+64-1 ) ); //LB7-LB64
- // This only caches it for later
- IS31FL3733_set_led_control_register( index, enabled, enabled, enabled );
- }
- // This actually updates the LED drivers
- IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
- IS31FL3733_update_led_control_registers( ISSI_ADDR_2, 1 );
-#else
- // Init the #1 driver
- IS31FL3731_init( ISSI_ADDR_1 );
- // Init the #2 driver (if used)
-#if !defined(RGB_BACKLIGHT_NEBULA12) && !defined(RGB_BACKLIGHT_M10_C)
- IS31FL3731_init( ISSI_ADDR_2 );
-#endif
- // Init the #3 driver (if used)
-#if defined(RGB_BACKLIGHT_U80_A)
- IS31FL3731_init( ISSI_ADDR_3 );
-#endif
-
- // Experimental feature, not in configuration yet
-#if defined(RGB_BACKLIGHT_ZEAL60)
- bool disable_spacebar_stab_leds = false;
-#endif
-
- for ( int index = 0; index < DRIVER_LED_TOTAL; index++ )
- {
- // OR the possible "disabled" cases together, then NOT the result to get the enabled state
- // LC6 LD13 not present on Zeal65
-#if defined(RGB_BACKLIGHT_ZEAL65)
- bool enabled = !( ( index == 18+5 && !g_config.use_split_backspace ) || // LB5
- ( index == 36+6 ) || // LC6
- ( index == 54+13 ) ); // LD13
-#elif defined(RGB_BACKLIGHT_KOYU)
- bool enabled = !( ( index == 36+15 ) || // LC15
- ( index == 54+13 ) || // LD13
- ( index == 54+17 ) ); // LD17
-#elif defined(RGB_BACKLIGHT_M65_B) || defined(RGB_BACKLIGHT_M65_BX)
- bool enabled = !(
- // LB6 not present on M65-B
-#if defined(RGB_BACKLIGHT_M65_B)
- ( index == 18+6 ) || // LB6
-#endif
- // LC15 LD13 not present on M65-B, M65-BX
- ( index == 36+15 ) || // LC15
- ( index == 54+13 ) ); // LD13
-#elif defined(RGB_BACKLIGHT_M60_A)
- bool enabled = !(
- // LB6 LB7 LB8 LB15 LB16 LB17 not present on M60-A
- ( index == 18+6 ) || // LB6
- ( index == 18+7 ) || // LB7
- ( index == 18+8 ) || // LB8
- ( index == 18+15 ) || // LB15
- ( index == 18+16 ) || // LB16
- ( index == 18+17 ) || // LB17
- // HHKB blockers (LC17, LD17) and ISO extra keys (LC15,LD13) not present on M60-A
- ( index == 36+17 ) || // LC17
- ( index == 54+17 ) || // LD17
- ( index == 36+15 ) || // LC15
- ( index == 54+13 ) ); // LD13
-#elif defined(RGB_BACKLIGHT_WT60_B) || defined(RGB_BACKLIGHT_WT60_BX) || defined(RGB_BACKLIGHT_WT60_C)
- bool enabled = !(
- // LB6 not present on WT60-B
-#if defined(RGB_BACKLIGHT_WT60_B)
- ( index == 18+6 ) || // LB6
-#endif
- // LB7 LB8 LB15 LB16 LB17 LC15 LD13 not present on WT60-B, WT60-BX, WT60-C
- ( index == 18+7 ) || // LB7
- ( index == 18+8 ) || // LB8
- ( index == 18+15 ) || // LB15
- ( index == 18+16 ) || // LB16
- ( index == 18+17 ) || // LB17
- ( index == 36+15 ) || // LC15
- ( index == 54+13 ) ); // LD13
-#elif defined(RGB_BACKLIGHT_ZEAL60)
- // LB6 LB7 LB8 LB15 LB16 LB17 not present on Zeal60
- bool enabled = !( ( index == 18+5 && !g_config.use_split_backspace ) || // LB5
- ( index == 36+15 && !g_config.use_split_left_shift ) || // LC15
- ( index == 54+8 && !g_config.use_split_right_shift ) || // LD8
- ( index == 54+13 && g_config.use_7u_spacebar ) || // LD13
- ( index == 36+17 && g_config.disable_hhkb_blocker_leds ) || // LC17
- ( index == 54+17 && g_config.disable_hhkb_blocker_leds ) || // LD17
- ( index == 18+6 ) || // LB6
- ( index == 18+7 ) || // LB7
- ( index == 18+8 ) || // LB8
- ( index == 18+15 ) || // LB15
- ( index == 18+16 ) || // LB16
- ( index == 18+17 ) || // LB17
- ( index == 36+6 && disable_spacebar_stab_leds ) || // LC6
- ( index == 54+13 && disable_spacebar_stab_leds ) || // LD13
- ( index == 54+14 && disable_spacebar_stab_leds && g_config.use_7u_spacebar ) ); // LD14
-#elif defined(RGB_BACKLIGHT_U80_A)
-// LB5, LB6, LB7, LB8, LB15, LB16, LB17, LC15, LD8, LD13, LE0-LE8, LF13
- bool enabled = !(
- ( index == 18+5 ) || // LB5
- ( index == 18+6 ) || // LB6
- ( index == 18+7 ) || // LB7
- ( index == 18+8 ) || // LB8
- ( index == 18+15 ) || // LB15
- ( index == 18+16 ) || // LB16
- ( index == 18+16 ) || // LB17
- ( index == 36+15 ) || // LC15
- ( index == 54+8 ) || // LD8
- ( index == 54+13 ) || // LD13
- ( index >= 72+0 && index <= 72+8 ) || // LE0-LE8
- ( index == 90+13 ) ); // LF13
-#elif defined(RGB_BACKLIGHT_DAWN60)
- bool enabled = !( ( index == 15+7 && !g_config.use_split_backspace ) || //other backspace
- ( index == 47+13 && g_config.use_7u_spacebar ) || //LD13
- ( index == 47+15 && g_config.use_7u_spacebar ) ); //LD15
-#elif defined(RGB_BACKLIGHT_NEBULA12)
- bool enabled = !( ( index >= 9-1 && index <= 12-1 ) ); // A9-A12
-#elif defined(RGB_BACKLIGHT_M50_A)
- bool enabled = !(
- // LA0, LA7, LA8, LA17
- ( index == 0+0 ) ||
- ( index == 0+7 ) ||
- ( index == 0+8 ) ||
- ( index == 0+17 ) ||
-
- // LB0, LB7, LB8, LB15, LB16, LB17,
- ( index == 18+0 ) ||
- ( index == 18+7 ) ||
- ( index == 18+8 ) ||
- ( index == 18+15 ) ||
- ( index == 18+16 ) ||
- ( index == 18+17 ) ||
- // LC0, LC8, LC16, LC17
- ( index == 36+0 ) ||
- ( index == 36+8 ) ||
- ( index == 36+16 ) ||
- ( index == 36+17 ) ||
- // LD0, LD7, LD8, LD9, LD15, LD16, LD17
- ( index == 54+0 ) ||
- ( index == 54+7 ) ||
- ( index == 54+8 ) ||
- ( index == 54+9 ) ||
- ( index == 54+15 ) ||
- ( index == 54+16 ) ||
- ( index == 54+17 ) );
-#elif defined(RGB_BACKLIGHT_M10_C)
- bool enabled = true;
-#endif
- // This only caches it for later
- IS31FL3731_set_led_control_register( index, enabled, enabled, enabled );
- }
- // This actually updates the LED drivers
- // TODO: refactor this to use DRIVER_COUNT
- IS31FL3731_update_led_control_registers( ISSI_ADDR_1, 0 );
-#if !defined(RGB_BACKLIGHT_NEBULA12) && !defined(RGB_BACKLIGHT_M10_C)
- IS31FL3731_update_led_control_registers( ISSI_ADDR_2, 1 );
-#endif
-#if defined(RGB_BACKLIGHT_U80_A)
- IS31FL3731_update_led_control_registers( ISSI_ADDR_3, 2 );
-#endif
-#endif
-
- // TODO: put the 1 second startup delay here?
-
- // clear the key hits
- for ( int led=0; led<BACKLIGHT_LED_COUNT; led++ )
- {
- g_key_hit[led] = 255;
- }
-}
-
-bool process_record_backlight(uint16_t keycode, keyrecord_t *record)
-{
- // Record keypresses for backlight effects
- if ( record->event.pressed )
- {
- backlight_set_key_hit( record->event.key.row, record->event.key.col );
- }
-
- switch(keycode)
- {
- case BR_INC:
- if (record->event.pressed)
- {
- backlight_brightness_increase();
- }
- return false;
- break;
- case BR_DEC:
- if (record->event.pressed)
- {
- backlight_brightness_decrease();
- }
- return false;
- break;
- case EF_INC:
- if (record->event.pressed)
- {
- backlight_effect_increase();
- }
- return false;
- break;
- case EF_DEC:
- if (record->event.pressed)
- {
- backlight_effect_decrease();
- }
- return false;
- break;
- case ES_INC:
- if (record->event.pressed)
- {
- backlight_effect_speed_increase();
- }
- return false;
- break;
- case ES_DEC:
- if (record->event.pressed)
- {
- backlight_effect_speed_decrease();
- }
- return false;
- break;
- case H1_INC:
- if (record->event.pressed)
- {
- backlight_color_1_hue_increase();
- }
- return false;
- break;
- case H1_DEC:
- if (record->event.pressed)
- {
- backlight_color_1_hue_decrease();
- }
- return false;
- break;
- case S1_INC:
- if (record->event.pressed)
- {
- backlight_color_1_sat_increase();
- }
- return false;
- break;
- case S1_DEC:
- if (record->event.pressed)
- {
- backlight_color_1_sat_decrease();
- break;
- }
- return false;
- break;
- case H2_INC:
- if (record->event.pressed)
- {
- backlight_color_2_hue_increase();
- }
- return false;
- break;
- case H2_DEC:
- if (record->event.pressed)
- {
- backlight_color_2_hue_decrease();
- }
- return false;
- break;
- case S2_INC:
- if (record->event.pressed)
- {
- backlight_color_2_sat_increase();
- }
- return false;
- break;
- case S2_DEC:
- if (record->event.pressed)
- {
- backlight_color_2_sat_decrease();
- break;
- }
- return false;
- break;
- }
-
- return true;
-}
-
-// Deals with the messy details of incrementing an integer
-uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max )
-{
- int16_t new_value = value;
- new_value += step;
- return MIN( MAX( new_value, min ), max );
-}
-
-uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max )
-{
- int16_t new_value = value;
- new_value -= step;
- return MIN( MAX( new_value, min ), max );
-}
-
-void backlight_effect_increase(void)
-{
- g_config.effect = increment( g_config.effect, 1, 0, BACKLIGHT_EFFECT_MAX );
- backlight_config_save();
-}
-
-void backlight_effect_decrease(void)
-{
- g_config.effect = decrement( g_config.effect, 1, 0, BACKLIGHT_EFFECT_MAX );
- backlight_config_save();
-}
-
-void backlight_effect_speed_increase(void)
-{
- g_config.effect_speed = increment( g_config.effect_speed, 1, 0, 3 );
- backlight_config_save();
-}
-
-void backlight_effect_speed_decrease(void)
-{
- g_config.effect_speed = decrement( g_config.effect_speed, 1, 0, 3 );
- backlight_config_save();
-}
-
-void backlight_brightness_increase(void)
-{
- g_config.brightness = increment( g_config.brightness, 8, 0, 255 );
- backlight_config_save();
-}
-
-void backlight_brightness_decrease(void)
-{
- g_config.brightness = decrement( g_config.brightness, 8, 0, 255 );
- backlight_config_save();
-}
-
-void backlight_color_1_hue_increase(void)
-{
- g_config.color_1.h = increment( g_config.color_1.h, 8, 0, 255 );
- backlight_config_save();
-}
-
-void backlight_color_1_hue_decrease(void)
-{
- g_config.color_1.h = decrement( g_config.color_1.h, 8, 0, 255 );
- backlight_config_save();
-}
-
-void backlight_color_1_sat_increase(void)
-{
- g_config.color_1.s = increment( g_config.color_1.s, 8, 0, 255 );
- backlight_config_save();
-}
-
-void backlight_color_1_sat_decrease(void)
-{
- g_config.color_1.s = decrement( g_config.color_1.s, 8, 0, 255 );
- backlight_config_save();
-}
-
-void backlight_color_2_hue_increase(void)
-{
- g_config.color_2.h = increment( g_config.color_2.h, 8, 0, 255 );
- backlight_config_save();
-}
-
-void backlight_color_2_hue_decrease(void)
-{
- g_config.color_2.h = decrement( g_config.color_2.h, 8, 0, 255 );
- backlight_config_save();
-}
-
-void backlight_color_2_sat_increase(void)
-{
- g_config.color_2.s = increment( g_config.color_2.s, 8, 0, 255 );
- backlight_config_save();
-}
-
-void backlight_color_2_sat_decrease(void)
-{
- g_config.color_2.s = decrement( g_config.color_2.s, 8, 0, 255 );
- backlight_config_save();
-}
-
-#if defined(RGB_DEBUGGING_ONLY)
-void backlight_test_led( uint8_t index, bool red, bool green, bool blue )
-{
- for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
- {
- if ( i == index )
- {
- IS31FL3731_set_led_control_register( i, red, green, blue );
- }
- else
- {
- IS31FL3731_set_led_control_register( i, false, false, false );
- }
- }
-}
-
-void backlight_debug_led( bool state )
-{
- if (state)
- {
- // Output high.
- DDRE |= (1<<6);
- PORTE |= (1<<6);
- }
- else
- {
- // Output low.
- DDRE &= ~(1<<6);
- PORTE &= ~(1<<6);
- }
-}
-#endif // defined(RGB_DEBUGGING_ONLY)
-
-
diff --git a/drivers/chibios/wt_rgb_backlight.h b/drivers/chibios/wt_rgb_backlight.h
deleted file mode 100644
index 529f84636a..0000000000
--- a/drivers/chibios/wt_rgb_backlight.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Copyright 2017 Jason Williams (Wilba)
- *
- * 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 RGB_BACKLIGHT_ENABLED
-#else
-#error rgb_backlight.h included when RGB_BACKLIGHT_ENABLED == 0
-#endif // RGB_BACKLIGHT_ENABLED
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#include "quantum/color.h"
-
-typedef struct PACKED
-{
- uint8_t h;
- uint8_t s;
-} HS;
-
-typedef struct
-{
- HS color;
- uint8_t index;
-} backlight_config_indicator;
-
-#if defined(RGB_BACKLIGHT_M6_B)
-#define RGB_BACKLIGHT_CUSTOM_COLORS_COUNT 6
-#elif defined(RGB_BACKLIGHT_M10_C)
-#define RGB_BACKLIGHT_CUSTOM_COLORS_COUNT 10
-#endif
-
-typedef struct
-{
- bool use_split_backspace:1; // |
- bool use_split_left_shift:1; // |
- bool use_split_right_shift:1; // |
- bool use_7u_spacebar:1; // |
- bool use_iso_enter:1; // |
- bool disable_when_usb_suspended:1; // |
- bool disable_hhkb_blocker_leds:1; // |
- bool __pad7:1; // 1 byte
- uint8_t disable_after_timeout; // 1 byte
- uint8_t brightness; // 1 byte
- uint8_t effect; // 1 byte
- uint8_t effect_speed; // 1 byte
- HS color_1; // 2 bytes
- HS color_2; // 2 bytes
- backlight_config_indicator caps_lock_indicator; // 3 bytes
- backlight_config_indicator layer_1_indicator; // 3 bytes
- backlight_config_indicator layer_2_indicator; // 3 bytes
- backlight_config_indicator layer_3_indicator; // 3 bytes
- uint16_t alphas_mods[5]; // 10 bytes
-#if defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_M10_C)
- HS custom_color[RGB_BACKLIGHT_CUSTOM_COLORS_COUNT]; // 12 or 20 bytes
-#endif
-} backlight_config; // = 31 bytes (M6-B = 43 bytes, M10-C 51 bytes)
-
-void backlight_config_load(void);
-void backlight_config_save(void);
-void backlight_config_set_value( uint8_t *data );
-void backlight_config_get_value( uint8_t *data );
-
-void backlight_init_drivers(void);
-
-void backlight_timer_init(void);
-void backlight_timer_enable(void);
-void backlight_timer_disable(void);
-
-void backlight_set_suspend_state(bool state);
-void backlight_set_indicator_state(uint8_t state);
-
-// This should not be called from an interrupt
-// (eg. from a timer interrupt).
-// Call this while idle (in between matrix scans).
-// If the buffer is dirty, it will update the driver with the buffer.
-void backlight_update_pwm_buffers(void);
-
-// Handle backlight specific keycodes
-bool process_record_backlight(uint16_t keycode, keyrecord_t *record);
-
-void backlight_set_key_hit(uint8_t row, uint8_t col);
-
-void backlight_effect_increase(void);
-void backlight_effect_decrease(void);
-void backlight_effect_speed_increase(void);
-void backlight_effect_speed_decrease(void);
-
-void backlight_brightness_increase(void);
-void backlight_brightness_decrease(void);
-
-void backlight_color_1_hue_increase(void);
-void backlight_color_1_hue_decrease(void);
-void backlight_color_1_sat_increase(void);
-void backlight_color_1_sat_decrease(void);
-void backlight_color_2_hue_increase(void);
-void backlight_color_2_hue_decrease(void);
-void backlight_color_2_sat_increase(void);
-void backlight_color_2_sat_decrease(void);
-
-void backlight_test_led( uint8_t index, bool red, bool green, bool blue );
-void backlight_debug_led(bool state);
diff --git a/drivers/chibios/wt_rgb_backlight_api.h b/drivers/chibios/wt_rgb_backlight_api.h
deleted file mode 100644
index 0cd6b85f07..0000000000
--- a/drivers/chibios/wt_rgb_backlight_api.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright 2017 Jason Williams (Wilba)
- *
- * 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
-
-enum wt_rgb_backlight_config_value
-{
- id_use_split_backspace = 0x01,
- id_use_split_left_shift = 0x02,
- id_use_split_right_shift = 0x03,
- id_use_7u_spacebar = 0x04,
- id_use_iso_enter = 0x05,
- id_disable_hhkb_blocker_leds = 0x06,
- id_disable_when_usb_suspended = 0x07,
- id_disable_after_timeout = 0x08,
- id_brightness = 0x09,
- id_effect = 0x0A,
- id_effect_speed = 0x0B,
- id_color_1 = 0x0C,
- id_color_2 = 0x0D,
- id_caps_lock_indicator_color = 0x0E,
- id_caps_lock_indicator_row_col = 0x0F,
- id_layer_1_indicator_color = 0x10,
- id_layer_1_indicator_row_col = 0x11,
- id_layer_2_indicator_color = 0x12,
- id_layer_2_indicator_row_col = 0x13,
- id_layer_3_indicator_color = 0x14,
- id_layer_3_indicator_row_col = 0x15,
- id_alphas_mods = 0x16,
- id_custom_color = 0x17
-};
diff --git a/drivers/chibios/wt_rgb_backlight_keycodes.h b/drivers/chibios/wt_rgb_backlight_keycodes.h
deleted file mode 100644
index 5a43649535..0000000000
--- a/drivers/chibios/wt_rgb_backlight_keycodes.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright 2017 Jason Williams (Wilba)
- *
- * 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
-
-// This is hardcoded at 0x5F00 so it's well after keycode value SAFE_RANGE
-enum wt_rgb_backlight_keycodes {
- BR_INC = 0x5F00, // backlight brightness increase
- BR_DEC, // backlight brightness decrease
- EF_INC, // backlight effect increase
- EF_DEC, // backlight effect decrease
- ES_INC,
- ES_DEC,
- H1_INC,
- H1_DEC,
- S1_INC,
- S1_DEC,
- H2_INC,
- H2_DEC,
- S2_INC,
- S2_DEC
-};
diff --git a/drivers/eeprom/eeprom_i2c.c b/drivers/eeprom/eeprom_i2c.c
index 4210f06f9f..8e80ff544f 100644
--- a/drivers/eeprom/eeprom_i2c.c
+++ b/drivers/eeprom/eeprom_i2c.c
@@ -16,6 +16,9 @@
#include <stdint.h>
#include <string.h>
+#if defined(EXTERNAL_EEPROM_WP_PIN)
+# include "gpio.h"
+#endif
/*
Note that the implementations of eeprom_XXXX_YYYY on AVR are normally
@@ -50,7 +53,14 @@ static inline void fill_target_address(uint8_t *buffer, const void *addr) {
}
}
-void eeprom_driver_init(void) { i2c_init(); }
+void eeprom_driver_init(void) {
+ i2c_init();
+#if defined(EXTERNAL_EEPROM_WP_PIN)
+ /* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */
+ writePin(EXTERNAL_EEPROM_WP_PIN, 1);
+ setPinInputHigh(EXTERNAL_EEPROM_WP_PIN);
+#endif
+}
void eeprom_driver_erase(void) {
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
@@ -89,6 +99,11 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
uint8_t * read_buf = (uint8_t *)buf;
uintptr_t target_addr = (uintptr_t)addr;
+#if defined(EXTERNAL_EEPROM_WP_PIN)
+ setPinOutput(EXTERNAL_EEPROM_WP_PIN);
+ writePin(EXTERNAL_EEPROM_WP_PIN, 0);
+#endif
+
while (len > 0) {
uintptr_t page_offset = target_addr % EXTERNAL_EEPROM_PAGE_SIZE;
int write_length = EXTERNAL_EEPROM_PAGE_SIZE - page_offset;
@@ -116,4 +131,10 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
target_addr += write_length;
len -= write_length;
}
+
+#if defined(EXTERNAL_EEPROM_WP_PIN)
+ /* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */
+ writePin(EXTERNAL_EEPROM_WP_PIN, 1);
+ setPinInputHigh(EXTERNAL_EEPROM_WP_PIN);
+#endif
}
diff --git a/drivers/eeprom/eeprom_spi.c b/drivers/eeprom/eeprom_spi.c
index 182731d82f..e273090854 100644
--- a/drivers/eeprom/eeprom_spi.c
+++ b/drivers/eeprom/eeprom_spi.c
@@ -31,6 +31,8 @@
*/
#include "wait.h"
+#include "debug.h"
+#include "timer.h"
#include "spi_master.h"
#include "eeprom.h"
#include "eeprom_spi.h"
@@ -50,11 +52,6 @@
# define EXTERNAL_EEPROM_SPI_TIMEOUT 100
#endif
-#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
-# include "timer.h"
-# include "debug.h"
-#endif // CONSOLE_ENABLE
-
static bool spi_eeprom_start(void) { return spi_start(EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN, EXTERNAL_EEPROM_SPI_LSBFIRST, EXTERNAL_EEPROM_SPI_MODE, EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR); }
static spi_status_t spi_eeprom_wait_while_busy(int timeout) {
diff --git a/drivers/eeprom/eeprom_stm32_L0_L1.c b/drivers/eeprom/eeprom_stm32_L0_L1.c
deleted file mode 100644
index ed26cc7145..0000000000
--- a/drivers/eeprom/eeprom_stm32_L0_L1.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Copyright 2020 Nick Brassel (tzarc)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdint.h>
-#include <string.h>
-
-#include <hal.h>
-#include "eeprom_driver.h"
-#include "eeprom_stm32_L0_L1.h"
-
-#define EEPROM_BASE_ADDR 0x08080000
-#define EEPROM_ADDR(offset) (EEPROM_BASE_ADDR + (offset))
-#define EEPROM_PTR(offset) ((__IO uint8_t *)EEPROM_ADDR(offset))
-#define EEPROM_BYTE(location, offset) (*(EEPROM_PTR(((uint32_t)location) + ((uint32_t)offset))))
-
-#define BUFFER_BYTE(buffer, offset) (*(((uint8_t *)buffer) + offset))
-
-#define FLASH_PEKEY1 0x89ABCDEF
-#define FLASH_PEKEY2 0x02030405
-
-static inline void STM32_L0_L1_EEPROM_WaitNotBusy(void) {
- while (FLASH->SR & FLASH_SR_BSY) {
- __WFI();
- }
-}
-
-static inline void STM32_L0_L1_EEPROM_Unlock(void) {
- STM32_L0_L1_EEPROM_WaitNotBusy();
- if (FLASH->PECR & FLASH_PECR_PELOCK) {
- FLASH->PEKEYR = FLASH_PEKEY1;
- FLASH->PEKEYR = FLASH_PEKEY2;
- }
-}
-
-static inline void STM32_L0_L1_EEPROM_Lock(void) {
- STM32_L0_L1_EEPROM_WaitNotBusy();
- FLASH->PECR |= FLASH_PECR_PELOCK;
-}
-
-void eeprom_driver_init(void) {}
-
-void eeprom_driver_erase(void) {
- STM32_L0_L1_EEPROM_Unlock();
-
- for (size_t offset = 0; offset < STM32_ONBOARD_EEPROM_SIZE; offset += sizeof(uint32_t)) {
- FLASH->PECR |= FLASH_PECR_ERASE | FLASH_PECR_DATA;
-
- *(__IO uint32_t *)EEPROM_ADDR(offset) = (uint32_t)0;
-
- STM32_L0_L1_EEPROM_WaitNotBusy();
- FLASH->PECR &= ~(FLASH_PECR_ERASE | FLASH_PECR_DATA);
- }
-
- STM32_L0_L1_EEPROM_Lock();
-}
-
-void eeprom_read_block(void *buf, const void *addr, size_t len) {
- for (size_t offset = 0; offset < len; ++offset) {
- // Drop out if we've hit the limit of the EEPROM
- if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) {
- break;
- }
-
- STM32_L0_L1_EEPROM_WaitNotBusy();
- BUFFER_BYTE(buf, offset) = EEPROM_BYTE(addr, offset);
- }
-}
-
-void eeprom_write_block(const void *buf, void *addr, size_t len) {
- STM32_L0_L1_EEPROM_Unlock();
-
- for (size_t offset = 0; offset < len; ++offset) {
- // Drop out if we've hit the limit of the EEPROM
- if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) {
- break;
- }
-
- STM32_L0_L1_EEPROM_WaitNotBusy();
- EEPROM_BYTE(addr, offset) = BUFFER_BYTE(buf, offset);
- }
-
- STM32_L0_L1_EEPROM_Lock();
-}
diff --git a/drivers/eeprom/eeprom_stm32_L0_L1.h b/drivers/eeprom/eeprom_stm32_L0_L1.h
deleted file mode 100644
index a35defca8b..0000000000
--- a/drivers/eeprom/eeprom_stm32_L0_L1.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Copyright 2020 Nick Brassel (tzarc)
- *
- * 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
-
-/*
- The size used by the STM32 L0/L1 EEPROM driver.
-*/
-#ifndef STM32_ONBOARD_EEPROM_SIZE
-# ifdef VIA_ENABLE
-# define STM32_ONBOARD_EEPROM_SIZE 1024
-# else
-# include "eeconfig.h"
-# define STM32_ONBOARD_EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO and EEPROM page sizing
-# endif
-#endif
-
-#if STM32_ONBOARD_EEPROM_SIZE > 128
-# pragma message("Please note: resetting EEPROM using an STM32L0/L1 device takes up to 1 second for every 1kB of internal EEPROM used.")
-#endif
diff --git a/drivers/haptic/haptic.c b/drivers/haptic/haptic.c
deleted file mode 100644
index 828c8fba71..0000000000
--- a/drivers/haptic/haptic.c
+++ /dev/null
@@ -1,395 +0,0 @@
-/* Copyright 2019 ishtob
- * Driver for haptic feedback written for QMK
- *
- * 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 "haptic.h"
-#include "eeconfig.h"
-#include "progmem.h"
-#include "debug.h"
-#ifdef DRV2605L
-# include "DRV2605L.h"
-#endif
-#ifdef SOLENOID_ENABLE
-# include "solenoid.h"
-#endif
-
-haptic_config_t haptic_config;
-
-void haptic_init(void) {
- debug_enable = 1; // Debug is ON!
- if (!eeconfig_is_enabled()) {
- eeconfig_init();
- }
- haptic_config.raw = eeconfig_read_haptic();
-#ifdef SOLENOID_ENABLE
- solenoid_set_dwell(haptic_config.dwell);
-#endif
- if ((haptic_config.raw == 0)
-#ifdef SOLENOID_ENABLE
- || (haptic_config.dwell == 0)
-#endif
- ) {
- // this will be called, if the eeprom is not corrupt,
- // but the previous firmware didn't have haptic enabled,
- // or the previous firmware didn't have solenoid enabled,
- // and the current one has solenoid enabled.
- haptic_reset();
- }
-#ifdef SOLENOID_ENABLE
- solenoid_setup();
- dprintf("Solenoid driver initialized\n");
-#endif
-#ifdef DRV2605L
- DRV_init();
- dprintf("DRV2605 driver initialized\n");
-#endif
- eeconfig_debug_haptic();
-}
-
-void haptic_task(void) {
-#ifdef SOLENOID_ENABLE
- solenoid_check();
-#endif
-}
-
-void eeconfig_debug_haptic(void) {
- dprintf("haptic_config eprom\n");
- dprintf("haptic_config.enable = %d\n", haptic_config.enable);
- dprintf("haptic_config.mode = %d\n", haptic_config.mode);
-}
-
-void haptic_enable(void) {
- haptic_config.enable = 1;
- xprintf("haptic_config.enable = %u\n", haptic_config.enable);
- eeconfig_update_haptic(haptic_config.raw);
-}
-
-void haptic_disable(void) {
- haptic_config.enable = 0;
- xprintf("haptic_config.enable = %u\n", haptic_config.enable);
- eeconfig_update_haptic(haptic_config.raw);
-}
-
-void haptic_toggle(void) {
- if (haptic_config.enable) {
- haptic_disable();
- } else {
- haptic_enable();
- }
- eeconfig_update_haptic(haptic_config.raw);
-}
-
-void haptic_feedback_toggle(void) {
- haptic_config.feedback++;
- if (haptic_config.feedback >= HAPTIC_FEEDBACK_MAX) haptic_config.feedback = KEY_PRESS;
- xprintf("haptic_config.feedback = %u\n", !haptic_config.feedback);
- eeconfig_update_haptic(haptic_config.raw);
-}
-
-void haptic_buzz_toggle(void) {
- bool buzz_stat = !haptic_config.buzz;
- haptic_config.buzz = buzz_stat;
- haptic_set_buzz(buzz_stat);
-}
-
-void haptic_mode_increase(void) {
- uint8_t mode = haptic_config.mode + 1;
-#ifdef DRV2605L
- if (haptic_config.mode >= drv_effect_max) {
- mode = 1;
- }
-#endif
- haptic_set_mode(mode);
-}
-
-void haptic_mode_decrease(void) {
- uint8_t mode = haptic_config.mode - 1;
-#ifdef DRV2605L
- if (haptic_config.mode < 1) {
- mode = (drv_effect_max - 1);
- }
-#endif
- haptic_set_mode(mode);
-}
-
-void haptic_dwell_increase(void) {
-#ifdef SOLENOID_ENABLE
- int16_t next_dwell = ((int16_t)haptic_config.dwell) + SOLENOID_DWELL_STEP_SIZE;
- if (haptic_config.dwell >= SOLENOID_MAX_DWELL) {
- // if it's already at max, we wrap back to min
- next_dwell = SOLENOID_MIN_DWELL;
- } else if (next_dwell > SOLENOID_MAX_DWELL) {
- // if we overshoot the max, then cap at max
- next_dwell = SOLENOID_MAX_DWELL;
- }
- solenoid_set_dwell(next_dwell);
-#else
- int16_t next_dwell = ((int16_t)haptic_config.dwell) + 1;
-#endif
- haptic_set_dwell(next_dwell);
-}
-
-void haptic_dwell_decrease(void) {
-#ifdef SOLENOID_ENABLE
- int16_t next_dwell = ((int16_t)haptic_config.dwell) - SOLENOID_DWELL_STEP_SIZE;
- if (haptic_config.dwell <= SOLENOID_MIN_DWELL) {
- // if it's already at min, we wrap to max
- next_dwell = SOLENOID_MAX_DWELL;
- } else if (next_dwell < SOLENOID_MIN_DWELL) {
- // if we go below min, then we cap to min
- next_dwell = SOLENOID_MIN_DWELL;
- }
- solenoid_set_dwell(next_dwell);
-#else
- int16_t next_dwell = ((int16_t)haptic_config.dwell) - 1;
-#endif
- haptic_set_dwell(next_dwell);
-}
-
-void haptic_reset(void) {
- haptic_config.enable = true;
- uint8_t feedback = HAPTIC_FEEDBACK_DEFAULT;
- haptic_config.feedback = feedback;
-#ifdef DRV2605L
- uint8_t mode = HAPTIC_MODE_DEFAULT;
- haptic_config.mode = mode;
-#endif
-#ifdef SOLENOID_ENABLE
- uint8_t dwell = SOLENOID_DEFAULT_DWELL;
- haptic_config.dwell = dwell;
- haptic_config.buzz = SOLENOID_DEFAULT_BUZZ;
- solenoid_set_dwell(dwell);
-#else
- // This is to trigger haptic_reset again, if solenoid is enabled in the future.
- haptic_config.dwell = 0;
- haptic_config.buzz = 0;
-#endif
- eeconfig_update_haptic(haptic_config.raw);
- xprintf("haptic_config.feedback = %u\n", haptic_config.feedback);
- xprintf("haptic_config.mode = %u\n", haptic_config.mode);
-}
-
-void haptic_set_feedback(uint8_t feedback) {
- haptic_config.feedback = feedback;
- eeconfig_update_haptic(haptic_config.raw);
- xprintf("haptic_config.feedback = %u\n", haptic_config.feedback);
-}
-
-void haptic_set_mode(uint8_t mode) {
- haptic_config.mode = mode;
- eeconfig_update_haptic(haptic_config.raw);
- xprintf("haptic_config.mode = %u\n", haptic_config.mode);
-}
-
-void haptic_set_amplitude(uint8_t amp) {
- haptic_config.amplitude = amp;
- eeconfig_update_haptic(haptic_config.raw);
- xprintf("haptic_config.amplitude = %u\n", haptic_config.amplitude);
-#ifdef DRV2605L
- DRV_amplitude(amp);
-#endif
-}
-
-void haptic_set_buzz(uint8_t buzz) {
- haptic_config.buzz = buzz;
- eeconfig_update_haptic(haptic_config.raw);
- xprintf("haptic_config.buzz = %u\n", haptic_config.buzz);
-}
-
-void haptic_set_dwell(uint8_t dwell) {
- haptic_config.dwell = dwell;
- eeconfig_update_haptic(haptic_config.raw);
- xprintf("haptic_config.dwell = %u\n", haptic_config.dwell);
-}
-
-uint8_t haptic_get_mode(void) {
- if (!haptic_config.enable) {
- return false;
- }
- return haptic_config.mode;
-}
-
-uint8_t haptic_get_feedback(void) {
- if (!haptic_config.enable) {
- return false;
- }
- return haptic_config.feedback;
-}
-
-uint8_t haptic_get_dwell(void) {
- if (!haptic_config.enable) {
- return false;
- }
- return haptic_config.dwell;
-}
-
-void haptic_enable_continuous(void) {
- haptic_config.cont = 1;
- xprintf("haptic_config.cont = %u\n", haptic_config.cont);
- eeconfig_update_haptic(haptic_config.raw);
-#ifdef DRV2605L
- DRV_rtp_init();
-#endif
-}
-
-void haptic_disable_continuous(void) {
- haptic_config.cont = 0;
- xprintf("haptic_config.cont = %u\n", haptic_config.cont);
- eeconfig_update_haptic(haptic_config.raw);
-#ifdef DRV2605L
- DRV_write(DRV_MODE, 0x00);
-#endif
-}
-
-void haptic_toggle_continuous(void) {
-#ifdef DRV2605L
- if (haptic_config.cont) {
- haptic_disable_continuous();
- } else {
- haptic_enable_continuous();
- }
- eeconfig_update_haptic(haptic_config.raw);
-#endif
-}
-
-void haptic_cont_increase(void) {
- uint8_t amp = haptic_config.amplitude + 10;
- if (haptic_config.amplitude >= 120) {
- amp = 120;
- }
- haptic_set_amplitude(amp);
-}
-
-void haptic_cont_decrease(void) {
- uint8_t amp = haptic_config.amplitude - 10;
- if (haptic_config.amplitude < 20) {
- amp = 20;
- }
- haptic_set_amplitude(amp);
-}
-
-void haptic_play(void) {
-#ifdef DRV2605L
- uint8_t play_eff = 0;
- play_eff = haptic_config.mode;
- DRV_pulse(play_eff);
-#endif
-#ifdef SOLENOID_ENABLE
- solenoid_fire();
-#endif
-}
-
-void haptic_toggle_continuous(void) {
-#ifdef DRV2605L
-if (haptic_config.cont) {
- haptic_disable_continuous();
- } else {
- haptic_enable_continuous();
- }
- eeconfig_update_haptic(haptic_config.raw);
-#endif
-}
-
-
-void haptic_cont_increase(void) {
- uint8_t amp = haptic_config.amplitude + 10;
- if (haptic_config.amplitude >= 120) {
- amp = 120;
- }
- haptic_set_amplitude(amp);
-}
-
-void haptic_cont_decrease(void) {
- uint8_t amp = haptic_config.amplitude - 10;
- if (haptic_config.amplitude < 20) {
- amp = 20;
- }
- haptic_set_amplitude(amp);
-}
-
-
-void haptic_play(void) {
-#ifdef DRV2605L
- uint8_t play_eff = 0;
- play_eff = haptic_config.mode;
- DRV_pulse(play_eff);
-#endif
-#ifdef SOLENOID_ENABLE
- solenoid_fire();
-#endif
-}
-
-bool process_haptic(uint16_t keycode, keyrecord_t *record) {
- if (keycode == HPT_ON && record->event.pressed) {
- haptic_enable();
- }
- if (keycode == HPT_OFF && record->event.pressed) {
- haptic_disable();
- }
- if (keycode == HPT_TOG && record->event.pressed) {
- haptic_toggle();
- }
- if (keycode == HPT_RST && record->event.pressed) {
- haptic_reset();
- }
- if (keycode == HPT_FBK && record->event.pressed) {
- haptic_feedback_toggle();
- }
- if (keycode == HPT_BUZ && record->event.pressed) {
- haptic_buzz_toggle();
- }
- if (keycode == HPT_MODI && record->event.pressed) {
- haptic_mode_increase();
- }
- if (keycode == HPT_MODD && record->event.pressed) {
- haptic_mode_decrease();
- }
- if (keycode == HPT_DWLI && record->event.pressed) {
- haptic_dwell_increase();
- }
- if (keycode == HPT_DWLD && record->event.pressed) {
- haptic_dwell_decrease();
- }
- if (keycode == HPT_CONT && record->event.pressed) {
- haptic_toggle_continuous();
- }
- if (keycode == HPT_CONI && record->event.pressed) {
- haptic_cont_increase();
- }
- if (keycode == HPT_COND && record->event.pressed) {
- haptic_cont_decrease();
- }
-
- if (haptic_config.enable) {
- if (record->event.pressed) {
- // keypress
- if (haptic_config.feedback < 2) {
- haptic_play();
- }
- } else {
- // keyrelease
- if (haptic_config.feedback > 0) {
- haptic_play();
- }
- }
- }
- return true;
-}
-
-void haptic_shutdown(void) {
-#ifdef SOLENOID_ENABLE
- solenoid_shutdown();
-#endif
-}
diff --git a/drivers/haptic/haptic.h b/drivers/haptic/haptic.h
deleted file mode 100644
index ba8e0d20be..0000000000
--- a/drivers/haptic/haptic.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Copyright 2019 ishtob
- * Driver for haptic feedback written for QMK
- *
- * 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 "quantum.h"
-#ifdef DRV2605L
-# include "DRV2605L.h"
-#endif
-
-#ifndef HAPTIC_FEEDBACK_DEFAULT
-# define HAPTIC_FEEDBACK_DEFAULT 0
-#endif
-#ifndef HAPTIC_MODE_DEFAULT
-# define HAPTIC_MODE_DEFAULT DRV_MODE_DEFAULT
-#endif
-
-/* EEPROM config settings */
-typedef union {
- uint32_t raw;
- struct {
- bool enable : 1;
- uint8_t feedback : 2;
- uint8_t mode : 7;
- bool buzz : 1;
- uint8_t dwell : 7;
- bool cont : 1;
- uint8_t amplitude : 8;
- uint8_t reserved : 5;
- };
-} haptic_config_t;
-
-typedef enum HAPTIC_FEEDBACK {
- KEY_PRESS,
- KEY_PRESS_RELEASE,
- KEY_RELEASE,
- HAPTIC_FEEDBACK_MAX,
-} HAPTIC_FEEDBACK;
-
-bool process_haptic(uint16_t keycode, keyrecord_t *record);
-void haptic_init(void);
-void haptic_task(void);
-void eeconfig_debug_haptic(void);
-void haptic_enable(void);
-void haptic_disable(void);
-void haptic_toggle(void);
-void haptic_feedback_toggle(void);
-void haptic_mode_increase(void);
-void haptic_mode_decrease(void);
-void haptic_mode(uint8_t mode);
-void haptic_reset(void);
-void haptic_set_feedback(uint8_t feedback);
-void haptic_set_mode(uint8_t mode);
-void haptic_set_dwell(uint8_t dwell);
-void haptic_set_buzz(uint8_t buzz);
-void haptic_buzz_toggle(void);
-uint8_t haptic_get_mode(void);
-uint8_t haptic_get_feedback(void);
-void haptic_dwell_increase(void);
-void haptic_dwell_decrease(void);
-void haptic_toggle_continuous(void);
-void haptic_cont_increase(void);
-void haptic_cont_decrease(void);
-
-void haptic_play(void);
-void haptic_shutdown(void);
diff --git a/drivers/haptic/solenoid.c b/drivers/haptic/solenoid.c
index 3e61d5a171..25cf344655 100644
--- a/drivers/haptic/solenoid.c
+++ b/drivers/haptic/solenoid.c
@@ -18,6 +18,7 @@
#include "timer.h"
#include "solenoid.h"
#include "haptic.h"
+#include "gpio.h"
bool solenoid_on = false;
bool solenoid_buzzing = false;
diff --git a/drivers/lcd/st7565.c b/drivers/lcd/st7565.c
new file mode 100644
index 0000000000..49b13c00f1
--- /dev/null
+++ b/drivers/lcd/st7565.c
@@ -0,0 +1,496 @@
+/*
+Copyright 2021
+
+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 "st7565.h"
+
+#include <string.h>
+
+#include "keyboard.h"
+#include "progmem.h"
+#include "timer.h"
+#include "wait.h"
+
+#include ST7565_FONT_H
+
+// Fundamental Commands
+#define CONTRAST 0x81
+#define DISPLAY_ALL_ON 0xA5
+#define DISPLAY_ALL_ON_RESUME 0xA4
+#define NORMAL_DISPLAY 0xA6
+#define INVERT_DISPLAY 0xA7
+#define DISPLAY_ON 0xAF
+#define DISPLAY_OFF 0xAE
+#define NOP 0xE3
+
+// Addressing Setting Commands
+#define PAM_SETCOLUMN_LSB 0x00
+#define PAM_SETCOLUMN_MSB 0x10
+#define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7
+
+// Hardware Configuration Commands
+#define DISPLAY_START_LINE 0x40
+#define SEGMENT_REMAP 0xA0
+#define SEGMENT_REMAP_INV 0xA1
+#define COM_SCAN_INC 0xC0
+#define COM_SCAN_DEC 0xC8
+#define LCD_BIAS_7 0xA3
+#define LCD_BIAS_9 0xA2
+#define RESISTOR_RATIO 0x20
+#define POWER_CONTROL 0x28
+
+// Misc defines
+#ifndef ST7565_BLOCK_COUNT
+# define ST7565_BLOCK_COUNT (sizeof(ST7565_BLOCK_TYPE) * 8)
+#endif
+#ifndef ST7565_BLOCK_SIZE
+# define ST7565_BLOCK_SIZE (ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT)
+#endif
+
+#define ST7565_ALL_BLOCKS_MASK (((((ST7565_BLOCK_TYPE)1 << (ST7565_BLOCK_COUNT - 1)) - 1) << 1) | 1)
+
+#define HAS_FLAGS(bits, flags) ((bits & flags) == flags)
+
+// Display buffer's is the same as the display memory layout
+// this is so we don't end up with rounding errors with
+// parts of the display unusable or don't get cleared correctly
+// and also allows for drawing & inverting
+uint8_t st7565_buffer[ST7565_MATRIX_SIZE];
+uint8_t * st7565_cursor;
+ST7565_BLOCK_TYPE st7565_dirty = 0;
+bool st7565_initialized = false;
+bool st7565_active = false;
+bool st7565_inverted = false;
+display_rotation_t st7565_rotation = DISPLAY_ROTATION_0;
+#if ST7565_TIMEOUT > 0
+uint32_t st7565_timeout;
+#endif
+#if ST7565_UPDATE_INTERVAL > 0
+uint16_t st7565_update_timeout;
+#endif
+
+// Flips the rendering bits for a character at the current cursor position
+static void InvertCharacter(uint8_t *cursor) {
+ const uint8_t *end = cursor + ST7565_FONT_WIDTH;
+ while (cursor < end) {
+ *cursor = ~(*cursor);
+ cursor++;
+ }
+}
+
+bool st7565_init(display_rotation_t rotation) {
+ setPinOutput(ST7565_A0_PIN);
+ writePinHigh(ST7565_A0_PIN);
+ setPinOutput(ST7565_RST_PIN);
+ writePinHigh(ST7565_RST_PIN);
+
+ st7565_rotation = st7565_init_user(rotation);
+
+ spi_init();
+ spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
+
+ st7565_reset();
+
+ st7565_send_cmd(LCD_BIAS_7);
+ if (!HAS_FLAGS(st7565_rotation, DISPLAY_ROTATION_180)) {
+ st7565_send_cmd(SEGMENT_REMAP);
+ st7565_send_cmd(COM_SCAN_DEC);
+ } else {
+ st7565_send_cmd(SEGMENT_REMAP_INV);
+ st7565_send_cmd(COM_SCAN_INC);
+ }
+ st7565_send_cmd(DISPLAY_START_LINE | 0x00);
+ st7565_send_cmd(CONTRAST);
+ st7565_send_cmd(ST7565_CONTRAST);
+ st7565_send_cmd(RESISTOR_RATIO | 0x01);
+ st7565_send_cmd(POWER_CONTROL | 0x04);
+ wait_ms(50);
+ st7565_send_cmd(POWER_CONTROL | 0x06);
+ wait_ms(50);
+ st7565_send_cmd(POWER_CONTROL | 0x07);
+ wait_ms(10);
+ st7565_send_cmd(DISPLAY_ON);
+ st7565_send_cmd(DISPLAY_ALL_ON_RESUME);
+ st7565_send_cmd(NORMAL_DISPLAY);
+
+ spi_stop();
+
+#if ST7565_TIMEOUT > 0
+ st7565_timeout = timer_read32() + ST7565_TIMEOUT;
+#endif
+
+ st7565_clear();
+ st7565_initialized = true;
+ st7565_active = true;
+ return true;
+}
+
+__attribute__((weak)) display_rotation_t st7565_init_user(display_rotation_t rotation) { return rotation; }
+
+void st7565_clear(void) {
+ memset(st7565_buffer, 0, sizeof(st7565_buffer));
+ st7565_cursor = &st7565_buffer[0];
+ st7565_dirty = ST7565_ALL_BLOCKS_MASK;
+}
+
+uint8_t crot(uint8_t a, int8_t n) {
+ const uint8_t mask = 0x7;
+ n &= mask;
+ return a << n | a >> (-n & mask);
+}
+
+void st7565_render(void) {
+ if (!st7565_initialized) {
+ return;
+ }
+
+ // Do we have work to do?
+ st7565_dirty &= ST7565_ALL_BLOCKS_MASK;
+ if (!st7565_dirty) {
+ return;
+ }
+
+ // Find first dirty block
+ uint8_t update_start = 0;
+ while (!(st7565_dirty & ((ST7565_BLOCK_TYPE)1 << update_start))) {
+ ++update_start;
+ }
+
+ // Calculate commands to set memory addressing bounds.
+ uint8_t start_page = ST7565_BLOCK_SIZE * update_start / ST7565_DISPLAY_WIDTH;
+ uint8_t start_column = ST7565_BLOCK_SIZE * update_start % ST7565_DISPLAY_WIDTH;
+ // IC has 132 segment drivers, for panels with less width we need to offset the starting column
+ if (HAS_FLAGS(st7565_rotation, DISPLAY_ROTATION_180)) {
+ start_column += (132 - ST7565_DISPLAY_WIDTH);
+ }
+
+ spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
+
+ st7565_send_cmd(PAM_PAGE_ADDR | start_page);
+ st7565_send_cmd(PAM_SETCOLUMN_LSB | ((ST7565_COLUMN_OFFSET + start_column) & 0x0f));
+ st7565_send_cmd(PAM_SETCOLUMN_MSB | ((ST7565_COLUMN_OFFSET + start_column) >> 4 & 0x0f));
+
+ st7565_send_data(&st7565_buffer[ST7565_BLOCK_SIZE * update_start], ST7565_BLOCK_SIZE);
+
+ // Turn on display if it is off
+ st7565_on();
+
+ // Clear dirty flag
+ st7565_dirty &= ~((ST7565_BLOCK_TYPE)1 << update_start);
+}
+
+void st7565_set_cursor(uint8_t col, uint8_t line) {
+ uint16_t index = line * ST7565_DISPLAY_WIDTH + col * ST7565_FONT_WIDTH;
+
+ // Out of bounds?
+ if (index >= ST7565_MATRIX_SIZE) {
+ index = 0;
+ }
+
+ st7565_cursor = &st7565_buffer[index];
+}
+
+void st7565_advance_page(bool clearPageRemainder) {
+ uint16_t index = st7565_cursor - &st7565_buffer[0];
+ uint8_t remaining = ST7565_DISPLAY_WIDTH - (index % ST7565_DISPLAY_WIDTH);
+
+ if (clearPageRemainder) {
+ // Remaining Char count
+ remaining = remaining / ST7565_FONT_WIDTH;
+
+ // Write empty character until next line
+ while (remaining--) st7565_write_char(' ', false);
+ } else {
+ // Next page index out of bounds?
+ if (index + remaining >= ST7565_MATRIX_SIZE) {
+ index = 0;
+ remaining = 0;
+ }
+
+ st7565_cursor = &st7565_buffer[index + remaining];
+ }
+}
+
+void st7565_advance_char(void) {
+ uint16_t nextIndex = st7565_cursor - &st7565_buffer[0] + ST7565_FONT_WIDTH;
+ uint8_t remainingSpace = ST7565_DISPLAY_WIDTH - (nextIndex % ST7565_DISPLAY_WIDTH);
+
+ // Do we have enough space on the current line for the next character
+ if (remainingSpace < ST7565_FONT_WIDTH) {
+ nextIndex += remainingSpace;
+ }
+
+ // Did we go out of bounds
+ if (nextIndex >= ST7565_MATRIX_SIZE) {
+ nextIndex = 0;
+ }
+
+ // Update cursor position
+ st7565_cursor = &st7565_buffer[nextIndex];
+}
+
+// Main handler that writes character data to the display buffer
+void st7565_write_char(const char data, bool invert) {
+ // Advance to the next line if newline
+ if (data == '\n') {
+ // Old source wrote ' ' until end of line...
+ st7565_advance_page(true);
+ return;
+ }
+
+ if (data == '\r') {
+ st7565_advance_page(false);
+ return;
+ }
+
+ // copy the current render buffer to check for dirty after
+ static uint8_t st7565_temp_buffer[ST7565_FONT_WIDTH];
+ memcpy(&st7565_temp_buffer, st7565_cursor, ST7565_FONT_WIDTH);
+
+ _Static_assert(sizeof(font) >= ((ST7565_FONT_END + 1 - ST7565_FONT_START) * ST7565_FONT_WIDTH), "ST7565_FONT_END references outside array");
+
+ // set the reder buffer data
+ uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index
+ if (cast_data < ST7565_FONT_START || cast_data > ST7565_FONT_END) {
+ memset(st7565_cursor, 0x00, ST7565_FONT_WIDTH);
+ } else {
+ const uint8_t *glyph = &font[(cast_data - ST7565_FONT_START) * ST7565_FONT_WIDTH];
+ memcpy_P(st7565_cursor, glyph, ST7565_FONT_WIDTH);
+ }
+
+ // Invert if needed
+ if (invert) {
+ InvertCharacter(st7565_cursor);
+ }
+
+ // Dirty check
+ if (memcmp(&st7565_temp_buffer, st7565_cursor, ST7565_FONT_WIDTH)) {
+ uint16_t index = st7565_cursor - &st7565_buffer[0];
+ st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE));
+ // Edgecase check if the written data spans the 2 chunks
+ st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << ((index + ST7565_FONT_WIDTH - 1) / ST7565_BLOCK_SIZE));
+ }
+
+ // Finally move to the next char
+ st7565_advance_char();
+}
+
+void st7565_write(const char *data, bool invert) {
+ const char *end = data + strlen(data);
+ while (data < end) {
+ st7565_write_char(*data, invert);
+ data++;
+ }
+}
+
+void st7565_write_ln(const char *data, bool invert) {
+ st7565_write(data, invert);
+ st7565_advance_page(true);
+}
+
+void st7565_pan(bool left) {
+ uint16_t i = 0;
+ for (uint16_t y = 0; y < ST7565_DISPLAY_HEIGHT / 8; y++) {
+ if (left) {
+ for (uint16_t x = 0; x < ST7565_DISPLAY_WIDTH - 1; x++) {
+ i = y * ST7565_DISPLAY_WIDTH + x;
+ st7565_buffer[i] = st7565_buffer[i + 1];
+ }
+ } else {
+ for (uint16_t x = ST7565_DISPLAY_WIDTH - 1; x > 0; x--) {
+ i = y * ST7565_DISPLAY_WIDTH + x;
+ st7565_buffer[i] = st7565_buffer[i - 1];
+ }
+ }
+ }
+ st7565_dirty = ST7565_ALL_BLOCKS_MASK;
+}
+
+display_buffer_reader_t st7565_read_raw(uint16_t start_index) {
+ if (start_index > ST7565_MATRIX_SIZE) start_index = ST7565_MATRIX_SIZE;
+ display_buffer_reader_t ret_reader;
+ ret_reader.current_element = &st7565_buffer[start_index];
+ ret_reader.remaining_element_count = ST7565_MATRIX_SIZE - start_index;
+ return ret_reader;
+}
+
+void st7565_write_raw_byte(const char data, uint16_t index) {
+ if (index > ST7565_MATRIX_SIZE) index = ST7565_MATRIX_SIZE;
+ if (st7565_buffer[index] == data) return;
+ st7565_buffer[index] = data;
+ st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE));
+}
+
+void st7565_write_raw(const char *data, uint16_t size) {
+ uint16_t cursor_start_index = st7565_cursor - &st7565_buffer[0];
+ if ((size + cursor_start_index) > ST7565_MATRIX_SIZE) size = ST7565_MATRIX_SIZE - cursor_start_index;
+ for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) {
+ uint8_t c = *data++;
+ if (st7565_buffer[i] == c) continue;
+ st7565_buffer[i] = c;
+ st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (i / ST7565_BLOCK_SIZE));
+ }
+}
+
+void st7565_write_pixel(uint8_t x, uint8_t y, bool on) {
+ if (x >= ST7565_DISPLAY_WIDTH) {
+ return;
+ }
+ uint16_t index = x + (y / 8) * ST7565_DISPLAY_WIDTH;
+ if (index >= ST7565_MATRIX_SIZE) {
+ return;
+ }
+ uint8_t data = st7565_buffer[index];
+ if (on) {
+ data |= (1 << (y % 8));
+ } else {
+ data &= ~(1 << (y % 8));
+ }
+ if (st7565_buffer[index] != data) {
+ st7565_buffer[index] = data;
+ st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE));
+ }
+}
+
+#if defined(__AVR__)
+void st7565_write_P(const char *data, bool invert) {
+ uint8_t c = pgm_read_byte(data);
+ while (c != 0) {
+ st7565_write_char(c, invert);
+ c = pgm_read_byte(++data);
+ }
+}
+
+void st7565_write_ln_P(const char *data, bool invert) {
+ st7565_write_P(data, invert);
+ st7565_advance_page(true);
+}
+
+void st7565_write_raw_P(const char *data, uint16_t size) {
+ uint16_t cursor_start_index = st7565_cursor - &st7565_buffer[0];
+ if ((size + cursor_start_index) > ST7565_MATRIX_SIZE) size = ST7565_MATRIX_SIZE - cursor_start_index;
+ for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) {
+ uint8_t c = pgm_read_byte(data++);
+ if (st7565_buffer[i] == c) continue;
+ st7565_buffer[i] = c;
+ st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (i / ST7565_BLOCK_SIZE));
+ }
+}
+#endif // defined(__AVR__)
+
+bool st7565_on(void) {
+ if (!st7565_initialized) {
+ return st7565_active;
+ }
+
+#if ST7565_TIMEOUT > 0
+ st7565_timeout = timer_read32() + ST7565_TIMEOUT;
+#endif
+
+ if (!st7565_active) {
+ spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
+ st7565_send_cmd(DISPLAY_ON);
+ spi_stop();
+ st7565_active = true;
+ st7565_on_user();
+ }
+ return st7565_active;
+}
+
+__attribute__((weak)) void st7565_on_user(void) {}
+
+bool st7565_off(void) {
+ if (!st7565_initialized) {
+ return !st7565_active;
+ }
+
+ if (st7565_active) {
+ spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
+ st7565_send_cmd(DISPLAY_OFF);
+ spi_stop();
+ st7565_active = false;
+ st7565_off_user();
+ }
+ return !st7565_active;
+}
+
+__attribute__((weak)) void st7565_off_user(void) {}
+
+bool st7565_is_on(void) { return st7565_active; }
+
+bool st7565_invert(bool invert) {
+ if (!st7565_initialized) {
+ return st7565_inverted;
+ }
+
+ if (invert != st7565_inverted) {
+ spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
+ st7565_send_cmd(invert ? INVERT_DISPLAY : NORMAL_DISPLAY);
+ spi_stop();
+ st7565_inverted = invert;
+ }
+ return st7565_inverted;
+}
+
+uint8_t st7565_max_chars(void) { return ST7565_DISPLAY_WIDTH / ST7565_FONT_WIDTH; }
+
+uint8_t st7565_max_lines(void) { return ST7565_DISPLAY_HEIGHT / ST7565_FONT_HEIGHT; }
+
+void st7565_task(void) {
+ if (!st7565_initialized) {
+ return;
+ }
+
+#if ST7565_UPDATE_INTERVAL > 0
+ if (timer_elapsed(st7565_update_timeout) >= ST7565_UPDATE_INTERVAL) {
+ st7565_update_timeout = timer_read();
+ st7565_set_cursor(0, 0);
+ st7565_task_user();
+ }
+#else
+ st7565_set_cursor(0, 0);
+ st7565_task_user();
+#endif
+
+ // Smart render system, no need to check for dirty
+ st7565_render();
+
+ // Display timeout check
+#if ST7565_TIMEOUT > 0
+ if (st7565_active && timer_expired32(timer_read32(), st7565_timeout)) {
+ st7565_off();
+ }
+#endif
+}
+
+__attribute__((weak)) void st7565_task_user(void) {}
+
+void st7565_reset(void) {
+ writePinLow(ST7565_RST_PIN);
+ wait_ms(20);
+ writePinHigh(ST7565_RST_PIN);
+ wait_ms(20);
+}
+
+spi_status_t st7565_send_cmd(uint8_t cmd) {
+ writePinLow(ST7565_A0_PIN);
+ return spi_write(cmd);
+}
+
+spi_status_t st7565_send_data(uint8_t *data, uint16_t length) {
+ writePinHigh(ST7565_A0_PIN);
+ return spi_transmit(data, length);
+}
diff --git a/drivers/lcd/st7565.h b/drivers/lcd/st7565.h
new file mode 100644
index 0000000000..d453dbe6da
--- /dev/null
+++ b/drivers/lcd/st7565.h
@@ -0,0 +1,219 @@
+/*
+Copyright 2021
+
+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 "spi_master.h"
+
+#ifndef ST7565_DISPLAY_WIDTH
+# define ST7565_DISPLAY_WIDTH 128
+#endif
+#ifndef ST7565_DISPLAY_HEIGHT
+# define ST7565_DISPLAY_HEIGHT 32
+#endif
+#ifndef ST7565_MATRIX_SIZE
+# define ST7565_MATRIX_SIZE (ST7565_DISPLAY_HEIGHT / 8 * ST7565_DISPLAY_WIDTH) // 1024 (compile time mathed)
+#endif
+#ifndef ST7565_BLOCK_TYPE
+# define ST7565_BLOCK_TYPE uint16_t
+#endif
+#ifndef ST7565_BLOCK_COUNT
+# define ST7565_BLOCK_COUNT (sizeof(ST7565_BLOCK_TYPE) * 8) // 32 (compile time mathed)
+#endif
+#ifndef ST7565_BLOCK_SIZE
+# define ST7565_BLOCK_SIZE (ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT) // 32 (compile time mathed)
+#endif
+
+// the column address corresponding to the first column in the display hardware
+#if !defined(ST7565_COLUMN_OFFSET)
+# define ST7565_COLUMN_OFFSET 0
+#endif
+
+// spi clock divisor
+#if !defined(ST7565_SPI_CLK_DIVISOR)
+# define ST7565_SPI_CLK_DIVISOR 4
+#endif
+
+// Custom font file to use
+#if !defined(ST7565_FONT_H)
+# define ST7565_FONT_H "glcdfont.c"
+#endif
+// unsigned char value of the first character in the font file
+#if !defined(ST7565_FONT_START)
+# define ST7565_FONT_START 0
+#endif
+// unsigned char value of the last character in the font file
+#if !defined(ST7565_FONT_END)
+# define ST7565_FONT_END 223
+#endif
+// Font render width
+#if !defined(ST7565_FONT_WIDTH)
+# define ST7565_FONT_WIDTH 6
+#endif
+// Font render height
+#if !defined(ST7565_FONT_HEIGHT)
+# define ST7565_FONT_HEIGHT 8
+#endif
+// Default contrast level
+#if !defined(ST7565_CONTRAST)
+# define ST7565_CONTRAST 32
+#endif
+
+#if !defined(ST7565_TIMEOUT)
+# if defined(ST7565_DISABLE_TIMEOUT)
+# define ST7565_TIMEOUT 0
+# else
+# define ST7565_TIMEOUT 60000
+# endif
+#endif
+
+#if !defined(ST7565_UPDATE_INTERVAL) && defined(SPLIT_KEYBOARD)
+# define ST7565_UPDATE_INTERVAL 50
+#endif
+
+typedef struct __attribute__((__packed__)) {
+ uint8_t *current_element;
+ uint16_t remaining_element_count;
+} display_buffer_reader_t;
+
+// Rotation enum values are flags
+typedef enum { DISPLAY_ROTATION_0, DISPLAY_ROTATION_180 } display_rotation_t;
+
+// Initialize the display, rotating the rendered output based on the define passed in.
+// Returns true if the display was initialized successfully
+bool st7565_init(display_rotation_t rotation);
+
+// Called at the start of st7565_init, weak function overridable by the user
+// rotation - the value passed into st7565_init
+// Return new display_rotation_t if you want to override default rotation
+display_rotation_t st7565_init_user(display_rotation_t rotation);
+
+// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
+void st7565_clear(void);
+
+// Renders the dirty chunks of the buffer to display
+void st7565_render(void);
+
+// Moves cursor to character position indicated by column and line, wraps if out of bounds
+// Max column denoted by 'st7565_max_chars()' and max lines by 'st7565_max_lines()' functions
+void st7565_set_cursor(uint8_t col, uint8_t line);
+
+// Advances the cursor to the next page, writing ' ' if true
+// Wraps to the begining when out of bounds
+void st7565_advance_page(bool clearPageRemainder);
+
+// Moves the cursor forward 1 character length
+// Advance page if there is not enough room for the next character
+// Wraps to the begining when out of bounds
+void st7565_advance_char(void);
+
+// Writes a single character to the buffer at current cursor position
+// Advances the cursor while writing, inverts the pixels if true
+// Main handler that writes character data to the display buffer
+void st7565_write_char(const char data, bool invert);
+
+// Writes a string to the buffer at current cursor position
+// Advances the cursor while writing, inverts the pixels if true
+void st7565_write(const char *data, bool invert);
+
+// Writes a string to the buffer at current cursor position
+// Advances the cursor while writing, inverts the pixels if true
+// Advances the cursor to the next page, wiring ' ' to the remainder of the current page
+void st7565_write_ln(const char *data, bool invert);
+
+// Pans the buffer to the right (or left by passing true) by moving contents of the buffer
+// Useful for moving the screen in preparation for new drawing
+void st7565_pan(bool left);
+
+// Returns a pointer to the requested start index in the buffer plus remaining
+// buffer length as struct
+display_buffer_reader_t st7565_read_raw(uint16_t start_index);
+
+// Writes a string to the buffer at current cursor position
+void st7565_write_raw(const char *data, uint16_t size);
+
+// Writes a single byte into the buffer at the specified index
+void st7565_write_raw_byte(const char data, uint16_t index);
+
+// Sets a specific pixel on or off
+// Coordinates start at top-left and go right and down for positive x and y
+void st7565_write_pixel(uint8_t x, uint8_t y, bool on);
+
+#if defined(__AVR__)
+// Writes a PROGMEM string to the buffer at current cursor position
+// Advances the cursor while writing, inverts the pixels if true
+// Remapped to call 'void st7565_write(const char *data, bool invert);' on ARM
+void st7565_write_P(const char *data, bool invert);
+
+// Writes a PROGMEM string to the buffer at current cursor position
+// Advances the cursor while writing, inverts the pixels if true
+// Advances the cursor to the next page, wiring ' ' to the remainder of the current page
+// Remapped to call 'void st7565_write_ln(const char *data, bool invert);' on ARM
+void st7565_write_ln_P(const char *data, bool invert);
+
+// Writes a PROGMEM string to the buffer at current cursor position
+void st7565_write_raw_P(const char *data, uint16_t size);
+#else
+# define st7565_write_P(data, invert) st7565_write(data, invert)
+# define st7565_write_ln_P(data, invert) st7565_write_ln(data, invert)
+# define st7565_write_raw_P(data, size) st7565_write_raw(data, size)
+#endif // defined(__AVR__)
+
+// Can be used to manually turn on the screen if it is off
+// Returns true if the screen was on or turns on
+bool st7565_on(void);
+
+// Called when st7565_on() turns on the screen, weak function overridable by the user
+// Not called if the screen is already on
+void st7565_on_user(void);
+
+// Can be used to manually turn off the screen if it is on
+// Returns true if the screen was off or turns off
+bool st7565_off(void);
+
+// Called when st7565_off() turns off the screen, weak function overridable by the user
+// Not called if the screen is already off
+void st7565_off_user(void);
+
+// Returns true if the screen is currently on, false if it is
+// not
+bool st7565_is_on(void);
+
+// Basically it's st7565_render, but with timeout management and st7565_task_user calling!
+void st7565_task(void);
+
+// Called at the start of st7565_task, weak function overridable by the user
+void st7565_task_user(void);
+
+// Inverts the display
+// Returns true if the screen was or is inverted
+bool st7565_invert(bool invert);
+
+// Returns the maximum number of characters that will fit on a line
+uint8_t st7565_max_chars(void);
+
+// Returns the maximum number of lines that will fit on the display
+uint8_t st7565_max_lines(void);
+
+void st7565_reset(void);
+
+spi_status_t st7565_send_cmd(uint8_t cmd);
+
+spi_status_t st7565_send_data(uint8_t *data, uint16_t length);
diff --git a/drivers/apa102/apa102.c b/drivers/led/apa102.c
index 7396dc3c55..7396dc3c55 100644
--- a/drivers/apa102/apa102.c
+++ b/drivers/led/apa102.c
diff --git a/drivers/apa102/apa102.h b/drivers/led/apa102.h
index 58cf020c1e..58cf020c1e 100644
--- a/drivers/apa102/apa102.h
+++ b/drivers/led/apa102.h
diff --git a/drivers/led/aw20216.c b/drivers/led/aw20216.c
new file mode 100644
index 0000000000..c608c0ab44
--- /dev/null
+++ b/drivers/led/aw20216.c
@@ -0,0 +1,141 @@
+/* Copyright 2021 Jasper Chan
+ *
+ * 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 "aw20216.h"
+#include "spi_master.h"
+
+/* The AW20216 appears to be somewhat similar to the IS31FL743, although quite
+ * a few things are different, such as the command byte format and page ordering.
+ * The LED addresses start from 0x00 instead of 0x01.
+ */
+#define AWINIC_ID 0b1010 << 4
+
+#define AW_PAGE_FUNCTION 0x00 << 1 // PG0, Function registers
+#define AW_PAGE_PWM 0x01 << 1 // PG1, LED PWM control
+#define AW_PAGE_SCALING 0x02 << 1 // PG2, LED current scaling control
+#define AW_PAGE_PATCHOICE 0x03 << 1 // PG3, Pattern choice?
+#define AW_PAGE_PWMSCALING 0x04 << 1 // PG4, LED PWM + Scaling control?
+
+#define AW_WRITE 0
+#define AW_READ 1
+
+#define AW_REG_CONFIGURATION 0x00 // PG0
+#define AW_REG_GLOBALCURRENT 0x01 // PG0
+
+// Default value of AW_REG_CONFIGURATION
+// D7:D4 = 1011, SWSEL (SW1~SW12 active)
+// D3 = 0?, reserved (apparently this should be 1 but it doesn't seem to matter)
+// D2:D1 = 00, OSDE (open/short detection enable)
+// D0 = 0, CHIPEN (write 1 to enable LEDs when hardware enable pulled high)
+#define AW_CONFIG_DEFAULT 0b10110000
+#define AW_CHIPEN 1
+
+#define AW_PWM_REGISTER_COUNT 216
+
+#ifndef AW_SCALING_MAX
+# define AW_SCALING_MAX 150
+#endif
+
+#ifndef AW_GLOBAL_CURRENT_MAX
+# define AW_GLOBAL_CURRENT_MAX 150
+#endif
+
+#ifndef AW_SPI_DIVISOR
+# define AW_SPI_DIVISOR 4
+#endif
+
+uint8_t g_pwm_buffer[DRIVER_COUNT][AW_PWM_REGISTER_COUNT];
+bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
+
+bool AW20216_write(pin_t cs_pin, uint8_t page, uint8_t reg, uint8_t* data, uint8_t len) {
+ static uint8_t s_spi_transfer_buffer[2] = {0};
+
+ if (!spi_start(cs_pin, false, 0, AW_SPI_DIVISOR)) {
+ spi_stop();
+ return false;
+ }
+
+ s_spi_transfer_buffer[0] = (AWINIC_ID | page | AW_WRITE);
+ s_spi_transfer_buffer[1] = reg;
+
+ if (spi_transmit(s_spi_transfer_buffer, 2) != SPI_STATUS_SUCCESS) {
+ spi_stop();
+ return false;
+ }
+
+ if (spi_transmit(data, len) != SPI_STATUS_SUCCESS) {
+ spi_stop();
+ return false;
+ }
+
+ spi_stop();
+ return true;
+}
+
+static inline bool AW20216_write_register(pin_t cs_pin, uint8_t page, uint8_t reg, uint8_t value) {
+ // Little wrapper so callers need not care about sending a buffer
+ return AW20216_write(cs_pin, page, reg, &value, 1);
+}
+
+static void AW20216_init_scaling(pin_t cs_pin) {
+ // Set constant current to the max, control brightness with PWM
+ for (uint8_t i = 0; i < AW_PWM_REGISTER_COUNT; i++) {
+ AW20216_write_register(cs_pin, AW_PAGE_SCALING, i, AW_SCALING_MAX);
+ }
+}
+
+static inline void AW20216_init_current_limit(pin_t cs_pin) {
+ // Push config
+ AW20216_write_register(cs_pin, AW_PAGE_FUNCTION, AW_REG_GLOBALCURRENT, AW_GLOBAL_CURRENT_MAX);
+}
+
+static inline void AW20216_soft_enable(pin_t cs_pin) {
+ // Push config
+ AW20216_write_register(cs_pin, AW_PAGE_FUNCTION, AW_REG_CONFIGURATION, AW_CONFIG_DEFAULT | AW_CHIPEN);
+}
+
+void AW20216_init(pin_t cs_pin, pin_t en_pin) {
+ setPinOutput(en_pin);
+ writePinHigh(en_pin);
+
+ // Drivers should start with all scaling and PWM registers as off
+ AW20216_init_current_limit(cs_pin);
+ AW20216_init_scaling(cs_pin);
+
+ AW20216_soft_enable(cs_pin);
+}
+
+void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+ aw_led led = g_aw_leds[index];
+
+ g_pwm_buffer[led.driver][led.r] = red;
+ g_pwm_buffer[led.driver][led.g] = green;
+ g_pwm_buffer[led.driver][led.b] = blue;
+ g_pwm_buffer_update_required[led.driver] = true;
+}
+
+void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+ for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
+ AW20216_set_color(i, red, green, blue);
+ }
+}
+
+void AW20216_update_pwm_buffers(pin_t cs_pin, uint8_t index) {
+ if (g_pwm_buffer_update_required[index]) {
+ AW20216_write(cs_pin, AW_PAGE_PWM, 0, g_pwm_buffer[index], AW_PWM_REGISTER_COUNT);
+ }
+ g_pwm_buffer_update_required[index] = false;
+}
diff --git a/drivers/led/aw20216.h b/drivers/led/aw20216.h
new file mode 100644
index 0000000000..97ac6dc5bf
--- /dev/null
+++ b/drivers/led/aw20216.h
@@ -0,0 +1,253 @@
+/* Copyright 2021 Jasper Chan (Gigahawk)
+ *
+ * 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 "progmem.h"
+#include "gpio.h"
+
+typedef struct aw_led {
+ uint8_t driver : 2;
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+} aw_led;
+
+extern const aw_led __flash g_aw_leds[DRIVER_LED_TOTAL];
+
+void AW20216_init(pin_t cs_pin, pin_t en_pin);
+void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
+void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
+void AW20216_update_pwm_buffers(pin_t cs_pin, uint8_t index);
+
+#define CS1_SW1 0x00
+#define CS2_SW1 0x01
+#define CS3_SW1 0x02
+#define CS4_SW1 0x03
+#define CS5_SW1 0x04
+#define CS6_SW1 0x05
+#define CS7_SW1 0x06
+#define CS8_SW1 0x07
+#define CS9_SW1 0x08
+#define CS10_SW1 0x09
+#define CS11_SW1 0x0A
+#define CS12_SW1 0x0B
+#define CS13_SW1 0x0C
+#define CS14_SW1 0x0D
+#define CS15_SW1 0x0E
+#define CS16_SW1 0x0F
+#define CS17_SW1 0x10
+#define CS18_SW1 0x11
+#define CS1_SW2 0x12
+#define CS2_SW2 0x13
+#define CS3_SW2 0x14
+#define CS4_SW2 0x15
+#define CS5_SW2 0x16
+#define CS6_SW2 0x17
+#define CS7_SW2 0x18
+#define CS8_SW2 0x19
+#define CS9_SW2 0x1A
+#define CS10_SW2 0x1B
+#define CS11_SW2 0x1C
+#define CS12_SW2 0x1D
+#define CS13_SW2 0x1E
+#define CS14_SW2 0x1F
+#define CS15_SW2 0x20
+#define CS16_SW2 0x21
+#define CS17_SW2 0x22
+#define CS18_SW2 0x23
+#define CS1_SW3 0x24
+#define CS2_SW3 0x25
+#define CS3_SW3 0x26
+#define CS4_SW3 0x27
+#define CS5_SW3 0x28
+#define CS6_SW3 0x29
+#define CS7_SW3 0x2A
+#define CS8_SW3 0x2B
+#define CS9_SW3 0x2C
+#define CS10_SW3 0x2D
+#define CS11_SW3 0x2E
+#define CS12_SW3 0x2F
+#define CS13_SW3 0x30
+#define CS14_SW3 0x31
+#define CS15_SW3 0x32
+#define CS16_SW3 0x33
+#define CS17_SW3 0x34
+#define CS18_SW3 0x35
+#define CS1_SW4 0x36
+#define CS2_SW4 0x37
+#define CS3_SW4 0x38
+#define CS4_SW4 0x39
+#define CS5_SW4 0x3A
+#define CS6_SW4 0x3B
+#define CS7_SW4 0x3C
+#define CS8_SW4 0x3D
+#define CS9_SW4 0x3E
+#define CS10_SW4 0x3F
+#define CS11_SW4 0x40
+#define CS12_SW4 0x41
+#define CS13_SW4 0x42
+#define CS14_SW4 0x43
+#define CS15_SW4 0x44
+#define CS16_SW4 0x45
+#define CS17_SW4 0x46
+#define CS18_SW4 0x47
+#define CS1_SW5 0x48
+#define CS2_SW5 0x49
+#define CS3_SW5 0x4A
+#define CS4_SW5 0x4B
+#define CS5_SW5 0x4C
+#define CS6_SW5 0x4D
+#define CS7_SW5 0x4E
+#define CS8_SW5 0x4F
+#define CS9_SW5 0x50
+#define CS10_SW5 0x51
+#define CS11_SW5 0x52
+#define CS12_SW5 0x53
+#define CS13_SW5 0x54
+#define CS14_SW5 0x55
+#define CS15_SW5 0x56
+#define CS16_SW5 0x57
+#define CS17_SW5 0x58
+#define CS18_SW5 0x59
+#define CS1_SW6 0x5A
+#define CS2_SW6 0x5B
+#define CS3_SW6 0x5C
+#define CS4_SW6 0x5D
+#define CS5_SW6 0x5E
+#define CS6_SW6 0x5F
+#define CS7_SW6 0x60
+#define CS8_SW6 0x61
+#define CS9_SW6 0x62
+#define CS10_SW6 0x63
+#define CS11_SW6 0x64
+#define CS12_SW6 0x65
+#define CS13_SW6 0x66
+#define CS14_SW6 0x67
+#define CS15_SW6 0x68
+#define CS16_SW6 0x69
+#define CS17_SW6 0x6A
+#define CS18_SW6 0x6B
+#define CS1_SW7 0x6C
+#define CS2_SW7 0x6D
+#define CS3_SW7 0x6E
+#define CS4_SW7 0x6F
+#define CS5_SW7 0x70
+#define CS6_SW7 0x71
+#define CS7_SW7 0x72
+#define CS8_SW7 0x73
+#define CS9_SW7 0x74
+#define CS10_SW7 0x75
+#define CS11_SW7 0x76
+#define CS12_SW7 0x77
+#define CS13_SW7 0x78
+#define CS14_SW7 0x79
+#define CS15_SW7 0x7A
+#define CS16_SW7 0x7B
+#define CS17_SW7 0x7C
+#define CS18_SW7 0x7D
+#define CS1_SW8 0x7E
+#define CS2_SW8 0x7F
+#define CS3_SW8 0x80
+#define CS4_SW8 0x81
+#define CS5_SW8 0x82
+#define CS6_SW8 0x83
+#define CS7_SW8 0x84
+#define CS8_SW8 0x85
+#define CS9_SW8 0x86
+#define CS10_SW8 0x87
+#define CS11_SW8 0x88
+#define CS12_SW8 0x89
+#define CS13_SW8 0x8A
+#define CS14_SW8 0x8B
+#define CS15_SW8 0x8C
+#define CS16_SW8 0x8D
+#define CS17_SW8 0x8E
+#define CS18_SW8 0x8F
+#define CS1_SW9 0x90
+#define CS2_SW9 0x91
+#define CS3_SW9 0x92
+#define CS4_SW9 0x93
+#define CS5_SW9 0x94
+#define CS6_SW9 0x95
+#define CS7_SW9 0x96
+#define CS8_SW9 0x97
+#define CS9_SW9 0x98
+#define CS10_SW9 0x99
+#define CS11_SW9 0x9A
+#define CS12_SW9 0x9B
+#define CS13_SW9 0x9C
+#define CS14_SW9 0x9D
+#define CS15_SW9 0x9E
+#define CS16_SW9 0x9F
+#define CS17_SW9 0xA0
+#define CS18_SW9 0xA1
+#define CS1_SW10 0xA2
+#define CS2_SW10 0xA3
+#define CS3_SW10 0xA4
+#define CS4_SW10 0xA5
+#define CS5_SW10 0xA6
+#define CS6_SW10 0xA7
+#define CS7_SW10 0xA8
+#define CS8_SW10 0xA9
+#define CS9_SW10 0xAA
+#define CS10_SW10 0xAB
+#define CS11_SW10 0xAC
+#define CS12_SW10 0xAD
+#define CS13_SW10 0xAE
+#define CS14_SW10 0xAF
+#define CS15_SW10 0xB0
+#define CS16_SW10 0xB1
+#define CS17_SW10 0xB2
+#define CS18_SW10 0xB3
+#define CS1_SW11 0xB4
+#define CS2_SW11 0xB5
+#define CS3_SW11 0xB6
+#define CS4_SW11 0xB7
+#define CS5_SW11 0xB8
+#define CS6_SW11 0xB9
+#define CS7_SW11 0xBA
+#define CS8_SW11 0xBB
+#define CS9_SW11 0xBC
+#define CS10_SW11 0xBD
+#define CS11_SW11 0xBE
+#define CS12_SW11 0xBF
+#define CS13_SW11 0xC0
+#define CS14_SW11 0xC1
+#define CS15_SW11 0xC2
+#define CS16_SW11 0xC3
+#define CS17_SW11 0xC4
+#define CS18_SW11 0xC5
+#define CS1_SW12 0xC6
+#define CS2_SW12 0xC7
+#define CS3_SW12 0xC8
+#define CS4_SW12 0xC9
+#define CS5_SW12 0xCA
+#define CS6_SW12 0xCB
+#define CS7_SW12 0xCC
+#define CS8_SW12 0xCD
+#define CS9_SW12 0xCE
+#define CS10_SW12 0xCF
+#define CS11_SW12 0xD0
+#define CS12_SW12 0xD1
+#define CS13_SW12 0xD2
+#define CS14_SW12 0xD3
+#define CS15_SW12 0xD4
+#define CS16_SW12 0xD5
+#define CS17_SW12 0xD6
+#define CS18_SW12 0xD7
diff --git a/drivers/issi/is31fl3218.c b/drivers/led/issi/is31fl3218.c
index d43863ac4b..d43863ac4b 100644
--- a/drivers/issi/is31fl3218.c
+++ b/drivers/led/issi/is31fl3218.c
diff --git a/drivers/issi/is31fl3218.h b/drivers/led/issi/is31fl3218.h
index fa760da191..fa760da191 100644
--- a/drivers/issi/is31fl3218.h
+++ b/drivers/led/issi/is31fl3218.h
diff --git a/drivers/issi/is31fl3731-simple.c b/drivers/led/issi/is31fl3731-simple.c
index d295772f5e..d295772f5e 100644
--- a/drivers/issi/is31fl3731-simple.c
+++ b/drivers/led/issi/is31fl3731-simple.c
diff --git a/drivers/issi/is31fl3731-simple.h b/drivers/led/issi/is31fl3731-simple.h
index 9665d6ed35..ecde31eed5 100644
--- a/drivers/issi/is31fl3731-simple.h
+++ b/drivers/led/issi/is31fl3731-simple.h
@@ -20,13 +20,14 @@
#include <stdint.h>
#include <stdbool.h>
+#include "progmem.h"
typedef struct is31_led {
uint8_t driver : 2;
uint8_t v;
} __attribute__((packed)) is31_led;
-extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3731_init(uint8_t addr);
void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/issi/is31fl3731.c b/drivers/led/issi/is31fl3731.c
index 110bdc1be4..110bdc1be4 100644
--- a/drivers/issi/is31fl3731.c
+++ b/drivers/led/issi/is31fl3731.c
diff --git a/drivers/issi/is31fl3731.h b/drivers/led/issi/is31fl3731.h
index 19e8e6251f..803ea3ea12 100644
--- a/drivers/issi/is31fl3731.h
+++ b/drivers/led/issi/is31fl3731.h
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "progmem.h"
typedef struct is31_led {
uint8_t driver : 2;
@@ -27,7 +28,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3731_init(uint8_t addr);
void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/issi/is31fl3733.c b/drivers/led/issi/is31fl3733.c
index d99e5339c9..d99e5339c9 100644
--- a/drivers/issi/is31fl3733.c
+++ b/drivers/led/issi/is31fl3733.c
diff --git a/drivers/issi/is31fl3733.h b/drivers/led/issi/is31fl3733.h
index 603d505a13..64fd38eb19 100644
--- a/drivers/issi/is31fl3733.h
+++ b/drivers/led/issi/is31fl3733.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "progmem.h"
typedef struct is31_led {
uint8_t driver : 2;
@@ -28,7 +29,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3733_init(uint8_t addr, uint8_t sync);
bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/issi/is31fl3736.c b/drivers/led/issi/is31fl3736.c
index 7dece1b1eb..7dece1b1eb 100644
--- a/drivers/issi/is31fl3736.c
+++ b/drivers/led/issi/is31fl3736.c
diff --git a/drivers/issi/is31fl3736.h b/drivers/led/issi/is31fl3736.h
index e48e31c279..c956c87f7c 100644
--- a/drivers/issi/is31fl3736.h
+++ b/drivers/led/issi/is31fl3736.h
@@ -18,6 +18,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "progmem.h"
// Simple interface option.
// If these aren't defined, just define them to make it compile
@@ -37,7 +38,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3736_init(uint8_t addr);
void IS31FL3736_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/issi/is31fl3737.c b/drivers/led/issi/is31fl3737.c
index 8647c93cc1..0bb4ddd425 100644
--- a/drivers/issi/is31fl3737.c
+++ b/drivers/led/issi/is31fl3737.c
@@ -65,11 +65,12 @@ uint8_t g_twi_transfer_buffer[20];
// We could optimize this and take out the unused registers from these
// buffers and the transfers in IS31FL3737_write_pwm_buffer() but it's
// probably not worth the extra complexity.
+
uint8_t g_pwm_buffer[DRIVER_COUNT][192];
-bool g_pwm_buffer_update_required = false;
+bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
-uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}};
-bool g_led_control_registers_update_required = false;
+uint8_t g_led_control_registers[DRIVER_COUNT][24] = {0};
+bool g_led_control_registers_update_required[DRIVER_COUNT] = {false};
void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
g_twi_transfer_buffer[0] = reg;
@@ -155,10 +156,10 @@ void IS31FL3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
if (index >= 0 && index < DRIVER_LED_TOTAL) {
is31_led led = g_is31_leds[index];
- g_pwm_buffer[led.driver][led.r] = red;
- g_pwm_buffer[led.driver][led.g] = green;
- g_pwm_buffer[led.driver][led.b] = blue;
- g_pwm_buffer_update_required = true;
+ g_pwm_buffer[led.driver][led.r] = red;
+ g_pwm_buffer[led.driver][led.g] = green;
+ g_pwm_buffer[led.driver][led.b] = blue;
+ g_pwm_buffer_update_required[led.driver] = true;
}
}
@@ -194,30 +195,28 @@ void IS31FL3737_set_led_control_register(uint8_t index, bool red, bool green, bo
g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
}
- g_led_control_registers_update_required = true;
+ g_led_control_registers_update_required[led.driver] = true;
}
-void IS31FL3737_update_pwm_buffers(uint8_t addr1, uint8_t addr2) {
- if (g_pwm_buffer_update_required) {
+void IS31FL3737_update_pwm_buffers(uint8_t addr, uint8_t index) {
+ if (g_pwm_buffer_update_required[index]) {
// Firstly we need to unlock the command register and select PG1
- IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
- IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
+ IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
+ IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
- IS31FL3737_write_pwm_buffer(addr1, g_pwm_buffer[0]);
- // IS31FL3737_write_pwm_buffer(addr2, g_pwm_buffer[1]);
+ IS31FL3737_write_pwm_buffer(addr, g_pwm_buffer[index]);
}
- g_pwm_buffer_update_required = false;
+ g_pwm_buffer_update_required[index] = false;
}
-void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2) {
- if (g_led_control_registers_update_required) {
+void IS31FL3737_update_led_control_registers(uint8_t addr, uint8_t index) {
+ if (g_led_control_registers_update_required[index]) {
// Firstly we need to unlock the command register and select PG0
- IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
- IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
+ IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
+ IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
for (int i = 0; i < 24; i++) {
- IS31FL3737_write_register(addr1, i, g_led_control_registers[0][i]);
- // IS31FL3737_write_register(addr2, i, g_led_control_registers[1][i]);
+ IS31FL3737_write_register(addr, i, g_led_control_registers[index][i]);
}
- g_led_control_registers_update_required = false;
}
+ g_led_control_registers_update_required[index] = false;
}
diff --git a/drivers/issi/is31fl3737.h b/drivers/led/issi/is31fl3737.h
index a1d2281778..06886e9c9b 100644
--- a/drivers/issi/is31fl3737.h
+++ b/drivers/led/issi/is31fl3737.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "progmem.h"
typedef struct is31_led {
uint8_t driver : 2;
@@ -28,7 +29,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3737_init(uint8_t addr);
void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/issi/is31fl3741.c b/drivers/led/issi/is31fl3741.c
index 1b533c9b6a..24a273514e 100644
--- a/drivers/issi/is31fl3741.c
+++ b/drivers/led/issi/is31fl3741.c
@@ -73,7 +73,7 @@ uint8_t g_twi_transfer_buffer[20] = {0xFF};
// buffers and the transfers in IS31FL3741_write_pwm_buffer() but it's
// probably not worth the extra complexity.
uint8_t g_pwm_buffer[DRIVER_COUNT][ISSI_MAX_LEDS];
-bool g_pwm_buffer_update_required = false;
+bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
bool g_scaling_registers_update_required[DRIVER_COUNT] = {false};
uint8_t g_scaling_registers[DRIVER_COUNT][ISSI_MAX_LEDS];
@@ -169,10 +169,10 @@ void IS31FL3741_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
if (index >= 0 && index < DRIVER_LED_TOTAL) {
is31_led led = g_is31_leds[index];
- g_pwm_buffer[led.driver][led.r] = red;
- g_pwm_buffer[led.driver][led.g] = green;
- g_pwm_buffer[led.driver][led.b] = blue;
- g_pwm_buffer_update_required = true;
+ g_pwm_buffer[led.driver][led.r] = red;
+ g_pwm_buffer[led.driver][led.g] = green;
+ g_pwm_buffer[led.driver][led.b] = blue;
+ g_pwm_buffer_update_required[led.driver] = true;
}
}
@@ -206,12 +206,12 @@ void IS31FL3741_set_led_control_register(uint8_t index, bool red, bool green, bo
g_scaling_registers_update_required[led.driver] = true;
}
-void IS31FL3741_update_pwm_buffers(uint8_t addr1, uint8_t addr2) {
- if (g_pwm_buffer_update_required) {
- IS31FL3741_write_pwm_buffer(addr1, g_pwm_buffer[0]);
+void IS31FL3741_update_pwm_buffers(uint8_t addr, uint8_t index) {
+ if (g_pwm_buffer_update_required[index]) {
+ IS31FL3741_write_pwm_buffer(addr, g_pwm_buffer[index]);
}
- g_pwm_buffer_update_required = false;
+ g_pwm_buffer_update_required[index] = false;
}
void IS31FL3741_set_pwm_buffer(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue) {
@@ -219,7 +219,7 @@ void IS31FL3741_set_pwm_buffer(const is31_led *pled, uint8_t red, uint8_t green,
g_pwm_buffer[pled->driver][pled->g] = green;
g_pwm_buffer[pled->driver][pled->b] = blue;
- g_pwm_buffer_update_required = true;
+ g_pwm_buffer_update_required[pled->driver] = true;
}
void IS31FL3741_update_led_control_registers(uint8_t addr, uint8_t index) {
diff --git a/drivers/issi/is31fl3741.h b/drivers/led/issi/is31fl3741.h
index 2df0c5b1a7..163a035233 100644
--- a/drivers/issi/is31fl3741.h
+++ b/drivers/led/issi/is31fl3741.h
@@ -21,6 +21,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "progmem.h"
typedef struct is31_led {
uint32_t driver : 2;
@@ -29,7 +30,7 @@ typedef struct is31_led {
uint32_t b : 10;
} __attribute__((packed)) is31_led;
-extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3741_init(uint8_t addr);
void IS31FL3741_write_register(uint8_t addr, uint8_t reg, uint8_t data);
@@ -44,8 +45,8 @@ void IS31FL3741_set_led_control_register(uint8_t index, bool red, bool green, bo
// (eg. from a timer interrupt).
// Call this while idle (in between matrix scans).
// If the buffer is dirty, it will update the driver with the buffer.
-void IS31FL3741_update_pwm_buffers(uint8_t addr1, uint8_t addr2);
-void IS31FL3741_update_led_control_registers(uint8_t addr1, uint8_t addr2);
+void IS31FL3741_update_pwm_buffers(uint8_t addr, uint8_t index);
+void IS31FL3741_update_led_control_registers(uint8_t addr, uint8_t index);
void IS31FL3741_set_scaling_registers(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue);
void IS31FL3741_set_pwm_buffer(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue);
diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h
index a6b85f37e6..13b73ede9d 100644
--- a/drivers/oled/oled_driver.h
+++ b/drivers/oled/oled_driver.h
@@ -313,6 +313,14 @@ bool oled_scroll_left(void);
// Returns true if the screen was not scrolling or stops scrolling
bool oled_scroll_off(void);
+// Returns true if the oled is currently scrolling, false if it is
+// not
+bool is_oled_scrolling(void);
+
+// Inverts the display
+// Returns true if the screen was or is inverted
+bool oled_invert(bool invert);
+
// Returns the maximum number of characters that will fit on a line
uint8_t oled_max_chars(void);
diff --git a/drivers/oled/oled_driver.c b/drivers/oled/ssd1306_sh1106.c
index 8e5ed5f070..e9049438f5 100644
--- a/drivers/oled/oled_driver.c
+++ b/drivers/oled/ssd1306_sh1106.c
@@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define DISPLAY_ALL_ON 0xA5
#define DISPLAY_ALL_ON_RESUME 0xA4
#define NORMAL_DISPLAY 0xA6
+#define INVERT_DISPLAY 0xA7
#define DISPLAY_ON 0xAF
#define DISPLAY_OFF 0xAE
#define NOP 0xE3
@@ -114,6 +115,7 @@ OLED_BLOCK_TYPE oled_dirty = 0;
bool oled_initialized = false;
bool oled_active = false;
bool oled_scrolling = false;
+bool oled_inverted = false;
uint8_t oled_brightness = OLED_BRIGHTNESS;
oled_rotation_t oled_rotation = 0;
uint8_t oled_rotation_width = 0;
@@ -690,6 +692,32 @@ bool oled_scroll_off(void) {
return !oled_scrolling;
}
+bool is_oled_scrolling(void) { return oled_scrolling; }
+
+bool oled_invert(bool invert) {
+ if (!oled_initialized) {
+ return oled_inverted;
+ }
+
+ if (invert && !oled_inverted) {
+ static const uint8_t PROGMEM display_inverted[] = {I2C_CMD, INVERT_DISPLAY};
+ if (I2C_TRANSMIT_P(display_inverted) != I2C_STATUS_SUCCESS) {
+ print("oled_invert cmd failed\n");
+ return oled_inverted;
+ }
+ oled_inverted = true;
+ } else if (!invert && oled_inverted) {
+ static const uint8_t PROGMEM display_normal[] = {I2C_CMD, NORMAL_DISPLAY};
+ if (I2C_TRANSMIT_P(display_normal) != I2C_STATUS_SUCCESS) {
+ print("oled_invert cmd failed\n");
+ return oled_inverted;
+ }
+ oled_inverted = false;
+ }
+
+ return oled_inverted;
+}
+
uint8_t oled_max_chars(void) {
if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {
return OLED_DISPLAY_WIDTH / OLED_FONT_WIDTH;
diff --git a/drivers/qwiic/micro_oled.c b/drivers/qwiic/micro_oled.c
index bbeb140cbe..8dfff6968f 100644
--- a/drivers/qwiic/micro_oled.c
+++ b/drivers/qwiic/micro_oled.c
@@ -70,25 +70,28 @@ static uint8_t micro_oled_screen_current[LCDWIDTH * LCDHEIGHT / 8] = {0};
D6 D6.............D6 /
D7 D7.............D7 ----
*/
-
-#if LCDWIDTH == 64
-# if LCDHEIGHT == 48
+#ifdef NO_LCD_SPLASH
+// do not initialize with a splash screen
+static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0};
+#else
+# if LCDWIDTH == 64
+# if LCDHEIGHT == 48
static uint8_t micro_oled_screen_buffer[] = {
// QMK Logo - generated at http://www.majer.ch/lcd/adf_bitmap.php
// 64x48 image
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 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, 0x60, 0x60, 0x60, 0x60, 0xF8, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xF8, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x8C, 0x8C, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xF1, 0xE3, 0xE7, 0xCF, 0xCF, 0xCF, 0xCF, 0x00, 0x00, 0xCF, 0xCF, 0xCF, 0xC7, 0xE7, 0xE3, 0xF1, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x1F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x1F, 0x06, 0x06, 0x06, 0x06, 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, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-# endif
-#elif LCDWIDTH == 128
-# if LCDHEIGHT == 32
+# endif
+# elif LCDWIDTH == 128
+# if LCDHEIGHT == 32
static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {
// 128x32 qmk image
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xFC, 0xFC, 0xE0, 0xFC, 0xFC, 0xE0, 0xF0, 0xFC, 0xE0, 0xE0, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0x10, 0x30, 0xE0, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xF0, 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, 0x12, 0xB2, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, 0x03, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xB2, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x02, 0x02, 0x03, 0x01, 0x00, 0x06, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x06, 0x00, 0x03, 0x1E, 0x18, 0x0F, 0x01, 0x0F, 0x18, 0x1E, 0x01, 0x00, 0x0F, 0x1F, 0x12, 0x02, 0x12, 0x13, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0x12, 0x02, 0x12, 0x13, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x1F, 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, 0x48, 0x4D, 0x4D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xF9, 0xF3, 0xF3, 0xC0, 0x80, 0xF3, 0xF3, 0xF3, 0xF9, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0xC0, 0x00, 0x70, 0xC0, 0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x1C, 0xF0, 0x00, 0x00, 0xFC, 0x0C, 0x38, 0xE0, 0x00, 0x00, 0xC0, 0x38, 0x0C, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x60, 0x90, 0x0C, 0x04, 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, 0x01, 0x03, 0x07, 0x07, 0x3F, 0x3F, 0x07, 0x3F, 0x3F, 0x07, 0x0F, 0x3F, 0x07, 0x07, 0x3F, 0x07, 0x07, 0x3F, 0x3F, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x06, 0x04, 0x04, 0x07, 0x01, 0x00, 0x00, 0x13, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04, 0x07, 0x0D, 0x08, 0x00, 0x07, 0x00, 0x00, 0x01, 0x07, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x01, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-# elif LCDHEIGHT == 64
+# elif LCDHEIGHT == 64
static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {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, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 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, 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, 0xC0, 0xC0, 0xC0, 0xC0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF, 0x7F, 0x7E, 0xFE, 0xFF, 0xFF, 0xFE, 0xFE, 0x7F, 0x7F, 0xFE, 0xFE, 0xFF, 0xFF, 0xFE, 0x7E, 0x7F, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xC0, 0xC0, 0xC0, 0xC0, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x88, 0x88, 0x88, 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,
@@ -99,10 +102,11 @@ static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 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, 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};
// TODO: generate bitmap of QMK logo here
-# endif
-#else
+# endif
+# else
// catchall for custom screen sizes
static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0};
+# endif
#endif
void micro_oled_init(void) {
@@ -145,7 +149,7 @@ void micro_oled_init(void) {
#endif
send_command(MEMORYMODE);
- send_command(0x10);
+ send_command(0x02); // 0x02 = 10b, Page addressing mode
send_command(SETCOMPINS); // 0xDA
if (LCDHEIGHT > 32) {
@@ -250,13 +254,14 @@ void send_buffer(void) {
if (micro_oled_screen_buffer[i * LCDWIDTH + j] != micro_oled_screen_current[i * LCDWIDTH + j]) {
if (page_addr != i) {
set_page_address(i);
+ page_addr = i;
}
if (col_addr != j) {
set_column_address(j);
+ col_addr = j + 1;
}
send_data(micro_oled_screen_buffer[i * LCDWIDTH + j]);
micro_oled_screen_current[i * LCDWIDTH + j] = micro_oled_screen_buffer[i * LCDWIDTH + j];
- col_addr = j + 1;
}
}
}
diff --git a/drivers/sensors/adns5050.c b/drivers/sensors/adns5050.c
new file mode 100644
index 0000000000..e7273977d5
--- /dev/null
+++ b/drivers/sensors/adns5050.c
@@ -0,0 +1,193 @@
+/* Copyright 2021 Colin Lam (Ploopy Corporation)
+ * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2019 Sunjun Kim
+ * Copyright 2019 Hiroyuki Okada
+ *
+ * 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 "adns5050.h"
+#include "wait.h"
+#include "debug.h"
+#include "print.h"
+#include "gpio.h"
+
+#ifndef OPTIC_ROTATED
+# define OPTIC_ROTATED false
+#endif
+
+// Definitions for the ADNS serial line.
+#ifndef ADNS_SCLK_PIN
+# define ADNS_SCLK_PIN B7
+#endif
+
+#ifndef ADNS_SDIO_PIN
+# define ADNS_SDIO_PIN C6
+#endif
+
+#ifndef ADNS_CS_PIN
+# define ADNS_CS_PIN B4
+#endif
+
+#ifdef CONSOLE_ENABLE
+void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
+#endif
+
+// Initialize the ADNS serial pins.
+void adns_init(void) {
+ setPinOutput(ADNS_SCLK_PIN);
+ setPinOutput(ADNS_SDIO_PIN);
+ setPinOutput(ADNS_CS_PIN);
+}
+
+// Perform a synchronization with the ADNS.
+// Just as with the serial protocol, this is used by the slave to send a
+// synchronization signal to the master.
+void adns_sync(void) {
+ writePinLow(ADNS_CS_PIN);
+ wait_us(1);
+ writePinHigh(ADNS_CS_PIN);
+}
+
+void adns_cs_select(void) {
+ writePinLow(ADNS_CS_PIN);
+}
+
+void adns_cs_deselect(void) {
+ writePinHigh(ADNS_CS_PIN);
+}
+
+uint8_t adns_serial_read(void) {
+ setPinInput(ADNS_SDIO_PIN);
+ uint8_t byte = 0;
+
+ for (uint8_t i = 0; i < 8; ++i) {
+ writePinLow(ADNS_SCLK_PIN);
+ wait_us(1);
+
+ byte = (byte << 1) | readPin(ADNS_SDIO_PIN);
+
+ writePinHigh(ADNS_SCLK_PIN);
+ wait_us(1);
+ }
+
+ return byte;
+}
+
+void adns_serial_write(uint8_t data) {
+ setPinOutput(ADNS_SDIO_PIN);
+
+ for (int8_t b = 7; b >= 0; b--) {
+ writePinLow(ADNS_SCLK_PIN);
+
+ if (data & (1 << b))
+ writePinHigh(ADNS_SDIO_PIN);
+ else
+ writePinLow(ADNS_SDIO_PIN);
+
+ wait_us(2);
+
+ writePinHigh(ADNS_SCLK_PIN);
+ }
+
+ // tSWR. See page 15 of the ADNS spec sheet.
+ // Technically, this is only necessary if the next operation is an SDIO
+ // read. This is not guaranteed to be the case, but we're being lazy.
+ wait_us(4);
+
+ // Note that tSWW is never necessary. All write operations require at
+ // least 32us, which exceeds tSWW, so there's never a need to wait for it.
+}
+
+// Read a byte of data from a register on the ADNS.
+// Don't forget to use the register map (as defined in the header file).
+uint8_t adns_read_reg(uint8_t reg_addr) {
+ adns_cs_select();
+
+ adns_serial_write(reg_addr);
+
+ // We don't need a minimum tSRAD here. That's because a 4ms wait time is
+ // already included in adns_serial_write(), so we're good.
+ // See page 10 and 15 of the ADNS spec sheet.
+ //wait_us(4);
+
+ uint8_t byte = adns_serial_read();
+
+ // tSRW & tSRR. See page 15 of the ADNS spec sheet.
+ // Technically, this is only necessary if the next operation is an SDIO
+ // read or write. This is not guaranteed to be the case.
+ // Honestly, this wait could probably be removed.
+ wait_us(1);
+
+ adns_cs_deselect();
+
+ return byte;
+}
+
+void adns_write_reg(uint8_t reg_addr, uint8_t data) {
+ adns_cs_select();
+ adns_serial_write( 0b10000000 | reg_addr );
+ adns_serial_write(data);
+ adns_cs_deselect();
+}
+
+report_adns_t adns_read_burst(void) {
+ adns_cs_select();
+
+ report_adns_t data;
+ data.dx = 0;
+ data.dy = 0;
+
+ adns_serial_write(REG_MOTION_BURST);
+
+ // We don't need a minimum tSRAD here. That's because a 4ms wait time is
+ // already included in adns_serial_write(), so we're good.
+ // See page 10 and 15 of the ADNS spec sheet.
+ //wait_us(4);
+
+ uint8_t x = adns_serial_read();
+ uint8_t y = adns_serial_read();
+
+ // Burst mode returns a bunch of other shit that we don't really need.
+ // Setting CS to high ends burst mode early.
+ adns_cs_deselect();
+
+ data.dx = convert_twoscomp(x);
+ data.dy = convert_twoscomp(y);
+
+ return data;
+}
+
+// Convert a two's complement byte from an unsigned data type into a signed
+// data type.
+int8_t convert_twoscomp(uint8_t data) {
+ if ((data & 0x80) == 0x80)
+ return -128 + (data & 0x7F);
+ else
+ return data;
+}
+
+// Don't forget to use the definitions for CPI in the header file.
+void adns_set_cpi(uint8_t cpi) {
+ adns_write_reg(REG_MOUSE_CONTROL2, cpi);
+}
+
+bool adns_check_signature(void) {
+ uint8_t pid = adns_read_reg(REG_PRODUCT_ID);
+ uint8_t rid = adns_read_reg(REG_REVISION_ID);
+ uint8_t pid2 = adns_read_reg(REG_PRODUCT_ID2);
+
+ return (pid == 0x12 && rid == 0x01 && pid2 == 0x26);
+}
diff --git a/drivers/sensors/adns5050.h b/drivers/sensors/adns5050.h
new file mode 100644
index 0000000000..ff8e8f78e9
--- /dev/null
+++ b/drivers/sensors/adns5050.h
@@ -0,0 +1,79 @@
+/* Copyright 2021 Colin Lam (Ploopy Corporation)
+ * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2019 Sunjun Kim
+ * Copyright 2019 Hiroyuki Okada
+ *
+ * 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>
+
+// Registers
+#define REG_PRODUCT_ID 0x00
+#define REG_REVISION_ID 0x01
+#define REG_MOTION 0x02
+#define REG_DELTA_X 0x03
+#define REG_DELTA_Y 0x04
+#define REG_SQUAL 0x05
+#define REG_SHUTTER_UPPER 0x06
+#define REG_SHUTTER_LOWER 0x07
+#define REG_MAXIMUM_PIXEL 0x08
+#define REG_PIXEL_SUM 0x09
+#define REG_MINIMUM_PIXEL 0x0a
+#define REG_PIXEL_GRAB 0x0b
+#define REG_MOUSE_CONTROL 0x0d
+#define REG_MOUSE_CONTROL2 0x19
+#define REG_LED_DC_MODE 0x22
+#define REG_CHIP_RESET 0x3a
+#define REG_PRODUCT_ID2 0x3e
+#define REG_INV_REV_ID 0x3f
+#define REG_MOTION_BURST 0x63
+
+// CPI values
+#define CPI125 0x11
+#define CPI250 0x12
+#define CPI375 0x13
+#define CPI500 0x14
+#define CPI625 0x15
+#define CPI750 0x16
+#define CPI875 0x17
+#define CPI1000 0x18
+#define CPI1125 0x19
+#define CPI1250 0x1a
+#define CPI1375 0x1b
+
+#ifdef CONSOLE_ENABLE
+void print_byte(uint8_t byte);
+#endif
+
+typedef struct {
+ int8_t dx;
+ int8_t dy;
+} report_adns_t;
+
+// A bunch of functions to implement the ADNS5050-specific serial protocol.
+// Note that the "serial.h" driver is insufficient, because it does not
+// manually manipulate a serial clock signal.
+void adns_init(void);
+void adns_sync(void);
+uint8_t adns_serial_read(void);
+void adns_serial_write(uint8_t data);
+uint8_t adns_read_reg(uint8_t reg_addr);
+void adns_write_reg(uint8_t reg_addr, uint8_t data);
+report_adns_t adns_read_burst(void);
+int8_t convert_twoscomp(uint8_t data);
+void adns_set_cpi(uint8_t cpi);
+bool adns_check_signature(void);
diff --git a/drivers/sensors/adns9800.c b/drivers/sensors/adns9800.c
new file mode 100644
index 0000000000..36213179f7
--- /dev/null
+++ b/drivers/sensors/adns9800.c
@@ -0,0 +1,219 @@
+/* Copyright 2020 Alexander Tulloh
+ *
+ * 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 "spi_master.h"
+#include "quantum.h"
+#include "adns9800_srom_A6.h"
+#include "adns9800.h"
+
+// registers
+#define REG_Product_ID 0x00
+#define REG_Revision_ID 0x01
+#define REG_Motion 0x02
+#define REG_Delta_X_L 0x03
+#define REG_Delta_X_H 0x04
+#define REG_Delta_Y_L 0x05
+#define REG_Delta_Y_H 0x06
+#define REG_SQUAL 0x07
+#define REG_Pixel_Sum 0x08
+#define REG_Maximum_Pixel 0x09
+#define REG_Minimum_Pixel 0x0a
+#define REG_Shutter_Lower 0x0b
+#define REG_Shutter_Upper 0x0c
+#define REG_Frame_Period_Lower 0x0d
+#define REG_Frame_Period_Upper 0x0e
+#define REG_Configuration_I 0x0f
+#define REG_Configuration_II 0x10
+#define REG_Frame_Capture 0x12
+#define REG_SROM_Enable 0x13
+#define REG_Run_Downshift 0x14
+#define REG_Rest1_Rate 0x15
+#define REG_Rest1_Downshift 0x16
+#define REG_Rest2_Rate 0x17
+#define REG_Rest2_Downshift 0x18
+#define REG_Rest3_Rate 0x19
+#define REG_Frame_Period_Max_Bound_Lower 0x1a
+#define REG_Frame_Period_Max_Bound_Upper 0x1b
+#define REG_Frame_Period_Min_Bound_Lower 0x1c
+#define REG_Frame_Period_Min_Bound_Upper 0x1d
+#define REG_Shutter_Max_Bound_Lower 0x1e
+#define REG_Shutter_Max_Bound_Upper 0x1f
+#define REG_LASER_CTRL0 0x20
+#define REG_Observation 0x24
+#define REG_Data_Out_Lower 0x25
+#define REG_Data_Out_Upper 0x26
+#define REG_SROM_ID 0x2a
+#define REG_Lift_Detection_Thr 0x2e
+#define REG_Configuration_V 0x2f
+#define REG_Configuration_IV 0x39
+#define REG_Power_Up_Reset 0x3a
+#define REG_Shutdown 0x3b
+#define REG_Inverse_Product_ID 0x3f
+#define REG_Motion_Burst 0x50
+#define REG_SROM_Load_Burst 0x62
+#define REG_Pixel_Burst 0x64
+
+#define ADNS_CLOCK_SPEED 2000000
+#define MIN_CPI 200
+#define MAX_CPI 8200
+#define CPI_STEP 200
+#define CLAMP_CPI(value) value < MIN_CPI ? MIN_CPI : value > MAX_CPI ? MAX_CPI : value
+#define SPI_MODE 3
+#define SPI_DIVISOR (F_CPU / ADNS_CLOCK_SPEED)
+#define US_BETWEEN_WRITES 120
+#define US_BETWEEN_READS 20
+#define US_BEFORE_MOTION 100
+#define MSB1 0x80
+
+extern const uint16_t adns_firmware_length;
+extern const uint8_t adns_firmware_data[];
+
+void adns_spi_start(void){
+ spi_start(SPI_SS_PIN, false, SPI_MODE, SPI_DIVISOR);
+}
+
+void adns_write(uint8_t reg_addr, uint8_t data){
+
+ adns_spi_start();
+ spi_write(reg_addr | MSB1);
+ spi_write(data);
+ spi_stop();
+ wait_us(US_BETWEEN_WRITES);
+}
+
+uint8_t adns_read(uint8_t reg_addr){
+
+ adns_spi_start();
+ spi_write(reg_addr & 0x7f );
+ uint8_t data = spi_read();
+ spi_stop();
+ wait_us(US_BETWEEN_READS);
+
+ return data;
+}
+
+void adns_init() {
+
+ setPinOutput(SPI_SS_PIN);
+
+ spi_init();
+
+ // reboot
+ adns_write(REG_Power_Up_Reset, 0x5a);
+ wait_ms(50);
+
+ // read registers and discard
+ adns_read(REG_Motion);
+ adns_read(REG_Delta_X_L);
+ adns_read(REG_Delta_X_H);
+ adns_read(REG_Delta_Y_L);
+ adns_read(REG_Delta_Y_H);
+
+ // upload firmware
+
+ // 3k firmware mode
+ adns_write(REG_Configuration_IV, 0x02);
+
+ // enable initialisation
+ adns_write(REG_SROM_Enable, 0x1d);
+
+ // wait a frame
+ wait_ms(10);
+
+ // start SROM download
+ adns_write(REG_SROM_Enable, 0x18);
+
+ // write the SROM file
+
+ adns_spi_start();
+
+ spi_write(REG_SROM_Load_Burst | 0x80);
+ wait_us(15);
+
+ // send all bytes of the firmware
+ unsigned char c;
+ for(int i = 0; i < adns_firmware_length; i++){
+ c = (unsigned char)pgm_read_byte(adns_firmware_data + i);
+ spi_write(c);
+ wait_us(15);
+ }
+
+ spi_stop();
+
+ wait_ms(10);
+
+ // enable laser
+ uint8_t laser_ctrl0 = adns_read(REG_LASER_CTRL0);
+ adns_write(REG_LASER_CTRL0, laser_ctrl0 & 0xf0);
+}
+
+config_adns_t adns_get_config(void) {
+ uint8_t config_1 = adns_read(REG_Configuration_I);
+ return (config_adns_t){ (config_1 & 0xFF) * CPI_STEP };
+}
+
+void adns_set_config(config_adns_t config) {
+ uint8_t config_1 = (CLAMP_CPI(config.cpi) / CPI_STEP) & 0xFF;
+ adns_write(REG_Configuration_I, config_1);
+}
+
+static int16_t convertDeltaToInt(uint8_t high, uint8_t low){
+
+ // join bytes into twos compliment
+ uint16_t twos_comp = (high << 8) | low;
+
+ // convert twos comp to int
+ if (twos_comp & 0x8000)
+ return -1 * (~twos_comp + 1);
+
+ return twos_comp;
+}
+
+report_adns_t adns_get_report(void) {
+
+ report_adns_t report = {0, 0};
+
+ adns_spi_start();
+
+ // start burst mode
+ spi_write(REG_Motion_Burst & 0x7f);
+
+ wait_us(US_BEFORE_MOTION);
+
+ uint8_t motion = spi_read();
+
+ if(motion & 0x80) {
+
+ // clear observation register
+ spi_read();
+
+ // delta registers
+ uint8_t delta_x_l = spi_read();
+ uint8_t delta_x_h = spi_read();
+ uint8_t delta_y_l = spi_read();
+ uint8_t delta_y_h = spi_read();
+
+ report.x = convertDeltaToInt(delta_x_h, delta_x_l);
+ report.y = convertDeltaToInt(delta_y_h, delta_y_l);
+ }
+
+ // clear residual motion
+ spi_write(REG_Motion & 0x7f);
+
+ spi_stop();
+
+ return report;
+}
diff --git a/drivers/chibios/analog.h b/drivers/sensors/adns9800.h
index e61c394265..2f50b8f1be 100644
--- a/drivers/chibios/analog.h
+++ b/drivers/sensors/adns9800.h
@@ -1,4 +1,4 @@
-/* Copyright 2019 Drew Mills
+/* Copyright 2020 Alexander Tulloh
*
* 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
@@ -17,25 +17,19 @@
#pragma once
#include <stdint.h>
-#include "quantum.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
typedef struct {
- uint16_t input;
- uint8_t adc;
-} adc_mux;
-#define TO_MUX(i, a) \
- (adc_mux) { i, a }
-
-int16_t analogReadPin(pin_t pin);
-int16_t analogReadPinAdc(pin_t pin, uint8_t adc);
-adc_mux pinToMux(pin_t pin);
+ /* 200 - 8200 CPI supported */
+ uint16_t cpi;
+} config_adns_t;
-int16_t adc_read(adc_mux mux);
+typedef struct {
+ int16_t x;
+ int16_t y;
+} report_adns_t;
-#ifdef __cplusplus
-}
-#endif
+void adns_init(void);
+config_adns_t adns_get_config(void);
+void adns_set_config(config_adns_t);
+/* Reads and clears the current delta values on the ADNS sensor */
+report_adns_t adns_get_report(void);
diff --git a/drivers/sensors/adns9800_srom_A6.h b/drivers/sensors/adns9800_srom_A6.h
new file mode 100644
index 0000000000..f5b3abeb62
--- /dev/null
+++ b/drivers/sensors/adns9800_srom_A6.h
@@ -0,0 +1,3078 @@
+#pragma once
+
+#include "progmem.h"
+
+const uint16_t adns_firmware_length = 3070;
+
+const uint8_t adns_firmware_data[] PROGMEM = {
+0x03,
+0xa6,
+0x68,
+0x1e,
+0x7d,
+0x10,
+0x7e,
+0x7e,
+0x5f,
+0x1c,
+0xb8,
+0xf2,
+0x47,
+0x0c,
+0x7b,
+0x74,
+0x4b,
+0x14,
+0x8b,
+0x75,
+0x66,
+0x51,
+0x0b,
+0x8c,
+0x76,
+0x74,
+0x4b,
+0x14,
+0xaa,
+0xd6,
+0x0f,
+0x9c,
+0xba,
+0xf6,
+0x6e,
+0x3f,
+0xdd,
+0x38,
+0xd5,
+0x02,
+0x80,
+0x9b,
+0x82,
+0x6d,
+0x58,
+0x13,
+0xa4,
+0xab,
+0xb5,
+0xc9,
+0x10,
+0xa2,
+0xc6,
+0x0a,
+0x7f,
+0x5d,
+0x19,
+0x91,
+0xa0,
+0xa3,
+0xce,
+0xeb,
+0x3e,
+0xc9,
+0xf1,
+0x60,
+0x42,
+0xe7,
+0x4c,
+0xfb,
+0x74,
+0x6a,
+0x56,
+0x2e,
+0xbf,
+0xdd,
+0x38,
+0xd3,
+0x05,
+0x88,
+0x92,
+0xa6,
+0xce,
+0xff,
+0x5d,
+0x38,
+0xd1,
+0xcf,
+0xef,
+0x58,
+0xcb,
+0x65,
+0x48,
+0xf0,
+0x35,
+0x85,
+0xa9,
+0xb2,
+0x8f,
+0x5e,
+0xf3,
+0x80,
+0x94,
+0x97,
+0x7e,
+0x75,
+0x97,
+0x87,
+0x73,
+0x13,
+0xb0,
+0x8a,
+0x69,
+0xd4,
+0x0a,
+0xde,
+0xc1,
+0x79,
+0x59,
+0x36,
+0xdb,
+0x9d,
+0xd6,
+0xb8,
+0x15,
+0x6f,
+0xce,
+0x3c,
+0x72,
+0x32,
+0x45,
+0x88,
+0xdf,
+0x6c,
+0xa5,
+0x6d,
+0xe8,
+0x76,
+0x96,
+0x14,
+0x74,
+0x20,
+0xdc,
+0xf4,
+0xfa,
+0x37,
+0x6a,
+0x27,
+0x32,
+0xe3,
+0x29,
+0xbf,
+0xc4,
+0xc7,
+0x06,
+0x9d,
+0x58,
+0xe7,
+0x87,
+0x7c,
+0x2e,
+0x9f,
+0x6e,
+0x49,
+0x07,
+0x5d,
+0x23,
+0x64,
+0x54,
+0x83,
+0x6e,
+0xcb,
+0xb7,
+0x77,
+0xf7,
+0x2b,
+0x6e,
+0x0f,
+0x2e,
+0x66,
+0x12,
+0x60,
+0x55,
+0x65,
+0xfc,
+0x43,
+0xb3,
+0x58,
+0x73,
+0x5b,
+0xe8,
+0x67,
+0x04,
+0x43,
+0x02,
+0xde,
+0xb3,
+0x89,
+0xa0,
+0x6d,
+0x3a,
+0x27,
+0x79,
+0x64,
+0x5b,
+0x0c,
+0x16,
+0x9e,
+0x66,
+0xb1,
+0x8b,
+0x87,
+0x0c,
+0x5d,
+0xf2,
+0xb6,
+0x3d,
+0x71,
+0xdf,
+0x42,
+0x03,
+0x8a,
+0x06,
+0x8d,
+0xef,
+0x1d,
+0xa8,
+0x96,
+0x5c,
+0xed,
+0x31,
+0x61,
+0x5c,
+0xa1,
+0x34,
+0xf6,
+0x8c,
+0x08,
+0x60,
+0x33,
+0x07,
+0x00,
+0x3e,
+0x79,
+0x95,
+0x1b,
+0x43,
+0x7f,
+0xfe,
+0xb6,
+0xa6,
+0xd4,
+0x9d,
+0x76,
+0x72,
+0xbf,
+0xad,
+0xc0,
+0x15,
+0xe8,
+0x37,
+0x31,
+0xa3,
+0x72,
+0x63,
+0x52,
+0x1d,
+0x1c,
+0x5d,
+0x51,
+0x1b,
+0xe1,
+0xa9,
+0xed,
+0x60,
+0x32,
+0x3e,
+0xa9,
+0x50,
+0x28,
+0x53,
+0x06,
+0x59,
+0xe2,
+0xfc,
+0xe7,
+0x02,
+0x64,
+0x39,
+0x21,
+0x56,
+0x4a,
+0xa5,
+0x40,
+0x80,
+0x81,
+0xd5,
+0x5a,
+0x60,
+0x7b,
+0x68,
+0x84,
+0xf1,
+0xe0,
+0xb1,
+0xb6,
+0x5b,
+0xdf,
+0xa8,
+0x1d,
+0x6d,
+0x65,
+0x20,
+0xc0,
+0xa2,
+0xb9,
+0xd9,
+0xbb,
+0x00,
+0xa6,
+0xdb,
+0x8b,
+0x01,
+0x53,
+0x91,
+0xfe,
+0xc4,
+0x51,
+0x85,
+0xb0,
+0x96,
+0x7f,
+0xfd,
+0x51,
+0xdd,
+0x14,
+0x03,
+0x67,
+0x2e,
+0x75,
+0x1c,
+0x76,
+0xd3,
+0x6e,
+0xdd,
+0x99,
+0x55,
+0x76,
+0xe5,
+0xab,
+0x23,
+0xfc,
+0x4a,
+0xd5,
+0xc6,
+0xe8,
+0x2e,
+0xca,
+0x8a,
+0xb3,
+0xf6,
+0x8c,
+0x6c,
+0xb0,
+0xe9,
+0xf2,
+0xe7,
+0x9e,
+0x69,
+0x41,
+0xed,
+0xf1,
+0x6d,
+0xd2,
+0x86,
+0xd8,
+0x7e,
+0xcb,
+0x5d,
+0x47,
+0x6c,
+0x85,
+0x6a,
+0x23,
+0xed,
+0x20,
+0x40,
+0x93,
+0xb4,
+0x20,
+0xc7,
+0xa5,
+0xc9,
+0xaf,
+0x03,
+0x15,
+0xac,
+0x19,
+0xe5,
+0x2a,
+0x36,
+0xdf,
+0x6d,
+0xc5,
+0x8c,
+0x80,
+0x07,
+0xce,
+0x92,
+0x0c,
+0xd8,
+0x06,
+0x62,
+0x0f,
+0xdd,
+0x48,
+0x46,
+0x1a,
+0x53,
+0xc7,
+0x8a,
+0x8c,
+0x5d,
+0x5d,
+0xb4,
+0xa1,
+0x02,
+0xd3,
+0xa9,
+0xb8,
+0xf3,
+0x94,
+0x8f,
+0x3f,
+0xe5,
+0x54,
+0xd4,
+0x11,
+0x65,
+0xb2,
+0x5e,
+0x09,
+0x0b,
+0x81,
+0xe3,
+0x75,
+0xa7,
+0x89,
+0x81,
+0x39,
+0x6c,
+0x46,
+0xf6,
+0x06,
+0x9f,
+0x27,
+0x3b,
+0xb6,
+0x2d,
+0x5f,
+0x1d,
+0x4b,
+0xd4,
+0x7b,
+0x1d,
+0x61,
+0x74,
+0x89,
+0xe4,
+0xe3,
+0xbd,
+0x98,
+0x1b,
+0xc4,
+0x51,
+0x3b,
+0xa4,
+0xfa,
+0xe0,
+0x92,
+0xf7,
+0xbe,
+0xf2,
+0x4d,
+0xbb,
+0xff,
+0xad,
+0x4f,
+0x6d,
+0x68,
+0xc2,
+0x79,
+0x40,
+0xaa,
+0x9b,
+0x8f,
+0x0c,
+0x32,
+0x4b,
+0x5f,
+0x3e,
+0xab,
+0x59,
+0x98,
+0xb3,
+0xf5,
+0x1d,
+0xac,
+0x5e,
+0xbc,
+0x78,
+0xd3,
+0x01,
+0x6c,
+0x64,
+0x15,
+0x2f,
+0xd8,
+0x71,
+0xa6,
+0x2d,
+0x45,
+0xe1,
+0x22,
+0x42,
+0xe4,
+0x4e,
+0x04,
+0x3c,
+0x7d,
+0xf4,
+0x40,
+0x21,
+0xb4,
+0x67,
+0x05,
+0xa8,
+0xe2,
+0xf3,
+0x72,
+0x87,
+0x4c,
+0x7d,
+0xd9,
+0x1b,
+0x65,
+0x97,
+0xf3,
+0xc2,
+0xe3,
+0xe4,
+0xc8,
+0xd2,
+0xde,
+0xf6,
+0xef,
+0xdc,
+0xbb,
+0x44,
+0x08,
+0x5e,
+0xe2,
+0x45,
+0x27,
+0x01,
+0xb0,
+0xf6,
+0x43,
+0xe7,
+0x3a,
+0xf6,
+0xdc,
+0x9d,
+0xed,
+0xf3,
+0xc5,
+0x0c,
+0xb8,
+0x9c,
+0x98,
+0x3a,
+0xd8,
+0x36,
+0xee,
+0x96,
+0x72,
+0x67,
+0xe7,
+0x81,
+0x91,
+0xd5,
+0x05,
+0x0a,
+0xe0,
+0x82,
+0xd5,
+0x8f,
+0xe8,
+0xf9,
+0xb0,
+0xc9,
+0xcf,
+0x93,
+0xe7,
+0x04,
+0xc5,
+0xbc,
+0x2b,
+0x43,
+0x56,
+0x7e,
+0xe8,
+0x67,
+0x7c,
+0xe5,
+0xfb,
+0x49,
+0xad,
+0x5e,
+0x9f,
+0x25,
+0x13,
+0xde,
+0x6e,
+0x6e,
+0xe9,
+0xf1,
+0xec,
+0x87,
+0x0b,
+0x59,
+0x81,
+0x76,
+0x84,
+0x76,
+0xb3,
+0x24,
+0xaf,
+0x30,
+0xfd,
+0x27,
+0x8b,
+0xab,
+0xd8,
+0x00,
+0x8b,
+0x9b,
+0x0c,
+0xd2,
+0xb2,
+0x4e,
+0x5e,
+0x9d,
+0x1d,
+0x96,
+0x01,
+0x00,
+0x67,
+0xc1,
+0x5f,
+0x02,
+0x20,
+0xfd,
+0x45,
+0x6a,
+0x01,
+0x60,
+0x58,
+0x45,
+0xca,
+0x47,
+0x21,
+0x90,
+0x5a,
+0xc4,
+0x43,
+0x26,
+0x1a,
+0xd7,
+0xa5,
+0x4a,
+0xb2,
+0x5d,
+0x2b,
+0x35,
+0x49,
+0xfb,
+0xa5,
+0x17,
+0x92,
+0x21,
+0x1e,
+0x93,
+0x96,
+0x67,
+0xa2,
+0x7e,
+0x36,
+0x7a,
+0xde,
+0x5f,
+0xbe,
+0x7a,
+0x58,
+0x9d,
+0xf8,
+0x78,
+0xa3,
+0xfa,
+0xc8,
+0xd5,
+0x17,
+0xf0,
+0x21,
+0x97,
+0x8c,
+0x80,
+0xb5,
+0x4b,
+0x3b,
+0xbd,
+0xbb,
+0x41,
+0x21,
+0xa8,
+0x50,
+0x67,
+0xf7,
+0xe7,
+0x19,
+0x80,
+0x10,
+0x8e,
+0xce,
+0x04,
+0x18,
+0x3f,
+0x51,
+0x6b,
+0x77,
+0xd8,
+0x9e,
+0x16,
+0xaf,
+0xec,
+0xef,
+0x48,
+0x16,
+0x4d,
+0x9e,
+0x85,
+0x38,
+0x18,
+0x3e,
+0xd4,
+0x28,
+0x87,
+0x60,
+0x2a,
+0xf6,
+0x7f,
+0x09,
+0x86,
+0x6f,
+0x9c,
+0x3c,
+0x3a,
+0xff,
+0xab,
+0xd0,
+0x61,
+0xa2,
+0x97,
+0x0d,
+0x71,
+0x94,
+0x7e,
+0xfd,
+0xb9,
+0x80,
+0x02,
+0x89,
+0x6a,
+0xb3,
+0x84,
+0x6c,
+0x2a,
+0x77,
+0x62,
+0xbe,
+0x0b,
+0xf4,
+0xaf,
+0xac,
+0x7b,
+0x7c,
+0x8e,
+0xca,
+0x01,
+0xba,
+0x71,
+0x78,
+0x94,
+0xfd,
+0xb5,
+0x39,
+0xa4,
+0x4d,
+0x2f,
+0x78,
+0xcf,
+0xca,
+0x92,
+0x0c,
+0x1a,
+0x99,
+0x48,
+0x4c,
+0x11,
+0x96,
+0xb5,
+0x4e,
+0x41,
+0x28,
+0xe4,
+0xa6,
+0xfe,
+0x4b,
+0x72,
+0x91,
+0xe7,
+0xd4,
+0xdd,
+0x9f,
+0x12,
+0xe6,
+0x29,
+0x38,
+0xce,
+0x45,
+0xae,
+0x02,
+0xb8,
+0x24,
+0xae,
+0xbd,
+0xe9,
+0x66,
+0x08,
+0x62,
+0xa2,
+0x2c,
+0x2b,
+0x00,
+0xe2,
+0x23,
+0xd9,
+0xc4,
+0x48,
+0xe4,
+0xd3,
+0xac,
+0xbb,
+0x34,
+0xc7,
+0xf0,
+0xe3,
+0x4f,
+0xb9,
+0x30,
+0xea,
+0xa2,
+0x12,
+0xf1,
+0x30,
+0x2c,
+0x36,
+0xde,
+0x48,
+0xf2,
+0xb0,
+0x4c,
+0x43,
+0x3f,
+0x2e,
+0x58,
+0xe4,
+0x20,
+0xe3,
+0x58,
+0xcd,
+0x31,
+0x22,
+0xf0,
+0xa2,
+0x2a,
+0xe6,
+0x19,
+0x90,
+0x55,
+0x86,
+0xf6,
+0x55,
+0x79,
+0xd1,
+0xd7,
+0x46,
+0x2f,
+0xc0,
+0xdc,
+0x99,
+0xe8,
+0xf3,
+0x6a,
+0xdf,
+0x7f,
+0xeb,
+0x24,
+0x4a,
+0x1e,
+0x5a,
+0x75,
+0xde,
+0x2f,
+0x5c,
+0x19,
+0x61,
+0x03,
+0x53,
+0x54,
+0x6a,
+0x3b,
+0x18,
+0x70,
+0xb6,
+0x4f,
+0xf1,
+0x9c,
+0x0a,
+0x59,
+0x9d,
+0x19,
+0x92,
+0x65,
+0x8c,
+0x83,
+0x14,
+0x2d,
+0x44,
+0x8a,
+0x75,
+0xa9,
+0xf5,
+0x90,
+0xd2,
+0x66,
+0x4e,
+0xfa,
+0x69,
+0x0f,
+0x5b,
+0x0b,
+0x98,
+0x65,
+0xc8,
+0x11,
+0x42,
+0x59,
+0x7f,
+0xdd,
+0x1b,
+0x75,
+0x17,
+0x31,
+0x4c,
+0x75,
+0x58,
+0xeb,
+0x58,
+0x63,
+0x7d,
+0xf2,
+0xa6,
+0xc2,
+0x6e,
+0xb7,
+0x3f,
+0x3e,
+0x5e,
+0x47,
+0xad,
+0xb7,
+0x04,
+0xe8,
+0x05,
+0xf8,
+0xb2,
+0xcf,
+0x19,
+0xf3,
+0xd2,
+0x85,
+0xfe,
+0x3e,
+0x3e,
+0xb1,
+0x62,
+0x08,
+0x2c,
+0x10,
+0x07,
+0x0d,
+0x73,
+0x90,
+0x17,
+0xfa,
+0x9b,
+0x56,
+0x02,
+0x75,
+0xf9,
+0x51,
+0xe0,
+0xe9,
+0x1a,
+0x7b,
+0x9f,
+0xb3,
+0xf3,
+0x98,
+0xb8,
+0x1c,
+0x9c,
+0xe1,
+0xd5,
+0x35,
+0xae,
+0xc8,
+0x60,
+0x48,
+0x11,
+0x09,
+0x94,
+0x6b,
+0xd0,
+0x8b,
+0x15,
+0xbc,
+0x05,
+0x68,
+0xd3,
+0x54,
+0x8a,
+0x51,
+0x39,
+0x5c,
+0x42,
+0x76,
+0xce,
+0xd8,
+0xad,
+0x89,
+0x30,
+0xc9,
+0x05,
+0x1c,
+0xcc,
+0x94,
+0x3f,
+0x0f,
+0x90,
+0x6f,
+0x72,
+0x2d,
+0x85,
+0x64,
+0x9a,
+0xb9,
+0x23,
+0xf9,
+0x0b,
+0xc3,
+0x7c,
+0x39,
+0x0f,
+0x97,
+0x07,
+0x97,
+0xda,
+0x58,
+0x48,
+0x33,
+0x05,
+0x23,
+0xb8,
+0x82,
+0xe8,
+0xd3,
+0x53,
+0x89,
+0xaf,
+0x33,
+0x80,
+0x22,
+0x84,
+0x0c,
+0x95,
+0x5c,
+0x67,
+0xb8,
+0x77,
+0x0c,
+0x5c,
+0xa2,
+0x5f,
+0x3d,
+0x58,
+0x0f,
+0x27,
+0xf3,
+0x2f,
+0xae,
+0x48,
+0xbd,
+0x0b,
+0x6f,
+0x54,
+0xfb,
+0x67,
+0x4c,
+0xea,
+0x32,
+0x27,
+0xf1,
+0xfa,
+0xe2,
+0xb0,
+0xec,
+0x0b,
+0x15,
+0xb4,
+0x70,
+0xf6,
+0x5c,
+0xdd,
+0x71,
+0x60,
+0xc3,
+0xc1,
+0xa8,
+0x32,
+0x65,
+0xac,
+0x7a,
+0x77,
+0x41,
+0xe5,
+0xa9,
+0x6b,
+0x11,
+0x81,
+0xfa,
+0x34,
+0x8d,
+0xfb,
+0xc1,
+0x80,
+0x6e,
+0xc4,
+0x60,
+0x30,
+0x07,
+0xd4,
+0x8b,
+0x67,
+0xbd,
+0xaa,
+0x8c,
+0x9c,
+0x64,
+0xac,
+0xdb,
+0x0b,
+0x24,
+0x8b,
+0x63,
+0x6f,
+0xe6,
+0xbc,
+0xe7,
+0x33,
+0xa4,
+0x4a,
+0x4c,
+0xa7,
+0x9f,
+0x43,
+0x53,
+0xd2,
+0xbb,
+0x8f,
+0x43,
+0xc7,
+0x3d,
+0x78,
+0x68,
+0x3f,
+0xa5,
+0x3d,
+0xca,
+0x69,
+0x84,
+0xa6,
+0x97,
+0x2d,
+0xc0,
+0x7d,
+0x31,
+0x34,
+0x55,
+0x1d,
+0x07,
+0xb1,
+0x5f,
+0x40,
+0x5c,
+0x93,
+0xb0,
+0xbc,
+0x7c,
+0xb0,
+0xbc,
+0xe7,
+0x12,
+0xee,
+0x6b,
+0x2b,
+0xd3,
+0x4d,
+0x67,
+0x70,
+0x3a,
+0x9a,
+0xf2,
+0x3c,
+0x7c,
+0x81,
+0xfa,
+0xd7,
+0xd9,
+0x90,
+0x91,
+0x81,
+0xb8,
+0xb1,
+0xf3,
+0x48,
+0x6a,
+0x26,
+0x4f,
+0x0c,
+0xce,
+0xb0,
+0x9e,
+0xfd,
+0x4a,
+0x3a,
+0xaf,
+0xac,
+0x5b,
+0x3f,
+0xbf,
+0x44,
+0x5a,
+0xa3,
+0x19,
+0x1e,
+0x4b,
+0xe7,
+0x36,
+0x6a,
+0xd7,
+0x20,
+0xae,
+0xd7,
+0x7d,
+0x3b,
+0xe7,
+0xff,
+0x3a,
+0x86,
+0x2e,
+0xd0,
+0x4a,
+0x3e,
+0xaf,
+0x9f,
+0x8e,
+0x01,
+0xbf,
+0xf8,
+0x4f,
+0xc1,
+0xe8,
+0x6f,
+0x74,
+0xe1,
+0x45,
+0xd3,
+0xf7,
+0x04,
+0x6a,
+0x4b,
+0x9d,
+0xec,
+0x33,
+0x27,
+0x76,
+0xd7,
+0xc5,
+0xe1,
+0xb0,
+0x3b,
+0x0e,
+0x23,
+0xec,
+0xf0,
+0x86,
+0xd2,
+0x1a,
+0xbf,
+0x3d,
+0x04,
+0x62,
+0xb3,
+0x6c,
+0xb2,
+0xeb,
+0x17,
+0x05,
+0xa6,
+0x0a,
+0x8a,
+0x7e,
+0x83,
+0x1c,
+0xb6,
+0x37,
+0x09,
+0xc6,
+0x0b,
+0x70,
+0x3c,
+0xb5,
+0x93,
+0x81,
+0xd8,
+0x93,
+0xa0,
+0x5f,
+0x1e,
+0x08,
+0xe2,
+0xc6,
+0xe5,
+0xc9,
+0x72,
+0xf1,
+0xf1,
+0xc1,
+0xed,
+0xd5,
+0x58,
+0x93,
+0x83,
+0xf8,
+0x65,
+0x67,
+0x2e,
+0x0d,
+0xa9,
+0xf1,
+0x64,
+0x12,
+0xe6,
+0x4c,
+0xea,
+0x15,
+0x3f,
+0x8c,
+0x1a,
+0xb6,
+0xbf,
+0xf6,
+0xb9,
+0x52,
+0x35,
+0x09,
+0xb0,
+0xe6,
+0xf7,
+0xcd,
+0xf1,
+0xa5,
+0xaa,
+0x81,
+0xd1,
+0x81,
+0x6f,
+0xb4,
+0xa9,
+0x66,
+0x1f,
+0xfc,
+0x48,
+0xc0,
+0xb6,
+0xd1,
+0x8b,
+0x06,
+0x2f,
+0xf6,
+0xef,
+0x1f,
+0x0a,
+0xe6,
+0xce,
+0x3a,
+0x4a,
+0x55,
+0xbf,
+0x6d,
+0xf9,
+0x4d,
+0xd4,
+0x08,
+0x45,
+0x4b,
+0xc3,
+0x66,
+0x19,
+0x92,
+0x10,
+0xe1,
+0x17,
+0x8e,
+0x28,
+0x91,
+0x16,
+0xbf,
+0x3c,
+0xee,
+0xa3,
+0xa6,
+0x99,
+0x92,
+0x10,
+0xe1,
+0xf6,
+0xcc,
+0xac,
+0xb8,
+0x65,
+0x0b,
+0x43,
+0x66,
+0xf8,
+0xe3,
+0xe5,
+0x3f,
+0x24,
+0x89,
+0x47,
+0x5d,
+0x78,
+0x43,
+0xd0,
+0x61,
+0x17,
+0xbd,
+0x5b,
+0x64,
+0x54,
+0x08,
+0x45,
+0x59,
+0x93,
+0xf6,
+0x95,
+0x8a,
+0x41,
+0x51,
+0x62,
+0x4b,
+0x51,
+0x02,
+0x30,
+0x73,
+0xc7,
+0x87,
+0xc5,
+0x4b,
+0xa2,
+0x97,
+0x0f,
+0xe8,
+0x46,
+0x5f,
+0x7e,
+0x2a,
+0xe1,
+0x30,
+0x20,
+0xb0,
+0xfa,
+0xe7,
+0xce,
+0x61,
+0x42,
+0x57,
+0x6e,
+0x21,
+0xf3,
+0x7a,
+0xec,
+0xe3,
+0x25,
+0xc7,
+0x25,
+0xf3,
+0x67,
+0xa7,
+0x57,
+0x40,
+0x00,
+0x02,
+0xcf,
+0x1c,
+0x80,
+0x77,
+0x67,
+0xbd,
+0x70,
+0xa1,
+0x19,
+0x92,
+0x31,
+0x75,
+0x93,
+0x27,
+0x27,
+0xb6,
+0x82,
+0xe4,
+0xeb,
+0x1d,
+0x78,
+0x48,
+0xe7,
+0xa5,
+0x5e,
+0x57,
+0xef,
+0x64,
+0x28,
+0x64,
+0x1b,
+0xf6,
+0x11,
+0xb2,
+0x03,
+0x9d,
+0xb9,
+0x18,
+0x02,
+0x27,
+0xf7,
+0xbe,
+0x9d,
+0x55,
+0xfc,
+0x00,
+0xd2,
+0xc7,
+0xae,
+0xad,
+0x0b,
+0xc5,
+0xe9,
+0x42,
+0x41,
+0x48,
+0xd8,
+0x32,
+0xcf,
+0xf6,
+0x0f,
+0xf5,
+0xbc,
+0x97,
+0xc6,
+0x99,
+0x47,
+0x76,
+0xbd,
+0x89,
+0x06,
+0x0f,
+0x63,
+0x0c,
+0x51,
+0xd4,
+0x5e,
+0xea,
+0x48,
+0xa8,
+0xa2,
+0x56,
+0x1c,
+0x79,
+0x84,
+0x86,
+0x40,
+0x88,
+0x41,
+0x76,
+0x55,
+0xfc,
+0xc2,
+0xd7,
+0xfd,
+0xc9,
+0xc7,
+0x80,
+0x61,
+0x35,
+0xa7,
+0x43,
+0x20,
+0xf7,
+0xeb,
+0x6c,
+0x66,
+0x13,
+0xb0,
+0xec,
+0x02,
+0x75,
+0x3e,
+0x4b,
+0xaf,
+0xb9,
+0x5d,
+0x40,
+0xda,
+0xd6,
+0x6e,
+0x2d,
+0x39,
+0x54,
+0xc2,
+0x95,
+0x35,
+0x54,
+0x25,
+0x72,
+0xe1,
+0x78,
+0xb8,
+0xeb,
+0xc1,
+0x16,
+0x58,
+0x0f,
+0x9c,
+0x9b,
+0xb4,
+0xea,
+0x37,
+0xec,
+0x3b,
+0x11,
+0xba,
+0xd5,
+0x8a,
+0xa9,
+0xe3,
+0x98,
+0x00,
+0x51,
+0x1c,
+0x14,
+0xe0,
+0x40,
+0x96,
+0xe5,
+0xe9,
+0xf2,
+0x21,
+0x22,
+0xb1,
+0x23,
+0x60,
+0x78,
+0xd3,
+0x17,
+0xf8,
+0x7a,
+0xa5,
+0xa8,
+0xba,
+0x20,
+0xd3,
+0x15,
+0x1e,
+0x32,
+0xe4,
+0x5e,
+0x15,
+0x48,
+0xae,
+0xa9,
+0xe5,
+0xb8,
+0x33,
+0xec,
+0xe8,
+0xa2,
+0x42,
+0xac,
+0xbf,
+0x10,
+0x84,
+0x53,
+0x87,
+0x19,
+0xb4,
+0x5f,
+0x76,
+0x4d,
+0x01,
+0x9d,
+0x56,
+0x74,
+0xd9,
+0x5c,
+0x97,
+0xe7,
+0x88,
+0xea,
+0x3a,
+0xbf,
+0xdc,
+0x4c,
+0x33,
+0x8a,
+0x16,
+0xb9,
+0x5b,
+0xfa,
+0xd8,
+0x42,
+0xa7,
+0xbb,
+0x3c,
+0x04,
+0x27,
+0x78,
+0x49,
+0x81,
+0x2a,
+0x5a,
+0x7d,
+0x7c,
+0x23,
+0xa8,
+0xba,
+0xf7,
+0x9a,
+0x9f,
+0xd2,
+0x66,
+0x3e,
+0x38,
+0x3c,
+0x75,
+0xf9,
+0xd1,
+0x30,
+0x26,
+0x30,
+0x6e,
+0x5a,
+0x6e,
+0xdc,
+0x6a,
+0x69,
+0x32,
+0x50,
+0x33,
+0x47,
+0x9e,
+0xa4,
+0xa8,
+0x64,
+0x66,
+0xf0,
+0x8a,
+0xe4,
+0xfd,
+0x27,
+0x6f,
+0x51,
+0x25,
+0x8b,
+0x43,
+0x74,
+0xc9,
+0x8e,
+0xbd,
+0x88,
+0x31,
+0xbe,
+0xec,
+0x65,
+0xd2,
+0xcb,
+0x8d,
+0x5a,
+0x13,
+0x48,
+0x16,
+0x8c,
+0x61,
+0x0b,
+0x11,
+0xf6,
+0xc6,
+0x66,
+0xae,
+0xc3,
+0xcc,
+0x0c,
+0xd2,
+0xe1,
+0x9f,
+0x82,
+0x41,
+0x3f,
+0x56,
+0xf9,
+0x73,
+0xef,
+0xdc,
+0x30,
+0x50,
+0xcf,
+0xb6,
+0x7f,
+0xbc,
+0xd0,
+0xb3,
+0x10,
+0xab,
+0x24,
+0xe4,
+0xec,
+0xad,
+0x18,
+0x8c,
+0x39,
+0x2d,
+0x30,
+0x4c,
+0xc5,
+0x40,
+0x0d,
+0xf6,
+0xac,
+0xd6,
+0x18,
+0x5d,
+0x96,
+0xbf,
+0x5f,
+0x71,
+0x75,
+0x96,
+0x22,
+0x97,
+0x0f,
+0x02,
+0x94,
+0x6e,
+0xa6,
+0xae,
+0x6d,
+0x8f,
+0x1e,
+0xca,
+0x12,
+0x9b,
+0x2a,
+0x1c,
+0xce,
+0xa9,
+0xee,
+0xfd,
+0x12,
+0x8e,
+0xfc,
+0xed,
+0x09,
+0x33,
+0xba,
+0xf4,
+0x1a,
+0x15,
+0xf6,
+0x9d,
+0x87,
+0x16,
+0x43,
+0x7c,
+0x78,
+0x57,
+0xe1,
+0x44,
+0xc9,
+0xeb,
+0x1f,
+0x58,
+0x4d,
+0xc1,
+0x49,
+0x11,
+0x5c,
+0xb2,
+0x11,
+0xa8,
+0x55,
+0x16,
+0xf1,
+0xc6,
+0x50,
+0xe9,
+0x87,
+0x89,
+0xf6,
+0xcf,
+0xd8,
+0x9c,
+0x51,
+0xa7,
+0xbc,
+0x5b,
+0x31,
+0x6d,
+0x4d,
+0x51,
+0xd0,
+0x4c,
+0xbc,
+0x0d,
+0x58,
+0x2d,
+0x7b,
+0x88,
+0x7a,
+0xf9,
+0x8e,
+0xd6,
+0x40,
+0x4d,
+0xbb,
+0xbe,
+0xc4,
+0xe5,
+0x07,
+0xfc,
+0xd9,
+0x7b,
+0x6d,
+0xa6,
+0x42,
+0x57,
+0x8f,
+0x02,
+0x94,
+0x4f,
+0xe4,
+0x2a,
+0x65,
+0xe2,
+0x19,
+0x5a,
+0x50,
+0xe1,
+0x25,
+0x65,
+0x4a,
+0x60,
+0xc2,
+0xcd,
+0xa8,
+0xec,
+0x05,
+0x2e,
+0x87,
+0x7b,
+0x95,
+0xb7,
+0x4f,
+0xa0,
+0x0b,
+0x1b,
+0x4a,
+0x7f,
+0x92,
+0xc8,
+0x90,
+0xee,
+0x89,
+0x1e,
+0x10,
+0xd2,
+0x85,
+0xe4,
+0x9f,
+0x63,
+0xc8,
+0x12,
+0xbb,
+0x4e,
+0xb8,
+0xcf,
+0x0a,
+0xec,
+0x18,
+0x4e,
+0xe6,
+0x7c,
+0xb3,
+0x33,
+0x26,
+0xc7,
+0x1f,
+0xd2,
+0x04,
+0x23,
+0xea,
+0x07,
+0x0c,
+0x5f,
+0x90,
+0xbd,
+0xa7,
+0x6a,
+0x0f,
+0x4a,
+0xd6,
+0x10,
+0x01,
+0x3c,
+0x12,
+0x29,
+0x2e,
+0x96,
+0xc0,
+0x4d,
+0xbb,
+0xbe,
+0xe5,
+0xa7,
+0x83,
+0xd5,
+0x6a,
+0x3c,
+0xe3,
+0x5b,
+0xb8,
+0xf2,
+0x5c,
+0x6d,
+0x1f,
+0xa6,
+0xf3,
+0x12,
+0x24,
+0xf6,
+0xd6,
+0x3b,
+0x10,
+0x14,
+0x09,
+0x07,
+0x82,
+0xe8,
+0x30,
+0x6a,
+0x99,
+0xdc,
+0x95,
+0x01,
+0x9c,
+0xd4,
+0x68,
+0x3b,
+0xca,
+0x98,
+0x12,
+0xab,
+0x77,
+0x25,
+0x15,
+0x7d,
+0x10,
+0x32,
+0x45,
+0x98,
+0xcd,
+0x7a,
+0xdf,
+0x71,
+0x8a,
+0x75,
+0xc1,
+0x1c,
+0xd4,
+0x68,
+0x25,
+0xeb,
+0xbb,
+0x54,
+0x27,
+0x6f,
+0x2a,
+0xf7,
+0xb9,
+0x98,
+0x03,
+0x27,
+0xde,
+0x24,
+0xa8,
+0xbb,
+0x98,
+0xc2,
+0x84,
+0xff,
+0x9b,
+0x51,
+0xd8,
+0x53,
+0x50,
+0xda,
+0xf5,
+0x88,
+0xaa,
+0x87,
+0x2f,
+0xae,
+0xd6,
+0xea,
+0x6b,
+0xde,
+0xc8,
+0xd7,
+0xa7,
+0x28,
+0x65,
+0x81,
+0xe8,
+0xb2,
+0x3b,
+0x1d,
+0x4f,
+0x75,
+0x8f,
+0x9f,
+0x7a,
+0x74,
+0x8e,
+0xc1,
+0x5f,
+0x9a,
+0xa8,
+0x9d,
+0xfa,
+0x03,
+0xa3,
+0x71,
+0x9b,
+0x37,
+0x6d,
+0xd5,
+0x0b,
+0xf5,
+0xe1,
+0xa1,
+0x1b,
+0x01,
+0x6a,
+0xc6,
+0x67,
+0xaa,
+0xea,
+0x2c,
+0x9d,
+0xa4,
+0xd2,
+0x6e,
+0xfc,
+0xde,
+0x2e,
+0x7f,
+0x94,
+0x69,
+0xe5,
+0x4a,
+0xe0,
+0x01,
+0x48,
+0x3c,
+0x6b,
+0xf7,
+0x1e,
+0xb6,
+0x0b,
+0x5f,
+0xf9,
+0x2e,
+0x07,
+0xc5,
+0xe8,
+0xae,
+0x37,
+0x1b,
+0xbc,
+0x3c,
+0xd8,
+0xd5,
+0x0b,
+0x91,
+0x9e,
+0x80,
+0x24,
+0xf5,
+0x06,
+0x0c,
+0x0e,
+0x98,
+0x07,
+0x96,
+0x2d,
+0x19,
+0xdc,
+0x58,
+0x93,
+0xcc,
+0xfb,
+0x4e,
+0xeb,
+0xbd,
+0x0f,
+0xf5,
+0xaf,
+0x01,
+0xfa,
+0xf1,
+0x7c,
+0x43,
+0x8c,
+0xb8,
+0x56,
+0x3e,
+0xbe,
+0x77,
+0x4e,
+0x2b,
+0xf7,
+0xbb,
+0xb7,
+0x45,
+0x47,
+0xcd,
+0xcc,
+0xa6,
+0x4c,
+0x72,
+0x7b,
+0x6a,
+0x2a,
+0x70,
+0x13,
+0x07,
+0xfd,
+0xb8,
+0x9c,
+0x98,
+0x3a,
+0xd8,
+0x23,
+0x67,
+0x5b,
+0x34,
+0xd5,
+0x14,
+0x0c,
+0xab,
+0x77,
+0x1f,
+0xf8,
+0x3d,
+0x5a,
+0x9f,
+0x92,
+0xb7,
+0x2c,
+0xad,
+0x31,
+0xde,
+0x61,
+0x07,
+0xb3,
+0x6b,
+0xf7,
+0x38,
+0x15,
+0x95,
+0x46,
+0x14,
+0x48,
+0x53,
+0x69,
+0x52,
+0x66,
+0x07,
+0x6d,
+0x83,
+0x71,
+0x8a,
+0x67,
+0x25,
+0x20,
+0x0f,
+0xfe,
+0xd7,
+0x02,
+0xd7,
+0x6e,
+0x2c,
+0xd2,
+0x1a,
+0x0a,
+0x5d,
+0xfd,
+0x0f,
+0x74,
+0xe3,
+0xa4,
+0x36,
+0x07,
+0x9a,
+0xdf,
+0xd4,
+0x79,
+0xbf,
+0xef,
+0x59,
+0xc0,
+0x44,
+0x52,
+0x87,
+0x9a,
+0x6e,
+0x1d,
+0x0e,
+0xee,
+0xde,
+0x2e,
+0x1a,
+0xa9,
+0x8f,
+0x3a,
+0xc9,
+0xba,
+0xec,
+0x99,
+0x78,
+0x2d,
+0x55,
+0x6b,
+0x14,
+0xc2,
+0x06,
+0xd5,
+0xfc,
+0x93,
+0x53,
+0x4d,
+0x11,
+0x8c,
+0xf8,
+0xfa,
+0x79,
+0x7c,
+0xa6,
+0x64,
+0xae,
+0x61,
+0xb8,
+0x7b,
+0x94,
+0x56,
+0xa6,
+0x39,
+0x78,
+0x9a,
+0xe5,
+0xc7,
+0xdf,
+0x18,
+0x63,
+0x23,
+0x9c,
+0xfa,
+0x66,
+0xbb,
+0xb7,
+0x5a,
+0x27,
+0x4c,
+0xd1,
+0xa1,
+0x83,
+0x22,
+0xb3,
+0x52,
+0x49,
+0x35,
+0xb0,
+0x22,
+0x83,
+0x59,
+0x12,
+0x00,
+0x16,
+0x98,
+0xdd,
+0xad,
+0xc2,
+0x94,
+0xf9,
+0xd3,
+0x7b,
+0x64,
+0x7f,
+0x44,
+0x3e,
+0x3c,
+0x8b,
+0x9a,
+0x83,
+0x9c,
+0x69,
+0x6b,
+0xe4,
+0xdf,
+0x9f,
+0xed,
+0x54,
+0x1f,
+0xe5,
+0x5d,
+0x7a,
+0x05,
+0x82,
+0xb3,
+0xdd,
+0xef,
+0xfc,
+0x53,
+0x96,
+0xb0,
+0x2c,
+0x5a,
+0xf8,
+0xdf,
+0x9c,
+0x8b,
+0x16,
+0x4e,
+0xdf,
+0xda,
+0x4d,
+0x09,
+0x09,
+0x69,
+0x50,
+0x03,
+0x65,
+0xd8,
+0x73,
+0x70,
+0xe8,
+0x86,
+0xbf,
+0xbb,
+0x35,
+0xce,
+0xb2,
+0x46,
+0xcb,
+0x02,
+0x00,
+0x5b,
+0xb4,
+0xe2,
+0xc6,
+0x8f,
+0x2f,
+0x98,
+0xaf,
+0x87,
+0x4b,
+0x48,
+0x45,
+0xed,
+0xcc,
+0x1d,
+0xe6,
+0x58,
+0xd6,
+0xf2,
+0x50,
+0x25,
+0x9f,
+0x52,
+0xc7,
+0xcb,
+0x8a,
+0x17,
+0x9d,
+0x5b,
+0xe5,
+0xc8,
+0xd7,
+0x72,
+0xb7,
+0x52,
+0xb2,
+0xc4,
+0x98,
+0xe3,
+0x7a,
+0x17,
+0x3e,
+0xc6,
+0x60,
+0xa7,
+0x97,
+0xb0,
+0xcf,
+0x18,
+0x81,
+0x53,
+0x84,
+0x4c,
+0xd5,
+0x17,
+0x32,
+0x03,
+0x13,
+0x39,
+0x51,
+0x09,
+0x10,
+0xe3,
+0x77,
+0x49,
+0x4f,
+0x62,
+0x01,
+0xbf,
+0x8c,
+0x9a,
+0xe0,
+0x41,
+0x9e,
+0x89,
+0x74,
+0x36,
+0xf9,
+0x96,
+0x86,
+0x2e,
+0x96,
+0x1c,
+0x4a,
+0xb7,
+0x2b,
+0x4a,
+0x97,
+0xbc,
+0x99,
+0x40,
+0xa3,
+0xe0,
+0x3d,
+0xc8,
+0xad,
+0x2f,
+0xdf,
+0x4f,
+0x2c,
+0xc4,
+0x69,
+0x82,
+0x9f,
+0x9b,
+0x81,
+0x0c,
+0x61,
+0x5c,
+0xa5,
+0x9d,
+0x8c,
+0x89,
+0xc0,
+0x2c,
+0xb4,
+0x4a,
+0x33,
+0x4e,
+0xeb,
+0xa2,
+0x56,
+0x40,
+0xc0,
+0xc2,
+0x46,
+0xaf,
+0x6a,
+0xfc,
+0x67,
+0xd1,
+0x80,
+0x5e,
+0xc5,
+0x6d,
+0x84,
+0x43,
+0x27,
+0x3f,
+0x55,
+0x15,
+0x96,
+0x6a,
+0xa0,
+0xa5,
+0xda,
+0xb7,
+0xff,
+0xb7,
+0x75,
+0x6e,
+0x4c,
+0x49,
+0x91,
+0x9d,
+0x22,
+0xa3,
+0x46,
+0xea,
+0xed,
+0x9a,
+0x00,
+0xe2,
+0x32,
+0xc3,
+0xd6,
+0xa9,
+0x71,
+0x20,
+0x55,
+0xa3,
+0x19,
+0xed,
+0xf8,
+0x4f,
+0xa7,
+0x12,
+0x9c,
+0x66,
+0x87,
+0xaf,
+0x4e,
+0xb7,
+0xf0,
+0xdb,
+0xbf,
+0xef,
+0xf0,
+0xf6,
+0xaf,
+0xea,
+0xda,
+0x09,
+0xfe,
+0xde,
+0x38,
+0x5c,
+0xa5,
+0xa2,
+0xdf,
+0x99,
+0x45,
+0xa8,
+0xe4,
+0xe7,
+0x92,
+0xac,
+0x67,
+0xaa,
+0x4f,
+0xbf,
+0x77,
+0x3e,
+0xa2,
+0x40,
+0x49,
+0x22,
+0x4a,
+0x1e,
+0x3b,
+0xaa,
+0x70,
+0x7f,
+0x95,
+0xaf,
+0x37,
+0x4b,
+0xfc,
+0x99,
+0xe2,
+0xe0,
+0xba,
+0xd7,
+0x34,
+0xce,
+0x55,
+0x88,
+0x5b,
+0x84,
+0x1b,
+0x57,
+0xc4,
+0x80,
+0x03,
+0x53,
+0xc9,
+0x2f,
+0x93,
+0x04,
+0x4d,
+0xd5,
+0x96,
+0xe5,
+0x70,
+0xa6,
+0x6e,
+0x63,
+0x5d,
+0x9d,
+0x6c,
+0xdb,
+0x02,
+0x0a,
+0xa9,
+0xda,
+0x8b,
+0x53,
+0xdc,
+0xd9,
+0x9a,
+0xc5,
+0x94,
+0x2c,
+0x91,
+0x92,
+0x2a,
+0xde,
+0xbb,
+0x8b,
+0x13,
+0xb9,
+0x19,
+0x96,
+0x64,
+0xcc,
+0xf2,
+0x64,
+0x39,
+0xb7,
+0x75,
+0x49,
+0xe9,
+0x86,
+0xc2,
+0x86,
+0x62,
+0xd9,
+0x24,
+0xd3,
+0x81,
+0x35,
+0x49,
+0xfc,
+0xa0,
+0xa5,
+0xa0,
+0x93,
+0x05,
+0x64,
+0xb4,
+0x1a,
+0x57,
+0xce,
+0x0c,
+0x90,
+0x02,
+0x27,
+0xc5,
+0x7a,
+0x2b,
+0x5d,
+0xae,
+0x3e,
+0xd5,
+0xdd,
+0x10,
+0x7c,
+0x14,
+0xea,
+0x3a,
+0x08,
+0xac,
+0x72,
+0x4e,
+0x90,
+0x3d,
+0x3b,
+0x7c,
+0x86,
+0x2e,
+0xeb,
+0xd4,
+0x06,
+0x70,
+0xe6,
+0xc7,
+0xfb,
+0x5f,
+0xbd,
+0x18,
+0xf4,
+0x11,
+0xa4,
+0x1a,
+0x93,
+0xc3,
+0xbe,
+0xd9,
+0xfb,
+0x26,
+0x48,
+0x2f,
+0x37,
+0x3c,
+0xd0,
+0x03,
+0x47,
+0x1a,
+0xf7,
+0x62,
+0x19,
+0x24,
+0x5c,
+0xf4,
+0xa8,
+0x92,
+0x20,
+0x7a,
+0xf2,
+0x9e,
+0x2a,
+0xc5,
+0x95,
+0xa2,
+0xfb,
+0xa4,
+0xea,
+0x85,
+0xd8,
+0x56,
+0xb7,
+0x70,
+0xd1,
+0x60,
+0x30,
+0xa5,
+0x30,
+0x82,
+0x70,
+0xdc,
+0x7a,
+0x65,
+0x8a,
+0x36,
+0x3f,
+0x5b,
+0x0c,
+0xae,
+0x54,
+0x7c,
+0xd3,
+0x57,
+0x84,
+0x7b,
+0x3a,
+0x65,
+0x18,
+0x81,
+0xee,
+0x05,
+0x9b,
+0x44,
+0x4d,
+0xb8,
+0xda,
+0xa2,
+0xa1,
+0xc9,
+0x15,
+0xd3,
+0x73,
+0x03,
+0x0e,
+0x43,
+0xe9,
+0x8e,
+0x15,
+0xf9,
+0xbe,
+0xc6,
+0xc5,
+0x8a,
+0xe5,
+0xc0,
+0x1e,
+0xc2,
+0x37,
+0x9e,
+0x2a,
+0x26,
+0xa5,
+0xa0,
+0xbd,
+0x24,
+0x5f,
+0xb9,
+0xc1,
+0xab,
+0x34,
+0x48,
+0xb9,
+0x5d,
+0x98,
+0xb4,
+0x65,
+0x18,
+0xf3,
+0x63,
+0x19,
+0x44,
+0x1b,
+0x11,
+0x16,
+0xff,
+0xdc,
+0xf1,
+0x79,
+0x08,
+0x86,
+0x0f,
+0x52,
+0x98,
+0x73,
+0xc4,
+0x92,
+0x90,
+0x2b,
+0x47,
+0x09,
+0xd0,
+0x43,
+0x6c,
+0x2f,
+0x20,
+0xeb,
+0xdc,
+0xda,
+0xc5,
+0x08,
+0x7b,
+0x94,
+0x42,
+0x30,
+0x6a,
+0xc7,
+0xda,
+0x8c,
+0xc3,
+0x76,
+0xa7,
+0xa5,
+0xcc,
+0x62,
+0x13,
+0x00,
+0x60,
+0x31,
+0x58,
+0x44,
+0x9b,
+0xf5,
+0x64,
+0x14,
+0xf5,
+0x11,
+0xc5,
+0x54,
+0x52,
+0x83,
+0xd4,
+0x73,
+0x01,
+0x16,
+0x0e,
+0xb3,
+0x7a,
+0x29,
+0x69,
+0x35,
+0x56,
+0xd4,
+0xee,
+0x8a,
+0x17,
+0xa2,
+0x99,
+0x24,
+0x9c,
+0xd7,
+0x8f,
+0xdb,
+0x55,
+0xb5,
+0x3e
+};
diff --git a/drivers/sensors/pimoroni_trackball.c b/drivers/sensors/pimoroni_trackball.c
new file mode 100644
index 0000000000..48098ff0cc
--- /dev/null
+++ b/drivers/sensors/pimoroni_trackball.c
@@ -0,0 +1,201 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2021 Dasky (@daskygit)
+ *
+ * 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 "pimoroni_trackball.h"
+#include "i2c_master.h"
+#include "print.h"
+
+#ifndef PIMORONI_TRACKBALL_ADDRESS
+# define PIMORONI_TRACKBALL_ADDRESS 0x0A
+#endif
+#ifndef PIMORONI_TRACKBALL_INTERVAL_MS
+# define PIMORONI_TRACKBALL_INTERVAL_MS 8
+#endif
+#ifndef PIMORONI_TRACKBALL_MOUSE_SCALE
+# define PIMORONI_TRACKBALL_MOUSE_SCALE 5
+#endif
+#ifndef PIMORONI_TRACKBALL_SCROLL_SCALE
+# define PIMORONI_TRACKBALL_SCROLL_SCALE 1
+#endif
+#ifndef PIMORONI_TRACKBALL_DEBOUNCE_CYCLES
+# define PIMORONI_TRACKBALL_DEBOUNCE_CYCLES 20
+#endif
+#ifndef PIMORONI_TRACKBALL_ERROR_COUNT
+# define PIMORONI_TRACKBALL_ERROR_COUNT 10
+#endif
+
+#define TRACKBALL_TIMEOUT 100
+#define TRACKBALL_REG_LED_RED 0x00
+#define TRACKBALL_REG_LED_GRN 0x01
+#define TRACKBALL_REG_LED_BLU 0x02
+#define TRACKBALL_REG_LED_WHT 0x03
+#define TRACKBALL_REG_LEFT 0x04
+#define TRACKBALL_REG_RIGHT 0x05
+#define TRACKBALL_REG_UP 0x06
+#define TRACKBALL_REG_DOWN 0x07
+
+static pimoroni_data current_pimoroni_data;
+static report_mouse_t mouse_report;
+static bool scrolling = false;
+static int16_t x_offset = 0;
+static int16_t y_offset = 0;
+static int16_t h_offset = 0;
+static int16_t v_offset = 0;
+static uint16_t precision = 128;
+static uint8_t error_count = 0;
+
+float trackball_get_precision(void) { return ((float)precision / 128); }
+void trackball_set_precision(float floatprecision) { precision = (floatprecision * 128); }
+bool trackball_is_scrolling(void) { return scrolling; }
+void trackball_set_scrolling(bool scroll) { scrolling = scroll; }
+
+void trackball_set_rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
+ uint8_t data[4] = {r, g, b, w};
+ __attribute__((unused)) i2c_status_t status = i2c_writeReg(PIMORONI_TRACKBALL_ADDRESS << 1, TRACKBALL_REG_LED_RED, data, sizeof(data), TRACKBALL_TIMEOUT);
+#ifdef TRACKBALL_DEBUG
+ dprintf("Trackball RGBW i2c_status_t: %d\n", status);
+#endif
+}
+
+i2c_status_t read_pimoroni_trackball(pimoroni_data* data) {
+ i2c_status_t status = i2c_readReg(PIMORONI_TRACKBALL_ADDRESS << 1, TRACKBALL_REG_LEFT, (uint8_t*)data, sizeof(*data), TRACKBALL_TIMEOUT);
+#ifdef TRACKBALL_DEBUG
+ dprintf("Trackball READ i2c_status_t: %d\nLeft: %d\nRight: %d\nUp: %d\nDown: %d\nSwtich: %d\n", status, data->left, data->right, data->up, data->down, data->click);
+#endif
+ return status;
+}
+
+__attribute__((weak)) void pointing_device_init(void) {
+ i2c_init();
+ trackball_set_rgbw(0x00, 0x00, 0x00, 0x00);
+}
+
+int16_t trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale) {
+ uint8_t offset = 0;
+ bool isnegative = false;
+ if (negative_dir > positive_dir) {
+ offset = negative_dir - positive_dir;
+ isnegative = true;
+ } else {
+ offset = positive_dir - negative_dir;
+ }
+ uint16_t magnitude = (scale * offset * offset * precision) >> 7;
+ return isnegative ? -(int16_t)(magnitude) : (int16_t)(magnitude);
+}
+
+void trackball_adapt_values(int8_t* mouse, int16_t* offset) {
+ if (*offset > 127) {
+ *mouse = 127;
+ *offset -= 127;
+ } else if (*offset < -127) {
+ *mouse = -127;
+ *offset += 127;
+ } else {
+ *mouse = *offset;
+ *offset = 0;
+ }
+}
+
+__attribute__((weak)) void trackball_click(bool pressed, report_mouse_t* mouse) {
+#ifdef PIMORONI_TRACKBALL_CLICK
+ if (pressed) {
+ mouse->buttons |= MOUSE_BTN1;
+ } else {
+ mouse->buttons &= ~MOUSE_BTN1;
+ }
+#endif
+}
+
+__attribute__((weak)) bool pointing_device_task_user(pimoroni_data* trackball_data) { return true; };
+
+__attribute__((weak)) void pointing_device_task() {
+ static fast_timer_t throttle = 0;
+ static uint16_t debounce = 0;
+
+ if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT && timer_elapsed_fast(throttle) >= PIMORONI_TRACKBALL_INTERVAL_MS) {
+ i2c_status_t status = read_pimoroni_trackball(&current_pimoroni_data);
+
+ if (status == I2C_STATUS_SUCCESS) {
+ error_count = 0;
+
+ if (pointing_device_task_user(&current_pimoroni_data)) {
+ mouse_report = pointing_device_get_report();
+
+ if (!(current_pimoroni_data.click & 128)) {
+ trackball_click(false, &mouse_report);
+ if (!debounce) {
+ if (scrolling) {
+#ifdef PIMORONI_TRACKBALL_INVERT_X
+ h_offset += trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_SCROLL_SCALE);
+#else
+ h_offset -= trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_SCROLL_SCALE);
+#endif
+#ifdef PIMORONI_TRACKBALL_INVERT_Y
+ v_offset += trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_SCROLL_SCALE);
+#else
+ v_offset -= trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_SCROLL_SCALE);
+#endif
+ } else {
+#ifdef PIMORONI_TRACKBALL_INVERT_X
+ x_offset -= trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_MOUSE_SCALE);
+#else
+ x_offset += trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_MOUSE_SCALE);
+#endif
+#ifdef PIMORONI_TRACKBALL_INVERT_Y
+ y_offset -= trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_MOUSE_SCALE);
+#else
+ y_offset += trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_MOUSE_SCALE);
+#endif
+ }
+ if (scrolling) {
+#ifndef PIMORONI_TRACKBALL_ROTATE
+ trackball_adapt_values(&mouse_report.h, &h_offset);
+ trackball_adapt_values(&mouse_report.v, &v_offset);
+#else
+ trackball_adapt_values(&mouse_report.h, &v_offset);
+ trackball_adapt_values(&mouse_report.v, &h_offset);
+#endif
+ mouse_report.x = 0;
+ mouse_report.y = 0;
+ } else {
+#ifndef PIMORONI_TRACKBALL_ROTATE
+ trackball_adapt_values(&mouse_report.x, &x_offset);
+ trackball_adapt_values(&mouse_report.y, &y_offset);
+#else
+ trackball_adapt_values(&mouse_report.x, &y_offset);
+ trackball_adapt_values(&mouse_report.y, &x_offset);
+#endif
+ mouse_report.h = 0;
+ mouse_report.v = 0;
+ }
+ } else {
+ debounce--;
+ }
+ } else {
+ trackball_click(true, &mouse_report);
+ debounce = PIMORONI_TRACKBALL_DEBOUNCE_CYCLES;
+ }
+ }
+ } else {
+ error_count++;
+ }
+
+ pointing_device_set_report(mouse_report);
+ pointing_device_send();
+
+ throttle = timer_read_fast();
+ }
+}
diff --git a/drivers/sensors/pimoroni_trackball.h b/drivers/sensors/pimoroni_trackball.h
new file mode 100644
index 0000000000..6b2a41425d
--- /dev/null
+++ b/drivers/sensors/pimoroni_trackball.h
@@ -0,0 +1,37 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2021 Dasky (@daskygit)
+ *
+ * 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 "quantum.h"
+#include "pointing_device.h"
+
+typedef struct pimoroni_data {
+ uint8_t left;
+ uint8_t right;
+ uint8_t up;
+ uint8_t down;
+ uint8_t click;
+} pimoroni_data;
+
+void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
+void trackball_click(bool pressed, report_mouse_t* mouse);
+int16_t trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale);
+void trackball_adapt_values(int8_t* mouse, int16_t* offset);
+float trackball_get_precision(void);
+void trackball_set_precision(float precision);
+bool trackball_is_scrolling(void);
+void trackball_set_scrolling(bool scroll);
diff --git a/drivers/sensors/pmw3360.c b/drivers/sensors/pmw3360.c
new file mode 100644
index 0000000000..17c4675ffa
--- /dev/null
+++ b/drivers/sensors/pmw3360.c
@@ -0,0 +1,271 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2019 Sunjun Kim
+ * Copyright 2020 Ploopy Corporation
+ *
+ * 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 "pmw3360.h"
+#include "wait.h"
+#include "debug.h"
+#include "print.h"
+#include "pmw3360_firmware.h"
+
+// Registers
+#define REG_Product_ID 0x00
+#define REG_Revision_ID 0x01
+#define REG_Motion 0x02
+#define REG_Delta_X_L 0x03
+#define REG_Delta_X_H 0x04
+#define REG_Delta_Y_L 0x05
+#define REG_Delta_Y_H 0x06
+#define REG_SQUAL 0x07
+#define REG_Raw_Data_Sum 0x08
+#define REG_Maximum_Raw_data 0x09
+#define REG_Minimum_Raw_data 0x0A
+#define REG_Shutter_Lower 0x0B
+#define REG_Shutter_Upper 0x0C
+#define REG_Control 0x0D
+#define REG_Config1 0x0F
+#define REG_Config2 0x10
+#define REG_Angle_Tune 0x11
+#define REG_Frame_Capture 0x12
+#define REG_SROM_Enable 0x13
+#define REG_Run_Downshift 0x14
+#define REG_Rest1_Rate_Lower 0x15
+#define REG_Rest1_Rate_Upper 0x16
+#define REG_Rest1_Downshift 0x17
+#define REG_Rest2_Rate_Lower 0x18
+#define REG_Rest2_Rate_Upper 0x19
+#define REG_Rest2_Downshift 0x1A
+#define REG_Rest3_Rate_Lower 0x1B
+#define REG_Rest3_Rate_Upper 0x1C
+#define REG_Observation 0x24
+#define REG_Data_Out_Lower 0x25
+#define REG_Data_Out_Upper 0x26
+#define REG_Raw_Data_Dump 0x29
+#define REG_SROM_ID 0x2A
+#define REG_Min_SQ_Run 0x2B
+#define REG_Raw_Data_Threshold 0x2C
+#define REG_Config5 0x2F
+#define REG_Power_Up_Reset 0x3A
+#define REG_Shutdown 0x3B
+#define REG_Inverse_Product_ID 0x3F
+#define REG_LiftCutoff_Tune3 0x41
+#define REG_Angle_Snap 0x42
+#define REG_LiftCutoff_Tune1 0x4A
+#define REG_Motion_Burst 0x50
+#define REG_LiftCutoff_Tune_Timeout 0x58
+#define REG_LiftCutoff_Tune_Min_Length 0x5A
+#define REG_SROM_Load_Burst 0x62
+#define REG_Lift_Config 0x63
+#define REG_Raw_Data_Burst 0x64
+#define REG_LiftCutoff_Tune2 0x65
+
+bool _inBurst = false;
+
+void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
+
+bool spi_start_adv(void) {
+ bool status = spi_start(PMW3360_CS_PIN, PMW3360_SPI_LSBFIRST, PMW3360_SPI_MODE, PMW3360_SPI_DIVISOR);
+ wait_us(1);
+ return status;
+}
+
+void spi_stop_adv(void) {
+ wait_us(1);
+ spi_stop();
+}
+
+spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data) {
+ if (reg_addr != REG_Motion_Burst) {
+ _inBurst = false;
+ }
+
+ spi_start_adv();
+ // send address of the register, with MSBit = 1 to indicate it's a write
+ spi_status_t status = spi_write(reg_addr | 0x80);
+ status = spi_write(data);
+
+ // tSCLK-NCS for write operation
+ wait_us(20);
+
+ // tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound
+ wait_us(100);
+ spi_stop();
+ return status;
+}
+
+uint8_t spi_read_adv(uint8_t reg_addr) {
+ spi_start_adv();
+ // send adress of the register, with MSBit = 0 to indicate it's a read
+ spi_write(reg_addr & 0x7f);
+
+ uint8_t data = spi_read();
+
+ // tSCLK-NCS for read operation is 120ns
+ wait_us(1);
+
+ // tSRW/tSRR (=20us) minus tSCLK-NCS
+ wait_us(19);
+
+ spi_stop();
+ return data;
+}
+
+void pmw_set_cpi(uint16_t cpi) {
+ uint8_t cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119
+
+ spi_start_adv();
+ spi_write_adv(REG_Config1, cpival);
+ spi_stop();
+}
+
+uint16_t pmw_get_cpi(void) {
+ uint8_t cpival = spi_read_adv(REG_Config1);
+ return (uint16_t)(cpival & 0xFF) * 100;
+}
+
+bool pmw_spi_init(void) {
+ setPinOutput(PMW3360_CS_PIN);
+
+ spi_init();
+ _inBurst = false;
+
+ spi_stop();
+ spi_start_adv();
+ spi_stop();
+
+ spi_write_adv(REG_Shutdown, 0xb6); // Shutdown first
+ wait_ms(300);
+
+ spi_start_adv();
+ wait_us(40);
+ spi_stop_adv();
+ wait_us(40);
+
+ spi_write_adv(REG_Power_Up_Reset, 0x5a);
+ wait_ms(50);
+
+ spi_read_adv(REG_Motion);
+ spi_read_adv(REG_Delta_X_L);
+ spi_read_adv(REG_Delta_X_H);
+ spi_read_adv(REG_Delta_Y_L);
+ spi_read_adv(REG_Delta_Y_H);
+
+ pmw_upload_firmware();
+
+ spi_stop_adv();
+
+ wait_ms(10);
+ pmw_set_cpi(PMW3360_CPI);
+
+ wait_ms(1);
+
+ spi_write_adv(REG_Config2, 0x00);
+
+ spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30));
+
+ bool init_success = pmw_check_signature();
+
+ writePinLow(PMW3360_CS_PIN);
+
+ return init_success;
+}
+
+void pmw_upload_firmware(void) {
+ spi_write_adv(REG_SROM_Enable, 0x1d);
+
+ wait_ms(10);
+
+ spi_write_adv(REG_SROM_Enable, 0x18);
+
+ spi_start_adv();
+ spi_write(REG_SROM_Load_Burst | 0x80);
+ wait_us(15);
+
+ unsigned char c;
+ for (int i = 0; i < firmware_length; i++) {
+ c = (unsigned char)pgm_read_byte(firmware_data + i);
+ spi_write(c);
+ wait_us(15);
+ }
+ wait_us(200);
+
+ spi_read_adv(REG_SROM_ID);
+
+ spi_write_adv(REG_Config2, 0x00);
+
+ spi_stop();
+ wait_ms(10);
+}
+
+bool pmw_check_signature(void) {
+ uint8_t pid = spi_read_adv(REG_Product_ID);
+ uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID);
+ uint8_t SROM_ver = spi_read_adv(REG_SROM_ID);
+ return (pid == 0x42 && iv_pid == 0xBD && SROM_ver == 0x04); // signature for SROM 0x04
+}
+
+report_pmw_t pmw_read_burst(void) {
+ if (!_inBurst) {
+ dprintf("burst on");
+ spi_write_adv(REG_Motion_Burst, 0x00);
+ _inBurst = true;
+ }
+
+ spi_start_adv();
+ spi_write(REG_Motion_Burst);
+ wait_us(35); // waits for tSRAD
+
+ report_pmw_t data;
+ data.motion = 0;
+ data.dx = 0;
+ data.mdx = 0;
+ data.dy = 0;
+ data.mdx = 0;
+
+ data.motion = spi_read();
+ spi_write(0x00); // skip Observation
+ data.dx = spi_read();
+ data.mdx = spi_read();
+ data.dy = spi_read();
+ data.mdy = spi_read();
+
+ spi_stop();
+
+ if (debug_mouse) {
+ print_byte(data.motion);
+ print_byte(data.dx);
+ print_byte(data.mdx);
+ print_byte(data.dy);
+ print_byte(data.mdy);
+ dprintf("\n");
+ }
+
+ data.isMotion = (data.motion & 0x80) != 0;
+ data.isOnSurface = (data.motion & 0x08) == 0;
+ data.dx |= (data.mdx << 8);
+ data.dx = data.dx * -1;
+ data.dy |= (data.mdy << 8);
+ data.dy = data.dy * -1;
+
+ spi_stop();
+
+ if (data.motion & 0b111) { // panic recovery, sometimes burst mode works weird.
+ _inBurst = false;
+ }
+
+ return data;
+}
diff --git a/drivers/sensors/pmw3360.h b/drivers/sensors/pmw3360.h
new file mode 100644
index 0000000000..124c62cf00
--- /dev/null
+++ b/drivers/sensors/pmw3360.h
@@ -0,0 +1,85 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2019 Sunjun Kim
+ * Copyright 2020 Ploopy Corporation
+ *
+ * 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 "spi_master.h"
+
+#ifndef PMW3360_CPI
+# define PMW3360_CPI 1600
+#endif
+
+#ifndef PMW3360_CLOCK_SPEED
+# define PMW3360_CLOCK_SPEED 70000000
+#endif
+
+#ifndef PMW3360_SPI_LSBFIRST
+# define PMW3360_SPI_LSBFIRST false
+#endif
+
+#ifndef PMW3360_SPI_MODE
+# define PMW3360_SPI_MODE 3
+#endif
+
+#ifndef PMW3360_SPI_DIVISOR
+# ifdef __AVR__
+# define PMW3360_SPI_DIVISOR (F_CPU / PMW3360_CLOCK_SPEED)
+# else
+# define PMW3360_SPI_DIVISOR 64
+# endif
+#endif
+
+#ifndef ROTATIONAL_TRANSFORM_ANGLE
+# define ROTATIONAL_TRANSFORM_ANGLE 0x00
+#endif
+
+#ifndef PMW3360_CS_PIN
+# error "No chip select pin defined -- missing PMW3360_CS_PIN"
+#endif
+
+#ifdef CONSOLE_ENABLE
+void print_byte(uint8_t byte);
+#endif
+
+typedef struct {
+ int8_t motion;
+ bool isMotion; // True if a motion is detected.
+ bool isOnSurface; // True when a chip is on a surface
+ int16_t dx; // displacement on x directions. Unit: Count. (CPI * Count = Inch value)
+ int8_t mdx;
+ int16_t dy; // displacement on y directions.
+ int8_t mdy;
+} report_pmw_t;
+
+
+
+bool spi_start_adv(void);
+void spi_stop_adv(void);
+spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data);
+uint8_t spi_read_adv(uint8_t reg_addr);
+bool pmw_spi_init(void);
+void pmw_set_cpi(uint16_t cpi);
+uint16_t pmw_get_cpi(void);
+void pmw_upload_firmware(void);
+bool pmw_check_signature(void);
+report_pmw_t pmw_read_burst(void);
+
+
+#define degToRad(angleInDegrees) ((angleInDegrees)*M_PI / 180.0)
+#define radToDeg(angleInRadians) ((angleInRadians)*180.0 / M_PI)
+#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
diff --git a/drivers/sensors/pmw3360_firmware.h b/drivers/sensors/pmw3360_firmware.h
new file mode 100644
index 0000000000..cca5a6a4d8
--- /dev/null
+++ b/drivers/sensors/pmw3360_firmware.h
@@ -0,0 +1,300 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2019 Sunjun Kim
+ * Copyright 2020 Ploopy Corporation
+ *
+ * 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
+
+// clang-format off
+// Firmware Blob foor PMW3360
+const uint16_t firmware_length = 4094;
+// clang-format off
+const uint8_t firmware_data[] PROGMEM = { // SROM 0x04
+0x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
+0xff, 0x5d, 0x19, 0xb0, 0xc2, 0x04, 0x69, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0xb0,
+0xc3, 0xe5, 0x29, 0xb1, 0xe0, 0x23, 0xa5, 0xa9, 0xb1, 0xc1, 0x00, 0x82, 0x67, 0x4c, 0x1a,
+0x97, 0x8d, 0x79, 0x51, 0x20, 0xc7, 0x06, 0x8e, 0x7c, 0x7c, 0x7a, 0x76, 0x4f, 0xfd, 0x59,
+0x30, 0xe2, 0x46, 0x0e, 0x9e, 0xbe, 0xdf, 0x1d, 0x99, 0x91, 0xa0, 0xa5, 0xa1, 0xa9, 0xd0,
+0x22, 0xc6, 0xef, 0x5c, 0x1b, 0x95, 0x89, 0x90, 0xa2, 0xa7, 0xcc, 0xfb, 0x55, 0x28, 0xb3,
+0xe4, 0x4a, 0xf7, 0x6c, 0x3b, 0xf4, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0x9d, 0xb8, 0xd3, 0x05,
+0x88, 0x92, 0xa6, 0xce, 0x1e, 0xbe, 0xdf, 0x1d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x5c, 0x07,
+0x11, 0x5d, 0x98, 0x0b, 0x9d, 0x94, 0x97, 0xee, 0x4e, 0x45, 0x33, 0x6b, 0x44, 0xc7, 0x29,
+0x56, 0x27, 0x30, 0xc6, 0xa7, 0xd5, 0xf2, 0x56, 0xdf, 0xb4, 0x38, 0x62, 0xcb, 0xa0, 0xb6,
+0xe3, 0x0f, 0x84, 0x06, 0x24, 0x05, 0x65, 0x6f, 0x76, 0x89, 0xb5, 0x77, 0x41, 0x27, 0x82,
+0x66, 0x65, 0x82, 0xcc, 0xd5, 0xe6, 0x20, 0xd5, 0x27, 0x17, 0xc5, 0xf8, 0x03, 0x23, 0x7c,
+0x5f, 0x64, 0xa5, 0x1d, 0xc1, 0xd6, 0x36, 0xcb, 0x4c, 0xd4, 0xdb, 0x66, 0xd7, 0x8b, 0xb1,
+0x99, 0x7e, 0x6f, 0x4c, 0x36, 0x40, 0x06, 0xd6, 0xeb, 0xd7, 0xa2, 0xe4, 0xf4, 0x95, 0x51,
+0x5a, 0x54, 0x96, 0xd5, 0x53, 0x44, 0xd7, 0x8c, 0xe0, 0xb9, 0x40, 0x68, 0xd2, 0x18, 0xe9,
+0xdd, 0x9a, 0x23, 0x92, 0x48, 0xee, 0x7f, 0x43, 0xaf, 0xea, 0x77, 0x38, 0x84, 0x8c, 0x0a,
+0x72, 0xaf, 0x69, 0xf8, 0xdd, 0xf1, 0x24, 0x83, 0xa3, 0xf8, 0x4a, 0xbf, 0xf5, 0x94, 0x13,
+0xdb, 0xbb, 0xd8, 0xb4, 0xb3, 0xa0, 0xfb, 0x45, 0x50, 0x60, 0x30, 0x59, 0x12, 0x31, 0x71,
+0xa2, 0xd3, 0x13, 0xe7, 0xfa, 0xe7, 0xce, 0x0f, 0x63, 0x15, 0x0b, 0x6b, 0x94, 0xbb, 0x37,
+0x83, 0x26, 0x05, 0x9d, 0xfb, 0x46, 0x92, 0xfc, 0x0a, 0x15, 0xd1, 0x0d, 0x73, 0x92, 0xd6,
+0x8c, 0x1b, 0x8c, 0xb8, 0x55, 0x8a, 0xce, 0xbd, 0xfe, 0x8e, 0xfc, 0xed, 0x09, 0x12, 0x83,
+0x91, 0x82, 0x51, 0x31, 0x23, 0xfb, 0xb4, 0x0c, 0x76, 0xad, 0x7c, 0xd9, 0xb4, 0x4b, 0xb2,
+0x67, 0x14, 0x09, 0x9c, 0x7f, 0x0c, 0x18, 0xba, 0x3b, 0xd6, 0x8e, 0x14, 0x2a, 0xe4, 0x1b,
+0x52, 0x9f, 0x2b, 0x7d, 0xe1, 0xfb, 0x6a, 0x33, 0x02, 0xfa, 0xac, 0x5a, 0xf2, 0x3e, 0x88,
+0x7e, 0xae, 0xd1, 0xf3, 0x78, 0xe8, 0x05, 0xd1, 0xe3, 0xdc, 0x21, 0xf6, 0xe1, 0x9a, 0xbd,
+0x17, 0x0e, 0xd9, 0x46, 0x9b, 0x88, 0x03, 0xea, 0xf6, 0x66, 0xbe, 0x0e, 0x1b, 0x50, 0x49,
+0x96, 0x40, 0x97, 0xf1, 0xf1, 0xe4, 0x80, 0xa6, 0x6e, 0xe8, 0x77, 0x34, 0xbf, 0x29, 0x40,
+0x44, 0xc2, 0xff, 0x4e, 0x98, 0xd3, 0x9c, 0xa3, 0x32, 0x2b, 0x76, 0x51, 0x04, 0x09, 0xe7,
+0xa9, 0xd1, 0xa6, 0x32, 0xb1, 0x23, 0x53, 0xe2, 0x47, 0xab, 0xd6, 0xf5, 0x69, 0x5c, 0x3e,
+0x5f, 0xfa, 0xae, 0x45, 0x20, 0xe5, 0xd2, 0x44, 0xff, 0x39, 0x32, 0x6d, 0xfd, 0x27, 0x57,
+0x5c, 0xfd, 0xf0, 0xde, 0xc1, 0xb5, 0x99, 0xe5, 0xf5, 0x1c, 0x77, 0x01, 0x75, 0xc5, 0x6d,
+0x58, 0x92, 0xf2, 0xb2, 0x47, 0x00, 0x01, 0x26, 0x96, 0x7a, 0x30, 0xff, 0xb7, 0xf0, 0xef,
+0x77, 0xc1, 0x8a, 0x5d, 0xdc, 0xc0, 0xd1, 0x29, 0x30, 0x1e, 0x77, 0x38, 0x7a, 0x94, 0xf1,
+0xb8, 0x7a, 0x7e, 0xef, 0xa4, 0xd1, 0xac, 0x31, 0x4a, 0xf2, 0x5d, 0x64, 0x3d, 0xb2, 0xe2,
+0xf0, 0x08, 0x99, 0xfc, 0x70, 0xee, 0x24, 0xa7, 0x7e, 0xee, 0x1e, 0x20, 0x69, 0x7d, 0x44,
+0xbf, 0x87, 0x42, 0xdf, 0x88, 0x3b, 0x0c, 0xda, 0x42, 0xc9, 0x04, 0xf9, 0x45, 0x50, 0xfc,
+0x83, 0x8f, 0x11, 0x6a, 0x72, 0xbc, 0x99, 0x95, 0xf0, 0xac, 0x3d, 0xa7, 0x3b, 0xcd, 0x1c,
+0xe2, 0x88, 0x79, 0x37, 0x11, 0x5f, 0x39, 0x89, 0x95, 0x0a, 0x16, 0x84, 0x7a, 0xf6, 0x8a,
+0xa4, 0x28, 0xe4, 0xed, 0x83, 0x80, 0x3b, 0xb1, 0x23, 0xa5, 0x03, 0x10, 0xf4, 0x66, 0xea,
+0xbb, 0x0c, 0x0f, 0xc5, 0xec, 0x6c, 0x69, 0xc5, 0xd3, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0x99,
+0x88, 0x76, 0x08, 0xa0, 0xa8, 0x95, 0x7c, 0xd8, 0x38, 0x6d, 0xcd, 0x59, 0x02, 0x51, 0x4b,
+0xf1, 0xb5, 0x2b, 0x50, 0xe3, 0xb6, 0xbd, 0xd0, 0x72, 0xcf, 0x9e, 0xfd, 0x6e, 0xbb, 0x44,
+0xc8, 0x24, 0x8a, 0x77, 0x18, 0x8a, 0x13, 0x06, 0xef, 0x97, 0x7d, 0xfa, 0x81, 0xf0, 0x31,
+0xe6, 0xfa, 0x77, 0xed, 0x31, 0x06, 0x31, 0x5b, 0x54, 0x8a, 0x9f, 0x30, 0x68, 0xdb, 0xe2,
+0x40, 0xf8, 0x4e, 0x73, 0xfa, 0xab, 0x74, 0x8b, 0x10, 0x58, 0x13, 0xdc, 0xd2, 0xe6, 0x78,
+0xd1, 0x32, 0x2e, 0x8a, 0x9f, 0x2c, 0x58, 0x06, 0x48, 0x27, 0xc5, 0xa9, 0x5e, 0x81, 0x47,
+0x89, 0x46, 0x21, 0x91, 0x03, 0x70, 0xa4, 0x3e, 0x88, 0x9c, 0xda, 0x33, 0x0a, 0xce, 0xbc,
+0x8b, 0x8e, 0xcf, 0x9f, 0xd3, 0x71, 0x80, 0x43, 0xcf, 0x6b, 0xa9, 0x51, 0x83, 0x76, 0x30,
+0x82, 0xc5, 0x6a, 0x85, 0x39, 0x11, 0x50, 0x1a, 0x82, 0xdc, 0x1e, 0x1c, 0xd5, 0x7d, 0xa9,
+0x71, 0x99, 0x33, 0x47, 0x19, 0x97, 0xb3, 0x5a, 0xb1, 0xdf, 0xed, 0xa4, 0xf2, 0xe6, 0x26,
+0x84, 0xa2, 0x28, 0x9a, 0x9e, 0xdf, 0xa6, 0x6a, 0xf4, 0xd6, 0xfc, 0x2e, 0x5b, 0x9d, 0x1a,
+0x2a, 0x27, 0x68, 0xfb, 0xc1, 0x83, 0x21, 0x4b, 0x90, 0xe0, 0x36, 0xdd, 0x5b, 0x31, 0x42,
+0x55, 0xa0, 0x13, 0xf7, 0xd0, 0x89, 0x53, 0x71, 0x99, 0x57, 0x09, 0x29, 0xc5, 0xf3, 0x21,
+0xf8, 0x37, 0x2f, 0x40, 0xf3, 0xd4, 0xaf, 0x16, 0x08, 0x36, 0x02, 0xfc, 0x77, 0xc5, 0x8b,
+0x04, 0x90, 0x56, 0xb9, 0xc9, 0x67, 0x9a, 0x99, 0xe8, 0x00, 0xd3, 0x86, 0xff, 0x97, 0x2d,
+0x08, 0xe9, 0xb7, 0xb3, 0x91, 0xbc, 0xdf, 0x45, 0xc6, 0xed, 0x0f, 0x8c, 0x4c, 0x1e, 0xe6,
+0x5b, 0x6e, 0x38, 0x30, 0xe4, 0xaa, 0xe3, 0x95, 0xde, 0xb9, 0xe4, 0x9a, 0xf5, 0xb2, 0x55,
+0x9a, 0x87, 0x9b, 0xf6, 0x6a, 0xb2, 0xf2, 0x77, 0x9a, 0x31, 0xf4, 0x7a, 0x31, 0xd1, 0x1d,
+0x04, 0xc0, 0x7c, 0x32, 0xa2, 0x9e, 0x9a, 0xf5, 0x62, 0xf8, 0x27, 0x8d, 0xbf, 0x51, 0xff,
+0xd3, 0xdf, 0x64, 0x37, 0x3f, 0x2a, 0x6f, 0x76, 0x3a, 0x7d, 0x77, 0x06, 0x9e, 0x77, 0x7f,
+0x5e, 0xeb, 0x32, 0x51, 0xf9, 0x16, 0x66, 0x9a, 0x09, 0xf3, 0xb0, 0x08, 0xa4, 0x70, 0x96,
+0x46, 0x30, 0xff, 0xda, 0x4f, 0xe9, 0x1b, 0xed, 0x8d, 0xf8, 0x74, 0x1f, 0x31, 0x92, 0xb3,
+0x73, 0x17, 0x36, 0xdb, 0x91, 0x30, 0xd6, 0x88, 0x55, 0x6b, 0x34, 0x77, 0x87, 0x7a, 0xe7,
+0xee, 0x06, 0xc6, 0x1c, 0x8c, 0x19, 0x0c, 0x48, 0x46, 0x23, 0x5e, 0x9c, 0x07, 0x5c, 0xbf,
+0xb4, 0x7e, 0xd6, 0x4f, 0x74, 0x9c, 0xe2, 0xc5, 0x50, 0x8b, 0xc5, 0x8b, 0x15, 0x90, 0x60,
+0x62, 0x57, 0x29, 0xd0, 0x13, 0x43, 0xa1, 0x80, 0x88, 0x91, 0x00, 0x44, 0xc7, 0x4d, 0x19,
+0x86, 0xcc, 0x2f, 0x2a, 0x75, 0x5a, 0xfc, 0xeb, 0x97, 0x2a, 0x70, 0xe3, 0x78, 0xd8, 0x91,
+0xb0, 0x4f, 0x99, 0x07, 0xa3, 0x95, 0xea, 0x24, 0x21, 0xd5, 0xde, 0x51, 0x20, 0x93, 0x27,
+0x0a, 0x30, 0x73, 0xa8, 0xff, 0x8a, 0x97, 0xe9, 0xa7, 0x6a, 0x8e, 0x0d, 0xe8, 0xf0, 0xdf,
+0xec, 0xea, 0xb4, 0x6c, 0x1d, 0x39, 0x2a, 0x62, 0x2d, 0x3d, 0x5a, 0x8b, 0x65, 0xf8, 0x90,
+0x05, 0x2e, 0x7e, 0x91, 0x2c, 0x78, 0xef, 0x8e, 0x7a, 0xc1, 0x2f, 0xac, 0x78, 0xee, 0xaf,
+0x28, 0x45, 0x06, 0x4c, 0x26, 0xaf, 0x3b, 0xa2, 0xdb, 0xa3, 0x93, 0x06, 0xb5, 0x3c, 0xa5,
+0xd8, 0xee, 0x8f, 0xaf, 0x25, 0xcc, 0x3f, 0x85, 0x68, 0x48, 0xa9, 0x62, 0xcc, 0x97, 0x8f,
+0x7f, 0x2a, 0xea, 0xe0, 0x15, 0x0a, 0xad, 0x62, 0x07, 0xbd, 0x45, 0xf8, 0x41, 0xd8, 0x36,
+0xcb, 0x4c, 0xdb, 0x6e, 0xe6, 0x3a, 0xe7, 0xda, 0x15, 0xe9, 0x29, 0x1e, 0x12, 0x10, 0xa0,
+0x14, 0x2c, 0x0e, 0x3d, 0xf4, 0xbf, 0x39, 0x41, 0x92, 0x75, 0x0b, 0x25, 0x7b, 0xa3, 0xce,
+0x39, 0x9c, 0x15, 0x64, 0xc8, 0xfa, 0x3d, 0xef, 0x73, 0x27, 0xfe, 0x26, 0x2e, 0xce, 0xda,
+0x6e, 0xfd, 0x71, 0x8e, 0xdd, 0xfe, 0x76, 0xee, 0xdc, 0x12, 0x5c, 0x02, 0xc5, 0x3a, 0x4e,
+0x4e, 0x4f, 0xbf, 0xca, 0x40, 0x15, 0xc7, 0x6e, 0x8d, 0x41, 0xf1, 0x10, 0xe0, 0x4f, 0x7e,
+0x97, 0x7f, 0x1c, 0xae, 0x47, 0x8e, 0x6b, 0xb1, 0x25, 0x31, 0xb0, 0x73, 0xc7, 0x1b, 0x97,
+0x79, 0xf9, 0x80, 0xd3, 0x66, 0x22, 0x30, 0x07, 0x74, 0x1e, 0xe4, 0xd0, 0x80, 0x21, 0xd6,
+0xee, 0x6b, 0x6c, 0x4f, 0xbf, 0xf5, 0xb7, 0xd9, 0x09, 0x87, 0x2f, 0xa9, 0x14, 0xbe, 0x27,
+0xd9, 0x72, 0x50, 0x01, 0xd4, 0x13, 0x73, 0xa6, 0xa7, 0x51, 0x02, 0x75, 0x25, 0xe1, 0xb3,
+0x45, 0x34, 0x7d, 0xa8, 0x8e, 0xeb, 0xf3, 0x16, 0x49, 0xcb, 0x4f, 0x8c, 0xa1, 0xb9, 0x36,
+0x85, 0x39, 0x75, 0x5d, 0x08, 0x00, 0xae, 0xeb, 0xf6, 0xea, 0xd7, 0x13, 0x3a, 0x21, 0x5a,
+0x5f, 0x30, 0x84, 0x52, 0x26, 0x95, 0xc9, 0x14, 0xf2, 0x57, 0x55, 0x6b, 0xb1, 0x10, 0xc2,
+0xe1, 0xbd, 0x3b, 0x51, 0xc0, 0xb7, 0x55, 0x4c, 0x71, 0x12, 0x26, 0xc7, 0x0d, 0xf9, 0x51,
+0xa4, 0x38, 0x02, 0x05, 0x7f, 0xb8, 0xf1, 0x72, 0x4b, 0xbf, 0x71, 0x89, 0x14, 0xf3, 0x77,
+0x38, 0xd9, 0x71, 0x24, 0xf3, 0x00, 0x11, 0xa1, 0xd8, 0xd4, 0x69, 0x27, 0x08, 0x37, 0x35,
+0xc9, 0x11, 0x9d, 0x90, 0x1c, 0x0e, 0xe7, 0x1c, 0xff, 0x2d, 0x1e, 0xe8, 0x92, 0xe1, 0x18,
+0x10, 0x95, 0x7c, 0xe0, 0x80, 0xf4, 0x96, 0x43, 0x21, 0xf9, 0x75, 0x21, 0x64, 0x38, 0xdd,
+0x9f, 0x1e, 0x95, 0x16, 0xda, 0x56, 0x1d, 0x4f, 0x9a, 0x53, 0xb2, 0xe2, 0xe4, 0x18, 0xcb,
+0x6b, 0x1a, 0x65, 0xeb, 0x56, 0xc6, 0x3b, 0xe5, 0xfe, 0xd8, 0x26, 0x3f, 0x3a, 0x84, 0x59,
+0x72, 0x66, 0xa2, 0xf3, 0x75, 0xff, 0xfb, 0x60, 0xb3, 0x22, 0xad, 0x3f, 0x2d, 0x6b, 0xf9,
+0xeb, 0xea, 0x05, 0x7c, 0xd8, 0x8f, 0x6d, 0x2c, 0x98, 0x9e, 0x2b, 0x93, 0xf1, 0x5e, 0x46,
+0xf0, 0x87, 0x49, 0x29, 0x73, 0x68, 0xd7, 0x7f, 0xf9, 0xf0, 0xe5, 0x7d, 0xdb, 0x1d, 0x75,
+0x19, 0xf3, 0xc4, 0x58, 0x9b, 0x17, 0x88, 0xa8, 0x92, 0xe0, 0xbe, 0xbd, 0x8b, 0x1d, 0x8d,
+0x9f, 0x56, 0x76, 0xad, 0xaf, 0x29, 0xe2, 0xd9, 0xd5, 0x52, 0xf6, 0xb5, 0x56, 0x35, 0x57,
+0x3a, 0xc8, 0xe1, 0x56, 0x43, 0x19, 0x94, 0xd3, 0x04, 0x9b, 0x6d, 0x35, 0xd8, 0x0b, 0x5f,
+0x4d, 0x19, 0x8e, 0xec, 0xfa, 0x64, 0x91, 0x0a, 0x72, 0x20, 0x2b, 0xbc, 0x1a, 0x4a, 0xfe,
+0x8b, 0xfd, 0xbb, 0xed, 0x1b, 0x23, 0xea, 0xad, 0x72, 0x82, 0xa1, 0x29, 0x99, 0x71, 0xbd,
+0xf0, 0x95, 0xc1, 0x03, 0xdd, 0x7b, 0xc2, 0xb2, 0x3c, 0x28, 0x54, 0xd3, 0x68, 0xa4, 0x72,
+0xc8, 0x66, 0x96, 0xe0, 0xd1, 0xd8, 0x7f, 0xf8, 0xd1, 0x26, 0x2b, 0xf7, 0xad, 0xba, 0x55,
+0xca, 0x15, 0xb9, 0x32, 0xc3, 0xe5, 0x88, 0x97, 0x8e, 0x5c, 0xfb, 0x92, 0x25, 0x8b, 0xbf,
+0xa2, 0x45, 0x55, 0x7a, 0xa7, 0x6f, 0x8b, 0x57, 0x5b, 0xcf, 0x0e, 0xcb, 0x1d, 0xfb, 0x20,
+0x82, 0x77, 0xa8, 0x8c, 0xcc, 0x16, 0xce, 0x1d, 0xfa, 0xde, 0xcc, 0x0b, 0x62, 0xfe, 0xcc,
+0xe1, 0xb7, 0xf0, 0xc3, 0x81, 0x64, 0x73, 0x40, 0xa0, 0xc2, 0x4d, 0x89, 0x11, 0x75, 0x33,
+0x55, 0x33, 0x8d, 0xe8, 0x4a, 0xfd, 0xea, 0x6e, 0x30, 0x0b, 0xd7, 0x31, 0x2c, 0xde, 0x47,
+0xe3, 0xbf, 0xf8, 0x55, 0x42, 0xe2, 0x7f, 0x59, 0xe5, 0x17, 0xef, 0x99, 0x34, 0x69, 0x91,
+0xb1, 0x23, 0x8e, 0x20, 0x87, 0x2d, 0xa8, 0xfe, 0xd5, 0x8a, 0xf3, 0x84, 0x3a, 0xf0, 0x37,
+0xe4, 0x09, 0x00, 0x54, 0xee, 0x67, 0x49, 0x93, 0xe4, 0x81, 0x70, 0xe3, 0x90, 0x4d, 0xef,
+0xfe, 0x41, 0xb7, 0x99, 0x7b, 0xc1, 0x83, 0xba, 0x62, 0x12, 0x6f, 0x7d, 0xde, 0x6b, 0xaf,
+0xda, 0x16, 0xf9, 0x55, 0x51, 0xee, 0xa6, 0x0c, 0x2b, 0x02, 0xa3, 0xfd, 0x8d, 0xfb, 0x30,
+0x17, 0xe4, 0x6f, 0xdf, 0x36, 0x71, 0xc4, 0xca, 0x87, 0x25, 0x48, 0xb0, 0x47, 0xec, 0xea,
+0xb4, 0xbf, 0xa5, 0x4d, 0x9b, 0x9f, 0x02, 0x93, 0xc4, 0xe3, 0xe4, 0xe8, 0x42, 0x2d, 0x68,
+0x81, 0x15, 0x0a, 0xeb, 0x84, 0x5b, 0xd6, 0xa8, 0x74, 0xfb, 0x7d, 0x1d, 0xcb, 0x2c, 0xda,
+0x46, 0x2a, 0x76, 0x62, 0xce, 0xbc, 0x5c, 0x9e, 0x8b, 0xe7, 0xcf, 0xbe, 0x78, 0xf5, 0x7c,
+0xeb, 0xb3, 0x3a, 0x9c, 0xaa, 0x6f, 0xcc, 0x72, 0xd1, 0x59, 0xf2, 0x11, 0x23, 0xd6, 0x3f,
+0x48, 0xd1, 0xb7, 0xce, 0xb0, 0xbf, 0xcb, 0xea, 0x80, 0xde, 0x57, 0xd4, 0x5e, 0x97, 0x2f,
+0x75, 0xd1, 0x50, 0x8e, 0x80, 0x2c, 0x66, 0x79, 0xbf, 0x72, 0x4b, 0xbd, 0x8a, 0x81, 0x6c,
+0xd3, 0xe1, 0x01, 0xdc, 0xd2, 0x15, 0x26, 0xc5, 0x36, 0xda, 0x2c, 0x1a, 0xc0, 0x27, 0x94,
+0xed, 0xb7, 0x9b, 0x85, 0x0b, 0x5e, 0x80, 0x97, 0xc5, 0xec, 0x4f, 0xec, 0x88, 0x5d, 0x50,
+0x07, 0x35, 0x47, 0xdc, 0x0b, 0x3b, 0x3d, 0xdd, 0x60, 0xaf, 0xa8, 0x5d, 0x81, 0x38, 0x24,
+0x25, 0x5d, 0x5c, 0x15, 0xd1, 0xde, 0xb3, 0xab, 0xec, 0x05, 0x69, 0xef, 0x83, 0xed, 0x57,
+0x54, 0xb8, 0x64, 0x64, 0x11, 0x16, 0x32, 0x69, 0xda, 0x9f, 0x2d, 0x7f, 0x36, 0xbb, 0x44,
+0x5a, 0x34, 0xe8, 0x7f, 0xbf, 0x03, 0xeb, 0x00, 0x7f, 0x59, 0x68, 0x22, 0x79, 0xcf, 0x73,
+0x6c, 0x2c, 0x29, 0xa7, 0xa1, 0x5f, 0x38, 0xa1, 0x1d, 0xf0, 0x20, 0x53, 0xe0, 0x1a, 0x63,
+0x14, 0x58, 0x71, 0x10, 0xaa, 0x08, 0x0c, 0x3e, 0x16, 0x1a, 0x60, 0x22, 0x82, 0x7f, 0xba,
+0xa4, 0x43, 0xa0, 0xd0, 0xac, 0x1b, 0xd5, 0x6b, 0x64, 0xb5, 0x14, 0x93, 0x31, 0x9e, 0x53,
+0x50, 0xd0, 0x57, 0x66, 0xee, 0x5a, 0x4f, 0xfb, 0x03, 0x2a, 0x69, 0x58, 0x76, 0xf1, 0x83,
+0xf7, 0x4e, 0xba, 0x8c, 0x42, 0x06, 0x60, 0x5d, 0x6d, 0xce, 0x60, 0x88, 0xae, 0xa4, 0xc3,
+0xf1, 0x03, 0xa5, 0x4b, 0x98, 0xa1, 0xff, 0x67, 0xe1, 0xac, 0xa2, 0xb8, 0x62, 0xd7, 0x6f,
+0xa0, 0x31, 0xb4, 0xd2, 0x77, 0xaf, 0x21, 0x10, 0x06, 0xc6, 0x9a, 0xff, 0x1d, 0x09, 0x17,
+0x0e, 0x5f, 0xf1, 0xaa, 0x54, 0x34, 0x4b, 0x45, 0x8a, 0x87, 0x63, 0xa6, 0xdc, 0xf9, 0x24,
+0x30, 0x67, 0xc6, 0xb2, 0xd6, 0x61, 0x33, 0x69, 0xee, 0x50, 0x61, 0x57, 0x28, 0xe7, 0x7e,
+0xee, 0xec, 0x3a, 0x5a, 0x73, 0x4e, 0xa8, 0x8d, 0xe4, 0x18, 0xea, 0xec, 0x41, 0x64, 0xc8,
+0xe2, 0xe8, 0x66, 0xb6, 0x2d, 0xb6, 0xfb, 0x6a, 0x6c, 0x16, 0xb3, 0xdd, 0x46, 0x43, 0xb9,
+0x73, 0x00, 0x6a, 0x71, 0xed, 0x4e, 0x9d, 0x25, 0x1a, 0xc3, 0x3c, 0x4a, 0x95, 0x15, 0x99,
+0x35, 0x81, 0x14, 0x02, 0xd6, 0x98, 0x9b, 0xec, 0xd8, 0x23, 0x3b, 0x84, 0x29, 0xaf, 0x0c,
+0x99, 0x83, 0xa6, 0x9a, 0x34, 0x4f, 0xfa, 0xe8, 0xd0, 0x3c, 0x4b, 0xd0, 0xfb, 0xb6, 0x68,
+0xb8, 0x9e, 0x8f, 0xcd, 0xf7, 0x60, 0x2d, 0x7a, 0x22, 0xe5, 0x7d, 0xab, 0x65, 0x1b, 0x95,
+0xa7, 0xa8, 0x7f, 0xb6, 0x77, 0x47, 0x7b, 0x5f, 0x8b, 0x12, 0x72, 0xd0, 0xd4, 0x91, 0xef,
+0xde, 0x19, 0x50, 0x3c, 0xa7, 0x8b, 0xc4, 0xa9, 0xb3, 0x23, 0xcb, 0x76, 0xe6, 0x81, 0xf0,
+0xc1, 0x04, 0x8f, 0xa3, 0xb8, 0x54, 0x5b, 0x97, 0xac, 0x19, 0xff, 0x3f, 0x55, 0x27, 0x2f,
+0xe0, 0x1d, 0x42, 0x9b, 0x57, 0xfc, 0x4b, 0x4e, 0x0f, 0xce, 0x98, 0xa9, 0x43, 0x57, 0x03,
+0xbd, 0xe7, 0xc8, 0x94, 0xdf, 0x6e, 0x36, 0x73, 0x32, 0xb4, 0xef, 0x2e, 0x85, 0x7a, 0x6e,
+0xfc, 0x6c, 0x18, 0x82, 0x75, 0x35, 0x90, 0x07, 0xf3, 0xe4, 0x9f, 0x3e, 0xdc, 0x68, 0xf3,
+0xb5, 0xf3, 0x19, 0x80, 0x92, 0x06, 0x99, 0xa2, 0xe8, 0x6f, 0xff, 0x2e, 0x7f, 0xae, 0x42,
+0xa4, 0x5f, 0xfb, 0xd4, 0x0e, 0x81, 0x2b, 0xc3, 0x04, 0xff, 0x2b, 0xb3, 0x74, 0x4e, 0x36,
+0x5b, 0x9c, 0x15, 0x00, 0xc6, 0x47, 0x2b, 0xe8, 0x8b, 0x3d, 0xf1, 0x9c, 0x03, 0x9a, 0x58,
+0x7f, 0x9b, 0x9c, 0xbf, 0x85, 0x49, 0x79, 0x35, 0x2e, 0x56, 0x7b, 0x41, 0x14, 0x39, 0x47,
+0x83, 0x26, 0xaa, 0x07, 0x89, 0x98, 0x11, 0x1b, 0x86, 0xe7, 0x73, 0x7a, 0xd8, 0x7d, 0x78,
+0x61, 0x53, 0xe9, 0x79, 0xf5, 0x36, 0x8d, 0x44, 0x92, 0x84, 0xf9, 0x13, 0x50, 0x58, 0x3b,
+0xa4, 0x6a, 0x36, 0x65, 0x49, 0x8e, 0x3c, 0x0e, 0xf1, 0x6f, 0xd2, 0x84, 0xc4, 0x7e, 0x8e,
+0x3f, 0x39, 0xae, 0x7c, 0x84, 0xf1, 0x63, 0x37, 0x8e, 0x3c, 0xcc, 0x3e, 0x44, 0x81, 0x45,
+0xf1, 0x4b, 0xb9, 0xed, 0x6b, 0x36, 0x5d, 0xbb, 0x20, 0x60, 0x1a, 0x0f, 0xa3, 0xaa, 0x55,
+0x77, 0x3a, 0xa9, 0xae, 0x37, 0x4d, 0xba, 0xb8, 0x86, 0x6b, 0xbc, 0x08, 0x50, 0xf6, 0xcc,
+0xa4, 0xbd, 0x1d, 0x40, 0x72, 0xa5, 0x86, 0xfa, 0xe2, 0x10, 0xae, 0x3d, 0x58, 0x4b, 0x97,
+0xf3, 0x43, 0x74, 0xa9, 0x9e, 0xeb, 0x21, 0xb7, 0x01, 0xa4, 0x86, 0x93, 0x97, 0xee, 0x2f,
+0x4f, 0x3b, 0x86, 0xa1, 0x41, 0x6f, 0x41, 0x26, 0x90, 0x78, 0x5c, 0x7f, 0x30, 0x38, 0x4b,
+0x3f, 0xaa, 0xec, 0xed, 0x5c, 0x6f, 0x0e, 0xad, 0x43, 0x87, 0xfd, 0x93, 0x35, 0xe6, 0x01,
+0xef, 0x41, 0x26, 0x90, 0x99, 0x9e, 0xfb, 0x19, 0x5b, 0xad, 0xd2, 0x91, 0x8a, 0xe0, 0x46,
+0xaf, 0x65, 0xfa, 0x4f, 0x84, 0xc1, 0xa1, 0x2d, 0xcf, 0x45, 0x8b, 0xd3, 0x85, 0x50, 0x55,
+0x7c, 0xf9, 0x67, 0x88, 0xd4, 0x4e, 0xe9, 0xd7, 0x6b, 0x61, 0x54, 0xa1, 0xa4, 0xa6, 0xa2,
+0xc2, 0xbf, 0x30, 0x9c, 0x40, 0x9f, 0x5f, 0xd7, 0x69, 0x2b, 0x24, 0x82, 0x5e, 0xd9, 0xd6,
+0xa7, 0x12, 0x54, 0x1a, 0xf7, 0x55, 0x9f, 0x76, 0x50, 0xa9, 0x95, 0x84, 0xe6, 0x6b, 0x6d,
+0xb5, 0x96, 0x54, 0xd6, 0xcd, 0xb3, 0xa1, 0x9b, 0x46, 0xa7, 0x94, 0x4d, 0xc4, 0x94, 0xb4,
+0x98, 0xe3, 0xe1, 0xe2, 0x34, 0xd5, 0x33, 0x16, 0x07, 0x54, 0xcd, 0xb7, 0x77, 0x53, 0xdb,
+0x4f, 0x4d, 0x46, 0x9d, 0xe9, 0xd4, 0x9c, 0x8a, 0x36, 0xb6, 0xb8, 0x38, 0x26, 0x6c, 0x0e,
+0xff, 0x9c, 0x1b, 0x43, 0x8b, 0x80, 0xcc, 0xb9, 0x3d, 0xda, 0xc7, 0xf1, 0x8a, 0xf2, 0x6d,
+0xb8, 0xd7, 0x74, 0x2f, 0x7e, 0x1e, 0xb7, 0xd3, 0x4a, 0xb4, 0xac, 0xfc, 0x79, 0x48, 0x6c,
+0xbc, 0x96, 0xb6, 0x94, 0x46, 0x57, 0x2d, 0xb0, 0xa3, 0xfc, 0x1e, 0xb9, 0x52, 0x60, 0x85,
+0x2d, 0x41, 0xd0, 0x43, 0x01, 0x1e, 0x1c, 0xd5, 0x7d, 0xfc, 0xf3, 0x96, 0x0d, 0xc7, 0xcb,
+0x2a, 0x29, 0x9a, 0x93, 0xdd, 0x88, 0x2d, 0x37, 0x5d, 0xaa, 0xfb, 0x49, 0x68, 0xa0, 0x9c,
+0x50, 0x86, 0x7f, 0x68, 0x56, 0x57, 0xf9, 0x79, 0x18, 0x39, 0xd4, 0xe0, 0x01, 0x84, 0x33,
+0x61, 0xca, 0xa5, 0xd2, 0xd6, 0xe4, 0xc9, 0x8a, 0x4a, 0x23, 0x44, 0x4e, 0xbc, 0xf0, 0xdc,
+0x24, 0xa1, 0xa0, 0xc4, 0xe2, 0x07, 0x3c, 0x10, 0xc4, 0xb5, 0x25, 0x4b, 0x65, 0x63, 0xf4,
+0x80, 0xe7, 0xcf, 0x61, 0xb1, 0x71, 0x82, 0x21, 0x87, 0x2c, 0xf5, 0x91, 0x00, 0x32, 0x0c,
+0xec, 0xa9, 0xb5, 0x9a, 0x74, 0x85, 0xe3, 0x36, 0x8f, 0x76, 0x4f, 0x9c, 0x6d, 0xce, 0xbc,
+0xad, 0x0a, 0x4b, 0xed, 0x76, 0x04, 0xcb, 0xc3, 0xb9, 0x33, 0x9e, 0x01, 0x93, 0x96, 0x69,
+0x7d, 0xc5, 0xa2, 0x45, 0x79, 0x9b, 0x04, 0x5c, 0x84, 0x09, 0xed, 0x88, 0x43, 0xc7, 0xab,
+0x93, 0x14, 0x26, 0xa1, 0x40, 0xb5, 0xce, 0x4e, 0xbf, 0x2a, 0x42, 0x85, 0x3e, 0x2c, 0x3b,
+0x54, 0xe8, 0x12, 0x1f, 0x0e, 0x97, 0x59, 0xb2, 0x27, 0x89, 0xfa, 0xf2, 0xdf, 0x8e, 0x68,
+0x59, 0xdc, 0x06, 0xbc, 0xb6, 0x85, 0x0d, 0x06, 0x22, 0xec, 0xb1, 0xcb, 0xe5, 0x04, 0xe6,
+0x3d, 0xb3, 0xb0, 0x41, 0x73, 0x08, 0x3f, 0x3c, 0x58, 0x86, 0x63, 0xeb, 0x50, 0xee, 0x1d,
+0x2c, 0x37, 0x74, 0xa9, 0xd3, 0x18, 0xa3, 0x47, 0x6e, 0x93, 0x54, 0xad, 0x0a, 0x5d, 0xb8,
+0x2a, 0x55, 0x5d, 0x78, 0xf6, 0xee, 0xbe, 0x8e, 0x3c, 0x76, 0x69, 0xb9, 0x40, 0xc2, 0x34,
+0xec, 0x2a, 0xb9, 0xed, 0x7e, 0x20, 0xe4, 0x8d, 0x00, 0x38, 0xc7, 0xe6, 0x8f, 0x44, 0xa8,
+0x86, 0xce, 0xeb, 0x2a, 0xe9, 0x90, 0xf1, 0x4c, 0xdf, 0x32, 0xfb, 0x73, 0x1b, 0x6d, 0x92,
+0x1e, 0x95, 0xfe, 0xb4, 0xdb, 0x65, 0xdf, 0x4d, 0x23, 0x54, 0x89, 0x48, 0xbf, 0x4a, 0x2e,
+0x70, 0xd6, 0xd7, 0x62, 0xb4, 0x33, 0x29, 0xb1, 0x3a, 0x33, 0x4c, 0x23, 0x6d, 0xa6, 0x76,
+0xa5, 0x21, 0x63, 0x48, 0xe6, 0x90, 0x5d, 0xed, 0x90, 0x95, 0x0b, 0x7a, 0x84, 0xbe, 0xb8,
+0x0d, 0x5e, 0x63, 0x0c, 0x62, 0x26, 0x4c, 0x14, 0x5a, 0xb3, 0xac, 0x23, 0xa4, 0x74, 0xa7,
+0x6f, 0x33, 0x30, 0x05, 0x60, 0x01, 0x42, 0xa0, 0x28, 0xb7, 0xee, 0x19, 0x38, 0xf1, 0x64,
+0x80, 0x82, 0x43, 0xe1, 0x41, 0x27, 0x1f, 0x1f, 0x90, 0x54, 0x7a, 0xd5, 0x23, 0x2e, 0xd1,
+0x3d, 0xcb, 0x28, 0xba, 0x58, 0x7f, 0xdc, 0x7c, 0x91, 0x24, 0xe9, 0x28, 0x51, 0x83, 0x6e,
+0xc5, 0x56, 0x21, 0x42, 0xed, 0xa0, 0x56, 0x22, 0xa1, 0x40, 0x80, 0x6b, 0xa8, 0xf7, 0x94,
+0xca, 0x13, 0x6b, 0x0c, 0x39, 0xd9, 0xfd, 0xe9, 0xf3, 0x6f, 0xa6, 0x9e, 0xfc, 0x70, 0x8a,
+0xb3, 0xbc, 0x59, 0x3c, 0x1e, 0x1d, 0x6c, 0xf9, 0x7c, 0xaf, 0xf9, 0x88, 0x71, 0x95, 0xeb,
+0x57, 0x00, 0xbd, 0x9f, 0x8c, 0x4f, 0xe1, 0x24, 0x83, 0xc5, 0x22, 0xea, 0xfd, 0xd3, 0x0c,
+0xe2, 0x17, 0x18, 0x7c, 0x6a, 0x4c, 0xde, 0x77, 0xb4, 0x53, 0x9b, 0x4c, 0x81, 0xcd, 0x23,
+0x60, 0xaa, 0x0e, 0x25, 0x73, 0x9c, 0x02, 0x79, 0x32, 0x30, 0xdf, 0x74, 0xdf, 0x75, 0x19,
+0xf4, 0xa5, 0x14, 0x5c, 0xf7, 0x7a, 0xa8, 0xa5, 0x91, 0x84, 0x7c, 0x60, 0x03, 0x06, 0x3b,
+0xcd, 0x50, 0xb6, 0x27, 0x9c, 0xfe, 0xb1, 0xdd, 0xcc, 0xd3, 0xb0, 0x59, 0x24, 0xb2, 0xca,
+0xe2, 0x1c, 0x81, 0x22, 0x9d, 0x07, 0x8f, 0x8e, 0xb9, 0xbe, 0x4e, 0xfa, 0xfc, 0x39, 0x65,
+0xba, 0xbf, 0x9d, 0x12, 0x37, 0x5e, 0x97, 0x7e, 0xf3, 0x89, 0xf5, 0x5d, 0xf5, 0xe3, 0x09,
+0x8c, 0x62, 0xb5, 0x20, 0x9d, 0x0c, 0x53, 0x8a, 0x68, 0x1b, 0xd2, 0x8f, 0x75, 0x17, 0x5d,
+0xd4, 0xe5, 0xda, 0x75, 0x62, 0x19, 0x14, 0x6a, 0x26, 0x2d, 0xeb, 0xf8, 0xaf, 0x37, 0xf0,
+0x6c, 0xa4, 0x55, 0xb1, 0xbc, 0xe2, 0x33, 0xc0, 0x9a, 0xca, 0xb0, 0x11, 0x49, 0x4f, 0x68,
+0x9b, 0x3b, 0x6b, 0x3c, 0xcc, 0x13, 0xf6, 0xc7, 0x85, 0x61, 0x68, 0x42, 0xae, 0xbb, 0xdd,
+0xcd, 0x45, 0x16, 0x29, 0x1d, 0xea, 0xdb, 0xc8, 0x03, 0x94, 0x3c, 0xee, 0x4f, 0x82, 0x11,
+0xc3, 0xec, 0x28, 0xbd, 0x97, 0x05, 0x99, 0xde, 0xd7, 0xbb, 0x5e, 0x22, 0x1f, 0xd4, 0xeb,
+0x64, 0xd9, 0x92, 0xd9, 0x85, 0xb7, 0x6a, 0x05, 0x6a, 0xe4, 0x24, 0x41, 0xf1, 0xcd, 0xf0,
+0xd8, 0x3f, 0xf8, 0x9e, 0x0e, 0xcd, 0x0b, 0x7a, 0x70, 0x6b, 0x5a, 0x75, 0x0a, 0x6a, 0x33,
+0x88, 0xec, 0x17, 0x75, 0x08, 0x70, 0x10, 0x2f, 0x24, 0xcf, 0xc4, 0xe9, 0x42, 0x00, 0x61,
+0x94, 0xca, 0x1f, 0x3a, 0x76, 0x06, 0xfa, 0xd2, 0x48, 0x81, 0xf0, 0x77, 0x60, 0x03, 0x45,
+0xd9, 0x61, 0xf4, 0xa4, 0x6f, 0x3d, 0xd9, 0x30, 0xc3, 0x04, 0x6b, 0x54, 0x2a, 0xb7, 0xec,
+0x3b, 0xf4, 0x4b, 0xf5, 0x68, 0x52, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xa5,
+0xa9, 0xb1, 0xe0, 0x23, 0xc4, 0x0a, 0x77, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xa5, 0xa9, 0xb1,
+0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0xeb, 0x54, 0x0b,
+0x75, 0x68, 0x52, 0x07, 0x8c, 0x9a, 0x97, 0x8d, 0x79, 0x70, 0x62, 0x46, 0xef, 0x5c, 0x1b,
+0x95, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x67, 0x4c, 0x1a, 0xb6,
+0xcf, 0xfd, 0x78, 0x53, 0x24, 0xab, 0xb5, 0xc9, 0xf1, 0x60, 0x23, 0xa5, 0xc8, 0x12, 0x87,
+0x6d, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xc7, 0x0c, 0x9a, 0x97, 0xac,
+0xda, 0x36, 0xee, 0x5e, 0x3e, 0xdf, 0x1d, 0xb8, 0xf2, 0x66, 0x2f, 0xbd, 0xf8, 0x72, 0x47,
+0xed, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x8c, 0x7b, 0x55, 0x09, 0x90, 0xa2, 0xc6, 0xef,
+0x3d, 0xf8, 0x53, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0xec, 0x5a, 0x36, 0xee, 0x5e, 0x3e, 0xdf,
+0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x59, 0x30, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x53, 0x05, 0x69,
+0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0xb0, 0xe2, 0x27, 0xcc, 0xfb, 0x74,
+0x4b, 0x14, 0x8b, 0x94, 0x8b, 0x75, 0x68, 0x33, 0xc5, 0x08, 0x92, 0x87, 0x8c, 0x9a, 0xb6,
+0xcf, 0x1c, 0xba, 0xd7, 0x0d, 0x98, 0xb2, 0xe6, 0x2f, 0xdc, 0x1b, 0x95, 0x89, 0x71, 0x60,
+0x23, 0xc4, 0x0a, 0x96, 0x8f, 0x9c, 0xba, 0xf6, 0x6e, 0x3f, 0xfc, 0x5b, 0x15, 0xa8, 0xd2,
+0x26, 0xaf, 0xbd, 0xf8, 0x72, 0x66, 0x2f, 0xdc, 0x1b, 0xb4, 0xcb, 0x14, 0x8b, 0x94, 0xaa,
+0xb7, 0xcd, 0xf9, 0x51, 0x01, 0x80, 0x82, 0x86, 0x6f, 0x3d, 0xd9, 0x30, 0xe2, 0x27, 0xcc,
+0xfb, 0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x70, 0x43, 0x04, 0x6b, 0x35, 0xc9, 0xf1,
+0x60, 0x23, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xe6, 0x2f, 0xbd,
+0xf8, 0x72, 0x66, 0x4e, 0x1e, 0xbe, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x1d, 0x99, 0x91, 0xa0,
+0xa3, 0xc4, 0x0a, 0x77, 0x4d, 0x18, 0x93, 0xa4, 0xab, 0xd4, 0x0b, 0x75, 0x49, 0x10, 0xa2,
+0xc6, 0xef, 0x3d, 0xf8, 0x53, 0x24, 0xab, 0xb5, 0xe8, 0x33, 0xe4, 0x4a, 0x16, 0xae, 0xde,
+0x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xb3, 0xc5, 0x08, 0x73, 0x45, 0xe9, 0x31, 0xc1, 0xe1, 0x21,
+0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x86, 0x6f, 0x5c, 0x3a, 0xd7, 0x0d, 0x98, 0x93, 0xa4, 0xca,
+0x16, 0xae, 0xde, 0x1f, 0x9d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x72, 0x47, 0x0c,
+0x9a, 0xb6, 0xcf, 0xfd, 0x59, 0x11, 0xa0, 0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87,
+0x6d, 0x39, 0xf0, 0x43, 0x04, 0x8a, 0x96, 0xae, 0xde, 0x3e, 0xdf, 0x1d, 0x99, 0x91, 0xa0,
+0xc2, 0x06, 0x6f, 0x3d, 0xf8, 0x72, 0x47, 0x0c, 0x9a, 0x97, 0x8d, 0x98, 0x93, 0x85, 0x88,
+0x73, 0x45, 0xe9, 0x31, 0xe0, 0x23, 0xa5, 0xa9, 0xd0, 0x03, 0x84, 0x8a, 0x96, 0xae, 0xde,
+0x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xd2, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0x81, 0x80, 0x82,
+0x67, 0x2d, 0xd8, 0x13, 0xa4, 0xab, 0xd4, 0x0b, 0x94, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20,
+0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0xe9, 0x50, 0x22, 0xc6, 0xef, 0x5c, 0x3a, 0xd7, 0x0d, 0x98,
+0x93, 0x85, 0x88, 0x73, 0x64, 0x4a, 0xf7, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0x0a, 0x96,
+0xae, 0xde, 0x3e, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x78, 0x72,
+0x66, 0x2f, 0xbd, 0xd9, 0x30, 0xc3, 0xe5, 0x48, 0x12, 0x87, 0x8c, 0x7b, 0x55, 0x28, 0xd2,
+0x07, 0x8c, 0x9a, 0x97, 0xac, 0xda, 0x17, 0x8d, 0x79, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x54,
+0x0b, 0x94, 0x8b, 0x94, 0xaa, 0xd6, 0x2e, 0xbf, 0xfc, 0x5b, 0x15, 0xa8, 0xd2, 0x26, 0xaf,
+0xdc, 0x1b, 0xb4, 0xea, 0x37, 0xec, 0x3b, 0xf4, 0x6a, 0x37, 0xcd, 0x18, 0x93, 0x85, 0x69,
+0x31, 0xc1, 0xe1, 0x40, 0xe3, 0x25, 0xc8, 0x12, 0x87, 0x8c, 0x9a, 0xb6, 0xcf, 0xfd, 0x59,
+0x11, 0xa0, 0xc2, 0x06, 0x8e, 0x7f, 0x5d, 0x38, 0xf2, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x37,
+0xec, 0x5a, 0x36, 0xee, 0x3f, 0xfc, 0x7a, 0x76, 0x4f, 0x1c, 0x9b, 0x95, 0x89, 0x71, 0x41,
+0x00, 0x63, 0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x0f, 0x9c, 0xba, 0xd7, 0x0d, 0x98, 0x93, 0x85,
+0x69, 0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x9e, 0xbe, 0xdf, 0x3c, 0xfa, 0x57, 0x2c, 0xda,
+0x36, 0xee, 0x3f, 0xfc, 0x5b, 0x15, 0x89, 0x71, 0x41, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d,
+0x38, 0xf2, 0x47, 0xed, 0x58, 0x13, 0xa4, 0xca, 0xf7, 0x4d, 0xf9, 0x51, 0x01, 0x80, 0x63,
+0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0x91, 0xa0, 0xa3, 0xa5, 0xa9, 0xb1,
+0xe0, 0x42, 0x06, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0x0a, 0x96, 0x8f, 0x7d,
+0x78, 0x72, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0xbc, 0xfa, 0x57, 0x0d,
+0x79, 0x51, 0x01, 0x61, 0x21, 0xa1, 0xc0, 0xe3, 0x25, 0xa9, 0xb1, 0xc1, 0xe1, 0x40, 0x02,
+0x67, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0x93, 0xa4, 0xab, 0xd4, 0x2a, 0xd6, 0x0f, 0x9c, 0x9b,
+0xb4, 0xcb, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x35, 0xc9, 0xf1,
+0x60, 0x42, 0x06, 0x8e, 0x7f, 0x7c, 0x7a, 0x76, 0x6e, 0x3f, 0xfc, 0x7a, 0x76, 0x6e, 0x5e,
+0x3e, 0xfe, 0x7e, 0x5f, 0x3c, 0xdb, 0x15, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xc0, 0xe3, 0x44,
+0xeb, 0x54, 0x2a, 0xb7, 0xcd, 0xf9, 0x70, 0x62, 0x27, 0xad, 0xd8, 0x32, 0xc7, 0x0c, 0x7b,
+0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xec, 0x3b, 0xd5, 0x28, 0xd2, 0x07, 0x6d, 0x39, 0xd1, 0x20,
+0xc2, 0xe7, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0xb2, 0xc7, 0x0c, 0x59, 0x28, 0xf3, 0x9b };
+
+// clang-format off
diff --git a/drivers/serial.h b/drivers/serial.h
new file mode 100644
index 0000000000..d9c2a69e96
--- /dev/null
+++ b/drivers/serial.h
@@ -0,0 +1,46 @@
+/* Copyright 2021 QMK
+ *
+ * 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 <transactions.h>
+
+// initiator is transaction start side
+void soft_serial_initiator_init(void);
+// target is interrupt accept side
+void soft_serial_target_init(void);
+
+// initiator result
+#define TRANSACTION_END 0
+#define TRANSACTION_NO_RESPONSE 0x1
+#define TRANSACTION_DATA_ERROR 0x2
+#define TRANSACTION_TYPE_ERROR 0x4
+int soft_serial_transaction(int sstd_index);
+
+// target status
+// *SSTD_t.status has
+// initiator:
+// TRANSACTION_END
+// or TRANSACTION_NO_RESPONSE
+// or TRANSACTION_DATA_ERROR
+// target:
+// TRANSACTION_DATA_ERROR
+// or TRANSACTION_ACCEPTED
+#define TRANSACTION_ACCEPTED 0x8
+int soft_serial_get_and_clean_status(int sstd_index);