diff --git a/rtl/system/ibex_demo_system.sv b/rtl/system/ibex_demo_system.sv index 8cdc8697..14bde260 100644 --- a/rtl/system/ibex_demo_system.sv +++ b/rtl/system/ibex_demo_system.sv @@ -38,7 +38,7 @@ module ibex_demo_system #( input logic td_i, // JTAG test data input pad output logic td_o // JTAG test data output pad ); - localparam logic [31:0] MEM_SIZE = 64 * 1024; // 64 KiB + localparam logic [31:0] MEM_SIZE = 128 * 1024; // 128 KiB localparam logic [31:0] MEM_START = 32'h00100000; localparam logic [31:0] MEM_MASK = ~(MEM_SIZE-1); diff --git a/sw/c/common/demo_system.h b/sw/c/common/demo_system.h index 1fc4bbc1..feeca883 100644 --- a/sw/c/common/demo_system.h +++ b/sw/c/common/demo_system.h @@ -24,7 +24,9 @@ #define NUM_PWM_MODULES 12 -#define DEFAULT_SPI SPI_FROM_BASE_ADDR(SPI0_BASE) +#define LCD_SPI SPI_FROM_BASE_ADDR(SPI0_BASE) + +#define SYSCLK_FREQ 50000000 /** * Writes character to default UART. Signature matches c stdlib function diff --git a/sw/c/common/spi.c b/sw/c/common/spi.c index d85903d4..89c992e2 100644 --- a/sw/c/common/spi.c +++ b/sw/c/common/spi.c @@ -20,3 +20,14 @@ void spi_send_byte_blocking(spi_t *spi, char c) { } spi_status_t spi_get_status(spi_t *spi) { return (spi_status_t)DEV_READ(spi->reg + SPI_STATUS_REG); } + +void spi_wait_idle(spi_t *spi) { + while ((spi_get_status(spi) & spi_status_fifo_empty) != spi_status_fifo_empty); +} + +void spi_tx(spi_t *spi, const uint8_t *data, uint32_t len) { + spi_wait_idle(spi); + while (len--) { + spi_send_byte_blocking(spi, *data++); + } +} diff --git a/sw/c/common/spi.h b/sw/c/common/spi.h index 37f5dee5..d4e3b65a 100644 --- a/sw/c/common/spi.h +++ b/sw/c/common/spi.h @@ -30,4 +30,7 @@ void spi_init(spi_t *spi, spi_reg_t reg, uint32_t speed); void spi_send_byte_blocking(spi_t *spi, char c); spi_status_t spi_get_status(spi_t *spi); +void spi_wait_idle(spi_t *spi); +void spi_tx(spi_t *spi, const uint8_t *data, uint32_t len); + #endif // SPI_H__ diff --git a/sw/c/demo/lcd_st7735/CMakeLists.txt b/sw/c/demo/lcd_st7735/CMakeLists.txt index f2371b88..c0446c5b 100644 --- a/sw/c/demo/lcd_st7735/CMakeLists.txt +++ b/sw/c/demo/lcd_st7735/CMakeLists.txt @@ -1,15 +1,42 @@ +# This is the same sets of compilation flags used in ibex CoreMark core_portme.mak. +set(CMAKE_C_FLAGS "-mtune=sifive-3-series -O3 -falign-functions=16 -funroll-all-loops -finline-functions -falign-jumps=4 -mstrict-align") add_library(lcd_st7735_lib ${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/display_drivers/core/lcd_base.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/display_drivers/core/lucida_console_10pt.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/display_drivers/core/lucida_console_12pt.c +${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/display_drivers/core/m3x6_16pt.c ${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/display_drivers/st7735/lcd_st7735.c ) +add_library(coremark +${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/lowrisc_ibex/vendor/eembc_coremark/core_list_join.c +${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/lowrisc_ibex/vendor/eembc_coremark/core_main.c +${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/lowrisc_ibex/vendor/eembc_coremark/core_matrix.c +${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/lowrisc_ibex/vendor/eembc_coremark/core_state.c +${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/lowrisc_ibex/vendor/eembc_coremark/core_util.c +${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/lowrisc_ibex/vendor/eembc_coremark/barebones/cvt.c +coremark/core_portme.c +coremark/ee_printf.c +) + +# core_main defines a `main` function, rename it to `coremark_main` instead. +set_source_files_properties( + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/lowrisc_ibex/vendor/eembc_coremark/core_main.c + PROPERTIES COMPILE_FLAGS -Dmain=coremark_main +) + +target_include_directories(coremark PRIVATE +${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/lowrisc_ibex/vendor/eembc_coremark +${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/lowrisc_ibex/examples/sw/benchmarks/coremark/ibex +) + +target_link_libraries(coremark common) + # add_executable(lcd_st7735 main.c) -add_executable(lcd_st7735 main.c lcd.c fractal_fixed.c fractal_float.c fractal_palette.c) +add_executable(lcd_st7735 main.c lcd.c fractal_fixed.c fractal_float.c fractal_palette.c fbcon.c) # pull in core dependencies and additional i2c hardware support -target_link_libraries(lcd_st7735 common lcd_st7735_lib) +target_link_libraries(lcd_st7735 common lcd_st7735_lib coremark) target_include_directories(lcd_st7735 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../../../vendor/display_drivers) diff --git a/sw/c/demo/lcd_st7735/coremark/core_portme.c b/sw/c/demo/lcd_st7735/coremark/core_portme.c new file mode 100644 index 00000000..8b8675af --- /dev/null +++ b/sw/c/demo/lcd_st7735/coremark/core_portme.c @@ -0,0 +1,66 @@ +// Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "core_portme.h" +#include "coremark.h" + +#include "demo_system.h" +#include "timer.h" + +#define ITERATIONS 100 + +#if VALIDATION_RUN +volatile ee_s32 seed1_volatile = 0x3415; +volatile ee_s32 seed2_volatile = 0x3415; +volatile ee_s32 seed3_volatile = 0x66; +#endif +#if PERFORMANCE_RUN +volatile ee_s32 seed1_volatile = 0x0; +volatile ee_s32 seed2_volatile = 0x0; +volatile ee_s32 seed3_volatile = 0x66; +#endif +#if PROFILE_RUN +volatile ee_s32 seed1_volatile = 0x8; +volatile ee_s32 seed2_volatile = 0x8; +volatile ee_s32 seed3_volatile = 0x8; +#endif +volatile ee_s32 seed4_volatile = ITERATIONS; +volatile ee_s32 seed5_volatile = 0; + +static uint64_t start_time_val, stop_time_val; + +void start_time(void) { + start_time_val = timer_read(); +} + +void stop_time(void) { + stop_time_val = timer_read(); +} + +CORE_TICKS get_time(void) { + return (CORE_TICKS)(stop_time_val - start_time_val); +} + +secs_ret time_in_secs(CORE_TICKS ticks) { + secs_ret retval = ((secs_ret)ticks) / (secs_ret)SYSCLK_FREQ; + return retval; +} + +ee_u32 default_num_contexts = 1; + +void portable_init(core_portable *p, int *argc, char *argv[]) { + p->portable_id = 1; +} + +void portable_fini(core_portable *p) { + CORE_TICKS elapsed = get_time(); + float coremark_mhz; + + coremark_mhz = (1000000.0f * (float)ITERATIONS) / elapsed; + + ee_printf("CoreMark / MHz: %f", coremark_mhz); + + p->portable_id = 0; +} diff --git a/sw/c/demo/lcd_st7735/coremark/ee_printf.c b/sw/c/demo/lcd_st7735/coremark/ee_printf.c new file mode 100644 index 00000000..01d94349 --- /dev/null +++ b/sw/c/demo/lcd_st7735/coremark/ee_printf.c @@ -0,0 +1,561 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include + +#define HAS_FLOAT 1 + +#define ZEROPAD (1<<0) /* Pad with zero */ +#define SIGN (1<<1) /* Unsigned/signed long */ +#define PLUS (1<<2) /* Show plus */ +#define SPACE (1<<3) /* Spacer */ +#define LEFT (1<<4) /* Left justified */ +#define HEX_PREP (1<<5) /* 0x */ +#define UPPERCASE (1<<6) /* 'ABCDEF' */ + +#define is_digit(c) ((c) >= '0' && (c) <= '9') + +static char *digits = "0123456789abcdefghijklmnopqrstuvwxyz"; +static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +static int skip_atoi(const char **s) +{ + int i = 0; + while (is_digit(**s)) i = i*10 + *((*s)++) - '0'; + return i; +} + +static char *number(char *str, long num, int base, int size, int precision, int type) +{ + char c, sign, tmp[66]; + char *dig = digits; + int i; + + if (type & UPPERCASE) dig = upper_digits; + if (type & LEFT) type &= ~ZEROPAD; + if (base < 2 || base > 36) return 0; + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) + { + if (num < 0) + { + sign = '-'; + num = -num; + size--; + } + else if (type & PLUS) + { + sign = '+'; + size--; + } + else if (type & SPACE) + { + sign = ' '; + size--; + } + } + + if (type & HEX_PREP) + { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + + i = 0; + + if (num == 0) + tmp[i++] = '0'; + else + { + while (num != 0) + { + tmp[i++] = dig[((unsigned long) num) % (unsigned) base]; + num = ((unsigned long) num) / (unsigned) base; + } + } + + if (i > precision) precision = i; + size -= precision; + if (!(type & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' '; + if (sign) *str++ = sign; + + if (type & HEX_PREP) + { + if (base == 8) + *str++ = '0'; + else if (base == 16) + { + *str++ = '0'; + *str++ = digits[33]; + } + } + + if (!(type & LEFT)) while (size-- > 0) *str++ = c; + while (i < precision--) *str++ = '0'; + while (i-- > 0) *str++ = tmp[i]; + while (size-- > 0) *str++ = ' '; + + return str; +} + +static char *eaddr(char *str, unsigned char *addr, int size, int precision, int type) +{ + char tmp[24]; + char *dig = digits; + int i, len; + + if (type & UPPERCASE) dig = upper_digits; + len = 0; + for (i = 0; i < 6; i++) + { + if (i != 0) tmp[len++] = ':'; + tmp[len++] = dig[addr[i] >> 4]; + tmp[len++] = dig[addr[i] & 0x0F]; + } + + if (!(type & LEFT)) while (len < size--) *str++ = ' '; + for (i = 0; i < len; ++i) *str++ = tmp[i]; + while (len < size--) *str++ = ' '; + + return str; +} + +static char *iaddr(char *str, unsigned char *addr, int size, int precision, int type) +{ + char tmp[24]; + int i, n, len; + + len = 0; + for (i = 0; i < 4; i++) + { + if (i != 0) tmp[len++] = '.'; + n = addr[i]; + + if (n == 0) + tmp[len++] = digits[0]; + else + { + if (n >= 100) + { + tmp[len++] = digits[n / 100]; + n = n % 100; + tmp[len++] = digits[n / 10]; + n = n % 10; + } + else if (n >= 10) + { + tmp[len++] = digits[n / 10]; + n = n % 10; + } + + tmp[len++] = digits[n]; + } + } + + if (!(type & LEFT)) while (len < size--) *str++ = ' '; + for (i = 0; i < len; ++i) *str++ = tmp[i]; + while (len < size--) *str++ = ' '; + + return str; +} + +#if HAS_FLOAT + +char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); +char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); + +static void parse_float(double value, char *buffer, char fmt, int precision) +{ + int decpt, sign, exp, pos; + char *digits = NULL; + char cvtbuf[80]; + int capexp = 0; + int magnitude; + + if (fmt == 'G' || fmt == 'E') + { + capexp = 1; + fmt += 'a' - 'A'; + } + + if (fmt == 'g') + { + digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf); + magnitude = decpt - 1; + if (magnitude < -4 || magnitude > precision - 1) + { + fmt = 'e'; + precision -= 1; + } + else + { + fmt = 'f'; + precision -= decpt; + } + } + + if (fmt == 'e') + { + digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf); + + if (sign) *buffer++ = '-'; + *buffer++ = *digits; + if (precision > 0) *buffer++ = '.'; + memcpy(buffer, digits + 1, precision); + buffer += precision; + *buffer++ = capexp ? 'E' : 'e'; + + if (decpt == 0) + { + if (value == 0.0) + exp = 0; + else + exp = -1; + } + else + exp = decpt - 1; + + if (exp < 0) + { + *buffer++ = '-'; + exp = -exp; + } + else + *buffer++ = '+'; + + buffer[2] = (exp % 10) + '0'; + exp = exp / 10; + buffer[1] = (exp % 10) + '0'; + exp = exp / 10; + buffer[0] = (exp % 10) + '0'; + buffer += 3; + } + else if (fmt == 'f') + { + digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf); + if (sign) *buffer++ = '-'; + if (*digits) + { + if (decpt <= 0) + { + *buffer++ = '0'; + *buffer++ = '.'; + for (pos = 0; pos < -decpt; pos++) *buffer++ = '0'; + while (*digits) *buffer++ = *digits++; + } + else + { + pos = 0; + while (*digits) + { + if (pos++ == decpt) *buffer++ = '.'; + *buffer++ = *digits++; + } + } + } + else + { + *buffer++ = '0'; + if (precision > 0) + { + *buffer++ = '.'; + for (pos = 0; pos < precision; pos++) *buffer++ = '0'; + } + } + } + + *buffer = '\0'; +} + +static void decimal_point(char *buffer) +{ + while (*buffer) + { + if (*buffer == '.') return; + if (*buffer == 'e' || *buffer == 'E') break; + buffer++; + } + + if (*buffer) + { + int n = strnlen(buffer,256); + while (n > 0) + { + buffer[n + 1] = buffer[n]; + n--; + } + + *buffer = '.'; + } + else + { + *buffer++ = '.'; + *buffer = '\0'; + } +} + +static void cropzeros(char *buffer) +{ + char *stop; + + while (*buffer && *buffer != '.') buffer++; + if (*buffer++) + { + while (*buffer && *buffer != 'e' && *buffer != 'E') buffer++; + stop = buffer--; + while (*buffer == '0') buffer--; + if (*buffer == '.') buffer--; + while (buffer!=stop) + *++buffer=0; + } +} + +static char *flt(char *str, double num, int size, int precision, char fmt, int flags) +{ + char tmp[80]; + char c, sign; + int n, i; + + // Left align means no zero padding + if (flags & LEFT) flags &= ~ZEROPAD; + + // Determine padding and sign char + c = (flags & ZEROPAD) ? '0' : ' '; + sign = 0; + if (flags & SIGN) + { + if (num < 0.0) + { + sign = '-'; + num = -num; + size--; + } + else if (flags & PLUS) + { + sign = '+'; + size--; + } + else if (flags & SPACE) + { + sign = ' '; + size--; + } + } + + // Compute the precision value + if (precision < 0) + precision = 6; // Default precision: 6 + + // Convert floating point number to text + parse_float(num, tmp, fmt, precision); + + if ((flags & HEX_PREP) && precision == 0) decimal_point(tmp); + if (fmt == 'g' && !(flags & HEX_PREP)) cropzeros(tmp); + + n = strnlen(tmp,256); + + // Output number with alignment and padding + size -= n; + if (!(flags & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' '; + if (sign) *str++ = sign; + if (!(flags & LEFT)) while (size-- > 0) *str++ = c; + for (i = 0; i < n; i++) *str++ = tmp[i]; + while (size-- > 0) *str++ = ' '; + + return str; +} + +#endif + +static int ee_vsprintf(char *buf, const char *fmt, va_list args) +{ + int len; + unsigned long num; + int i, base; + char *str; + char *s; + + int flags; // Flags to number() + + int field_width; // Width of output field + int precision; // Min. # of digits for integers; max number of chars for from string + int qualifier; // 'h', 'l', or 'L' for integer fields + + for (str = buf; *fmt; fmt++) + { + if (*fmt != '%') + { + *str++ = *fmt; + continue; + } + + // Process flags + flags = 0; +repeat: + fmt++; // This also skips first '%' + switch (*fmt) + { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= HEX_PREP; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + // Get field width + field_width = -1; + if (is_digit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') + { + fmt++; + field_width = va_arg(args, int); + if (field_width < 0) + { + field_width = -field_width; + flags |= LEFT; + } + } + + // Get the precision + precision = -1; + if (*fmt == '.') + { + ++fmt; + if (is_digit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') + { + ++fmt; + precision = va_arg(args, int); + } + if (precision < 0) precision = 0; + } + + // Get the conversion qualifier + qualifier = -1; + if (*fmt == 'l' || *fmt == 'L') + { + qualifier = *fmt; + fmt++; + } + + // Default base + base = 10; + + switch (*fmt) + { + case 'c': + if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) *str++ = ' '; + continue; + + case 's': + s = va_arg(args, char *); + if (!s) s = ""; + len = strnlen(s, precision); + if (!(flags & LEFT)) while (len < field_width--) *str++ = ' '; + for (i = 0; i < len; ++i) *str++ = *s++; + while (len < field_width--) *str++ = ' '; + continue; + + case 'p': + if (field_width == -1) + { + field_width = 2 * sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags); + continue; + + case 'A': + flags |= UPPERCASE; + + case 'a': + if (qualifier == 'l') + str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags); + else + str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags); + continue; + + // Integer number formats - set up the flags and "break" + case 'o': + base = 8; + break; + + case 'X': + flags |= UPPERCASE; + + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + + case 'u': + break; + +#if HAS_FLOAT + + case 'f': + str = flt(str, va_arg(args, double), field_width, precision, *fmt, flags | SIGN); + continue; + +#endif + + default: + if (*fmt != '%') *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + continue; + } + + if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + + str = number(str, num, base, field_width, precision, flags); + } + + *str = '\0'; + return str - buf; +} + +void fbcon_putstr(const char *str); + +int ee_printf(const char *fmt, ...) +{ + char buf[256]; + va_list args; + va_start(args, fmt); + int n = ee_vsprintf(buf, fmt, args); + va_end(args); + fbcon_putstr(buf); + return n; +} diff --git a/sw/c/demo/lcd_st7735/fbcon.c b/sw/c/demo/lcd_st7735/fbcon.c new file mode 100644 index 00000000..94941777 --- /dev/null +++ b/sw/c/demo/lcd_st7735/fbcon.c @@ -0,0 +1,58 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "fbcon.h" + +static St7735Context *ctx; +static LCD_Point pos = {.x = 0, .y = 0}; + +void fbcon_init(St7735Context* st_ctx) { + ctx = st_ctx; +} + +static void newline() { + pos.x = 0; + pos.y += ctx->parent.font->height; + + // Warp to the top if the screen is full. + if (pos.y + ctx->parent.font->height > ctx->parent.height) { + pos.y = 0; + } + + // Clear the content on the new line. + lcd_st7735_fill_rectangle( + ctx, + (LCD_rectangle){ + .origin = pos, .width = ctx->parent.width, .height = ctx->parent.font->height}, + 0xffffff); +} + +void fbcon_putstr(const char *str) { + while (*str) { + char ch = *str++; + switch (ch) { + case '\r': + pos.x = 0; + break; + case '\n': + newline(); + break; + case '\f': + lcd_st7735_clean(ctx); + pos.x = 0; + pos.y = 0; + break; + default: { + int width = ctx->parent.font->descriptor_table[ch - ctx->parent.font->startCharacter].width; + if (pos.x + width > ctx->parent.width) { + newline(); + } + + lcd_st7735_putchar(ctx, pos, ch); + pos.x += width; + break; + } + } + } +} diff --git a/sw/c/demo/lcd_st7735/fbcon.h b/sw/c/demo/lcd_st7735/fbcon.h new file mode 100644 index 00000000..7e5b914f --- /dev/null +++ b/sw/c/demo/lcd_st7735/fbcon.h @@ -0,0 +1,24 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef FBCON_H__ +#define FBCON_H__ + +#include + +/** + * Initialize the framebuffer console. + * + * @param ctx The ST7735 context to display on. + */ +void fbcon_init(St7735Context* ctx); + +/** + * Print a string to the framebuffer console. + * + * @param str The string to print. + */ +void fbcon_putstr(const char *str); + +#endif diff --git a/sw/c/demo/lcd_st7735/lcd.c b/sw/c/demo/lcd_st7735/lcd.c index 67b4fc6e..846dac42 100644 --- a/sw/c/demo/lcd_st7735/lcd.c +++ b/sw/c/demo/lcd_st7735/lcd.c @@ -7,50 +7,52 @@ #include "st7735/lcd_st7735.h" #include "string.h" -void lcd_show_menu(St7735Context *lcd, Menu_t *menu) { - size_t line = 0; - size_t selected = 1; +void lcd_show_menu(St7735Context *lcd, Menu_t *menu, size_t selected) { + // Include 2 pixels for borders. + uint32_t line_height = lcd->parent.font->height + 2; + // Clean the screen. lcd_st7735_fill_rectangle( - lcd, (LCD_rectangle){.origin = {.x = 0, .y = 0}, .width = lcd->parent.width, .height = lcd->parent.font->height}, - menu->color); + lcd, (LCD_rectangle){.origin = {.x = 0, .y = 0}, .width = lcd->parent.width, .height = line_height}, menu->color); // Invert background and foreground colors for the title. lcd_st7735_set_font_colors(lcd, menu->color, menu->background); - lcd_println(lcd, menu->title, alined_center, line++); + lcd_println(lcd, menu->title, alined_center, (LCD_Point){.x = 0, .y = 1}); // Set the colors for the menu items. lcd_st7735_set_font_colors(lcd, menu->background, menu->color); // Draw the menu items. for (int i = 0; i < menu->items_count; ++i) { - lcd_println(lcd, menu->items[i], alined_left, line++); + lcd_println(lcd, menu->items[i], alined_left, (LCD_Point){.x = 1, .y = (i + 1) * line_height + 1}); } - // Drow a boarder around the selected item. + // Draw a boarder around the selected item. + // Increment `selected` to skip the title bar. selected++; lcd_st7735_draw_horizontal_line( - lcd, (LCD_Line){{.x = 0, .y = lcd->parent.font->height * selected}, lcd->parent.width}, menu->selected_color); + lcd, (LCD_Line){{.x = 0, .y = line_height * selected}, lcd->parent.width}, menu->selected_color); lcd_st7735_draw_horizontal_line( - lcd, (LCD_Line){{.x = 0, .y = lcd->parent.font->height * (selected + 1) - 1}, lcd->parent.width}, + lcd, (LCD_Line){{.x = 0, .y = line_height * (selected + 1) - 1}, lcd->parent.width}, menu->selected_color); lcd_st7735_draw_vertical_line( - lcd, (LCD_Line){{.x = 0, .y = lcd->parent.font->height * selected}, lcd->parent.font->height - 1}, + lcd, (LCD_Line){{.x = 0, .y = line_height * selected}, line_height - 1}, menu->selected_color); lcd_st7735_draw_vertical_line( lcd, - (LCD_Line){{.x = lcd->parent.width - 1, .y = lcd->parent.font->height * selected}, lcd->parent.font->height - 1}, + (LCD_Line){{.x = lcd->parent.width - 1, .y = line_height * selected}, line_height - 1}, menu->selected_color); } -void lcd_println(St7735Context *lcd, const char *str, TextAlignment_t alignment, int32_t line) { - // Align the test in the left. - LCD_Point pos = {.y = line * lcd->parent.font->height, .x = 0}; - +void lcd_println(St7735Context *lcd, const char *str, TextAlignment_t alignment, LCD_Point pos) { if (alignment != alined_left) { - // Align the text in the right. - pos.x = lcd->parent.width - strlen(str) * lcd->parent.font->descriptor_table->width; + uint32_t line_width = 0; + for (const char *ptr = str; *ptr; ptr++) { + line_width += lcd->parent.font->descriptor_table[*ptr - lcd->parent.font->startCharacter].width; + } + if (alignment == alined_center) { - // Align the test in the center. - pos.x /= 2; + pos.x = (lcd->parent.width - line_width) / 2; + } else { + pos.x = lcd->parent.width - pos.x - line_width; } } diff --git a/sw/c/demo/lcd_st7735/lcd.h b/sw/c/demo/lcd_st7735/lcd.h index 5441b1f9..c8fcd2fe 100644 --- a/sw/c/demo/lcd_st7735/lcd.h +++ b/sw/c/demo/lcd_st7735/lcd.h @@ -30,10 +30,9 @@ typedef enum TextAlignment { * @param lcd LCD handle. * @param str NULL terminated string. * @param alignment Text horizontal alignment in the screen. - * @param line Position line starting at 0. The total number of lines will vary depending on - * the font size. + * @param pos Position of the line. The x component indicates horizontal padding. */ -void lcd_println(St7735Context *lcd, const char *str, TextAlignment_t alignment, int32_t line); +void lcd_println(St7735Context *lcd, const char *str, TextAlignment_t alignment, LCD_Point pos); typedef struct Menu { const char *title; // Pointer to a NULL terminated string to be used as the title. @@ -49,6 +48,7 @@ typedef struct Menu { * * @param lcd LCD handle. * @param menu Menu configuration. + * @param selected Index of the selected menu item */ -void lcd_show_menu(St7735Context *lcd, Menu_t *menu); +void lcd_show_menu(St7735Context *lcd, Menu_t *menu, size_t selected); #endif diff --git a/sw/c/demo/lcd_st7735/main.c b/sw/c/demo/lcd_st7735/main.c index af311775..edd757ac 100644 --- a/sw/c/demo/lcd_st7735/main.c +++ b/sw/c/demo/lcd_st7735/main.c @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "core/lucida_console_10pt.h" +#include "core/m3x6_16pt.h" #include "demo_system.h" #include "fractal.h" #include "gpio.h" @@ -11,6 +12,7 @@ #include "spi.h" #include "st7735/lcd_st7735.h" #include "timer.h" +#include "fbcon.h" // Constants. enum { @@ -26,11 +28,13 @@ enum { }; // Buttons +// The direction is relative to the screen in landscape orientation. typedef enum { - BTN0 = 0b0001, - BTN1 = 0b0010, - BTN2 = 0b0100, - BTN3 = 0b1000, + BTN_DOWN = 0b00001, + BTN_LEFT = 0b00010, + BTN_CLICK = 0b00100, + BTN_RIGHT = 0b01000, + BTN_UP = 0b10000, } Buttons_t; // Local functions declaration. @@ -38,7 +42,7 @@ static uint32_t spi_write(void *handle, uint8_t *data, size_t len); static uint32_t gpio_write(void *handle, bool cs, bool dc); static void timer_delay(uint32_t ms); static void fractal_test(St7735Context *lcd); -static Buttons_t scan_buttons(uint32_t timeout, Buttons_t def); +static Buttons_t scan_buttons(uint32_t timeout); int main(void) { timer_init(); @@ -50,7 +54,7 @@ int main(void) { // Init spi driver. spi_t spi; - spi_init(&spi, DEFAULT_SPI, SpiSpeedHz); + spi_init(&spi, LCD_SPI, SpiSpeedHz); // Reset LCD. set_output_bit(GPIO_OUT, LcdRstPin, 0x0); @@ -80,68 +84,159 @@ int main(void) { // Draw the splash screen with a RGB 565 bitmap and text in the bottom. lcd_st7735_draw_rgb565(&lcd, (LCD_rectangle){.origin = {.x = (160 - 105) / 2, .y = 5}, .width = 105, .height = 80}, (uint8_t *)lowrisc_logo_105x80); - lcd_println(&lcd, "Booting...", alined_center, 7); + + lcd_println(&lcd, "Booting...", alined_center, (LCD_Point){.x = 0, .y = 100}); timer_delay(1000); - do { - lcd_st7735_clean(&lcd); - - // Show the main menu. - const char *items[] = { - "0. Fractal", - "1. Custom", - }; - Menu_t main_menu = { - .title = "Main menu", - .color = BGRColorBlue, - .selected_color = BGRColorRed, - .background = BGRColorWhite, - .items_count = sizeof(items) / sizeof(items[0]), - .items = items, - }; - lcd_show_menu(&lcd, &main_menu); - lcd_st7735_puts(&lcd, (LCD_Point){.x = 5, .y = 106}, "Defaulting to item"); - lcd_st7735_puts(&lcd, (LCD_Point){.x = 5, .y = 118}, "0 after 3 seconds"); - - switch (scan_buttons(3000, BTN0)) { - case BTN0: - // Run the fractal examples. - fractal_test(&lcd); - break; - case BTN1: - lcd_st7735_puts(&lcd, (LCD_Point){.x = 5, .y = 80}, "Button 1 pressed"); - timer_delay(1000); - break; - case BTN2: + // Show the main menu. + const char *items[] = { + "0. Fractal", + "1. CoreMark", + }; + Menu_t main_menu = { + .title = "Main menu", + .color = BGRColorBlue, + .selected_color = BGRColorRed, + .background = BGRColorWhite, + .items_count = sizeof(items) / sizeof(items[0]), + .items = items, + }; + + bool repaint = true; + size_t selected = 0; + char line_buffer[21]; + + // Boot countdown when no button is pressed. Value 0 indicates the countdown is dismissed. + int boot_countdown_sec = 3; + +menu: + while (1) { + if (repaint) { + repaint = false; + lcd_st7735_clean(&lcd); + lcd_show_menu(&lcd, &main_menu, selected); + + if (boot_countdown_sec != 0) { + lcd_st7735_puts(&lcd, (LCD_Point){.x = 8, .y = 102}, "Defaulting to item"); + strcpy(line_buffer, "0 after 0 seconds"); + line_buffer[strlen("0 after ")] += boot_countdown_sec; + lcd_st7735_puts(&lcd, (LCD_Point){.x = 12, .y = 115}, line_buffer); + } + } + + switch (scan_buttons(1000)) { + case BTN_UP: + if (selected > 0) { + selected--; + } else { + selected = main_menu.items_count - 1; + } + repaint = true; + boot_countdown_sec = 0; break; - case BTN3: + case BTN_DOWN: + if (selected < main_menu.items_count - 1) { + selected++; + } else { + selected = 0; + } + repaint = true; + boot_countdown_sec = 0; break; + // Left/right buttons currently don't do anything. + case BTN_LEFT: + case BTN_RIGHT: + continue; + + case BTN_CLICK: + goto boot; + default: + if (boot_countdown_sec == 0) { + continue; + } + + if (--boot_countdown_sec == 0) { + goto boot; + } + + repaint = true; break; } - } while (1); + }; + +boot: + switch (selected) { + case 0: + fractal_test(&lcd); + break; + + case 1: + // Switch to a smaller font for the coremark. + lcd_st7735_set_font(&lcd, &m3x6_16ptFont); + + fbcon_init(&lcd); + + // Trick to make the coremark appear at bottom. + fbcon_putstr("\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + + // Clean the screen and draw "CoreMark" as title bar. + lcd_st7735_clean(&lcd); + lcd_st7735_fill_rectangle( + &lcd, + (LCD_rectangle){.origin = {.x = 0, .y = 0}, .width = lcd.parent.width, .height = lcd.parent.font->height + 2}, + BGRColorBlue); + lcd_st7735_set_font_colors(&lcd, BGRColorBlue, BGRColorWhite); + lcd_println(&lcd, "CoreMark", alined_center, (LCD_Point){.x = 0, .y = 1}); + lcd_st7735_set_font_colors(&lcd, BGRColorWhite, BGRColorBlue); + + int coremark_main(); + coremark_main(); + break; + } + + // Wait until navigation button is clicked. + while (scan_buttons(1000) != BTN_CLICK) + ; + + // Return to the main menu. + repaint = true; + goto menu; + + return 0; } -static Buttons_t scan_buttons(uint32_t timeout, Buttons_t def) { - do { - // Sample buttons (debounced). - const uint32_t in_val = read_gpio(GPIO_IN_DBNC) & 0xf; +static Buttons_t scan_buttons(uint32_t timeout) { + while (true) { + // Sample navigation buttons (debounced). + uint32_t in_val = read_gpio(GPIO_IN_DBNC) & 0x1f; if (in_val == 0) { // No button pressed, so delay for 20ms and then try again, unless the timeout is reached. const uint32_t poll_delay = 20; timer_delay(poll_delay); if (timeout < poll_delay) { - // Timeout reached, return default button. - return def; + // Timeout reached, return 0. + return 0; } else { // Timeout not reached yet, decrease it and try again. timeout -= poll_delay; } - } else { - // Some button pressed, return the sampled value. - return (Buttons_t)in_val; + continue; } - } while (1); + + // Some button pressed. + // Find the most significant bit set. + in_val |= in_val >> 1; + in_val |= in_val >> 2; + in_val |= in_val >> 4; + in_val = (in_val >> 1) + 1; + + // Wait until the button is released to avoid an event being triggered multiple times. + while (read_gpio(GPIO_IN_DBNC) & in_val) + ; + + return in_val; + } } static void fractal_test(St7735Context *lcd) { @@ -152,13 +247,9 @@ static void fractal_test(St7735Context *lcd) { } static uint32_t spi_write(void *handle, uint8_t *data, size_t len) { - const uint32_t data_sent = len; - while (len--) { - spi_send_byte_blocking(handle, *data++); - } - while ((spi_get_status(handle) & spi_status_fifo_empty) != spi_status_fifo_empty) - ; - return data_sent; + spi_tx(handle, data, len); + spi_wait_idle(handle); + return len; } static uint32_t gpio_write(void *handle, bool cs, bool dc) { @@ -169,7 +260,7 @@ static uint32_t gpio_write(void *handle, bool cs, bool dc) { static void timer_delay(uint32_t ms) { // Configure timer to trigger every 1 ms - timer_enable(50000); + timer_enable(SYSCLK_FREQ / 1000); uint32_t timeout = get_elapsed_time() + ms; while (get_elapsed_time() < timeout) { asm volatile("wfi"); diff --git a/sw/common/link.ld b/sw/common/link.ld index d1ed3e19..98613709 100644 --- a/sw/common/link.ld +++ b/sw/common/link.ld @@ -6,9 +6,9 @@ OUTPUT_ARCH(riscv) MEMORY { - /* 60 KiB should be enough for anybody... */ - ram : ORIGIN = 0x00100000, LENGTH = 0xE000 /* 56 KiB */ - stack : ORIGIN = 0x0010E000, LENGTH = 0x2000 /* 4 KiB */ + /* 124 KiB should be enough for anybody... */ + ram : ORIGIN = 0x00100000, LENGTH = 0x1E000 /* 124 KiB */ + stack : ORIGIN = 0x0011E000, LENGTH = 0x02000 /* 4 KiB */ } /* Stack information variables */ diff --git a/vendor/display_drivers.lock.hjson b/vendor/display_drivers.lock.hjson index ecbd45e7..99bd8cb5 100644 --- a/vendor/display_drivers.lock.hjson +++ b/vendor/display_drivers.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/engdoreis/display_drivers.git - rev: fc08092cfd80b1a6cb401bb4e3b5cf0ab4de46c6 + rev: d0ea11852c43bd7db2ba9316e4170b8297a1d6a0 } } diff --git a/vendor/display_drivers.vendor.hjson b/vendor/display_drivers.vendor.hjson index 795fc7f6..c8e43b71 100644 --- a/vendor/display_drivers.vendor.hjson +++ b/vendor/display_drivers.vendor.hjson @@ -10,4 +10,8 @@ url: "https://github.com/engdoreis/display_drivers.git", rev: "main", } + + exclude_from_upstream: [ + "tools", + ] } diff --git a/vendor/display_drivers/core/lcd_base.c b/vendor/display_drivers/core/lcd_base.c index f1a7b74f..ec3c3c23 100644 --- a/vendor/display_drivers/core/lcd_base.c +++ b/vendor/display_drivers/core/lcd_base.c @@ -16,7 +16,7 @@ Result LCD_Init(LCD_Context *ctx, LCD_Interface *interface, uint32_t width, uint inline uint16_t LCD_rgb24_to_bgr565(uint32_t rgb) { uint8_t b = (rgb >> 16) & 0xFF, g = (rgb >> 8) & 0xFF, r = rgb & 0xFF; - uint16_t color = ((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3); + uint16_t color = (uint16_t)(((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3)); return ENDIANESS_TO_HALF_WORD(color); } @@ -28,8 +28,8 @@ inline uint16_t LCD_rgb565_to_bgr565(const uint8_t rgb[2]) { // | half word | // |b b b b b g g g g g g r r r r r |5f0d // |15 11 5 0 | - uint8_t b = (rgb[1] >> 3), g = (rgb[1] & 0x7) << 3 | rgb[0] >> 5, r = rgb[0] & 0x1F; - uint16_t color = b | g << 5 | r << 11; + uint8_t b = (uint8_t)(rgb[1] >> 3), g = (uint8_t)((rgb[1] & 0x7) << 3 | rgb[0] >> 5), r = (uint8_t)(rgb[0] & 0x1F); + uint16_t color = (uint16_t)(b | g << 5 | r << 11); return ENDIANESS_TO_HALF_WORD(color); } diff --git a/vendor/display_drivers/core/lcd_base.h b/vendor/display_drivers/core/lcd_base.h index f801fc1c..e03c01b9 100644 --- a/vendor/display_drivers/core/lcd_base.h +++ b/vendor/display_drivers/core/lcd_base.h @@ -25,7 +25,7 @@ #define MAX(_A, _B) _A < _B ? _B : _A typedef enum { - LCD_Rotate_0 = 0, + LCD_Rotate0 = 0, LCD_Rotate90, LCD_Rotate180, LCD_Rotate270, @@ -33,7 +33,7 @@ typedef enum { // TODO: Define error codes. typedef struct Result_st { - uint32_t code; /*!< */ + int32_t code; /*!< */ } Result; /** diff --git a/vendor/display_drivers/core/m3x6_16pt.c b/vendor/display_drivers/core/m3x6_16pt.c new file mode 100644 index 00000000..d17ad1c9 --- /dev/null +++ b/vendor/display_drivers/core/m3x6_16pt.c @@ -0,0 +1,1070 @@ +// Copyright 2024 Gary Guo. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This is a rasterized version of the m3x6 font. +// The m3x6 font is created by Daniel Linssen and is free to use with attribution. +// The original TTF font can be found at https://managore.itch.io/m3x6 + +#include "m3x6_16pt.h" + +// Character bitmaps for m3x6 16pt +const unsigned char m3x6_16ptBitmaps[] = { + // @32 ' ' (5 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @33 '!' (2 pixels wide) + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x00, // + 0x01, // # + 0x00, // + 0x00, // + + // @34 '"' (4 pixels wide) + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @35 '#' (6 pixels wide) + 0x0a, // # # + 0x1f, // ##### + 0x0a, // # # + 0x0a, // # # + 0x1f, // ##### + 0x0a, // # # + 0x00, // + 0x00, // + + // @36 '$' (4 pixels wide) + 0x02, // # + 0x06, // ## + 0x01, // # + 0x07, // ### + 0x04, // # + 0x03, // ## + 0x02, // # + 0x00, // + + // @37 '%' (4 pixels wide) + 0x00, // + 0x01, // # + 0x04, // # + 0x02, // # + 0x01, // # + 0x04, // # + 0x00, // + 0x00, // + + // @38 '&' (6 pixels wide) + 0x02, // # + 0x05, // # # + 0x02, // # + 0x15, // # # # + 0x09, // # # + 0x16, // ## # + 0x00, // + 0x00, // + + // @39 ''' (2 pixels wide) + 0x01, // # + 0x01, // # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @40 '(' (3 pixels wide) + 0x02, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x02, // # + 0x00, // + + // @41 ')' (3 pixels wide) + 0x01, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x01, // # + 0x00, // + + // @42 '*' (4 pixels wide) + 0x05, // # # + 0x02, // # + 0x05, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @43 '+' (4 pixels wide) + 0x00, // + 0x00, // + 0x02, // # + 0x07, // ### + 0x02, // # + 0x00, // + 0x00, // + 0x00, // + + // @44 ',' (2 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x01, // # + 0x01, // # + 0x00, // + + // @45 '-' (4 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x07, // ### + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @46 '.' (2 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x01, // # + 0x00, // + 0x00, // + + // @47 '/' (4 pixels wide) + 0x04, // # + 0x04, // # + 0x02, // # + 0x02, // # + 0x01, // # + 0x01, // # + 0x00, // + 0x00, // + + // @48 '0' (4 pixels wide) + 0x06, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x03, // ## + 0x00, // + 0x00, // + + // @49 '1' (4 pixels wide) + 0x02, // # + 0x03, // ## + 0x02, // # + 0x02, // # + 0x02, // # + 0x07, // ### + 0x00, // + 0x00, // + + // @50 '2' (4 pixels wide) + 0x03, // ## + 0x04, // # + 0x04, // # + 0x02, // # + 0x01, // # + 0x07, // ### + 0x00, // + 0x00, // + + // @51 '3' (4 pixels wide) + 0x03, // ## + 0x04, // # + 0x03, // ## + 0x04, // # + 0x04, // # + 0x03, // ## + 0x00, // + 0x00, // + + // @52 '4' (4 pixels wide) + 0x05, // # # + 0x05, // # # + 0x06, // ## + 0x04, // # + 0x04, // # + 0x04, // # + 0x00, // + 0x00, // + + // @53 '5' (4 pixels wide) + 0x07, // ### + 0x01, // # + 0x03, // ## + 0x04, // # + 0x04, // # + 0x03, // ## + 0x00, // + 0x00, // + + // @54 '6' (4 pixels wide) + 0x06, // ## + 0x01, // # + 0x03, // ## + 0x05, // # # + 0x05, // # # + 0x06, // ## + 0x00, // + 0x00, // + + // @55 '7' (4 pixels wide) + 0x07, // ### + 0x04, // # + 0x04, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x00, // + 0x00, // + + // @56 '8' (4 pixels wide) + 0x06, // ## + 0x05, // # # + 0x02, // # + 0x05, // # # + 0x05, // # # + 0x03, // ## + 0x00, // + 0x00, // + + // @57 '9' (4 pixels wide) + 0x03, // ## + 0x05, // # # + 0x05, // # # + 0x06, // ## + 0x04, // # + 0x03, // ## + 0x00, // + 0x00, // + + // @58 ':' (2 pixels wide) + 0x00, // + 0x00, // + 0x01, // # + 0x00, // + 0x00, // + 0x01, // # + 0x00, // + 0x00, // + + // @59 ';' (2 pixels wide) + 0x00, // + 0x00, // + 0x01, // # + 0x00, // + 0x00, // + 0x01, // # + 0x01, // # + 0x00, // + + // @60 '<' (4 pixels wide) + 0x00, // + 0x04, // # + 0x02, // # + 0x01, // # + 0x02, // # + 0x04, // # + 0x00, // + 0x00, // + + // @61 '=' (4 pixels wide) + 0x00, // + 0x00, // + 0x07, // ### + 0x00, // + 0x07, // ### + 0x00, // + 0x00, // + 0x00, // + + // @62 '>' (4 pixels wide) + 0x00, // + 0x01, // # + 0x02, // # + 0x04, // # + 0x02, // # + 0x01, // # + 0x00, // + 0x00, // + + // @63 '?' (4 pixels wide) + 0x03, // ## + 0x04, // # + 0x04, // # + 0x02, // # + 0x00, // + 0x02, // # + 0x00, // + 0x00, // + + // @64 '@' (6 pixels wide) + 0x0e, // ### + 0x19, // # ## + 0x15, // # # # + 0x1d, // # ### + 0x01, // # + 0x1e, // #### + 0x00, // + 0x00, // + + // @65 'A' (4 pixels wide) + 0x06, // ## + 0x05, // # # + 0x07, // ### + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + + // @66 'B' (4 pixels wide) + 0x03, // ## + 0x05, // # # + 0x07, // ### + 0x05, // # # + 0x05, // # # + 0x07, // ### + 0x00, // + 0x00, // + + // @67 'C' (4 pixels wide) + 0x06, // ## + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x07, // ### + 0x00, // + 0x00, // + + // @68 'D' (4 pixels wide) + 0x03, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x03, // ## + 0x00, // + 0x00, // + + // @69 'E' (4 pixels wide) + 0x07, // ### + 0x01, // # + 0x03, // ## + 0x01, // # + 0x01, // # + 0x07, // ### + 0x00, // + 0x00, // + + // @70 'F' (4 pixels wide) + 0x06, // ## + 0x01, // # + 0x03, // ## + 0x01, // # + 0x01, // # + 0x01, // # + 0x00, // + 0x00, // + + // @71 'G' (4 pixels wide) + 0x06, // ## + 0x01, // # + 0x01, // # + 0x05, // # # + 0x05, // # # + 0x07, // ### + 0x00, // + 0x00, // + + // @72 'H' (4 pixels wide) + 0x05, // # # + 0x05, // # # + 0x07, // ### + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + + // @73 'I' (4 pixels wide) + 0x07, // ### + 0x02, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x07, // ### + 0x00, // + 0x00, // + + // @74 'J' (4 pixels wide) + 0x07, // ### + 0x04, // # + 0x04, // # + 0x04, // # + 0x04, // # + 0x03, // ## + 0x00, // + 0x00, // + + // @75 'K' (4 pixels wide) + 0x05, // # # + 0x05, // # # + 0x03, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + + // @76 'L' (4 pixels wide) + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x07, // ### + 0x00, // + 0x00, // + + // @77 'M' (6 pixels wide) + 0x0f, // #### + 0x15, // # # # + 0x15, // # # # + 0x15, // # # # + 0x15, // # # # + 0x11, // # # + 0x00, // + 0x00, // + + // @78 'N' (4 pixels wide) + 0x03, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + + // @79 'O' (4 pixels wide) + 0x06, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x03, // ## + 0x00, // + 0x00, // + + // @80 'P' (4 pixels wide) + 0x07, // ### + 0x05, // # # + 0x03, // ## + 0x01, // # + 0x01, // # + 0x01, // # + 0x00, // + 0x00, // + + // @81 'Q' (4 pixels wide) + 0x06, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x03, // ## + 0x04, // # + 0x00, // + + // @82 'R' (4 pixels wide) + 0x07, // ### + 0x05, // # # + 0x03, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + + // @83 'S' (4 pixels wide) + 0x06, // ## + 0x01, // # + 0x07, // ### + 0x04, // # + 0x04, // # + 0x03, // ## + 0x00, // + 0x00, // + + // @84 'T' (4 pixels wide) + 0x07, // ### + 0x02, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x00, // + 0x00, // + + // @85 'U' (4 pixels wide) + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x07, // ### + 0x00, // + 0x00, // + + // @86 'V' (4 pixels wide) + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x02, // # + 0x00, // + 0x00, // + + // @87 'W' (6 pixels wide) + 0x11, // # # + 0x15, // # # # + 0x15, // # # # + 0x15, // # # # + 0x15, // # # # + 0x0a, // # # + 0x00, // + 0x00, // + + // @88 'X' (4 pixels wide) + 0x05, // # # + 0x05, // # # + 0x02, // # + 0x02, // # + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + + // @89 'Y' (4 pixels wide) + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x02, // # + 0x02, // # + 0x02, // # + 0x00, // + 0x00, // + + // @90 'Z' (4 pixels wide) + 0x07, // ### + 0x04, // # + 0x02, // # + 0x02, // # + 0x01, // # + 0x07, // ### + 0x00, // + 0x00, // + + // @91 '[' (3 pixels wide) + 0x03, // ## + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x03, // ## + 0x00, // + + // @92 '\' (4 pixels wide) + 0x01, // # + 0x01, // # + 0x02, // # + 0x02, // # + 0x04, // # + 0x04, // # + 0x00, // + 0x00, // + + // @93 ']' (3 pixels wide) + 0x03, // ## + 0x02, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x03, // ## + 0x00, // + + // @94 '^' (4 pixels wide) + 0x00, // + 0x02, // # + 0x05, // # # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @95 '_' (4 pixels wide) + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x07, // ### + 0x00, // + 0x00, // + + // @96 '`' (2 pixels wide) + 0x01, // # + 0x01, // # + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + 0x00, // + + // @97 'a' (4 pixels wide) + 0x00, // + 0x03, // ## + 0x04, // # + 0x06, // ## + 0x05, // # # + 0x07, // ### + 0x00, // + 0x00, // + + // @98 'b' (4 pixels wide) + 0x01, // # + 0x03, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x07, // ### + 0x00, // + 0x00, // + + // @99 'c' (4 pixels wide) + 0x00, // + 0x06, // ## + 0x01, // # + 0x01, // # + 0x01, // # + 0x07, // ### + 0x00, // + 0x00, // + + // @100 'd' (4 pixels wide) + 0x04, // # + 0x06, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x07, // ### + 0x00, // + 0x00, // + + // @101 'e' (4 pixels wide) + 0x00, // + 0x06, // ## + 0x05, // # # + 0x07, // ### + 0x01, // # + 0x06, // ## + 0x00, // + 0x00, // + + // @102 'f' (4 pixels wide) + 0x04, // # + 0x02, // # + 0x02, // # + 0x07, // ### + 0x02, // # + 0x02, // # + 0x00, // + 0x00, // + + // @103 'g' (4 pixels wide) + 0x00, // + 0x06, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x07, // ### + 0x04, // # + 0x03, // ## + + // @104 'h' (4 pixels wide) + 0x01, // # + 0x03, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + + // @105 'i' (2 pixels wide) + 0x01, // # + 0x00, // + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x00, // + 0x00, // + + // @106 'j' (3 pixels wide) + 0x02, // # + 0x00, // + 0x02, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x02, // # + 0x01, // # + + // @107 'k' (4 pixels wide) + 0x01, // # + 0x01, // # + 0x05, // # # + 0x03, // ## + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + + // @108 'l' (3 pixels wide) + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x02, // # + 0x00, // + 0x00, // + + // @109 'm' (6 pixels wide) + 0x00, // + 0x0b, // ## # + 0x15, // # # # + 0x15, // # # # + 0x15, // # # # + 0x15, // # # # + 0x00, // + 0x00, // + + // @110 'n' (4 pixels wide) + 0x00, // + 0x03, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + + // @111 'o' (4 pixels wide) + 0x00, // + 0x06, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x03, // ## + 0x00, // + 0x00, // + + // @112 'p' (4 pixels wide) + 0x00, // + 0x07, // ### + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x03, // ## + 0x01, // # + 0x01, // # + + // @113 'q' (4 pixels wide) + 0x00, // + 0x06, // ## + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x07, // ### + 0x04, // # + 0x04, // # + + // @114 'r' (4 pixels wide) + 0x00, // + 0x06, // ## + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x00, // + 0x00, // + + // @115 's' (4 pixels wide) + 0x00, // + 0x06, // ## + 0x01, // # + 0x07, // ### + 0x04, // # + 0x03, // ## + 0x00, // + 0x00, // + + // @116 't' (4 pixels wide) + 0x02, // # + 0x02, // # + 0x07, // ### + 0x02, // # + 0x02, // # + 0x02, // # + 0x00, // + 0x00, // + + // @117 'u' (4 pixels wide) + 0x00, // + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x07, // ### + 0x00, // + 0x00, // + + // @118 'v' (4 pixels wide) + 0x00, // + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x02, // # + 0x00, // + 0x00, // + + // @119 'w' (6 pixels wide) + 0x00, // + 0x11, // # # + 0x15, // # # # + 0x15, // # # # + 0x15, // # # # + 0x0a, // # # + 0x00, // + 0x00, // + + // @120 'x' (4 pixels wide) + 0x00, // + 0x05, // # # + 0x05, // # # + 0x02, // # + 0x05, // # # + 0x05, // # # + 0x00, // + 0x00, // + + // @121 'y' (4 pixels wide) + 0x00, // + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x05, // # # + 0x06, // ## + 0x04, // # + 0x03, // ## + + // @122 'z' (4 pixels wide) + 0x00, // + 0x07, // ### + 0x04, // # + 0x02, // # + 0x01, // # + 0x07, // ### + 0x00, // + 0x00, // + + // @123 '{' (4 pixels wide) + 0x04, // # + 0x02, // # + 0x02, // # + 0x01, // # + 0x02, // # + 0x02, // # + 0x04, // # + 0x00, // + + // @124 '|' (2 pixels wide) + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x01, // # + 0x00, // + + // @125 '}' (4 pixels wide) + 0x01, // # + 0x02, // # + 0x02, // # + 0x04, // # + 0x02, // # + 0x02, // # + 0x01, // # + 0x00, // + + // @126 '~' (4 pixels wide) + 0x00, // + 0x00, // + 0x06, // ## + 0x03, // ## + 0x00, // + 0x00, // + 0x00, // + 0x00, // +}; + +// Character descriptors for m3x6 16pt +const FontCharInfo m3x6_16ptDescriptors[] = { + { 5, 0 }, // ' ' + { 2, 8 }, // '!' + { 4, 16 }, // '"' + { 6, 24 }, // '#' + { 4, 32 }, // '$' + { 4, 40 }, // '%' + { 6, 48 }, // '&' + { 2, 56 }, // ''' + { 3, 64 }, // '(' + { 3, 72 }, // ')' + { 4, 80 }, // '*' + { 4, 88 }, // '+' + { 2, 96 }, // ',' + { 4, 104 }, // '-' + { 2, 112 }, // '.' + { 4, 120 }, // '/' + { 4, 128 }, // '0' + { 4, 136 }, // '1' + { 4, 144 }, // '2' + { 4, 152 }, // '3' + { 4, 160 }, // '4' + { 4, 168 }, // '5' + { 4, 176 }, // '6' + { 4, 184 }, // '7' + { 4, 192 }, // '8' + { 4, 200 }, // '9' + { 2, 208 }, // ':' + { 2, 216 }, // ';' + { 4, 224 }, // '<' + { 4, 232 }, // '=' + { 4, 240 }, // '>' + { 4, 248 }, // '?' + { 6, 256 }, // '@' + { 4, 264 }, // 'A' + { 4, 272 }, // 'B' + { 4, 280 }, // 'C' + { 4, 288 }, // 'D' + { 4, 296 }, // 'E' + { 4, 304 }, // 'F' + { 4, 312 }, // 'G' + { 4, 320 }, // 'H' + { 4, 328 }, // 'I' + { 4, 336 }, // 'J' + { 4, 344 }, // 'K' + { 4, 352 }, // 'L' + { 6, 360 }, // 'M' + { 4, 368 }, // 'N' + { 4, 376 }, // 'O' + { 4, 384 }, // 'P' + { 4, 392 }, // 'Q' + { 4, 400 }, // 'R' + { 4, 408 }, // 'S' + { 4, 416 }, // 'T' + { 4, 424 }, // 'U' + { 4, 432 }, // 'V' + { 6, 440 }, // 'W' + { 4, 448 }, // 'X' + { 4, 456 }, // 'Y' + { 4, 464 }, // 'Z' + { 3, 472 }, // '[' + { 4, 480 }, // '\' + { 3, 488 }, // ']' + { 4, 496 }, // '^' + { 4, 504 }, // '_' + { 2, 512 }, // '`' + { 4, 520 }, // 'a' + { 4, 528 }, // 'b' + { 4, 536 }, // 'c' + { 4, 544 }, // 'd' + { 4, 552 }, // 'e' + { 4, 560 }, // 'f' + { 4, 568 }, // 'g' + { 4, 576 }, // 'h' + { 2, 584 }, // 'i' + { 3, 592 }, // 'j' + { 4, 600 }, // 'k' + { 3, 608 }, // 'l' + { 6, 616 }, // 'm' + { 4, 624 }, // 'n' + { 4, 632 }, // 'o' + { 4, 640 }, // 'p' + { 4, 648 }, // 'q' + { 4, 656 }, // 'r' + { 4, 664 }, // 's' + { 4, 672 }, // 't' + { 4, 680 }, // 'u' + { 4, 688 }, // 'v' + { 6, 696 }, // 'w' + { 4, 704 }, // 'x' + { 4, 712 }, // 'y' + { 4, 720 }, // 'z' + { 4, 728 }, // '{' + { 2, 736 }, // '|' + { 4, 744 }, // '}' + { 4, 752 }, // '~' +}; + +// Font information for m3x6 16pt +const Font m3x6_16ptFont = { + 8, // Character height + ' ', // Start character + '~', // End character + m3x6_16ptDescriptors, // Character descriptor array + m3x6_16ptBitmaps, // Character bitmap array +}; diff --git a/vendor/display_drivers/core/m3x6_16pt.h b/vendor/display_drivers/core/m3x6_16pt.h new file mode 100644 index 00000000..29b9eef1 --- /dev/null +++ b/vendor/display_drivers/core/m3x6_16pt.h @@ -0,0 +1,17 @@ +// Copyright (c) 2024 Gary Guo. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef M3X6_16PT_H_ +#define M3X6_16PT_H_ + +#include + +#include "font.h" + +// Font data for Lucida Console 16pt +extern const unsigned char m3x6_16ptBitmaps[]; +extern const Font m3x6_16ptFont; +extern const FontCharInfo m3x6_16ptDescriptors[]; + +#endif /* M3X6_16PT_H_ */ diff --git a/vendor/display_drivers/st7735/lcd_st7735.c b/vendor/display_drivers/st7735/lcd_st7735.c index 352b7bc4..a1470307 100644 --- a/vendor/display_drivers/st7735/lcd_st7735.c +++ b/vendor/display_drivers/st7735/lcd_st7735.c @@ -51,16 +51,16 @@ static void run_script(St7735Context *ctx, const uint8_t *addr) { } } -static void set_address(St7735Context *ctx, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) { +static void set_address(St7735Context *ctx, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1) { uint32_t coordinate = 0; - coordinate = x0 << 8 | x1 << 24; + coordinate = (uint32_t)(x0 << 8 | x1 << 24); write_command(ctx, ST7735_CASET); // Column addr set ctx->parent.interface->gpio_write(ctx->parent.interface->handle, false, true); write_buffer(ctx, (uint8_t *)&coordinate, sizeof(coordinate)); ctx->parent.interface->gpio_write(ctx->parent.interface->handle, true, true); - coordinate = y0 << 8 | y1 << 24; + coordinate = (uint32_t)(y0 << 8 | y1 << 24); write_command(ctx, ST7735_RASET); // Row addr set ctx->parent.interface->gpio_write(ctx->parent.interface->handle, false, true); write_buffer(ctx, (uint8_t *)&coordinate, sizeof(coordinate)); @@ -78,7 +78,9 @@ static void write_register(St7735Context *ctx, uint8_t addr, uint8_t value) { Result lcd_st7735_init(St7735Context *ctx, LCD_Interface *interface) { LCD_Init(&ctx->parent, interface, 160, 128); - int result = 0; + lcd_st7735_set_font_colors(ctx, 0xFFFFFF, 0x000000); + + int32_t result = 0; run_script(ctx, init_script_b); run_script(ctx, init_script_r); @@ -89,10 +91,10 @@ Result lcd_st7735_init(St7735Context *ctx, LCD_Interface *interface) { Result lcd_st7735_set_orientation(St7735Context *ctx, LCD_Orientation orientation) { const static uint8_t st7735_orientation_map[] = { - 0, + ST77_MADCTL_MY | ST77_MADCTL_MV, ST77_MADCTL_MX | ST77_MADCTL_MV, ST77_MADCTL_MX | ST77_MADCTL_MY, - ST77_MADCTL_MY | ST77_MADCTL_MV, + 0, }; write_register(ctx, ST7735_MADCTL, st7735_orientation_map[orientation] | ST77_MADCTL_RGB); @@ -102,8 +104,7 @@ Result lcd_st7735_set_orientation(St7735Context *ctx, LCD_Orientation orientatio Result lcd_st7735_clean(St7735Context *ctx) { size_t w, h; lcd_st7735_get_resolution(ctx, &h, &w); - lcd_st7735_fill_rectangle(ctx, (LCD_rectangle){.origin = {.x = 0, .y = 0}, .width = w, .height = h}, 0xffffff); - return (Result){.code = 0}; + return lcd_st7735_fill_rectangle(ctx, (LCD_rectangle){.origin = {.x = 0, .y = 0}, .width = w, .height = h}, 0xffffff); } Result lcd_st7735_draw_pixel(St7735Context *ctx, LCD_Point pixel, uint32_t color) { @@ -171,15 +172,15 @@ Result lcd_st7735_fill_rectangle(St7735Context *ctx, LCD_rectangle rectangle, ui return (Result){.code = -1}; } - uint16_t w = MIN(rectangle.origin.x + rectangle.width, ctx->parent.width) - rectangle.origin.x; - uint16_t h = MIN(rectangle.origin.y + rectangle.height, ctx->parent.height) - rectangle.origin.y; + uint16_t w = (uint16_t)(MIN(rectangle.origin.x + rectangle.width, ctx->parent.width) - rectangle.origin.x); + uint16_t h = (uint16_t)(MIN(rectangle.origin.y + rectangle.height, ctx->parent.height) - rectangle.origin.y); color = LCD_rgb24_to_bgr565(color); // Create an array with the pixes for the lines. uint16_t row[w]; for (int i = 0; i < w; ++i) { - row[i] = color; + row[i] = (uint16_t)color; } set_address(ctx, rectangle.origin.x, rectangle.origin.y, rectangle.origin.x + w - 1, rectangle.origin.y + h - 1); @@ -203,9 +204,10 @@ Result lcd_st7735_putchar(St7735Context *ctx, LCD_Point origin, char character) const uint8_t *char_bitmap = &font->bitmap_table[char_descriptor->position - 1]; for (int row = 0; row < font->height; row++) { for (int column = 0; column < char_descriptor->width; column++) { - uint8_t bit = column % 8; + uint8_t bit = (uint8_t)(column % 8); char_bitmap += (uint8_t)(bit == 0); - buffer[column] = (*char_bitmap & (0x01 << bit)) ? ctx->parent.foreground_color : ctx->parent.background_color; + buffer[column] = + (uint16_t)((*char_bitmap & (0x01 << bit)) ? ctx->parent.foreground_color : ctx->parent.background_color); } write_buffer(ctx, (uint8_t *)buffer, sizeof(buffer)); } @@ -214,10 +216,10 @@ Result lcd_st7735_putchar(St7735Context *ctx, LCD_Point origin, char character) } Result lcd_st7735_puts(St7735Context *ctx, LCD_Point pos, const char *text) { - int count = 0; - int width = ctx->parent.font->descriptor_table[text[0] - ctx->parent.font->startCharacter].width; + size_t count = 0; while (*text) { + uint32_t width = ctx->parent.font->descriptor_table[*text - ctx->parent.font->startCharacter].width; if ((pos.x + width) > ctx->parent.width) { return (Result){.code = 0}; } @@ -230,7 +232,7 @@ Result lcd_st7735_puts(St7735Context *ctx, LCD_Point pos, const char *text) { count++; } - return (Result){.code = count}; // number of chars printed + return (Result){.code = (int32_t)count}; // number of chars printed } Result lcd_st7735_draw_bgr(St7735Context *ctx, LCD_rectangle rectangle, const uint8_t *bgr) { @@ -239,7 +241,7 @@ Result lcd_st7735_draw_bgr(St7735Context *ctx, LCD_rectangle rectangle, const ui ctx->parent.interface->gpio_write(ctx->parent.interface->handle, false, true); for (int i = 0; i < rectangle.width * rectangle.height * 3; i += 3) { - uint16_t color = LCD_rgb24_to_bgr565(bgr[i] << 16 | bgr[i + 1] << 8 | bgr[i + 2]); + uint16_t color = LCD_rgb24_to_bgr565((uint32_t)(bgr[i] << 16 | bgr[i + 1] << 8 | bgr[i + 2])); write_buffer(ctx, (uint8_t *)&color, 2); } ctx->parent.interface->gpio_write(ctx->parent.interface->handle, true, true); diff --git a/vendor/display_drivers/st7735/lcd_st7735.h b/vendor/display_drivers/st7735/lcd_st7735.h index 88ec53b4..17b6c648 100644 --- a/vendor/display_drivers/st7735/lcd_st7735.h +++ b/vendor/display_drivers/st7735/lcd_st7735.h @@ -6,6 +6,8 @@ #ifndef DISPLAY_DRIVERS_ST7735_ST7735_H_ #define DISPLAY_DRIVERS_ST7735_ST7735_H_ +#include + #include "../core/font.h" #include "../core/lcd_base.h" #include "lcd_st7735_cmds.h" @@ -16,6 +18,8 @@ */ typedef struct stSt7735Context { LCD_Context parent; /*!< Base context*/ + uint32_t rgb_background; + uint32_t rgb_foreground; } St7735Context; /** @@ -166,6 +170,8 @@ inline Result lcd_st7735_set_font(St7735Context *ctx, const Font *font) { return * @return Result of the operation. */ inline Result lcd_st7735_set_font_colors(St7735Context *ctx, uint32_t background_color, uint32_t foreground_color) { + ctx->rgb_background = background_color; + ctx->rgb_foreground = foreground_color; return LCD_set_font_colors(&ctx->parent, LCD_rgb24_to_bgr565(background_color), LCD_rgb24_to_bgr565(foreground_color)); } diff --git a/vendor/display_drivers/st7735/lcd_st7735_cmds.h b/vendor/display_drivers/st7735/lcd_st7735_cmds.h index e5e05ada..50d45ba9 100644 --- a/vendor/display_drivers/st7735/lcd_st7735_cmds.h +++ b/vendor/display_drivers/st7735/lcd_st7735_cmds.h @@ -8,7 +8,7 @@ // ----> https://www.adafruit.com/product/2088 // as well as Adafruit raw 1.8" TFT display // ----> http://www.adafruit.com/products/618 - + // Check out the links above for our tutorials and wiring diagrams. // These displays use SPI to communicate, 4 or 5 pins are required to // interface (RST is optional). @@ -20,7 +20,11 @@ // Written by Limor Fried/Ladyada for Adafruit Industries. // MIT license, all text above must be included in any redistribution. -// Recent Arduino IDE releases include the Library Manager for easy installation. Otherwise, to download, click the DOWNLOAD ZIP button, uncompress and rename the uncompressed folder Adafruit_ST7735. Confirm that the Adafruit_ST7735 folder contains Adafruit_ST7735.cpp, Adafruit_ST7735.h and related source files. Place the Adafruit_ST7735 library folder your ArduinoSketchFolder/Libraries/ folder. You may need to create the Libraries subfolder if its your first library. Restart the IDE. +// Recent Arduino IDE releases include the Library Manager for easy installation. Otherwise, to download, click the +// DOWNLOAD ZIP button, uncompress and rename the uncompressed folder Adafruit_ST7735. Confirm that the Adafruit_ST7735 +// folder contains Adafruit_ST7735.cpp, Adafruit_ST7735.h and related source files. Place the Adafruit_ST7735 library +// folder your ArduinoSketchFolder/Libraries/ folder. You may need to create the Libraries subfolder if its your first +// library. Restart the IDE. // Also requires the Adafruit_GFX library for Arduino. @@ -68,13 +72,13 @@ typedef enum { } ST7735_Cmd; typedef enum { - ST77_MADCTL_MX = 0x01 << 7, //Column Address Order - ST77_MADCTL_MV = 0x01 << 6, //Row/Column Exchange - ST77_MADCTL_MY = 0x01 << 5, //Row Address Order + ST77_MADCTL_MX = 0x01 << 7, // Column Address Order + ST77_MADCTL_MV = 0x01 << 6, // Row/Column Exchange + ST77_MADCTL_MY = 0x01 << 5, // Row Address Order ST77_MADCTL_ML = 0x01 << 4, ST77_MADCTL_RGB = 0x01 << 3, ST77_MADCTL_MH = 0x01 << 2 -}ST77_MADCTL_Bits; +} ST77_MADCTL_Bits; // Color definitions typedef enum { diff --git a/vendor/display_drivers/st7735/lcd_st7735_init.h b/vendor/display_drivers/st7735/lcd_st7735_init.h index 85918651..7664f7b7 100644 --- a/vendor/display_drivers/st7735/lcd_st7735_init.h +++ b/vendor/display_drivers/st7735/lcd_st7735_init.h @@ -9,7 +9,7 @@ // ----> https://www.adafruit.com/product/2088 // as well as Adafruit raw 1.8" TFT display // ----> http://www.adafruit.com/products/618 - + // Check out the links above for our tutorials and wiring diagrams. // These displays use SPI to communicate, 4 or 5 pins are required to // interface (RST is optional). @@ -21,7 +21,11 @@ // Written by Limor Fried/Ladyada for Adafruit Industries. // MIT license, all text above must be included in any redistribution. -// Recent Arduino IDE releases include the Library Manager for easy installation. Otherwise, to download, click the DOWNLOAD ZIP button, uncompress and rename the uncompressed folder Adafruit_ST7735. Confirm that the Adafruit_ST7735 folder contains Adafruit_ST7735.cpp, Adafruit_ST7735.h and related source files. Place the Adafruit_ST7735 library folder your ArduinoSketchFolder/Libraries/ folder. You may need to create the Libraries subfolder if its your first library. Restart the IDE. +// Recent Arduino IDE releases include the Library Manager for easy installation. Otherwise, to download, click the +// DOWNLOAD ZIP button, uncompress and rename the uncompressed folder Adafruit_ST7735. Confirm that the Adafruit_ST7735 +// folder contains Adafruit_ST7735.cpp, Adafruit_ST7735.h and related source files. Place the Adafruit_ST7735 library +// folder your ArduinoSketchFolder/Libraries/ folder. You may need to create the Libraries subfolder if its your first +// library. Restart the IDE. // Also requires the Adafruit_GFX library for Arduino. @@ -157,4 +161,4 @@ static const uint8_t init_script_r3[] = { }; // clang-format on -#endif +#endif