summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/eeprom/eeprom_custom.c-template11
-rw-r--r--drivers/eeprom/eeprom_driver.c6
-rw-r--r--drivers/eeprom/eeprom_driver.h2
-rw-r--r--drivers/eeprom/eeprom_i2c.c8
-rw-r--r--drivers/eeprom/eeprom_spi.c8
-rw-r--r--drivers/eeprom/eeprom_transient.c9
-rw-r--r--drivers/eeprom/eeprom_wear_leveling.c6
-rw-r--r--drivers/encoder/encoder_quadrature.c18
-rw-r--r--drivers/flash/flash.h126
-rw-r--r--drivers/flash/flash_spi.c89
-rw-r--r--drivers/flash/flash_spi.h31
-rw-r--r--drivers/led/apa102.c23
-rw-r--r--drivers/led/apa102.h15
-rw-r--r--drivers/painter/gc9a01/qp_gc9a01_opcodes.h77
-rw-r--r--drivers/painter/gc9xxx/qp_gc9107.c114
-rw-r--r--drivers/painter/gc9xxx/qp_gc9107.h37
-rw-r--r--drivers/painter/gc9xxx/qp_gc9107_opcodes.h135
-rw-r--r--drivers/painter/gc9xxx/qp_gc9a01.c (renamed from drivers/painter/gc9a01/qp_gc9a01.c)78
-rw-r--r--drivers/painter/gc9xxx/qp_gc9a01.h (renamed from drivers/painter/gc9a01/qp_gc9a01.h)0
-rw-r--r--drivers/painter/gc9xxx/qp_gc9a01_opcodes.h104
-rw-r--r--drivers/painter/gc9xxx/qp_gc9xxx_opcodes.h55
-rw-r--r--drivers/sensors/adns9800.c11
-rw-r--r--drivers/sensors/cirque_pinnacle_gestures.h2
-rw-r--r--drivers/sensors/pmw33xx_common.c4
-rw-r--r--drivers/wear_leveling/wear_leveling_flash_spi.c4
25 files changed, 739 insertions, 234 deletions
diff --git a/drivers/eeprom/eeprom_custom.c-template b/drivers/eeprom/eeprom_custom.c-template
index 5f915f7fab..fb1f0a3a97 100644
--- a/drivers/eeprom/eeprom_custom.c-template
+++ b/drivers/eeprom/eeprom_custom.c-template
@@ -23,6 +23,17 @@ void eeprom_driver_init(void) {
/* Any initialisation code */
}
+void eeprom_driver_format(bool erase) {
+ /* If erase=false, then only do the absolute minimum initialisation necessary
+ to make sure that the eeprom driver is usable. It doesn't need to guarantee
+ that the content of the eeprom is reset to any particular value. For many
+ eeprom drivers this may be a no-op.
+
+ If erase=true, then in addition to making sure the eeprom driver is in a
+ usable state, also make sure that it is erased.
+ */
+}
+
void eeprom_driver_erase(void) {
/* Wipe out the EEPROM, setting values to zero */
}
diff --git a/drivers/eeprom/eeprom_driver.c b/drivers/eeprom/eeprom_driver.c
index 885cf21981..1f3f96f006 100644
--- a/drivers/eeprom/eeprom_driver.c
+++ b/drivers/eeprom/eeprom_driver.c
@@ -77,3 +77,9 @@ void eeprom_update_dword(uint32_t *addr, uint32_t value) {
eeprom_write_dword(addr, value);
}
}
+
+void eeprom_driver_format(bool erase) __attribute__((weak));
+void eeprom_driver_format(bool erase) {
+ (void)erase; /* The default implementation assumes that the eeprom must be erased in order to be usable. */
+ eeprom_driver_erase();
+}
diff --git a/drivers/eeprom/eeprom_driver.h b/drivers/eeprom/eeprom_driver.h
index 74592bc8f0..0c55c497d4 100644
--- a/drivers/eeprom/eeprom_driver.h
+++ b/drivers/eeprom/eeprom_driver.h
@@ -16,7 +16,9 @@
#pragma once
+#include <stdbool.h>
#include "eeprom.h"
void eeprom_driver_init(void);
+void eeprom_driver_format(bool erase);
void eeprom_driver_erase(void);
diff --git a/drivers/eeprom/eeprom_i2c.c b/drivers/eeprom/eeprom_i2c.c
index 0d3d5ccbe5..d29aff5f85 100644
--- a/drivers/eeprom/eeprom_i2c.c
+++ b/drivers/eeprom/eeprom_i2c.c
@@ -36,6 +36,7 @@
#include "wait.h"
#include "i2c_master.h"
#include "eeprom.h"
+#include "eeprom_driver.h"
#include "eeprom_i2c.h"
// #define DEBUG_EEPROM_OUTPUT
@@ -62,6 +63,13 @@ void eeprom_driver_init(void) {
#endif
}
+void eeprom_driver_format(bool erase) {
+ /* i2c eeproms do not need to be formatted before use */
+ if (erase) {
+ eeprom_driver_erase();
+ }
+}
+
void eeprom_driver_erase(void) {
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
uint32_t start = timer_read32();
diff --git a/drivers/eeprom/eeprom_spi.c b/drivers/eeprom/eeprom_spi.c
index 51ba25dece..14f0afa68b 100644
--- a/drivers/eeprom/eeprom_spi.c
+++ b/drivers/eeprom/eeprom_spi.c
@@ -35,6 +35,7 @@
#include "timer.h"
#include "spi_master.h"
#include "eeprom.h"
+#include "eeprom_driver.h"
#include "eeprom_spi.h"
#define CMD_WREN 6
@@ -92,6 +93,13 @@ void eeprom_driver_init(void) {
spi_init();
}
+void eeprom_driver_format(bool erase) {
+ /* spi eeproms do not need to be formatted before use */
+ if (erase) {
+ eeprom_driver_erase();
+ }
+}
+
void eeprom_driver_erase(void) {
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
uint32_t start = timer_read32();
diff --git a/drivers/eeprom/eeprom_transient.c b/drivers/eeprom/eeprom_transient.c
index 9dc4289c27..d9f5db9853 100644
--- a/drivers/eeprom/eeprom_transient.c
+++ b/drivers/eeprom/eeprom_transient.c
@@ -30,8 +30,13 @@ size_t clamp_length(intptr_t offset, size_t len) {
return len;
}
-void eeprom_driver_init(void) {
- eeprom_driver_erase();
+void eeprom_driver_init(void) {}
+
+void eeprom_driver_format(bool erase) {
+ /* The transient eeprom driver doesn't necessarily need to be formatted before use, and it always starts up filled with zeros, due to placement in the .bss section */
+ if (erase) {
+ eeprom_driver_erase();
+ }
}
void eeprom_driver_erase(void) {
diff --git a/drivers/eeprom/eeprom_wear_leveling.c b/drivers/eeprom/eeprom_wear_leveling.c
index bd77eef35c..24ca6c3c6b 100644
--- a/drivers/eeprom/eeprom_wear_leveling.c
+++ b/drivers/eeprom/eeprom_wear_leveling.c
@@ -10,6 +10,12 @@ void eeprom_driver_init(void) {
wear_leveling_init();
}
+void eeprom_driver_format(bool erase) {
+ /* wear leveling requires the write log data structures to be erased before use. */
+ (void)erase;
+ eeprom_driver_erase();
+}
+
void eeprom_driver_erase(void) {
wear_leveling_erase();
}
diff --git a/drivers/encoder/encoder_quadrature.c b/drivers/encoder/encoder_quadrature.c
index cd589bf1e2..086f500391 100644
--- a/drivers/encoder/encoder_quadrature.c
+++ b/drivers/encoder/encoder_quadrature.c
@@ -22,7 +22,7 @@
#endif
#undef ENCODER_DEFAULT_PIN_API_IMPL
-#if defined(ENCODERS_PAD_A) && defined(ENCODERS_PAD_B)
+#if defined(ENCODER_A_PINS) && defined(ENCODER_B_PINS)
// Inform the quadrature driver that it needs to implement pin init/read functions
# define ENCODER_DEFAULT_PIN_API_IMPL
#endif
@@ -34,8 +34,8 @@ __attribute__((weak)) uint8_t encoder_quadrature_read_pin(uint8_t index, bool pa
#ifdef ENCODER_DEFAULT_PIN_API_IMPL
-static pin_t encoders_pad_a[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_A;
-static pin_t encoders_pad_b[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_B;
+static pin_t encoders_pad_a[NUM_ENCODERS_MAX_PER_SIDE] = ENCODER_A_PINS;
+static pin_t encoders_pad_b[NUM_ENCODERS_MAX_PER_SIDE] = ENCODER_B_PINS;
__attribute__((weak)) void encoder_wait_pullup_charge(void) {
wait_us(100);
@@ -123,25 +123,25 @@ void encoder_driver_init(void) {
// here, but it's the simplest solution.
memset(encoder_state, 0, sizeof(encoder_state));
memset(encoder_pulses, 0, sizeof(encoder_pulses));
- const pin_t encoders_pad_a_left[] = ENCODERS_PAD_A;
- const pin_t encoders_pad_b_left[] = ENCODERS_PAD_B;
+ const pin_t encoders_pad_a_left[] = ENCODER_A_PINS;
+ const pin_t encoders_pad_b_left[] = ENCODER_B_PINS;
for (uint8_t i = 0; i < thisCount; i++) {
encoders_pad_a[i] = encoders_pad_a_left[i];
encoders_pad_b[i] = encoders_pad_b_left[i];
}
#endif
-#if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT)
+#if defined(SPLIT_KEYBOARD) && defined(ENCODER_A_PINS_RIGHT) && defined(ENCODER_B_PINS_RIGHT)
// Re-initialise the pads if it's the right-hand side
if (!isLeftHand) {
- const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT;
- const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT;
+ const pin_t encoders_pad_a_right[] = ENCODER_A_PINS_RIGHT;
+ const pin_t encoders_pad_b_right[] = ENCODER_B_PINS_RIGHT;
for (uint8_t i = 0; i < thisCount; i++) {
encoders_pad_a[i] = encoders_pad_a_right[i];
encoders_pad_b[i] = encoders_pad_b_right[i];
}
}
-#endif // defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT)
+#endif // defined(SPLIT_KEYBOARD) && defined(ENCODER_A_PINS_RIGHT) && defined(ENCODER_B_PINS_RIGHT)
// Encoder resolutions is defined differently in config.h, so concatenate
#if defined(SPLIT_KEYBOARD) && defined(ENCODER_RESOLUTIONS)
diff --git a/drivers/flash/flash.h b/drivers/flash/flash.h
new file mode 100644
index 0000000000..4d62475139
--- /dev/null
+++ b/drivers/flash/flash.h
@@ -0,0 +1,126 @@
+// Copyright 2024 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+/**
+ * @brief The status of a flash operation.
+ */
+enum {
+ FLASH_STATUS_SUCCESS = 0, //< The operation completed successfully.
+ FLASH_STATUS_ERROR = -1, //< An error occurred during the operation.
+ FLASH_STATUS_TIMEOUT = -2, //< The operation timed out.
+ FLASH_STATUS_BAD_ADDRESS = -3, //< The address is out of bounds.
+ FLASH_STATUS_BUSY = -4, //< The flash is busy.
+};
+
+/**
+ * @brief The status of a flash operation.
+ */
+typedef int16_t flash_status_t;
+
+/**
+ * @brief Initializes the flash driver.
+ *
+ * This function initializes the flash driver and prepares it for use.
+ * It should be called before any other flash-related functions are used.
+ */
+void flash_init(void);
+
+/**
+ * @brief Checks if the flash is busy.
+ *
+ * This function checks if the flash is currently busy with an operation.
+ *
+ * @return FLASH_STATUS_SUCCESS if the flash is not busy, FLASH_STATUS_BUSY if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
+ */
+flash_status_t flash_is_busy(void);
+
+/**
+ * @brief Initiates a chip erase operation.
+ *
+ * This function does not wait for the flash to become ready.
+ *
+ * @return FLASH_STATUS_SUCCESS if the erase command was successfully sent, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
+ */
+flash_status_t flash_begin_erase_chip(void);
+
+/**
+ * @brief Waits for the chip erase operation to complete.
+ *
+ * This function waits for the chip erase operation to complete.
+ *
+ * @return FLASH_STATUS_SUCCESS if the chip erase operation completed successfully, FLASH_STATUS_TIMEOUT if the flash was still busy, or FLASH_STATUS_ERROR if an error occurred.
+ */
+flash_status_t flash_wait_erase_chip(void);
+
+/**
+ * @brief Erases the entire flash memory chip.
+ *
+ * This function initiates an erase operation to erase the entire flash memory chip.
+ * It waits for the operation to complete.
+ *
+ * @return FLASH_STATUS_SUCCESS if the erase was successfully executed, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
+ */
+flash_status_t flash_erase_chip(void);
+
+/**
+ * @brief Erases a block of flash memory.
+ *
+ * This function initiates an erase operation to erase a block of flash memory.
+ * It waits for the operation to complete.
+ *
+ * @param addr The address of the block to erase.
+ *
+ * @return FLASH_STATUS_SUCCESS if the erase was successfully executed, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
+ */
+flash_status_t flash_erase_block(uint32_t addr);
+
+/**
+ * @brief Erases a sector of flash memory.
+ *
+ * This function initiates an erase operation to erase a sector of flash memory.
+ * It waits for the operation to complete.
+ *
+ * @param addr The address of the sector to erase.
+ *
+ * @return FLASH_STATUS_SUCCESS if the erase was successfully executed, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
+ */
+flash_status_t flash_erase_sector(uint32_t addr);
+
+/**
+ * @brief Reads a range of flash memory.
+ *
+ * This function reads a range of flash memory into a buffer.
+ *
+ * @param addr The address of the range to read.
+ * @param buf A pointer to the buffer to read the range into.
+ * @param len The length of the range to read.
+ *
+ * @return FLASH_STATUS_SUCCESS if the range was successfully read, FLASH_STATUS_BAD_ADDRESS if the address is out of bounds, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
+ */
+flash_status_t flash_read_range(uint32_t addr, void *buf, size_t len);
+
+/**
+ * @brief Writes a range of flash memory.
+ *
+ * This function writes a range of flash memory from a buffer.
+ *
+ * @param addr The address of the range to write.
+ * @param buf A pointer to the buffer to write to the range.
+ * @param len The length of the range to write.
+ *
+ * @return FLASH_STATUS_SUCCESS if the range was successfully written, FLASH_STATUS_BAD_ADDRESS if the address is out of bounds, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
+ */
+flash_status_t flash_write_range(uint32_t addr, const void *buf, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/drivers/flash/flash_spi.c b/drivers/flash/flash_spi.c
index 0c0eb8a99e..7226773ff4 100644
--- a/drivers/flash/flash_spi.c
+++ b/drivers/flash/flash_spi.c
@@ -1,22 +1,10 @@
-/*
-Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd
-
-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/>.
-*/
+// Copyright 2021 Westberry Technology (ChangZhou) Corp., Ltd
+// Copyright 2024 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <string.h>
+#include "flash.h"
#include "util.h"
#include "wait.h"
#include "debug.h"
@@ -69,33 +57,43 @@ static bool spi_flash_start(void) {
return spi_start(EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN, EXTERNAL_FLASH_SPI_LSBFIRST, EXTERNAL_FLASH_SPI_MODE, EXTERNAL_FLASH_SPI_CLOCK_DIVISOR);
}
-static flash_status_t spi_flash_wait_while_busy(void) {
- uint32_t deadline = timer_read32() + EXTERNAL_FLASH_SPI_TIMEOUT;
+static flash_status_t spi_flash_wait_while_busy_multiplier(int multiplier) {
flash_status_t response = FLASH_STATUS_SUCCESS;
- uint8_t retval;
-
+ uint32_t deadline = timer_read32() + ((EXTERNAL_FLASH_SPI_TIMEOUT)*multiplier);
do {
- bool res = spi_flash_start();
- if (!res) {
- dprint("Failed to start SPI! [spi flash wait while busy]\n");
- return FLASH_STATUS_ERROR;
- }
-
- spi_write(FLASH_CMD_RDSR);
-
- retval = (uint8_t)spi_read();
-
- spi_stop();
-
if (timer_read32() >= deadline) {
response = FLASH_STATUS_TIMEOUT;
break;
}
- } while (retval & FLASH_FLAG_WIP);
+ response = flash_is_busy();
+ } while (response == FLASH_STATUS_BUSY);
return response;
}
+static flash_status_t spi_flash_wait_while_busy(void) {
+ return spi_flash_wait_while_busy_multiplier(1);
+}
+
+flash_status_t flash_is_busy(void) {
+ bool res = spi_flash_start();
+ if (!res) {
+ dprint("Failed to start SPI! [spi flash wait while busy]\n");
+ return FLASH_STATUS_ERROR;
+ }
+
+ spi_write(FLASH_CMD_RDSR);
+ spi_status_t status = spi_read();
+ spi_stop();
+
+ if (status < 0) {
+ return status;
+ }
+
+ uint8_t sr = (uint8_t)status;
+ return (sr & FLASH_FLAG_WIP) ? FLASH_STATUS_BUSY : FLASH_STATUS_SUCCESS;
+}
+
static flash_status_t spi_flash_write_enable(void) {
bool res = spi_flash_start();
if (!res) {
@@ -104,7 +102,6 @@ static flash_status_t spi_flash_write_enable(void) {
}
spi_write(FLASH_CMD_WREN);
-
spi_stop();
return FLASH_STATUS_SUCCESS;
@@ -118,7 +115,6 @@ static flash_status_t spi_flash_write_disable(void) {
}
spi_write(FLASH_CMD_WRDI);
-
spi_stop();
return FLASH_STATUS_SUCCESS;
@@ -166,7 +162,7 @@ void flash_init(void) {
spi_init();
}
-flash_status_t flash_erase_chip(void) {
+flash_status_t flash_begin_erase_chip(void) {
flash_status_t response = FLASH_STATUS_SUCCESS;
/* Wait for the write-in-progress bit to be cleared. */
@@ -191,17 +187,28 @@ flash_status_t flash_erase_chip(void) {
}
spi_write(FLASH_CMD_CE);
spi_stop();
+ return FLASH_STATUS_SUCCESS;
+}
- /* Wait for the write-in-progress bit to be cleared.*/
- response = spi_flash_wait_while_busy();
+flash_status_t flash_wait_erase_chip(void) {
+ flash_status_t response = spi_flash_wait_while_busy_multiplier(250); // Chip erase can take a long time, wait 250x the usual timeout
if (response != FLASH_STATUS_SUCCESS) {
dprint("Failed to check WIP flag! [spi flash erase chip]\n");
return response;
}
-
return response;
}
+flash_status_t flash_erase_chip(void) {
+ flash_status_t response = flash_begin_erase_chip();
+ if (response != FLASH_STATUS_SUCCESS) {
+ dprint("Failed to begin erase chip! [spi flash erase chip]\n");
+ return response;
+ }
+
+ return flash_wait_erase_chip();
+}
+
flash_status_t flash_erase_sector(uint32_t addr) {
flash_status_t response = FLASH_STATUS_SUCCESS;
@@ -282,7 +289,7 @@ flash_status_t flash_erase_block(uint32_t addr) {
return response;
}
-flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len) {
+flash_status_t flash_read_range(uint32_t addr, void *buf, size_t len) {
flash_status_t response = FLASH_STATUS_SUCCESS;
uint8_t * read_buf = (uint8_t *)buf;
@@ -313,7 +320,7 @@ flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len) {
return response;
}
-flash_status_t flash_write_block(uint32_t addr, const void *buf, size_t len) {
+flash_status_t flash_write_range(uint32_t addr, const void *buf, size_t len) {
flash_status_t response = FLASH_STATUS_SUCCESS;
uint8_t * write_buf = (uint8_t *)buf;
diff --git a/drivers/flash/flash_spi.h b/drivers/flash/flash_spi.h
index 87460fc210..7a979daf0f 100644
--- a/drivers/flash/flash_spi.h
+++ b/drivers/flash/flash_spi.h
@@ -17,6 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
+#include "flash.h"
+
/* All the following default configurations are based on MX25L4006E Nor FLASH. */
/*
@@ -105,32 +107,3 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
The page count of the FLASH, calculated by total FLASH size and page size.
*/
#define EXTERNAL_FLASH_PAGE_COUNT ((EXTERNAL_FLASH_SIZE) / (EXTERNAL_FLASH_PAGE_SIZE))
-
-typedef int16_t flash_status_t;
-
-#define FLASH_STATUS_SUCCESS (0)
-#define FLASH_STATUS_ERROR (-1)
-#define FLASH_STATUS_TIMEOUT (-2)
-#define FLASH_STATUS_BAD_ADDRESS (-3)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-void flash_init(void);
-
-flash_status_t flash_erase_chip(void);
-
-flash_status_t flash_erase_block(uint32_t addr);
-
-flash_status_t flash_erase_sector(uint32_t addr);
-
-flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len);
-
-flash_status_t flash_write_block(uint32_t addr, const void *buf, size_t len);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/drivers/led/apa102.c b/drivers/led/apa102.c
index b171b07b12..0cf0ecb401 100644
--- a/drivers/led/apa102.c
+++ b/drivers/led/apa102.c
@@ -53,7 +53,8 @@
io_wait; \
} while (0)
-uint8_t apa102_led_brightness = APA102_DEFAULT_BRIGHTNESS;
+rgb_led_t apa102_leds[APA102_LED_COUNT];
+uint8_t apa102_led_brightness = APA102_DEFAULT_BRIGHTNESS;
static void apa102_send_byte(uint8_t byte) {
APA102_SEND_BIT(byte, 7);
@@ -121,14 +122,24 @@ void apa102_init(void) {
gpio_set_pin_output(APA102_CI_PIN);
}
-void apa102_setleds(rgb_led_t *start_led, uint16_t num_leds) {
- rgb_led_t *end = start_led + num_leds;
+void apa102_set_color(uint16_t index, uint8_t red, uint8_t green, uint8_t blue) {
+ apa102_leds[index].r = red;
+ apa102_leds[index].g = green;
+ apa102_leds[index].b = blue;
+}
+
+void apa102_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+ for (uint16_t i = 0; i < APA102_LED_COUNT; i++) {
+ apa102_set_color(i, red, green, blue);
+ }
+}
+void apa102_flush(void) {
apa102_start_frame();
- for (rgb_led_t *led = start_led; led < end; led++) {
- apa102_send_frame(led->r, led->g, led->b, apa102_led_brightness);
+ for (uint8_t i = 0; i < APA102_LED_COUNT; i++) {
+ apa102_send_frame(apa102_leds[i].r, apa102_leds[i].g, apa102_leds[i].b, apa102_led_brightness);
}
- apa102_end_frame(num_leds);
+ apa102_end_frame(APA102_LED_COUNT);
}
void apa102_set_brightness(uint8_t brightness) {
diff --git a/drivers/led/apa102.h b/drivers/led/apa102.h
index 5e2f78658b..42f1344f0c 100644
--- a/drivers/led/apa102.h
+++ b/drivers/led/apa102.h
@@ -32,17 +32,8 @@
#define APA102_MAX_BRIGHTNESS 31
void apa102_init(void);
-
-/* User Interface
- *
- * Input:
- * start_led: An array of GRB data describing the LED colors
- * num_leds: The number of LEDs to write
- *
- * The functions will perform the following actions:
- * - Set the data-out pin as output
- * - Send out the LED data
- */
-void apa102_setleds(rgb_led_t *start_led, uint16_t num_leds);
+void apa102_set_color(uint16_t index, uint8_t red, uint8_t green, uint8_t blue);
+void apa102_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
+void apa102_flush(void);
void apa102_set_brightness(uint8_t brightness);
diff --git a/drivers/painter/gc9a01/qp_gc9a01_opcodes.h b/drivers/painter/gc9a01/qp_gc9a01_opcodes.h
deleted file mode 100644
index 828e42752b..0000000000
--- a/drivers/painter/gc9a01/qp_gc9a01_opcodes.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2021 Paul Cotter (@gr1mr3aver)
-// SPDX-License-Identifier: GPL-2.0-or-later
-#pragma once
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Quantum Painter GC9A01 command opcodes
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Level 1 command opcodes
-
-#define GC9A01_GET_ID_INFO 0x04 // Get ID information
-#define GC9A01_GET_STATUS 0x09 // Get status
-#define GC9A01_CMD_SLEEP_ON 0x10 // Enter sleep mode
-#define GC9A01_CMD_SLEEP_OFF 0x11 // Exit sleep mode
-#define GC9A01_CMD_PARTIAL_ON 0x12 // Enter partial mode
-#define GC9A01_CMD_PARTIAL_OFF 0x13 // Exit partial mode
-#define GC9A01_CMD_INVERT_ON 0x20 // Enter inverted mode
-#define GC9A01_CMD_INVERT_OFF 0x21 // Exit inverted mode
-#define GC9A01_CMD_DISPLAY_OFF 0x28 // Disable display
-#define GC9A01_CMD_DISPLAY_ON 0x29 // Enable display
-#define GC9A01_SET_COL_ADDR 0x2A // Set column address
-#define GC9A01_SET_PAGE_ADDR 0x2B // Set page address
-#define GC9A01_SET_MEM 0x2C // Set memory
-#define GC9A01_SET_PARTIAL_AREA 0x30 // Set partial area
-#define GC9A01_SET_VSCROLL 0x33 // Set vertical scroll def
-#define GC9A01_CMD_TEARING_ON 0x34 // Tearing line enabled
-#define GC9A01_CMD_TEARING_OFF 0x35 // Tearing line disabled
-#define GC9A01_SET_MEM_ACS_CTL 0x36 // Set mem access ctl
-#define GC9A01_SET_VSCROLL_ADDR 0x37 // Set vscroll start addr
-#define GC9A01_CMD_IDLE_OFF 0x38 // Exit idle mode
-#define GC9A01_CMD_IDLE_ON 0x39 // Enter idle mode
-#define GC9A01_SET_PIX_FMT 0x3A // Set pixel format
-#define GC9A01_SET_MEM_CONT 0x3C // Set memory continue
-#define GC9A01_SET_TEAR_SCANLINE 0x44 // Set tearing scanline
-#define GC9A01_GET_TEAR_SCANLINE 0x45 // Get tearing scanline
-#define GC9A01_SET_BRIGHTNESS 0x51 // Set brightness
-#define GC9A01_SET_DISPLAY_CTL 0x53 // Set display ctl
-#define GC9A01_GET_ID1 0xDA // Get ID1
-#define GC9A01_GET_ID2 0xDB // Get ID2
-#define GC9A01_GET_ID3 0xDC // Get ID3
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Level 2 command opcodes
-
-#define GC9A01_SET_RGB_IF_SIG_CTL 0xB0 // RGB IF signal ctl
-#define GC9A01_SET_BLANKING_PORCH_CTL 0xB5 // Set blanking porch ctl
-#define GC9A01_SET_FUNCTION_CTL 0xB6 // Set function ctl
-#define GC9A01_SET_TEARING_EFFECT 0xBA // Set backlight ctl 3
-#define GC9A01_SET_IF_CTL 0xF6 // Set interface control
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Level 3 command opcodes
-
-#define GC9A01_SET_FRAME_RATE 0xE8 // Set frame rate
-#define GC9A01_SET_SPI_2DATA 0xE9 // Set frame rate
-#define GC9A01_SET_POWER_CTL_1 0xC1 // Set power ctl 1
-#define GC9A01_SET_POWER_CTL_2 0xC3 // Set power ctl 2
-#define GC9A01_SET_POWER_CTL_3 0xC4 // Set power ctl 3
-#define GC9A01_SET_POWER_CTL_4 0xC9 // Set power ctl 4
-#define GC9A01_SET_POWER_CTL_7 0xA7 // Set power ctl 7
-#define GC9A01_SET_INTER_REG_ENABLE1 0xFE // Enable Inter Register 1
-#define GC9A01_SET_INTER_REG_ENABLE2 0xEF // Enable Inter Register 2
-#define GC9A01_SET_GAMMA1 0xF0 //
-#define GC9A01_SET_GAMMA2 0xF1
-#define GC9A01_SET_GAMMA3 0xF2
-#define GC9A01_SET_GAMMA4 0xF3
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// MADCTL Flags
-#define GC9A01_MADCTL_MY 0b10000000
-#define GC9A01_MADCTL_MX 0b01000000
-#define GC9A01_MADCTL_MV 0b00100000
-#define GC9A01_MADCTL_ML 0b00010000
-#define GC9A01_MADCTL_RGB 0b00000000
-#define GC9A01_MADCTL_BGR 0b00001000
-#define GC9A01_MADCTL_MH 0b00000100
diff --git a/drivers/painter/gc9xxx/qp_gc9107.c b/drivers/painter/gc9xxx/qp_gc9107.c
new file mode 100644
index 0000000000..108344da4f
--- /dev/null
+++ b/drivers/painter/gc9xxx/qp_gc9107.c
@@ -0,0 +1,114 @@
+// Copyright 2024 Fernando Birra
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include "qp_internal.h"
+#include "qp_comms.h"
+#include "qp_gc9107.h"
+#include "qp_gc9xxx_opcodes.h"
+#include "qp_gc9107_opcodes.h"
+#include "qp_tft_panel.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Driver storage
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+tft_panel_dc_reset_painter_device_t gc9107_drivers[GC9107_NUM_DEVICES] = {0};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Initialization
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+__attribute__((weak)) bool qp_gc9107_init(painter_device_t device, painter_rotation_t rotation) {
+ // A lot of these "unknown" opcodes are sourced from other OSS projects and are seemingly required for this display to function.
+ // clang-format off
+ const uint8_t gc9107_init_sequence[] = {
+ GC9XXX_SET_INTER_REG_ENABLE1, 5, 0,
+ GC9XXX_SET_INTER_REG_ENABLE2, 5, 0,
+ GC9107_SET_FUNCTION_CTL6, 0, 1, GC9107_ALLOW_SET_COMPLEMENT_RGB | 0x08 | GC9107_ALLOW_SET_FRAMERATE,
+ GC9107_SET_COMPLEMENT_RGB, 0, 1, GC9107_COMPLEMENT_WITH_LSB,
+ 0xAB, 0, 1, 0x0E,
+ GC9107_SET_FRAME_RATE, 0, 1, 0x19,
+ GC9XXX_SET_PIXEL_FORMAT, 0, 1, GC9107_PIXEL_FORMAT_16_BPP_IFPF,
+ GC9XXX_CMD_SLEEP_OFF, 120, 0,
+ GC9XXX_CMD_DISPLAY_ON, 20, 0
+ };
+
+ // clang-format on
+ qp_comms_bulk_command_sequence(device, gc9107_init_sequence, sizeof(gc9107_init_sequence));
+
+ // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
+ const uint8_t madctl[] = {
+ [QP_ROTATION_0] = GC9XXX_MADCTL_BGR,
+ [QP_ROTATION_90] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MV,
+ [QP_ROTATION_180] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MY,
+ [QP_ROTATION_270] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MV | GC9XXX_MADCTL_MY,
+ };
+ qp_comms_command_databyte(device, GC9XXX_SET_MEM_ACS_CTL, madctl[rotation]);
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Driver vtable
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const tft_panel_dc_reset_painter_driver_vtable_t gc9107_driver_vtable = {
+ .base =
+ {
+ .init = qp_gc9107_init,
+ .power = qp_tft_panel_power,
+ .clear = qp_tft_panel_clear,
+ .flush = qp_tft_panel_flush,
+ .pixdata = qp_tft_panel_pixdata,
+ .viewport = qp_tft_panel_viewport,
+ .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
+ .append_pixels = qp_tft_panel_append_pixels_rgb565,
+ .append_pixdata = qp_tft_panel_append_pixdata,
+ },
+ .num_window_bytes = 2,
+ .swap_window_coords = false,
+ .opcodes =
+ {
+ .display_on = GC9XXX_CMD_DISPLAY_ON,
+ .display_off = GC9XXX_CMD_DISPLAY_OFF,
+ .set_column_address = GC9XXX_SET_COL_ADDR,
+ .set_row_address = GC9XXX_SET_ROW_ADDR,
+ .enable_writes = GC9XXX_SET_MEM,
+ },
+};
+
+#ifdef QUANTUM_PAINTER_GC9107_SPI_ENABLE
+// Factory function for creating a handle to the GC9107 device
+painter_device_t qp_gc9107_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode) {
+ for (uint32_t i = 0; i < GC9107_NUM_DEVICES; ++i) {
+ tft_panel_dc_reset_painter_device_t *driver = &gc9107_drivers[i];
+ if (!driver->base.driver_vtable) {
+ driver->base.driver_vtable = (const painter_driver_vtable_t *)&gc9107_driver_vtable;
+ driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_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 = 2;
+ driver->base.offset_y = 1;
+
+ // SPI and other pin configuration
+ driver->base.comms_config = &driver->spi_dc_reset_config;
+ driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin;
+ driver->spi_dc_reset_config.spi_config.divisor = spi_divisor;
+ driver->spi_dc_reset_config.spi_config.lsb_first = false;
+ driver->spi_dc_reset_config.spi_config.mode = spi_mode;
+ driver->spi_dc_reset_config.dc_pin = dc_pin;
+ driver->spi_dc_reset_config.reset_pin = reset_pin;
+ driver->spi_dc_reset_config.command_params_uses_command_pin = false;
+
+ if (!qp_internal_register_device((painter_device_t)driver)) {
+ memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t));
+ return NULL;
+ }
+
+ return (painter_device_t)driver;
+ }
+ }
+ return NULL;
+}
+
+#endif // QUANTUM_PAINTER_GC9107_SPI_ENABLE
diff --git a/drivers/painter/gc9xxx/qp_gc9107.h b/drivers/painter/gc9xxx/qp_gc9107.h
new file mode 100644
index 0000000000..b0b08f7665
--- /dev/null
+++ b/drivers/painter/gc9xxx/qp_gc9107.h
@@ -0,0 +1,37 @@
+// Copyright 2024 Fernando Birra (@gr1mr3aver)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#include "gpio.h"
+#include "qp_internal.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter GC9107 configurables (add to your keyboard's config.h)
+
+#ifndef GC9107_NUM_DEVICES
+/**
+ * @def This controls the maximum number of GC9107 devices that Quantum Painter can communicate with at any one time.
+ * Increasing this number allows for multiple displays to be used.
+ */
+# define GC9107_NUM_DEVICES 1
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter GC9107 device factories
+
+#ifdef QUANTUM_PAINTER_GC9107_SPI_ENABLE
+/**
+ * Factory method for an GC9107 SPI LCD device.
+ *
+ * @param panel_width[in] the width of the display panel
+ * @param panel_height[in] the height of the display panel
+ * @param chip_select_pin[in] the GPIO pin used for SPI chip select
+ * @param dc_pin[in] the GPIO pin used for D/C control
+ * @param reset_pin[in] the GPIO pin used for RST
+ * @param spi_divisor[in] the SPI divisor to use when communicating with the display
+ * @param spi_mode[in] the SPI mode to use when communicating with the display
+ * @return the device handle used with all drawing routines in Quantum Painter
+ */
+painter_device_t qp_gc9107_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode);
+
+#endif // QUANTUM_PAINTER_GC9107_SPI_ENABLE
diff --git a/drivers/painter/gc9xxx/qp_gc9107_opcodes.h b/drivers/painter/gc9xxx/qp_gc9107_opcodes.h
new file mode 100644
index 0000000000..e9b308eb49
--- /dev/null
+++ b/drivers/painter/gc9xxx/qp_gc9107_opcodes.h
@@ -0,0 +1,135 @@
+// Copyright 2024 Fernando Birra
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter GC9107 command opcodes
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define GC9107_GET_POWER_MODE 0x0A // Get power mode
+#define GC9107_GET_MADCTL 0x0B // Get MADCTL
+#define GC9107_GET_PIXEL_FMT 0x0C // Get pixel format
+#define GC9107_GET_IMAGE_FMT 0x0D // Get image format
+#define GC9107_GET_SIGNAL_MODE 0x0E // Get signal mode
+#define GC9107_GET_DIAG_RESULT 0x0F // Get self-diagnostic results
+
+#define GC9107_SET_FRAME_RATE 0xA8 // Set frame rate
+#define GC9107_SET_COMPLEMENT_RGB 0xAC // Set complement Principle RGB
+#define GC9107_SET_BLANK_PORCH 0xAD // Set blank porch control, 0;front_porch[6:0],0;back_porch[6:0]
+#define GC9107_SET_FUNCTION_CTL1 0xB1 // Set access to AVDD_VCL_CLK and VGH_VGL_CLK commands
+#define GC9107_SET_FUNCTION_CTL2 0xB2 // Set access to VGH, VGH control commands
+#define GC9107_SET_FUNCTION_CTL3 0xB3 // Set access to Gamma control commands
+#define GC9107_SET_DISPLAY_INVERSION 0xB4 // Set Display Inversion control
+#define GC9107_SET_FUNCTION_CTL6 0xB6 // Set access to commands SET_FRAME_RATE, SET_COMPLEMENT_RGB and SET_BLANK_PORCH
+#define GC9107_SET_CUSTOM_ID_INFO 0xD3 // Set customized display id information
+#define GC9107_AVDD_VCL_CLK 0xE3 // AVDD_CLK
+#define GC9107_SET_VGH 0xE8 // Set VGH
+#define GC9107_SET_VGL 0xE9 // Set VGL
+#define GC9107_SET_VGH_VGL_CLK 0xEA // Set VGH and VGL clock divisors
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// GC9107 Parameter constants
+
+// Parameter values for
+// GC9107_SET_PIXEL_FORMAT
+#define GC9107_PIXEL_FORMAT_12_BPP_IFPF (0b001 << 0) // 12 bits per pixel
+#define GC9107_PIXEL_FORMAT_16_BPP_IFPF (0b101 << 0) // 16 bits per pixel
+#define GC9107_PIXEL_FORMAT_18_BPP_IFPB (0b110 << 0) // 18 bits per pixel
+
+// Parameter values for
+// GC9107_SET_COMPLEMENT_RGB
+#define GC9107_COMPLEMENT_WITH_0 0x00 // R0 <- B0 <- 0, except if data is FFh
+#define GC9107_COMPLEMENT_WITH_1 0x40 // R0 <- B0 <- 1, except if data is 00h
+#define GC9107_COMPLEMENT_WITH_MSB 0x80 // R0 <- R5, B0 <- B5
+#define GC9107_COMPLEMENT_WITH_LSB 0xC0 // R0 <- B0 <- G0
+// Parameter masks for
+// GC9107_SET_FUNCTION_CTL1
+#define GC9107_ALLOW_AVDD_VCL_CLK 0b00001000 // Allow AVDD_VCL_CLK command
+// Parameter masks for
+// GC9107_SET_FUNCTION_CTL2
+#define GC9107_ALLOW_SET_VGH 0b00000001 // Allow GC9107_SET_VGH
+#define GC9107_ALLOW_SET_VGL 0b00000010 // Allow GC9107_SET_VGL
+#define GC9107_ALLOW_SET_VGH_VGL_CLK 0b00000100 // Allow GC9107_SET_VGH_VGL_CLK
+// Parameter masks for
+// GC9107_SET_FUNCTION_CTL3
+#define GC9107_ALLOW_SET_GAMMA1 0b00000001 // Allow GC9107_SET_GAMMA1
+#define GC9107_ALLOW_SET_GAMMA2 0b00000010 // Allow GC9107_SET_GAMMA2
+// Parameter mask for
+// GC9107_SET_FUNCTION_CTL6
+#define GC9107_ALLOW_SET_FRAMERATE 0b000000001 // Allow GC9107_SET_FRAME_RATE
+#define GC9107_ALLOW_SET_COMPLEMENT_RGB 0b000010000 // Allow GC9107_SET_COMPLEMENT_RGB
+#define GC9107_ALLOW_SET_BLANK_PORCH 0b000100000 // Allow GFC9107_SET_BLANK_PORCH
+// Parameter values for
+// AVDD_CLK_AD part (Most significant nibble)
+#define GC9107_AVDD_CLK_AD_2T 0x00
+#define GC9107_AVDD_CLK_AD_3T 0x10
+#define GC9107_AVDD_CLK_AD_4T 0x20
+#define GC9107_AVDD_CLK_AD_5T 0x30
+#define GC9107_AVDD_CLK_AD_6T 0x40
+#define GC9107_AVDD_CLK_AD_7T 0x50
+#define GC9107_AVDD_CLK_AD_8T 0x60
+#define GC9107_AVDD_CLK_AD_9T 0x70
+// Parameter values for
+// VCL_CLK_AD part (Least significant nibble)
+#define GC9107_VCL_CLK_AD_2T 0x00
+#define GC9107_VCL_CLK_AD_3T 0x01
+#define GC9107_VCL_CLK_AD_4T 0x02
+#define GC9107_VCL_CLK_AD_5T 0x03
+#define GC9107_VCL_CLK_AD_6T 0x04
+#define GC9107_VCL_CLK_AD_7T 0x05
+#define GC9107_VCL_CLK_AD_8T 0x06
+#define GC9107_VCL_CLK_AD_9T 0x07
+// Parameter values for
+// GC9107_SET_VGH
+#define GC9107_VGH_P100 0x20 // +10 V
+#define GC9107_VGH_P110 0x21 // +11 V
+#define GC9107_VGH_P120 0x22 // +12 V
+#define GC9107_VGH_P130 0x23 // +13 V
+#define GC9107_VGH_P140 0x24 // +14 V
+#define GC9107_VGH_P150 0x25 // +15 V
+// Parameter values for
+// GC9107_SET_VGL
+#define VGL_N_075 0x40 // -7.5 V
+#define VGL_N_085 0x41 // -8.5 V
+#define VGL_N_095 0x42 // -9.5 V
+#define VGL_N_100 0x43 // -10.0 V
+#define VGL_N_105 0x44 // -10.5 V
+#define VGL_N_110 0x45 // -11.0 V
+#define VGL_N_120 0x46 // -12.0 V
+#define VGL_N_130 0x47 // -13.0 V
+// Parameter masks for
+// GC9107_SET_VGH_VGL_CLK (VGH Divisor)
+#define GC9107_VGH_CLK_DIV_2 0x00 // Clock divisor = 2 -> 6.0 Mhz
+#define GC9107_VGH_CLK_DIV_3 0x10 // Clock divisor = 3 -> 4.0 Mhz
+#define GC9107_VGH_CLK_DIV_4 0x20 // Clock divisor = 4 -> 3.0 Mhz
+#define GC9107_VGH_CLK_DIV_5 0x30 // Clock divisor = 5 -> 2.4 Mhz
+#define GC9107_VGH_CLK_DIV_6 0x40 // Clock divisor = 6 -> 2.0 Mhz
+#define GC9107_VGH_CLK_DIV_7 0x50 // Clock divisor = 7 -> 1.7 Mhz
+#define GC9107_VGH_CLK_DIV_8 0x60 // Clock divisor = 8 -> 1.5 Mhz
+#define GC9107_VGH_CLK_DIV_9 0x70 // Clock divisor = 9 -> 1.3 Mhz
+#define GC9107_VGH_CLK_DIV_10 0x80 // Clock divisor = 10 -> 1.2 Mhz
+#define GC9107_VGH_CLK_DIV_12 0x90 // Clock divisor = 12 -> 1.0 Mhz
+#define GC9107_VGH_CLK_DIV_15 0xA0 // Clock divisor = 15 -> 0.8 Mhz
+#define GC9107_VGH_CLK_DIV_20 0xB0 // Clock divisor = 20 -> 0.6 Mhz
+#define GC9107_VGH_CLK_DIV_24 0xC0 // Clock divisor = 24 -> 0.5 Mhz
+#define GC9107_VGH_CLK_DIV_30 0xD0 // Clock divisor = 30 -> 0.4 Mhz
+#define GC9107_VGH_CLK_DIV_40 0xE0 // Clock divisor = 40 -> 0.3 Mhz
+#define GC9107_VGH_CLK_DIV_60 0xE0 // Clock divisor = 40 -> 0.2 Mhz
+// Parameter masks for
+// GC9107_SET_VGH_VGL_CLK (VGL Divisor)
+#define GC9107_VGL_CLK_DIV_2 0x00 // Clock divisor = 2 -> 6.0 Mhz
+#define GC9107_VGL_CLK_DIV_3 0x01 // Clock divisor = 3 -> 4.0 Mhz
+#define GC9107_VGL_CLK_DIV_4 0x02 // Clock divisor = 4 -> 3.0 Mhz
+#define GC9107_VGL_CLK_DIV_5 0x03 // Clock divisor = 5 -> 2.4 Mhz
+#define GC9107_VGL_CLK_DIV_6 0x04 // Clock divisor = 6 -> 2.0 Mhz
+#define GC9107_VGL_CLK_DIV_7 0x05 // Clock divisor = 7 -> 1.7 Mhz
+#define GC9107_VGL_CLK_DIV_8 0x06 // Clock divisor = 8 -> 1.5 Mhz
+#define GC9107_VGL_CLK_DIV_9 0x07 // Clock divisor = 9 -> 1.3 Mhz
+#define GC9107_VGL_CLK_DIV_10 0x08 // Clock divisor = 10 -> 1.2 Mhz
+#define GC9107_VGL_CLK_DIV_12 0x09 // Clock divisor = 12 -> 1.0 Mhz
+#define GC9107_VGL_CLK_DIV_15 0x0A // Clock divisor = 15 -> 0.8 Mhz
+#define GC9107_VGL_CLK_DIV_20 0x0B // Clock divisor = 20 -> 0.6 Mhz
+#define GC9107_VGL_CLK_DIV_24 0x0C // Clock divisor = 24 -> 0.5 Mhz
+#define GC9107_VGL_CLK_DIV_30 0x0D // Clock divisor = 30 -> 0.4 Mhz
+#define GC9107_VGL_CLK_DIV_40 0x0E // Clock divisor = 40 -> 0.3 Mhz
+#define GC9107_VGL_CLK_DIV_60 0x0E // Clock divisor = 40 -> 0.2 Mhz
diff --git a/drivers/painter/gc9a01/qp_gc9a01.c b/drivers/painter/gc9xxx/qp_gc9a01.c
index fe6fa7a9d0..f037a4cc87 100644
--- a/drivers/painter/gc9a01/qp_gc9a01.c
+++ b/drivers/painter/gc9xxx/qp_gc9a01.c
@@ -5,6 +5,7 @@
#include "qp_internal.h"
#include "qp_comms.h"
#include "qp_gc9a01.h"
+#include "qp_gc9xxx_opcodes.h"
#include "qp_gc9a01_opcodes.h"
#include "qp_tft_panel.h"
@@ -20,71 +21,40 @@ tft_panel_dc_reset_painter_device_t gc9a01_drivers[GC9A01_NUM_DEVICES] = {0};
__attribute__((weak)) bool qp_gc9a01_init(painter_device_t device, painter_rotation_t rotation) {
// A lot of these "unknown" opcodes are sourced from other OSS projects and are seemingly required for this display to function.
// clang-format off
+
const uint8_t gc9a01_init_sequence[] = {
// Command, Delay, N, Data[N]
- GC9A01_SET_INTER_REG_ENABLE2, 0, 0,
- 0xEB, 0, 1, 0x14,
- GC9A01_SET_INTER_REG_ENABLE1, 0, 0,
- GC9A01_SET_INTER_REG_ENABLE2, 0, 0,
- 0xEB, 0, 1, 0x14,
+ GC9XXX_SET_INTER_REG_ENABLE1, 0, 0,
+ GC9XXX_SET_INTER_REG_ENABLE2, 0, 0,
0x84, 0, 1, 0x40,
- 0x85, 0, 1, 0xFF,
- 0x86, 0, 1, 0xFF,
- 0x87, 0, 1, 0xFF,
- 0x88, 0, 1, 0x0A,
- 0x89, 0, 1, 0x21,
- 0x8a, 0, 1, 0x00,
- 0x8b, 0, 1, 0x80,
- 0x8c, 0, 1, 0x01,
- 0x8d, 0, 1, 0x01,
- 0x8e, 0, 1, 0xFF,
- 0x8f, 0, 1, 0xFF,
- GC9A01_SET_FUNCTION_CTL, 0, 2, 0x00, 0x20,
- GC9A01_SET_PIX_FMT, 0, 1, 0x55,
- 0x90, 0, 4, 0x08, 0x08, 0x08, 0x08,
- 0xBD, 0, 1, 0x06,
- 0xBC, 0, 1, 0x00,
- 0xFF, 0, 3, 0x60, 0x01, 0x04,
- GC9A01_SET_POWER_CTL_2, 0, 1, 0x13,
- GC9A01_SET_POWER_CTL_3, 0, 1, 0x13,
+ GC9A01_SET_FUNCTION_CTL, 0, 3, 0x00, GC9A01_SOURCE_OUTPUT_SCAN_DIRECTION_S360_TO_S1 | GC9A01_GATE_OUTPUT_SCAN_DIRECTION_G1_TO_G32, GC9A01_LCD_DRIVE_LINE_240, // Only works if the previous command is present (undocumented)
+ GC9A01_SET_POWER_CTL_2, 0, 1, 0x20,
+ GC9A01_SET_POWER_CTL_3, 0, 1, 0x20,
GC9A01_SET_POWER_CTL_4, 0, 1, 0x22,
- 0xBE, 0, 1, 0x11,
- 0xE1, 0, 2, 0x10, 0x0E,
- 0xDF, 0, 3, 0x21, 0x0C, 0x02,
- GC9A01_SET_GAMMA1, 0, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A,
- GC9A01_SET_GAMMA2, 0, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F,
+ GC9XXX_SET_GAMMA1, 0, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A,
+ GC9XXX_SET_GAMMA2, 0, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F,
GC9A01_SET_GAMMA3, 0, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A,
GC9A01_SET_GAMMA4, 0, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F,
- 0xED, 0, 2, 0x1B, 0x0B,
- 0xAE, 0, 1, 0x77,
- 0xCD, 0, 1, 0x63,
- 0x70, 0, 9, 0x07, 0x07, 0x04, 0x0E, 0x0F, 0x09, 0x07, 0x08, 0x03,
- GC9A01_SET_FRAME_RATE, 0, 1, 0x34,
- 0x62, 0, 12, 0x18, 0x0D, 0x71, 0xED, 0x70, 0x70, 0x18, 0x0F, 0x71, 0xEF, 0x70, 0x70,
- 0x63, 0, 12, 0x18, 0x11, 0x71, 0xF1, 0x70, 0x70, 0x18, 0x13, 0x71, 0xF3, 0x70, 0x70,
- 0x64, 0, 7, 0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07,
0x66, 0, 10, 0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0x00, 0x00, 0x00,
0x67, 0, 10, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0x10, 0x32, 0x98,
- 0x74, 0, 7, 0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00,
- 0x98, 0, 2, 0x3E, 0x07,
- GC9A01_CMD_TEARING_OFF, 0, 0,
- GC9A01_CMD_INVERT_OFF, 0, 0,
- GC9A01_CMD_SLEEP_OFF, 120, 0,
- GC9A01_CMD_DISPLAY_ON, 20, 0
+ GC9XXX_CMD_TEARING_ON, 0, 0,
+ GC9XXX_SET_PIXEL_FORMAT, 0, 1, GC9A01_PIXEL_FORMAT_16_BPP_DBI,
+ GC9XXX_CMD_INVERT_ON, 0, 0,
+ GC9XXX_CMD_SLEEP_OFF, 120, 0,
+ GC9XXX_CMD_DISPLAY_ON, 20, 0
};
// clang-format on
- // clang-format on
qp_comms_bulk_command_sequence(device, gc9a01_init_sequence, sizeof(gc9a01_init_sequence));
// Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
const uint8_t madctl[] = {
- [QP_ROTATION_0] = GC9A01_MADCTL_BGR,
- [QP_ROTATION_90] = GC9A01_MADCTL_BGR | GC9A01_MADCTL_MX | GC9A01_MADCTL_MV,
- [QP_ROTATION_180] = GC9A01_MADCTL_BGR | GC9A01_MADCTL_MX | GC9A01_MADCTL_MY,
- [QP_ROTATION_270] = GC9A01_MADCTL_BGR | GC9A01_MADCTL_MV | GC9A01_MADCTL_MY,
+ [QP_ROTATION_0] = GC9XXX_MADCTL_BGR,
+ [QP_ROTATION_90] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MV,
+ [QP_ROTATION_180] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MY,
+ [QP_ROTATION_270] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MV | GC9XXX_MADCTL_MY,
};
- qp_comms_command_databyte(device, GC9A01_SET_MEM_ACS_CTL, madctl[rotation]);
+ qp_comms_command_databyte(device, GC9XXX_SET_MEM_ACS_CTL, madctl[rotation]);
return true;
}
@@ -110,11 +80,11 @@ const tft_panel_dc_reset_painter_driver_vtable_t gc9a01_driver_vtable = {
.swap_window_coords = false,
.opcodes =
{
- .display_on = GC9A01_CMD_DISPLAY_ON,
- .display_off = GC9A01_CMD_DISPLAY_OFF,
- .set_column_address = GC9A01_SET_COL_ADDR,
- .set_row_address = GC9A01_SET_PAGE_ADDR,
- .enable_writes = GC9A01_SET_MEM,
+ .display_on = GC9XXX_CMD_DISPLAY_ON,
+ .display_off = GC9XXX_CMD_DISPLAY_OFF,
+ .set_column_address = GC9XXX_SET_COL_ADDR,
+ .set_row_address = GC9XXX_SET_ROW_ADDR,
+ .enable_writes = GC9XXX_SET_MEM,
},
};
diff --git a/drivers/painter/gc9a01/qp_gc9a01.h b/drivers/painter/gc9xxx/qp_gc9a01.h
index 31a3804b50..31a3804b50 100644
--- a/drivers/painter/gc9a01/qp_gc9a01.h
+++ b/drivers/painter/gc9xxx/qp_gc9a01.h
diff --git a/drivers/painter/gc9xxx/qp_gc9a01_opcodes.h b/drivers/painter/gc9xxx/qp_gc9a01_opcodes.h
new file mode 100644
index 0000000000..5853902e68
--- /dev/null
+++ b/drivers/painter/gc9xxx/qp_gc9a01_opcodes.h
@@ -0,0 +1,104 @@
+// Copyright 2021 Paul Cotter (@gr1mr3aver)
+// Copyright 2024 Fernando Birra
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter GC9A01 command opcodes
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define GC9A01_SET_MEM_CONT 0x3C // Set memory continue
+#define GC9A01_SET_BRIGHTNESS 0x51 // Set brightness
+#define GC9A01_SET_DISPLAY_CTL 0x53 // Set display ctl
+
+#define GC9A01_SET_RGB_IF_SIG_CTL 0xB0 // RGB IF signal ctl
+#define GC9A01_SET_BLANKING_PORCH_CTL 0xB5 // Set blanking porch ctl
+#define GC9A01_SET_FUNCTION_CTL 0xB6 // Set function ctl
+#define GC9A01_SET_TEARING_EFFECT 0xBA // Set tering effect control
+#define GC9A01_SET_POWER_CTL_7 0xA7 // Set power ctl 7
+#define GC9A01_SET_POWER_CTL_1 0xC1 // Set power ctl 1
+#define GC9A01_SET_POWER_CTL_2 0xC3 // Set power ctl 2
+#define GC9A01_SET_POWER_CTL_3 0xC4 // Set power ctl 3
+#define GC9A01_SET_POWER_CTL_4 0xC9 // Set power ctl 4
+#define GC9A01_SET_FRAME_RATE 0xE8 // Set frame rate
+#define GC9A01_SET_SPI_2DATA 0xE9 // Set frame rate
+#define GC9A01_SET_GAMMA3 0xF2 // Set gamma 3
+#define GC9A01_SET_GAMMA4 0xF3 // Set gamma 4
+#define GC9A01_SET_IF_CTL 0xF6 // Set interface control
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// GC9A01 MADCTL Flags
+#define GC9A01_MADCTL_MH 0b00000100
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// GC9A01 Parameter constants
+
+// Parameter values for
+// GC9A01_SET_PIXEL_FORMAT
+#define GC9A01_PIXEL_FORMAT_12_BPP_DBI (0b011 << 0) // 12 bits/pixel MCU interface format
+#define GC9A01_PIXEL_FORMAT_16_BPP_DBI (0b101 << 0) // 16 bits/pixel MCU interface format
+#define GC9A01_PIXEL_FORMAT_18_BPP_DBI (0b110 << 0) // 18 bits/pixel MCU interface format
+#define GC9A01_PIXEL_FORMAT_16_BPP_DPI (0b101 << 4) // 16 bits/pixel RGB interface format
+#define GC9A01_PIXEL_FORMAT_18_BPP_DPI (0b110 << 4) // 18 bits/pixel RGB interface format
+
+// Parameter values for
+// GC9A01_SET_FUNCTION_CTL (2nd parameter)
+#define GC9A01_SOURCE_OUTPUT_SCAN_DIRECTION_S1_TO_S360 0b00000000
+#define GC9A01_SOURCE_OUTPUT_SCAN_DIRECTION_S360_TO_S1 0b00100000
+#define GC9A01_GATE_OUTPUT_SCAN_DIRECTION_G1_TO_G32 0b00000000
+#define GC9A01_GATE_OUTPUT_SCAN_DIRECTION_G32_TO_G1 0b01000000
+#define GC9A01_SCAN_MODE_INTER 0x10
+
+// Parameter values for
+// GC9A01_SET_FUNCTION_CTL (3rd parameter)
+#define GC9A01_LCD_DRIVE_LINE_16 0x01
+#define GC9A01_LCD_DRIVE_LINE_24 0x02
+#define GC9A01_LCD_DRIVE_LINE_32 0x03
+#define GC9A01_LCD_DRIVE_LINE_40 0x04
+#define GC9A01_LCD_DRIVE_LINE_48 0x05
+#define GC9A01_LCD_DRIVE_LINE_56 0x06
+#define GC9A01_LCD_DRIVE_LINE_64 0x07
+#define GC9A01_LCD_DRIVE_LINE_72 0x08
+#define GC9A01_LCD_DRIVE_LINE_80 0x09
+#define GC9A01_LCD_DRIVE_LINE_88 0x0A
+#define GC9A01_LCD_DRIVE_LINE_96 0x0B
+#define GC9A01_LCD_DRIVE_LINE_104 0x0C
+#define GC9A01_LCD_DRIVE_LINE_112 0x0D
+#define GC9A01_LCD_DRIVE_LINE_120 0x0E
+#define GC9A01_LCD_DRIVE_LINE_128 0x0F
+#define GC9A01_LCD_DRIVE_LINE_136 0x10
+#define GC9A01_LCD_DRIVE_LINE_144 0x11
+#define GC9A01_LCD_DRIVE_LINE_152 0x12
+#define GC9A01_LCD_DRIVE_LINE_160 0x13
+#define GC9A01_LCD_DRIVE_LINE_168 0x14
+#define GC9A01_LCD_DRIVE_LINE_176 0x15
+#define GC9A01_LCD_DRIVE_LINE_184 0x16
+#define GC9A01_LCD_DRIVE_LINE_192 0x17
+#define GC9A01_LCD_DRIVE_LINE_200 0x18
+#define GC9A01_LCD_DRIVE_LINE_208 0x19
+#define GC9A01_LCD_DRIVE_LINE_216 0x1A
+#define GC9A01_LCD_DRIVE_LINE_224 0x1B
+#define GC9A01_LCD_DRIVE_LINE_232 0x1C
+#define GC9A01_LCD_DRIVE_LINE_240 0x1D
+
+// Parameter values for
+// GC9A01_SET_DISPLAY_CTL
+#define GC9A01_BRIGHTNESS_CONTROL_ON 0b00100000
+#define GC9A01_DIMMING_ON 0b00001000
+#define GC9A01_BACKLIGHT_ON 0b00000100
+#define GC9A01_BRIGHTNESS_CONTROL_OFF 0b00000000
+#define GC9A01_DIMMING_OFF 0b00000000
+#define GC9A01_BACKLIGHT_OFF 0b00000000
+
+// Parameter values for
+// GC9A01_SET_IF_CTL
+#define GC9A01_DISPLAY_MODE_INTERNAL_CLOCK 0b00000000
+#define GC9A01_DISPLAY_MODE_RGB_INTERFACE 0b00000100
+#define GC9A01_DISPLAY_MODE_VSYNC_INTERFACE 0b00001000
+#define GC9A01_DSISPLAY_MODE_DISABLED 0b00001100
+
+#define GC0A01_GRAM_INTERFACE_VSYNC 0b00000000
+#define GC9A01_GRAM_INTERFACE_RGB 0b00000010
+
+#define GC9A01_RGB_INTERFACE_MODE_1_TRANSFER 0b00000000
+#define GC9A01_RGB_INTERFACE_MODE_3_TRANSFER 0b00000001 \ No newline at end of file
diff --git a/drivers/painter/gc9xxx/qp_gc9xxx_opcodes.h b/drivers/painter/gc9xxx/qp_gc9xxx_opcodes.h
new file mode 100644
index 0000000000..7e0fbf9110
--- /dev/null
+++ b/drivers/painter/gc9xxx/qp_gc9xxx_opcodes.h
@@ -0,0 +1,55 @@
+// Copyright 2021 Paul Cotter (@gr1mr3aver)
+// Copyright 2024 Fernando Birra
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter GC9xxx command opcodes
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define GC9XXX_GET_ID_INFO 0x04 // Get ID information
+#define GC9XXX_GET_STATUS 0x09 // Get status
+
+#define GC9XXX_CMD_SLEEP_ON 0x10 // Enter sleep mode
+#define GC9XXX_CMD_SLEEP_OFF 0x11 // Exit sleep mode
+#define GC9XXX_CMD_PARTIAL_ON 0x12 // Enter partial mode
+#define GC9XXX_CMD_PARTIAL_OFF 0x13 // Exit partial mode
+
+#define GC9XXX_CMD_INVERT_OFF 0x20 // Exit inverted mode
+#define GC9XXX_CMD_INVERT_ON 0x21 // Enter inverted mode
+#define GC9XXX_CMD_DISPLAY_OFF 0x28 // Disable display
+#define GC9XXX_CMD_DISPLAY_ON 0x29 // Enable display
+#define GC9XXX_SET_COL_ADDR 0x2A // Set column address (MSB(StartCol),LSB(StartCol),MSB(EndCol),LSB(EndCol)
+#define GC9XXX_SET_ROW_ADDR 0x2B // Set row address (MSB(StartRow),LSB(StartRow),MSB(EndRow),LSB(EndRow)
+#define GC9XXX_SET_MEM 0x2C // Set (write) memory
+
+#define GC9XXX_SET_PARTIAL_AREA 0x30 // Set partial area (MSB(StartRow),LSB(StartRow),MSB(EndRow),LSB(EndRow)
+#define GC9XXX_SET_VSCROLL 0x33 // Set vertical scroll MSB(TFA),LSB(TFA),MSB(VSA),LSB(VSA)+ GC9107 extra param: MSB(BFA),LSB(BFA)
+#define GC9XXX_CMD_TEARING_OFF 0x34 // Tearing effect line OFF
+#define GC9XXX_CMD_TEARING_ON 0x35 // Tearing effect line ON
+#define GC9XXX_SET_MEM_ACS_CTL 0x36 // Set mem access ctl
+#define GC9XXX_SET_VSCROLL_ADDR 0x37 // Set vscroll start addr
+#define GC9XXX_CMD_IDLE_OFF 0x38 // Exit idle mode
+#define GC9XXX_CMD_IDLE_ON 0x39 // Enter idle mode
+#define GC9XXX_SET_PIXEL_FORMAT 0x3A // Set pixel format
+#define GC9XXX_SET_TEAR_SCANLINE 0x44 // Set tearing scanline (Scanline = LS bit of Param 1 (GC9A01) + Param 2(GC9XXX))
+#define GC9XXX_GET_TEAR_SCANLINE 0x45 // Get tearing scanline (Scanline = LS bit of Param 1 (GC9A01) + Param 2(GC9XXX))
+#define GC9XXX_GET_ID1 0xDA // Get ID1
+#define GC9XXX_GET_ID2 0xDB // Get ID2
+#define GC9XXX_GET_ID3 0xDC // Get ID3
+#define GC9XXX_SET_INTER_REG_ENABLE1 0xFE // Enable Inter Register 1
+#define GC9XXX_SET_INTER_REG_ENABLE2 0xEF // Enable Inter Register 2
+#define GC9XXX_SET_GAMMA1 0xF0 // Set gamma 1
+#define GC9XXX_SET_GAMMA2 0xF1 // Set gamma 2
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// MADCTL Flags
+#define GC9XXX_MADCTL_MY 0b10000000 // Mirror Y (row address order)
+#define GC9XXX_MADCTL_MX 0b01000000 // Mirror X (column address order)
+#define GC9XXX_MADCTL_MV 0b00100000 // Vertical Refresh Order (bottom to top)
+#define GC9XXX_MADCTL_ML 0b00010000
+#define GC9XXX_MADCTL_BGR 0b00001000
+#define GC9XXX_MADCTL_RGB 0b00000000
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// GC9XXX Parameter constants
diff --git a/drivers/sensors/adns9800.c b/drivers/sensors/adns9800.c
index f34529ee90..0ba26a365a 100644
--- a/drivers/sensors/adns9800.c
+++ b/drivers/sensors/adns9800.c
@@ -115,6 +115,7 @@ void adns9800_init(void) {
adns9800_read(REG_Delta_Y_L);
adns9800_read(REG_Delta_Y_H);
+#ifdef ADNS9800_UPLOAD_SROM
// upload firmware
// 3k firmware mode
@@ -145,6 +146,16 @@ void adns9800_init(void) {
spi_stop();
wait_ms(10);
+#else
+ // write reset value to REG_Configuration_IV
+ adns9800_write(REG_Configuration_IV, 0x0);
+
+ // write reset value to REG_SROM_Enable
+ adns9800_write(REG_SROM_Enable, 0x0);
+
+ // wait a frame
+ wait_ms(10);
+#endif
// enable laser
uint8_t laser_ctrl0 = adns9800_read(REG_LASER_CTRL0);
diff --git a/drivers/sensors/cirque_pinnacle_gestures.h b/drivers/sensors/cirque_pinnacle_gestures.h
index d2aa206b2b..1412c86f7e 100644
--- a/drivers/sensors/cirque_pinnacle_gestures.h
+++ b/drivers/sensors/cirque_pinnacle_gestures.h
@@ -28,7 +28,7 @@ typedef struct {
# ifndef CIRQUE_PINNACLE_TAPPING_TERM
# include "action.h"
# include "action_tapping.h"
-# define CIRQUE_PINNACLE_TAPPING_TERM GET_TAPPING_TERM(KC_BTN1, &(keyrecord_t){})
+# define CIRQUE_PINNACLE_TAPPING_TERM GET_TAPPING_TERM(QK_MOUSE_BUTTON_1, &(keyrecord_t){})
# endif
# ifndef CIRQUE_PINNACLE_TOUCH_DEBOUNCE
# define CIRQUE_PINNACLE_TOUCH_DEBOUNCE (CIRQUE_PINNACLE_TAPPING_TERM * 8)
diff --git a/drivers/sensors/pmw33xx_common.c b/drivers/sensors/pmw33xx_common.c
index 82a7ec3297..f1f2d0e865 100644
--- a/drivers/sensors/pmw33xx_common.c
+++ b/drivers/sensors/pmw33xx_common.c
@@ -154,10 +154,12 @@ bool pmw33xx_init(uint8_t sensor) {
pmw33xx_read(sensor, REG_Delta_Y_L);
pmw33xx_read(sensor, REG_Delta_Y_H);
+#ifdef PMW33XX_UPLOAD_SROM
if (!pmw33xx_upload_firmware(sensor)) {
pd_dprintf("PMW33XX (%d): firmware upload failed!\n", sensor);
return false;
}
+#endif
spi_stop();
@@ -200,7 +202,7 @@ pmw33xx_report_t pmw33xx_read_burst(uint8_t sensor) {
spi_write(REG_Motion_Burst);
wait_us(35); // waits for tSRAD_MOTBR
- spi_receive((uint8_t*)&report, sizeof(report));
+ spi_receive((uint8_t *)&report, sizeof(report));
// panic recovery, sometimes burst mode works weird.
if (report.motion.w & 0b111) {
diff --git a/drivers/wear_leveling/wear_leveling_flash_spi.c b/drivers/wear_leveling/wear_leveling_flash_spi.c
index 6191f8bf09..304aed1641 100644
--- a/drivers/wear_leveling/wear_leveling_flash_spi.c
+++ b/drivers/wear_leveling/wear_leveling_flash_spi.c
@@ -58,7 +58,7 @@ bool backing_store_read(uint32_t address, backing_store_int_t *value) {
bool backing_store_read_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
bs_dprintf("Read ");
uint32_t offset = (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) * (EXTERNAL_FLASH_BLOCK_SIZE) + address;
- flash_status_t status = flash_read_block(offset, values, sizeof(backing_store_int_t) * item_count);
+ flash_status_t status = flash_read_range(offset, values, sizeof(backing_store_int_t) * item_count);
if (status == FLASH_STATUS_SUCCESS) {
for (size_t i = 0; i < item_count; ++i) {
values[i] = ~values[i];
@@ -88,7 +88,7 @@ bool backing_store_write_bulk(uint32_t address, backing_store_int_t *values, siz
}
// Write out the block
- if (flash_write_block(offset, temp, sizeof(backing_store_int_t) * this_loop) != FLASH_STATUS_SUCCESS) {
+ if (flash_write_range(offset, temp, sizeof(backing_store_int_t) * this_loop) != FLASH_STATUS_SUCCESS) {
return false;
}