summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/arm/i2c_master.c2
-rw-r--r--drivers/arm/i2c_master.h28
-rw-r--r--drivers/arm/ws2812.c96
-rw-r--r--drivers/arm/ws2812.h16
-rw-r--r--drivers/avr/analog.c110
-rw-r--r--drivers/avr/analog.h37
-rw-r--r--drivers/avr/ws2812.c141
-rw-r--r--drivers/avr/ws2812.h3
-rw-r--r--drivers/avr/ws2812_i2c.c12
-rw-r--r--drivers/gpio/pca9555.c17
-rw-r--r--drivers/gpio/pca9555.h2
-rw-r--r--drivers/haptic/DRV2605L.c12
-rw-r--r--drivers/haptic/haptic.c85
-rw-r--r--drivers/haptic/haptic.h16
-rw-r--r--drivers/haptic/solenoid.h6
-rw-r--r--drivers/issi/is31fl3733.c50
-rw-r--r--drivers/issi/is31fl3733.h4
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;
+