summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bluetooth/bluefruit_le.cpp66
-rw-r--r--drivers/bluetooth/bluefruit_le.h14
-rw-r--r--drivers/bluetooth/bluetooth.c62
-rw-r--r--drivers/bluetooth/bluetooth.h52
-rw-r--r--drivers/bluetooth/rn42.c32
-rw-r--r--drivers/bluetooth/rn42.h4
-rw-r--r--drivers/haptic/solenoid.c5
-rw-r--r--drivers/haptic/solenoid.h2
-rw-r--r--drivers/led/aw20216.c2
-rw-r--r--drivers/led/aw20216.h2
-rw-r--r--drivers/led/ckled2001-simple.c4
-rw-r--r--drivers/led/ckled2001-simple.h2
-rw-r--r--drivers/led/ckled2001.c4
-rw-r--r--drivers/led/ckled2001.h2
-rw-r--r--drivers/led/issi/is31fl3731-simple.c4
-rw-r--r--drivers/led/issi/is31fl3731-simple.h2
-rw-r--r--drivers/led/issi/is31fl3731.c4
-rw-r--r--drivers/led/issi/is31fl3731.h2
-rw-r--r--drivers/led/issi/is31fl3733-simple.c4
-rw-r--r--drivers/led/issi/is31fl3733-simple.h2
-rw-r--r--drivers/led/issi/is31fl3733.c4
-rw-r--r--drivers/led/issi/is31fl3733.h2
-rw-r--r--drivers/led/issi/is31fl3736.c4
-rw-r--r--drivers/led/issi/is31fl3736.h6
-rw-r--r--drivers/led/issi/is31fl3737.c4
-rw-r--r--drivers/led/issi/is31fl3737.h2
-rw-r--r--drivers/led/issi/is31fl3741.c4
-rw-r--r--drivers/led/issi/is31fl3741.h2
-rw-r--r--drivers/led/issi/is31flcommon.c15
-rw-r--r--drivers/led/issi/is31flcommon.h6
-rw-r--r--drivers/painter/generic/qp_rgb565_surface.c277
-rw-r--r--drivers/painter/generic/qp_rgb565_surface.h42
-rw-r--r--drivers/painter/tft_panel/qp_tft_panel.c4
-rw-r--r--drivers/sensors/cirque_pinnacle.c8
-rw-r--r--drivers/sensors/cirque_pinnacle.h1
-rw-r--r--drivers/sensors/cirque_pinnacle_gestures.c8
-rw-r--r--drivers/sensors/cirque_pinnacle_i2c.c10
-rw-r--r--drivers/sensors/cirque_pinnacle_spi.c10
-rw-r--r--drivers/sensors/pimoroni_trackball.c21
-rw-r--r--drivers/sensors/pmw33xx_common.c19
40 files changed, 554 insertions, 166 deletions
diff --git a/drivers/bluetooth/bluefruit_le.cpp b/drivers/bluetooth/bluefruit_le.cpp
index 19310767cf..39c14ddd13 100644
--- a/drivers/bluetooth/bluefruit_le.cpp
+++ b/drivers/bluetooth/bluefruit_le.cpp
@@ -5,7 +5,7 @@
#include <alloca.h>
#include "debug.h"
#include "timer.h"
-#include "action_util.h"
+#include "gpio.h"
#include "ringbuffer.hpp"
#include <string.h>
#include "spi_master.h"
@@ -79,9 +79,7 @@ struct sdep_msg {
enum queue_type {
QTKeyReport, // 1-byte modifier + 6-byte key report
QTConsumer, // 16-bit key code
-#ifdef MOUSE_ENABLE
QTMouseMove, // 4-byte mouse report
-#endif
};
struct queue_item {
@@ -290,7 +288,7 @@ static void resp_buf_wait(const char *cmd) {
}
}
-static bool ble_init(void) {
+void bluefruit_le_init(void) {
state.initialized = false;
state.configured = false;
state.is_connected = false;
@@ -309,7 +307,6 @@ static bool ble_init(void) {
wait_ms(1000); // Give it a second to initialize
state.initialized = true;
- return state.initialized;
}
static inline uint8_t min(uint8_t a, uint8_t b) {
@@ -433,7 +430,7 @@ bool bluefruit_le_is_connected(void) {
bool bluefruit_le_enable_keyboard(void) {
char resbuf[128];
- if (!state.initialized && !ble_init()) {
+ if (!state.initialized) {
return false;
}
@@ -442,7 +439,7 @@ bool bluefruit_le_enable_keyboard(void) {
// Disable command echo
static const char kEcho[] PROGMEM = "ATE=0";
// Make the advertised name match the keyboard
- static const char kGapDevName[] PROGMEM = "AT+GAPDEVNAME=" STR(PRODUCT);
+ static const char kGapDevName[] PROGMEM = "AT+GAPDEVNAME=" PRODUCT;
// Turn on keyboard support
static const char kHidEnOn[] PROGMEM = "AT+BLEHIDEN=1";
@@ -581,10 +578,12 @@ static bool process_queue_item(struct queue_item *item, uint16_t timeout) {
snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->key.modifier, item->key.keys[0], item->key.keys[1], item->key.keys[2], item->key.keys[3], item->key.keys[4], item->key.keys[5]);
return at_command(cmdbuf, NULL, 0, true, timeout);
+#ifdef EXTRAKEY_ENABLE
case QTConsumer:
strcpy_P(fmtbuf, PSTR("AT+BLEHIDCONTROLKEY=0x%04x"));
snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->consumer);
return at_command(cmdbuf, NULL, 0, true, timeout);
+#endif
#ifdef MOUSE_ENABLE
case QTMouseMove:
@@ -613,41 +612,24 @@ static bool process_queue_item(struct queue_item *item, uint16_t timeout) {
}
}
-void bluefruit_le_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys) {
+void bluefruit_le_send_keyboard(report_keyboard_t *report) {
struct queue_item item;
- bool didWait = false;
item.queue_type = QTKeyReport;
- item.key.modifier = hid_modifier_mask;
- item.added = timer_read();
-
- while (nkeys >= 0) {
- item.key.keys[0] = keys[0];
- item.key.keys[1] = nkeys >= 1 ? keys[1] : 0;
- item.key.keys[2] = nkeys >= 2 ? keys[2] : 0;
- item.key.keys[3] = nkeys >= 3 ? keys[3] : 0;
- item.key.keys[4] = nkeys >= 4 ? keys[4] : 0;
- item.key.keys[5] = nkeys >= 5 ? keys[5] : 0;
-
- if (!send_buf.enqueue(item)) {
- if (!didWait) {
- dprint("wait for buf space\n");
- didWait = true;
- }
- send_buf_send_one();
- continue;
- }
+ item.key.modifier = report->mods;
+ item.key.keys[0] = report->keys[0];
+ item.key.keys[1] = report->keys[1];
+ item.key.keys[2] = report->keys[2];
+ item.key.keys[3] = report->keys[3];
+ item.key.keys[4] = report->keys[4];
+ item.key.keys[5] = report->keys[5];
- if (nkeys <= 6) {
- return;
- }
-
- nkeys -= 6;
- keys += 6;
+ while (!send_buf.enqueue(item)) {
+ send_buf_send_one();
}
}
-void bluefruit_le_send_consumer_key(uint16_t usage) {
+void bluefruit_le_send_consumer(uint16_t usage) {
struct queue_item item;
item.queue_type = QTConsumer;
@@ -658,22 +640,20 @@ void bluefruit_le_send_consumer_key(uint16_t usage) {
}
}
-#ifdef MOUSE_ENABLE
-void bluefruit_le_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons) {
+void bluefruit_le_send_mouse(report_mouse_t *report) {
struct queue_item item;
item.queue_type = QTMouseMove;
- item.mousemove.x = x;
- item.mousemove.y = y;
- item.mousemove.scroll = scroll;
- item.mousemove.pan = pan;
- item.mousemove.buttons = buttons;
+ item.mousemove.x = report->x;
+ item.mousemove.y = report->y;
+ item.mousemove.scroll = report->v;
+ item.mousemove.pan = report->h;
+ item.mousemove.buttons = report->buttons;
while (!send_buf.enqueue(item)) {
send_buf_send_one();
}
}
-#endif
uint32_t bluefruit_le_read_battery_voltage(void) {
return state.vbat;
diff --git a/drivers/bluetooth/bluefruit_le.h b/drivers/bluetooth/bluefruit_le.h
index de301c6167..a3de03c35c 100644
--- a/drivers/bluetooth/bluefruit_le.h
+++ b/drivers/bluetooth/bluefruit_le.h
@@ -7,9 +7,7 @@
#include <stdbool.h>
#include <stdint.h>
-#include <string.h>
-
-#include "config_common.h"
+#include "report.h"
#ifdef __cplusplus
extern "C" {
@@ -26,6 +24,8 @@ extern bool bluefruit_le_query_is_connected(void);
* calling ble_task() periodically. */
extern bool bluefruit_le_is_connected(void);
+extern void bluefruit_le_init(void);
+
/* Call this periodically to process BLE-originated things */
extern void bluefruit_le_task(void);
@@ -34,18 +34,16 @@ extern void bluefruit_le_task(void);
* this set of keys.
* Also sends a key release indicator, so that the keys do not remain
* held down. */
-extern void bluefruit_le_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys);
+extern void bluefruit_le_send_keyboard(report_keyboard_t *report);
/* Send a consumer usage.
* (milliseconds) */
-extern void bluefruit_le_send_consumer_key(uint16_t usage);
+extern void bluefruit_le_send_consumer(uint16_t usage);
-#ifdef MOUSE_ENABLE
/* Send a mouse/wheel movement report.
* The parameters are signed and indicate positive or negative direction
* change. */
-extern void bluefruit_le_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons);
-#endif
+extern void bluefruit_le_send_mouse(report_mouse_t *report);
/* Compute battery voltage by reading an analog pin.
* Returns the integer number of millivolts */
diff --git a/drivers/bluetooth/bluetooth.c b/drivers/bluetooth/bluetooth.c
new file mode 100644
index 0000000000..d5382401e7
--- /dev/null
+++ b/drivers/bluetooth/bluetooth.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2022
+ *
+ * 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 "bluetooth.h"
+
+#if defined(BLUETOOTH_BLUEFRUIT_LE)
+# include "bluefruit_le.h"
+#elif defined(BLUETOOTH_RN42)
+# include "rn42.h"
+#endif
+
+void bluetooth_init(void) {
+#if defined(BLUETOOTH_BLUEFRUIT_LE)
+ bluefruit_le_init();
+#elif defined(BLUETOOTH_RN42)
+ rn42_init();
+#endif
+}
+
+void bluetooth_task(void) {
+#if defined(BLUETOOTH_BLUEFRUIT_LE)
+ bluefruit_le_task();
+#endif
+}
+
+void bluetooth_send_keyboard(report_keyboard_t *report) {
+#if defined(BLUETOOTH_BLUEFRUIT_LE)
+ bluefruit_le_send_keyboard(report);
+#elif defined(BLUETOOTH_RN42)
+ rn42_send_keyboard(report);
+#endif
+}
+
+void bluetooth_send_mouse(report_mouse_t *report) {
+#if defined(BLUETOOTH_BLUEFRUIT_LE)
+ bluefruit_le_send_mouse(report);
+#elif defined(BLUETOOTH_RN42)
+ rn42_send_mouse(report);
+#endif
+}
+
+void bluetooth_send_consumer(uint16_t usage) {
+#if defined(BLUETOOTH_BLUEFRUIT_LE)
+ bluefruit_le_send_consumer(usage);
+#elif defined(BLUETOOTH_RN42)
+ rn42_send_consumer(usage);
+#endif
+}
diff --git a/drivers/bluetooth/bluetooth.h b/drivers/bluetooth/bluetooth.h
new file mode 100644
index 0000000000..2e4d0df538
--- /dev/null
+++ b/drivers/bluetooth/bluetooth.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2022
+ *
+ * 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 "report.h"
+
+/**
+ * \brief Initialize the Bluetooth system.
+ */
+void bluetooth_init(void);
+
+/**
+ * \brief Perform housekeeping tasks.
+ */
+void bluetooth_task(void);
+
+/**
+ * \brief Send a keyboard report.
+ *
+ * \param report The keyboard report to send.
+ */
+void bluetooth_send_keyboard(report_keyboard_t *report);
+
+/**
+ * \brief Send a mouse report.
+ *
+ * \param report The mouse report to send.
+ */
+void bluetooth_send_mouse(report_mouse_t *report);
+
+/**
+ * \brief Send a consumer usage.
+ *
+ * \param usage The consumer usage to send.
+ */
+void bluetooth_send_consumer(uint16_t usage);
diff --git a/drivers/bluetooth/rn42.c b/drivers/bluetooth/rn42.c
index 5d497cda20..0eb1733723 100644
--- a/drivers/bluetooth/rn42.c
+++ b/drivers/bluetooth/rn42.c
@@ -14,6 +14,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "rn42.h"
+
#include "report.h"
#include "uart.h"
@@ -69,33 +71,35 @@ void rn42_send_keyboard(report_keyboard_t *report) {
uart_write(0xFD);
uart_write(0x09);
uart_write(0x01);
+
uart_write(report->mods);
uart_write(0x00);
- for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
- uart_write(report->keys[i]);
- }
+ uart_write(report->keys[0]);
+ uart_write(report->keys[1]);
+ uart_write(report->keys[2]);
+ uart_write(report->keys[3]);
+ uart_write(report->keys[4]);
+ uart_write(report->keys[5]);
}
void rn42_send_mouse(report_mouse_t *report) {
uart_write(0xFD);
- uart_write(0x00);
- uart_write(0x03);
+ uart_write(0x05);
+ uart_write(0x02);
+
uart_write(report->buttons);
uart_write(report->x);
uart_write(report->y);
- uart_write(report->v); // should try sending the wheel v here
- uart_write(report->h); // should try sending the wheel h here
- uart_write(0x00);
+ uart_write(report->v);
}
-void rn42_send_consumer(uint16_t data) {
- static uint16_t last_data = 0;
- if (data == last_data) return;
- last_data = data;
- uint16_t bitmap = rn42_consumer_usage_to_bitmap(data);
+void rn42_send_consumer(uint16_t usage) {
+ uint16_t bitmap = rn42_consumer_usage_to_bitmap(usage);
+
uart_write(0xFD);
uart_write(0x03);
uart_write(0x03);
+
uart_write(bitmap & 0xFF);
- uart_write((bitmap >> 8) & 0xFF);
+ uart_write(bitmap >> 8);
}
diff --git a/drivers/bluetooth/rn42.h b/drivers/bluetooth/rn42.h
index 4747759111..89b716bfcd 100644
--- a/drivers/bluetooth/rn42.h
+++ b/drivers/bluetooth/rn42.h
@@ -14,6 +14,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdint.h>
+
#include "report.h"
void rn42_init(void);
@@ -22,4 +24,4 @@ void rn42_send_keyboard(report_keyboard_t *report);
void rn42_send_mouse(report_mouse_t *report);
-void rn42_send_consumer(uint16_t data);
+void rn42_send_consumer(uint16_t usage);
diff --git a/drivers/haptic/solenoid.c b/drivers/haptic/solenoid.c
index 637a77da3d..4e43903255 100644
--- a/drivers/haptic/solenoid.c
+++ b/drivers/haptic/solenoid.c
@@ -20,11 +20,12 @@
#include "haptic.h"
#include "gpio.h"
#include "usb_device_state.h"
+#include "util.h"
#include <stdlib.h>
uint8_t solenoid_dwell = SOLENOID_DEFAULT_DWELL;
static pin_t solenoid_pads[] = SOLENOID_PINS;
-#define NUMBER_OF_SOLENOIDS (sizeof(solenoid_pads) / sizeof(pin_t))
+#define NUMBER_OF_SOLENOIDS ARRAY_SIZE(solenoid_pads)
bool solenoid_on[NUMBER_OF_SOLENOIDS] = {false};
bool solenoid_buzzing[NUMBER_OF_SOLENOIDS] = {false};
uint16_t solenoid_start[NUMBER_OF_SOLENOIDS] = {0};
@@ -147,7 +148,7 @@ void solenoid_check(void) {
void solenoid_setup(void) {
#ifdef SOLENOID_PINS_ACTIVE_STATE
bool state_temp[] = SOLENOID_PINS_ACTIVE_STATE;
- uint8_t bound_check = (sizeof(state_temp) / sizeof(bool));
+ uint8_t bound_check = ARRAY_SIZE(state_temp);
#endif
for (uint8_t i = 0; i < NUMBER_OF_SOLENOIDS; i++) {
diff --git a/drivers/haptic/solenoid.h b/drivers/haptic/solenoid.h
index 952f86e922..17f5345bc6 100644
--- a/drivers/haptic/solenoid.h
+++ b/drivers/haptic/solenoid.h
@@ -54,7 +54,7 @@
# endif
#endif
-void solenoidbuzz_on(void);
+void solenoid_buzz_on(void);
void solenoid_buzz_off(void);
void solenoid_set_buzz(uint8_t buzz);
diff --git a/drivers/led/aw20216.c b/drivers/led/aw20216.c
index 55083936ef..cbb0b60774 100644
--- a/drivers/led/aw20216.c
+++ b/drivers/led/aw20216.c
@@ -133,7 +133,7 @@ void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
}
void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
- for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (uint8_t i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
AW20216_set_color(i, red, green, blue);
}
}
diff --git a/drivers/led/aw20216.h b/drivers/led/aw20216.h
index 0a17050fed..c6e71b4b4e 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 PROGMEM g_aw_leds[DRIVER_LED_TOTAL];
+extern const aw_led PROGMEM g_aw_leds[RGB_MATRIX_LED_COUNT];
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-simple.c b/drivers/led/ckled2001-simple.c
index da4bf20b99..6c4ffd398e 100644
--- a/drivers/led/ckled2001-simple.c
+++ b/drivers/led/ckled2001-simple.c
@@ -148,7 +148,7 @@ void CKLED2001_init(uint8_t addr) {
void CKLED2001_set_value(int index, uint8_t value) {
ckled2001_led led;
- if (index >= 0 && index < DRIVER_LED_TOTAL) {
+ if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
memcpy_P(&led, (&g_ckled2001_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.v] = value;
@@ -157,7 +157,7 @@ void CKLED2001_set_value(int index, uint8_t value) {
}
void CKLED2001_set_value_all(uint8_t value) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
CKLED2001_set_value(i, value);
}
}
diff --git a/drivers/led/ckled2001-simple.h b/drivers/led/ckled2001-simple.h
index 731da2e1cd..a56cad3461 100644
--- a/drivers/led/ckled2001-simple.h
+++ b/drivers/led/ckled2001-simple.h
@@ -25,7 +25,7 @@ typedef struct ckled2001_led {
uint8_t v;
} __attribute__((packed)) ckled2001_led;
-extern const ckled2001_led PROGMEM g_ckled2001_leds[DRIVER_LED_TOTAL];
+extern const ckled2001_led PROGMEM g_ckled2001_leds[LED_MATRIX_LED_COUNT];
void CKLED2001_init(uint8_t addr);
bool CKLED2001_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/led/ckled2001.c b/drivers/led/ckled2001.c
index b7e7db06cc..1651628175 100644
--- a/drivers/led/ckled2001.c
+++ b/drivers/led/ckled2001.c
@@ -148,7 +148,7 @@ void CKLED2001_init(uint8_t addr) {
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) {
+ if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
memcpy_P(&led, (&g_ckled2001_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.r] = red;
@@ -159,7 +159,7 @@ 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) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
CKLED2001_set_color(i, red, green, blue);
}
}
diff --git a/drivers/led/ckled2001.h b/drivers/led/ckled2001.h
index 7d5ad34f95..aa70a0623f 100644
--- a/drivers/led/ckled2001.h
+++ b/drivers/led/ckled2001.h
@@ -27,7 +27,7 @@ typedef struct ckled2001_led {
uint8_t b;
} __attribute__((packed)) ckled2001_led;
-extern const ckled2001_led PROGMEM g_ckled2001_leds[DRIVER_LED_TOTAL];
+extern const ckled2001_led PROGMEM g_ckled2001_leds[RGB_MATRIX_LED_COUNT];
void CKLED2001_init(uint8_t addr);
bool CKLED2001_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/led/issi/is31fl3731-simple.c b/drivers/led/issi/is31fl3731-simple.c
index 3abe9ea337..84060f9426 100644
--- a/drivers/led/issi/is31fl3731-simple.c
+++ b/drivers/led/issi/is31fl3731-simple.c
@@ -194,7 +194,7 @@ 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) {
+ if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
// Subtract 0x24 to get the second index of g_pwm_buffer
@@ -204,7 +204,7 @@ void IS31FL3731_set_value(int index, uint8_t value) {
}
void IS31FL3731_set_value_all(uint8_t value) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
IS31FL3731_set_value(i, value);
}
}
diff --git a/drivers/led/issi/is31fl3731-simple.h b/drivers/led/issi/is31fl3731-simple.h
index ded94b0470..1ddadd5209 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 PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT];
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 9c6c29f081..fed5354145 100644
--- a/drivers/led/issi/is31fl3731.c
+++ b/drivers/led/issi/is31fl3731.c
@@ -182,7 +182,7 @@ 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) {
+ if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
// Subtract 0x24 to get the second index of g_pwm_buffer
@@ -194,7 +194,7 @@ void IS31FL3731_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
}
void IS31FL3731_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
IS31FL3731_set_color(i, red, green, blue);
}
}
diff --git a/drivers/led/issi/is31fl3731.h b/drivers/led/issi/is31fl3731.h
index 6647119eba..6791289c9e 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 PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT];
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-simple.c b/drivers/led/issi/is31fl3733-simple.c
index 2f41a7b1a9..1e0994d780 100644
--- a/drivers/led/issi/is31fl3733-simple.c
+++ b/drivers/led/issi/is31fl3733-simple.c
@@ -195,7 +195,7 @@ void IS31FL3733_init(uint8_t addr, uint8_t sync) {
}
void IS31FL3733_set_value(int index, uint8_t value) {
- if (index >= 0 && index < DRIVER_LED_TOTAL) {
+ if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
is31_led led = g_is31_leds[index];
g_pwm_buffer[led.driver][led.v] = value;
@@ -204,7 +204,7 @@ void IS31FL3733_set_value(int index, uint8_t value) {
}
void IS31FL3733_set_value_all(uint8_t value) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
IS31FL3733_set_value(i, value);
}
}
diff --git a/drivers/led/issi/is31fl3733-simple.h b/drivers/led/issi/is31fl3733-simple.h
index f5253e3101..f0ea3adca0 100644
--- a/drivers/led/issi/is31fl3733-simple.h
+++ b/drivers/led/issi/is31fl3733-simple.h
@@ -29,7 +29,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 __flash g_is31_leds[LED_MATRIX_LED_COUNT];
void IS31FL3733_init(uint8_t addr, uint8_t sync);
bool IS31FL3733_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 add998f256..379eaa0ae3 100644
--- a/drivers/led/issi/is31fl3733.c
+++ b/drivers/led/issi/is31fl3733.c
@@ -186,7 +186,7 @@ void IS31FL3733_init(uint8_t addr, uint8_t sync) {
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) {
+ if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.r] = red;
@@ -197,7 +197,7 @@ 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) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
IS31FL3733_set_color(i, red, green, blue);
}
}
diff --git a/drivers/led/issi/is31fl3733.h b/drivers/led/issi/is31fl3733.h
index 7653dd17c0..29441846ac 100644
--- a/drivers/led/issi/is31fl3733.h
+++ b/drivers/led/issi/is31fl3733.h
@@ -30,7 +30,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT];
void IS31FL3733_init(uint8_t addr, uint8_t sync);
bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/led/issi/is31fl3736.c b/drivers/led/issi/is31fl3736.c
index e9943614d2..82e7ee3d18 100644
--- a/drivers/led/issi/is31fl3736.c
+++ b/drivers/led/issi/is31fl3736.c
@@ -168,7 +168,7 @@ 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) {
+ if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.r] = red;
@@ -179,7 +179,7 @@ void IS31FL3736_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
}
void IS31FL3736_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
IS31FL3736_set_color(i, red, green, blue);
}
}
diff --git a/drivers/led/issi/is31fl3736.h b/drivers/led/issi/is31fl3736.h
index f126034615..ccb19afbcc 100644
--- a/drivers/led/issi/is31fl3736.h
+++ b/drivers/led/issi/is31fl3736.h
@@ -28,8 +28,8 @@
# define DRIVER_COUNT 2
#endif
-#ifndef DRIVER_LED_TOTAL
-# define DRIVER_LED_TOTAL 96
+#ifndef RGB_MATRIX_LED_COUNT
+# define RGB_MATRIX_LED_COUNT 96
#endif
typedef struct is31_led {
@@ -39,7 +39,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT];
void IS31FL3736_init(uint8_t addr);
void IS31FL3736_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/led/issi/is31fl3737.c b/drivers/led/issi/is31fl3737.c
index 932530ac0a..45a20018c5 100644
--- a/drivers/led/issi/is31fl3737.c
+++ b/drivers/led/issi/is31fl3737.c
@@ -175,7 +175,7 @@ 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) {
+ if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.r] = red;
@@ -186,7 +186,7 @@ void IS31FL3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
}
void IS31FL3737_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
IS31FL3737_set_color(i, red, green, blue);
}
}
diff --git a/drivers/led/issi/is31fl3737.h b/drivers/led/issi/is31fl3737.h
index ddb70a9df5..fb0c33420c 100644
--- a/drivers/led/issi/is31fl3737.h
+++ b/drivers/led/issi/is31fl3737.h
@@ -30,7 +30,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT];
void IS31FL3737_init(uint8_t addr);
void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/led/issi/is31fl3741.c b/drivers/led/issi/is31fl3741.c
index ba6b6761a3..c2cdd4c46f 100644
--- a/drivers/led/issi/is31fl3741.c
+++ b/drivers/led/issi/is31fl3741.c
@@ -179,7 +179,7 @@ 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) {
+ if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.r] = red;
@@ -190,7 +190,7 @@ void IS31FL3741_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
}
void IS31FL3741_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
IS31FL3741_set_color(i, red, green, blue);
}
}
diff --git a/drivers/led/issi/is31fl3741.h b/drivers/led/issi/is31fl3741.h
index 3bdb23bd2d..b0089ea5ba 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 PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT];
void IS31FL3741_init(uint8_t addr);
void IS31FL3741_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/led/issi/is31flcommon.c b/drivers/led/issi/is31flcommon.c
index 9f4b2123ff..106890a8bf 100644
--- a/drivers/led/issi/is31flcommon.c
+++ b/drivers/led/issi/is31flcommon.c
@@ -135,14 +135,17 @@ void IS31FL_common_update_pwm_register(uint8_t addr, uint8_t index) {
void IS31FL_set_manual_scaling_buffer(void) {
for (int i = 0; i < ISSI_MANUAL_SCALING; i++) {
is31_led scale = g_is31_scaling[i];
- if (scale.driver >= 0 && scale.driver < DRIVER_LED_TOTAL) {
+# ifdef RGB_MATRIX_ENABLE
+ if (scale.driver >= 0 && scale.driver < RGB_MATRIX_LED_COUNT) {
is31_led led = g_is31_leds[scale.driver];
-# ifdef RGB_MATRIX_ENABLE
g_scaling_buffer[led.driver][led.r] = scale.r;
g_scaling_buffer[led.driver][led.g] = scale.g;
g_scaling_buffer[led.driver][led.b] = scale.b;
# elif defined(LED_MATRIX_ENABLE)
+ if (scale.driver >= 0 && scale.driver < LED_MATRIX_LED_COUNT) {
+ is31_led led = g_is31_leds[scale.driver];
+
g_scaling_buffer[led.driver][led.v] = scale.v;
# endif
g_scaling_buffer_update_required[led.driver] = true;
@@ -165,7 +168,7 @@ void IS31FL_common_update_scaling_register(uint8_t addr, uint8_t index) {
#ifdef RGB_MATRIX_ENABLE
// Colour is set by adjusting PWM register
void IS31FL_RGB_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
- if (index >= 0 && index < DRIVER_LED_TOTAL) {
+ if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
is31_led led = g_is31_leds[index];
g_pwm_buffer[led.driver][led.r] = red;
@@ -176,7 +179,7 @@ void IS31FL_RGB_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
}
void IS31FL_RGB_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
IS31FL_RGB_set_color(i, red, green, blue);
}
}
@@ -215,7 +218,7 @@ void IS31FL_simple_set_scaling_buffer(uint8_t index, bool value) {
}
void IS31FL_simple_set_brightness(int index, uint8_t value) {
- if (index >= 0 && index < DRIVER_LED_TOTAL) {
+ if (index >= 0 && index < LED_MATRIX_LED_COUNT) {
is31_led led = g_is31_leds[index];
g_pwm_buffer[led.driver][led.v] = value;
g_pwm_buffer_update_required[led.driver] = true;
@@ -223,7 +226,7 @@ void IS31FL_simple_set_brightness(int index, uint8_t value) {
}
void IS31FL_simple_set_brigntness_all(uint8_t value) {
- for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ for (int i = 0; i < LED_MATRIX_LED_COUNT; i++) {
IS31FL_simple_set_brightness(i, value);
}
}
diff --git a/drivers/led/issi/is31flcommon.h b/drivers/led/issi/is31flcommon.h
index 77e9665e32..18432ffc31 100644
--- a/drivers/led/issi/is31flcommon.h
+++ b/drivers/led/issi/is31flcommon.h
@@ -43,11 +43,15 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
+extern const is31_led __flash g_is31_leds[RGB_MATRIX_LED_COUNT];
+
#elif defined(LED_MATRIX_ENABLE)
typedef struct is31_led {
uint8_t driver;
uint8_t v;
} __attribute__((packed)) is31_led;
+
+extern const is31_led __flash g_is31_leds[LED_MATRIX_LED_COUNT];
#endif
#ifdef ISSI_MANUAL_SCALING
@@ -55,8 +59,6 @@ extern const is31_led __flash g_is31_scaling[];
void IS31FL_set_manual_scaling_buffer(void);
#endif
-extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
-
void IS31FL_write_single_register(uint8_t addr, uint8_t reg, uint8_t data);
bool IS31FL_write_multi_registers(uint8_t addr, uint8_t *source_buffer, uint8_t buffer_size, uint8_t transfer_size, uint8_t start_reg_addr);
void IS31FL_unlock_register(uint8_t addr, uint8_t page);
diff --git a/drivers/painter/generic/qp_rgb565_surface.c b/drivers/painter/generic/qp_rgb565_surface.c
new file mode 100644
index 0000000000..c4de336535
--- /dev/null
+++ b/drivers/painter/generic/qp_rgb565_surface.c
@@ -0,0 +1,277 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include "color.h"
+#include "qp_rgb565_surface.h"
+#include "qp_draw.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Common
+
+// Device definition
+typedef struct rgb565_surface_painter_device_t {
+ struct painter_driver_t base; // must be first, so it can be cast to/from the painter_device_t* type
+
+ // The target buffer
+ uint16_t *buffer;
+
+ // Manually manage the viewport for streaming pixel data to the display
+ uint16_t viewport_l;
+ uint16_t viewport_t;
+ uint16_t viewport_r;
+ uint16_t viewport_b;
+
+ // Current write location to the display when streaming pixel data
+ uint16_t pixdata_x;
+ uint16_t pixdata_y;
+
+ // Maintain a dirty region so we can stream only what we need
+ bool is_dirty;
+ uint16_t dirty_l;
+ uint16_t dirty_t;
+ uint16_t dirty_r;
+ uint16_t dirty_b;
+
+} rgb565_surface_painter_device_t;
+
+// Driver storage
+rgb565_surface_painter_device_t surface_drivers[RGB565_SURFACE_NUM_DEVICES] = {0};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Helpers
+
+static inline void increment_pixdata_location(rgb565_surface_painter_device_t *surface) {
+ // Increment the X-position
+ surface->pixdata_x++;
+
+ // If the x-coord has gone past the right-side edge, loop it back around and increment the y-coord
+ if (surface->pixdata_x > surface->viewport_r) {
+ surface->pixdata_x = surface->viewport_l;
+ surface->pixdata_y++;
+ }
+
+ // If the y-coord has gone past the bottom, loop it back to the top
+ if (surface->pixdata_y > surface->viewport_b) {
+ surface->pixdata_y = surface->viewport_t;
+ }
+}
+
+static inline void setpixel(rgb565_surface_painter_device_t *surface, uint16_t x, uint16_t y, uint16_t rgb565) {
+ // Skip messing with the dirty info if the original value already matches
+ if (surface->buffer[y * surface->base.panel_width + x] != rgb565) {
+ // Maintain dirty region
+ if (surface->dirty_l > x) {
+ surface->dirty_l = x;
+ }
+ if (surface->dirty_r < x) {
+ surface->dirty_r = x;
+ }
+ if (surface->dirty_t > y) {
+ surface->dirty_t = y;
+ }
+ if (surface->dirty_b < y) {
+ surface->dirty_b = y;
+ }
+
+ // Always dirty after a setpixel
+ surface->is_dirty = true;
+
+ // Update the pixel data in the buffer
+ surface->buffer[y * surface->base.panel_width + x] = rgb565;
+ }
+}
+
+static inline void append_pixel(rgb565_surface_painter_device_t *surface, uint16_t rgb565) {
+ setpixel(surface, surface->pixdata_x, surface->pixdata_y, rgb565);
+ increment_pixdata_location(surface);
+}
+
+static inline void stream_pixdata(rgb565_surface_painter_device_t *surface, const uint16_t *data, uint32_t native_pixel_count) {
+ for (uint32_t pixel_counter = 0; pixel_counter < native_pixel_count; ++pixel_counter) {
+ append_pixel(surface, data[pixel_counter]);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Driver vtable
+
+static bool qp_rgb565_surface_init(painter_device_t device, painter_rotation_t rotation) {
+ struct painter_driver_t * driver = (struct painter_driver_t *)device;
+ rgb565_surface_painter_device_t *surface = (rgb565_surface_painter_device_t *)driver;
+ memset(surface->buffer, 0, driver->panel_width * driver->panel_height * driver->native_bits_per_pixel / 8);
+ return true;
+}
+
+static bool qp_rgb565_surface_power(painter_device_t device, bool power_on) {
+ // No-op.
+ return true;
+}
+
+static bool qp_rgb565_surface_clear(painter_device_t device) {
+ struct painter_driver_t *driver = (struct painter_driver_t *)device;
+ driver->driver_vtable->init(device, driver->rotation); // Re-init the surface
+ return true;
+}
+
+static bool qp_rgb565_surface_flush(painter_device_t device) {
+ struct painter_driver_t * driver = (struct painter_driver_t *)device;
+ rgb565_surface_painter_device_t *surface = (rgb565_surface_painter_device_t *)driver;
+ surface->dirty_l = surface->dirty_t = UINT16_MAX;
+ surface->dirty_r = surface->dirty_b = 0;
+ surface->is_dirty = false;
+ return true;
+}
+
+static bool qp_rgb565_surface_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) {
+ struct painter_driver_t * driver = (struct painter_driver_t *)device;
+ rgb565_surface_painter_device_t *surface = (rgb565_surface_painter_device_t *)driver;
+
+ // Set the viewport locations
+ surface->viewport_l = left;
+ surface->viewport_t = top;
+ surface->viewport_r = right;
+ surface->viewport_b = bottom;
+
+ // Reset the write location to the top left
+ surface->pixdata_x = left;
+ surface->pixdata_y = top;
+ return true;
+}
+
+// Stream pixel data to the current write position in GRAM
+static bool qp_rgb565_surface_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) {
+ struct painter_driver_t * driver = (struct painter_driver_t *)device;
+ rgb565_surface_painter_device_t *surface = (rgb565_surface_painter_device_t *)driver;
+ stream_pixdata(surface, (const uint16_t *)pixel_data, native_pixel_count);
+ return true;
+}
+
+// Pixel colour conversion
+static bool qp_rgb565_surface_palette_convert_rgb565_swapped(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) {
+ for (int16_t i = 0; i < palette_size; ++i) {
+ RGB rgb = hsv_to_rgb_nocie((HSV){palette[i].hsv888.h, palette[i].hsv888.s, palette[i].hsv888.v});
+ uint16_t rgb565 = (((uint16_t)rgb.r) >> 3) << 11 | (((uint16_t)rgb.g) >> 2) << 5 | (((uint16_t)rgb.b) >> 3);
+ palette[i].rgb565 = __builtin_bswap16(rgb565);
+ }
+ return true;
+}
+
+// Append pixels to the target location, keyed by the pixel index
+static bool qp_rgb565_surface_append_pixels_rgb565(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) {
+ uint16_t *buf = (uint16_t *)target_buffer;
+ for (uint32_t i = 0; i < pixel_count; ++i) {
+ buf[pixel_offset + i] = palette[palette_indices[i]].rgb565;
+ }
+ return true;
+}
+
+const struct painter_driver_vtable_t rgb565_surface_driver_vtable = {
+ .init = qp_rgb565_surface_init,
+ .power = qp_rgb565_surface_power,
+ .clear = qp_rgb565_surface_clear,
+ .flush = qp_rgb565_surface_flush,
+ .pixdata = qp_rgb565_surface_pixdata,
+ .viewport = qp_rgb565_surface_viewport,
+ .palette_convert = qp_rgb565_surface_palette_convert_rgb565_swapped,
+ .append_pixels = qp_rgb565_surface_append_pixels_rgb565,
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Comms vtable
+
+static bool qp_rgb565_surface_comms_init(painter_device_t device) {
+ // No-op.
+ return true;
+}
+static bool qp_rgb565_surface_comms_start(painter_device_t device) {
+ // No-op.
+ return true;
+}
+static void qp_rgb565_surface_comms_stop(painter_device_t device) {
+ // No-op.
+}
+uint32_t qp_rgb565_surface_comms_send(painter_device_t device, const void *data, uint32_t byte_count) {
+ // No-op.
+ return byte_count;
+}
+
+struct painter_comms_vtable_t rgb565_surface_driver_comms_vtable = {
+ // These are all effective no-op's because they're not actually needed.
+ .comms_init = qp_rgb565_surface_comms_init,
+ .comms_start = qp_rgb565_surface_comms_start,
+ .comms_stop = qp_rgb565_surface_comms_stop,
+ .comms_send = qp_rgb565_surface_comms_send};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Factory function for creating a handle to an rgb565 surface
+
+painter_device_t qp_rgb565_make_surface(uint16_t panel_width, uint16_t panel_height, void *buffer) {
+ for (uint32_t i = 0; i < RGB565_SURFACE_NUM_DEVICES; ++i) {
+ rgb565_surface_painter_device_t *driver = &surface_drivers[i];
+ if (!driver->base.driver_vtable) {
+ driver->base.driver_vtable = &rgb565_surface_driver_vtable;
+ driver->base.comms_vtable = &rgb565_surface_driver_comms_vtable;
+ driver->base.native_bits_per_pixel = 16; // RGB565
+ driver->base.panel_width = panel_width;
+ driver->base.panel_height = panel_height;
+ driver->base.rotation = QP_ROTATION_0;
+ driver->base.offset_x = 0;
+ driver->base.offset_y = 0;
+ driver->buffer = (uint16_t *)buffer;
+ return (painter_device_t)driver;
+ }
+ }
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Drawing routine to copy out the dirty region and send it to another device
+
+bool qp_rgb565_surface_draw(painter_device_t surface, painter_device_t display, uint16_t x, uint16_t y) {
+ struct painter_driver_t * surface_driver = (struct painter_driver_t *)surface;
+ rgb565_surface_painter_device_t *surface_handle = (rgb565_surface_painter_device_t *)surface_driver;
+
+ // If we're not dirty... we're done.
+ if (!surface_handle->is_dirty) {
+ return true;
+ }
+
+ // Set the target drawing area
+ bool ok = qp_viewport(display, x + surface_handle->dirty_l, y + surface_handle->dirty_t, x + surface_handle->dirty_r, y + surface_handle->dirty_b);
+ if (!ok) {
+ return false;
+ }
+
+ // Housekeeping of the amount of pixels to transfer
+ uint32_t total_pixel_count = QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE / sizeof(uint16_t);
+ uint32_t pixel_counter = 0;
+ uint16_t *target_buffer = (uint16_t *)qp_internal_global_pixdata_buffer;
+
+ // Fill the global pixdata area so that we can start transferring to the panel
+ for (uint16_t y = surface_handle->dirty_t; y <= surface_handle->dirty_b; ++y) {
+ for (uint16_t x = surface_handle->dirty_l; x <= surface_handle->dirty_r; ++x) {
+ // Update the target buffer
+ target_buffer[pixel_counter++] = surface_handle->buffer[y * surface_handle->base.panel_width + x];
+
+ // If we've accumulated enough data, send it
+ if (pixel_counter == total_pixel_count) {
+ ok = qp_pixdata(display, qp_internal_global_pixdata_buffer, pixel_counter);
+ if (!ok) {
+ return false;
+ }
+ // Reset the counter
+ pixel_counter = 0;
+ }
+ }
+ }
+
+ // If there's any leftover data, send it
+ if (pixel_counter > 0) {
+ ok = qp_pixdata(display, qp_internal_global_pixdata_buffer, pixel_counter);
+ if (!ok) {
+ return false;
+ }
+ }
+
+ // Clear the dirty info for the surface
+ return qp_flush(surface);
+}
diff --git a/drivers/painter/generic/qp_rgb565_surface.h b/drivers/painter/generic/qp_rgb565_surface.h
new file mode 100644
index 0000000000..19e919bb91
--- /dev/null
+++ b/drivers/painter/generic/qp_rgb565_surface.h
@@ -0,0 +1,42 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include "qp_internal.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter RGB565 surface configurables (add to your keyboard's config.h)
+
+#ifndef RGB565_SURFACE_NUM_DEVICES
+/**
+ * @def This controls the maximum number of surface devices that Quantum Painter can use at any one time.
+ * Increasing this number allows for multiple framebuffers to be used. Each requires its own RAM allocation.
+ */
+# define RGB565_SURFACE_NUM_DEVICES 1
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Forward declarations
+
+#ifdef QUANTUM_PAINTER_RGB565_SURFACE_ENABLE
+/**
+ * Factory method for an RGB565 surface (aka framebuffer).
+ *
+ * @param panel_width[in] the width of the display panel
+ * @param panel_height[in] the height of the display panel
+ * @param buffer[in] pointer to a preallocated buffer of size `(sizeof(uint16_t) * panel_width * panel_height)`
+ * @return the device handle used with all drawing routines in Quantum Painter
+ */
+painter_device_t qp_rgb565_make_surface(uint16_t panel_width, uint16_t panel_height, void *buffer);
+
+/**
+ * Helper method to draw the dirty contents of the framebuffer to the target device.
+ *
+ * After successful completion, the dirty area is reset.
+ *
+ * @param surface[in] the surface to copy from
+ * @param display[in] the display to copy into
+ * @param x[in] the x-location of the original position of the framebuffer
+ * @param y[in] the y-location of the original position of the framebuffer
+ * @return whether the draw operation completed successfully
+ */
+bool qp_rgb565_surface_draw(painter_device_t surface, painter_device_t display, uint16_t x, uint16_t y);
+#endif // QUANTUM_PAINTER_RGB565_SURFACE_ENABLE
diff --git a/drivers/painter/tft_panel/qp_tft_panel.c b/drivers/painter/tft_panel/qp_tft_panel.c
index ad83b6c792..e7c744ab34 100644
--- a/drivers/painter/tft_panel/qp_tft_panel.c
+++ b/drivers/painter/tft_panel/qp_tft_panel.c
@@ -7,8 +7,6 @@
#include "qp_draw.h"
#include "qp_tft_panel.h"
-#define BYTE_SWAP(x) (((((uint16_t)(x)) >> 8) & 0x00FF) | ((((uint16_t)(x)) << 8) & 0xFF00))
-
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter API implementations
@@ -94,7 +92,7 @@ bool qp_tft_panel_palette_convert_rgb565_swapped(painter_device_t device, int16_
for (int16_t i = 0; i < palette_size; ++i) {
RGB rgb = hsv_to_rgb_nocie((HSV){palette[i].hsv888.h, palette[i].hsv888.s, palette[i].hsv888.v});
uint16_t rgb565 = (((uint16_t)rgb.r) >> 3) << 11 | (((uint16_t)rgb.g) >> 2) << 5 | (((uint16_t)rgb.b) >> 3);
- palette[i].rgb565 = BYTE_SWAP(rgb565);
+ palette[i].rgb565 = __builtin_bswap16(rgb565);
}
return true;
}
diff --git a/drivers/sensors/cirque_pinnacle.c b/drivers/sensors/cirque_pinnacle.c
index 8bd4eb736e..4aed5fe67a 100644
--- a/drivers/sensors/cirque_pinnacle.c
+++ b/drivers/sensors/cirque_pinnacle.c
@@ -4,8 +4,6 @@
// refer to documentation: Gen2 and Gen3 (Pinnacle ASIC) at https://www.cirque.com/documentation
#include "cirque_pinnacle.h"
-#include "print.h"
-#include "debug.h"
#include "wait.h"
#include "timer.h"
@@ -27,12 +25,6 @@ void cirque_pinnacle_enable_feed(bool feedEnable);
void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count);
void RAP_Write(uint8_t address, uint8_t data);
-#ifdef CONSOLE_ENABLE
-void print_byte(uint8_t byte) {
- xprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0'));
-}
-#endif
-
#if CIRQUE_PINNACLE_POSITION_MODE
/* Logical Scaling Functions */
// Clips raw coordinates to "reachable" window of sensor
diff --git a/drivers/sensors/cirque_pinnacle.h b/drivers/sensors/cirque_pinnacle.h
index fa06e047f2..8717b32991 100644
--- a/drivers/sensors/cirque_pinnacle.h
+++ b/drivers/sensors/cirque_pinnacle.h
@@ -5,6 +5,7 @@
#include "cirque_pinnacle_regdefs.h"
#include <stdint.h>
#include <stdbool.h>
+#include "pointing_device_internal.h"
#ifndef CIRQUE_PINNACLE_TIMEOUT
# define CIRQUE_PINNACLE_TIMEOUT 20 // I2C timeout in milliseconds
diff --git a/drivers/sensors/cirque_pinnacle_gestures.c b/drivers/sensors/cirque_pinnacle_gestures.c
index a73b745e59..ae3eca71c2 100644
--- a/drivers/sensors/cirque_pinnacle_gestures.c
+++ b/drivers/sensors/cirque_pinnacle_gestures.c
@@ -37,14 +37,6 @@ static report_mouse_t trackpad_tap(report_mouse_t mouse_report, pinnacle_data_t
if (!touchData.zValue) {
if (timer_elapsed(tap.timer) < CIRQUE_PINNACLE_TAPPING_TERM && tap.timer != 0) {
mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
- pointing_device_set_report(mouse_report);
- pointing_device_send();
-# if TAP_CODE_DELAY > 0
- wait_ms(TAP_CODE_DELAY);
-# endif
- mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
- pointing_device_set_report(mouse_report);
- pointing_device_send();
}
}
tap.timer = timer_read();
diff --git a/drivers/sensors/cirque_pinnacle_i2c.c b/drivers/sensors/cirque_pinnacle_i2c.c
index b328dd9a7a..3c11e5f079 100644
--- a/drivers/sensors/cirque_pinnacle_i2c.c
+++ b/drivers/sensors/cirque_pinnacle_i2c.c
@@ -1,8 +1,6 @@
// Copyright (c) 2018 Cirque Corp. Restrictions apply. See: www.cirque.com/sw-license
#include "cirque_pinnacle.h"
#include "i2c_master.h"
-#include "print.h"
-#include "debug.h"
#include "stdio.h"
// Masks for Cirque Register Access Protocol (RAP)
@@ -18,9 +16,7 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
if (touchpad_init) {
i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, NULL, 0, CIRQUE_PINNACLE_TIMEOUT);
if (i2c_readReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, data, count, CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) {
-#ifdef CONSOLE_ENABLE
- dprintf("error cirque_pinnacle i2c_readReg\n");
-#endif
+ pd_dprintf("error cirque_pinnacle i2c_readReg\n");
touchpad_init = false;
}
i2c_stop();
@@ -33,9 +29,7 @@ void RAP_Write(uint8_t address, uint8_t data) {
if (touchpad_init) {
if (i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, &data, sizeof(data), CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) {
-#ifdef CONSOLE_ENABLE
- dprintf("error cirque_pinnacle i2c_writeReg\n");
-#endif
+ pd_dprintf("error cirque_pinnacle i2c_writeReg\n");
touchpad_init = false;
}
i2c_stop();
diff --git a/drivers/sensors/cirque_pinnacle_spi.c b/drivers/sensors/cirque_pinnacle_spi.c
index bd980fc863..5cb39aebb0 100644
--- a/drivers/sensors/cirque_pinnacle_spi.c
+++ b/drivers/sensors/cirque_pinnacle_spi.c
@@ -1,8 +1,6 @@
// Copyright (c) 2018 Cirque Corp. Restrictions apply. See: www.cirque.com/sw-license
#include "cirque_pinnacle.h"
#include "spi_master.h"
-#include "print.h"
-#include "debug.h"
// Masks for Cirque Register Access Protocol (RAP)
#define WRITE_MASK 0x80
@@ -24,9 +22,7 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
data[i] = spi_write(FILLER_BYTE); // write filler, receive data on the third filler send
}
} else {
-#ifdef CONSOLE_ENABLE
- dprintf("error cirque_pinnacle spi_start read\n");
-#endif
+ pd_dprintf("error cirque_pinnacle spi_start read\n");
touchpad_init = false;
}
spi_stop();
@@ -42,9 +38,7 @@ void RAP_Write(uint8_t address, uint8_t data) {
spi_write(cmdByte);
spi_write(data);
} else {
-#ifdef CONSOLE_ENABLE
- dprintf("error cirque_pinnacle spi_start write\n");
-#endif
+ pd_dprintf("error cirque_pinnacle spi_start write\n");
touchpad_init = false;
}
spi_stop();
diff --git a/drivers/sensors/pimoroni_trackball.c b/drivers/sensors/pimoroni_trackball.c
index 88a351316b..326e59744f 100644
--- a/drivers/sensors/pimoroni_trackball.c
+++ b/drivers/sensors/pimoroni_trackball.c
@@ -14,10 +14,10 @@
* 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 "pointing_device_internal.h"
#include "pimoroni_trackball.h"
#include "i2c_master.h"
-#include "print.h"
-#include "debug.h"
#include "timer.h"
// clang-format off
@@ -58,20 +58,17 @@ void pimoroni_trackball_set_rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
uint8_t data[4] = {r, g, b, w};
__attribute__((unused)) i2c_status_t status = i2c_writeReg(PIMORONI_TRACKBALL_ADDRESS << 1, PIMORONI_TRACKBALL_REG_LED_RED, data, sizeof(data), PIMORONI_TRACKBALL_TIMEOUT);
-#ifdef CONSOLE_ENABLE
- if (debug_mouse) dprintf("Trackball RGBW i2c_status_t: %d\n", status);
-#endif
+ pd_dprintf("Trackball RGBW i2c_status_t: %d\n", status);
}
i2c_status_t read_pimoroni_trackball(pimoroni_data_t* data) {
i2c_status_t status = i2c_readReg(PIMORONI_TRACKBALL_ADDRESS << 1, PIMORONI_TRACKBALL_REG_LEFT, (uint8_t*)data, sizeof(*data), PIMORONI_TRACKBALL_TIMEOUT);
-#ifdef CONSOLE_ENABLE
- if (debug_mouse) {
- static uint16_t d_timer;
- if (timer_elapsed(d_timer) > PIMORONI_TRACKBALL_DEBUG_INTERVAL) {
- dprintf("Trackball READ i2c_status_t: %d L: %d R: %d Up: %d D: %d SW: %d\n", status, data->left, data->right, data->up, data->down, data->click);
- d_timer = timer_read();
- }
+
+#ifdef POINTING_DEVICE_DEBUG
+ static uint16_t d_timer;
+ if (timer_elapsed(d_timer) > PIMORONI_TRACKBALL_DEBUG_INTERVAL) {
+ pd_dprintf("Trackball READ i2c_status_t: %d L: %d R: %d Up: %d D: %d SW: %d\n", status, data->left, data->right, data->up, data->down, data->click);
+ d_timer = timer_read();
}
#endif
diff --git a/drivers/sensors/pmw33xx_common.c b/drivers/sensors/pmw33xx_common.c
index 13164cb150..b8d4e532ca 100644
--- a/drivers/sensors/pmw33xx_common.c
+++ b/drivers/sensors/pmw33xx_common.c
@@ -7,9 +7,8 @@
// Copyright 2020 Ploopy Corporation
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "debug.h"
+#include "pointing_device_internal.h"
#include "pmw33xx_common.h"
-#include "print.h"
#include "string.h"
#include "wait.h"
#include "spi_master.h"
@@ -18,10 +17,10 @@
extern const uint8_t pmw33xx_firmware_data[PMW33XX_FIRMWARE_LENGTH] PROGMEM;
extern const uint8_t pmw33xx_firmware_signature[3] PROGMEM;
-static const pin_t cs_pins[] = PMW33XX_CS_PINS;
-static bool in_burst[sizeof(cs_pins) / sizeof(pin_t)] = {0};
+static const pin_t cs_pins[] = PMW33XX_CS_PINS;
+static bool in_burst[ARRAY_SIZE(cs_pins)] = {0};
-const size_t pmw33xx_number_of_sensors = sizeof(cs_pins) / sizeof(pin_t);
+const size_t pmw33xx_number_of_sensors = ARRAY_SIZE(cs_pins);
bool __attribute__((cold)) pmw33xx_upload_firmware(uint8_t sensor);
bool __attribute__((cold)) pmw33xx_check_signature(uint8_t sensor);
@@ -154,7 +153,7 @@ bool pmw33xx_init(uint8_t sensor) {
pmw33xx_read(sensor, REG_Delta_Y_H);
if (!pmw33xx_upload_firmware(sensor)) {
- dprintf("PMW33XX (%d): firmware upload failed!\n", sensor);
+ pd_dprintf("PMW33XX (%d): firmware upload failed!\n", sensor);
return false;
}
@@ -170,7 +169,7 @@ bool pmw33xx_init(uint8_t sensor) {
pmw33xx_write(sensor, REG_Lift_Config, PMW33XX_LIFTOFF_DISTANCE);
if (!pmw33xx_check_signature(sensor)) {
- dprintf("PMW33XX (%d): firmware signature verification failed!\n", sensor);
+ pd_dprintf("PMW33XX (%d): firmware signature verification failed!\n", sensor);
return false;
}
@@ -185,7 +184,7 @@ pmw33xx_report_t pmw33xx_read_burst(uint8_t sensor) {
}
if (!in_burst[sensor]) {
- dprintf("PMW33XX (%d): burst\n", sensor);
+ pd_dprintf("PMW33XX (%d): burst\n", sensor);
if (!pmw33xx_write(sensor, REG_Motion_Burst, 0x00)) {
return report;
}
@@ -208,9 +207,7 @@ pmw33xx_report_t pmw33xx_read_burst(uint8_t sensor) {
spi_stop();
- if (debug_config.mouse) {
- dprintf("PMW33XX (%d): motion: 0x%x dx: %i dy: %i\n", sensor, report.motion.w, report.delta_x, report.delta_y);
- }
+ pd_dprintf("PMW33XX (%d): motion: 0x%x dx: %i dy: %i\n", sensor, report.motion.w, report.delta_x, report.delta_y);
report.delta_x *= -1;
report.delta_y *= -1;