aboutsummaryrefslogtreecommitdiff
path: root/modules/ls0xx/ls0xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ls0xx/ls0xx.c')
-rw-r--r--modules/ls0xx/ls0xx.c277
1 files changed, 0 insertions, 277 deletions
diff --git a/modules/ls0xx/ls0xx.c b/modules/ls0xx/ls0xx.c
deleted file mode 100644
index 01a02c6..0000000
--- a/modules/ls0xx/ls0xx.c
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright Pablo Martinez (@elpekenin) <[email protected]>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "ls0xx.h"
-
-#include "ls0xx_opcodes.h"
-#include "qp_comms_spi.h"
-#include "qp_surface_internal.h"
-#include "spi_master.h"
-
-typedef struct {
- painter_driver_t base; // must be first, so it can be cast to/from the
- // painter_device_t* type
- qp_comms_spi_config_t spi_config;
- surface_painter_device_t surface;
-} ls0xx_painter_device_t;
-
-// need custom comms vtable for inverted CS logic
-bool inverted_cs_init(painter_device_t device) {
- painter_driver_t *driver = (painter_driver_t *)device;
- qp_comms_spi_config_t *comms_config =
- (qp_comms_spi_config_t *)driver->comms_config;
-
- // Initialize the SPI peripheral
- spi_init();
-
- // Set up CS as output high
- gpio_set_pin_output(comms_config->chip_select_pin);
- gpio_write_pin_low(comms_config->chip_select_pin);
-
- return true;
-}
-
-bool inverted_cs_start(painter_device_t device) {
- painter_driver_t *driver = (painter_driver_t *)device;
- qp_comms_spi_config_t *comms_config =
- (qp_comms_spi_config_t *)driver->comms_config;
-
- spi_start_config_t config = (spi_start_config_t){
- .slave_pin = comms_config->chip_select_pin,
- .lsb_first = comms_config->lsb_first,
- .mode = comms_config->mode,
- .divisor = comms_config->divisor,
- .cs_active_low = false,
- };
-
- return spi_start_extended(&config);
-}
-
-const painter_comms_vtable_t spi_comms_inverted_cs_vtable = {
- .comms_init = inverted_cs_init,
- .comms_start = inverted_cs_start,
- .comms_send = qp_comms_spi_send_data,
- .comms_stop = qp_comms_spi_stop,
-};
-
-ls0xx_painter_device_t ls0xx_device_t_drivers[LS0XX_NUM_DEVICES] = {0};
-
-__attribute__((weak)) bool qp_ls0xx_init(painter_device_t device,
- painter_rotation_t rotation) {
- ls0xx_painter_device_t *ls0xx = (ls0xx_painter_device_t *)device;
- painter_driver_t *surface = (painter_driver_t *)&ls0xx->surface;
-
- // Change the surface geometry based on the panel rotation
- if (rotation == QP_ROTATION_90 || rotation == QP_ROTATION_270) {
- surface->panel_width = ls0xx->base.panel_height;
- surface->panel_height = ls0xx->base.panel_width;
- } else {
- surface->panel_width = ls0xx->base.panel_width;
- surface->panel_height = ls0xx->base.panel_height;
- }
-
- // Init the internal surface
- if (!surface->driver_vtable->init(surface, QP_ROTATION_0)) {
- qp_dprintf("Failed to init internal surface in qp_ls0xx_init\n");
- return false;
- }
-
- ls0xx->base.rotation = rotation;
-
- writePinHigh(ls0xx->spi_config.chip_select_pin);
- const uint8_t ls0xx_init_sequence[] = {LS0XX_CLEAR, 0};
- spi_transmit(ls0xx_init_sequence, ARRAY_SIZE(ls0xx_init_sequence));
- writePinLow(ls0xx->spi_config.chip_select_pin);
-
- return true;
-}
-
-bool qp_ls0xx_passthru_power(painter_device_t device, bool power_on) {
- // No-op
- return true;
-}
-
-bool qp_ls0xx_passthru_clear(painter_device_t device) {
- // Just re-init the display
- painter_driver_t *driver = (painter_driver_t *)device;
- return qp_ls0xx_init(device, driver->rotation);
-}
-
-bool qp_ls0xx_flush(painter_device_t device) {
- ls0xx_painter_device_t *ls0xx = (ls0xx_painter_device_t *)device;
- surface_painter_device_t *surface = &(ls0xx->surface);
- surface_dirty_data_t dirty = surface->dirty;
-
- if (!dirty.is_dirty) {
- // nothing to be sent
- return true;
- }
-
- // find out dirty area. update is done on **complete** horizontal lines,
- // which means that if device is sideways, we need to check l/r instead
- uint16_t top = 0;
- uint16_t bottom = 0;
- switch (ls0xx->base.rotation) {
- case QP_ROTATION_0:
- top = dirty.t;
- bottom = dirty.b;
- break;
-
- // TODO: Check whether this are backwards
- case QP_ROTATION_90:
- top = dirty.l;
- bottom = dirty.r;
- break;
-
- case QP_ROTATION_180:
- top = dirty.b;
- bottom = dirty.t;
- break;
-
- case QP_ROTATION_270:
- top = dirty.r;
- bottom = dirty.l;
- break;
- }
-
- // bytes sent for each row's data
- uint8_t bytes_per_line =
- (ls0xx->base.panel_width + 7) / 8 * ls0xx->base.native_bits_per_pixel;
- // offset used to access such data
- uint16_t buffer_offset = top * bytes_per_line;
-
- // start sending
- writePinHigh(ls0xx->spi_config.chip_select_pin);
- uint8_t cmd = LS0XX_WRITE | LS0XX_VCOM;
- spi_transmit(&cmd, 1);
-
- // dummy data for alignment, value doesn't matter
- uint8_t dummy = 0;
-
- // iterate over the lines
- for (uint8_t i = 0; i < bottom + 1 - top; ++i) {
- // set y-pos (counts from 1, needs the `+1`)
- uint8_t n_line = bitrev(i + top + 1);
- spi_transmit(&n_line, 1);
-
- // send data
- spi_transmit(&surface->u8buffer[buffer_offset], bytes_per_line);
- buffer_offset += bytes_per_line;
-
- spi_transmit(&dummy, 1);
- }
-
- spi_transmit(&dummy, 1);
- writePinLow(ls0xx->spi_config.chip_select_pin);
-
- // clear surface's dirty area, no API to prevent extra prints
- surface->base.driver_vtable->flush(surface);
-
- return true;
-}
-
-bool qp_ls0xx_passthru_viewport(painter_device_t device, uint16_t left,
- uint16_t top, uint16_t right, uint16_t bottom) {
- ls0xx_painter_device_t *ls0xx = (ls0xx_painter_device_t *)device;
- painter_driver_t *surface = (painter_driver_t *)&ls0xx->surface;
-
- return surface->driver_vtable->viewport(surface, left, top, right, bottom);
-}
-
-bool qp_ls0xx_passthru_pixdata(painter_device_t device, const void *pixel_data,
- uint32_t native_pixel_count) {
- ls0xx_painter_device_t *ls0xx = (ls0xx_painter_device_t *)device;
- painter_driver_t *surface = (painter_driver_t *)&ls0xx->surface;
-
- return surface->driver_vtable->pixdata(surface, pixel_data,
- native_pixel_count);
-}
-
-bool qp_ls0xx_passthru_palette_convert(painter_device_t device,
- int16_t palette_size,
- qp_pixel_t *palette) {
- ls0xx_painter_device_t *ls0xx = (ls0xx_painter_device_t *)device;
- painter_driver_t *surface = (painter_driver_t *)&ls0xx->surface;
-
- return surface->driver_vtable->palette_convert(surface, palette_size,
- palette);
-}
-
-bool qp_ls0xx_passthru_append_pixels(painter_device_t device,
- uint8_t *target_buffer,
- qp_pixel_t *palette, uint32_t pixel_offset,
- uint32_t pixel_count,
- uint8_t *palette_indices) {
- ls0xx_painter_device_t *ls0xx = (ls0xx_painter_device_t *)device;
- painter_driver_t *surface = (painter_driver_t *)&ls0xx->surface;
-
- return surface->driver_vtable->append_pixels(surface, target_buffer, palette,
- pixel_offset, pixel_count,
- palette_indices);
-}
-
-bool qp_ls0xx_passthru_append_pixdata(painter_device_t device,
- uint8_t *target_buffer,
- uint32_t pixdata_offset,
- uint8_t pixdata_byte) {
- ls0xx_painter_device_t *ls0xx = (ls0xx_painter_device_t *)device;
- painter_driver_t *surface = (painter_driver_t *)&ls0xx->surface;
-
- return surface->driver_vtable->append_pixdata(surface, target_buffer,
- pixdata_offset, pixdata_byte);
-}
-
-const painter_driver_vtable_t ls0xx_driver_vtable = {
- .init = qp_ls0xx_init,
- .power = qp_ls0xx_passthru_power,
- .clear = qp_ls0xx_passthru_clear,
- .flush = qp_ls0xx_flush,
- .pixdata = qp_ls0xx_passthru_pixdata,
- .viewport = qp_ls0xx_passthru_viewport,
- .palette_convert = qp_ls0xx_passthru_palette_convert,
- .append_pixels = qp_ls0xx_passthru_append_pixels,
- .append_pixdata = qp_ls0xx_passthru_append_pixdata,
-};
-
-painter_device_t qp_ls0xx_device_t_make_spi_device(uint16_t panel_width,
- uint16_t panel_height,
- pin_t chip_select_pin,
- uint16_t spi_divisor,
- int spi_mode, void *buf) {
- for (uint32_t i = 0; i < LS0XX_NUM_DEVICES; ++i) {
- ls0xx_painter_device_t *driver = &ls0xx_device_t_drivers[i];
- if (!driver->base.driver_vtable) {
- painter_device_t surface = qp_make_mono1bpp_surface_advanced(
- &driver->surface, 1, panel_width, panel_height, buf);
- if (!surface) {
- return NULL;
- }
- driver->base.driver_vtable =
- (const painter_driver_vtable_t *)&ls0xx_driver_vtable;
- driver->base.comms_vtable =
- (const painter_comms_vtable_t *)&spi_comms_inverted_cs_vtable;
- driver->base.native_bits_per_pixel = 1;
- 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;
-
- // SPI and other pin configuration
- driver->base.comms_config = &driver->spi_config;
- driver->spi_config.chip_select_pin = chip_select_pin;
- driver->spi_config.lsb_first = false;
- driver->spi_config.divisor = spi_divisor;
- driver->spi_config.mode = spi_mode;
-
- if (!qp_internal_register_device((painter_device_t)driver)) {
- memset(driver, 0, sizeof(ls0xx_painter_device_t));
- return NULL;
- }
-
- return (painter_device_t)driver;
- }
- }
-
- return NULL;
-}