Created
August 27, 2024 10:37
-
-
Save denizzzka/29d85889a4e0fe0d90bb4df8b1702262 to your computer and use it in GitHub Desktop.
ESP32c3 and ILI9341 display using Dlang: wrong colors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module main; | |
| import esp_idf_binding; | |
| enum CONFIG_FREERTOS_HZ = 1000; | |
| enum portTICK_PERIOD_MS = 1000 / CONFIG_FREERTOS_HZ; | |
| void ledBlink(gpio_num_t gpio, int delayMs) nothrow | |
| { | |
| gpio_reset_pin(gpio); | |
| /* Set the GPIO as a push/pull output */ | |
| gpio_set_direction(gpio, gpio_mode_t.GPIO_MODE_OUTPUT); | |
| ubyte s_led_state; | |
| while (1) { | |
| gpio_set_level(gpio, s_led_state); | |
| s_led_state = !s_led_state; | |
| vTaskDelay(delayMs / portTICK_PERIOD_MS); | |
| } | |
| } | |
| extern(C) export void d_app_main() nothrow | |
| { | |
| import core.thread; | |
| try | |
| { | |
| auto ledBlink1 = new Thread( | |
| () =>ledBlink(gpio_num_t.GPIO_NUM_12, 20 / portTICK_PERIOD_MS) | |
| ).start; | |
| auto ledBlink2 = new Thread( | |
| () =>ledBlink(gpio_num_t.GPIO_NUM_13, 30 / portTICK_PERIOD_MS) | |
| ).start; | |
| } | |
| catch(Exception e){} | |
| auto displ = new Displ(); | |
| auto active_scr = displ.displ.lv_display_get_screen_active(); | |
| auto black = lv_color_t(0, 0, 0); | |
| lv_obj_set_style_bg_color(active_scr, black, 0); | |
| void createSquare(ref lv_style_t style, lv_align_t _align) | |
| { | |
| auto rect = lv_obj_create(active_scr); | |
| lv_obj_set_size(rect , 70, 40); | |
| lv_obj_align(rect, _align, 0, 0); | |
| lv_obj_add_style(rect, &style, 0); | |
| } | |
| auto red_col = lv_color_t(0, 0, 255); | |
| lv_style_t red_style; | |
| lv_style_init(&red_style); | |
| lv_style_set_border_width(&red_style, 5); | |
| lv_style_set_outline_width(&red_style, 5); | |
| lv_style_set_border_color(&red_style, red_col); | |
| lv_style_set_outline_color(&red_style, black); | |
| lv_style_set_text_color(&red_style, black); | |
| lv_style_set_text_decor(&red_style, _lv_text_decor_t.LV_TEXT_DECOR_UNDERLINE); | |
| lv_style_t green; | |
| lv_style_init(&green); | |
| lv_style_set_border_width(&green, 5); | |
| lv_style_set_outline_width(&green, 5); | |
| lv_style_set_border_color(&green, lv_color_t(0, 255, 0)); | |
| lv_style_set_outline_color(&green, lv_color_t(0, 255, 0)); | |
| lv_style_t blue; | |
| lv_style_init(&blue); | |
| lv_style_set_border_width(&blue, 5); | |
| lv_style_set_outline_width(&blue, 5); | |
| lv_style_set_border_color(&blue, lv_color_t(255, 0, 0)); | |
| lv_style_set_outline_color(&blue, lv_color_t(255, 0, 0)); | |
| lv_style_set_text_color(&blue, black); | |
| createSquare(red_style, _lv_align_t.LV_ALIGN_BOTTOM_RIGHT); | |
| createSquare(green, _lv_align_t.LV_ALIGN_BOTTOM_MID); | |
| createSquare(blue, _lv_align_t.LV_ALIGN_BOTTOM_LEFT); | |
| lv_obj_t* label = lv_label_create(active_scr); | |
| lv_label_set_text(label, cast(const ubyte*) "Hello, world!"); | |
| lv_obj_align(label, _lv_align_t.LV_ALIGN_CENTER, 0, 0); | |
| lv_obj_add_style(label, &blue, 0); | |
| try | |
| while(true) | |
| { | |
| vTaskDelay(1000 / portTICK_PERIOD_MS); | |
| } | |
| catch(Exception e){} | |
| } | |
| lv_color_t lv_color_hex(uint32_t c) nothrow | |
| { | |
| lv_color_t ret; | |
| ret.red = (c >> 16) & 0xff; | |
| ret.green = (c >> 8) & 0xff; | |
| ret.blue = (c >> 0) & 0xff; | |
| return ret; | |
| } | |
| void lcd_hello_world(lv_obj_t* active_scr) | |
| { | |
| /*Change the active screen's background color*/ | |
| static uint color = 0x003a57; | |
| color+=100; | |
| lv_obj_set_style_bg_color(active_scr, lv_color_hex(color), _lv_part_t.LV_PART_MAIN); | |
| } | |
| class Displ | |
| { | |
| import core.thread: Thread; | |
| enum sizeX = 240; | |
| enum sizeY = 320; | |
| enum host = spi_host_device_t.SPI2_HOST; | |
| enum cmdPin = gpio_num_t.GPIO_NUM_6; | |
| private __gshared static Thread ticks; | |
| private __gshared static Thread relatedTasks; | |
| private esp_lcd_panel_t* panel; | |
| private esp_lcd_panel_io_t* panel_handle; | |
| private lv_display_t* displ; | |
| private void startLvRoutines() | |
| { | |
| lv_tick_set_cb(&xTaskGetTickCount); | |
| static extern(C) void delay(uint ms) => vTaskDelay(ms / portTICK_PERIOD_MS); | |
| lv_delay_set_cb(&delay); | |
| relatedTasks = new Thread((){ | |
| while(true) | |
| { | |
| auto time_till_next_ms = lv_timer_handler(); | |
| lv_delay_ms(50); | |
| } | |
| }).start; | |
| } | |
| private static void initSPI() nothrow | |
| { | |
| //To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. More means more memory use, | |
| //but less overhead for setting up / finishing transfers. Make sure 240 is dividable by this. | |
| enum PARALLEL_LINES = 16; | |
| spi_bus_config_t bus_cfg; | |
| //GPIO nums meant here: | |
| bus_cfg.miso_io_num = 10; | |
| bus_cfg.mosi_io_num = 3; | |
| bus_cfg.sclk_io_num = 2; | |
| bus_cfg.quadwp_io_num = -1; | |
| bus_cfg.quadhd_io_num = -1; | |
| bus_cfg.max_transfer_sz = PARALLEL_LINES * sizeX * 2 + 8; | |
| //Initialize the SPI bus | |
| auto ret = spi_bus_initialize(host, &bus_cfg, spi_common_dma_t.SPI_DMA_CH_AUTO); | |
| ESP_ERROR_CHECK(ret); | |
| } | |
| private void initEspPanelDrv() nothrow | |
| { | |
| esp_lcd_panel_io_spi_config_t displaySpiDevCfg = { | |
| dc_gpio_num: cmdPin, | |
| cs_gpio_num: 7, //CS pin | |
| pclk_hz: 40 * 1000 * 1000, | |
| lcd_cmd_bits: 8, | |
| lcd_param_bits: 8, | |
| spi_mode: 0, //not Dual or Quad SPI, etc | |
| trans_queue_depth: 10, //TODO: We want to be able to queue 7 transactions at a time | |
| on_color_trans_done: ¬ify_lvgl_flush_ready, | |
| user_ctx: &displ, | |
| }; | |
| //Attach the LCD to the SPI bus | |
| ESP_ERROR_CHECK( | |
| esp_lcd_new_panel_io_spi(host, &displaySpiDevCfg, &panel_handle) | |
| ); | |
| assert(panel_handle !is null); | |
| esp_lcd_panel_dev_config_t cfg = { | |
| reset_gpio_num: gpio_num_t.GPIO_NUM_8, | |
| bits_per_pixel: 16, | |
| }; | |
| cfg.rgb_ele_order = lcd_rgb_element_order_t.LCD_RGB_ELEMENT_ORDER_BGR; | |
| ESP_ERROR_CHECK( | |
| //TODO: panel_handle -> panel_io | |
| esp_lcd_new_panel_ili9341(panel_handle, &cfg, &panel) | |
| ); | |
| ESP_ERROR_CHECK( | |
| esp_lcd_panel_reset(panel) | |
| ); | |
| ESP_ERROR_CHECK( | |
| esp_lcd_panel_init(panel) | |
| ); | |
| //~ ESP_ERROR_CHECK( | |
| //~ esp_lcd_panel_invert_color(panel, true) | |
| //~ ); | |
| ESP_ERROR_CHECK( | |
| esp_lcd_panel_disp_on_off(panel, true) | |
| ); | |
| ESP_ERROR_CHECK( | |
| esp_lcd_panel_mirror(panel, true, false) | |
| ); | |
| } | |
| private void initLvBinding() nothrow | |
| { | |
| lv_init(); | |
| /* Allocate draw buffers. Use two partial buffers of 1/10th size of the screen */ | |
| const buf_size = sizeX * sizeY / 10 * lv_color_t.sizeof; | |
| auto buf1 = lv_malloc(buf_size); | |
| assert(buf1 !is null); | |
| auto buf2 = lv_malloc(buf_size); | |
| assert(buf2 !is null); | |
| //Initialize driver | |
| displ = lv_display_create(sizeX, sizeY); | |
| lv_display_set_color_format(displ, cast(ubyte) _lv_color_format_t.LV_COLOR_FORMAT_RGB565); | |
| lv_display_set_buffers(displ, buf1, buf2, buf_size, lv_display_render_mode_t.LV_DISPLAY_RENDER_MODE_PARTIAL); | |
| lv_display_set_flush_cb(displ, &flush); | |
| lv_display_set_user_data(displ, panel); // pass spi pointer to callback functions | |
| } | |
| this() nothrow | |
| { | |
| initSPI(); | |
| initEspPanelDrv(); | |
| initLvBinding(); | |
| displ.lv_display_set_theme = lv_theme_simple_get; | |
| try | |
| startLvRoutines(); | |
| catch(Exception e){ abort(); } | |
| } | |
| private extern(C) static void flush(lv_display_t* disp, const lv_area_t* area, ubyte* color_map) | |
| { | |
| auto panel = cast(esp_lcd_panel_t*) lv_display_get_user_data(disp); | |
| // copy a buffer's content to a specific area of the display | |
| esp_lcd_panel_draw_bitmap(panel, area.x1, area.y1, area.x2 + 1, area.y2 + 1, color_map); | |
| } | |
| private extern(C) static bool notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t* edata, void* user_ctx) | |
| { | |
| auto disp = cast(lv_display_t**) user_ctx; | |
| lv_display_flush_ready(*disp); | |
| return false; | |
| } | |
| } | |
| void ESP_ERROR_CHECK(esp_err_t ret) nothrow | |
| { | |
| assert(ret == 0 /*ESP_OK*/); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment