Skip to content

Commit

Permalink
Merge remote-tracking branch 'Dexter93/sn32_rgb' into sn32_develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Jpe230 committed Dec 16, 2022
2 parents df76a8d + aebfe46 commit ce1c7d0
Show file tree
Hide file tree
Showing 5 changed files with 309 additions and 1 deletion.
8 changes: 7 additions & 1 deletion builddefs/common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ endif

RGB_MATRIX_ENABLE ?= no

VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A CKLED2001 WS2812 custom
VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 IS31FL3742A IS31FL3743A IS31FL3745 IS31FL3746A CKLED2001 WS2812 SN32F24xB custom
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid RGB_MATRIX_DRIVER,RGB_MATRIX_DRIVER="$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
Expand Down Expand Up @@ -515,6 +515,12 @@ endif
APA102_DRIVER_REQUIRED := yes
endif

ifeq ($(strip $(RGB_MATRIX_DRIVER)), SN32F24xB)
OPT_DEFS += -DSN32F24xB
COMMON_VPATH += $(DRIVER_PATH)/led/sn32
SRC += rgb_matrix_sn32f24xb.c
endif

ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes)
OPT_DEFS += -DRGB_MATRIX_CUSTOM_KB
endif
Expand Down
282 changes: 282 additions & 0 deletions drivers/led/sn32/rgb_matrix_sn32f24xb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
#include "rgb_matrix.h"
#include "sn32f24xb.h"

#if !defined(RGB_MATRIX_HUE_STEP)
# define RGB_MATRIX_HUE_STEP 8
#endif

#if !defined(RGB_MATRIX_SAT_STEP)
# define RGB_MATRIX_SAT_STEP 16
#endif

#if !defined(RGB_MATRIX_VAL_STEP)
# define RGB_MATRIX_VAL_STEP 16
#endif

#if !defined(RGB_MATRIX_SPD_STEP)
# define RGB_MATRIX_SPD_STEP 16
#endif

#define ROWS_PER_HAND (MATRIX_ROWS)

#if !defined(MATRIX_IO_DELAY)
# define MATRIX_IO_DELAY 30
#endif

#if !defined(PWM_OUTPUT_ACTIVE_LEVEL)
# define PWM_OUTPUT_ACTIVE_LEVEL PWM_OUTPUT_ACTIVE_LOW
#endif
/*
COLS key / led
SS8050 transistors NPN driven low
base - GPIO
collector - LED Col pins
emitter - VDD
VDD GPIO
(E) (B)
| PNP |
|_______|
|
|
(C)
LED
ROWS RGB
SS8550 transistors PNP driven high
base - GPIO
collector - LED RGB row pins
emitter - GND
LED
(C)
|
|
_______
| NPN |
| |
(B) (E)
GPIO GND
*/
static uint8_t chan_col_order[LED_MATRIX_COLS] = {0}; // track the channel col order
static uint8_t current_row = 0; // LED row scan counter
static uint8_t row_idx = 0; // key row scan counter
extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
static matrix_row_t shared_matrix[MATRIX_ROWS]; // scan values
static volatile bool matrix_locked = false; // matrix update check
static volatile bool matrix_scanned = false;
static const uint32_t periodticks = 256;
static const uint32_t freq = (RGB_MATRIX_HUE_STEP * RGB_MATRIX_SAT_STEP * RGB_MATRIX_VAL_STEP * RGB_MATRIX_SPD_STEP * RGB_MATRIX_LED_PROCESS_LIMIT);
static const pin_t led_row_pins[LED_MATRIX_ROWS_HW] = LED_MATRIX_ROW_PINS; // We expect a R,B,G order here
static const pin_t led_col_pins[LED_MATRIX_COLS] = LED_MATRIX_COL_PINS;
static RGB led_state[RGB_MATRIX_LED_COUNT]; // led state buffer
static RGB led_state_buf[RGB_MATRIX_LED_COUNT]; // led state buffer
#ifdef UNDERGLOW_RBG // handle underglow with flipped B,G channels
static const uint8_t underglow_leds[UNDERGLOW_LEDS] = UNDERGLOW_IDX;
#endif

void matrix_output_unselect_delay(uint8_t line, bool key_pressed) {
for (int i = 0; i < TIME_US2I(MATRIX_IO_DELAY); ++i) {
__asm__ volatile("" ::: "memory");
}
}
bool matrix_available(void) {
return matrix_scanned;
}

/* PWM configuration structure. We use timer CT16B1 with 24 channels. */
static PWMConfig pwmcfg = {
freq, /* PWM clock frequency. */
periodticks, /* PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */
NULL, /* RGB Callback */
{
/* Default all channels to disabled - Channels will be configured during init */
[0 ... 23] = {PWM_OUTPUT_DISABLED, NULL, 0},
},
0 /* HW dependent part.*/
};

static void rgb_ch_ctrl(PWMConfig *cfg) {
/* Enable PWM function, IOs and select the PWM modes for the LED column pins */
for (uint8_t i = 0; i < LED_MATRIX_COLS; i++) {
// Only P0.0 to P2.15 can be used as pwm output
if (led_col_pins[i] > C15) continue;
/* We use a tricky here, accordint to pfpa table of sn32f240b datasheet,
pwm channel and pfpa of pin Px.y can be calculated as below:
channel = (x*16+y)%24
pfpa = 1, when (x*16+y)>23
*/
uint8_t pio_value = ((uint32_t)(PAL_PORT(led_col_pins[i])) - (uint32_t)(PAL_PORT(A0))) / ((uint32_t)(PAL_PORT(B0)) - (uint32_t)(PAL_PORT(A0))) * 16 + PAL_PAD(led_col_pins[i]);
uint8_t ch_idx = pio_value % 24;
chan_col_order[i] = ch_idx;
cfg->channels[ch_idx].pfpamsk = pio_value > 23;
cfg->channels[ch_idx].mode = PWM_OUTPUT_ACTIVE_LEVEL;
}
}
static void rgb_callback(PWMDriver *pwmp);

static void shared_matrix_rgb_enable(void) {
pwmcfg.callback = rgb_callback;
pwmEnablePeriodicNotification(&PWMD1);
}

static void shared_matrix_rgb_disable_pwm(void) {
// Disable PWM outputs on column pins
for (uint8_t y = 0; y < LED_MATRIX_COLS; y++) {
pwmDisableChannel(&PWMD1, chan_col_order[y]);
}
}

static void shared_matrix_rgb_disable_leds(void) {
// Disable LED outputs on RGB channel pins
for (uint8_t x = 0; x < LED_MATRIX_ROWS_HW; x++) {
ATOMIC_BLOCK_FORCEON {
writePinLow(led_row_pins[x]);
}
}
}

static void update_pwm_channels(PWMDriver *pwmp) {
bool enable_pwm_output = false;
matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
for (uint8_t col_idx = 0; col_idx < LED_MATRIX_COLS; col_idx++, row_shifter <<= 1) {
#if (DIODE_DIRECTION == ROW2COL)
// Scan the key matrix column
if (!matrix_scanned) {
matrix_locked = true;
matrix_read_rows_on_col(shared_matrix, col_idx, row_shifter);
}
#endif // DIODE_DIRECTION == ROW2COL
uint8_t led_index = g_led_config.matrix_co[row_idx][col_idx];
// Check if we need to enable RGB output
if (led_state[led_index].b != 0) enable_pwm_output |= true;
if (led_state[led_index].g != 0) enable_pwm_output |= true;
if (led_state[led_index].r != 0) enable_pwm_output |= true;
// Update matching RGB channel PWM configuration
switch (current_row % LED_MATRIX_ROW_CHANNELS) {
case 0:
pwmEnableChannel(pwmp, chan_col_order[col_idx], led_state[led_index].b);
break;
case 1:
pwmEnableChannel(pwmp, chan_col_order[col_idx], led_state[led_index].g);
break;
case 2:
pwmEnableChannel(pwmp, chan_col_order[col_idx], led_state[led_index].r);
break;
default:;
}
}
// Enable RGB output
if (enable_pwm_output) {
ATOMIC_BLOCK_FORCEON {
writePinHigh(led_row_pins[current_row]);
}
}
#if (DIODE_DIRECTION == ROW2COL)
// The whole matrix has been scanned
matrix_locked = false;
matrix_scanned = true;
#endif // DIODE_DIRECTION == ROW2COL
}
static void rgb_callback(PWMDriver *pwmp) {
// Disable the interrupt
pwmDisablePeriodicNotification(pwmp);
// Advance to the next LED RGB channels
current_row++;
if (current_row >= LED_MATRIX_ROWS_HW) current_row = 0;
#if (DIODE_DIRECTION == COL2ROW)
uint8_t last_row_idx = row_idx;
#endif // DIODE_DIRECTION == COL2ROW
// Advance to the next key matrix row
if (current_row % LED_MATRIX_ROW_CHANNELS == 2) row_idx++;
if (row_idx >= LED_MATRIX_ROWS) row_idx = 0;
// Disable LED output before scanning the key matrix
shared_matrix_rgb_disable_leds();
shared_matrix_rgb_disable_pwm();
#if (DIODE_DIRECTION == COL2ROW)
// Scan the key matrix row
static uint8_t first_scanned_row;
if (!matrix_scanned) {
if (!matrix_locked) {
matrix_locked = true;
first_scanned_row = row_idx;
} else {
if ((last_row_idx != row_idx) && (row_idx == first_scanned_row)) {
matrix_locked = false;
matrix_scanned = true;
}
}
if (matrix_locked) {
matrix_read_cols_on_row(shared_matrix, row_idx);
}
}
#endif // DIODE_DIRECTION == COL2ROW
update_pwm_channels(pwmp);
chSysLockFromISR();
// Advance the timer to just before the wrap-around, that will start a new PWM cycle
pwm_lld_change_counter(pwmp, 0xFFFF);
// Enable the interrupt
pwmEnablePeriodicNotificationI(pwmp);
chSysUnlockFromISR();
}

void SN32F24xB_init(void) {
for (uint8_t x = 0; x < LED_MATRIX_ROWS_HW; x++) {
ATOMIC_BLOCK_FORCEON {
setPinOutput(led_row_pins[x]);
writePinLow(led_row_pins[x]);
}
}
// Determine which PWM channels we need to control
rgb_ch_ctrl(&pwmcfg);
// initialize matrix state: all keys off
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
shared_matrix[i] = 0;
}
pwmStart(&PWMD1, &pwmcfg);
shared_matrix_rgb_enable();
}

void SN32F24xB_flush(void) {
memcpy(led_state, led_state_buf, sizeof(RGB) * RGB_MATRIX_LED_COUNT);
}

void SN32F24xB_set_color(int index, uint8_t r, uint8_t g, uint8_t b) {
#ifdef UNDERGLOW_RBG
bool flip_gb = false;
for (uint8_t led_id = 0; led_id < UNDERGLOW_LEDS; led_id++) {
if (underglow_leds[led_id] == index) {
flip_gb = true;
}
}
if (flip_gb) {
led_state_buf[index].r = r;
led_state_buf[index].b = g;
led_state_buf[index].g = b;
} else {
#endif // UNDERGLOW_RBG
led_state_buf[index].r = r;
led_state_buf[index].b = b;
led_state_buf[index].g = g;
#ifdef UNDERGLOW_RBG
}
#endif // UNDERGLOW_RBG
}

void SN32F24xB_set_color_all(uint8_t r, uint8_t g, uint8_t b) {
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
SN32F24xB_set_color(i, r, g, b);
}
}

bool matrix_scan_custom(matrix_row_t current_matrix[]) {
if (!matrix_scanned) return false; // Nothing to process until we have the matrix scanned

bool changed = memcmp(raw_matrix, shared_matrix, sizeof(shared_matrix)) != 0;
if (changed) memcpy(raw_matrix, shared_matrix, sizeof(shared_matrix));

matrix_scanned = false;

return changed;
}
9 changes: 9 additions & 0 deletions drivers/led/sn32/sn32f24xb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <stdint.h>
#include <stdbool.h>

void SN32F24xB_init(void);
void SN32F24xB_flush(void);
void SN32F24xB_set_color(int index, uint8_t r, uint8_t g, uint8_t b);
void SN32F24xB_set_color_all(uint8_t r, uint8_t g, uint8_t b);
2 changes: 2 additions & 0 deletions quantum/rgb_matrix/rgb_matrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
# include "aw20216.h"
#elif defined(WS2812)
# include "ws2812.h"
#elif defined(SN32F24xB)
# include "sn32f24xb.h"
#endif

#ifndef RGB_MATRIX_LED_FLUSH_LIMIT
Expand Down
9 changes: 9 additions & 0 deletions quantum/rgb_matrix/rgb_matrix_drivers.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,4 +398,13 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color = setled,
.set_color_all = setled_all,
};

#elif defined(SN32F24xB)

const rgb_matrix_driver_t rgb_matrix_driver = {
.init = SN32F24xB_init,
.flush = SN32F24xB_flush,
.set_color = SN32F24xB_set_color,
.set_color_all = SN32F24xB_set_color_all,
};
#endif

0 comments on commit ce1c7d0

Please sign in to comment.