| |
| #include "stdio.h" |
| #include "stdlib.h" |
| #include "ili9341_pio.h" |
| #include "pico/stdlib.h" |
| #include "hardware/clocks.h" |
| #include "string.h" |
| #include "registers.h" |
| #include "ili9341.h" |
| |
| PIO ili9341_pio = pio1; |
| uint ili9341_sm = 0; |
| uint out_base_pin = 4; |
| uint in_base_pin = 4; |
| uint set_base_pin = 12; |
| |
| static uint8_t p_count = 0; |
| static uint8_t d_count = 0; |
| static uint8_t data_recv = 0; |
| static uint8_t params[8]; |
| static uint32_t data[8]; |
| |
| void ili9341_cmd(uint32_t cmd, uint32_t count, uint8_t *param) |
| { |
| pio_sm_restart(ili9341_pio, ili9341_sm); |
| |
| pio_sm_put_blocking(ili9341_pio, ili9341_sm, cmd); |
| pio_sm_put_blocking(ili9341_pio, ili9341_sm, count); |
| for (int i = 0; i < count; i++) |
| { |
| pio_sm_put_blocking(ili9341_pio, ili9341_sm, param[i]); |
| } |
| } |
| |
| void ili9431_pio_cmd_init(PIO pio, uint sm, uint out_base, uint set_base, uint32_t freq) |
| { |
| uint offset = 0; |
| pio_sm_config c; |
| offset = pio_add_program(pio, &ili9341_pio_cmd_program); |
| c = ili9341_pio_cmd_program_get_default_config(offset); |
| |
| for (int i = 0; i < 8; i++) |
| pio_gpio_init(pio, out_base + i); |
| for (int i = 0; i < 4; i++) |
| pio_gpio_init(pio, set_base + i); |
| |
| pio_sm_set_consecutive_pindirs(pio, sm, out_base, 8, true); |
| pio_sm_set_consecutive_pindirs(pio, sm, set_base, 4, true); |
| |
| sm_config_set_out_pins(&c, out_base, 8); |
| sm_config_set_set_pins(&c, set_base, 4); |
| |
| sm_config_set_out_shift(&c, true, false, 32); |
| |
| float div = clock_get_hz(clk_sys) / freq; |
| sm_config_set_clkdiv(&c, div); |
| |
| pio_sm_init(pio, sm, offset, &c); |
| pio_sm_set_enabled(pio, sm, true); |
| } |
| |
| uint16_t ili9341_color_565RGB(uint8_t R, uint8_t G, uint8_t B) |
| { |
| uint16_t c; |
| c = (((uint16_t)R) >> 3) << 11 | (((uint16_t)G) >> 2) << 5 | ((uint16_t)B) >> 3; |
| return c; |
| } |
| void ili9341_set_address_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) |
| { |
| uint8_t addr[4]; |
| addr[0] = (uint8_t)(x1 >> 8); |
| addr[1] = (uint8_t)(x1 & 0xff); |
| addr[2] = (uint8_t)(x2 >> 8); |
| addr[3] = (uint8_t)(x2 & 0xff); |
| ili9341_cmd(ILI9341_COLADDRSET, 4, addr); |
| |
| addr[0] = (uint8_t)(y1 >> 8); |
| addr[1] = (uint8_t)(y1 & 0xff); |
| addr[2] = (uint8_t)(y2 >> 8); |
| addr[3] = (uint8_t)(y2 & 0xff); |
| ili9341_cmd(ILI9341_PAGEADDRSET, 4, addr); |
| |
| ili9341_cmd(ILI9341_MEMORYWRITE, 0, NULL); |
| } |
| |
| void ili9341_draw_pixel(uint16_t x, uint16_t y, uint16_t color) |
| { |
| if (x < 0 || x > SCREEN_WIDTH || y < 0 || y > SCREEN_HEIGHT) |
| return; |
| ili9341_set_address_window(x, y, x, y); |
| ili9341_cmd(ILI9341_NOP, 2, (uint8_t[2]){(uint8_t)(color >> 8), (uint8_t)color}); |
| } |
| void ili9341_invert_display(bool invert) |
| { |
| if (invert) |
| ili9341_cmd(ILI9341_INVERTON, 0, NULL); |
| else |
| ili9341_cmd(ILI9341_INVERTOFF, 0, NULL); |
| } |
| void ili9341_fill_rect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) |
| { |
| if (x < 0) |
| x = 0; |
| if (y < 0) |
| y = 0; |
| if (x + width > SCREEN_WIDTH) |
| width = SCREEN_WIDTH - x; |
| if (y + height > SCREEN_HEIGHT) |
| height = SCREEN_HEIGHT - y; |
| ili9341_set_address_window(x, y, x + width, y + height); |
| for (int j = y; j < y + height; j++) |
| for (int i = x; i < x + width; i++) |
| ili9341_cmd(ILI9341_NOP, 2, (uint8_t[2]){(uint8_t)(color >> 8), (uint8_t)(color & 0x00ff)}); |
| } |
| |
| void ili9341_draw_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color) |
| { |
| |
| int dx = abs(x1 - x0); |
| int sx = x0 < x1 ? 1 : -1; |
| int dy = -abs(y1 - y0); |
| int sy = y0 < y1 ? 1 : -1; |
| int error = dx + dy; |
| int e2; |
| while (1) |
| { |
| |
| ili9341_draw_pixel(x0, y0, color); |
| if (x0 == x1 && y0 == y1) |
| break; |
| e2 = 2 * error; |
| if (e2 >= dy) |
| { |
| if (x0 == x1) |
| break; |
| error = error + dy; |
| x0 = x0 + sx; |
| } |
| if (e2 <= dx) |
| { |
| if (y0 == y1) |
| break; |
| error = error + dx; |
| y0 = y0 + sy; |
| } |
| } |
| } |
| |
| void ili9341_draw_bitmap(uint16_t x, uint16_t y, const tImage *bitmap) |
| { |
| uint16_t width = 0, height = 0; |
| width = bitmap->width; |
| height = bitmap->height; |
| |
| uint16_t total_pixels = width * height; |
| |
| ili9341_set_address_window(x, y, x + width - 1, y + height - 1); |
| |
| for (uint16_t pixels = 0; pixels < total_pixels; pixels++) |
| { |
| ili9341_cmd(ILI9341_NOP, 1, (uint8_t[1]){(uint8_t)(bitmap->data[2 * pixels])}); |
| ili9341_cmd(ILI9341_NOP, 1, (uint8_t[1]){(uint8_t)(bitmap->data[2 * pixels + 1])}); |
| } |
| } |
| void ili9431_init_config() |
| { |
| ili9341_cmd(ILI9341_SOFTRESET, 0, NULL); |
| sleep_ms(150); |
| ili9341_cmd(ILI9341_DISPLAYOFF, 0, NULL); |
| sleep_ms(150); |
| ili9341_cmd(ILI9341_PIXELFORMAT, 1, (uint8_t[1]){0x55}); |
| ili9341_cmd(ILI9341_POWERCONTROL1, 1, (uint8_t[1]){0x05}); |
| ili9341_cmd(ILI9341_POWERCONTROL2, 1, (uint8_t[1]){0x10}); |
| ili9341_cmd(ILI9341_VCOMCONTROL1, 2, (uint8_t[2]){0x3E, 0x28}); |
| ili9341_cmd(ILI9341_VCOMCONTROL2, 1, (uint8_t[1]){0x86}); |
| ili9341_cmd(ILI9341_MADCTL, 1, (uint8_t[1]){0x40}); |
| ili9341_cmd(ILI9341_FRAMECONTROL, 2, (uint8_t[2]){0x00, 0x1B}); |
| ili9341_cmd(ILI9341_DISPLAYFUNC, 4, (uint8_t[4]){0x0A, 0xA2, 0x27, 0x04}); |
| ili9341_cmd(ILI9341_GAMMASET, 1, (uint8_t[1]){0x01}); |
| |
| ili9341_cmd(ILI9341_PGAMCOR, 15, (uint8_t[15]){0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1, 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00}); |
| ili9341_cmd(ILI9341_NGAMCOR, 15, (uint8_t[15]){0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1, 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f}); |
| |
| ili9341_cmd(ILI9341_SLEEPOUT, 0, NULL); |
| sleep_ms(150); |
| ili9341_cmd(ILI9341_DISPLAYON, 0, NULL); |
| sleep_ms(500); |
| } |
| void ili9341_init() |
| { |
| |
| ili9431_pio_cmd_init(ili9341_pio, ili9341_sm, out_base_pin, set_base_pin, 70 * 1000000); |
| ili9431_init_config(); |
| } |
沒有留言:
張貼留言