diff options
Diffstat (limited to 'drivers/led')
-rw-r--r-- | drivers/led/apa102.c | 4 | ||||
-rw-r--r-- | drivers/led/aw20216.c | 3 | ||||
-rw-r--r-- | drivers/led/aw20216.h | 2 | ||||
-rw-r--r-- | drivers/led/ckled2001.c | 228 | ||||
-rw-r--r-- | drivers/led/ckled2001.h | 339 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3731-simple.c | 13 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3731-simple.h | 2 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3731.c | 13 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3731.h | 2 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3733.c | 25 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3733.h | 11 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3736.c | 19 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3736.h | 12 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3737.c | 19 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3737.h | 12 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3741.c | 16 | ||||
-rw-r--r-- | drivers/led/issi/is31fl3741.h | 11 |
17 files changed, 707 insertions, 24 deletions
diff --git a/drivers/led/apa102.c b/drivers/led/apa102.c index 7396dc3c55..00e7eb4505 100644 --- a/drivers/led/apa102.c +++ b/drivers/led/apa102.c @@ -24,8 +24,8 @@ # elif defined(PROTOCOL_CHIBIOS) # include "hal.h" -# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) -# define APA102_NOPS (100 / (1000000000L / (STM32_SYSCLK / 4))) // This calculates how many loops of 4 nops to run to delay 100 ns +# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(GD32VF103) +# define APA102_NOPS (100 / (1000000000L / (CPU_CLOCK / 4))) // This calculates how many loops of 4 nops to run to delay 100 ns # else # error("APA102_NOPS configuration required") # define APA102_NOPS 0 // this just pleases the compile so the above error is easier to spot diff --git a/drivers/led/aw20216.c b/drivers/led/aw20216.c index c608c0ab44..2c7ff8f088 100644 --- a/drivers/led/aw20216.c +++ b/drivers/led/aw20216.c @@ -119,7 +119,8 @@ void AW20216_init(pin_t cs_pin, pin_t en_pin) { } void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { - aw_led led = g_aw_leds[index]; + aw_led led; + memcpy_P(&led, (&g_aw_leds[index]), sizeof(led)); g_pwm_buffer[led.driver][led.r] = red; g_pwm_buffer[led.driver][led.g] = green; diff --git a/drivers/led/aw20216.h b/drivers/led/aw20216.h index 97ac6dc5bf..0a17050fed 100644 --- a/drivers/led/aw20216.h +++ b/drivers/led/aw20216.h @@ -28,7 +28,7 @@ typedef struct aw_led { uint8_t b; } aw_led; -extern const aw_led __flash g_aw_leds[DRIVER_LED_TOTAL]; +extern const aw_led PROGMEM g_aw_leds[DRIVER_LED_TOTAL]; void AW20216_init(pin_t cs_pin, pin_t en_pin); void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); diff --git a/drivers/led/ckled2001.c b/drivers/led/ckled2001.c new file mode 100644 index 0000000000..990e50cb60 --- /dev/null +++ b/drivers/led/ckled2001.c @@ -0,0 +1,228 @@ +/* Copyright 2021 @ Keychron (https://www.keychron.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ckled2001.h" +#include "i2c_master.h" +#include "wait.h" + +#ifndef CKLED2001_TIMEOUT +# define CKLED2001_TIMEOUT 100 +#endif + +#ifndef CKLED2001_PERSISTENCE +# define CKLED2001_PERSISTENCE 0 +#endif + +#ifndef PHASE_CHANNEL +# define PHASE_CHANNEL MSKPHASE_12CHANNEL +#endif + +// Transfer buffer for TWITransmitData() +uint8_t g_twi_transfer_buffer[20]; + +// These buffers match the CKLED2001 PWM registers. +// The control buffers match the PG0 LED On/Off registers. +// Storing them like this is optimal for I2C transfers to the registers. +// We could optimize this and take out the unused registers from these +// buffers and the transfers in CKLED2001_write_pwm_buffer() but it's +// probably not worth the extra complexity. +uint8_t g_pwm_buffer[DRIVER_COUNT][192]; +bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false}; + +uint8_t g_led_control_registers[DRIVER_COUNT][24] = {0}; +bool g_led_control_registers_update_required[DRIVER_COUNT] = {false}; + +bool CKLED2001_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 CKLED2001_PERSISTENCE > 0 + for (uint8_t i = 0; i < CKLED2001_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, CKLED2001_TIMEOUT) != 0) { + return false; + } + } +#else + if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, CKLED2001_TIMEOUT) != 0) { + return false; + } +#endif + return true; +} + +bool CKLED2001_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. + 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. + for (int j = 0; j < 16; j++) { + g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; + } + +#if CKLED2001_PERSISTENCE > 0 + for (uint8_t i = 0; i < CKLED2001_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, CKLED2001_TIMEOUT) != 0) { + return false; + } + } +#else + if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, CKLED2001_TIMEOUT) != 0) { + return false; + } +#endif + } + return true; +} + +void CKLED2001_init(uint8_t addr) { + // Select to function page + CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, FUNCTION_PAGE); + // Setting LED driver to shutdown mode + CKLED2001_write_register(addr, CONFIGURATION_REG, MSKSW_SHUT_DOWN_MODE); + // Setting internal channel pulldown/pullup + CKLED2001_write_register(addr, PDU_REG, MSKSET_CA_CB_CHANNEL); + // Select number of scan phase + CKLED2001_write_register(addr, SCAN_PHASE_REG, PHASE_CHANNEL); + // Setting PWM Delay Phase + CKLED2001_write_register(addr, SLEW_RATE_CONTROL_MODE1_REG, MSKPWM_DELAY_PHASE_ENABLE); + // Setting Driving/Sinking Channel Slew Rate + CKLED2001_write_register(addr, SLEW_RATE_CONTROL_MODE2_REG, MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_ENABLE); + // Setting Iref + CKLED2001_write_register(addr, SOFTWARE_SLEEP_REG, MSKSLEEP_DISABLE); + // Set LED CONTROL PAGE (Page 0) + CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, LED_CONTROL_PAGE); + for (int i = 0; i < LED_CONTROL_ON_OFF_LENGTH; i++) { + CKLED2001_write_register(addr, i, 0x00); + } + + // Set PWM PAGE (Page 1) + CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, LED_PWM_PAGE); + for (int i = 0; i < LED_CURRENT_TUNE_LENGTH; i++) { + CKLED2001_write_register(addr, i, 0x00); + } + + // Set CURRENT PAGE (Page 4) + CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, CURRENT_TUNE_PAGE); + for (int i = 0; i < LED_CURRENT_TUNE_LENGTH; i++) { + CKLED2001_write_register(addr, i, 0xFF); + } + + // Enable LEDs ON/OFF + CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, LED_CONTROL_PAGE); + for (int i = 0; i < LED_CONTROL_ON_OFF_LENGTH; i++) { + CKLED2001_write_register(addr, i, 0xFF); + } + + // Select to function page + CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, FUNCTION_PAGE); + // Setting LED driver to normal mode + CKLED2001_write_register(addr, CONFIGURATION_REG, MSKSW_NORMAL_MODE); +} + +void CKLED2001_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + ckled2001_led led; + if (index >= 0 && index < DRIVER_LED_TOTAL) { + memcpy_P(&led, (&g_ckled2001_leds[index]), sizeof(led)); + + g_pwm_buffer[led.driver][led.r] = red; + g_pwm_buffer[led.driver][led.g] = green; + g_pwm_buffer[led.driver][led.b] = blue; + g_pwm_buffer_update_required[led.driver] = true; + } +} + +void CKLED2001_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { + for (int i = 0; i < DRIVER_LED_TOTAL; i++) { + CKLED2001_set_color(i, red, green, blue); + } +} + +void CKLED2001_set_led_control_register(uint8_t index, bool red, bool green, bool blue) { + ckled2001_led led; + memcpy_P(&led, (&g_ckled2001_leds[index]), sizeof(led)); + + uint8_t control_register_r = led.r / 8; + uint8_t control_register_g = led.g / 8; + uint8_t control_register_b = led.b / 8; + uint8_t bit_r = led.r % 8; + uint8_t bit_g = led.g % 8; + uint8_t bit_b = led.b % 8; + + if (red) { + g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r); + } else { + g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r); + } + if (green) { + g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g); + } else { + g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g); + } + if (blue) { + g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b); + } else { + g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b); + } + + g_led_control_registers_update_required[led.driver] = true; +} + +void CKLED2001_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, LED_PWM_PAGE); + + // If any of the transactions fail we risk writing dirty PG0, + // refresh page 0 just in case. + if (!CKLED2001_write_pwm_buffer(addr, g_pwm_buffer[index])) { + g_led_control_registers_update_required[index] = true; + } + } + g_pwm_buffer_update_required[index] = false; +} + +void CKLED2001_update_led_control_registers(uint8_t addr, uint8_t index) { + if (g_led_control_registers_update_required[index]) { + CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, LED_CONTROL_PAGE); + for (int i = 0; i < 24; i++) { + CKLED2001_write_register(addr, i, g_led_control_registers[index][i]); + } + } + g_led_control_registers_update_required[index] = false; +} + +void CKLED2001_return_normal(uint8_t addr) { + // Select to function page + CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, FUNCTION_PAGE); + // Setting LED driver to normal mode + CKLED2001_write_register(addr, CONFIGURATION_REG, MSKSW_NORMAL_MODE); +} + +void CKLED2001_shutdown(uint8_t addr) { + // Select to function page + CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, FUNCTION_PAGE); + // Setting LED driver to shutdown mode + CKLED2001_write_register(addr, CONFIGURATION_REG, MSKSW_SHUT_DOWN_MODE); + // Write SW Sleep Register + CKLED2001_write_register(addr, SOFTWARE_SLEEP_REG, MSKSLEEP_ENABLE); +} diff --git a/drivers/led/ckled2001.h b/drivers/led/ckled2001.h new file mode 100644 index 0000000000..1967961d20 --- /dev/null +++ b/drivers/led/ckled2001.h @@ -0,0 +1,339 @@ +/* Copyright 2021 @ Keychron (https://www.keychron.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <stdint.h> +#include <stdbool.h> +#include "progmem.h" + +typedef struct ckled2001_led { + uint8_t driver : 2; + uint8_t r; + uint8_t g; + uint8_t b; +} __attribute__((packed)) ckled2001_led; + +extern const ckled2001_led PROGMEM g_ckled2001_leds[DRIVER_LED_TOTAL]; + +void CKLED2001_init(uint8_t addr); +bool CKLED2001_write_register(uint8_t addr, uint8_t reg, uint8_t data); +bool CKLED2001_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void CKLED2001_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); +void CKLED2001_set_color_all(uint8_t red, uint8_t green, uint8_t blue); + +void CKLED2001_set_led_control_register(uint8_t index, bool red, bool green, bool blue); + +// This should not be called from an interrupt +// (eg. from a timer interrupt). +// Call this while idle (in between matrix scans). +// If the buffer is dirty, it will update the driver with the buffer. +void CKLED2001_update_pwm_buffers(uint8_t addr, uint8_t index); +void CKLED2001_update_led_control_registers(uint8_t addr, uint8_t index); + +void CKLED2001_return_normal(uint8_t addr); +void CKLED2001_shutdown(uint8_t addr); + +// Registers Page Define +#define CONFIGURE_CMD_PAGE 0xFD +#define LED_CONTROL_PAGE 0x00 +#define LED_PWM_PAGE 0x01 +#define FUNCTION_PAGE 0x03 +#define CURRENT_TUNE_PAGE 0x04 + +// Function Register: address 0x00 +#define CONFIGURATION_REG 0x00 +#define MSKSW_SHUT_DOWN_MODE (0x0 << 0) +#define MSKSW_NORMAL_MODE (0x1 << 0) + +#define DRIVER_ID_REG 0x11 +#define CKLED2001_ID 0x8A + +#define PDU_REG 0x13 +#define MSKSET_CA_CB_CHANNEL 0xAA +#define MSKCLR_CA_CB_CHANNEL 0x00 + +#define SCAN_PHASE_REG 0x14 +#define MSKPHASE_12CHANNEL 0x00 +#define MSKPHASE_11CHANNEL 0x01 +#define MSKPHASE_10CHANNEL 0x02 +#define MSKPHASE_9CHANNEL 0x03 +#define MSKPHASE_8CHANNEL 0x04 +#define MSKPHASE_7CHANNEL 0x05 +#define MSKPHASE_6CHANNEL 0x06 +#define MSKPHASE_5CHANNEL 0x07 +#define MSKPHASE_4CHANNEL 0x08 +#define MSKPHASE_3CHANNEL 0x09 +#define MSKPHASE_2CHANNEL 0x0A +#define MSKPHASE_1CHANNEL 0x0B + +#define SLEW_RATE_CONTROL_MODE1_REG 0x15 +#define MSKPWM_DELAY_PHASE_ENABLE 0x04 +#define MSKPWM_DELAY_PHASE_DISABLE 0x00 + +#define SLEW_RATE_CONTROL_MODE2_REG 0x16 +#define MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_ENABLE 0xC0 +#define MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_DISABLE 0x00 + +#define OPEN_SHORT_ENABLE_REG 0x17 +#define MSKOPEN_DETECTION_ENABLE (0x01 << 7) +#define MSKOPEN_DETECTION_DISABLE (0x00) + +#define MSKSHORT_DETECTION_ENABLE (0x01 << 6) +#define MSKSHORT_DETECTION_DISABLE (0x00) + +#define OPEN_SHORT_DUTY_REG 0x18 +#define OPEN_SHORT_FLAG_REG 0x19 + +#define MSKOPEN_DETECTION_INTERRUPT_ENABLE (0x01 << 7) +#define MSKOPEN_DETECTION_INTERRUPT_DISABLE (0x00) + +#define MSKSHORT_DETECTION_INTERRUPT_ENABLE (0x01 << 6) +#define MSKSHORT_DETECTION_INTERRUPT_DISABLE (0x00) + +#define SOFTWARE_SLEEP_REG 0x1A +#define MSKSLEEP_ENABLE 0x02 +#define MSKSLEEP_DISABLE 0x00 + +// LED Control Registers +#define LED_CONTROL_ON_OFF_FIRST_ADDR 0x0 +#define LED_CONTROL_ON_OFF_LAST_ADDR 0x17 +#define LED_CONTROL_ON_OFF_LENGTH ((LED_CONTROL_ON_OFF_LAST_ADDR - LED_CONTROL_ON_OFF_FIRST_ADDR) + 1) + +#define LED_CONTROL_OPEN_FIRST_ADDR 0x18 +#define LED_CONTROL_OPEN_LAST_ADDR 0x2F +#define LED_CONTROL_OPEN_LENGTH ((LED_CONTROL_OPEN_LAST_ADDR - LED_CONTROL_OPEN_FIRST_ADDR) + 1) + +#define LED_CONTROL_SHORT_FIRST_ADDR 0x30 +#define LED_CONTROL_SHORT_LAST_ADDR 0x47 +#define LED_CONTROL_SHORT_LENGTH ((LED_CONTROL_SHORT_LAST_ADDR - LED_CONTROL_SHORT_FIRST_ADDR) + 1) + +#define LED_CONTROL_PAGE_LENGTH 0x48 + +// LED Control Registers +#define LED_PWM_FIRST_ADDR 0x00 +#define LED_PWM_LAST_ADDR 0xBF +#define LED_PWM_LENGTH 0xC0 + +// Current Tune Registers +#define LED_CURRENT_TUNE_FIRST_ADDR 0x00 +#define LED_CURRENT_TUNE_LAST_ADDR 0x0B +#define LED_CURRENT_TUNE_LENGTH 0x0C + +#define A_1 0x00 +#define A_2 0x01 +#define A_3 0x02 +#define A_4 0x03 +#define A_5 0x04 +#define A_6 0x05 +#define A_7 0x06 +#define A_8 0x07 +#define A_9 0x08 +#define A_10 0x09 +#define A_11 0x0A +#define A_12 0x0B +#define A_13 0x0C +#define A_14 0x0D +#define A_15 0x0E +#define A_16 0x0F + +#define B_1 0x10 +#define B_2 0x11 +#define B_3 0x12 +#define B_4 0x13 +#define B_5 0x14 +#define B_6 0x15 +#define B_7 0x16 +#define B_8 0x17 +#define B_9 0x18 +#define B_10 0x19 +#define B_11 0x1A +#define B_12 0x1B +#define B_13 0x1C +#define B_14 0x1D +#define B_15 0x1E +#define B_16 0x1F + +#define C_1 0x20 +#define C_2 0x21 +#define C_3 0x22 +#define C_4 0x23 +#define C_5 0x24 +#define C_6 0x25 +#define C_7 0x26 +#define C_8 0x27 +#define C_9 0x28 +#define C_10 0x29 +#define C_11 0x2A +#define C_12 0x2B +#define C_13 0x2C +#define C_14 0x2D +#define C_15 0x2E +#define C_16 0x2F + +#define D_1 0x30 +#define D_2 0x31 +#define D_3 0x32 +#define D_4 0x33 +#define D_5 0x34 +#define D_6 0x35 +#define D_7 0x36 +#define D_8 0x37 +#define D_9 0x38 +#define D_10 0x39 +#define D_11 0x3A +#define D_12 0x3B +#define D_13 0x3C +#define D_14 0x3D +#define D_15 0x3E +#define D_16 0x3F + +#define E_1 0x40 +#define E_2 0x41 +#define E_3 0x42 +#define E_4 0x43 +#define E_5 0x44 +#define E_6 0x45 +#define E_7 0x46 +#define E_8 0x47 +#define E_9 0x48 +#define E_10 0x49 +#define E_11 0x4A +#define E_12 0x4B +#define E_13 0x4C +#define E_14 0x4D +#define E_15 0x4E +#define E_16 0x4F + +#define F_1 0x50 +#define F_2 0x51 +#define F_3 0x52 +#define F_4 0x53 +#define F_5 0x54 +#define F_6 0x55 +#define F_7 0x56 +#define F_8 0x57 +#define F_9 0x58 +#define F_10 0x59 +#define F_11 0x5A +#define F_12 0x5B +#define F_13 0x5C +#define F_14 0x5D +#define F_15 0x5E +#define F_16 0x5F + +#define G_1 0x60 +#define G_2 0x61 +#define G_3 0x62 +#define G_4 0x63 +#define G_5 0x64 +#define G_6 0x65 +#define G_7 0x66 +#define G_8 0x67 +#define G_9 0x68 +#define G_10 0x69 +#define G_11 0x6A +#define G_12 0x6B +#define G_13 0x6C +#define G_14 0x6D +#define G_15 0x6E +#define G_16 0x6F + +#define H_1 0x70 +#define H_2 0x71 +#define H_3 0x72 +#define H_4 0x73 +#define H_5 0x74 +#define H_6 0x75 +#define H_7 0x76 +#define H_8 0x77 +#define H_9 0x78 +#define H_10 0x79 +#define H_11 0x7A +#define H_12 0x7B +#define H_13 0x7C +#define H_14 0x7D +#define H_15 0x7E +#define H_16 0x7F + +#define I_1 0x80 +#define I_2 0x81 +#define I_3 0x82 +#define I_4 0x83 +#define I_5 0x84 +#define I_6 0x85 +#define I_7 0x86 +#define I_8 0x87 +#define I_9 0x88 +#define I_10 0x89 +#define I_11 0x8A +#define I_12 0x8B +#define I_13 0x8C +#define I_14 0x8D +#define I_15 0x8E +#define I_16 0x8F + +#define J_1 0x90 +#define J_2 0x91 +#define J_3 0x92 +#define J_4 0x93 +#define J_5 0x94 +#define J_6 0x95 +#define J_7 0x96 +#define J_8 0x97 +#define J_9 0x98 +#define J_10 0x99 +#define J_11 0x9A +#define J_12 0x9B +#define J_13 0x9C +#define J_14 0x9D +#define J_15 0x9E +#define J_16 0x9F + +#define K_1 0xA0 +#define K_2 0xA1 +#define K_3 0xA2 +#define K_4 0xA3 +#define K_5 0xA4 +#define K_6 0xA5 +#define K_7 0xA6 +#define K_8 0xA7 +#define K_9 0xA8 +#define K_10 0xA9 +#define K_11 0xAA +#define K_12 0xAB +#define K_13 0xAC +#define K_14 0xAD +#define K_15 0xAE +#define K_16 0xAF + +#define L_1 0xB0 +#define L_2 0xB1 +#define L_3 0xB2 +#define L_4 0xB3 +#define L_5 0xB4 +#define L_6 0xB5 +#define L_7 0xB6 +#define L_8 0xB7 +#define L_9 0xB8 +#define L_10 0xB9 +#define L_11 0xBA +#define L_12 0xBB +#define L_13 0xBC +#define L_14 0xBD +#define L_15 0xBE +#define L_16 0xBF
\ No newline at end of file diff --git a/drivers/led/issi/is31fl3731-simple.c b/drivers/led/issi/is31fl3731-simple.c index d295772f5e..f51e2e38af 100644 --- a/drivers/led/issi/is31fl3731-simple.c +++ b/drivers/led/issi/is31fl3731-simple.c @@ -1,6 +1,7 @@ /* Copyright 2017 Jason Williams * Copyright 2018 Jack Humbert * Copyright 2019 Clueboard + * Copyright 2021 Doni Crosby * * 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 @@ -40,6 +41,9 @@ #define ISSI_REG_PICTUREFRAME 0x01 +// Not defined in the datasheet -- See AN for IC +#define ISSI_REG_GHOST_IMAGE_PREVENTION 0xC2 // Set bit 4 to enable de-ghosting + #define ISSI_REG_SHUTDOWN 0x0A #define ISSI_REG_AUDIOSYNC 0x06 @@ -144,6 +148,9 @@ void IS31FL3731_init(uint8_t addr) { // enable software shutdown IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00); +#ifdef ISSI_3731_DEGHOST // set to enable de-ghosting of the array + IS31FL3731_write_register(addr, ISSI_REG_GHOST_IMAGE_PREVENTION, 0x10); +#endif // this delay was copied from other drivers, might not be needed wait_ms(10); @@ -186,8 +193,9 @@ void IS31FL3731_init(uint8_t addr) { } void IS31FL3731_set_value(int index, uint8_t value) { + is31_led led; if (index >= 0 && index < DRIVER_LED_TOTAL) { - is31_led led = g_is31_leds[index]; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); // Subtract 0x24 to get the second index of g_pwm_buffer g_pwm_buffer[led.driver][led.v - 0x24] = value; @@ -202,7 +210,8 @@ void IS31FL3731_set_value_all(uint8_t value) { } void IS31FL3731_set_led_control_register(uint8_t index, bool value) { - is31_led led = g_is31_leds[index]; + is31_led led; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); uint8_t control_register = (led.v - 0x24) / 8; uint8_t bit_value = (led.v - 0x24) % 8; diff --git a/drivers/led/issi/is31fl3731-simple.h b/drivers/led/issi/is31fl3731-simple.h index ecde31eed5..ded94b0470 100644 --- a/drivers/led/issi/is31fl3731-simple.h +++ b/drivers/led/issi/is31fl3731-simple.h @@ -27,7 +27,7 @@ typedef struct is31_led { uint8_t v; } __attribute__((packed)) is31_led; -extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3731_init(uint8_t addr); void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data); diff --git a/drivers/led/issi/is31fl3731.c b/drivers/led/issi/is31fl3731.c index 110bdc1be4..e6190a6b90 100644 --- a/drivers/led/issi/is31fl3731.c +++ b/drivers/led/issi/is31fl3731.c @@ -1,5 +1,6 @@ /* Copyright 2017 Jason Williams * Copyright 2018 Jack Humbert + * Copyright 2021 Doni Crosby * * 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 @@ -39,6 +40,9 @@ #define ISSI_REG_PICTUREFRAME 0x01 +// Not defined in the datasheet -- See AN for IC +#define ISSI_REG_GHOST_IMAGE_PREVENTION 0xC2 // Set bit 4 to enable de-ghosting + #define ISSI_REG_SHUTDOWN 0x0A #define ISSI_REG_AUDIOSYNC 0x06 @@ -132,6 +136,9 @@ void IS31FL3731_init(uint8_t addr) { // enable software shutdown IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00); +#ifdef ISSI_3731_DEGHOST // set to enable de-ghosting of the array + IS31FL3731_write_register(addr, ISSI_REG_GHOST_IMAGE_PREVENTION, 0x10); +#endif // this delay was copied from other drivers, might not be needed wait_ms(10); @@ -174,8 +181,9 @@ void IS31FL3731_init(uint8_t addr) { } void IS31FL3731_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + is31_led led; if (index >= 0 && index < DRIVER_LED_TOTAL) { - is31_led led = g_is31_leds[index]; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); // Subtract 0x24 to get the second index of g_pwm_buffer g_pwm_buffer[led.driver][led.r - 0x24] = red; @@ -192,7 +200,8 @@ void IS31FL3731_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { } void IS31FL3731_set_led_control_register(uint8_t index, bool red, bool green, bool blue) { - is31_led led = g_is31_leds[index]; + is31_led led; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); uint8_t control_register_r = (led.r - 0x24) / 8; uint8_t control_register_g = (led.g - 0x24) / 8; diff --git a/drivers/led/issi/is31fl3731.h b/drivers/led/issi/is31fl3731.h index 803ea3ea12..6647119eba 100644 --- a/drivers/led/issi/is31fl3731.h +++ b/drivers/led/issi/is31fl3731.h @@ -28,7 +28,7 @@ typedef struct is31_led { uint8_t b; } __attribute__((packed)) is31_led; -extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3731_init(uint8_t addr); void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data); diff --git a/drivers/led/issi/is31fl3733.c b/drivers/led/issi/is31fl3733.c index d99e5339c9..696491d070 100644 --- a/drivers/led/issi/is31fl3733.c +++ b/drivers/led/issi/is31fl3733.c @@ -1,6 +1,7 @@ /* Copyright 2017 Jason Williams * Copyright 2018 Jack Humbert * Copyright 2018 Yiancar + * Copyright 2021 Doni Crosby * * 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 @@ -56,6 +57,18 @@ # define ISSI_PERSISTENCE 0 #endif +#ifndef ISSI_PWM_FREQUENCY +# define ISSI_PWM_FREQUENCY 0b000 // PFS - IS31FL3733B only +#endif + +#ifndef ISSI_SWPULLUP +# define ISSI_SWPULLUP PUR_0R +#endif + +#ifndef ISSI_CSPULLUP +# define ISSI_CSPULLUP PUR_0R +#endif + // Transfer buffer for TWITransmitData() uint8_t g_twi_transfer_buffer[20]; @@ -154,18 +167,23 @@ void IS31FL3733_init(uint8_t addr, uint8_t sync) { // Select PG3 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION); + // Set de-ghost pull-up resistors (SWx) + IS31FL3733_write_register(addr, ISSI_REG_SWPULLUP, ISSI_SWPULLUP); + // Set de-ghost pull-down resistors (CSx) + IS31FL3733_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP); // Set global current to maximum. IS31FL3733_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF); // Disable software shutdown. - IS31FL3733_write_register(addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01); + IS31FL3733_write_register(addr, ISSI_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((ISSI_PWM_FREQUENCY & 0b111) << 3) | 0x01); // Wait 10ms to ensure the device has woken up. wait_ms(10); } void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + is31_led led; if (index >= 0 && index < DRIVER_LED_TOTAL) { - is31_led led = g_is31_leds[index]; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); g_pwm_buffer[led.driver][led.r] = red; g_pwm_buffer[led.driver][led.g] = green; @@ -181,7 +199,8 @@ void IS31FL3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { } void IS31FL3733_set_led_control_register(uint8_t index, bool red, bool green, bool blue) { - is31_led led = g_is31_leds[index]; + is31_led led; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); uint8_t control_register_r = led.r / 8; uint8_t control_register_g = led.g / 8; diff --git a/drivers/led/issi/is31fl3733.h b/drivers/led/issi/is31fl3733.h index 64fd38eb19..c5d62fed85 100644 --- a/drivers/led/issi/is31fl3733.h +++ b/drivers/led/issi/is31fl3733.h @@ -1,6 +1,7 @@ /* Copyright 2017 Jason Williams * Copyright 2018 Jack Humbert * Copyright 2018 Yiancar + * Copyright 2021 Doni Crosby * * 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 @@ -29,7 +30,7 @@ typedef struct is31_led { uint8_t b; } __attribute__((packed)) is31_led; -extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3733_init(uint8_t addr, uint8_t sync); bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data); @@ -47,6 +48,14 @@ 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); void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index); +#define PUR_0R 0x00 // No PUR resistor +#define PUR_05KR 0x02 // 0.5k Ohm resistor in t_NOL +#define PUR_3KR 0x03 // 3.0k Ohm resistor on all the time +#define PUR_4KR 0x04 // 4.0k Ohm resistor on all the time +#define PUR_8KR 0x05 // 8.0k Ohm resistor on all the time +#define PUR_16KR 0x06 // 16k Ohm resistor on all the time +#define PUR_32KR 0x07 // 32k Ohm resistor in t_NOL + #define A_1 0x00 #define A_2 0x01 #define A_3 0x02 diff --git a/drivers/led/issi/is31fl3736.c b/drivers/led/issi/is31fl3736.c index 7dece1b1eb..c9a871118d 100644 --- a/drivers/led/issi/is31fl3736.c +++ b/drivers/led/issi/is31fl3736.c @@ -1,4 +1,5 @@ /* Copyright 2018 Jason Williams (Wilba) + * Copyright 2021 Doni Crosby * * 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 @@ -54,6 +55,14 @@ # define ISSI_PERSISTENCE 0 #endif +#ifndef ISSI_SWPULLUP +# define ISSI_SWPULLUP PUR_0R +#endif + +#ifndef ISSI_CSPULLUP +# define ISSI_CSPULLUP PUR_0R +#endif + // Transfer buffer for TWITransmitData() uint8_t g_twi_transfer_buffer[20]; @@ -140,6 +149,10 @@ void IS31FL3736_init(uint8_t addr) { // Select PG3 IS31FL3736_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION); + // Set de-ghost pull-up resistors (SWx) + IS31FL3736_write_register(addr, ISSI_REG_SWPULLUP, ISSI_SWPULLUP); + // Set de-ghost pull-down resistors (CSx) + IS31FL3736_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP); // Set global current to maximum. IS31FL3736_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF); // Disable software shutdown. @@ -150,8 +163,9 @@ void IS31FL3736_init(uint8_t addr) { } void IS31FL3736_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + is31_led led; if (index >= 0 && index < DRIVER_LED_TOTAL) { - is31_led led = g_is31_leds[index]; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); g_pwm_buffer[led.driver][led.r] = red; g_pwm_buffer[led.driver][led.g] = green; @@ -167,7 +181,8 @@ void IS31FL3736_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { } void IS31FL3736_set_led_control_register(uint8_t index, bool red, bool green, bool blue) { - is31_led led = g_is31_leds[index]; + is31_led led; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); // IS31FL3733 // The PWM register for a matrix position (0x00 to 0xBF) can be diff --git a/drivers/led/issi/is31fl3736.h b/drivers/led/issi/is31fl3736.h index c956c87f7c..9fbe1cc577 100644 --- a/drivers/led/issi/is31fl3736.h +++ b/drivers/led/issi/is31fl3736.h @@ -1,4 +1,5 @@ /* Copyright 2018 Jason Williams (Wilba) + * Copyright 2021 Doni Crosby * * 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 @@ -38,7 +39,7 @@ typedef struct is31_led { uint8_t b; } __attribute__((packed)) is31_led; -extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3736_init(uint8_t addr); void IS31FL3736_write_register(uint8_t addr, uint8_t reg, uint8_t data); @@ -60,6 +61,15 @@ void IS31FL3736_mono_set_led_control_register(uint8_t index, bool enabled); void IS31FL3736_update_pwm_buffers(uint8_t addr1, uint8_t addr2); void IS31FL3736_update_led_control_registers(uint8_t addr1, uint8_t addr2); +#define PUR_0R 0x00 // No PUR resistor +#define PUR_05KR 0x01 // 0.5k Ohm resistor +#define PUR_1KR 0x02 // 1.0k Ohm resistor +#define PUR_2KR 0x03 // 2.0k Ohm resistor +#define PUR_4KR 0x04 // 4.0k Ohm resistor +#define PUR_8KR 0x05 // 8.0k Ohm resistor +#define PUR_16KR 0x06 // 16k Ohm resistor +#define PUR_32KR 0x07 // 32k Ohm resistor + #define A_1 0x00 #define A_2 0x02 #define A_3 0x04 diff --git a/drivers/led/issi/is31fl3737.c b/drivers/led/issi/is31fl3737.c index 0bb4ddd425..0722e18869 100644 --- a/drivers/led/issi/is31fl3737.c +++ b/drivers/led/issi/is31fl3737.c @@ -1,6 +1,7 @@ /* Copyright 2017 Jason Williams * Copyright 2018 Jack Humbert * Copyright 2018 Yiancar + * Copyright 2021 Doni Crosby * * 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 @@ -56,6 +57,14 @@ # define ISSI_PERSISTENCE 0 #endif +#ifndef ISSI_SWPULLUP +# define ISSI_SWPULLUP PUR_0R +#endif + +#ifndef ISSI_CSPULLUP +# define ISSI_CSPULLUP PUR_0R +#endif + // Transfer buffer for TWITransmitData() uint8_t g_twi_transfer_buffer[20]; @@ -143,6 +152,10 @@ void IS31FL3737_init(uint8_t addr) { // Select PG3 IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION); + // Set de-ghost pull-up resistors (SWx) + IS31FL3737_write_register(addr, ISSI_REG_SWPULLUP, ISSI_SWPULLUP); + // Set de-ghost pull-down resistors (CSx) + IS31FL3737_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP); // Set global current to maximum. IS31FL3737_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF); // Disable software shutdown. @@ -153,8 +166,9 @@ void IS31FL3737_init(uint8_t addr) { } void IS31FL3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + is31_led led; if (index >= 0 && index < DRIVER_LED_TOTAL) { - is31_led led = g_is31_leds[index]; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); g_pwm_buffer[led.driver][led.r] = red; g_pwm_buffer[led.driver][led.g] = green; @@ -170,7 +184,8 @@ void IS31FL3737_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { } void IS31FL3737_set_led_control_register(uint8_t index, bool red, bool green, bool blue) { - is31_led led = g_is31_leds[index]; + is31_led led; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); uint8_t control_register_r = led.r / 8; uint8_t control_register_g = led.g / 8; diff --git a/drivers/led/issi/is31fl3737.h b/drivers/led/issi/is31fl3737.h index 06886e9c9b..31b1a22267 100644 --- a/drivers/led/issi/is31fl3737.h +++ b/drivers/led/issi/is31fl3737.h @@ -1,6 +1,7 @@ /* Copyright 2017 Jason Williams * Copyright 2018 Jack Humbert * Copyright 2018 Yiancar + * Copyright 2021 Doni Crosby * * 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 @@ -29,7 +30,7 @@ typedef struct is31_led { uint8_t b; } __attribute__((packed)) is31_led; -extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3737_init(uint8_t addr); void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data); @@ -47,6 +48,15 @@ void IS31FL3737_set_led_control_register(uint8_t index, bool red, bool green, bo void IS31FL3737_update_pwm_buffers(uint8_t addr1, uint8_t addr2); void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2); +#define PUR_0R 0x00 // No PUR resistor +#define PUR_05KR 0x01 // 0.5k Ohm resistor in t_NOL +#define PUR_1KR 0x02 // 1.0k Ohm resistor in t_NOL +#define PUR_2KR 0x03 // 2.0k Ohm resistor in t_NOL +#define PUR_4KR 0x04 // 4.0k Ohm resistor in t_NOL +#define PUR_8KR 0x05 // 8.0k Ohm resistor in t_NOL +#define PUR_16KR 0x06 // 16k Ohm resistor in t_NOL +#define PUR_32KR 0x07 // 32k Ohm resistor in t_NOL + #define A_1 0x00 #define A_2 0x01 #define A_3 0x02 diff --git a/drivers/led/issi/is31fl3741.c b/drivers/led/issi/is31fl3741.c index 24a273514e..8d347a5e60 100644 --- a/drivers/led/issi/is31fl3741.c +++ b/drivers/led/issi/is31fl3741.c @@ -61,6 +61,14 @@ # define ISSI_PERSISTENCE 0 #endif +#ifndef ISSI_SWPULLUP +# define ISSI_SWPULLUP PUR_32KR +#endif + +#ifndef ISSI_CSPULLUP +# define ISSI_CSPULLUP PUR_32KR +#endif + #define ISSI_MAX_LEDS 351 // Transfer buffer for TWITransmitData() @@ -157,7 +165,7 @@ void IS31FL3741_init(uint8_t addr) { // Set Golbal Current Control Register IS31FL3741_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF); // Set Pull up & Down for SWx CSy - IS31FL3741_write_register(addr, ISSI_REG_PULLDOWNUP, 0x77); + IS31FL3741_write_register(addr, ISSI_REG_PULLDOWNUP, ((ISSI_CSPULLUP << 4) | ISSI_SWPULLUP)); // IS31FL3741_update_led_scaling_registers(addr, 0xFF, 0xFF, 0xFF); @@ -166,8 +174,9 @@ void IS31FL3741_init(uint8_t addr) { } void IS31FL3741_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + is31_led led; if (index >= 0 && index < DRIVER_LED_TOTAL) { - is31_led led = g_is31_leds[index]; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); g_pwm_buffer[led.driver][led.r] = red; g_pwm_buffer[led.driver][led.g] = green; @@ -183,7 +192,8 @@ void IS31FL3741_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { } void IS31FL3741_set_led_control_register(uint8_t index, bool red, bool green, bool blue) { - is31_led led = g_is31_leds[index]; + is31_led led; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); if (red) { g_scaling_registers[led.driver][led.r] = 0xFF; diff --git a/drivers/led/issi/is31fl3741.h b/drivers/led/issi/is31fl3741.h index 163a035233..8154f8be70 100644 --- a/drivers/led/issi/is31fl3741.h +++ b/drivers/led/issi/is31fl3741.h @@ -30,7 +30,7 @@ typedef struct is31_led { uint32_t b : 10; } __attribute__((packed)) is31_led; -extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3741_init(uint8_t addr); void IS31FL3741_write_register(uint8_t addr, uint8_t reg, uint8_t data); @@ -51,6 +51,15 @@ void IS31FL3741_set_scaling_registers(const is31_led *pled, uint8_t red, uint8_t void IS31FL3741_set_pwm_buffer(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue); +#define PUR_0R 0x00 // No PUR resistor +#define PUR_05KR 0x01 // 0.5k Ohm resistor +#define PUR_1KR 0x02 // 1.0k Ohm resistor +#define PUR_2KR 0x03 // 2.0k Ohm resistor +#define PUR_4KR 0x04 // 4.0k Ohm resistor +#define PUR_8KR 0x05 // 8.0k Ohm resistor +#define PUR_16KR 0x06 // 16k Ohm resistor +#define PUR_32KR 0x07 // 32k Ohm resistor + #define CS1_SW1 0x00 #define CS2_SW1 0x01 #define CS3_SW1 0x02 |