diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/arm/i2c_master.c | 5 | ||||
-rw-r--r-- | drivers/arm/i2c_master.h | 23 | ||||
-rw-r--r-- | drivers/arm/ws2812.c | 2 | ||||
-rw-r--r-- | drivers/arm/ws2812_spi.c | 91 | ||||
-rw-r--r-- | drivers/avr/analog.c | 110 | ||||
-rw-r--r-- | drivers/avr/analog.h | 37 | ||||
-rw-r--r-- | drivers/gpio/pca9555.c | 17 | ||||
-rw-r--r-- | drivers/gpio/pca9555.h | 2 | ||||
-rw-r--r-- | drivers/haptic/DRV2605L.c | 11 | ||||
-rw-r--r-- | drivers/issi/is31fl3218.h | 1 | ||||
-rw-r--r-- | drivers/issi/is31fl3731-simple.c | 15 | ||||
-rw-r--r-- | drivers/issi/is31fl3731-simple.h | 8 | ||||
-rw-r--r-- | drivers/issi/is31fl3731.c | 18 | ||||
-rw-r--r-- | drivers/issi/is31fl3731.h | 5 | ||||
-rw-r--r-- | drivers/issi/is31fl3733.c | 65 | ||||
-rw-r--r-- | drivers/issi/is31fl3733.h | 9 | ||||
-rw-r--r-- | drivers/issi/is31fl3736.c | 21 | ||||
-rw-r--r-- | drivers/issi/is31fl3737.c | 23 | ||||
-rw-r--r-- | drivers/issi/is31fl3737.h | 5 | ||||
-rw-r--r-- | drivers/oled/oled_driver.h | 2 |
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 |