mirror of
https://github.com/0015/ThatProject.git
synced 2026-01-12 09:17:42 +03:00
ZX2D10GE01R-V4848_Arduino
This commit is contained in:
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* Project ZX2D10GE01R-V4848 for Arduino
|
||||||
|
* Description: The base project that can be used in the Arduino environment using the ZX2D10GE01R-V4848 device
|
||||||
|
* Author: Eric Nam
|
||||||
|
* Date: 03-18-2023
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ** Prerequisites **
|
||||||
|
// ESP32 Arduino 2.0.7 based on ESP-IDF 4.4.4
|
||||||
|
// https://github.com/espressif/arduino-esp32
|
||||||
|
|
||||||
|
// LVGL version 8.3.5
|
||||||
|
// https://github.com/lvgl/lvgl
|
||||||
|
|
||||||
|
// GFX Library for Arduino 1.3.2
|
||||||
|
// https://github.com/moononournation/Arduino_GFX
|
||||||
|
|
||||||
|
// ZX2D10GE01R-V4848 for ESP-IDF
|
||||||
|
// https://github.com/wireless-tag-com/ZX2D10GE01R-V4848
|
||||||
|
|
||||||
|
#include <lvgl.h>
|
||||||
|
#include <Arduino_GFX_Library.h>
|
||||||
|
#include "button.hpp"
|
||||||
|
#include "mt8901.hpp"
|
||||||
|
|
||||||
|
#define ECO_O(y) (y > 0) ? -1 : 1
|
||||||
|
#define ECO_STEP(x) x ? ECO_O(x) : 0
|
||||||
|
#define GFX_BL 38
|
||||||
|
|
||||||
|
Arduino_DataBus *bus = new Arduino_SWSPI(
|
||||||
|
GFX_NOT_DEFINED /* DC */, 21 /* CS */,
|
||||||
|
47 /* SCK */, 41 /* MOSI */, GFX_NOT_DEFINED /* MISO */);
|
||||||
|
Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel(
|
||||||
|
39 /* DE */, 48 /* VSYNC */, 40 /* HSYNC */, 45 /* PCLK */,
|
||||||
|
10 /* R0 */, 16 /* R1 */, 9 /* R2 */, 15 /* R3 */, 46 /* R4 */,
|
||||||
|
8 /* G0 */, 13 /* G1 */, 18 /* G2 */, 12 /* G3 */, 11 /* G4 */, 17 /* G5 */,
|
||||||
|
47 /* B0 */, 41 /* B1 */, 0 /* B2 */, 42 /* B3 */, 14 /* B4 */,
|
||||||
|
1 /* hsync_polarity */, 10 /* hsync_front_porch */, 10 /* hsync_pulse_width */, 10 /* hsync_back_porch */,
|
||||||
|
1 /* vsync_polarity */, 14 /* vsync_front_porch */, 2 /* vsync_pulse_width */, 12 /* vsync_back_porch */);
|
||||||
|
Arduino_RGB_Display *gfx = new Arduino_RGB_Display(
|
||||||
|
480 /* width */, 480 /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
|
||||||
|
bus, GFX_NOT_DEFINED /* RST */, st7701_type7_init_operations, sizeof(st7701_type7_init_operations));
|
||||||
|
|
||||||
|
static button_t *g_btn;
|
||||||
|
static uint32_t screenWidth;
|
||||||
|
static uint32_t screenHeight;
|
||||||
|
static lv_disp_draw_buf_t draw_buf;
|
||||||
|
static lv_color_t *disp_draw_buf;
|
||||||
|
static lv_disp_drv_t disp_drv;
|
||||||
|
static lv_group_t *lv_group;
|
||||||
|
static lv_obj_t *lv_btn_1;
|
||||||
|
static lv_obj_t *lv_btn_2;
|
||||||
|
|
||||||
|
/* Display flushing */
|
||||||
|
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
|
||||||
|
uint32_t w = (area->x2 - area->x1 + 1);
|
||||||
|
uint32_t h = (area->y2 - area->y1 + 1);
|
||||||
|
|
||||||
|
#if (LV_COLOR_16_SWAP != 0)
|
||||||
|
gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
|
||||||
|
#else
|
||||||
|
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lv_disp_flush_ready(disp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void encoder_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
|
||||||
|
static int16_t cont_last = 0;
|
||||||
|
int16_t cont_now = mt8901_get_count();
|
||||||
|
data->enc_diff = ECO_STEP(cont_now - cont_last);
|
||||||
|
cont_last = cont_now;
|
||||||
|
if (button_isPressed(g_btn)) {
|
||||||
|
data->state = LV_INDEV_STATE_PR;
|
||||||
|
} else {
|
||||||
|
data->state = LV_INDEV_STATE_REL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
gfx->begin();
|
||||||
|
gfx->fillScreen(BLACK);
|
||||||
|
|
||||||
|
pinMode(GFX_BL, OUTPUT);
|
||||||
|
digitalWrite(GFX_BL, HIGH);
|
||||||
|
|
||||||
|
lv_init();
|
||||||
|
|
||||||
|
// Hardware Button
|
||||||
|
g_btn = button_attch(3, 0, 10);
|
||||||
|
|
||||||
|
// Magnetic Encoder
|
||||||
|
mt8901_init(5, 6);
|
||||||
|
|
||||||
|
screenWidth = gfx->width();
|
||||||
|
screenHeight = gfx->height();
|
||||||
|
|
||||||
|
// Must to use PSRAM
|
||||||
|
disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * 32, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||||
|
|
||||||
|
if (!disp_draw_buf) {
|
||||||
|
Serial.println("LVGL disp_draw_buf allocate failed!");
|
||||||
|
} else {
|
||||||
|
lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * 32);
|
||||||
|
|
||||||
|
/* Initialize the display */
|
||||||
|
lv_disp_drv_init(&disp_drv);
|
||||||
|
/* Change the following line to your display resolution */
|
||||||
|
disp_drv.hor_res = screenWidth;
|
||||||
|
disp_drv.ver_res = screenHeight;
|
||||||
|
disp_drv.flush_cb = my_disp_flush;
|
||||||
|
disp_drv.draw_buf = &draw_buf;
|
||||||
|
lv_disp_drv_register(&disp_drv);
|
||||||
|
|
||||||
|
/* Initialize the input device driver */
|
||||||
|
static lv_indev_drv_t indev_drv;
|
||||||
|
lv_indev_drv_init(&indev_drv);
|
||||||
|
indev_drv.read_cb = encoder_read;
|
||||||
|
indev_drv.type = LV_INDEV_TYPE_ENCODER;
|
||||||
|
lv_indev_drv_register(&indev_drv);
|
||||||
|
|
||||||
|
init_lv_group();
|
||||||
|
lv_example_get_started_1();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
lv_timer_handler(); /* let the GUI do its work */
|
||||||
|
delay(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_lv_group() {
|
||||||
|
lv_group = lv_group_create();
|
||||||
|
lv_group_set_default(lv_group);
|
||||||
|
|
||||||
|
lv_indev_t *cur_drv = NULL;
|
||||||
|
for (;;) {
|
||||||
|
cur_drv = lv_indev_get_next(cur_drv);
|
||||||
|
if (!cur_drv) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur_drv->driver->type == LV_INDEV_TYPE_ENCODER) {
|
||||||
|
lv_indev_set_group(cur_drv, lv_group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btn_event_cb(lv_event_t *e) {
|
||||||
|
lv_event_code_t code = lv_event_get_code(e);
|
||||||
|
lv_obj_t *btn = lv_event_get_target(e);
|
||||||
|
if (code == LV_EVENT_CLICKED) {
|
||||||
|
|
||||||
|
uint8_t cnt = 0;
|
||||||
|
if (btn == lv_btn_1) {
|
||||||
|
static uint8_t cnt_1 = 0;
|
||||||
|
cnt_1++;
|
||||||
|
cnt = cnt_1;
|
||||||
|
} else {
|
||||||
|
static uint8_t cnt_2 = 0;
|
||||||
|
cnt_2++;
|
||||||
|
cnt = cnt_2;
|
||||||
|
}
|
||||||
|
/*Get the first child of the button which is the label and change its text*/
|
||||||
|
lv_obj_t *label = lv_obj_get_child(btn, 0);
|
||||||
|
lv_label_set_text_fmt(label, "Button: %d", cnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a button with a label and react on click event.
|
||||||
|
*/
|
||||||
|
void lv_example_get_started_1(void) {
|
||||||
|
lv_btn_1 = lv_btn_create(lv_scr_act()); /*Add a button the current screen*/
|
||||||
|
lv_obj_set_size(lv_btn_1, 120, 50); /*Set its size*/
|
||||||
|
lv_obj_align(lv_btn_1, LV_ALIGN_CENTER, 0, -40); /*Set its position*/
|
||||||
|
lv_obj_add_event_cb(lv_btn_1, btn_event_cb, LV_EVENT_ALL, NULL); /*Assign a callback to the button*/
|
||||||
|
|
||||||
|
lv_obj_t *label = lv_label_create(lv_btn_1); /*Add a label to the button*/
|
||||||
|
lv_label_set_text(label, "Button"); /*Set the labels text*/
|
||||||
|
lv_obj_center(label);
|
||||||
|
|
||||||
|
lv_btn_2 = lv_btn_create(lv_scr_act()); /*Add a button the current screen*/
|
||||||
|
lv_obj_set_style_bg_color(lv_btn_2, lv_palette_main(LV_PALETTE_RED), LV_PART_MAIN); /*Set its main color*/
|
||||||
|
|
||||||
|
lv_obj_set_size(lv_btn_2, 120, 50); /*Set its size*/
|
||||||
|
lv_obj_align(lv_btn_2, LV_ALIGN_CENTER, 0, 40); /*Set its position*/
|
||||||
|
lv_obj_add_event_cb(lv_btn_2, btn_event_cb, LV_EVENT_ALL, NULL); /*Assign a callback to the button*/
|
||||||
|
|
||||||
|
lv_obj_t *label2 = lv_label_create(lv_btn_2); /*Add a label to the button*/
|
||||||
|
lv_label_set_text(label2, "Button"); /*Set the labels text*/
|
||||||
|
lv_obj_center(label2);
|
||||||
|
}
|
||||||
92
ESP32_LVGL/LVGL8/ZX2D10GE01R-V4848_Arduino/button.cpp
Executable file
92
ESP32_LVGL/LVGL8/ZX2D10GE01R-V4848_Arduino/button.cpp
Executable file
@@ -0,0 +1,92 @@
|
|||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "freertos/xtensa_api.h"
|
||||||
|
#endif
|
||||||
|
#include "freertos/portmacro.h"
|
||||||
|
#include "rom/gpio.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "button.hpp"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
static QueueHandle_t btn_queue = NULL;
|
||||||
|
|
||||||
|
static void IRAM_ATTR gpio_isr_handler(void* arg) {
|
||||||
|
xQueueSendFromISR(btn_queue, &arg, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void button_update_task(void* arg) {
|
||||||
|
button_t* btn = NULL;
|
||||||
|
for (;;) {
|
||||||
|
xQueueReceive(btn_queue, &btn, portMAX_DELAY);
|
||||||
|
uint32_t time = xTaskGetTickCount();
|
||||||
|
if (time - btn->last_press_time < btn->filter_time) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (time - btn->last_release_time < btn->filter_time) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(btn->filter_time));
|
||||||
|
if (gpio_get_level(gpio_num_t(btn->pin_io)) == btn->pressed_value) {
|
||||||
|
btn->pressed = 1;
|
||||||
|
btn->last_press_time = time;
|
||||||
|
} else {
|
||||||
|
btn->released = 1;
|
||||||
|
btn->last_release_time = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t button_isPressed(button_t* button) {
|
||||||
|
return gpio_get_level(gpio_num_t(button->pin_io)) == button->pressed_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t button_isRelease(button_t* button) {
|
||||||
|
return !(gpio_get_level(gpio_num_t(button->pin_io)) == button->pressed_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t button_wasPressed(button_t* button) {
|
||||||
|
uint32_t time = xTaskGetTickCount();
|
||||||
|
uint8_t pressed = button->pressed;
|
||||||
|
button->pressed = 0;
|
||||||
|
return pressed && ((time - button->last_press_time) < 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t button_wasPressFor(button_t* button, uint32_t press_time) {
|
||||||
|
uint32_t time_now = xTaskGetTickCount();
|
||||||
|
if (button->pressed && ((time_now - button->last_press_time) > press_time) && button->last_press_time > button->last_release_time) {
|
||||||
|
button->pressed = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t button_wasRelease(button_t* button) {
|
||||||
|
uint32_t time = xTaskGetTickCount();
|
||||||
|
uint8_t released = button->released;
|
||||||
|
button->released = 0;
|
||||||
|
return released && ((time - button->last_release_time) < 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
button_t* button_attch(uint16_t gpio_pin, uint8_t press_value, uint16_t filter_time) {
|
||||||
|
if (btn_queue == NULL) {
|
||||||
|
btn_queue = xQueueCreate(10, sizeof(button_t*));
|
||||||
|
xTaskCreatePinnedToCore(button_update_task, "btn", 2 * 1024, NULL, 4, NULL, 1);
|
||||||
|
gpio_install_isr_service(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
button_t* button = (button_t*)calloc(1, sizeof(button_t));
|
||||||
|
button->pin_io = gpio_pin;
|
||||||
|
button->pressed_value = press_value;
|
||||||
|
button->filter_time = filter_time;
|
||||||
|
|
||||||
|
gpio_pad_select_gpio(gpio_num_t(button->pin_io));
|
||||||
|
gpio_set_direction(gpio_num_t(button->pin_io), GPIO_MODE_INPUT);
|
||||||
|
|
||||||
|
gpio_set_intr_type(gpio_num_t(button->pin_io), GPIO_INTR_ANYEDGE);
|
||||||
|
gpio_isr_handler_add(gpio_num_t(button->pin_io), gpio_isr_handler, button);
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
20
ESP32_LVGL/LVGL8/ZX2D10GE01R-V4848_Arduino/button.hpp
Executable file
20
ESP32_LVGL/LVGL8/ZX2D10GE01R-V4848_Arduino/button.hpp
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t pin_io;
|
||||||
|
uint8_t pressed_value;
|
||||||
|
uint8_t pressed;
|
||||||
|
uint8_t released;
|
||||||
|
uint32_t last_press_time;
|
||||||
|
uint32_t last_release_time;
|
||||||
|
uint16_t filter_time;
|
||||||
|
} button_t;
|
||||||
|
|
||||||
|
uint8_t button_isPressed(button_t* button);
|
||||||
|
uint8_t button_isRelease(button_t* button);
|
||||||
|
uint8_t button_wasPressed(button_t* button);
|
||||||
|
uint8_t button_wasRelease(button_t* button);
|
||||||
|
uint8_t button_wasPressFor(button_t* button, uint32_t press_time);
|
||||||
|
button_t* button_attch(uint16_t gpio_pin, uint8_t press_value, uint16_t filter_time);
|
||||||
44
ESP32_LVGL/LVGL8/ZX2D10GE01R-V4848_Arduino/mt8901.cpp
Executable file
44
ESP32_LVGL/LVGL8/ZX2D10GE01R-V4848_Arduino/mt8901.cpp
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
#include "driver/pcnt.h"
|
||||||
|
|
||||||
|
#define PCNT_H_LIM_VAL INT16_MAX
|
||||||
|
#define PCNT_L_LIM_VAL INT16_MIN
|
||||||
|
|
||||||
|
static pcnt_unit_t unit = PCNT_UNIT_0;
|
||||||
|
|
||||||
|
void mt8901_init(int16_t sig_pin, int16_t dir_pin) {
|
||||||
|
/* Prepare configuration for the PCNT unit */
|
||||||
|
pcnt_config_t pcnt_config;
|
||||||
|
pcnt_config.pulse_gpio_num = sig_pin;
|
||||||
|
pcnt_config.ctrl_gpio_num = dir_pin;
|
||||||
|
pcnt_config.channel = PCNT_CHANNEL_0;
|
||||||
|
pcnt_config.unit = unit;
|
||||||
|
pcnt_config.pos_mode = PCNT_COUNT_DEC;
|
||||||
|
pcnt_config.neg_mode = PCNT_COUNT_INC;
|
||||||
|
pcnt_config.lctrl_mode = PCNT_MODE_REVERSE;
|
||||||
|
pcnt_config.hctrl_mode = PCNT_MODE_KEEP;
|
||||||
|
pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;
|
||||||
|
pcnt_config.counter_l_lim = PCNT_L_LIM_VAL;
|
||||||
|
|
||||||
|
/* Initialize PCNT unit */
|
||||||
|
pcnt_unit_config(&pcnt_config);
|
||||||
|
|
||||||
|
/* Configure and enable the input filter */
|
||||||
|
pcnt_set_filter_value(unit, 1000);
|
||||||
|
pcnt_filter_enable(unit);
|
||||||
|
|
||||||
|
/* Initialize PCNT's counter */
|
||||||
|
pcnt_counter_pause(unit);
|
||||||
|
pcnt_counter_clear(unit);
|
||||||
|
|
||||||
|
/* Everything is set up, now go to counting */
|
||||||
|
pcnt_counter_resume(unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t mt8901_get_count() {
|
||||||
|
int16_t count = 0;
|
||||||
|
pcnt_get_counter_value(unit, &count);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
7
ESP32_LVGL/LVGL8/ZX2D10GE01R-V4848_Arduino/mt8901.hpp
Executable file
7
ESP32_LVGL/LVGL8/ZX2D10GE01R-V4848_Arduino/mt8901.hpp
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
void mt8901_init(int16_t sig_pin, int16_t dir_pin);
|
||||||
|
|
||||||
|
int16_t mt8901_get_count();
|
||||||
Reference in New Issue
Block a user