diff options
| author | Joel Challis <git@zvecr.com> | 2021-07-27 23:55:51 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-07-27 23:55:51 +0100 |
| commit | 3858a784c702d75d207e62c6cdf4449eed41c789 (patch) | |
| tree | 17713862786ea5951f7fb15605df7e2082fdc34b /drivers | |
| parent | 56443fe3cf19768f34e065319d50164d4e99dd3c (diff) | |
| download | qmk_firmware-3858a784c702d75d207e62c6cdf4449eed41c789.tar.gz qmk_firmware-3858a784c702d75d207e62c6cdf4449eed41c789.zip | |
Align AW20216 driver (#13712)
* Align AW20216 driver
* Update drivers/awinic/aw20216.h
Co-authored-by: Ryan <fauxpark@gmail.com>
* Review comments
* formatting fixes
* stop if start failed?
* review comments
Co-authored-by: Ryan <fauxpark@gmail.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/awinic/aw20216.c | 131 | ||||
| -rw-r--r-- | drivers/awinic/aw20216.h | 5 |
2 files changed, 48 insertions, 88 deletions
diff --git a/drivers/awinic/aw20216.c b/drivers/awinic/aw20216.c index 776653fa6..c608c0ab4 100644 --- a/drivers/awinic/aw20216.c +++ b/drivers/awinic/aw20216.c | |||
| @@ -45,8 +45,6 @@ | |||
| 45 | 45 | ||
| 46 | #define AW_PWM_REGISTER_COUNT 216 | 46 | #define AW_PWM_REGISTER_COUNT 216 |
| 47 | 47 | ||
| 48 | #define AW_SPI_START(PIN) spi_start(PIN, false, 0, AW_SPI_DIVISOR) | ||
| 49 | |||
| 50 | #ifndef AW_SCALING_MAX | 48 | #ifndef AW_SCALING_MAX |
| 51 | # define AW_SCALING_MAX 150 | 49 | # define AW_SCALING_MAX 150 |
| 52 | #endif | 50 | #endif |
| @@ -55,128 +53,89 @@ | |||
| 55 | # define AW_GLOBAL_CURRENT_MAX 150 | 53 | # define AW_GLOBAL_CURRENT_MAX 150 |
| 56 | #endif | 54 | #endif |
| 57 | 55 | ||
| 58 | #ifndef DRIVER_1_CS | ||
| 59 | # define DRIVER_1_CS B13 | ||
| 60 | #endif | ||
| 61 | |||
| 62 | #ifndef DRIVER_1_EN | ||
| 63 | # define DRIVER_1_EN C13 | ||
| 64 | #endif | ||
| 65 | |||
| 66 | #ifndef AW_SPI_DIVISOR | 56 | #ifndef AW_SPI_DIVISOR |
| 67 | # define AW_SPI_DIVISOR 4 | 57 | # define AW_SPI_DIVISOR 4 |
| 68 | #endif | 58 | #endif |
| 69 | 59 | ||
| 70 | uint8_t g_spi_transfer_buffer[3] = {0}; | ||
| 71 | uint8_t g_pwm_buffer[DRIVER_COUNT][AW_PWM_REGISTER_COUNT]; | 60 | uint8_t g_pwm_buffer[DRIVER_COUNT][AW_PWM_REGISTER_COUNT]; |
| 72 | bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false}; | 61 | bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false}; |
| 73 | 62 | ||
| 74 | bool AW20216_write_register(pin_t slave_pin, uint8_t page, uint8_t reg, uint8_t data) { | 63 | bool AW20216_write(pin_t cs_pin, uint8_t page, uint8_t reg, uint8_t* data, uint8_t len) { |
| 75 | // Do we need to call spi_stop() if this fails? | 64 | static uint8_t s_spi_transfer_buffer[2] = {0}; |
| 76 | if (!AW_SPI_START(slave_pin)) { | 65 | |
| 66 | if (!spi_start(cs_pin, false, 0, AW_SPI_DIVISOR)) { | ||
| 67 | spi_stop(); | ||
| 77 | return false; | 68 | return false; |
| 78 | } | 69 | } |
| 79 | 70 | ||
| 80 | g_spi_transfer_buffer[0] = (AWINIC_ID | page | AW_WRITE); | 71 | s_spi_transfer_buffer[0] = (AWINIC_ID | page | AW_WRITE); |
| 81 | g_spi_transfer_buffer[1] = reg; | 72 | s_spi_transfer_buffer[1] = reg; |
| 82 | g_spi_transfer_buffer[2] = data; | ||
| 83 | 73 | ||
| 84 | if (spi_transmit(g_spi_transfer_buffer, 3) != SPI_STATUS_SUCCESS) { | 74 | if (spi_transmit(s_spi_transfer_buffer, 2) != SPI_STATUS_SUCCESS) { |
| 85 | spi_stop(); | 75 | spi_stop(); |
| 86 | return false; | 76 | return false; |
| 87 | } | 77 | } |
| 78 | |||
| 79 | if (spi_transmit(data, len) != SPI_STATUS_SUCCESS) { | ||
| 80 | spi_stop(); | ||
| 81 | return false; | ||
| 82 | } | ||
| 83 | |||
| 88 | spi_stop(); | 84 | spi_stop(); |
| 89 | return true; | 85 | return true; |
| 90 | } | 86 | } |
| 91 | 87 | ||
| 92 | bool AW20216_init_scaling(void) { | 88 | static inline bool AW20216_write_register(pin_t cs_pin, uint8_t page, uint8_t reg, uint8_t value) { |
| 89 | // Little wrapper so callers need not care about sending a buffer | ||
| 90 | return AW20216_write(cs_pin, page, reg, &value, 1); | ||
| 91 | } | ||
| 92 | |||
| 93 | static void AW20216_init_scaling(pin_t cs_pin) { | ||
| 93 | // Set constant current to the max, control brightness with PWM | 94 | // Set constant current to the max, control brightness with PWM |
| 94 | aw_led led; | 95 | for (uint8_t i = 0; i < AW_PWM_REGISTER_COUNT; i++) { |
| 95 | for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) { | 96 | AW20216_write_register(cs_pin, AW_PAGE_SCALING, i, AW_SCALING_MAX); |
| 96 | led = g_aw_leds[i]; | ||
| 97 | if (led.driver == 0) { | ||
| 98 | AW20216_write_register(DRIVER_1_CS, AW_PAGE_SCALING, led.r, AW_SCALING_MAX); | ||
| 99 | AW20216_write_register(DRIVER_1_CS, AW_PAGE_SCALING, led.g, AW_SCALING_MAX); | ||
| 100 | AW20216_write_register(DRIVER_1_CS, AW_PAGE_SCALING, led.b, AW_SCALING_MAX); | ||
| 101 | } | ||
| 102 | #ifdef DRIVER_2_CS | ||
| 103 | else if (led.driver == 1) { | ||
| 104 | AW20216_write_register(DRIVER_2_CS, AW_PAGE_SCALING, led.r, AW_SCALING_MAX); | ||
| 105 | AW20216_write_register(DRIVER_2_CS, AW_PAGE_SCALING, led.g, AW_SCALING_MAX); | ||
| 106 | AW20216_write_register(DRIVER_2_CS, AW_PAGE_SCALING, led.b, AW_SCALING_MAX); | ||
| 107 | } | ||
| 108 | #endif | ||
| 109 | } | 97 | } |
| 110 | return true; | ||
| 111 | } | 98 | } |
| 112 | 99 | ||
| 113 | bool AW20216_soft_enable(void) { | 100 | static inline void AW20216_init_current_limit(pin_t cs_pin) { |
| 114 | AW20216_write_register(DRIVER_1_CS, AW_PAGE_FUNCTION, AW_REG_CONFIGURATION, AW_CONFIG_DEFAULT | AW_CHIPEN); | 101 | // Push config |
| 115 | #ifdef DRIVER_2_CS | 102 | AW20216_write_register(cs_pin, AW_PAGE_FUNCTION, AW_REG_GLOBALCURRENT, AW_GLOBAL_CURRENT_MAX); |
| 116 | AW20216_write_register(DRIVER_2_CS, AW_PAGE_FUNCTION, AW_REG_CONFIGURATION, AW_CONFIG_DEFAULT | AW_CHIPEN); | ||
| 117 | #endif | ||
| 118 | return true; | ||
| 119 | } | 103 | } |
| 120 | 104 | ||
| 121 | void AW20216_update_pwm(int index, uint8_t red, uint8_t green, uint8_t blue) { | 105 | static inline void AW20216_soft_enable(pin_t cs_pin) { |
| 122 | aw_led led = g_aw_leds[index]; | 106 | // Push config |
| 123 | if (led.driver == 0) { | 107 | AW20216_write_register(cs_pin, AW_PAGE_FUNCTION, AW_REG_CONFIGURATION, AW_CONFIG_DEFAULT | AW_CHIPEN); |
| 124 | AW20216_write_register(DRIVER_1_CS, AW_PAGE_PWM, led.r, red); | ||
| 125 | AW20216_write_register(DRIVER_1_CS, AW_PAGE_PWM, led.g, green); | ||
| 126 | AW20216_write_register(DRIVER_1_CS, AW_PAGE_PWM, led.b, blue); | ||
| 127 | } | ||
| 128 | #ifdef DRIVER_2_CS | ||
| 129 | else if (led.driver == 1) { | ||
| 130 | AW20216_write_register(DRIVER_2_CS, AW_PAGE_PWM, led.r, red); | ||
| 131 | AW20216_write_register(DRIVER_2_CS, AW_PAGE_PWM, led.g, green); | ||
| 132 | AW20216_write_register(DRIVER_2_CS, AW_PAGE_PWM, led.b, blue); | ||
| 133 | } | ||
| 134 | #endif | ||
| 135 | return; | ||
| 136 | } | 108 | } |
| 137 | 109 | ||
| 138 | void AW20216_init(void) { | 110 | void AW20216_init(pin_t cs_pin, pin_t en_pin) { |
| 139 | // All LEDs should start with all scaling and PWM registers as off | 111 | setPinOutput(en_pin); |
| 140 | setPinOutput(DRIVER_1_EN); | 112 | writePinHigh(en_pin); |
| 141 | writePinHigh(DRIVER_1_EN); | 113 | |
| 142 | AW20216_write_register(DRIVER_1_CS, AW_PAGE_FUNCTION, AW_REG_GLOBALCURRENT, AW_GLOBAL_CURRENT_MAX); | 114 | // Drivers should start with all scaling and PWM registers as off |
| 143 | #ifdef DRIVER_2_EN | 115 | AW20216_init_current_limit(cs_pin); |
| 144 | setPinOutput(DRIVER_2_EN); | 116 | AW20216_init_scaling(cs_pin); |
| 145 | writePinHigh(DRIVER_2_EN); | 117 | |
| 146 | AW20216_write_register(DRIVER_2_CS, AW_PAGE_FUNCTION, AW_REG_GLOBALCURRENT, AW_GLOBAL_CURRENT_MAX); | 118 | AW20216_soft_enable(cs_pin); |
| 147 | #endif | ||
| 148 | AW20216_init_scaling(); | ||
| 149 | AW20216_soft_enable(); | ||
| 150 | return; | ||
| 151 | } | 119 | } |
| 152 | 120 | ||
| 153 | void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { | 121 | void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { |
| 154 | aw_led led = g_aw_leds[index]; | 122 | aw_led led = g_aw_leds[index]; |
| 123 | |||
| 155 | g_pwm_buffer[led.driver][led.r] = red; | 124 | g_pwm_buffer[led.driver][led.r] = red; |
| 156 | g_pwm_buffer[led.driver][led.g] = green; | 125 | g_pwm_buffer[led.driver][led.g] = green; |
| 157 | g_pwm_buffer[led.driver][led.b] = blue; | 126 | g_pwm_buffer[led.driver][led.b] = blue; |
| 158 | g_pwm_buffer_update_required[led.driver] = true; | 127 | g_pwm_buffer_update_required[led.driver] = true; |
| 159 | return; | ||
| 160 | } | 128 | } |
| 129 | |||
| 161 | void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { | 130 | void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { |
| 162 | for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) { | 131 | for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) { |
| 163 | AW20216_set_color(i, red, green, blue); | 132 | AW20216_set_color(i, red, green, blue); |
| 164 | } | 133 | } |
| 165 | return; | ||
| 166 | } | ||
| 167 | |||
| 168 | void AW20216_write_pwm_buffer(pin_t slave_pin, uint8_t buffer_idx) { | ||
| 169 | AW_SPI_START(slave_pin); | ||
| 170 | spi_write((AWINIC_ID | AW_PAGE_PWM | AW_WRITE)); | ||
| 171 | spi_write(0); | ||
| 172 | spi_transmit(g_pwm_buffer[buffer_idx], AW_PWM_REGISTER_COUNT); | ||
| 173 | spi_stop(); | ||
| 174 | } | 134 | } |
| 175 | 135 | ||
| 176 | void AW20216_update_pwm_buffers(void) { | 136 | void AW20216_update_pwm_buffers(pin_t cs_pin, uint8_t index) { |
| 177 | AW20216_write_pwm_buffer(DRIVER_1_CS, 0); | 137 | if (g_pwm_buffer_update_required[index]) { |
| 178 | #ifdef DRIVER_2_CS | 138 | AW20216_write(cs_pin, AW_PAGE_PWM, 0, g_pwm_buffer[index], AW_PWM_REGISTER_COUNT); |
| 179 | AW20216_write_pwm_buffer(DRIVER_2_CS, 1); | 139 | } |
| 180 | #endif | 140 | g_pwm_buffer_update_required[index] = false; |
| 181 | return; | ||
| 182 | } | 141 | } |
diff --git a/drivers/awinic/aw20216.h b/drivers/awinic/aw20216.h index 9c6865cc8..c55d9605f 100644 --- a/drivers/awinic/aw20216.h +++ b/drivers/awinic/aw20216.h | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | #include <stdint.h> | 19 | #include <stdint.h> |
| 20 | #include <stdbool.h> | 20 | #include <stdbool.h> |
| 21 | #include "gpio.h" | ||
| 21 | 22 | ||
| 22 | typedef struct aw_led { | 23 | typedef struct aw_led { |
| 23 | uint8_t driver : 2; | 24 | uint8_t driver : 2; |
| @@ -28,10 +29,10 @@ typedef struct aw_led { | |||
| 28 | 29 | ||
| 29 | extern const aw_led g_aw_leds[DRIVER_LED_TOTAL]; | 30 | extern const aw_led g_aw_leds[DRIVER_LED_TOTAL]; |
| 30 | 31 | ||
| 31 | void AW20216_init(void); | 32 | void AW20216_init(pin_t cs_pin, pin_t en_pin); |
| 32 | void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); | 33 | void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); |
| 33 | void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue); | 34 | void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue); |
| 34 | void AW20216_update_pwm_buffers(void); | 35 | void AW20216_update_pwm_buffers(pin_t cs_pin, uint8_t index); |
| 35 | 36 | ||
| 36 | #define CS1_SW1 0x00 | 37 | #define CS1_SW1 0x00 |
| 37 | #define CS2_SW1 0x01 | 38 | #define CS2_SW1 0x01 |
