Commit dcac74db authored by schneider's avatar schneider
Browse files

Merge branch 'rahix/ctx' into 'master'

CTX Rendering

See merge request !473
parents 1695d090 9aa8c62c
Pipeline #5276 passed with stages
in 1 minute and 23 seconds
flags = -DBOARD_CARD10=1 -D_FILE_OFFSET_BITS=64 -DTARGET=32665 -DTARGET_REV=0x4131 -target thumbv7m-none-eabi -Ibuild/epicardium -Ibuild/epicardium/366573f@@api-caller@sta -Ibuild/epicardium/366573f@@api-dispatcher@sta -Ibuild/epicardium/366573f@@epicardium.elf@exe -Ibuild/epicardium/366573f@@freertos@sta -Ibuild/lib/card10 -Ibuild/lib/card10/7eaaaa5@@card10@sta -Ibuild/lib/ff13 -Ibuild/lib/ff13/a277df3@@ff13@sta -Ibuild/lib/gfx -Ibuild/lib/gfx/2308dff@@gfx@sta -Ibuild/lib/micropython -Ibuild/lib/micropython/a57cd11@@mpy-cross-wrapper@exe -Ibuild/lib/mx25lba -Ibuild/lib/mx25lba/c7b864b@@mx25lba@sta -Ibuild/lib/sdk/Libraries/Boards/card10 -Ibuild/lib/sdk/Libraries/Boards/card10/9eeeac4@@board-card10@sta -Ibuild/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665 -Ibuild/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/a500f70@@max32665-startup-core0@sta -Ibuild/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/a500f70@@max32665-startup-core1@sta -Ibuild/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/a500f70@@max32665-startup@sta -Ibuild/lib/sdk/Libraries/MAX32665PeriphDriver -Ibuild/lib/sdk/Libraries/MAX32665PeriphDriver/0d96707@@PeriphDriver@sta -Ibuild/lib/sdk/Libraries/MAXUSB -Ibuild/lib/sdk/Libraries/MAXUSB/9a51a91@@maxusb@sta -Ibuild/lib/vendor/Bosch/BHy1 -Ibuild/lib/vendor/Bosch/BHy1/6298ab9@@bhy1@sta -Ibuild/lib/vendor/Bosch/BMA400 -Ibuild/lib/vendor/Bosch/BMA400/b6b0216@@bma400@sta -Ibuild/lib/vendor/Bosch/BME680 -Ibuild/lib/vendor/Bosch/BME680/ef6f079@@bme680@sta -Ibuild/lib/vendor/Maxim/MAX77650 -Ibuild/lib/vendor/Maxim/MAX77650/cc369b8@@max77650@sta -Ibuild/lib/vendor/Maxim/MAX86150 -Ibuild/lib/vendor/Maxim/MAX86150/21e3a66@@max86150@sta -Ibuild/pycardium -Ibuild/pycardium/1f90fd2@@micropython@sta -Ibuild/pycardium/1f90fd2@@pycardium.elf@exe -Iepicardium -Ilib/card10 -Ilib/ff13 -Ilib/ff13/Source -Ilib/ff13/util -Ilib/FreeRTOS/Source/include -Ilib/FreeRTOS/Source/portable/GCC/ARM_CM4F -Ilib/gfx -Ilib/gfx/Fonts -Ilib/gfx/GUI_DEV -Ilib/gfx/LCD -Ilib/micropython -Ilib/micropython/micropython -Ilib/micropython/micropython/extmod -Ilib/micropython/micropython/lib/utils -Ilib/mx25lba -Ilib/sdk/Libraries/Boards/card10 -Ilib/sdk/Libraries/Boards/card10/Include -Ilib/sdk/Libraries/Boards/Include -Ilib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665 -Ilib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Include -Ilib/sdk/Libraries/CMSIS/Include -Ilib/sdk/Libraries/MAX32665PeriphDriver -Ilib/sdk/Libraries/MAX32665PeriphDriver/Include -Ilib/sdk/Libraries/MAXUSB -Ilib/sdk/Libraries/MAXUSB/include/core -Ilib/sdk/Libraries/MAXUSB/include/core/musbhsfc -Ilib/sdk/Libraries/MAXUSB/include/dbg_log -Ilib/sdk/Libraries/MAXUSB/include/devclass -Ilib/sdk/Libraries/MAXUSB/include/enumerate -Ilib/sdk/Libraries/MAXUSB/include/util -Ilib/vendor/Bosch/BHy1 -Ilib/vendor/Bosch/BHy1/driver/inc -Ilib/vendor/Bosch/BHy1/examples/firmware -Ilib/vendor/Bosch/BMA400 -Ilib/vendor/Bosch/BME680 -Ilib/vendor/Maxim/MAX77650 -Ilib/vendor/Maxim/MAX86150 -Ipycardium
flags = -DBOARD_CARD10=1 -D_FILE_OFFSET_BITS=64 -DTARGET=32665 -DTARGET_REV=0x4131 -target thumbv7m-none-eabi -Ibuild/epicardium -Ibuild/epicardium/366573f@@api-caller@sta -Ibuild/epicardium/366573f@@api-dispatcher@sta -Ibuild/epicardium/366573f@@epicardium.elf@exe -Ibuild/epicardium/366573f@@freertos@sta -Ibuild/lib/card10 -Ibuild/lib/card10/7eaaaa5@@card10@sta -Ibuild/lib/ff13 -Ibuild/lib/ff13/a277df3@@ff13@sta -Ibuild/lib/gfx -Ibuild/lib/gfx/2308dff@@gfx@sta -Ibuild/lib/micropython -Ibuild/lib/micropython/a57cd11@@mpy-cross-wrapper@exe -Ibuild/lib/mx25lba -Ibuild/lib/mx25lba/c7b864b@@mx25lba@sta -Ibuild/lib/sdk/Libraries/Boards/card10 -Ibuild/lib/sdk/Libraries/Boards/card10/9eeeac4@@board-card10@sta -Ibuild/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665 -Ibuild/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/a500f70@@max32665-startup-core0@sta -Ibuild/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/a500f70@@max32665-startup-core1@sta -Ibuild/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/a500f70@@max32665-startup@sta -Ibuild/lib/sdk/Libraries/MAX32665PeriphDriver -Ibuild/lib/sdk/Libraries/MAX32665PeriphDriver/0d96707@@PeriphDriver@sta -Ibuild/lib/sdk/Libraries/MAXUSB -Ibuild/lib/sdk/Libraries/MAXUSB/9a51a91@@maxusb@sta -Ibuild/lib/vendor/Bosch/BHy1 -Ibuild/lib/vendor/Bosch/BHy1/6298ab9@@bhy1@sta -Ibuild/lib/vendor/Bosch/BMA400 -Ibuild/lib/vendor/Bosch/BMA400/b6b0216@@bma400@sta -Ibuild/lib/vendor/Bosch/BME680 -Ibuild/lib/vendor/Bosch/BME680/ef6f079@@bme680@sta -Ibuild/lib/vendor/Maxim/MAX77650 -Ibuild/lib/vendor/Maxim/MAX77650/cc369b8@@max77650@sta -Ibuild/lib/vendor/Maxim/MAX86150 -Ibuild/lib/vendor/Maxim/MAX86150/21e3a66@@max86150@sta -Ibuild/pycardium -Ibuild/pycardium/1f90fd2@@micropython@sta -Ibuild/pycardium/1f90fd2@@pycardium.elf@exe -Iepicardium -Ilib/card10 -Ilib/ff13 -Ilib/ff13/Source -Ilib/ff13/util -Ilib/FreeRTOS/Source/include -Ilib/FreeRTOS/Source/portable/GCC/ARM_CM4F -Ilib/gfx -Ilib/gfx/Fonts -Ilib/gfx/GUI_DEV -Ilib/gfx/LCD -Ilib/micropython -Ilib/micropython/micropython -Ilib/micropython/micropython/extmod -Ilib/micropython/micropython/lib/utils -Ilib/mx25lba -Ilib/sdk/Libraries/Boards/card10 -Ilib/sdk/Libraries/Boards/card10/Include -Ilib/sdk/Libraries/Boards/Include -Ilib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665 -Ilib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Include -Ilib/sdk/Libraries/CMSIS/Include -Ilib/sdk/Libraries/MAX32665PeriphDriver -Ilib/sdk/Libraries/MAX32665PeriphDriver/Include -Ilib/sdk/Libraries/MAXUSB -Ilib/sdk/Libraries/MAXUSB/include/core -Ilib/sdk/Libraries/MAXUSB/include/core/musbhsfc -Ilib/sdk/Libraries/MAXUSB/include/dbg_log -Ilib/sdk/Libraries/MAXUSB/include/devclass -Ilib/sdk/Libraries/MAXUSB/include/enumerate -Ilib/sdk/Libraries/MAXUSB/include/util -Ilib/vendor/Bosch/BHy1 -Ilib/vendor/Bosch/BHy1/driver/inc -Ilib/vendor/Bosch/BHy1/examples/firmware -Ilib/vendor/Bosch/BMA400 -Ilib/vendor/Bosch/BME680 -Ilib/vendor/Maxim/MAX77650 -Ilib/vendor/Maxim/MAX86150 -Ipycardium -Ilib/ctx
#include "display.h"
#include "Fonts/fonts.h"
#include "epicardium.h"
#include "drivers/display/lcd.h"
#include "drivers/display/epic_ctx.h"
#include "FreeRTOS.h"
#include "LCD_Driver.h"
#include "epicardium.h"
#include "gfx.h"
#include "gpio.h"
#include "task.h"
#include "tmr.h"
#include "tmr_utils.h"
#include <machine/endian.h>
#include <string.h>
static TaskHandle_t lock = NULL;
static int check_lock()
......@@ -21,6 +24,20 @@ static int check_lock()
}
}
static uint16_t rgb888_to_rgb565(uint8_t *bytes)
{
return ((bytes[0] & 0b11111000) << 8) | ((bytes[1] & 0b11111100) << 3) |
(bytes[2] >> 3);
}
static inline void
rgb565_to_rgb888(uint16_t pixel, uint8_t *red, uint8_t *green, uint8_t *blue)
{
*blue = (pixel & 31) << 3;
*green = ((pixel >> 5) & 63) << 2;
*red = ((pixel >> 11) & 31) << 3;
}
int epic_disp_print(
int16_t posx,
int16_t posy,
......@@ -31,10 +48,9 @@ int epic_disp_print(
return epic_disp_print_adv(DISP_FONT20, posx, posy, pString, fg, bg);
}
static const sFONT *font_map[] = {
[DISP_FONT8] = &Font8, [DISP_FONT12] = &Font12,
[DISP_FONT16] = &Font16, [DISP_FONT20] = &Font20,
[DISP_FONT24] = &Font24,
static const float font_map[] = {
[DISP_FONT8] = 8.0f, [DISP_FONT12] = 12.0f, [DISP_FONT16] = 16.0f,
[DISP_FONT20] = 20.0f, [DISP_FONT24] = 24.0f,
};
int epic_disp_print_adv(
......@@ -45,24 +61,34 @@ int epic_disp_print_adv(
uint16_t fg,
uint16_t bg
) {
uint8_t r, g, b;
int cl = check_lock();
if (font >= (sizeof(font_map) / sizeof(sFONT *))) {
return -EINVAL;
}
if (cl < 0) {
return cl;
} else {
gfx_puts(
font_map[font],
&display_screen,
posx,
posy,
pString,
fg,
bg
);
return 0;
}
if (font >= (sizeof(font_map) / sizeof(font_map[0]))) {
return -EINVAL;
}
float font_size = font_map[font];
ctx_font_size(epicardium_ctx, font_size);
if (fg != bg) {
/* non-transparent background */
rgb565_to_rgb888(bg, &r, &g, &b);
ctx_rgba8(epicardium_ctx, r, g, b, 255);
float width = ctx_text_width(epicardium_ctx, pString);
ctx_rectangle(epicardium_ctx, posx, posy, width, font_size);
ctx_fill(epicardium_ctx);
}
rgb565_to_rgb888(fg, &r, &g, &b);
ctx_rgba8(epicardium_ctx, r, g, b, 255);
ctx_move_to(epicardium_ctx, posx, (float)posy + font_size * 0.8f);
ctx_text(epicardium_ctx, pString);
return 0;
}
int epic_disp_clear(uint16_t color)
......@@ -70,10 +96,18 @@ int epic_disp_clear(uint16_t color)
int cl = check_lock();
if (cl < 0) {
return cl;
} else {
gfx_clear_to_color(&display_screen, color);
return 0;
}
/*
* We could use ctx for this but it's much easier to just clear the
* framebuffer directly.
*/
for (size_t i = 0; i < sizeof(epicardium_ctx_fb); i += 2) {
epicardium_ctx_fb[i] = color >> 8;
epicardium_ctx_fb[i + 1] = color & 0xff;
}
return 0;
}
int epic_disp_pixel(int16_t x, int16_t y, uint16_t color)
......@@ -81,9 +115,45 @@ int epic_disp_pixel(int16_t x, int16_t y, uint16_t color)
int cl = check_lock();
if (cl < 0) {
return cl;
} else {
gfx_setpixel(&display_screen, x, y, color);
return 0;
}
uint8_t r, g, b;
rgb565_to_rgb888(color, &r, &g, &b);
ctx_set_pixel_u8(epicardium_ctx, x, y, r, g, b, 255);
return 0;
}
static uint16_t rgb565_pixel_from_buf(
uint8_t *img,
enum epic_rgb_format format,
int16_t width,
int16_t x,
int16_t y,
uint8_t *alpha
) {
uint16_t tmp16;
uint8_t rgba[4];
switch (format) {
case EPIC_RGB565:
*alpha = 255;
memcpy(&tmp16, &img[y * width * 2 + x * 2], 2);
return tmp16;
case EPIC_RGBA5551:
memcpy(&tmp16, &img[y * width * 2 + x * 2], 2);
*alpha = (tmp16 & 0x01) ? 255 : 0;
return (tmp16 & 0xFFC0) | ((tmp16 & 0x3E) >> 1);
case EPIC_RGB8:
*alpha = 255;
memcpy(rgba, &img[y * width * 3 + x * 3], 3);
return rgb888_to_rgb565(rgba);
case EPIC_RGBA8:
memcpy(rgba, &img[y * width * 4 + x * 4], 4);
*alpha = rgba[3];
return rgb888_to_rgb565(rgba);
default:
return 0xFFFF;
}
}
......@@ -100,69 +170,27 @@ int epic_disp_blit(
return cl;
}
int16_t offset_x = (pos_x < 0) ? -pos_x : 0;
int16_t count_x = width - offset_x;
int16_t offset_y = (pos_y < 0) ? -pos_y : 0;
int16_t count_y = height - offset_y;
for (int16_t xsrc = 0; xsrc < width; xsrc += 1) {
for (int16_t ysrc = 0; ysrc < height; ysrc += 1) {
int16_t xscreen = pos_x + xsrc;
int16_t yscreen = pos_y + ysrc;
size_t offset = yscreen * 160 * 2 + xscreen * 2;
if (xscreen < 0 || xscreen >= 160 || yscreen < 0 ||
yscreen >= 80) {
continue;
}
if (pos_x + width >= 160) {
count_x -= (pos_x + width) % 160;
}
if (pos_y + height >= 80) {
count_y -= (pos_y + height) % 80;
}
uint8_t alpha = 255;
uint16_t pixel = rgb565_pixel_from_buf(
img, format, width, xsrc, ysrc, &alpha
);
size_t bpp;
enum gfx_encoding encoding;
if (alpha == 0) {
continue;
}
switch (format) {
case EPIC_RGB565:
bpp = 2;
encoding = GFX_RGB565;
break;
case EPIC_RGBA5551:
bpp = 2;
encoding = GFX_RGBA5551;
break;
case EPIC_RGB8:
bpp = 3;
encoding = GFX_RGB8;
break;
case EPIC_RGBA8:
bpp = 4;
encoding = GFX_RGBA8;
break;
default:
return -1;
break;
}
if (offset_x == 0 && offset_y == 0 && count_x == width &&
count_y == height) {
/* Copy full image. No cropping.*/
gfx_copy_region(
&display_screen,
pos_x,
pos_y,
width,
height,
encoding,
img
);
} else {
/* Copy cropped image line by line. */
int16_t curr_y;
for (curr_y = offset_y; curr_y < offset_y + count_y; curr_y++) {
uint8_t *line = img + (curr_y * width + offset_x) * bpp;
gfx_copy_region(
&display_screen,
pos_x + offset_x,
pos_y + curr_y,
count_x,
1,
encoding,
line
);
epicardium_ctx_fb[offset] = (pixel & 0xFF00) >> 8;
epicardium_ctx_fb[offset + 1] = pixel & 0xFF;
}
}
......@@ -181,19 +209,31 @@ int epic_disp_line(
int cl = check_lock();
if (cl < 0) {
return cl;
} else {
/* TODO add linestyle support to gfx code */
gfx_line(
&display_screen,
xstart,
ystart,
xend,
yend,
pixelsize,
color
);
return 0;
}
float xstartf = xstart, ystartf = ystart, xendf = xend, yendf = yend;
/*
* For odd line widths, shift the line by half a pixel so it aligns
* perfectly with the pixel grid.
*/
if (pixelsize % 2 == 1) {
xstartf += 0.5f;
ystartf += 0.5f;
yendf += 0.5f;
xendf += 0.5f;
}
uint8_t r, g, b;
rgb565_to_rgb888(color, &r, &g, &b);
ctx_rgba8_stroke(epicardium_ctx, r, g, b, 255);
ctx_line_width(epicardium_ctx, pixelsize);
ctx_move_to(epicardium_ctx, xstartf, ystartf);
ctx_line_to(epicardium_ctx, xendf, yendf);
ctx_stroke(epicardium_ctx);
return 0;
}
int epic_disp_rect(
......@@ -209,29 +249,29 @@ int epic_disp_rect(
if (cl < 0)
return cl;
uint8_t r, g, b;
rgb565_to_rgb888(color, &r, &g, &b);
ctx_rectangle(
epicardium_ctx,
xstart,
ystart,
xend - xstart + 1,
yend - ystart + 1
);
switch (fillstyle) {
case FILLSTYLE_EMPTY:
gfx_rectangle(
&display_screen,
xstart,
ystart,
xend - xstart,
yend - ystart,
pixelsize,
color
);
ctx_rgba8_stroke(epicardium_ctx, r, g, b, 255);
ctx_line_width(epicardium_ctx, pixelsize);
ctx_stroke(epicardium_ctx);
break;
case FILLSTYLE_FILLED:
gfx_rectangle_fill(
&display_screen,
xstart,
ystart,
xend - xstart,
yend - ystart,
color
);
ctx_rgba8(epicardium_ctx, r, g, b, 255);
ctx_fill(epicardium_ctx);
break;
}
return 0;
}
......@@ -247,12 +287,20 @@ int epic_disp_circ(
if (cl < 0)
return cl;
uint8_t r, g, b;
rgb565_to_rgb888(color, &r, &g, &b);
ctx_arc(epicardium_ctx, x, y, rad, 0.0f, CTX_PI * 1.95, 0);
switch (fillstyle) {
case FILLSTYLE_EMPTY:
gfx_circle(&display_screen, x, y, rad, pixelsize, color);
ctx_rgba8_stroke(epicardium_ctx, r, g, b, 255);
ctx_line_width(epicardium_ctx, pixelsize);
ctx_stroke(epicardium_ctx);
break;
case FILLSTYLE_FILLED:
gfx_circle_fill(&display_screen, x, y, rad, color);
ctx_rgba8(epicardium_ctx, r, g, b, 255);
ctx_fill(epicardium_ctx);
break;
}
......@@ -266,7 +314,8 @@ int epic_disp_update()
return cl;
}
gfx_update(&display_screen);
lcd_write_fb(epicardium_ctx_fb);
return 0;
}
......@@ -277,13 +326,24 @@ int epic_disp_framebuffer(union disp_framebuffer *fb)
return cl;
}
LCD_Set(fb->raw, sizeof(fb->raw));
/*
* Flip the screen because that's what this API call historically
* expects.
*/
lcd_set_screenflip(true);
lcd_write_fb(fb->raw);
lcd_set_screenflip(false);
return 0;
}
int epic_disp_backlight(uint16_t brightness)
{
/* TODO: lock? */
if (brightness == 0) {
lcd_set_sleep(true);
} else {
lcd_set_sleep(false);
}
LCD_SetBacklight(brightness);
return 0;
}
......
#pragma once
#include "ctx.h"
extern Ctx *epicardium_ctx;
extern uint8_t epicardium_ctx_fb[160 * 80 * 2];
#include "drivers/display/lcd.h"
#include "drivers/display/epic_ctx.h"
#include "drivers/drivers.h"
#include "display.h"
#include "ctx.h"
#include <stdint.h>
#include <machine/endian.h>
#if BYTE_ORDER == LITTLE_ENDIAN
#define CARD10_CTX_FORMAT CTX_FORMAT_RGB565_BYTESWAPPED
#else
#define CARD10_CTX_FORMAT CTX_FORMAT_RGB565
#endif
uint8_t epicardium_ctx_fb[160 * 80 * 2] = { 0 };
Ctx *epicardium_ctx = NULL;
void disp_init(void)
{
/*
* The bootloader has already initialized the display, so we only need
* to do the bare minimum here.
*/
lcd_reconfigure();
/*
* Initialize the graphics context.
*/
disp_ctx_reinit();
}
void disp_ctx_reinit(void)
{
if (epicardium_ctx != NULL) {
ctx_free(epicardium_ctx);
}
epicardium_ctx = ctx_new_for_framebuffer(
epicardium_ctx_fb, 160, 80, 160 * 2, CARD10_CTX_FORMAT
);
/* set some defaults */
ctx_rgba(epicardium_ctx, 1.0f, 1.0f, 1.0f, 1.0f);
ctx_rgba_stroke(epicardium_ctx, 1.0f, 1.0f, 1.0f, 1.0f);
ctx_font(epicardium_ctx, "ctx-mono");
}
#include "os/core.h"
#include "MAX77650-Arduino-Library.h"
#include "gpio.h"
#include "mxc_delay.h"
#include "portexpander.h"
#include "spi.h"
#include <machine/endian.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/* HAL Interfaces {{{ */
static const gpio_cfg_t GPIO_PIN_DC = {
PORT_1, PIN_6, GPIO_FUNC_OUT, GPIO_PAD_NONE
};
static void lcd_hw_init(void)
{
GPIO_Config(&GPIO_PIN_DC);
/* for the reset pin */
if (!portexpander_detected()) {
/* Open-drain */
MAX77650_setDRV(false);
/* Output */
MAX77650_setDIR(false);
}
}
static void lcd_set_dc(bool state)
{
if (state) {
GPIO_OutSet(&GPIO_PIN_DC);
} else {
GPIO_OutClr(&GPIO_PIN_DC);
}
}
static void lcd_set_rst(bool state)
{
if (!portexpander_detected()) {
MAX77650_setDO(state ? true : false);
} else {
portexpander_out_put(PIN_4, state ? 0xFF : 0);
}
}
/** Bit Rate. Display has 15 MHz limit */
#define SPI_SPEED (15 * 1000 * 1000)
static void lcd_spi_write(const uint8_t *data, size_t count)
{
const sys_cfg_spi_t spi_master_cfg = {
.map = MAP_A,
.ss0 = Enable,
.ss1 = Disable,
.ss2 = Disable,
.num_io = 2,
};
spi_req_t request = {
.ssel = 0,
.deass = 1,
.ssel_pol = SPI17Y_POL_LOW,
.tx_data = data,
.rx_data = NULL,
.width = SPI17Y_WIDTH_1,
.len = count,
.bits = 8,
.rx_num = 0,
.tx_num = 0,
.callback = NULL,
};
if (SPI_Init(SPI2, 0, SPI_SPEED, spi_master_cfg) != 0) {
panic("Error configuring display SPI");
}
SPI_MasterTrans(SPI2, &request);
}
static void lcd_delay(size_t millis)
{
// TODO: Is this what we want?
mxc_delay(millis * 1000);
}
/* HAL Interfaces }}} */
enum lcd_commands {
/** Sleep In */
LCD_SLPIN = 0x10,
/** Sleep Out */
LCD_SLPOUT = 0x11,
/** Display Inversion On */
LCD_INVON = 0x21,
/** Display On */
LCD_DISPON = 0x29,
/** Column Address Set */
LCD_CASET = 0x2A,
/** Row Address Set */
LCD_RASET = 0x2B,
/** Memory Write */
LCD_RAMWR = 0x2C,
/** Memory Data Access Control */
LCD_MADCTL = 0x36,
/** Interface Pixel Format */
LCD_COLMOD = 0x3A,
/** Frame Rate Control (In normal mode/ Full colors) */
LCD_FRMCTR1 = 0xB1,
/** Frame Rate Control (In Idle mode/ 8-colors) */
LCD_FRMCTR2 = 0xB2,
/** Frame Rate Control (In Partial mode/ full colors) */
LCD_FRMCTR3 = 0xB3,
/** Display Inversion Control */
LCD_INVCTR = 0xB4,
/** Power Control 1 */
LCD_PWCTR1 = 0xC0,
/** Power Control 2 */
LCD_PWCTR2 = 0xC1,
/** Power Control 3 (in Normal mode/ Full colors) */
LCD_PWCTR3 = 0xC2,
/** Power Control 4 (in Idle mode/ 8-colors) */
LCD_PWCTR4 = 0xC3,
/** Power Control 5 (in Partial mode/ full-colors) */
LCD_PWCTR5 = 0xC4,
/** VCOM Control 1 */
LCD_VMCTR1 = 0xC5,
/** Gamma (+ polarity) Correction Characteristics Setting */
LCD_GMCTRP1 = 0xE0,
/** Gamma (- polarity) Correction Characteristics Setting */
LCD_GMCTRN1 = 0xE1,
};
enum madctl_bits {
MADCTL_MY = 0x80,
MADCTL_MX = 0x40,
MADCTL_MV = 0x20,
MADCTL_ML = 0x10,
MADCTL_RGB = 0x08,
MADCTL_MH = 0x04,
};
static void
lcd_send_command(enum lcd_commands cmd, const uint8_t *args, size_t count)
{