From 79add7baf5d4f7f77f8bb3cfcf4fd24483539e39 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jan 2024 15:49:27 +0700 Subject: [PATCH 1/5] - add screen/display support for st77xx - able to make spi transfer, but data seem to be off --- CMakeLists.txt | 39 ++++-- Makefile | 6 +- linker/nrf52840_debug.ld | 2 +- src/boards/boards.c | 245 ++++++++++++++++++++++++++++++++++++-- src/boards/boards.h | 10 ++ src/images.c | 124 +++++++++++++++++++ src/main.c | 5 - src/nrfx_config.h | 2 - src/screen.c | 251 +++++++++++++++++++++++++++++++++++++++ src/usb/usb.c | 45 +++---- 10 files changed, 676 insertions(+), 53 deletions(-) create mode 100644 src/images.c create mode 100644 src/screen.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d5b2369f..a124031d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,8 +35,6 @@ set(TUSB ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb/src) #------------------- set(CMAKE_EXECUTABLE_SUFFIX .elf) add_executable(bootloader) -#set_target_properties(bootloader PROPERTIES OUTPUT_NAME "${BOARD}_bootloader.elf") - # SD_VERSION can be overwritten by board.cmake if(NOT DEFINED SD_VERSION) @@ -51,6 +49,8 @@ target_sources(bootloader PUBLIC src/dfu_init.c src/flash_nrf5x.c src/main.c + src/screen.c + src/images.c src/boards/boards.c # nrfx ${NRFX}/drivers/src/nrfx_power.c @@ -112,10 +112,29 @@ target_include_directories(bootloader PUBLIC ${SOFTDEVICE}/mbr/headers ) +# Debug option if (CMAKE_BUILD_TYPE STREQUAL "Debug") # TODO not work yet, also need to add segger rtt, DFU_APP_DATA_RESERVED=0, BOOTLOADER_REGION_START=0xED000 set(LD_FILE ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_debug.ld) - message(FATAL_ERROR "Debug build not supported yet") + + target_sources(bootloader PUBLIC + lib/SEGGER_RTT/RTT/SEGGER_RTT.c + ) + target_include_directories(bootloader PUBLIC + lib/SEGGER_RTT/RTT + ) + + target_compile_definitions(bootloader PUBLIC + CFG_DEBUG + SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL + DFU_APP_DATA_RESERVED=0 + ) + + if (MCU_VARIANT STREQUAL "nrf52840") + target_compile_definitions(bootloader PUBLIC BOOTLOADER_REGION_START=0xEA000) + else () + target_compile_definitions(bootloader PUBLIC BOOTLOADER_REGION_START=0x6D000) + endif () else () set(LD_FILE ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}.ld) endif () @@ -123,8 +142,7 @@ endif () target_link_options(bootloader PUBLIC "LINKER:--script=${LD_FILE}" -L${NRFX}/mdk - --specs=nosys.specs - --specs=nano.specs + --specs=nosys.specs --specs=nano.specs ) target_compile_options(bootloader PUBLIC -fno-builtin @@ -149,7 +167,6 @@ target_compile_options(bootloader PUBLIC ) target_compile_definitions(bootloader PUBLIC SOFTDEVICE_PRESENT - DFU_APP_DATA_RESERVED=7*4096 ) if (TRACE_ETM STREQUAL "1") @@ -195,6 +212,7 @@ endif () if (MCU_VARIANT STREQUAL "nrf52") set(SD_NAME s132) set(DFU_DEV_REV 0xADAF) + set(DFU_APP_DATA_RESERVED 7*4096) target_compile_definitions(bootloader PUBLIC NRF52 NRF52832_XXAA @@ -207,6 +225,7 @@ if (MCU_VARIANT STREQUAL "nrf52") elseif (MCU_VARIANT STREQUAL "nrf52833") set(SD_NAME s140) set(DFU_DEV_REV 52833) + set(DFU_APP_DATA_RESERVED 7*4096) target_compile_definitions(bootloader PUBLIC NRF52833_XXAA S140 @@ -218,6 +237,8 @@ elseif (MCU_VARIANT STREQUAL "nrf52833") elseif (MCU_VARIANT STREQUAL "nrf52840") set(SD_NAME s140) set(DFU_DEV_REV 52840) + # App reserved 40KB (8+32) to match circuitpython for 840 + set(DFU_APP_DATA_RESERVED 10*4096) target_compile_definitions(bootloader PUBLIC NRF52840_XXAA S140 @@ -233,6 +254,10 @@ endif () set(SD_FILENAME ${SD_NAME}_nrf52_${SD_VERSION}) set(SD_HEX ${SOFTDEVICE}/${SD_FILENAME}/${SD_FILENAME}_softdevice.hex) +if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + target_compile_definitions(bootloader PUBLIC DFU_APP_DATA_RESERVED=${DFU_APP_DATA_RESERVED}) +endif () + #---------------------------------- # Get UF2 version from git #---------------------------------- @@ -257,12 +282,12 @@ math(EXPR MK_BOOTLOADER_VERSION "(${RELEASE_VERSION_MAJOR} << 16) + (${RELEASE_V cmake_print_variables(GIT_VERSION GIT_SUBMODULE_VERSIONS MK_BOOTLOADER_VERSION) target_compile_definitions(bootloader PUBLIC + UF2_VERSION_BASE="${GIT_VERSION}" UF2_VERSION="${GIT_VERSION} - ${GIT_SUBMODULE_VERSIONS}" BLEDIS_FW_VERSION="${GIT_VERSION} ${SD_NAME} ${SD_VERSION}" MK_BOOTLOADER_VERSION=${MK_BOOTLOADER_VERSION} ) - #---------------------------------- # Post build #---------------------------------- diff --git a/Makefile b/Makefile index fb1f521a..866d4a63 100644 --- a/Makefile +++ b/Makefile @@ -123,7 +123,7 @@ else ifeq ($(MCU_SUB_VARIANT),nrf52840) SD_NAME = s140 DFU_DEV_REV = 52840 CFLAGS += -DNRF52840_XXAA -DS140 - # App reserved 40KB to match circuitpython for 840 + # App reserved 40KB (8+32) to match circuitpython for 840 DFU_APP_DATA_RESERVED=10*4096 else $(error Sub Variant $(MCU_SUB_VARIANT) is unknown) @@ -328,9 +328,9 @@ ifeq ($(DEBUG), 1) C_SRC += $(RTT_SRC)/RTT/SEGGER_RTT.c DFU_APP_DATA_RESERVED = 0 - # expand bootloader address to 28KB of reserved app + # expand bootloader address to 28KB/40KB of reserved app ifeq ($(MCU_SUB_VARIANT),nrf52840) - CFLAGS += -DBOOTLOADER_REGION_START=0xED000 + CFLAGS += -DBOOTLOADER_REGION_START=0xEA000 else CFLAGS += -DBOOTLOADER_REGION_START=0x6D000 endif diff --git a/linker/nrf52840_debug.ld b/linker/nrf52840_debug.ld index 324cad1d..7c68a830 100644 --- a/linker/nrf52840_debug.ld +++ b/linker/nrf52840_debug.ld @@ -12,7 +12,7 @@ MEMORY * APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START); */ /* due to lack of flash for debug, we will use reserved app to extend bootloader size */ - FLASH (rx) : ORIGIN = 0xF4000-28K, LENGTH = 0xFE000-0xF4000 - 2K + 28K /* 38 KB */ + FLASH (rx) : ORIGIN = 0xF4000 - 40K, LENGTH = 0xFE000-0xF4000 - 2K + 40K /* 38 KB */ BOOTLOADER_CONFIG (r): ORIGIN = 0xFE000 - 2K, LENGTH = 2K diff --git a/src/boards/boards.c b/src/boards/boards.c index 8b4583fb..b88d3f5c 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -24,6 +24,7 @@ #include "boards.h" #include "nrf_pwm.h" +#include "nrf_spim.h" #include "app_scheduler.h" #include "app_timer.h" @@ -31,9 +32,6 @@ #include "nrf_spim.h" #endif -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ #define SCHED_MAX_EVENT_DATA_SIZE sizeof(app_timer_event_t) /**< Maximum size of scheduler events. */ #define SCHED_QUEUE_SIZE 30 /**< Maximum number of events in the scheduler queue. */ @@ -43,7 +41,16 @@ void neopixel_write(uint8_t* pixels); void neopixel_teardown(void); #endif -//------------- IMPLEMENTATION -------------// +//--------------------------------------------------------------------+ +// IMPLEMENTATION +//--------------------------------------------------------------------+ + +static uint32_t _systick_count = 0; +void SysTick_Handler(void) { + _systick_count++; + led_tick(); +} + void button_init(uint32_t pin) { if (BUTTON_PULL == NRF_GPIO_PIN_PULLDOWN) { nrf_gpio_cfg_sense_input(pin, BUTTON_PULL, NRF_GPIO_PIN_SENSE_HIGH); @@ -96,6 +103,7 @@ void board_init(void) { #if ENABLE_DCDC_1 == 1 NRF_POWER->DCDCEN = 1; #endif + // Make sure any custom inits are performed board_init2(); @@ -144,6 +152,10 @@ void board_teardown(void) { neopixel_teardown(); #endif +#ifdef DISPLAY_PIN_SCK + board_display_teardown(); +#endif + // Stop RTC1 used by app_timer NVIC_DisableIRQ(RTC1_IRQn); NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk; @@ -164,13 +176,134 @@ void board_teardown(void) { board_teardown2(); } -static uint32_t _systick_count = 0; +//--------------------------------------------------------------------+ +// Display +//--------------------------------------------------------------------+ +#ifdef DISPLAY_PIN_SCK -void SysTick_Handler(void) { - _systick_count++; - led_tick(); +// Note don't use SPIM3 since it has lots of errata +NRF_SPIM_Type* _spim = NRF_SPIM0; + +static void spi_write(NRF_SPIM_Type *p_spim, uint8_t const *tx_buf, size_t tx_len) { + nrf_spim_tx_buffer_set(p_spim, tx_buf, tx_len); + nrf_spim_rx_buffer_set(p_spim, NULL, 0); + + nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_ENDTX); + nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END); + nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START); + + // blocking wait until xfer complete + while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END)){} } +static void tft_controller_init(void); + +static inline void tft_cs(bool state) { + if (state) { + nrf_gpio_pin_set(DISPLAY_PIN_CS); + } else { + nrf_gpio_pin_clear(DISPLAY_PIN_CS); + } +} + +static inline void tft_dc(bool state) { + if (state) { + nrf_gpio_pin_set(DISPLAY_PIN_DC); + } else { + nrf_gpio_pin_clear(DISPLAY_PIN_DC); + } +} + +static void tft_cmd(uint8_t cmd, uint8_t const* data, uint8_t narg) { + tft_cs(false); + + // send command + tft_dc(false); + spi_write(_spim, &cmd, 1); + + // send data + if (narg > 0) { + tft_dc(true); + spi_write(_spim, data, narg); + } + + tft_cs(true); +} + +void board_display_init(void) { + //------------- SPI init -------------// + // highspeed SPIM should set SCK and MOSI to high drive + nrf_gpio_cfg(DISPLAY_PIN_SCK, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_CONNECT, + NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg(DISPLAY_PIN_MOSI, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, + NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_output(DISPLAY_PIN_CS); + nrf_gpio_pin_set(DISPLAY_PIN_CS); + + nrf_spim_pins_set(_spim, DISPLAY_PIN_SCK, DISPLAY_PIN_MOSI, NRF_SPIM_PIN_NOT_CONNECTED); + nrf_spim_frequency_set(_spim, NRF_SPIM_FREQ_4M); + nrf_spim_configure(_spim, NRF_SPIM_MODE_0, NRF_SPIM_BIT_ORDER_MSB_FIRST); + nrf_spim_orc_set(_spim, 0xFF); + + nrf_spim_enable(_spim); + + //------------- Display Init -------------// + nrf_gpio_cfg_output(DISPLAY_PIN_DC); + + #if defined(DISPLAY_PIN_RST) && DISPLAY_PIN_RST >= 0 + nrf_gpio_cfg_output(DISPLAY_PIN_RST); + nrf_gpio_pin_write(DISPLAY_PIN_RST, 0); + NRFX_DELAY_MS(10); + nrf_gpio_pin_write(DISPLAY_PIN_RST, 1); + #endif + + #if defined(DISPLAY_PIN_BL) && DISPLAY_PIN_BL >= 0 + nrf_gpio_cfg_output(DISPLAY_PIN_BL); + nrf_gpio_pin_write(DISPLAY_PIN_BL, DISPLAY_BL_ON); + #endif + + tft_controller_init(); +} + +void board_display_teardown(void) { + nrf_spim_disable(_spim); +} + +// Send the whole buffer data to display controller +extern const uint16_t color_palette[]; +void board_display_draw_screen(uint8_t const* fb) { + + tft_cs(false); + + // command: memory write + uint8_t cmd = 0x2C; + tft_dc(false); + spi_write(_spim, &cmd, 1); + + // data + tft_dc(true); + + uint8_t const* p = fb; + for (int i = 0; i < DISPLAY_WIDTH; ++i) { + uint8_t cc[DISPLAY_HEIGHT * 2]; + uint32_t dst = 0; + for (int j = 0; j < DISPLAY_HEIGHT; ++j) { + uint16_t color = color_palette[*p++ & 0xf]; + cc[dst++] = color >> 8; + cc[dst++] = color & 0xff; + } + + spi_write(_spim, cc, sizeof(cc)); + } + + tft_cs(true); +} + +#endif + +//--------------------------------------------------------------------+ +// LED Indicator +//--------------------------------------------------------------------+ void pwm_teardown(NRF_PWM_Type* pwm) { pwm->TASKS_SEQSTART[0] = 0; pwm->ENABLE = 0; @@ -547,3 +680,99 @@ void neopixel_write (uint8_t *pixels) { led_pwm_duty_cycle(LED_RGB_BLUE, pixels[0]); } #endif + +#ifdef DISPLAY_CONTROLLER_ST7789 + +#define ST_CMD_DELAY 0x80 // special signifier for command lists + +#define ST77XX_NOP 0x00 +#define ST77XX_SWRESET 0x01 +#define ST77XX_RDDID 0x04 +#define ST77XX_RDDST 0x09 + +#define ST77XX_SLPIN 0x10 +#define ST77XX_SLPOUT 0x11 +#define ST77XX_PTLON 0x12 +#define ST77XX_NORON 0x13 + +#define ST77XX_INVOFF 0x20 +#define ST77XX_INVON 0x21 +#define ST77XX_DISPOFF 0x28 +#define ST77XX_DISPON 0x29 +#define ST77XX_CASET 0x2A +#define ST77XX_RASET 0x2B +#define ST77XX_RAMWR 0x2C +#define ST77XX_RAMRD 0x2E + +#define ST77XX_PTLAR 0x30 +#define ST77XX_TEOFF 0x34 +#define ST77XX_TEON 0x35 +#define ST77XX_MADCTL 0x36 +#define ST77XX_COLMOD 0x3A + +#define ST77XX_MADCTL_MY 0x80 +#define ST77XX_MADCTL_MX 0x40 +#define ST77XX_MADCTL_MV 0x20 +#define ST77XX_MADCTL_ML 0x10 +#define ST77XX_MADCTL_RGB 0x00 + +#define ST77XX_RDID1 0xDA +#define ST77XX_RDID2 0xDB +#define ST77XX_RDID3 0xDC +#define ST77XX_RDID4 0xDD + +// Some ready-made 16-bit ('565') color settings: +#define ST77XX_BLACK 0x0000 +#define ST77XX_WHITE 0xFFFF +#define ST77XX_RED 0xF800 +#define ST77XX_GREEN 0x07E0 +#define ST77XX_BLUE 0x001F +#define ST77XX_CYAN 0x07FF +#define ST77XX_MAGENTA 0xF81F +#define ST77XX_YELLOW 0xFFE0 +#define ST77XX_ORANGE 0xFC00 + +static void tft_controller_init(void) { + // Init commands for 7789 screens + uint8_t cmdinit_st7789[] = { + // 1: Software reset, no args, w/delay ~150 ms delay + ST77XX_SWRESET, ST_CMD_DELAY, 150, + // 2: Out of sleep mode, no args, w/delay 10 ms delay + ST77XX_SLPOUT, ST_CMD_DELAY, 10, + // 3: Set color mode, 1 arg + delay: 16-bit color, 10 ms delay + ST77XX_COLMOD, 1 + ST_CMD_DELAY, 0x55, 10, + // 4: Mem access ctrl (directions), 1 arg: Row/col addr, bottom-top refresh + ST77XX_MADCTL, 1, 0x08, + // 5: Column addr set, 4 args, no delay: XSTART = 0, XEND = 240 + ST77XX_CASET, 4, 0x00, 0, 0, 240, + // 6: Row addr set, 4 args, no delay: YSTART = 0 YEND = 320 + ST77XX_RASET, 4, 0x00, 0, 320 >> 8, 320 & 0xFF, + // 7: hack + ST77XX_INVON, ST_CMD_DELAY, 10, + // 8: Normal display on, no args, w/delay 10 ms delay + ST77XX_NORON, ST_CMD_DELAY, 10, + // 9: Main screen turn on, no args, delay 10 ms delay + ST77XX_DISPON, ST_CMD_DELAY, 10 + }; + + size_t count = 0; + while (count < sizeof(cmdinit_st7789)) { + uint8_t const cmd = cmdinit_st7789[count++]; + uint8_t const cmd_arg = cmdinit_st7789[count++]; + uint8_t const has_delay = cmd_arg & ST_CMD_DELAY; + uint8_t const narg = cmd_arg & ~ST_CMD_DELAY; + + tft_cmd(cmd, cmdinit_st7789 + count, narg); + count += narg; + + if (has_delay) { + uint16_t delay = (uint16_t) cmdinit_st7789[count++]; + if (delay == 255) { + delay = 500; // If 255, delay for 500 ms + } + NRFX_DELAY_MS(delay); + } + } +} + +#endif \ No newline at end of file diff --git a/src/boards/boards.h b/src/boards/boards.h index 8aa0ece6..e5bf3d88 100644 --- a/src/boards/boards.h +++ b/src/boards/boards.h @@ -114,6 +114,16 @@ bool button_pressed(uint32_t pin); bool is_ota(void); +//--------------------------------------------------------------------+ +// Display +//--------------------------------------------------------------------+ +#ifdef DISPLAY_PIN_SCK +void board_display_init(void); +void board_display_teardown(void); +void board_display_draw_screen(uint8_t const* fb); +void screen_draw_drag(void); +#endif + //--------------------------------------------------------------------+ // DEBUG //--------------------------------------------------------------------+ diff --git a/src/images.c b/src/images.c new file mode 100644 index 00000000..2f2767fd --- /dev/null +++ b/src/images.c @@ -0,0 +1,124 @@ +#include "boards.h" + +#if defined(DISPLAY_PIN_SCK) + +#include + +// all https://makecode.com/_VrfEKzV4xfvq + +// https://makecode.com/_7VxXm3JMPXfM - file +// https://makecode.com/_LuEUCsPEKUbs - download +const uint8_t fileLogo[] = { +32, 32, 71, 140, 201, 151, 1, 2, 146, 1, 2, 146, 63, 2, 151, 9, 153, 9, 153, 9, 146, 1, 9, 146, 3, 9, 146, 7, 9, 137, 205, 72, 140, 206, 36, 139, 207, 18, 138, 206, 36, 139, 205, 72, 149, 7, 9, 146, 3, 9, 146, 1, 9, 153, 9, 153, 9, 153, 9, 148, 63, 2, 146, 1, 2, 146, 1, 2, 146, 201, 191, 191, 191, 174 +}; + +// https://makecode.com/_9b0RcK5yRa12 +const uint8_t pendriveLogo[] = { +32, 32, 59, 137, 215, 137, 1, 143, 1, 8, 146, 203, 149, 3, 8, 146, 3, 8, 146, 115, 8, 146, 115, 8, 146, 3, 8, 146, 3, 8, 146, 115, 8, 146, 115, 8, 146, 3, 8, 146, 3, 8, 146, 203, 149, 1, 8, 146, 1, 8, 146, 1, 120, 211, 191, 191, 191, 191, 191, 191, 191, 135 +}; + +// https://makecode.com/_TTqbj705L4mr +const uint8_t arrowLogo[] = { +32, 32, 54, 137, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 146, 211, 142, 209, 144, 207, 146, 205, 148, 203, 150, 201, 152, 199, 154, 31, 154, 7, 154, 1, 191, 191, 191, 175 +}; + +const uint8_t font8[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0x00, 0x0e, 0x00, 0x0e, 0x00, 0x00, +0x28, 0xfe, 0x28, 0xfe, 0x28, 0x00, +0x4c, 0x92, 0xff, 0x92, 0x64, 0x00, +0x02, 0x65, 0x12, 0x48, 0xa6, 0x40, +0x6c, 0x92, 0x92, 0x6c, 0xa0, 0x00, +0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0x82, 0x00, 0x00, +0x00, 0x00, 0x82, 0x7c, 0x00, 0x00, +0x54, 0x38, 0x10, 0x38, 0x54, 0x00, +0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, +0x00, 0x00, 0x90, 0x70, 0x00, 0x00, +0x10, 0x10, 0x10, 0x10, 0x10, 0x00, +0x00, 0x00, 0x60, 0x60, 0x00, 0x00, +0x00, 0x60, 0x10, 0x08, 0x06, 0x00, +0x00, 0x3c, 0x42, 0x42, 0x3c, 0x00, +0x00, 0x44, 0x7e, 0x40, 0x00, 0x00, +0x00, 0x44, 0x62, 0x52, 0x4c, 0x00, +0x00, 0x42, 0x4a, 0x4e, 0x32, 0x00, +0x30, 0x28, 0x24, 0x7e, 0x20, 0x00, +0x00, 0x4e, 0x4a, 0x4a, 0x32, 0x00, +0x00, 0x3c, 0x4a, 0x4a, 0x30, 0x00, +0x00, 0x02, 0x62, 0x12, 0x0e, 0x00, +0x00, 0x34, 0x4a, 0x4a, 0x34, 0x00, +0x00, 0x0c, 0x52, 0x52, 0x3c, 0x00, +0x00, 0x00, 0x6c, 0x6c, 0x00, 0x00, +0x00, 0x00, 0x96, 0x76, 0x00, 0x00, +0x10, 0x28, 0x28, 0x44, 0x44, 0x00, +0x28, 0x28, 0x28, 0x28, 0x28, 0x00, +0x44, 0x44, 0x28, 0x28, 0x10, 0x00, +0x00, 0x02, 0x59, 0x09, 0x06, 0x00, +0x3c, 0x42, 0x5a, 0x56, 0x08, 0x00, +0x78, 0x14, 0x12, 0x14, 0x78, 0x00, +0x7e, 0x4a, 0x4a, 0x4a, 0x34, 0x00, +0x00, 0x3c, 0x42, 0x42, 0x24, 0x00, +0x00, 0x7e, 0x42, 0x42, 0x3c, 0x00, +0x00, 0x7e, 0x4a, 0x4a, 0x42, 0x00, +0x00, 0x7e, 0x0a, 0x0a, 0x02, 0x00, +0x00, 0x3c, 0x42, 0x52, 0x34, 0x00, +0x00, 0x7e, 0x08, 0x08, 0x7e, 0x00, +0x00, 0x42, 0x7e, 0x42, 0x00, 0x00, +0x20, 0x40, 0x42, 0x3e, 0x02, 0x00, +0x00, 0x7e, 0x08, 0x14, 0x62, 0x00, +0x00, 0x7e, 0x40, 0x40, 0x40, 0x00, +0x7e, 0x04, 0x18, 0x04, 0x7e, 0x00, +0x00, 0x7e, 0x04, 0x08, 0x7e, 0x00, +0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, +0x00, 0x7e, 0x12, 0x12, 0x0c, 0x00, +0x00, 0x3c, 0x52, 0x62, 0xbc, 0x00, +0x00, 0x7e, 0x12, 0x12, 0x6c, 0x00, +0x00, 0x24, 0x4a, 0x52, 0x24, 0x00, +0x02, 0x02, 0x7e, 0x02, 0x02, 0x00, +0x00, 0x3e, 0x40, 0x40, 0x3e, 0x00, +0x00, 0x1e, 0x70, 0x70, 0x1e, 0x00, +0x7e, 0x20, 0x18, 0x20, 0x7e, 0x00, +0x42, 0x24, 0x18, 0x24, 0x42, 0x00, +0x06, 0x08, 0x70, 0x08, 0x06, 0x00, +0x00, 0x62, 0x52, 0x4a, 0x46, 0x00, +0x00, 0x7e, 0x42, 0x42, 0x00, 0x00, +0x00, 0x06, 0x08, 0x10, 0x60, 0x00, +0x00, 0x42, 0x42, 0x7e, 0x00, 0x00, +0x08, 0x04, 0x02, 0x04, 0x08, 0x00, +0x80, 0x80, 0x80, 0x80, 0x80, 0x00, +0x00, 0x00, 0x02, 0x04, 0x00, 0x00, +0x00, 0x30, 0x48, 0x48, 0x78, 0x00, +0x00, 0x7e, 0x48, 0x48, 0x30, 0x00, +0x00, 0x30, 0x48, 0x48, 0x48, 0x00, +0x00, 0x30, 0x48, 0x48, 0x7e, 0x00, +0x00, 0x30, 0x68, 0x58, 0x50, 0x00, +0x00, 0x10, 0x7c, 0x12, 0x04, 0x00, +0x00, 0x18, 0xa4, 0xa4, 0x78, 0x00, +0x00, 0x7e, 0x08, 0x08, 0x70, 0x00, +0x00, 0x48, 0x7a, 0x40, 0x00, 0x00, +0x00, 0x40, 0x84, 0x7d, 0x00, 0x00, +0x00, 0x7e, 0x10, 0x28, 0x40, 0x00, +0x00, 0x42, 0x7e, 0x40, 0x00, 0x00, +0x78, 0x08, 0x30, 0x08, 0x70, 0x00, +0x00, 0x78, 0x08, 0x08, 0x70, 0x00, +0x00, 0x30, 0x48, 0x48, 0x30, 0x00, +0x00, 0xfc, 0x24, 0x24, 0x18, 0x00, +0x00, 0x18, 0x24, 0x24, 0xfc, 0x00, +0x00, 0x78, 0x10, 0x08, 0x10, 0x00, +0x00, 0x50, 0x58, 0x68, 0x28, 0x00, +0x00, 0x08, 0x3e, 0x48, 0x20, 0x00, +0x00, 0x38, 0x40, 0x40, 0x78, 0x00, +0x00, 0x18, 0x60, 0x60, 0x18, 0x00, +0x38, 0x40, 0x30, 0x40, 0x38, 0x00, +0x00, 0x48, 0x30, 0x30, 0x48, 0x00, +0x00, 0x5c, 0xa0, 0xa0, 0x7c, 0x00, +0x00, 0x48, 0x68, 0x58, 0x48, 0x00, +0x00, 0x08, 0x36, 0x41, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, +0x00, 0x41, 0x36, 0x08, 0x00, 0x00, +0x00, 0x08, 0x04, 0x08, 0x04, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index cf005419..92ad0208 100644 --- a/src/main.c +++ b/src/main.c @@ -477,9 +477,4 @@ __attribute__ ((used)) int _write (int fhdl, const void *buf, size_t count) { return count; } -__attribute__ ((used)) int _read (int fhdl, char *buf, size_t count) { - (void) fhdl; - return SEGGER_RTT_Read(0, buf, count); -} - #endif diff --git a/src/nrfx_config.h b/src/nrfx_config.h index b626e000..74e5fdbc 100644 --- a/src/nrfx_config.h +++ b/src/nrfx_config.h @@ -18,10 +18,8 @@ // UART #ifdef NRF52832_XXAA - #define NRFX_UART_ENABLED 1 #define NRFX_UART0_ENABLED 1 - #define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_UART_DEFAULT_CONFIG_HWFC NRF_UART_HWFC_DISABLED #define NRFX_UART_DEFAULT_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED diff --git a/src/screen.c b/src/screen.c new file mode 100644 index 00000000..adf21981 --- /dev/null +++ b/src/screen.c @@ -0,0 +1,251 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ha Thach (tinyusb.org) for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards.h" + +#if defined(DISPLAY_PIN_SCK) + +#include +#include + +// Overlap 4x chars by this much. +#define CHAR4_KERNING 3 + +// Width of a single 4x char, adjusted by kerning +#define CHAR4_KERNED_WIDTH (6 * 4 - CHAR4_KERNING) + +#define COL0(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) +#define COL(c) COL0((c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff) + +enum { + COLOR_BLACK = 0, + COLOR_WHITE = 1, + COLOR_RED = 2, + COLOR_PINK = 3, + COLOR_ORANGE = 4, + COLOR_YELLOW = 5, + COLOR_CYAN = 6, + COLOR_GREEN = 7, + COLOR_BLUE = 8, + COLOR_AQUA = 9, + COLOR_PURPLE = 10, +}; + +// 16-bit 565 color from 24-bit 888 format +const uint16_t color_palette[] = { + COL(0x000000), // 0 + COL(0xffffff), // 1 + COL(0xff2121), // 2 + COL(0xff93c4), // 3 + COL(0xff8135), // 4 + COL(0xfff609), // 5 + COL(0x249ca3), // 6 + COL(0x78dc52), // 7 + COL(0x003fad), // 8 + COL(0x87f2ff), // 9 + COL(0x8e2ec4), // 10 + + COL(0xa4839f), // 11 + COL(0x5c406c), // 12 + COL(0xe5cdc4), // 13 + COL(0x91463d), // 14 + COL(0x000000), // 15 +}; + +// TODO only buffer partial screen to save SRAM +// ESP32s2 can only statically allocated DRAM up to 160KB. +// the remaining 160KB can only be allocated at runtime as heap. +static uint8_t frame_buf[DISPLAY_WIDTH * DISPLAY_HEIGHT]; +//static uint8_t* frame_buf; + +extern const uint8_t font8[]; +extern const uint8_t fileLogo[]; +extern const uint8_t pendriveLogo[]; +extern const uint8_t arrowLogo[]; + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +// print character with font size = 1 +static void printch(int x, int y, int color, const uint8_t* fnt) { + for (int i = 0; i < 6; ++i) { + uint8_t* p = frame_buf + (x + i) * DISPLAY_HEIGHT + y; + uint8_t mask = 0x01; + for (int j = 0; j < 8; ++j) { + if (*fnt & mask) { + *p = color; + } + p++; + mask <<= 1; + } + fnt++; + } +} + +// print character with font size = 4 +static void printch4(int x, int y, int color, const uint8_t* fnt) { + for (int i = 0; i < 6 * 4; ++i) { + uint8_t* p = frame_buf + (x + i) * DISPLAY_HEIGHT + y; + uint8_t mask = 0x01; + for (int j = 0; j < 8; ++j) { + for (int k = 0; k < 4; ++k) { + if (*fnt & mask) { + *p = color; + } + p++; + } + mask <<= 1; + } + if ((i & 3) == 3) { + fnt++; + } + } +} + +// print icon +static void printicon(int x, int y, int color, const uint8_t* icon) { + int w = *icon++; + int h = *icon++; + int sz = *icon++; + + uint8_t mask = 0x80; + int runlen = 0; + int runbit = 0; + uint8_t lastb = 0x00; + + for (int i = 0; i < w; ++i) { + uint8_t* p = frame_buf + (x + i) * DISPLAY_HEIGHT + y; + for (int j = 0; j < h; ++j) { + int c = 0; + if (mask != 0x80) { + if (lastb & mask) { + c = 1; + } + mask <<= 1; + } else if (runlen) { + if (runbit) { + c = 1; + } + runlen--; + } else { + if (sz-- <= 0) { + //TU_LOG1("Screen Panic code = 10"); + } + lastb = *icon++; + if (lastb & 0x80) { + runlen = lastb & 63; + runbit = lastb & 0x40; + } else { + mask = 0x01; + } + --j; + continue; // restart + } + if (c) { + *p = color; + } + p++; + } + } +} + +// print text with font size = 1 +static void print(int x, int y, int col, const char* text) { + int x0 = x; + while (*text) { + char c = *text++; + if (c == '\r') continue; + if (c == '\n') { + x = x0; + y += 10; + continue; + } + /* + if (x + 8 > DISPLAY_WIDTH) { + x = x0; + y += 10; + } + */ + if (c < ' ') c = '?'; + if (c >= 0x7f) c = '?'; + c -= ' '; + printch(x, y, col, &font8[c * 6]); + x += 6; + } +} + +// Print text with font size = 4 +static void print4(int x, int y, int color, const char* text) { + while (*text) { + char c = *text++; + c -= ' '; + printch4(x, y, color, &font8[c * 6]); + x += CHAR4_KERNED_WIDTH; + if (x + CHAR4_KERNED_WIDTH > DISPLAY_WIDTH) { + // Next char won't fit. + return; + } + } +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +// draw color bar +static void drawBar(int y, int h, int color) { + for (int x = 0; x < DISPLAY_WIDTH; ++x) { + memset(frame_buf + x * DISPLAY_HEIGHT + y, color, h); + } +} + +// draw drag & drop screen +void screen_draw_drag(void) { + drawBar(0, 52, COLOR_GREEN); + drawBar(52, 55, COLOR_BLUE); + drawBar(107, 14, COLOR_ORANGE); + + // Center UF2_PRODUCT_NAME and UF2_VERSION_BASE. + int name_x = (DISPLAY_WIDTH - CHAR4_KERNED_WIDTH * (int) strlen(DISPLAY_TITLE)) / 2; + print4(name_x >= 0 ? name_x : 0, 5, COLOR_WHITE, DISPLAY_TITLE); + + int version_x = (DISPLAY_WIDTH - 6 * (int) strlen(UF2_VERSION_BASE)) / 2; + print(version_x >= 0 ? version_x : 0, 40, COLOR_PURPLE, UF2_VERSION_BASE); + + // TODO the reset should be center as well + print(23, 110, 1, "circuitpython.org"); + +#define DRAG 70 +#define DRAGX 10 + printicon(DRAGX + 20, DRAG + 5, COLOR_WHITE, fileLogo); + printicon(DRAGX + 66, DRAG, COLOR_WHITE, arrowLogo); + printicon(DRAGX + 108, DRAG, COLOR_WHITE, pendriveLogo); + print(10, DRAG - 12, COLOR_WHITE, "firmware.uf2"); + print(90, DRAG - 12, COLOR_WHITE, UF2_VOLUME_LABEL); + + board_display_draw_screen(frame_buf); +} + +#endif diff --git a/src/usb/usb.c b/src/usb/usb.c index 6cbfa76d..30d91c0d 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -43,49 +43,41 @@ extern void tusb_hal_nrf_power_event(uint32_t event); // power callback when SD is not enabled -static void power_event_handler(nrfx_power_usb_evt_t event) -{ +static void power_event_handler(nrfx_power_usb_evt_t event) { tusb_hal_nrf_power_event((uint32_t) event); } // Forward USB interrupt events to TinyUSB IRQ Handler -void USBD_IRQHandler(void) -{ +void USBD_IRQHandler(void) { tud_int_handler(0); } //------------- IMPLEMENTATION -------------// -void usb_init(bool cdc_only) -{ +void usb_init(bool cdc_only) { // 0, 1 is reserved for SD NVIC_SetPriority(USBD_IRQn, 2); // USB power may already be ready at this time -> no event generated // We need to invoke the handler based on the status initially uint32_t usb_reg; - uint8_t sd_en = false; - if ( is_sd_existed() ) - { + if (is_sd_existed()) { sd_softdevice_is_enabled(&sd_en); } - if ( sd_en ) - { + if (sd_en) { sd_power_usbdetected_enable(true); sd_power_usbpwrrdy_enable(true); sd_power_usbremoved_enable(true); - sd_power_usbregstatus_get(&usb_reg); - }else - { + } else { // Power module init - const nrfx_power_config_t pwr_cfg = { 0 }; + const nrfx_power_config_t pwr_cfg = {0}; nrfx_power_init(&pwr_cfg); // Register USB power handler - const nrfx_power_usbevt_config_t config = { .handler = power_event_handler }; + const nrfx_power_usbevt_config_t config = {.handler = power_event_handler}; nrfx_power_usbevt_init(&config); nrfx_power_usbevt_enable(); @@ -93,24 +85,25 @@ void usb_init(bool cdc_only) usb_reg = NRF_POWER->USBREGSTATUS; } - if ( usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk ) { + if (usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk) { tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_DETECTED); } - if ( usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk ) { + if (usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk) { tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY); } usb_desc_init(cdc_only); - uf2_init(); - - // Init TinyUSB stack tusb_init(); + + #ifdef DISPLAY_PIN_SCK + board_display_init(); + screen_draw_drag(); + #endif } -void usb_teardown(void) -{ +void usb_teardown(void) { // Simulate an disconnect which cause pullup disable, USB perpheral disable and hclk disable tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_REMOVED); } @@ -118,12 +111,10 @@ void usb_teardown(void) //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { led_state(STATE_USB_MOUNTED); } -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { led_state(STATE_USB_UNMOUNTED); } From a6a8962b1d286400b090cf2fc9d5123b653a7f69 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jan 2024 16:46:02 +0700 Subject: [PATCH 2/5] get slash screen running --- src/boards/boards.c | 48 ++++++++++++++++++++------------------------- src/boards/boards.h | 2 +- src/screen.c | 19 ++++++++++++++++-- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index b88d3f5c..4ab04be5 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -214,7 +214,7 @@ static inline void tft_dc(bool state) { } } -static void tft_cmd(uint8_t cmd, uint8_t const* data, uint8_t narg) { +static void tft_cmd(uint8_t cmd, uint8_t const* data, size_t narg) { tft_cs(false); // send command @@ -269,34 +269,20 @@ void board_display_teardown(void) { nrf_spim_disable(_spim); } -// Send the whole buffer data to display controller -extern const uint16_t color_palette[]; -void board_display_draw_screen(uint8_t const* fb) { +void board_display_draw_line(uint16_t y, uint8_t const* buf, size_t nbytes) { + // column and row address set + uint32_t xa32 = DISPLAY_COL_OFFSET << 16 | DISPLAY_WIDTH; + xa32 = __builtin_bswap32(xa32); - tft_cs(false); - - // command: memory write - uint8_t cmd = 0x2C; - tft_dc(false); - spi_write(_spim, &cmd, 1); + y += DISPLAY_ROW_OFFSET; + uint32_t ya32 = (y << 16) | (y + 1); + ya32 = __builtin_bswap32(ya32); - // data - tft_dc(true); - - uint8_t const* p = fb; - for (int i = 0; i < DISPLAY_WIDTH; ++i) { - uint8_t cc[DISPLAY_HEIGHT * 2]; - uint32_t dst = 0; - for (int j = 0; j < DISPLAY_HEIGHT; ++j) { - uint16_t color = color_palette[*p++ & 0xf]; - cc[dst++] = color >> 8; - cc[dst++] = color & 0xff; - } + tft_cmd(0x2A, (uint8_t*) &xa32, 4); + tft_cmd(0x2B, (uint8_t*) &ya32, 4); - spi_write(_spim, cc, sizeof(cc)); - } - - tft_cs(true); + // command: memory write + tft_cmd(0x2C, buf, nbytes); } #endif @@ -681,6 +667,14 @@ void neopixel_write (uint8_t *pixels) { } #endif +#define TFT_MADCTL_MY 0x80 ///< Page addr order: Bottom to top +#define TFT_MADCTL_MX 0x40 ///< Column addr order: Right to left +#define TFT_MADCTL_MV 0x20 ///< Page/Column order: Reverse Mode ( X <-> Y ) +#define TFT_MADCTL_ML 0x10 ///< LCD refresh Bottom to top +#define TFT_MADCTL_MH 0x04 ///< LCD refresh right to left +#define TFT_MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order +#define TFT_MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order + #ifdef DISPLAY_CONTROLLER_ST7789 #define ST_CMD_DELAY 0x80 // special signifier for command lists @@ -742,7 +736,7 @@ static void tft_controller_init(void) { // 3: Set color mode, 1 arg + delay: 16-bit color, 10 ms delay ST77XX_COLMOD, 1 + ST_CMD_DELAY, 0x55, 10, // 4: Mem access ctrl (directions), 1 arg: Row/col addr, bottom-top refresh - ST77XX_MADCTL, 1, 0x08, + ST77XX_MADCTL, 1, DISPLAY_MADCTL, // 5: Column addr set, 4 args, no delay: XSTART = 0, XEND = 240 ST77XX_CASET, 4, 0x00, 0, 0, 240, // 6: Row addr set, 4 args, no delay: YSTART = 0 YEND = 320 diff --git a/src/boards/boards.h b/src/boards/boards.h index e5bf3d88..26a3e135 100644 --- a/src/boards/boards.h +++ b/src/boards/boards.h @@ -120,7 +120,7 @@ bool is_ota(void); #ifdef DISPLAY_PIN_SCK void board_display_init(void); void board_display_teardown(void); -void board_display_draw_screen(uint8_t const* fb); +void board_display_draw_line(uint16_t y, uint8_t const* buf, size_t nbytes); void screen_draw_drag(void); #endif diff --git a/src/screen.c b/src/screen.c index adf21981..8931b550 100644 --- a/src/screen.c +++ b/src/screen.c @@ -53,7 +53,7 @@ enum { }; // 16-bit 565 color from 24-bit 888 format -const uint16_t color_palette[] = { +const uint16_t palette[] = { COL(0x000000), // 0 COL(0xffffff), // 1 COL(0xff2121), // 2 @@ -214,6 +214,21 @@ static void print4(int x, int y, int color, const char* text) { // //--------------------------------------------------------------------+ +static void draw_screen(uint8_t const* fb) { + uint8_t const* p = fb; + for (int y = 0; y < DISPLAY_WIDTH; ++y) { + uint8_t cc[DISPLAY_HEIGHT * 2]; + uint32_t dst = 0; + for (int x = 0; x < DISPLAY_HEIGHT; ++x) { + uint16_t color = palette[*p++ & 0xf]; + cc[dst++] = color >> 8; + cc[dst++] = color & 0xff; + } + + board_display_draw_line(y, cc, sizeof(cc)); + } +} + // draw color bar static void drawBar(int y, int h, int color) { for (int x = 0; x < DISPLAY_WIDTH; ++x) { @@ -245,7 +260,7 @@ void screen_draw_drag(void) { print(10, DRAG - 12, COLOR_WHITE, "firmware.uf2"); print(90, DRAG - 12, COLOR_WHITE, UF2_VOLUME_LABEL); - board_display_draw_screen(frame_buf); + draw_screen(frame_buf); } #endif From 0eead42aec954565a4d338b3da0edd94493a9493 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jan 2024 16:59:16 +0700 Subject: [PATCH 3/5] add display for sense tft --- Makefile | 3 ++ src/boards/boards.c | 42 +++++++++---------- src/boards/feather_nrf52840_sense_tft/board.h | 28 ++++++++++++- 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index 866d4a63..17fa1050 100644 --- a/Makefile +++ b/Makefile @@ -139,6 +139,8 @@ C_SRC += \ src/dfu_init.c \ src/flash_nrf5x.c \ src/main.c \ + src/screen.c \ + src/images.c \ # all files in boards C_SRC += src/boards/boards.c @@ -314,6 +316,7 @@ ifneq ($(USE_NFCT),yes) endif CFLAGS += -DSOFTDEVICE_PRESENT +CFLAGS += -DUF2_VERSION_BASE='"$(GIT_VERSION)"' CFLAGS += -DUF2_VERSION='"$(GIT_VERSION) $(GIT_SUBMODULE_VERSIONS)"' CFLAGS += -DBLEDIS_FW_VERSION='"$(GIT_VERSION) $(SD_NAME) $(SD_VERSION)"' diff --git a/src/boards/boards.c b/src/boards/boards.c index 4ab04be5..563ed6f1 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -181,6 +181,14 @@ void board_teardown(void) { //--------------------------------------------------------------------+ #ifdef DISPLAY_PIN_SCK +#define TFT_MADCTL_MY 0x80 ///< Page addr order: Bottom to top +#define TFT_MADCTL_MX 0x40 ///< Column addr order: Right to left +#define TFT_MADCTL_MV 0x20 ///< Page/Column order: Reverse Mode ( X <-> Y ) +#define TFT_MADCTL_ML 0x10 ///< LCD refresh Bottom to top +#define TFT_MADCTL_MH 0x04 ///< LCD refresh right to left +#define TFT_MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order +#define TFT_MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order + // Note don't use SPIM3 since it has lots of errata NRF_SPIM_Type* _spim = NRF_SPIM0; @@ -199,19 +207,11 @@ static void spi_write(NRF_SPIM_Type *p_spim, uint8_t const *tx_buf, size_t tx_le static void tft_controller_init(void); static inline void tft_cs(bool state) { - if (state) { - nrf_gpio_pin_set(DISPLAY_PIN_CS); - } else { - nrf_gpio_pin_clear(DISPLAY_PIN_CS); - } + nrf_gpio_pin_write(DISPLAY_PIN_CS, state); } static inline void tft_dc(bool state) { - if (state) { - nrf_gpio_pin_set(DISPLAY_PIN_DC); - } else { - nrf_gpio_pin_clear(DISPLAY_PIN_DC); - } + nrf_gpio_pin_write(DISPLAY_PIN_DC, state); } static void tft_cmd(uint8_t cmd, uint8_t const* data, size_t narg) { @@ -250,17 +250,17 @@ void board_display_init(void) { //------------- Display Init -------------// nrf_gpio_cfg_output(DISPLAY_PIN_DC); - #if defined(DISPLAY_PIN_RST) && DISPLAY_PIN_RST >= 0 +#if defined(DISPLAY_PIN_RST) && DISPLAY_PIN_RST >= 0 nrf_gpio_cfg_output(DISPLAY_PIN_RST); - nrf_gpio_pin_write(DISPLAY_PIN_RST, 0); + nrf_gpio_pin_clear(DISPLAY_PIN_RST); NRFX_DELAY_MS(10); - nrf_gpio_pin_write(DISPLAY_PIN_RST, 1); - #endif + nrf_gpio_pin_set(DISPLAY_PIN_RST); +#endif - #if defined(DISPLAY_PIN_BL) && DISPLAY_PIN_BL >= 0 +#if defined(DISPLAY_PIN_BL) && DISPLAY_PIN_BL >= 0 nrf_gpio_cfg_output(DISPLAY_PIN_BL); nrf_gpio_pin_write(DISPLAY_PIN_BL, DISPLAY_BL_ON); - #endif +#endif tft_controller_init(); } @@ -667,13 +667,9 @@ void neopixel_write (uint8_t *pixels) { } #endif -#define TFT_MADCTL_MY 0x80 ///< Page addr order: Bottom to top -#define TFT_MADCTL_MX 0x40 ///< Column addr order: Right to left -#define TFT_MADCTL_MV 0x20 ///< Page/Column order: Reverse Mode ( X <-> Y ) -#define TFT_MADCTL_ML 0x10 ///< LCD refresh Bottom to top -#define TFT_MADCTL_MH 0x04 ///< LCD refresh right to left -#define TFT_MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order -#define TFT_MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order +//--------------------------------------------------------------------+ +// Display controller +//--------------------------------------------------------------------+ #ifdef DISPLAY_CONTROLLER_ST7789 diff --git a/src/boards/feather_nrf52840_sense_tft/board.h b/src/boards/feather_nrf52840_sense_tft/board.h index 3dcea991..902e75ce 100644 --- a/src/boards/feather_nrf52840_sense_tft/board.h +++ b/src/boards/feather_nrf52840_sense_tft/board.h @@ -47,6 +47,32 @@ #define BUTTON_2 _PINNUM(1, 10) // DFU pin #define BUTTON_PULL NRF_GPIO_PIN_PULLUP +//--------------------------------------------------------------------+ +// Display +//--------------------------------------------------------------------+ +#define DISPLAY_CONTROLLER_ST7789 + +#define DISPLAY_PIN_MOSI _PINNUM(0, 5) +#define DISPLAY_PIN_SCK _PINNUM(0, 26) + +#define DISPLAY_PIN_CS _PINNUM(1, 5) +#define DISPLAY_PIN_DC _PINNUM(1, 1) +#define DISPLAY_PIN_RST _PINNUM(1, 3) +#define DISPLAY_PIN_BL _PINNUM(0, 27) +#define DISPLAY_BL_ON 1 // GPIO state to enable back light + +#define DISPLAY_WIDTH 240 +#define DISPLAY_HEIGHT 135 + +#define DISPLAY_COL_OFFSET 53 +#define DISPLAY_ROW_OFFSET 40 + +// Memory Data Access Control & // Vertical Scroll Start Address +#define DISPLAY_MADCTL (TFT_MADCTL_MX) +#define DISPLAY_VSCSAD 0 + +#define DISPLAY_TITLE "Sense TFT" + //--------------------------------------------------------------------+ // BLE OTA //--------------------------------------------------------------------+ @@ -62,7 +88,7 @@ //------------- UF2 -------------// #define UF2_PRODUCT_NAME "Adafruit Feather nRF52840 Sense TFT" -#define UF2_VOLUME_LABEL "FTHRSNSBOOT" +#define UF2_VOLUME_LABEL "SENSTFTBOOT" #define UF2_BOARD_ID "nRF52840-FeatherSenseTFT-revA" #define UF2_INDEX_URL "https://www.adafruit.com/product/" From ed9bf7a8dd2590face6cc173e2239709b6804805 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jan 2024 17:25:53 +0700 Subject: [PATCH 4/5] fix ci --- src/boards/boards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index 563ed6f1..b9ed2c0a 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -24,7 +24,6 @@ #include "boards.h" #include "nrf_pwm.h" -#include "nrf_spim.h" #include "app_scheduler.h" #include "app_timer.h" @@ -180,6 +179,7 @@ void board_teardown(void) { // Display //--------------------------------------------------------------------+ #ifdef DISPLAY_PIN_SCK +#include "nrf_spim.h" #define TFT_MADCTL_MY 0x80 ///< Page addr order: Bottom to top #define TFT_MADCTL_MX 0x40 ///< Column addr order: Right to left From 3d920bf62b57b2c82b24ac2545dc1a94225e8285 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jan 2024 19:06:01 +0700 Subject: [PATCH 5/5] - add slash screen for CLUE - optimize ST77XX_SWRESET, skip if reset pin is available. --- CMakeLists.txt | 13 +++++++++- src/boards/boards.c | 24 ++++++++++------- .../circuitplayground_nrf52840/board.cmake | 1 + src/boards/clue_nrf52840/board.cmake | 1 + src/boards/clue_nrf52840/board.h | 26 +++++++++++++++++++ src/boards/feather_nrf52840_sense_tft/board.h | 2 +- 6 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 src/boards/circuitplayground_nrf52840/board.cmake create mode 100644 src/boards/clue_nrf52840/board.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a124031d..08ff5c2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 3.17) +find_package(Python COMPONENTS Interpreter) if (NOT DEFINED BOARD) message(FATAL_ERROR "BOARD is not defined") @@ -30,6 +31,9 @@ set(SDK ${CMAKE_CURRENT_LIST_DIR}/lib/sdk/components) set(SOFTDEVICE ${CMAKE_CURRENT_LIST_DIR}/lib/softdevice) set(TUSB ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb/src) +set(UF2CONV_PY ${CMAKE_CURRENT_LIST_DIR}/lib/uf2/utils/uf2conv.py) +set(UF2_FAMILY_ID_BOOTLOADER 0xd663823c) + #------------------- # Bootloader #------------------- @@ -301,6 +305,8 @@ add_custom_command(TARGET bootloader POST_BUILD add_custom_command(TARGET bootloader POST_BUILD COMMAND ${CMAKE_OBJCOPY} -Obinary $ $/bootloader.bin COMMAND ${CMAKE_OBJCOPY} -Oihex $ $/bootloader.hex + COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/tools/hexmerge.py --overlap=replace -o $/bootloader_mbr.hex $/bootloader.hex ${MBR_HEX} + COMMAND ${Python_EXECUTABLE} ${UF2CONV_PY} -f ${UF2_FAMILY_ID_BOOTLOADER} -c -o $/bootloader_mbr.uf2 $/bootloader_mbr.hex VERBATIM) #---------------------------------- @@ -311,11 +317,16 @@ if (NOT DEFINED NRFJPROG) set(NRFJPROG nrfjprog) endif() -add_custom_target(flash +add_custom_target(flash-jlink DEPENDS bootloader COMMAND ${NRFJPROG} --program $ --verify --sectoranduicrerase -f nrf52 --reset ) +add_custom_target(flash-uf2 + DEPENDS bootloader + COMMAND ${Python_EXECUTABLE} ${UF2CONV_PY} -f ${UF2_FAMILY_ID_BOOTLOADER} --deploy $/bootloader_mbr.uf2 + ) + add_custom_target(flash-sd COMMAND ${NRFJPROG} --program ${SD_HEX} --verify --sectorerase -f nrf52 --reset ) diff --git a/src/boards/boards.c b/src/boards/boards.c index b9ed2c0a..74840bf0 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -255,6 +255,7 @@ void board_display_init(void) { nrf_gpio_pin_clear(DISPLAY_PIN_RST); NRFX_DELAY_MS(10); nrf_gpio_pin_set(DISPLAY_PIN_RST); + NRFX_DELAY_MS(20); #endif #if defined(DISPLAY_PIN_BL) && DISPLAY_PIN_BL >= 0 @@ -698,6 +699,7 @@ void neopixel_write (uint8_t *pixels) { #define ST77XX_TEOFF 0x34 #define ST77XX_TEON 0x35 #define ST77XX_MADCTL 0x36 +#define ST77XX_VSCSAD 0x37 #define ST77XX_COLMOD 0x3A #define ST77XX_MADCTL_MY 0x80 @@ -725,23 +727,27 @@ void neopixel_write (uint8_t *pixels) { static void tft_controller_init(void) { // Init commands for 7789 screens uint8_t cmdinit_st7789[] = { - // 1: Software reset, no args, w/delay ~150 ms delay + #if !defined(DISPLAY_PIN_RST) || (DISPLAY_PIN_RST < 0) + // Software reset if rst pin not available, no args, w/delay ~150 ms delay ST77XX_SWRESET, ST_CMD_DELAY, 150, - // 2: Out of sleep mode, no args, w/delay 10 ms delay + #endif + // Out of sleep mode, no args, w/delay 10 ms delay ST77XX_SLPOUT, ST_CMD_DELAY, 10, - // 3: Set color mode, 1 arg + delay: 16-bit color, 10 ms delay + // Set color mode, 1 arg + delay: 16-bit color, 10 ms delay ST77XX_COLMOD, 1 + ST_CMD_DELAY, 0x55, 10, - // 4: Mem access ctrl (directions), 1 arg: Row/col addr, bottom-top refresh + // Mem access ctrl (directions), 1 arg: Row/col addr, bottom-top refresh ST77XX_MADCTL, 1, DISPLAY_MADCTL, - // 5: Column addr set, 4 args, no delay: XSTART = 0, XEND = 240 + // Vertical Scroll Start Address of RAM + // ST77XX_VSCSAD, 2, DISPLAY_VSCSAD >> 8, DISPLAY_VSCSAD & 0xFF, + // Column addr set, 4 args, no delay: XSTART = 0, XEND = 240 ST77XX_CASET, 4, 0x00, 0, 0, 240, - // 6: Row addr set, 4 args, no delay: YSTART = 0 YEND = 320 + // Row addr set, 4 args, no delay: YSTART = 0 YEND = 320 ST77XX_RASET, 4, 0x00, 0, 320 >> 8, 320 & 0xFF, - // 7: hack + // Inversion on ST77XX_INVON, ST_CMD_DELAY, 10, - // 8: Normal display on, no args, w/delay 10 ms delay + // Normal display on, no args, w/delay 10 ms delay ST77XX_NORON, ST_CMD_DELAY, 10, - // 9: Main screen turn on, no args, delay 10 ms delay + // Main screen turn on, no args, delay 10 ms delay ST77XX_DISPON, ST_CMD_DELAY, 10 }; diff --git a/src/boards/circuitplayground_nrf52840/board.cmake b/src/boards/circuitplayground_nrf52840/board.cmake new file mode 100644 index 00000000..25daf71d --- /dev/null +++ b/src/boards/circuitplayground_nrf52840/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/clue_nrf52840/board.cmake b/src/boards/clue_nrf52840/board.cmake new file mode 100644 index 00000000..25daf71d --- /dev/null +++ b/src/boards/clue_nrf52840/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/clue_nrf52840/board.h b/src/boards/clue_nrf52840/board.h index efba060a..818f2f4d 100644 --- a/src/boards/clue_nrf52840/board.h +++ b/src/boards/clue_nrf52840/board.h @@ -46,6 +46,32 @@ #define BUTTON_2 _PINNUM(1, 10) // right button #define BUTTON_PULL NRF_GPIO_PIN_PULLUP +//--------------------------------------------------------------------+ +// Display +//--------------------------------------------------------------------+ +#define DISPLAY_CONTROLLER_ST7789 + +#define DISPLAY_PIN_SCK _PINNUM(0, 14) +#define DISPLAY_PIN_MOSI _PINNUM(0, 15) + +#define DISPLAY_PIN_CS _PINNUM(0, 12) +#define DISPLAY_PIN_DC _PINNUM(0, 13) +#define DISPLAY_PIN_RST _PINNUM(1, 3) +#define DISPLAY_PIN_BL _PINNUM(1, 5) +#define DISPLAY_BL_ON 1 // GPIO state to enable back light + +#define DISPLAY_WIDTH 240 +#define DISPLAY_HEIGHT 240 + +#define DISPLAY_COL_OFFSET 0 +#define DISPLAY_ROW_OFFSET 80 + +// Memory Data Access Control & // Vertical Scroll Start Address +#define DISPLAY_MADCTL (TFT_MADCTL_MY) +#define DISPLAY_VSCSAD 0 + +#define DISPLAY_TITLE "CLUE" + //--------------------------------------------------------------------+ // BLE OTA //--------------------------------------------------------------------+ diff --git a/src/boards/feather_nrf52840_sense_tft/board.h b/src/boards/feather_nrf52840_sense_tft/board.h index 902e75ce..b78e2512 100644 --- a/src/boards/feather_nrf52840_sense_tft/board.h +++ b/src/boards/feather_nrf52840_sense_tft/board.h @@ -52,8 +52,8 @@ //--------------------------------------------------------------------+ #define DISPLAY_CONTROLLER_ST7789 -#define DISPLAY_PIN_MOSI _PINNUM(0, 5) #define DISPLAY_PIN_SCK _PINNUM(0, 26) +#define DISPLAY_PIN_MOSI _PINNUM(0, 5) #define DISPLAY_PIN_CS _PINNUM(1, 5) #define DISPLAY_PIN_DC _PINNUM(1, 1)