aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/arm/i2c_master.c5
-rw-r--r--drivers/arm/i2c_master.h23
-rw-r--r--drivers/arm/ws2812.c2
-rw-r--r--drivers/arm/ws2812_spi.c91
-rw-r--r--drivers/avr/analog.c110
-rw-r--r--drivers/avr/analog.h37
-rw-r--r--drivers/gpio/pca9555.c17
-rw-r--r--drivers/gpio/pca9555.h2
-rw-r--r--drivers/haptic/DRV2605L.c11
-rw-r--r--drivers/issi/is31fl3218.h1
-rw-r--r--drivers/issi/is31fl3731-simple.c15
-rw-r--r--drivers/issi/is31fl3731-simple.h8
-rw-r--r--drivers/issi/is31fl3731.c18
-rw-r--r--drivers/issi/is31fl3731.h5
-rw-r--r--drivers/issi/is31fl3733.c65
-rw-r--r--drivers/issi/is31fl3733.h9
-rw-r--r--drivers/issi/is31fl3736.c21
-rw-r--r--drivers/issi/is31fl3737.c23
-rw-r--r--drivers/issi/is31fl3737.h5
-rw-r--r--drivers/oled/oled_driver.h2
20 files changed, 291 insertions, 179 deletions
diff --git a/drivers/arm/i2c_master.c b/drivers/arm/i2c_master.c
index 2a43ba239..21aefd497 100644
--- a/drivers/arm/i2c_master.c
+++ b/drivers/arm/i2c_master.c
@@ -24,9 +24,8 @@
* 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 "i2c_master.h"
#include "quantum.h"
+#include "i2c_master.h"
#include <string.h>
#include <hal.h>
@@ -62,7 +61,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 efe3909a6..3d3891289 100644
--- a/drivers/arm/i2c_master.h
+++ b/drivers/arm/i2c_master.h
@@ -27,10 +27,6 @@
#include "ch.h"
#include <hal.h>
-#if defined(STM32F1XX) || defined(STM32F1xx) || defined(STM32F2xx) || defined(STM32F4xx) || defined(STM32L0xx) || defined(STM32L1xx)
-# define USE_I2CV1
-#endif
-
#ifdef I2C1_BANK
# define I2C1_SCL_BANK I2C1_BANK
# define I2C1_SDA_BANK I2C1_BANK
@@ -62,14 +58,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
@@ -93,6 +81,16 @@
# define I2C_DRIVER I2CD1
#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
+
typedef int16_t i2c_status_t;
#define I2C_STATUS_SUCCESS (0)
@@ -103,7 +101,6 @@ 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_transmit_receive(uint8_t address, uint8_t* tx_body, uint16_t tx_length, uint8_t* rx_body, uint16_t rx_length);
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/arm/ws2812.c b/drivers/arm/ws2812.c
index fa702fca9..bdca565d8 100644
--- a/drivers/arm/ws2812.c
+++ b/drivers/arm/ws2812.c
@@ -6,7 +6,7 @@
/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
#ifndef NOP_FUDGE
-# if defined(STM32F1XX) || defined(STM32F1xx) || defined(STM32F0XX) || defined(STM32F0xx) || defined(STM32F3XX) || defined(STM32F3xx) || defined(STM32L0XX) || defined(STM32L0xx)
+# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
# define NOP_FUDGE 0.4
# else
# error("NOP_FUDGE configuration required")
diff --git a/drivers/arm/ws2812_spi.c b/drivers/arm/ws2812_spi.c
index 2094e5009..0e954ec50 100644
--- a/drivers/arm/ws2812_spi.c
+++ b/drivers/arm/ws2812_spi.c
@@ -1 +1,90 @@
-#error("NOT SUPPORTED") \ No newline at end of file
+#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
+
+#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 200
+#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];
+
+ 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);
+}
+
+void ws2812_init(void) {
+#if defined(USE_GPIOV1)
+ palSetLineMode(RGB_DI_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+#else
+ palSetLineMode(RGB_DI_PIN, PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL);
+#endif
+
+ // TODO: more dynamic baudrate
+ static const SPIConfig spicfg = {
+ NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN),
+ SPI_CR1_BR_1 | SPI_CR1_BR_0 // baudrate : fpclk / 8 => 1tick is 0.32us (2.25 MHz)
+ };
+
+ spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */
+ spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters. */
+ spiSelect(&WS2812_SPI); /* Slave Select assertion. */
+}
+
+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).
+#ifdef WS2812_SPI_SYNC
+ spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf);
+#else
+ spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf);
+#endif
+}
diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c
index 1a8da4261..abe478b71 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 1b773d82c..058882450 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/gpio/pca9555.c b/drivers/gpio/pca9555.c
index 496bbca04..02b5abbdd 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 ebb97e2f3..3341ec3eb 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 c40731913..830d629da 100644
--- a/drivers/haptic/DRV2605L.c
+++ b/drivers/haptic/DRV2605L.c
@@ -32,16 +32,9 @@ void DRV_write(uint8_t drv_register, uint8_t settings) {
}
uint8_t DRV_read(uint8_t regaddress) {
-#ifdef __AVR__
i2c_readReg(DRV2605L_BASE_ADDRESS << 1, regaddress, DRV2605L_read_buffer, 1, 100);
DRV2605L_read_register = (uint8_t)DRV2605L_read_buffer[0];
-#else
- DRV2605L_tx_register[0] = regaddress;
- if (MSG_OK != i2c_transmit_receive(DRV2605L_BASE_ADDRESS << 1, DRV2605L_tx_register, 1, DRV2605L_read_buffer, 1)) {
- printf("err reading reg \n");
- }
- DRV2605L_read_register = (uint8_t)DRV2605L_read_buffer[0];
-#endif
+
return DRV2605L_read_register;
}
@@ -127,4 +120,4 @@ void DRV_pulse(uint8_t sequence) {
DRV_write(DRV_GO, 0x00);
DRV_write(DRV_WAVEFORM_SEQ_1, sequence);
DRV_write(DRV_GO, 0x01);
-} \ No newline at end of file
+}
diff --git a/drivers/issi/is31fl3218.h b/drivers/issi/is31fl3218.h
index a70cc1e79..fa760da19 100644
--- a/drivers/issi/is31fl3218.h
+++ b/drivers/issi/is31fl3218.h
@@ -13,6 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#pragma once
#include <stdint.h>
diff --git a/drivers/issi/is31fl3731-simple.c b/drivers/issi/is31fl3731-simple.c
index fad4676de..bd3bb4746 100644
--- a/drivers/issi/is31fl3731-simple.c
+++ b/drivers/issi/is31fl3731-simple.c
@@ -16,21 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef __AVR__
-# include <avr/interrupt.h>
-# include <avr/io.h>
-# include <util/delay.h>
-#else
-# include "wait.h"
-#endif
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
#include "is31fl3731-simple.h"
#include "i2c_master.h"
-#include "progmem.h"
-#include "print.h"
+#include "wait.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)
@@ -156,6 +144,7 @@ void IS31FL3731_init(uint8_t addr) {
// enable software shutdown
IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00);
+
// this delay was copied from other drivers, might not be needed
wait_ms(10);
diff --git a/drivers/issi/is31fl3731-simple.h b/drivers/issi/is31fl3731-simple.h
index a223c351e..85b458753 100644
--- a/drivers/issi/is31fl3731-simple.h
+++ b/drivers/issi/is31fl3731-simple.h
@@ -16,8 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef IS31FL3731_DRIVER_H
-#define IS31FL3731_DRIVER_H
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
typedef struct is31_led {
uint8_t driver : 2;
@@ -203,5 +205,3 @@ void IS31FL3731_update_led_control_registers(uint8_t addr, uint8_t index);
#define C9_14 0xB1
#define C9_15 0xB2
#define C9_16 0xB3
-
-#endif // IS31FL3731_DRIVER_H
diff --git a/drivers/issi/is31fl3731.c b/drivers/issi/is31fl3731.c
index 0b6f3e985..9f006b817 100644
--- a/drivers/issi/is31fl3731.c
+++ b/drivers/issi/is31fl3731.c
@@ -15,18 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef __AVR__
-# include <avr/interrupt.h>
-# include <avr/io.h>
-# include <util/delay.h>
-#else
-# include "wait.h"
-#endif
-
#include "is31fl3731.h"
-#include <string.h>
#include "i2c_master.h"
-#include "progmem.h"
+#include "wait.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)
@@ -141,12 +132,9 @@ void IS31FL3731_init(uint8_t addr) {
// enable software shutdown
IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00);
-// this delay was copied from other drivers, might not be needed
-#ifdef __AVR__
- _delay_ms(10);
-#else
+
+ // this delay was copied from other drivers, might not be needed
wait_ms(10);
-#endif
// picture mode
IS31FL3731_write_register(addr, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE);
diff --git a/drivers/issi/is31fl3731.h b/drivers/issi/is31fl3731.h
index 6a7a45d8f..19e8e6251 100644
--- a/drivers/issi/is31fl3731.h
+++ b/drivers/issi/is31fl3731.h
@@ -15,8 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef IS31FL3731_DRIVER_H
-#define IS31FL3731_DRIVER_H
+#pragma once
#include <stdint.h>
#include <stdbool.h>
@@ -207,5 +206,3 @@ void IS31FL3731_update_led_control_registers(uint8_t addr, uint8_t index);
#define C9_14 0xB1
#define C9_15 0xB2
#define C9_16 0xB3
-
-#endif // IS31FL3731_DRIVER_H
diff --git a/drivers/issi/is31fl3733.c b/drivers/issi/is31fl3733.c
index cc2d895ef..b913922b0 100644
--- a/drivers/issi/is31fl3733.c
+++ b/drivers/issi/is31fl3733.c
@@ -16,18 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef __AVR__
-# include <avr/interrupt.h>
-# include <avr/io.h>
-# include <util/delay.h>
-#else
-# include "wait.h"
-#endif
-
#include "is31fl3733.h"
-#include <string.h>
#include "i2c_master.h"
-#include "progmem.h"
+#include "wait.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 +71,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;
+ if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) != 0) {
+ return false;
+ }
}
#else
- i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT);
+ if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) != 0) {
+ return false;
+ }
#endif
}
+ return true;
}
void IS31FL3733_init(uint8_t addr, uint8_t sync) {
@@ -157,12 +159,8 @@ void IS31FL3733_init(uint8_t addr, uint8_t sync) {
// Disable software shutdown.
IS31FL3733_write_register(addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01);
-// Wait 10ms to ensure the device has woken up.
-#ifdef __AVR__
- _delay_ms(10);
-#else
+ // Wait 10ms to ensure the device has woken up.
wait_ms(10);
-#endif
}
void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
@@ -213,11 +211,15 @@ void IS31FL3733_set_led_control_register(uint8_t index, bool red, bool green, bo
void IS31FL3733_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
+ // Firstly we need to unlock the command register and select PG1.
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
- IS31FL3733_write_pwm_buffer(addr, g_pwm_buffer[index]);
+ // If any of the transactions fail we risk writing dirty PG0,
+ // refresh page 0 just in case.
+ if (!IS31FL3733_write_pwm_buffer(addr, g_pwm_buffer[index])){
+ g_led_control_registers_update_required[index] = true;
+ }
}
g_pwm_buffer_update_required[index] = false;
}
@@ -231,6 +233,5 @@ void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index) {
IS31FL3733_write_register(addr, i, g_led_control_registers[index][i]);
}
}
- // This seems counter intuitive but sometimes this page can get corrupted. So update it every time.
- // g_led_control_registers_update_required[index] = false;
+ g_led_control_registers_update_required[index] = false;
}
diff --git a/drivers/issi/is31fl3733.h b/drivers/issi/is31fl3733.h
index 5b3283e03..603d505a1 100644
--- a/drivers/issi/is31fl3733.h
+++ b/drivers/issi/is31fl3733.h
@@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef IS31FL3733_DRIVER_H
-#define IS31FL3733_DRIVER_H
+#pragma once
#include <stdint.h>
#include <stdbool.h>
@@ -32,8 +31,8 @@ typedef struct is31_led {
extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3733_init(uint8_t addr, uint8_t sync);
-void IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data);
-void IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
+bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data);
+bool IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
void IS31FL3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
@@ -250,5 +249,3 @@ void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index);
#define L_14 0xBD
#define L_15 0xBE
#define L_16 0xBF
-
-#endif // IS31FL3733_DRIVER_H
diff --git a/drivers/issi/is31fl3736.c b/drivers/issi/is31fl3736.c
index 754292425..9bd8fecfb 100644
--- a/drivers/issi/is31fl3736.c
+++ b/drivers/issi/is31fl3736.c
@@ -14,18 +14,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef __AVR__
-# include <avr/interrupt.h>
-# include <avr/io.h>
-# include <util/delay.h>
-#else
-# include "wait.h"
-#endif
-
#include "is31fl3736.h"
-#include <string.h>
#include "i2c_master.h"
-#include "progmem.h"
+#include "wait.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)
@@ -154,12 +145,8 @@ void IS31FL3736_init(uint8_t addr) {
// Disable software shutdown.
IS31FL3736_write_register(addr, ISSI_REG_CONFIGURATION, 0x01);
-// Wait 10ms to ensure the device has woken up.
-#ifdef __AVR__
- _delay_ms(10);
-#else
+ // Wait 10ms to ensure the device has woken up.
wait_ms(10);
-#endif
}
void IS31FL3736_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
@@ -263,7 +250,7 @@ void IS31FL3736_update_pwm_buffers(uint8_t addr1, uint8_t addr2) {
IS31FL3736_write_register(addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
IS31FL3736_write_pwm_buffer(addr1, g_pwm_buffer[0]);
- // IS31FL3736_write_pwm_buffer( addr2, g_pwm_buffer[1] );
+ // IS31FL3736_write_pwm_buffer(addr2, g_pwm_buffer[1]);
}
g_pwm_buffer_update_required = false;
}
@@ -275,7 +262,7 @@ void IS31FL3736_update_led_control_registers(uint8_t addr1, uint8_t addr2) {
IS31FL3736_write_register(addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
for (int i = 0; i < 24; i++) {
IS31FL3736_write_register(addr1, i, g_led_control_registers[0][i]);
- // IS31FL3736_write_register(addr2, i, g_led_control_registers[1][i] );
+ // IS31FL3736_write_register(addr2, i, g_led_control_registers[1][i]);
}
}
}
diff --git a/drivers/issi/is31fl3737.c b/drivers/issi/is31fl3737.c
index 4cc46272e..37c5c58e4 100644
--- a/drivers/issi/is31fl3737.c
+++ b/drivers/issi/is31fl3737.c
@@ -16,18 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef __AVR__
-# include <avr/interrupt.h>
-# include <avr/io.h>
-# include <util/delay.h>
-#else
-# include "wait.h"
-#endif
-
-#include <string.h>
+#include "is31fl3737.h"
#include "i2c_master.h"
-#include "progmem.h"
-#include "rgb_matrix.h"
+#include "wait.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)
@@ -156,12 +147,8 @@ void IS31FL3737_init(uint8_t addr) {
// Disable software shutdown.
IS31FL3737_write_register(addr, ISSI_REG_CONFIGURATION, 0x01);
-// Wait 10ms to ensure the device has woken up.
-#ifdef __AVR__
- _delay_ms(10);
-#else
+ // Wait 10ms to ensure the device has woken up.
wait_ms(10);
-#endif
}
void IS31FL3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
@@ -217,7 +204,7 @@ void IS31FL3737_update_pwm_buffers(uint8_t addr1, uint8_t addr2) {
IS31FL3737_write_register(addr1, 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(addr2, g_pwm_buffer[1]);
}
g_pwm_buffer_update_required = false;
}
@@ -229,7 +216,7 @@ void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2) {
IS31FL3737_write_register(addr1, 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(addr2, i, g_led_control_registers[1][i]);
}
}
}
diff --git a/drivers/issi/is31fl3737.h b/drivers/issi/is31fl3737.h
index 2c2fb1964..a1d228177 100644
--- a/drivers/issi/is31fl3737.h
+++ b/drivers/issi/is31fl3737.h
@@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef IS31FL3737_DRIVER_H
-#define IS31FL3737_DRIVER_H
+#pragma once
#include <stdint.h>
#include <stdbool.h>
@@ -202,5 +201,3 @@ void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2);
#define L_10 0xBB
#define L_11 0xBC
#define L_12 0xBD
-
-#endif // IS31FL3737_DRIVER_H
diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h
index bba6a7a12..f490f367a 100644
--- a/drivers/oled/oled_driver.h
+++ b/drivers/oled/oled_driver.h
@@ -224,6 +224,8 @@ void oled_write_raw_P(const char *data, uint16_t size);
// 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
# define oled_write_ln_P(data, invert) oled_write(data, invert)
+
+# define oled_write_raw_P(data, size) oled_write_raw(data, size)
#endif // defined(__AVR__)
// Can be used to manually turn on the screen if it is off