diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/arm/i2c_master.c | 2 | ||||
-rw-r--r-- | drivers/arm/i2c_master.h | 28 | ||||
-rw-r--r-- | drivers/arm/ws2812.c | 96 | ||||
-rw-r--r-- | drivers/arm/ws2812.h | 16 | ||||
-rw-r--r-- | drivers/avr/analog.c | 110 | ||||
-rw-r--r-- | drivers/avr/analog.h | 37 | ||||
-rw-r--r-- | drivers/avr/ws2812.c | 141 | ||||
-rw-r--r-- | drivers/avr/ws2812.h | 3 | ||||
-rw-r--r-- | drivers/avr/ws2812_i2c.c | 12 | ||||
-rw-r--r-- | drivers/gpio/pca9555.c | 17 | ||||
-rw-r--r-- | drivers/gpio/pca9555.h | 2 | ||||
-rw-r--r-- | drivers/haptic/DRV2605L.c | 12 | ||||
-rw-r--r-- | drivers/haptic/haptic.c | 85 | ||||
-rw-r--r-- | drivers/haptic/haptic.h | 16 | ||||
-rw-r--r-- | drivers/haptic/solenoid.h | 6 | ||||
-rw-r--r-- | drivers/issi/is31fl3733.c | 50 | ||||
-rw-r--r-- | drivers/issi/is31fl3733.h | 4 |
17 files changed, 354 insertions, 283 deletions
diff --git a/drivers/arm/i2c_master.c b/drivers/arm/i2c_master.c index 2a43ba2393..b9eff0ad2e 100644 --- a/drivers/arm/i2c_master.c +++ b/drivers/arm/i2c_master.c @@ -62,7 +62,7 @@ __attribute__((weak)) void i2c_init(void) { palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT); chThdSleepMilliseconds(10); -#ifdef USE_I2CV1 +#if defined(USE_GPIOV1) palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); #else diff --git a/drivers/arm/i2c_master.h b/drivers/arm/i2c_master.h index a8ed66403a..31cbfb9774 100644 --- a/drivers/arm/i2c_master.h +++ b/drivers/arm/i2c_master.h @@ -1,9 +1,9 @@ /* Copyright 2018 Jack Humbert * Copyright 2018 Yiancar * - * This program is free sofare: you can redistribute it and/or modify + * 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 Sofare Foundation, either version 2 of the License, or + * 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, @@ -27,7 +27,7 @@ #include "ch.h" #include <hal.h> -#if defined(STM32F1XX) || defined(STM32F1xx) || defined(STM32F2xx) || defined(STM32F4xx) || defined(STM32L0xx) || defined(STM32L1xx) +#if defined(STM32F1XX) || defined(STM32F1xx) || defined(STM32F2xx) || defined(STM32F4xx) || defined(STM32F4XX) || defined(STM32L0xx) || defined(STM32L1xx) # define USE_I2CV1 #endif @@ -51,6 +51,20 @@ # define I2C1_SDA 7 #endif +#if defined(STM32F1XX) || defined(STM32F1xx) +# define USE_GPIOV1 +#endif + +#ifndef USE_GPIOV1 +// 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 + #ifdef USE_I2CV1 # ifndef I2C1_OPMODE # define I2C1_OPMODE OPMODE_I2C @@ -62,14 +76,6 @@ # define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */ # 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 - // 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 diff --git a/drivers/arm/ws2812.c b/drivers/arm/ws2812.c index 2094e50098..bdca565d88 100644 --- a/drivers/arm/ws2812.c +++ b/drivers/arm/ws2812.c @@ -1 +1,95 @@ -#error("NOT SUPPORTED")
\ No newline at end of file +#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 + +#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 10000 // 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) { setPinOutput(RGB_DI_PIN); } + +// 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 + sendByte(ledarray[i].g); + sendByte(ledarray[i].r); + sendByte(ledarray[i].b); +#ifdef RGBW + sendByte(ledarray[i].w); +#endif + } + + wait_ns(RES); + + chSysUnlock(); +} diff --git a/drivers/arm/ws2812.h b/drivers/arm/ws2812.h new file mode 100644 index 0000000000..41c22a00b8 --- /dev/null +++ b/drivers/arm/ws2812.h @@ -0,0 +1,16 @@ +#pragma once + +#include "quantum/color.h" + +/* User Interface + * + * Input: + * ledarray: An array of GRB data describing the LED colors + * number_of_leds: The number of LEDs to write + * + * The functions will perform the following actions: + * - Set the data-out pin as output + * - Send out the LED data + * - Wait 50us to reset the LEDs + */ +void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c index 1a8da4261d..abe478b712 100644 --- a/drivers/avr/analog.c +++ b/drivers/avr/analog.c @@ -14,24 +14,31 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -// Simple analog to digitial conversion - #include <avr/io.h> #include <avr/pgmspace.h> #include <stdint.h> #include "analog.h" -static uint8_t aref = (1 << REFS0); // default to AREF = Vcc +static uint8_t aref = ADC_REF_POWER; -void analogReference(uint8_t mode) { aref = mode & 0xC0; } +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__) - static const uint8_t PROGMEM pin_to_mux[] = {0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20}; + // 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_AT90USB1286__) +#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega328P__) if (pin >= 8) return 0; return adc_read(pin); #else @@ -39,20 +46,87 @@ int16_t analogRead(uint8_t pin) { #endif } -// Mux input +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__) + 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 + } +} + int16_t adc_read(uint8_t mux) { -#if defined(__AVR_AT90USB162__) - return 0; -#else uint8_t low; - ADCSRA = (1 << ADEN) | ADC_PRESCALER; // enable ADC - ADCSRB = (1 << ADHSM) | (mux & 0x20); // high speed mode - ADMUX = aref | (mux & 0x1F); // configure mux input - ADCSRA = (1 << ADEN) | ADC_PRESCALER | (1 << ADSC); // start the conversion - while (ADCSRA & (1 << ADSC)) - ; // wait for result - low = ADCL; // must read LSB first - return (ADCH << 8) | low; // must read MSB only once! + // 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! + return (ADCH << 8) | low; } diff --git a/drivers/avr/analog.h b/drivers/avr/analog.h index 1b773d82ce..058882450d 100644 --- a/drivers/avr/analog.h +++ b/drivers/avr/analog.h @@ -14,45 +14,40 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _analog_h_included__ -#define _analog_h_included__ +#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_POWER (1 << REFS0) -#define ADC_REF_INTERNAL ((1 << REFS1) | (1 << REFS0)) -#define ADC_REF_EXTERNAL (0) +#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 -# define ADC_PRESCALER ((1 << ADPS2) | (1 << ADPS1)) +#if F_CPU == 16000000L || F_CPU == 12000000L +# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS1)) // /64 #elif F_CPU == 8000000L -# define ADC_PRESCALER ((1 << ADPS2) | (1 << ADPS0)) +# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS0)) // /32 #elif F_CPU == 4000000L -# define ADC_PRESCALER ((1 << ADPS2)) +# define ADC_PRESCALER (_BV(ADPS2)) // /16 #elif F_CPU == 2000000L -# define ADC_PRESCALER ((1 << ADPS1) | (1 << ADPS0)) +# define ADC_PRESCALER (_BV(ADPS1) | _BV(ADPS0)) // /8 #elif F_CPU == 1000000L -# define ADC_PRESCALER ((1 << ADPS1)) +# define ADC_PRESCALER _BV(ADPS1) // /4 #else -# define ADC_PRESCALER ((1 << ADPS0)) -#endif - -// some avr-libc versions do not properly define ADHSM -#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) -# if !defined(ADHSM) -# define ADHSM (7) -# endif -#endif - +# define ADC_PRESCALER _BV(ADPS0) // /2 #endif diff --git a/drivers/avr/ws2812.c b/drivers/avr/ws2812.c index 5c733c4ab0..82d985c20a 100644 --- a/drivers/avr/ws2812.c +++ b/drivers/avr/ws2812.c @@ -36,109 +36,6 @@ void ws2812_sendarray(uint8_t *array, uint16_t length); void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask); - -#ifdef RGBW_BB_TWI - -// Port for the I2C -# define I2C_DDR DDRD -# define I2C_PIN PIND -# define I2C_PORT PORTD - -// Pins to be used in the bit banging -# define I2C_CLK 0 -# define I2C_DAT 1 - -# define I2C_DATA_HI() \ - I2C_DDR &= ~(1 << I2C_DAT); \ - I2C_PORT |= (1 << I2C_DAT); -# define I2C_DATA_LO() \ - I2C_DDR |= (1 << I2C_DAT); \ - I2C_PORT &= ~(1 << I2C_DAT); - -# define I2C_CLOCK_HI() \ - I2C_DDR &= ~(1 << I2C_CLK); \ - I2C_PORT |= (1 << I2C_CLK); -# define I2C_CLOCK_LO() \ - I2C_DDR |= (1 << I2C_CLK); \ - I2C_PORT &= ~(1 << I2C_CLK); - -# define I2C_DELAY 1 - -void I2C_WriteBit(unsigned char c) { - if (c > 0) { - I2C_DATA_HI(); - } else { - I2C_DATA_LO(); - } - - I2C_CLOCK_HI(); - _delay_us(I2C_DELAY); - - I2C_CLOCK_LO(); - _delay_us(I2C_DELAY); - - if (c > 0) { - I2C_DATA_LO(); - } - - _delay_us(I2C_DELAY); -} - -// Inits bitbanging port, must be called before using the functions below -// -void I2C_Init(void) { - I2C_PORT &= ~((1 << I2C_DAT) | (1 << I2C_CLK)); - - I2C_CLOCK_HI(); - I2C_DATA_HI(); - - _delay_us(I2C_DELAY); -} - -// Send a START Condition -// -void I2C_Start(void) { - // set both to high at the same time - I2C_DDR &= ~((1 << I2C_DAT) | (1 << I2C_CLK)); - _delay_us(I2C_DELAY); - - I2C_DATA_LO(); - _delay_us(I2C_DELAY); - - I2C_CLOCK_LO(); - _delay_us(I2C_DELAY); -} - -// Send a STOP Condition -// -void I2C_Stop(void) { - I2C_CLOCK_HI(); - _delay_us(I2C_DELAY); - - I2C_DATA_HI(); - _delay_us(I2C_DELAY); -} - -// write a byte to the I2C slave device -// -unsigned char I2C_Write(unsigned char c) { - for (char i = 0; i < 8; i++) { - I2C_WriteBit(c & 128); - - c <<= 1; - } - - I2C_WriteBit(0); - _delay_us(I2C_DELAY); - _delay_us(I2C_DELAY); - - // _delay_us(I2C_DELAY); - // return I2C_ReadBit(); - return 0; -} - -#endif - // Setleds for standard RGB void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin)); @@ -146,45 +43,15 @@ void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { } void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) { - // ws2812_DDRREG |= pinmask; // Enable DDR // new universal format (DDR) _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask; - ws2812_sendarray_mask((uint8_t *)ledarray, leds + leds + leds, pinmask); - _delay_us(50); -} - -// Setleds for SK6812RGBW -void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds) { -#ifdef RGBW_BB_TWI - uint8_t sreg_prev, twcr_prev; - sreg_prev = SREG; - twcr_prev = TWCR; - cli(); - TWCR &= ~(1 << TWEN); - I2C_Init(); - I2C_Start(); - I2C_Write(0x84); - uint16_t datlen = leds << 2; - uint8_t curbyte; - uint8_t *data = (uint8_t *)ledarray; - while (datlen--) { - curbyte = *data++; - I2C_Write(curbyte); - } - I2C_Stop(); - SREG = sreg_prev; - TWCR = twcr_prev; -#endif - - // ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR - // new universal format (DDR) - _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF); - - ws2812_sendarray_mask((uint8_t *)ledarray, leds << 2, _BV(RGB_DI_PIN & 0xF)); + ws2812_sendarray_mask((uint8_t *)ledarray, leds * sizeof(LED_TYPE), pinmask); -#ifndef RGBW_BB_TWI +#ifdef RGBW _delay_us(80); +#else + _delay_us(50); #endif } diff --git a/drivers/avr/ws2812.h b/drivers/avr/ws2812.h index 9652b94bbe..b869fb28c8 100644 --- a/drivers/avr/ws2812.h +++ b/drivers/avr/ws2812.h @@ -34,8 +34,7 @@ * The functions will perform the following actions: * - Set the data-out pin as output * - Send out the LED data - * - Wait 50�s to reset the LEDs + * - Wait 50us to reset the LEDs */ void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask); -void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); diff --git a/drivers/avr/ws2812_i2c.c b/drivers/avr/ws2812_i2c.c index 8525a026c7..1c332e24b6 100644 --- a/drivers/avr/ws2812_i2c.c +++ b/drivers/avr/ws2812_i2c.c @@ -1,6 +1,10 @@ #include "ws2812.h" #include "i2c_master.h" +#ifdef RGBW +# error "RGBW not supported" +#endif + #ifndef WS2812_ADDRESS # define WS2812_ADDRESS 0xb0 #endif @@ -21,11 +25,3 @@ void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { i2c_transmit(WS2812_ADDRESS, (uint8_t *)ledarray, sizeof(LED_TYPE) * leds, WS2812_TIMEOUT); } - -// Setleds for SK6812RGBW -void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds) { -// not supported - for now error out if its enabled -#ifdef RGBW -# error "RGBW not supported" -#endif -} diff --git a/drivers/gpio/pca9555.c b/drivers/gpio/pca9555.c index 496bbca04e..02b5abbdde 100644 --- a/drivers/gpio/pca9555.c +++ b/drivers/gpio/pca9555.c @@ -76,3 +76,20 @@ uint8_t pca9555_readPins(uint8_t slave_addr, uint8_t port) { } return data; } + +uint16_t pca9555_readAllPins(uint8_t slave_addr) { + uint8_t addr = SLAVE_TO_ADDR(slave_addr); + + typedef union { + uint8_t u8[2]; + uint16_t u16; + } data16; + + data16 data; + + i2c_status_t ret = i2c_readReg(addr, CMD_INPUT_0, &data.u8[0], sizeof(data), TIMEOUT); + if (ret != I2C_STATUS_SUCCESS) { + print("pca9555_readAllPins::FAILED\n"); + } + return data.u16; +} diff --git a/drivers/gpio/pca9555.h b/drivers/gpio/pca9555.h index ebb97e2f30..3341ec3eb5 100644 --- a/drivers/gpio/pca9555.h +++ b/drivers/gpio/pca9555.h @@ -53,3 +53,5 @@ void pca9555_set_config(uint8_t slave_addr, uint8_t port, uint8_t conf); void pca9555_set_output(uint8_t slave_addr, uint8_t port, uint8_t conf); uint8_t pca9555_readPins(uint8_t slave_addr, uint8_t port); + +uint16_t pca9555_readAllPins(uint8_t slave_addr); diff --git a/drivers/haptic/DRV2605L.c b/drivers/haptic/DRV2605L.c index 728554b01e..c40731913b 100644 --- a/drivers/haptic/DRV2605L.c +++ b/drivers/haptic/DRV2605L.c @@ -115,15 +115,13 @@ void DRV_init(void) { } void DRV_rtp_init(void) { - DRV_write(DRV_GO, 0x00); - DRV_write(DRV_RTP_INPUT, 20); //20 is the lowest value I've found where haptics can still be felt. - DRV_write(DRV_MODE, 0x05); - DRV_write(DRV_GO, 0x01); + DRV_write(DRV_GO, 0x00); + DRV_write(DRV_RTP_INPUT, 20); // 20 is the lowest value I've found where haptics can still be felt. + DRV_write(DRV_MODE, 0x05); + DRV_write(DRV_GO, 0x01); } -void DRV_amplitude(uint8_t amplitude) { - DRV_write(DRV_RTP_INPUT, amplitude); -} +void DRV_amplitude(uint8_t amplitude) { DRV_write(DRV_RTP_INPUT, amplitude); } void DRV_pulse(uint8_t sequence) { DRV_write(DRV_GO, 0x00); diff --git a/drivers/haptic/haptic.c b/drivers/haptic/haptic.c index 989970beee..2ce279b753 100644 --- a/drivers/haptic/haptic.c +++ b/drivers/haptic/haptic.c @@ -169,12 +169,12 @@ void haptic_set_mode(uint8_t 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 + 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) { @@ -211,52 +211,50 @@ uint8_t haptic_get_dwell(void) { } 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 + 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 + 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); + 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); + 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); + 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; @@ -269,7 +267,6 @@ void haptic_play(void) { } bool process_haptic(uint16_t keycode, keyrecord_t *record) { - if (keycode == HPT_ON && record->event.pressed) { haptic_enable(); } @@ -300,16 +297,16 @@ bool process_haptic(uint16_t keycode, keyrecord_t *record) { if (keycode == HPT_DWLD && record->event.pressed) { haptic_dwell_decrease(); } - if (keycode == HPT_CONT && record->event.pressed) { - haptic_toggle_continuous(); + if (keycode == HPT_CONT && record->event.pressed) { + haptic_toggle_continuous(); } - if (keycode == HPT_CONI && record->event.pressed) { - haptic_cont_increase(); + if (keycode == HPT_CONI && record->event.pressed) { + haptic_cont_increase(); } - if (keycode == HPT_COND && record->event.pressed) { - haptic_cont_decrease(); + if (keycode == HPT_COND && record->event.pressed) { + haptic_cont_decrease(); } - + if (haptic_config.enable) { if (record->event.pressed) { // keypress diff --git a/drivers/haptic/haptic.h b/drivers/haptic/haptic.h index 2f6eb31fc2..5d3bd1c310 100644 --- a/drivers/haptic/haptic.h +++ b/drivers/haptic/haptic.h @@ -34,14 +34,14 @@ 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; - uint16_t reserved :7; + 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; + uint16_t reserved : 7; }; } haptic_config_t; diff --git a/drivers/haptic/solenoid.h b/drivers/haptic/solenoid.h index 53dc626e33..dd6ececa68 100644 --- a/drivers/haptic/solenoid.h +++ b/drivers/haptic/solenoid.h @@ -29,12 +29,8 @@ # define SOLENOID_MIN_DWELL 4 #endif -#ifndef SOLENOID_ACTIVE -# define SOLENOID_ACTIVE false -#endif - #ifndef SOLENOID_PIN -# define SOLENOID_PIN F6 +# error SOLENOID_PIN not defined #endif void solenoid_buzz_on(void); diff --git a/drivers/issi/is31fl3733.c b/drivers/issi/is31fl3733.c index cc2d895efd..e60f0e878e 100644 --- a/drivers/issi/is31fl3733.c +++ b/drivers/issi/is31fl3733.c @@ -24,10 +24,10 @@ # include "wait.h" #endif -#include "is31fl3733.h" #include <string.h> #include "i2c_master.h" #include "progmem.h" +#include "is31fl3733.h" // 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) @@ -80,43 +80,54 @@ bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false}; uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}, {0}}; bool g_led_control_registers_update_required[DRIVER_COUNT] = {false}; -void IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) { +bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + // If the transaction fails function returns false. g_twi_transfer_buffer[0] = reg; g_twi_transfer_buffer[1] = data; #if ISSI_PERSISTENCE > 0 for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0) break; + if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) != 0) { + return false; + } } #else - i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT); + if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) != 0) { + return false; + } #endif + return true; } -void IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // assumes PG1 is already selected - - // transmit PWM registers in 12 transfers of 16 bytes +bool IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // Assumes PG1 is already selected. + // If any of the transactions fails function returns false. + // Transmit PWM registers in 12 transfers of 16 bytes. // g_twi_transfer_buffer[] is 20 bytes - // iterate over the pwm_buffer contents at 16 byte intervals + // Iterate over the pwm_buffer contents at 16 byte intervals. for (int i = 0; i < 192; i += 16) { g_twi_transfer_buffer[0] = i; - // copy the data from i to i+15 - // device will auto-increment register for data after the first byte - // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer + // Copy the data from i to i+15. + // Device will auto-increment register for data after the first byte + // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. for (int j = 0; j < 16; j++) { g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; } #if ISSI_PERSISTENCE > 0 for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0) break; + |