This commit is contained in:
Joshua King
2026-10-02 12:23:58 -04:00
parent f0af1dbbcb
commit ad1e7e6d01
219 changed files with 488314 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
#include "BAT_Driver.h"
float BAT_analogVolts = 0;
void BAT_Init(void)
{
//set the resolution to 12 bits (0-4095)
analogReadResolution(12);
}
float BAT_Get_Volts(void)
{
int Volts = analogReadMilliVolts(BAT_ADC_PIN); // millivolts
BAT_analogVolts = (float)(Volts * 3.0 / 1000.0) / Measurement_offset;
// printf("BAT voltage : %.2f V\r\n", BAT_analogVolts);
return BAT_analogVolts;
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <Arduino.h>
#define BAT_ADC_PIN 4
#define Measurement_offset 0.992857
extern float BAT_analogVolts;
void BAT_Init(void);
float BAT_Get_Volts(void);
+428
View File
@@ -0,0 +1,428 @@
#include "Display_ST7701.h"
spi_device_handle_t SPI_handle = NULL;
esp_lcd_panel_handle_t panel_handle = NULL;
void ST7701_WriteCommand(uint8_t cmd)
{
spi_transaction_t spi_tran = {
.cmd = 0,
.addr = cmd,
.length = 0,
.rxlength = 0,
};
spi_device_transmit(SPI_handle, &spi_tran);
}
void ST7701_WriteData(uint8_t data)
{
spi_transaction_t spi_tran = {
.cmd = 1,
.addr = data,
.length = 0,
.rxlength = 0,
};
spi_device_transmit(SPI_handle, &spi_tran);
}
void ST7701_CS_EN(){
Set_EXIO(EXIO_PIN3,Low);
vTaskDelay(pdMS_TO_TICKS(10));
}
void ST7701_CS_Dis(){
Set_EXIO(EXIO_PIN3,High);
vTaskDelay(pdMS_TO_TICKS(10));
}
void ST7701_Reset(){
Set_EXIO(EXIO_PIN1,Low);
vTaskDelay(pdMS_TO_TICKS(10));
Set_EXIO(EXIO_PIN1,High);
vTaskDelay(pdMS_TO_TICKS(50));
}
void ST7701_Init()
{
spi_bus_config_t buscfg = {
.mosi_io_num = LCD_MOSI_PIN,
.miso_io_num = -1,
.sclk_io_num = LCD_CLK_PIN,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 64, // ESP32 S3 max size is 64Kbytes
};
spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
spi_device_interface_config_t devcfg = {
.command_bits = 1,
.address_bits = 8,
.mode = SPI_MODE0,
.clock_speed_hz = 40000000,
.spics_io_num = -1,
.queue_size = 1, // Not using queues
};
spi_bus_add_device(SPI2_HOST, &devcfg, &SPI_handle);
ST7701_CS_EN();
ST7701_WriteCommand(0xFF);
ST7701_WriteData(0x77);
ST7701_WriteData(0x01);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x10);
ST7701_WriteCommand(0xC0);
ST7701_WriteData(0x3B);//Scan line
ST7701_WriteData(0x00);
ST7701_WriteCommand(0xC1);
ST7701_WriteData(0x0B); //VBP
ST7701_WriteData(0x02);
ST7701_WriteCommand(0xC2);
ST7701_WriteData(0x07);
ST7701_WriteData(0x02);
ST7701_WriteCommand(0xCC);
ST7701_WriteData(0x10);
ST7701_WriteCommand(0xCD);//RGB format
ST7701_WriteData(0x08);
ST7701_WriteCommand(0xB0); // IPS
ST7701_WriteData(0x00); // 255
ST7701_WriteData(0x11); // 251
ST7701_WriteData(0x16); // 247 down
ST7701_WriteData(0x0e); // 239
ST7701_WriteData(0x11); // 231
ST7701_WriteData(0x06); // 203
ST7701_WriteData(0x05); // 175
ST7701_WriteData(0x09); // 147
ST7701_WriteData(0x08); // 108
ST7701_WriteData(0x21); // 80
ST7701_WriteData(0x06); // 52
ST7701_WriteData(0x13); // 24
ST7701_WriteData(0x10); // 16
ST7701_WriteData(0x29); // 8 down
ST7701_WriteData(0x31); // 4
ST7701_WriteData(0x18); // 0
ST7701_WriteCommand(0xB1);// IPS
ST7701_WriteData(0x00);// 255
ST7701_WriteData(0x11);// 251
ST7701_WriteData(0x16);// 247 down
ST7701_WriteData(0x0e);// 239
ST7701_WriteData(0x11);// 231
ST7701_WriteData(0x07);// 203
ST7701_WriteData(0x05);// 175
ST7701_WriteData(0x09);// 147
ST7701_WriteData(0x09);// 108
ST7701_WriteData(0x21);// 80
ST7701_WriteData(0x05);// 52
ST7701_WriteData(0x13);// 24
ST7701_WriteData(0x11);// 16
ST7701_WriteData(0x2a);// 8 down
ST7701_WriteData(0x31);// 4
ST7701_WriteData(0x18);// 0
ST7701_WriteCommand(0xFF);
ST7701_WriteData(0x77);
ST7701_WriteData(0x01);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x11);
ST7701_WriteCommand(0xB0); //VOP 3.5375+ *x 0.0125
ST7701_WriteData(0x6d); //5D
ST7701_WriteCommand(0xB1); //VCOM amplitude setting
ST7701_WriteData(0x37); //
ST7701_WriteCommand(0xB2); //VGH Voltage setting
ST7701_WriteData(0x81); //12V
ST7701_WriteCommand(0xB3);
ST7701_WriteData(0x80);
ST7701_WriteCommand(0xB5); //VGL Voltage setting
ST7701_WriteData(0x43); //-8.3V
ST7701_WriteCommand(0xB7);
ST7701_WriteData(0x85);
ST7701_WriteCommand(0xB8);
ST7701_WriteData(0x20);
ST7701_WriteCommand(0xC1);
ST7701_WriteData(0x78);
ST7701_WriteCommand(0xC2);
ST7701_WriteData(0x78);
ST7701_WriteCommand(0xD0);
ST7701_WriteData(0x88);
ST7701_WriteCommand(0xE0);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x02);
ST7701_WriteCommand(0xE1);
ST7701_WriteData(0x03);
ST7701_WriteData(0xA0);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x04);
ST7701_WriteData(0xA0);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x20);
ST7701_WriteData(0x20);
ST7701_WriteCommand(0xE2);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteCommand(0xE3);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x11);
ST7701_WriteData(0x00);
ST7701_WriteCommand(0xE4);
ST7701_WriteData(0x22);
ST7701_WriteData(0x00);
ST7701_WriteCommand(0xE5);
ST7701_WriteData(0x05);
ST7701_WriteData(0xEC);
ST7701_WriteData(0xA0);
ST7701_WriteData(0xA0);
ST7701_WriteData(0x07);
ST7701_WriteData(0xEE);
ST7701_WriteData(0xA0);
ST7701_WriteData(0xA0);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteCommand(0xE6);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x11);
ST7701_WriteData(0x00);
ST7701_WriteCommand(0xE7);
ST7701_WriteData(0x22);
ST7701_WriteData(0x00);
ST7701_WriteCommand(0xE8);
ST7701_WriteData(0x06);
ST7701_WriteData(0xED);
ST7701_WriteData(0xA0);
ST7701_WriteData(0xA0);
ST7701_WriteData(0x08);
ST7701_WriteData(0xEF);
ST7701_WriteData(0xA0);
ST7701_WriteData(0xA0);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteCommand(0xEB);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x40);
ST7701_WriteData(0x40);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteCommand(0xED);
ST7701_WriteData(0xFF);
ST7701_WriteData(0xFF);
ST7701_WriteData(0xFF);
ST7701_WriteData(0xBA);
ST7701_WriteData(0x0A);
ST7701_WriteData(0xBF);
ST7701_WriteData(0x45);
ST7701_WriteData(0xFF);
ST7701_WriteData(0xFF);
ST7701_WriteData(0x54);
ST7701_WriteData(0xFB);
ST7701_WriteData(0xA0);
ST7701_WriteData(0xAB);
ST7701_WriteData(0xFF);
ST7701_WriteData(0xFF);
ST7701_WriteData(0xFF);
ST7701_WriteCommand(0xEF);
ST7701_WriteData(0x10);
ST7701_WriteData(0x0D);
ST7701_WriteData(0x04);
ST7701_WriteData(0x08);
ST7701_WriteData(0x3F);
ST7701_WriteData(0x1F);
ST7701_WriteCommand(0xFF);
ST7701_WriteData(0x77);
ST7701_WriteData(0x01);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x13);
ST7701_WriteCommand(0xEF);
ST7701_WriteData(0x08);
ST7701_WriteCommand(0xFF);
ST7701_WriteData(0x77);
ST7701_WriteData(0x01);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteData(0x00);
ST7701_WriteCommand(0x36);
ST7701_WriteData(0x00);
ST7701_WriteCommand(0x3A);
ST7701_WriteData(0x66);
ST7701_WriteCommand(0x11);
vTaskDelay(pdMS_TO_TICKS(480));
ST7701_WriteCommand(0x20); //
vTaskDelay(pdMS_TO_TICKS(120));
ST7701_WriteCommand(0x29);
ST7701_CS_Dis();
// RGB
esp_lcd_rgb_panel_config_t rgb_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.timings = {
.pclk_hz = ESP_PANEL_LCD_RGB_TIMING_FREQ_HZ,
.h_res = ESP_PANEL_LCD_HEIGHT,
.v_res = ESP_PANEL_LCD_WIDTH,
.hsync_pulse_width = ESP_PANEL_LCD_RGB_TIMING_HPW,
.hsync_back_porch = ESP_PANEL_LCD_RGB_TIMING_HBP,
.hsync_front_porch = ESP_PANEL_LCD_RGB_TIMING_HFP,
.vsync_pulse_width = ESP_PANEL_LCD_RGB_TIMING_VPW,
.vsync_back_porch = ESP_PANEL_LCD_RGB_TIMING_VBP,
.vsync_front_porch = ESP_PANEL_LCD_RGB_TIMING_VFP,
.flags = {
.hsync_idle_low = 0, /*!< The hsync signal is low in IDLE state */
.vsync_idle_low = 0, /*!< The vsync signal is low in IDLE state */
.de_idle_high = 0, /*!< The de signal is high in IDLE state */
.pclk_active_neg = false,
.pclk_idle_high = 0, /*!< The PCLK stays at high level in IDLE phase */
},
},
.data_width = ESP_PANEL_LCD_RGB_DATA_WIDTH,
.bits_per_pixel = ESP_PANEL_LCD_RGB_PIXEL_BITS,
.num_fbs = ESP_PANEL_LCD_RGB_FRAME_BUF_NUM,
.bounce_buffer_size_px = 10 * ESP_PANEL_LCD_HEIGHT,
.psram_trans_align = 64,
.hsync_gpio_num = ESP_PANEL_LCD_PIN_NUM_RGB_HSYNC,
.vsync_gpio_num = ESP_PANEL_LCD_PIN_NUM_RGB_VSYNC,
.de_gpio_num = ESP_PANEL_LCD_PIN_NUM_RGB_DE,
.pclk_gpio_num = ESP_PANEL_LCD_PIN_NUM_RGB_PCLK,
.disp_gpio_num = ESP_PANEL_LCD_PIN_NUM_RGB_DISP,
.data_gpio_nums = {
ESP_PANEL_LCD_PIN_NUM_RGB_DATA0,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA1,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA2,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA3,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA4,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA5,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA6,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA7,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA8,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA9,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA10,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA11,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA12,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA13,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA14,
ESP_PANEL_LCD_PIN_NUM_RGB_DATA15,
},
.flags = {
.disp_active_low = 0,
.refresh_on_demand = 0,
.fb_in_psram = true,
.double_fb = true,
.no_fb = 0,
.bb_invalidate_cache = 0,
},
};
esp_lcd_new_rgb_panel(&rgb_config, &panel_handle);
// esp_lcd_rgb_panel_event_callbacks_t cbs = {
// .on_vsync = example_on_vsync_event,
// };
// esp_lcd_rgb_panel_register_event_callbacks(panel_handle, &cbs, &disp_drv);
esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
}
bool example_on_vsync_event(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_data)
{
BaseType_t high_task_awoken = pdFALSE;
return high_task_awoken == pdTRUE;
}
void LCD_Init() {
ST7701_Reset();
ST7701_Init();
Touch_Init();
Backlight_Init();
}
void LCD_addWindow(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,uint8_t* color) {
Xend = Xend + 1; // esp_lcd_panel_draw_bitmap: x_end End index on x-axis (x_end not included)
Yend = Yend + 1; // esp_lcd_panel_draw_bitmap: y_end End index on y-axis (y_end not included)
if (Xend >= ESP_PANEL_LCD_WIDTH)
Xend = ESP_PANEL_LCD_WIDTH;
if (Yend >= ESP_PANEL_LCD_HEIGHT)
Yend = ESP_PANEL_LCD_HEIGHT;
esp_lcd_panel_draw_bitmap(panel_handle, Xstart, Ystart, Xend, Yend, color); // x_end End index on x-axis (x_end not included)
}
// backlight
uint8_t LCD_Backlight = 50;
void Backlight_Init()
{
ledcAttach(LCD_Backlight_PIN, Frequency, Resolution);
Set_Backlight(LCD_Backlight); //0~100
}
void Set_Backlight(uint8_t Light) //
{
if(Light > Backlight_MAX || Light < 0)
printf("Set Backlight parameters in the range of 0 to 100 \r\n");
else{
uint32_t Backlight = Light*10;
if(Backlight == 1000)
Backlight = 1024;
ledcWrite(LCD_Backlight_PIN, Backlight);
}
}
+92
View File
@@ -0,0 +1,92 @@
#pragma once
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_rgb.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "freertos/task.h"
#include "TCA9554PWR.h"
#include "LVGL_Driver.h"
#include "Touch_CST820.h"
#define LCD_CLK_PIN 2
#define LCD_MOSI_PIN 1
#define LCD_Backlight_PIN 6
// Backlight
#define PWM_Channel 1 // PWM Channel
#define Frequency 20000 // PWM frequencyconst
#define Resolution 10 // PWM resolution ratio MAX:13
#define Dutyfactor 500 // PWM Dutyfactor
#define Backlight_MAX 100
#define ESP_PANEL_LCD_WIDTH (480)
#define ESP_PANEL_LCD_HEIGHT (480)
#define ESP_PANEL_LCD_COLOR_BITS (16)
#define ESP_PANEL_LCD_RGB_PIXEL_BITS (16) // 24 | 16
#define ESP_PANEL_LCD_RGB_DATA_WIDTH (16)
#define ESP_PANEL_LCD_RGB_TIMING_FREQ_HZ (16 * 1000 * 1000)
#define ESP_PANEL_LCD_RGB_TIMING_HPW (8)
#define ESP_PANEL_LCD_RGB_TIMING_HBP (10)
#define ESP_PANEL_LCD_RGB_TIMING_HFP (50)
#define ESP_PANEL_LCD_RGB_TIMING_VPW (3)
#define ESP_PANEL_LCD_RGB_TIMING_VBP (8)
#define ESP_PANEL_LCD_RGB_TIMING_VFP (8)
#define ESP_PANEL_LCD_RGB_FRAME_BUF_NUM (2) // 1/2/3
#define ESP_PANEL_LCD_RGB_BOUNCE_BUF_SIZE (ESP_PANEL_LCD_WIDTH * 10) // Bounce buffer size in bytes. This function is used to avoid screen drift.
// To enable the bounce buffer, set it to a non-zero value. Typically set to `ESP_PANEL_LCD_WIDTH * 10`
// The size of the Bounce Buffer must satisfy `width_of_lcd * height_of_lcd = size_of_buffer * N`,
// where N is an even number.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////// Please update the following configuration according to your board spec ////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define ESP_PANEL_LCD_PIN_NUM_RGB_HSYNC (38)
#define ESP_PANEL_LCD_PIN_NUM_RGB_VSYNC (39)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DE (40)
#define ESP_PANEL_LCD_PIN_NUM_RGB_PCLK (41)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA0 (5)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA1 (45)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA2 (48)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA3 (47)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA4 (21)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA5 (14)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA6 (13)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA7 (12)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA8 (11)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA9 (10)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA10 (9)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA11 (46)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA12 (3)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA13 (8)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA14 (18)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA15 (17)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DISP (-1)
#define ESP_PANEL_LCD_BK_LIGHT_ON_LEVEL (1)
#define ESP_PANEL_LCD_BK_LIGHT_OFF_LEVEL !ESP_PANEL_LCD_BK_LIGHT_ON_LEVEL
#define EXAMPLE_ENABLE_PRINT_LCD_FPS (0)
extern uint8_t LCD_Backlight;
extern esp_lcd_panel_handle_t panel_handle;
bool example_on_vsync_event(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_data);
void ST7701_Init();
void LCD_Init();
void LCD_addWindow(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,uint8_t* color);
// backlight
void Backlight_Init();
void Set_Backlight(uint8_t Light);
+174
View File
@@ -0,0 +1,174 @@
#include "EyeScene.h"
#include "FreddyIris.h"
#include <cmath>
#include <lvgl.h>
#ifndef EYE_BOARD_NUMBER
#define EYE_BOARD_NUMBER 1
#endif
namespace {
constexpr int kDisplaySize = 480;
constexpr int kIrisSize = 178;
constexpr int kIrisRadius = kIrisSize / 2;
constexpr uint32_t kBlinkPeriodMs = 4600;
constexpr uint32_t kBlinkDurationMs = 300;
lv_obj_t *iris = nullptr;
lv_obj_t *red_iris = nullptr;
lv_obj_t *red_halo = nullptr;
lv_obj_t *sclera = nullptr;
lv_obj_t *upper_lid = nullptr;
lv_obj_t *lower_lid = nullptr;
lv_obj_t *status_label = nullptr;
bool tracking_red = false;
bool gaze_valid = false;
uint16_t gaze_x = 500;
uint16_t gaze_y = 500;
float drawn_x = 240.0f;
float drawn_y = 240.0f;
lv_obj_t *make_circle(lv_obj_t *parent, int size, uint32_t color) {
lv_obj_t *obj = lv_obj_create(parent);
lv_obj_set_size(obj, size, size);
lv_obj_set_style_radius(obj, LV_RADIUS_CIRCLE, 0);
lv_obj_set_style_bg_color(obj, lv_color_hex(color), 0);
lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, 0);
lv_obj_set_style_border_width(obj, 0, 0);
lv_obj_set_style_outline_width(obj, 0, 0);
lv_obj_set_style_shadow_width(obj, 0, 0);
lv_obj_set_style_pad_all(obj, 0, 0);
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
return obj;
}
lv_obj_t *make_lid(lv_obj_t *parent) {
lv_obj_t *obj = lv_obj_create(parent);
lv_obj_set_style_radius(obj, 0, 0);
lv_obj_set_style_bg_color(obj, lv_color_hex(0x743824), 0);
lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, 0);
lv_obj_set_style_border_width(obj, 0, 0);
lv_obj_set_style_outline_width(obj, 0, 0);
lv_obj_set_style_shadow_width(obj, 0, 0);
lv_obj_set_style_pad_all(obj, 0, 0);
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
return obj;
}
lv_obj_t *make_red_layer(lv_obj_t *parent, int size, uint32_t color,
lv_opa_t opacity) {
lv_obj_t *layer = make_circle(parent, size, color);
lv_obj_set_style_bg_opa(layer, opacity, 0);
lv_obj_set_pos(layer, (kIrisSize - size) / 2, (kIrisSize - size) / 2);
return layer;
}
void eye_tick(lv_timer_t *) {
const uint32_t elapsed_ms = lv_tick_get();
const float seconds = static_cast<float>(elapsed_ms) / 1000.0f;
// Easing continues between camera updates and back into idle after loss.
const float desired_x = gaze_valid
? 240.0f + (static_cast<int>(gaze_x) - 500) * 0.104f
: 240.0f + 52.0f * sinf(seconds * 0.86f);
const float desired_y = gaze_valid
? 240.0f + (static_cast<int>(gaze_y) - 500) * 0.062f
: 240.0f + 31.0f * sinf(seconds * 0.53f + 0.8f);
drawn_x += (desired_x - drawn_x) * 0.20f;
drawn_y += (desired_y - drawn_y) * 0.20f;
const int iris_x = static_cast<int>(drawn_x);
const int iris_y = static_cast<int>(drawn_y);
lv_obj_set_pos(iris, iris_x - kIrisRadius, iris_y - kIrisRadius);
lv_obj_set_pos(red_iris, iris_x - kIrisRadius, iris_y - kIrisRadius);
if (tracking_red) {
const int pulse = static_cast<int>(14.0f * sinf(seconds * 4.5f));
lv_obj_set_style_bg_opa(red_halo, 55 + pulse, 0);
}
const uint32_t phase_ms = elapsed_ms % kBlinkPeriodMs;
int lid_height = 1;
if (phase_ms < kBlinkDurationMs) {
const float phase = static_cast<float>(phase_ms) / kBlinkDurationMs;
const float closure = sinf(phase * 3.14159265f);
lid_height += static_cast<int>(240.0f * closure);
}
lv_obj_set_size(upper_lid, kDisplaySize, lid_height);
lv_obj_set_size(lower_lid, kDisplaySize, lid_height);
lv_obj_set_pos(lower_lid, 0, kDisplaySize - lid_height);
}
void set_tracking_red(bool enabled) {
if (tracking_red == enabled) return;
tracking_red = enabled;
if (enabled) {
lv_obj_add_flag(iris, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(red_iris, LV_OBJ_FLAG_HIDDEN);
lv_obj_set_style_bg_color(sclera, lv_color_hex(0x21191B), 0);
} else {
lv_obj_add_flag(red_iris, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(iris, LV_OBJ_FLAG_HIDDEN);
lv_obj_set_style_bg_color(sclera, lv_color_hex(0xF5F4EA), 0);
}
}
} // namespace
void EyeScene_SetGaze(uint16_t x, uint16_t y, bool valid) {
if (gaze_valid != valid && status_label) {
#if EYE_BOARD_NUMBER == 2
lv_label_set_text(status_label, valid ? "BOARD 2 TRACK" : "BOARD 2 IDLE");
#else
lv_label_set_text(status_label, valid ? "BOARD 1 TRACK" : "BOARD 1 IDLE");
#endif
}
gaze_x = x;
gaze_y = y;
gaze_valid = valid;
set_tracking_red(valid);
}
void EyeScene_Create() {
lv_obj_t *screen = lv_scr_act();
lv_obj_clean(screen);
lv_obj_set_style_bg_color(screen, lv_color_hex(0x39271D), 0);
lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0);
lv_obj_clear_flag(screen, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_t *sclera_outline = make_circle(screen, 444, 0x743824);
lv_obj_set_pos(sclera_outline, 18, 18);
sclera = make_circle(screen, 432, 0xF5F4EA);
lv_obj_set_pos(sclera, 24, 24);
iris = lv_img_create(screen);
lv_img_set_src(iris, &kFreddyIris);
lv_obj_clear_flag(iris, LV_OBJ_FLAG_SCROLLABLE);
red_iris = lv_obj_create(screen);
lv_obj_set_size(red_iris, kIrisSize, kIrisSize);
lv_obj_set_style_bg_opa(red_iris, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(red_iris, 0, 0);
lv_obj_set_style_pad_all(red_iris, 0, 0);
lv_obj_clear_flag(red_iris, LV_OBJ_FLAG_SCROLLABLE);
make_red_layer(red_iris, kIrisSize, 0x150909, LV_OPA_COVER);
make_red_layer(red_iris, 144, 0x6E0B08, 34);
red_halo = make_red_layer(red_iris, 116, 0xBE1B13, 55);
make_red_layer(red_iris, 82, 0xE22D1E, 90);
make_red_layer(red_iris, 48, 0xFA412B, 165);
make_red_layer(red_iris, 28, 0xFF3A2B, LV_OPA_COVER);
make_red_layer(red_iris, 13, 0xFFF2E3, LV_OPA_COVER);
lv_obj_add_flag(red_iris, LV_OBJ_FLAG_HIDDEN);
status_label = lv_label_create(screen);
#if EYE_BOARD_NUMBER == 2
lv_label_set_text(status_label, "BOARD 2 IDLE");
#else
lv_label_set_text(status_label, "BOARD 1 IDLE");
#endif
lv_obj_set_style_text_color(status_label, lv_color_hex(0x3F5361), 0);
lv_obj_align(status_label, LV_ALIGN_TOP_MID, 0, 48);
upper_lid = make_lid(screen);
lower_lid = make_lid(screen);
eye_tick(nullptr);
lv_timer_create(eye_tick, 30, nullptr);
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <stdint.h>
// Creates a moving and blinking eye on the Waveshare 480x480 display.
void EyeScene_Create();
// Normalized camera-image coordinates. A valid target switches to the red eye;
// an invalid target returns to blue. Call from the LVGL loop task.
void EyeScene_SetGaze(uint16_t x, uint16_t y, bool valid);
File diff suppressed because it is too large Load Diff
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <lvgl.h>
extern const lv_img_dsc_t kFreddyIris;
+304
View File
@@ -0,0 +1,304 @@
#include "Gyro_QMI8658.h"
IMUdata Accel;
IMUdata Gyro;
uint8_t Device_addr ; // default for SD0/SA0 low, 0x6A if high
acc_scale_t acc_scale = ACC_RANGE_4G;
gyro_scale_t gyro_scale = GYR_RANGE_64DPS;
acc_odr_t acc_odr = acc_odr_norm_8000;
gyro_odr_t gyro_odr = gyro_odr_norm_8000;
sensor_state_t sensor_state = sensor_default;
lpf_t acc_lpf;
float accelScales, gyroScales;
uint8_t readings[12];
uint32_t reading_timestamp_us; // timestamp in arduino micros() time
/**
* Inialize Wire and send default configs
* @param addr I2C address of sensor, typically 0x6A or 0x6B
*/
void QMI8658_Init(void)
{
uint8_t buf[1];
Device_addr = QMI8658_L_SLAVE_ADDRESS;
I2C_Read(Device_addr, QMI8658_REVISION_ID, buf, 1);
printf("QMI8658 Device ID: %x\r\n",buf[0]); // Get chip id
setState(sensor_running);
setAccScale(acc_scale);
setAccODR(acc_odr);
setAccLPF(LPF_MODE_0);
switch (acc_scale) {
// Possible accelerometer scales (and their register bit settings) are:
// 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs (11).
// Here's a bit of an algorith to calculate DPS/(ADC tick) based on that
// 2-bit value:
case ACC_RANGE_2G: accelScales = 2.0 / 32768.0; break;
case ACC_RANGE_4G: accelScales = 4.0 / 32768.0; break;
case ACC_RANGE_8G: accelScales = 8.0 / 32768.0; break;
case ACC_RANGE_16G: accelScales = 16.0 / 32768.0; break;
}
setGyroScale(gyro_scale);
setGyroODR(gyro_odr);
setGyroLPF(LPF_MODE_3);
switch (gyro_scale) {
// Possible gyro scales (and their register bit settings) are:
// 250 DPS (00), 500 DPS (01), 1000 DPS (10), and 2000 DPS (11).
// Here's a bit of an algorith to calculate DPS/(ADC tick) based on that
// 2-bit value:
case GYR_RANGE_16DPS: gyroScales = 16.0 / 32768.0; break;
case GYR_RANGE_32DPS: gyroScales = 32.0 / 32768.0; break;
case GYR_RANGE_64DPS: gyroScales = 64.0 / 32768.0; break;
case GYR_RANGE_128DPS: gyroScales = 128.0 / 32768.0; break;
case GYR_RANGE_256DPS: gyroScales = 256.0 / 32768.0; break;
case GYR_RANGE_512DPS: gyroScales = 512.0 / 32768.0; break;
case GYR_RANGE_1024DPS: gyroScales = 1024.0 / 32768.0; break;
}
}
void QMI8658_Loop(void)
{
getAccelerometer();
}
/**
* Transmit one uint8_t of data to QMI8658.
* @param addr address of data to be written
* @param data the data to be written
*/
void QMI8658_transmit(uint8_t addr, uint8_t data)
{
I2C_Write(Device_addr, addr, &data, 1);
}
/**
* Receive one uint8_t of data from QMI8658.
* @param addr address of data to be read
* @return the uint8_t of data that was read
*/
uint8_t QMI8658_receive(uint8_t addr)
{
uint8_t retval;
I2C_Read(Device_addr, addr, &retval, 1);
return retval;
}
/**
* Writes data to CTRL9 (command register) and waits for ACK.
* @param command the command to be executed
*/
void QMI8658_CTRL9_Write(uint8_t command)
{
// transmit command
QMI8658_transmit(QMI8658_CTRL9, command);
// wait for command to be done
while (((QMI8658_receive(QMI8658_STATUSINT)) & 0x80) == 0x00);
}
/**
* Set output data rate (ODR) of accelerometer.
* @param odr acc_odr_t variable representing new data rate
*/
void setAccODR(acc_odr_t odr)
{
if (sensor_state != sensor_default) // If the device is not in the default state
{
uint8_t ctrl2 = QMI8658_receive(QMI8658_CTRL2);
ctrl2 &= ~QMI8658_AODR_MASK; // clear previous setting
ctrl2 |= odr; // OR in new setting
QMI8658_transmit(QMI8658_CTRL2, ctrl2);
}
acc_odr = odr;
}
/**
* Set output data rate (ODR) of gyro.
* @param odr gyro_odr_t variable representing new data rate
*/
void setGyroODR(gyro_odr_t odr)
{
if (sensor_state != sensor_default)
{
uint8_t ctrl3 = QMI8658_receive(QMI8658_CTRL3);
ctrl3 &= ~QMI8658_GODR_MASK; // clear previous setting
ctrl3 |= odr; // OR in new setting
QMI8658_transmit(QMI8658_CTRL3, ctrl3);
}
gyro_odr = odr;
}
/**
* Set scale of accelerometer output.
* @param scale acc_scale_t variable representing new scale
*/
void setAccScale(acc_scale_t scale)
{
if (sensor_state != sensor_default)
{
uint8_t ctrl2 = QMI8658_receive(QMI8658_CTRL2);
ctrl2 &= ~QMI8658_ASCALE_MASK; // clear previous setting
ctrl2 |= scale << QMI8658_ASCALE_OFFSET; // OR in new setting
QMI8658_transmit(QMI8658_CTRL2, ctrl2);
}
acc_scale = scale;
}
/**
* Set scale of gyro output.
* @param scale gyro_scale_t variable representing new scale
*/
void setGyroScale(gyro_scale_t scale)
{
if (sensor_state != sensor_default)
{
uint8_t ctrl3 = QMI8658_receive(QMI8658_CTRL3);
ctrl3 &= ~QMI8658_GSCALE_MASK; // clear previous setting
ctrl3 |= scale << QMI8658_GSCALE_OFFSET; // OR in new setting
QMI8658_transmit(QMI8658_CTRL3, ctrl3);
}
gyro_scale = scale;
}
/**
* Set new low-pass filter value for accelerometer
* @param lp lpf_t variable representing new low-pass filter value
*/
void setAccLPF(lpf_t lpf)
{
if (sensor_state != sensor_default)
{
uint8_t ctrl5 = QMI8658_receive(QMI8658_CTRL5);
ctrl5 &= !QMI8658_ALPF_MASK;
ctrl5 |= lpf << QMI8658_ALPF_OFFSET;
ctrl5 |= 0x01; // turn on acc low pass filter
QMI8658_transmit(QMI8658_CTRL5, ctrl5);
}
acc_lpf = lpf;
}
/**
* Set new low-pass filter value for gyro
* @param lp lpf_t variable representing new low-pass filter value
*/
void setGyroLPF(lpf_t lpf)
{
if (sensor_state != sensor_default)
{
uint8_t ctrl5 = QMI8658_receive(QMI8658_CTRL5);
ctrl5 &= !QMI8658_GLPF_MASK;
ctrl5 |= lpf << QMI8658_GLPF_OFFSET;
ctrl5 |= 0x10; // turn on gyro low pass filter
QMI8658_transmit(QMI8658_CTRL5, ctrl5);
}
}
/**
* Set new state of QMI8658.
* @param state new state to transition to
*/
void setState(sensor_state_t state)
{
uint8_t ctrl1;
switch (state)
{
case sensor_running:
ctrl1 = QMI8658_receive(QMI8658_CTRL1);
// enable 2MHz oscillator
ctrl1 &= 0xFE;
// enable auto address increment for fast block reads
ctrl1 |= 0x40;
QMI8658_transmit(QMI8658_CTRL1, ctrl1);
// enable high speed internal clock,
// acc and gyro in full mode, and
// disable syncSample mode
QMI8658_transmit(QMI8658_CTRL7, 0x43);
// disable AttitudeEngine Motion On Demand
QMI8658_transmit(QMI8658_CTRL6, 0x00);
break;
case sensor_power_down:
// disable high speed internal clock,
// acc and gyro powered down
QMI8658_transmit(QMI8658_CTRL7, 0x00);
ctrl1 = QMI8658_receive(QMI8658_CTRL1);
// disable 2MHz oscillator
ctrl1|= 0x01;
QMI8658_transmit(QMI8658_CTRL1, ctrl1);
break;
case sensor_locking:
ctrl1 = QMI8658_receive(QMI8658_CTRL1);
// enable 2MHz oscillator
ctrl1 &= 0xFE;
// enable auto address increment for fast block reads
ctrl1 |= 0x40;
QMI8658_transmit(QMI8658_CTRL1, ctrl1);
// enable high speed internal clock,
// acc and gyro in full mode, and
// enable syncSample mode
QMI8658_transmit(QMI8658_CTRL7, 0x83);
// disable AttitudeEngine Motion On Demand
QMI8658_transmit(QMI8658_CTRL6, 0x00);
// disable internal AHB clock gating:
QMI8658_transmit(QMI8658_CAL1_L, 0x01);
QMI8658_CTRL9_Write(0x12);
// re-enable clock gating
QMI8658_transmit(QMI8658_CAL1_L, 0x00);
QMI8658_CTRL9_Write(0x12);
break;
default:
break;
}
sensor_state = state;
}
void getAccelerometer(void)
{
uint8_t buf[6];
I2C_Read(Device_addr, QMI8658_AX_L, buf, 6);
Accel.x = (float)((int16_t)((buf[1]<<8) | (buf[0])));
Accel.y = (float)((int16_t)((buf[3]<<8) | (buf[2])));
Accel.z = (float)((int16_t)((buf[5]<<8) | (buf[4])));
Accel.x = Accel.x * accelScales;
Accel.y = Accel.y * accelScales;
Accel.z = Accel.z * accelScales;
}
void getGyroscope(void)
{
uint8_t buf[6];
I2C_Read(Device_addr, QMI8658_GX_L, buf, 6);
Gyro.x = (float)((int16_t)((buf[1]<<8) | (buf[0])));
Gyro.y = (float)((int16_t)((buf[3]<<8) | (buf[2])));
Gyro.z = (float)((int16_t)((buf[5]<<8) | (buf[4])));
Gyro.x = Gyro.x * gyroScales;
Gyro.y = Gyro.y * gyroScales;
Gyro.z = Gyro.z * gyroScales;
}
+161
View File
@@ -0,0 +1,161 @@
#pragma once
#include "I2C_Driver.h"
//device address
#define QMI8658_L_SLAVE_ADDRESS (0x6B)
#define QMI8658_H_SLAVE_ADDRESS (0x6A)
#define QMI8658_WHO_AM_I 0x00 // devide identifier
#define QMI8658_REVISION_ID 0x01
#define QMI8658_CTRL1 0x02 // SPI interface and sensor enable
#define QMI8658_CTRL2 0x03 // Accelerometer settings
#define QMI8658_CTRL3 0x04 // Gyro settings
#define QMI8658_CTRL4 0x05 // reserved (we don't use this)
#define QMI8658_CTRL5 0x06 // Low-pass filter settings
#define QMI8658_CTRL6 0x07 // AttitudeEngine settings (we don't use these)
#define QMI8658_CTRL7 0x08 // Sensor enable
#define QMI8658_CTRL8 0x09 // Motion detection control (not in current lib version)
#define QMI8658_CTRL9 0x0A // Host commands (not in current lib version)
#define QMI8658_CAL1_L 0x0B // calibration 1 register, lower bits
#define QMI8658_CAL1_H 0x0C // calibration 1 register, higher bits
#define QMI8658_CAL2_L 0x0D // calibration 2 register, lower bits
#define QMI8658_CAL2_H 0x0E // calibration 2 register, higher bits
#define QMI8658_CAL3_L 0x0F // calibration 3 register, lower bits
#define QMI8658_CAL3_H 0x10 // calibration 3 register, higher bits
#define QMI8658_CAL4_L 0x11 // calibration 4 register, lower bits
#define QMI8658_CAL4_H 0x12 // calibration 4 register, higher bits
#define QMI8658_TEMP_L 0x33 // lower bits of temperature data
#define QMI8658_TEMP_H 0x34 // upper bits of temperature data
#define QMI8658_STATUSINT 0x2D // status + interrupt register
#define QMI8658_AX_L 0x35 // lower bits of x-axis acceleration
#define QMI8658_AX_H 0x36 // upper bits of x-axis acceleration
#define QMI8658_AY_L 0x37 // lower bits of y-axis acceleration
#define QMI8658_AY_H 0x38 // upper bits of y-axis acceleration
#define QMI8658_AZ_L 0x39
#define QMI8658_AZ_H 0x3A
#define QMI8658_GX_L 0x3B // lower bits of x-axis angular velocity
#define QMI8658_GX_H 0x3C // upper bits of x-axis angular velocity
#define QMI8658_GY_L 0x3D
#define QMI8658_GY_H 0x3E
#define QMI8658_GZ_L 0x3F
#define QMI8658_GZ_H 0x40
#define QMI8658_AODR_MASK 0x0F // bits in acc data rate are 1, rest are 0 (CTRL2)
#define QMI8658_GODR_MASK 0x0F // bits in gyro data rate are 1, rest are 0 (CTRL3)
#define QMI8658_ASCALE_MASK 0x70 // bits in acc scale are 1, rest are 0
#define QMI8658_GSCALE_MASK 0x70 // bits in gyro scale are 1, rest are 0
#define QMI8658_ALPF_MASK 0x06 // bits in acc low pass filter setting
#define QMI8658_GLPF_MASK 0x60 // bits in gyro low pass filter setting
#define QMI8658_ASCALE_OFFSET 4 // offset to acc scale bits
#define QMI8658_GSCALE_OFFSET 4 // offset to gyro scale bits
#define QMI8658_ALPF_OFFSET 1 // offset to acc low pass filter bits
#define QMI8658_GLPF_OFFSET 5 // offset to gyro low pass filter bits
#define QMI8658_COMM_TIMEOUT 50 // communication timeout, in ms
// delay between refreshes of sensor data in us
// applies to individual sensor readings while in locking mode
// has no effect in running mode
#define QMI8658_REFRESH_DELAY 2000
// control clock gating (necessary to use data locking)
#define QMI8658_CTRL_CMD_AHB_CLOCK_GATING 0x12
typedef enum {
acc_odr_norm_8000 = 0x0,
acc_odr_norm_4000,
acc_odr_norm_2000,
acc_odr_norm_1000,
acc_odr_norm_500,
acc_odr_norm_250,
acc_odr_norm_120,
acc_odr_norm_60,
acc_odr_norm_30,
acc_odr_lp_128 = 0xC,
acc_odr_lp_21,
acc_odr_lp_11,
acc_odr_lp_3,
} acc_odr_t;
typedef enum {
gyro_odr_norm_8000 = 0x0,
gyro_odr_norm_4000,
gyro_odr_norm_2000,
gyro_odr_norm_1000,
gyro_odr_norm_500,
gyro_odr_norm_250,
gyro_odr_norm_120,
gyro_odr_norm_60,
gyro_odr_norm_30
} gyro_odr_t;
typedef enum {
ACC_RANGE_2G = 0x0,
ACC_RANGE_4G,
ACC_RANGE_8G,
ACC_RANGE_16G
} acc_scale_t;
typedef enum {
GYR_RANGE_16DPS = 0x0,
GYR_RANGE_32DPS,
GYR_RANGE_64DPS,
GYR_RANGE_128DPS,
GYR_RANGE_256DPS,
GYR_RANGE_512DPS,
GYR_RANGE_1024DPS
} gyro_scale_t;
typedef enum {
LPF_MODE_0 = 0x0, //2.66% of ODR
LPF_MODE_1 = 0x2, //3.63% of ODR
LPF_MODE_2 = 0x4, //5.39% of ODR
LPF_MODE_3 = 0x6 //13.37% of ODR
} lpf_t;
typedef enum {
sensor_default,
sensor_power_down,
sensor_running,
sensor_locking
} sensor_state_t;
typedef struct __IMUdata {
float x;
float y;
float z;
} IMUdata;
extern IMUdata Accel;
extern IMUdata Gyro;
void QMI8658_Init(void);
void QMI8658_Loop(void);
void QMI8658_transmit(uint8_t addr, uint8_t data);
uint8_t QMI8658_receive(uint8_t addr);
void QMI8658_CTRL9_Write(uint8_t command);
void QMI8658_sensor_update();
void QMI8658_update_if_needed();
void setAccODR(acc_odr_t odr);
void setGyroODR(gyro_odr_t odr);
void setAccScale(acc_scale_t scale);
void setGyroScale(gyro_scale_t scale);
void setAccLPF(lpf_t lpf);
void setGyroLPF(lpf_t lpf);
void setState(sensor_state_t state);
void getRawReadings(int16_t* buf);
float getAccX();
float getAccY();
float getAccZ();
float getGyroX();
float getGyroY();
float getGyroZ();
void getAccelerometer(void);
void getGyroscope(void);
+35
View File
@@ -0,0 +1,35 @@
#include "I2C_Driver.h"
void I2C_Init(void) {
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
}
// 寄存器地址为 8 位的
bool I2C_Read(uint8_t Driver_addr, uint8_t Reg_addr, uint8_t *Reg_data, uint32_t Length)
{
Wire.beginTransmission(Driver_addr);
Wire.write(Reg_addr);
if ( Wire.endTransmission(true)){
printf("The I2C transmission fails. - I2C Read\r\n");
return -1;
}
Wire.requestFrom(Driver_addr, Length);
for (int i = 0; i < Length; i++) {
*Reg_data++ = Wire.read();
}
return 0;
}
bool I2C_Write(uint8_t Driver_addr, uint8_t Reg_addr, const uint8_t *Reg_data, uint32_t Length)
{
Wire.beginTransmission(Driver_addr);
Wire.write(Reg_addr);
for (int i = 0; i < Length; i++) {
Wire.write(*Reg_data++);
}
if ( Wire.endTransmission(true))
{
printf("The I2C transmission fails. - I2C Write\r\n");
return -1;
}
return 0;
}
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include <Wire.h>
#define I2C_SCL_PIN 7
#define I2C_SDA_PIN 15
void I2C_Init(void);
bool I2C_Read(uint8_t Driver_addr, uint8_t Reg_addr, uint8_t *Reg_data, uint32_t Length);
bool I2C_Write(uint8_t Driver_addr, uint8_t Reg_addr, const uint8_t *Reg_data, uint32_t Length);
+102
View File
@@ -0,0 +1,102 @@
/*****************************************************************************
| File : LVGL_Driver.c
| help :
The provided LVGL library file must be installed first
******************************************************************************/
#include "LVGL_Driver.h"
lv_disp_drv_t disp_drv;
static lv_disp_draw_buf_t draw_buf;
void* buf1 = NULL;
void* buf2 = NULL;
// static lv_color_t buf1[ LVGL_BUF_LEN ];
// static lv_color_t buf2[ LVGL_BUF_LEN ];
// static lv_color_t* buf1 = (lv_color_t*) heap_caps_malloc(LVGL_BUF_LEN, MALLOC_CAP_SPIRAM);
// static lv_color_t* buf2 = (lv_color_t*) heap_caps_malloc(LVGL_BUF_LEN, MALLOC_CAP_SPIRAM);
/* Serial debugging */
void Lvgl_print(const char * buf)
{
// Serial.printf(buf);
// Serial.flush();
}
/* Display flushing
Displays LVGL content on the LCD
This function implements associating LVGL data to the LCD screen
*/
void Lvgl_Display_LCD( lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p )
{
LCD_addWindow(area->x1, area->y1, area->x2, area->y2, ( uint8_t *)&color_p->full);
lv_disp_flush_ready( disp_drv );
}
/*Read the touchpad*/
void Lvgl_Touchpad_Read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{
Touch_Read_Data();
if (touch_data.points != 0x00) {
data->point.x = touch_data.x;
data->point.y = touch_data.y;
data->state = LV_INDEV_STATE_PR;
printf("LVGL : X=%u Y=%u points=%d\r\n", touch_data.x , touch_data.y,touch_data.points);
} else {
data->state = LV_INDEV_STATE_REL;
}
if (touch_data.gesture != NONE ) {
}
touch_data.x = 0;
touch_data.y = 0;
touch_data.points = 0;
touch_data.gesture = NONE;
}
void example_increase_lvgl_tick(void *arg)
{
/* Tell LVGL how many milliseconds has elapsed */
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
}
void Lvgl_Init(void)
{
lv_init();
esp_lcd_rgb_panel_get_frame_buffer(panel_handle, 2, &buf1, &buf2);
lv_disp_draw_buf_init( &draw_buf, buf1, buf2, ESP_PANEL_LCD_WIDTH * ESP_PANEL_LCD_HEIGHT);
/*Initialize the display*/
lv_disp_drv_init( &disp_drv );
/*Change the following line to your display resolution*/
disp_drv.hor_res = LCD_HEIGHT;
disp_drv.ver_res = LCD_WIDTH;
disp_drv.flush_cb = Lvgl_Display_LCD;
disp_drv.full_refresh = 1; /**< 1: Always make the whole screen redrawn*/
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register( &disp_drv );
/*Initialize the (dummy) input device driver*/
static lv_indev_drv_t indev_drv;
lv_indev_drv_init( &indev_drv );
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = Lvgl_Touchpad_Read;
lv_indev_drv_register( &indev_drv );
/* Create simple label */
lv_obj_t *label = lv_label_create( lv_scr_act() );
lv_label_set_text( label, "Hello Ardino and LVGL!");
lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );
const esp_timer_create_args_t lvgl_tick_timer_args = {
.callback = &example_increase_lvgl_tick,
.name = "lvgl_tick"
};
esp_timer_handle_t lvgl_tick_timer = NULL;
esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer);
esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000);
}
void Lvgl_Loop(void)
{
lv_timer_handler(); /* let the GUI do its work */
// vTaskDelay(pdMS_TO_TICKS(5));
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <lvgl.h>
#include "lv_conf.h"
#include <demos/lv_demos.h>
#include <esp_heap_caps.h>
#include "Display_ST7701.h"
#include "Touch_CST820.h"
#define LCD_WIDTH ESP_PANEL_LCD_WIDTH
#define LCD_HEIGHT ESP_PANEL_LCD_HEIGHT
#define LVGL_BUF_LEN (ESP_PANEL_LCD_WIDTH * ESP_PANEL_LCD_HEIGHT / 5)
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
extern lv_disp_drv_t disp_drv;
void Lvgl_print(const char * buf);
void Lvgl_Display_LCD( lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p ); // Displays LVGL content on the LCD. This function implements associating LVGL data to the LCD screen
void Lvgl_Touchpad_Read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data ); // Read the touchpad
void example_increase_lvgl_tick(void *arg);
void Lvgl_Init(void);
void Lvgl_Loop(void);
+620
View File
@@ -0,0 +1,620 @@
#include "LVGL_Example.h"
// #include "LVGL_Music.h"
#include <demos/lv_demos.h>
/**********************
* TYPEDEFS
**********************/
typedef enum {
DISP_SMALL,
DISP_MEDIUM,
DISP_LARGE,
} disp_size_t;
/**********************
* STATIC PROTOTYPES
**********************/
static void Onboard_create(lv_obj_t * parent);
static void Buzzer_create(lv_obj_t * parent);
static void Music_create(lv_obj_t * parent);
static void color_changer_create(lv_obj_t * parent);
static void color_changer_event_cb(lv_event_t * e);
static void color_event_cb(lv_event_t * e);
static void ta_event_cb(lv_event_t * e);
static void birthday_event_cb(lv_event_t * e);
static void calendar_event_cb(lv_event_t * e);
void example1_increase_lvgl_tick(lv_timer_t * t);
/**********************
* STATIC VARIABLES
**********************/
static disp_size_t disp_size;
static lv_obj_t * tv;
static lv_obj_t * calendar;
lv_style_t style_text_muted;
lv_style_t style_title;
static lv_style_t style_icon;
static lv_style_t style_bullet;
static lv_obj_t * chart1;
static lv_obj_t * chart2;
static lv_obj_t * chart3;
static lv_chart_series_t * ser1;
static lv_chart_series_t * ser2;
static lv_chart_series_t * ser3;
static lv_chart_series_t * ser4;
static const lv_font_t * font_large;
static const lv_font_t * font_normal;
static lv_timer_t * auto_step_timer;
static lv_color_t original_screen_bg_color;
static lv_timer_t * meter2_timer;
lv_obj_t * SD_Size;
lv_obj_t * FlashSize;
lv_obj_t * BAT_Volts;
lv_obj_t * Board_angle;
lv_obj_t * RTC_Time;
lv_obj_t * Wireless_Scan;
lv_obj_t * Backlight_slider;
void Lvgl_Example1(void){
if(LV_HOR_RES <= 320) disp_size = DISP_SMALL;
else if(LV_HOR_RES < 720) disp_size = DISP_MEDIUM;
else disp_size = DISP_LARGE;
font_large = LV_FONT_DEFAULT;
font_normal = LV_FONT_DEFAULT;
lv_coord_t tab_h;
if(disp_size == DISP_LARGE) {
tab_h = 70;
#if LV_FONT_MONTSERRAT_24
font_large = &lv_font_montserrat_24;
#else
LV_LOG_WARN("LV_FONT_MONTSERRAT_24 is not enabled for the widgets demo. Using LV_FONT_DEFAULT instead.");
#endif
#if LV_FONT_MONTSERRAT_16
font_normal = &lv_font_montserrat_16;
#else
LV_LOG_WARN("LV_FONT_MONTSERRAT_16 is not enabled for the widgets demo. Using LV_FONT_DEFAULT instead.");
#endif
}
else if(disp_size == DISP_MEDIUM) {
tab_h = 45;
#if LV_FONT_MONTSERRAT_20
font_large = &lv_font_montserrat_20;
#else
LV_LOG_WARN("LV_FONT_MONTSERRAT_20 is not enabled for the widgets demo. Using LV_FONT_DEFAULT instead.");
#endif
#if LV_FONT_MONTSERRAT_14
font_normal = &lv_font_montserrat_14;
#else
LV_LOG_WARN("LV_FONT_MONTSERRAT_14 is not enabled for the widgets demo. Using LV_FONT_DEFAULT instead.");
#endif
}
else { /* disp_size == DISP_SMALL */
tab_h = 45;
#if LV_FONT_MONTSERRAT_18
font_large = &lv_font_montserrat_18;
#else
LV_LOG_WARN("LV_FONT_MONTSERRAT_18 is not enabled for the widgets demo. Using LV_FONT_DEFAULT instead.");
#endif
#if LV_FONT_MONTSERRAT_12
font_normal = &lv_font_montserrat_12;
#else
LV_LOG_WARN("LV_FONT_MONTSERRAT_12 is not enabled for the widgets demo. Using LV_FONT_DEFAULT instead.");
#endif
} // 设置字体
lv_style_init(&style_text_muted);
lv_style_set_text_opa(&style_text_muted, LV_OPA_90);
lv_style_init(&style_title);
lv_style_set_text_font(&style_title, font_large);
lv_style_init(&style_icon);
lv_style_set_text_color(&style_icon, lv_theme_get_color_primary(NULL));
lv_style_set_text_font(&style_icon, font_large);
lv_style_init(&style_bullet);
lv_style_set_border_width(&style_bullet, 0);
lv_style_set_radius(&style_bullet, LV_RADIUS_CIRCLE);
tv = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, tab_h);
lv_obj_set_style_text_font(lv_scr_act(), font_normal, 0);
if(disp_size == DISP_LARGE) {
lv_obj_t * tab_btns = lv_tabview_get_tab_btns(tv);
lv_obj_set_style_pad_left(tab_btns, LV_HOR_RES / 2, 0);
lv_obj_t * logo = lv_img_create(tab_btns);
LV_IMG_DECLARE(img_lvgl_logo);
lv_img_set_src(logo, &img_lvgl_logo);
lv_obj_align(logo, LV_ALIGN_LEFT_MID, -LV_HOR_RES / 2 + 25, 0);
lv_obj_t * label = lv_label_create(tab_btns);
lv_obj_add_style(label, &style_title, 0);
lv_label_set_text(label, "LVGL v8");
lv_obj_align_to(label, logo, LV_ALIGN_OUT_RIGHT_TOP, 10, 0);
label = lv_label_create(tab_btns);
lv_label_set_text(label, "Widgets demo");
lv_obj_add_style(label, &style_text_muted, 0);
lv_obj_align_to(label, logo, LV_ALIGN_OUT_RIGHT_BOTTOM, 10, 0);
}
lv_obj_t * t1 = lv_tabview_add_tab(tv, "Onboard");
// lv_obj_t * t2 = lv_tabview_add_tab(tv, "Buzzer");
// lv_obj_t * t3 = lv_tabview_add_tab(tv, "Shop");
// lv_coord_t screen_width = lv_obj_get_width(lv_scr_act());
// lv_obj_set_width(t1, screen_width);
Onboard_create(t1);
// Buzzer_create(t2);
// shop_create(t3);
// color_changer_create(tv);
}
static void led_event_cb(lv_event_t *e) {
lv_obj_t *led = (lv_obj_t *)lv_event_get_user_data(e);
lv_obj_t *sw = lv_event_get_target(e);
if (lv_obj_get_state(sw) & LV_STATE_CHECKED) {
lv_led_on(led);
Set_EXIO(EXIO_PIN8,High);
}
else {
lv_led_off(led);
Set_EXIO(EXIO_PIN8,Low);
}
}
static void Buzzer_create(lv_obj_t * parent)
{
lv_obj_t *label = lv_label_create(parent);
lv_label_set_text(label, "The buzzer tes");
lv_obj_set_size(label, LV_PCT(30), LV_PCT(5));
lv_obj_align(label, LV_ALIGN_CENTER, 0, -60);
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_t *led = lv_led_create(parent);
lv_obj_set_size(led, 50, 50);
lv_obj_align(led, LV_ALIGN_CENTER, -60, 0);
lv_led_off(led);
lv_obj_t *sw = lv_switch_create(parent);
lv_obj_align(sw, LV_ALIGN_CENTER, 60, 0);
lv_obj_add_event_cb(sw, led_event_cb, LV_EVENT_VALUE_CHANGED, led);
}
void Lvgl_Example1_close(void)
{
/*Delete all animation*/
lv_anim_del(NULL, NULL);
lv_timer_del(meter2_timer);
meter2_timer = NULL;
lv_obj_clean(lv_scr_act());
lv_style_reset(&style_text_muted);
lv_style_reset(&style_title);
lv_style_reset(&style_icon);
lv_style_reset(&style_bullet);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void Onboard_create(lv_obj_t * parent)
{
/*Create a panel*/
lv_obj_t * panel1 = lv_obj_create(parent);
lv_obj_set_height(panel1, LV_SIZE_CONTENT);
lv_obj_t * panel1_title = lv_label_create(panel1);
lv_label_set_text(panel1_title, "Onboard parameter");
lv_obj_add_style(panel1_title, &style_title, 0);
lv_obj_t * SD_label = lv_label_create(panel1);
lv_label_set_text(SD_label, "SD Card");
lv_obj_add_style(SD_label, &style_text_muted, 0);
SD_Size = lv_textarea_create(panel1);
lv_textarea_set_one_line(SD_Size, true);
lv_textarea_set_placeholder_text(SD_Size, "SD Size");
lv_obj_add_event_cb(SD_Size, ta_event_cb, LV_EVENT_ALL, NULL);
lv_obj_t * Flash_label = lv_label_create(panel1);
lv_label_set_text(Flash_label, "Flash Size");
lv_obj_add_style(Flash_label, &style_text_muted, 0);
FlashSize = lv_textarea_create(panel1);
lv_textarea_set_one_line(FlashSize, true);
lv_textarea_set_placeholder_text(FlashSize, "Flash Size");
lv_obj_add_event_cb(FlashSize, ta_event_cb, LV_EVENT_ALL, NULL);
lv_obj_t * BAT_label = lv_label_create(panel1);
lv_label_set_text(BAT_label, "Battery Voltage");
lv_obj_add_style(BAT_label, &style_text_muted, 0);
BAT_Volts = lv_textarea_create(panel1);
lv_textarea_set_one_line(BAT_Volts, true);
lv_textarea_set_placeholder_text(BAT_Volts, "BAT Volts");
lv_obj_add_event_cb(BAT_Volts, ta_event_cb, LV_EVENT_ALL, NULL);
lv_obj_t * angle_label = lv_label_create(panel1);
lv_label_set_text(angle_label, "Angular deflection");
lv_obj_add_style(angle_label, &style_text_muted, 0);
Board_angle = lv_textarea_create(panel1);
lv_textarea_set_one_line(Board_angle, true);
lv_textarea_set_placeholder_text(Board_angle, "Board angle");
lv_obj_add_event_cb(Board_angle, ta_event_cb, LV_EVENT_ALL, NULL);
lv_obj_t * Time_label = lv_label_create(panel1);
lv_label_set_text(Time_label, "RTC Time");
lv_obj_add_style(Time_label, &style_text_muted, 0);
RTC_Time = lv_textarea_create(panel1);
lv_textarea_set_one_line(RTC_Time, true);
lv_textarea_set_placeholder_text(RTC_Time, "Display time");
lv_obj_add_event_cb(RTC_Time, ta_event_cb, LV_EVENT_ALL, NULL);
lv_obj_t * Wireless_label = lv_label_create(panel1);
lv_label_set_text(Wireless_label, "Wireless scan");
lv_obj_add_style(Wireless_label, &style_text_muted, 0);
Wireless_Scan = lv_textarea_create(panel1);
lv_textarea_set_one_line(Wireless_Scan, true);
lv_textarea_set_placeholder_text(Wireless_Scan, "Wireless number");
lv_obj_add_event_cb(Wireless_Scan, ta_event_cb, LV_EVENT_ALL, NULL);
lv_obj_t * Backlight_label = lv_label_create(panel1);
lv_label_set_text(Backlight_label, "Backlight brightness");
lv_obj_add_style(Backlight_label, &style_text_muted, 0);
Backlight_slider = lv_slider_create(panel1);
lv_obj_add_flag(Backlight_slider, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_size(Backlight_slider, 200, 35);
lv_obj_set_style_radius(Backlight_slider, 3, LV_PART_KNOB); // Adjust the value for more or less rounding
lv_obj_set_style_bg_opa(Backlight_slider, LV_OPA_TRANSP, LV_PART_KNOB);
// lv_obj_set_style_pad_all(Backlight_slider, 0, LV_PART_KNOB);
lv_obj_set_style_bg_color(Backlight_slider, lv_color_hex(0xAAAAAA), LV_PART_KNOB);
lv_obj_set_style_bg_color(Backlight_slider, lv_color_hex(0xFFFFFF), LV_PART_INDICATOR);
lv_obj_set_style_outline_width(Backlight_slider, 2, LV_PART_INDICATOR);
lv_obj_set_style_outline_color(Backlight_slider, lv_color_hex(0xD3D3D3), LV_PART_INDICATOR);
lv_slider_set_range(Backlight_slider, 5, Backlight_MAX);
lv_slider_set_value(Backlight_slider, LCD_Backlight, LV_ANIM_ON);
lv_obj_add_event_cb(Backlight_slider, Backlight_adjustment_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
lv_obj_t * panel2 = lv_obj_create(parent);
lv_obj_set_height(panel2, LV_SIZE_CONTENT);
lv_obj_t * panel2_title = lv_label_create(panel2);
lv_label_set_text(panel2_title, "The buzzer tes");
lv_obj_add_style(panel2_title, &style_title, 0);
lv_obj_t *led = lv_led_create(panel2);
lv_obj_set_size(led, 50, 50);
lv_obj_align(led, LV_ALIGN_CENTER, -60, 0);
lv_led_off(led);
lv_obj_t *sw = lv_switch_create(panel2);
lv_obj_set_size(sw, 65, 40);
lv_obj_align(sw, LV_ALIGN_CENTER, 60, 0);
lv_obj_add_event_cb(sw, led_event_cb, LV_EVENT_VALUE_CHANGED, led);
/////////////////////////////////////////////////////////
static lv_coord_t grid_main_col_dsc[] = {LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
static lv_coord_t grid_main_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
/*Create the top panel*/
static lv_coord_t grid_1_col_dsc[] = {LV_GRID_FR(4), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(4), LV_GRID_TEMPLATE_LAST};
static lv_coord_t grid_1_row_dsc[] = {
LV_GRID_CONTENT, /*Name*/
LV_GRID_CONTENT, /*Description*/
LV_GRID_CONTENT, /*Email*/
LV_GRID_CONTENT, /*Email*/
LV_GRID_TEMPLATE_LAST
};
static lv_coord_t grid_2_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(5), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
static lv_coord_t grid_2_row_dsc[] = {
LV_GRID_CONTENT, /*Title*/
5, /*Separator*/
LV_GRID_CONTENT, /*Box title*/
40, /*Box*/
LV_GRID_CONTENT, /*Box title*/
40, /*Box*/
LV_GRID_CONTENT, /*Box title*/
40, /*Box*/
LV_GRID_CONTENT, /*Box title*/
40, /*Box*/
LV_GRID_CONTENT, /*Box title*/
40, /*Box*/
LV_GRID_CONTENT, /*Box title*/
40, /*Box*/
LV_GRID_CONTENT, /*Box title*/
40, /*Box*/
LV_GRID_TEMPLATE_LAST
};
lv_obj_set_grid_dsc_array(parent, grid_main_col_dsc, grid_main_row_dsc);
lv_obj_set_grid_cell(panel1, LV_GRID_ALIGN_STRETCH, 0, 1, LV_GRID_ALIGN_START, 0, 1);
lv_obj_set_grid_dsc_array(panel1, grid_2_col_dsc, grid_2_row_dsc);
lv_obj_set_grid_cell(panel1_title, LV_GRID_ALIGN_CENTER, 1, 1, LV_GRID_ALIGN_CENTER, 0, 1);
lv_obj_set_grid_cell(SD_label, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_START, 2, 1);
lv_obj_set_grid_cell(SD_Size, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 3, 1);
lv_obj_set_grid_cell(Flash_label, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_START, 4, 1);
lv_obj_set_grid_cell(FlashSize, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 5, 1);
lv_obj_set_grid_cell(BAT_label, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_START, 6, 1);
lv_obj_set_grid_cell(BAT_Volts, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 7, 1);
lv_obj_set_grid_cell(angle_label, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_START, 8, 1);
lv_obj_set_grid_cell(Board_angle, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 9, 1);
lv_obj_set_grid_cell(Time_label, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_START, 10, 1);
lv_obj_set_grid_cell(RTC_Time, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 11, 1);
lv_obj_set_grid_cell(Wireless_label, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_START, 12, 1);
lv_obj_set_grid_cell(Wireless_Scan, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 13, 1);
lv_obj_set_grid_cell(Backlight_label, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_START, 14, 1);
lv_obj_set_grid_cell(Backlight_slider, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 15, 1);
lv_obj_set_grid_cell(panel2, LV_GRID_ALIGN_STRETCH, 0, 1, LV_GRID_ALIGN_STRETCH, 1, 1);
lv_obj_set_grid_dsc_array(panel2, grid_1_col_dsc, grid_1_row_dsc);
lv_obj_set_grid_cell(panel2_title, LV_GRID_ALIGN_CENTER, 2, 1, LV_GRID_ALIGN_CENTER, 0, 1);
lv_obj_set_grid_cell(led, LV_GRID_ALIGN_CENTER, 1, 1, LV_GRID_ALIGN_CENTER, 2, 1);
lv_obj_set_grid_cell(sw, LV_GRID_ALIGN_CENTER, 3, 1, LV_GRID_ALIGN_CENTER, 2, 1);
auto_step_timer = lv_timer_create(example1_increase_lvgl_tick, 100, NULL);
}
void example1_increase_lvgl_tick(lv_timer_t * t)
{
char buf[100];
snprintf(buf, sizeof(buf), "%d MB\r\n", SDCard_Size);
lv_textarea_set_placeholder_text(SD_Size, buf);
snprintf(buf, sizeof(buf), "%d MB\r\n", Flash_Size);
lv_textarea_set_placeholder_text(FlashSize, buf);
snprintf(buf, sizeof(buf), "%.2f V\r\n", BAT_analogVolts);
lv_textarea_set_placeholder_text(BAT_Volts, buf);
snprintf(buf, sizeof(buf), "X:%.2f Y:%.2f Z:%.2f\r\n", Accel.x, Accel.y, Accel.z);
lv_textarea_set_placeholder_text(Board_angle, buf);
snprintf(buf, sizeof(buf), "%d.%d.%d %d:%d:%d\r\n",datetime.year,datetime.month,datetime.day,datetime.hour,datetime.minute,datetime.second);
lv_textarea_set_placeholder_text(RTC_Time, buf);
if(Scan_finish)
snprintf(buf, sizeof(buf), "WIFI: %d BLE: %d ..Scan Finish.\r\n",WIFI_NUM,BLE_NUM);
else
snprintf(buf, sizeof(buf), "WIFI: %d BLE: %d\r\n",WIFI_NUM,BLE_NUM);
lv_textarea_set_placeholder_text(Wireless_Scan, buf);
lv_slider_set_value(Backlight_slider, LCD_Backlight, LV_ANIM_ON);
LVGL_Backlight_adjustment(LCD_Backlight);
}
// static void Music_create(lv_obj_t * parent)
// {
// static lv_obj_t * ctrl;
// original_screen_bg_color = lv_obj_get_style_bg_color(parent, 0);
// lv_obj_set_style_bg_color(parent, lv_color_hex(0x343247), 0);
// ctrl = _lv_demo_music_main_create(parent);
// }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void color_changer_create(lv_obj_t * parent)
{
static lv_palette_t palette[] = {
LV_PALETTE_BLUE, LV_PALETTE_GREEN, LV_PALETTE_BLUE_GREY, LV_PALETTE_ORANGE,
LV_PALETTE_RED, LV_PALETTE_PURPLE, LV_PALETTE_TEAL, _LV_PALETTE_LAST
};
lv_obj_t * color_cont = lv_obj_create(parent);
lv_obj_remove_style_all(color_cont);
lv_obj_set_flex_flow(color_cont, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(color_cont, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_add_flag(color_cont, LV_OBJ_FLAG_FLOATING);
lv_obj_set_style_bg_color(color_cont, lv_color_white(), 0);
lv_obj_set_style_pad_right(color_cont, disp_size == DISP_SMALL ? LV_DPX(47) : LV_DPX(55), 0);
lv_obj_set_style_bg_opa(color_cont, LV_OPA_COVER, 0);
lv_obj_set_style_radius(color_cont, LV_RADIUS_CIRCLE, 0);
if(disp_size == DISP_SMALL) lv_obj_set_size(color_cont, LV_DPX(52), LV_DPX(52));
else lv_obj_set_size(color_cont, LV_DPX(60), LV_DPX(60));
lv_obj_align(color_cont, LV_ALIGN_BOTTOM_RIGHT, - LV_DPX(10), - LV_DPX(10));
uint32_t i;
for(i = 0; palette[i] != _LV_PALETTE_LAST; i++) {
lv_obj_t * c = lv_btn_create(color_cont);
lv_obj_set_style_bg_color(c, lv_palette_main(palette[i]), 0);
lv_obj_set_style_radius(c, LV_RADIUS_CIRCLE, 0);
lv_obj_set_style_opa(c, LV_OPA_TRANSP, 0);
lv_obj_set_size(c, 20, 20);
lv_obj_add_event_cb(c, color_event_cb, LV_EVENT_ALL, &palette[i]);
lv_obj_clear_flag(c, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
}
lv_obj_t * btn = lv_btn_create(parent);
lv_obj_add_flag(btn, LV_OBJ_FLAG_FLOATING | LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_style_bg_color(btn, lv_color_white(), LV_STATE_CHECKED);
lv_obj_set_style_pad_all(btn, 10, 0);
lv_obj_set_style_radius(btn, LV_RADIUS_CIRCLE, 0);
lv_obj_add_event_cb(btn, color_changer_event_cb, LV_EVENT_ALL, color_cont);
lv_obj_set_style_shadow_width(btn, 0, 0);
lv_obj_set_style_bg_img_src(btn, LV_SYMBOL_TINT, 0);
if(disp_size == DISP_SMALL) {
lv_obj_set_size(btn, LV_DPX(42), LV_DPX(42));
lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -LV_DPX(15), -LV_DPX(15));
}
else {
lv_obj_set_size(btn, LV_DPX(50), LV_DPX(50));
lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -LV_DPX(15), -LV_DPX(15));
}
}
static void color_changer_anim_cb(void * var, int32_t v)
{
lv_obj_t * obj =(lv_obj_t *) var;
lv_coord_t max_w = lv_obj_get_width(lv_obj_get_parent(obj)) - LV_DPX(20);
lv_coord_t w;
if(disp_size == DISP_SMALL) {
w = lv_map(v, 0, 256, LV_DPX(52), max_w);
lv_obj_set_width(obj, w);
lv_obj_align(obj, LV_ALIGN_BOTTOM_RIGHT, - LV_DPX(10), - LV_DPX(10));
}
else {
w = lv_map(v, 0, 256, LV_DPX(60), max_w);
lv_obj_set_width(obj, w);
lv_obj_align(obj, LV_ALIGN_BOTTOM_RIGHT, - LV_DPX(10), - LV_DPX(10));
}
if(v > LV_OPA_COVER) v = LV_OPA_COVER;
uint32_t i;
for(i = 0; i < lv_obj_get_child_cnt(obj); i++) {
lv_obj_set_style_opa(lv_obj_get_child(obj, i), v, 0);
}
}
static void color_changer_event_cb(lv_event_t * e)
{
if(lv_event_get_code(e) == LV_EVENT_CLICKED) {
lv_obj_t * color_cont = (lv_obj_t *)lv_event_get_user_data(e);
if(lv_obj_get_width(color_cont) < LV_HOR_RES / 2) {
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, color_cont);
lv_anim_set_exec_cb(&a, color_changer_anim_cb);
lv_anim_set_values(&a, 0, 256);
lv_anim_set_time(&a, 200);
lv_anim_start(&a);
}
else {
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, color_cont);
lv_anim_set_exec_cb(&a, color_changer_anim_cb);
lv_anim_set_values(&a, 256, 0);
lv_anim_set_time(&a, 200);
lv_anim_start(&a);
}
}
}
static void color_event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_FOCUSED) {
lv_obj_t * color_cont = lv_obj_get_parent(obj);
if(lv_obj_get_width(color_cont) < LV_HOR_RES / 2) {
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, color_cont);
lv_anim_set_exec_cb(&a, color_changer_anim_cb);
lv_anim_set_values(&a, 0, 256);
lv_anim_set_time(&a, 200);
lv_anim_start(&a);
}
}
else if(code == LV_EVENT_CLICKED) {
lv_palette_t * palette_primary = (lv_palette_t *)lv_event_get_user_data(e);
lv_palette_t palette_secondary =(lv_palette_t) ((*palette_primary) + 3); /*Use another palette as secondary*/
if(palette_secondary >= _LV_PALETTE_LAST) palette_secondary =(lv_palette_t)(0);
#if LV_USE_THEME_DEFAULT
lv_theme_default_init(NULL, lv_palette_main(*palette_primary), lv_palette_main(palette_secondary),
LV_THEME_DEFAULT_DARK, font_normal);
#endif
lv_color_t color = lv_palette_main(*palette_primary);
lv_style_set_text_color(&style_icon, color);
lv_chart_set_series_color(chart1, ser1, color);
lv_chart_set_series_color(chart2, ser3, color);
}
}
static void ta_event_cb(lv_event_t * e)
{
}
static void birthday_event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * ta = lv_event_get_target(e);
if(code == LV_EVENT_FOCUSED) {
if(lv_indev_get_type(lv_indev_get_act()) == LV_INDEV_TYPE_POINTER) {
if(calendar == NULL) {
lv_obj_add_flag(lv_layer_top(), LV_OBJ_FLAG_CLICKABLE);
calendar = lv_calendar_create(lv_layer_top());
lv_obj_set_style_bg_opa(lv_layer_top(), LV_OPA_50, 0);
lv_obj_set_style_bg_color(lv_layer_top(), lv_palette_main(LV_PALETTE_GREY), 0);
if(disp_size == DISP_SMALL) lv_obj_set_size(calendar, 180, 200);
else if(disp_size == DISP_MEDIUM) lv_obj_set_size(calendar, 200, 220);
else lv_obj_set_size(calendar, 300, 330);
lv_calendar_set_showed_date(calendar, 1990, 01);
lv_obj_align(calendar, LV_ALIGN_CENTER, 0, 30);
lv_obj_add_event_cb(calendar, calendar_event_cb, LV_EVENT_ALL, ta);
lv_calendar_header_dropdown_create(calendar);
}
}
}
}
static void calendar_event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * ta = (lv_obj_t *)lv_event_get_user_data(e);
lv_obj_t * obj = (lv_obj_t *)lv_event_get_current_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
lv_calendar_date_t d;
lv_calendar_get_pressed_date(obj, &d);
char buf[32];
lv_snprintf(buf, sizeof(buf), "%02d.%02d.%d", d.day, d.month, d.year);
lv_textarea_set_text(ta, buf);
lv_obj_del(calendar);
calendar = NULL;
lv_obj_clear_flag(lv_layer_top(), LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_style_bg_opa(lv_layer_top(), LV_OPA_TRANSP, 0);
}
}
void Backlight_adjustment_event_cb(lv_event_t * e) {
uint8_t Backlight = lv_slider_get_value(lv_event_get_target(e));
if (Backlight >= 0 && Backlight <= Backlight_MAX) {
lv_slider_set_value(Backlight_slider, Backlight, LV_ANIM_ON);
LCD_Backlight = Backlight;
LVGL_Backlight_adjustment(Backlight);
}
else
printf("Backlight out of range: %d\n", Backlight);
}
void LVGL_Backlight_adjustment(uint8_t Backlight) {
Set_Backlight(Backlight);
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "LVGL_Driver.h"
#include "Gyro_QMI8658.h"
#include "RTC_PCF85063.h"
#include "SD_Card.h"
#include "Wireless.h"
#include "BAT_Driver.h"
#include "Display_ST7701.h"
#define EXAMPLE1_LVGL_TICK_PERIOD_MS 1000
void Backlight_adjustment_event_cb(lv_event_t * e);
void LVGL_Backlight_adjustment(uint8_t Backlight);
void Lvgl_Example1(void);
+168
View File
@@ -0,0 +1,168 @@
#include "OtaService.h"
#include <cstring>
#include "WiFi.h"
#include "WebServer.h"
#include "Update.h"
#include "esp_ota_ops.h"
#include "esp_system.h"
#include "mbedtls/sha256.h"
#include "../shared/OtaAuth.h"
#include "../shared/OtaSecrets.h"
#ifndef EYE_BOARD_NUMBER
#define EYE_BOARD_NUMBER 1
#endif
namespace {
constexpr uint16_t kPort = 3232;
#if EYE_BOARD_NUMBER == 2
constexpr char kDevice[] = "eye-2";
constexpr char kImageTarget[] = "FREDDY_OTA_TARGET:eye-2";
#else
constexpr char kDevice[] = "eye-1";
constexpr char kImageTarget[] = "FREDDY_OTA_TARGET:eye-1";
#endif
WebServer server(kPort);
char nonce[33] = {};
char expected_sha[65] = {};
uint32_t nonce_time = 0;
uint32_t retry_time = 0;
uint32_t status_time = 0;
uint32_t restart_time = 0;
size_t expected_length = 0;
bool listening = false;
bool upload_ok = false;
bool upload_started = false;
mbedtls_sha256_context sha_context;
void new_nonce() {
uint8_t random_bytes[16];
esp_fill_random(random_bytes, sizeof(random_bytes));
freddy_ota::to_hex(random_bytes, sizeof(random_bytes), nonce);
nonce_time = millis();
}
void send_info() {
new_nonce();
const esp_partition_t *slot = esp_ota_get_next_update_partition(nullptr);
const esp_partition_t *running = esp_ota_get_running_partition();
char body[180];
snprintf(body, sizeof(body),
"{\"device\":\"%s\",\"nonce\":\"%s\",\"slot_bytes\":%u,\"running_slot\":%d}",
kDevice, nonce, slot ? static_cast<unsigned>(slot->size) : 0,
running ? static_cast<int>(running->subtype) - ESP_PARTITION_SUBTYPE_APP_OTA_0 : -1);
server.send(200, "application/json", body);
}
void handle_raw() {
HTTPRaw &raw = server.raw();
if (raw.status == RAW_START) {
upload_ok = false;
upload_started = false;
const String length_text = server.header("Content-Length");
const String nonce_text = server.header("X-Freddy-Nonce");
const String sha_text = server.header("X-Freddy-SHA256");
const String signature = server.header("X-Freddy-Signature");
char *end = nullptr;
const unsigned long parsed = strtoul(length_text.c_str(), &end, 10);
const esp_partition_t *slot = esp_ota_get_next_update_partition(nullptr);
if (!slot || !end || *end || !parsed || parsed > slot->size ||
millis() - nonce_time > 60000 || nonce_text != nonce ||
!freddy_ota::verify(FREDDY_OTA_KEY, kDevice, nonce,
sha_text.c_str(), parsed, signature.c_str())) return;
expected_length = parsed;
memcpy(expected_sha, sha_text.c_str(), 65);
nonce[0] = 0; // One use, even when the transfer fails.
if (!Update.begin(expected_length)) return;
mbedtls_sha256_init(&sha_context);
if (mbedtls_sha256_starts(&sha_context, 0) != 0) {
Update.abort();
mbedtls_sha256_free(&sha_context);
return;
}
upload_started = true;
} else if (raw.status == RAW_WRITE && upload_started) {
if (Update.write(raw.buf, raw.currentSize) != raw.currentSize ||
mbedtls_sha256_update(&sha_context, raw.buf, raw.currentSize) != 0) {
Update.abort();
mbedtls_sha256_free(&sha_context);
upload_started = false;
}
} else if (raw.status == RAW_END && upload_started) {
uint8_t digest[32] = {};
char actual[65];
const bool hash_ok =
raw.totalSize == expected_length &&
mbedtls_sha256_finish(&sha_context, digest) == 0;
mbedtls_sha256_free(&sha_context);
freddy_ota::to_hex(digest, sizeof(digest), actual);
upload_ok = hash_ok &&
freddy_ota::constant_time_equal(actual, expected_sha, 64);
if (upload_ok) upload_ok = Update.end();
else Update.abort();
upload_started = false;
} else if (raw.status == RAW_ABORTED && upload_started) {
Update.abort();
mbedtls_sha256_free(&sha_context);
upload_started = false;
}
}
void finish_upload() {
if (upload_ok) {
server.send(200, "application/json", "{\"ok\":true}");
restart_time = millis() + 1000;
} else {
server.send(400, "application/json", "{\"ok\":false}");
}
}
} // namespace
void OtaService_Begin() {
if (!FREDDY_WIFI_SSID[0] || strlen(FREDDY_OTA_KEY) < 32) {
Serial.println("OTA_DISABLED: configure firmware/private/ first");
return;
}
const char *headers[] = {
"Content-Length", "X-Freddy-Nonce", "X-Freddy-SHA256",
"X-Freddy-Signature"};
server.collectHeaders(headers, 4);
server.on("/ota/info", HTTP_GET, send_info);
server.on("/ota", HTTP_POST, finish_upload, handle_raw);
WiFi.mode(WIFI_STA);
WiFi.setHostname(EYE_BOARD_NUMBER == 2 ? "freddy-eye-2" : "freddy-eye-1");
WiFi.setSleep(false);
WiFi.begin(FREDDY_WIFI_SSID, FREDDY_WIFI_PASSWORD);
retry_time = millis();
}
void OtaService_Loop() {
if (!FREDDY_WIFI_SSID[0] || strlen(FREDDY_OTA_KEY) < 32) return;
if (restart_time && static_cast<int32_t>(millis() - restart_time) >= 0)
ESP.restart();
if (millis() - status_time >= 10000) {
status_time = millis();
if (Serial) Serial.printf("OTA_WIFI device=%s status=%d ip=%s\n",
kDevice, WiFi.status(),
WiFi.localIP().toString().c_str());
}
if (WiFi.status() != WL_CONNECTED) {
if (listening) {
server.stop();
listening = false;
}
if (millis() - retry_time > 10000) {
WiFi.reconnect();
retry_time = millis();
}
return;
}
if (!listening) {
server.begin();
listening = true;
Serial.printf("OTA_READY device=%s image=%s ip=%s port=%u\n",
kDevice, kImageTarget, WiFi.localIP().toString().c_str(), kPort);
}
server.handleClient();
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
void OtaService_Begin();
void OtaService_Loop();
+229
View File
@@ -0,0 +1,229 @@
#include "RTC_PCF85063.h"
datetime_t datetime= {0};
static uint8_t decToBcd(int val);
static int bcdToDec(uint8_t val);
const unsigned char MonthStr[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov","Dec"};
/******************************************************************************
function: PCF85063 initialized
parameter:
Info:Initiate Normal Mode, RTC Run, NO reset, No correction , 24hr format, Internal load capacitane 12.5pf
******************************************************************************/
void PCF85063_Init()
{
uint8_t Value = RTC_CTRL_1_DEFAULT|RTC_CTRL_1_CAP_SEL;
I2C_Write(PCF85063_ADDRESS, RTC_CTRL_1_ADDR, &Value, 1);
I2C_Read(PCF85063_ADDRESS, RTC_CTRL_1_ADDR, &Value, 1);
if(Value & RTC_CTRL_1_STOP)
printf("PCF85063 failed to be initialized.state :%d\r\n",Value);
else
printf("PCF85063 is running,state :%d\r\n",Value);
// datetime_t Now_datetime= {0};
// Now_datetime.year = 2024;
// Now_datetime.month = 9;
// Now_datetime.day = 20;
// Now_datetime.dotw = 5;
// Now_datetime.hour = 9;
// Now_datetime.minute = 50;
// Now_datetime.second = 0;
// PCF85063_Set_All(Now_datetime);
}
void RTC_Loop(void)
{
PCF85063_Read_Time(&datetime);
}
/******************************************************************************
function: Reset PCF85063
parameter:
Info:
******************************************************************************/
void PCF85063_Reset()
{
uint8_t Value = RTC_CTRL_1_DEFAULT|RTC_CTRL_1_CAP_SEL|RTC_CTRL_1_SR;
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_CTRL_1_ADDR, &Value, 1);
if(ret != ESP_OK)
printf("PCF85063 : Reset failure\r\n");
}
/******************************************************************************
function: Set Time
parameter:
Info:
******************************************************************************/
void PCF85063_Set_Time(datetime_t time)
{
uint8_t buf[3] = {decToBcd(time.second),
decToBcd(time.minute),
decToBcd(time.hour)};
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_SECOND_ADDR, buf, sizeof(buf));
if(ret != ESP_OK)
printf("PCF85063 : Time setting failure\r\n");
}
/******************************************************************************
function: Set Date
parameter:
Info:
******************************************************************************/
void PCF85063_Set_Date(datetime_t date)
{
uint8_t buf[4] = {decToBcd(date.day),
decToBcd(date.dotw),
decToBcd(date.month),
decToBcd(date.year - YEAR_OFFSET)};
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_DAY_ADDR, buf, sizeof(buf));
if(ret != ESP_OK)
printf("PCF85063 : Date setting failed\r\n");
}
/******************************************************************************
function: Set Time And Date
parameter:
Info:
******************************************************************************/
void PCF85063_Set_All(datetime_t time)
{
uint8_t buf[7] = {decToBcd(time.second),
decToBcd(time.minute),
decToBcd(time.hour),
decToBcd(time.day),
decToBcd(time.dotw),
decToBcd(time.month),
decToBcd(time.year - YEAR_OFFSET)};
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_SECOND_ADDR, buf, sizeof(buf));
if(ret != ESP_OK)
printf("PCF85063 : Failed to set the date and time\r\n");
}
/******************************************************************************
function: Read Time And Date
parameter:
Info:
******************************************************************************/
void PCF85063_Read_Time(datetime_t *time)
{
uint8_t buf[7] = {0};
esp_err_t ret = I2C_Read(PCF85063_ADDRESS, RTC_SECOND_ADDR, buf, sizeof(buf));
if(ret != ESP_OK)
printf("PCF85063 : Time read failure\r\n");
else{
time->second = bcdToDec(buf[0] & 0x7F);
time->minute = bcdToDec(buf[1] & 0x7F);
time->hour = bcdToDec(buf[2] & 0x3F);
time->day = bcdToDec(buf[3] & 0x3F);
time->dotw = bcdToDec(buf[4] & 0x07);
time->month = bcdToDec(buf[5] & 0x1F);
time->year = bcdToDec(buf[6]) + YEAR_OFFSET;
}
}
/******************************************************************************
function: Enable Alarm and Clear Alarm flag
parameter:
Info:
******************************************************************************/
void PCF85063_Enable_Alarm()
{
uint8_t Value = RTC_CTRL_2_DEFAULT | RTC_CTRL_2_AIE;
Value &= ~RTC_CTRL_2_AF;
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_CTRL_2_ADDR, &Value, 1);
if(ret != ESP_OK)
printf("PCF85063 : Failed to enable Alarm Flag and Clear Alarm Flag \r\n");
}
/******************************************************************************
function: Get Alarm flag
parameter:
Info:
******************************************************************************/
uint8_t PCF85063_Get_Alarm_Flag()
{
uint8_t Value = 0;
esp_err_t ret = I2C_Read(PCF85063_ADDRESS, RTC_CTRL_2_ADDR, &Value, 1);
if(ret != ESP_OK)
printf("PCF85063 : Failed to obtain a warning flag.\r\n");
else
Value &= RTC_CTRL_2_AF | RTC_CTRL_2_AIE;
//printf("Value = 0x%x",Value);
return Value;
}
/******************************************************************************
function: Set Alarm
parameter:
Info:
******************************************************************************/
void PCF85063_Set_Alarm(datetime_t time)
{
uint8_t buf[5] ={
decToBcd(time.second)&(~RTC_ALARM),
decToBcd(time.minute)&(~RTC_ALARM),
decToBcd(time.hour)&(~RTC_ALARM),
//decToBcd(time.day)&(~RTC_ALARM),
//decToBcd(time.dotw)&(~RTC_ALARM)
RTC_ALARM, //disalbe day
RTC_ALARM //disalbe weekday
};
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_SECOND_ALARM, buf, sizeof(buf));
if(ret != ESP_OK)
printf("PCF85063 : Failed to set alarm flag\r\n");
}
/******************************************************************************
function: Read Alarm
parameter:
Info:
******************************************************************************/
void PCF85063_Read_Alarm(datetime_t *time)
{
uint8_t buf[5] = {0};
esp_err_t ret = I2C_Read(PCF85063_ADDRESS, RTC_SECOND_ALARM, buf, sizeof(buf));
if(ret != ESP_OK)
printf("PCF85063 : Failed to read the alarm sign\r\n");
else{
time->second = bcdToDec(buf[0] & 0x7F);
time->minute = bcdToDec(buf[1] & 0x7F);
time->hour = bcdToDec(buf[2] & 0x3F);
time->day = bcdToDec(buf[3] & 0x3F);
time->dotw = bcdToDec(buf[4] & 0x07);
}
}
/******************************************************************************
function: Convert normal decimal numbers to binary coded decimal
parameter:
Info:
******************************************************************************/
static uint8_t decToBcd(int val)
{
return (uint8_t)((val / 10 * 16) + (val % 10));
}
/******************************************************************************
function: Convert binary coded decimal to normal decimal numbers
parameter:
Info:
******************************************************************************/
static int bcdToDec(uint8_t val)
{
return (int)((val / 16 * 10) + (val % 16));
}
/******************************************************************************
function:
parameter:
Info:
******************************************************************************/
void datetime_to_str(char *datetime_str,datetime_t time)
{
sprintf(datetime_str, " %d.%d.%d %d %d:%d:%d ", time.year, time.month,
time.day, time.dotw, time.hour, time.minute, time.second);
}
+102
View File
@@ -0,0 +1,102 @@
#pragma once
#include "I2C_Driver.h"
//PCF85063_ADDRESS
#define PCF85063_ADDRESS (0x51)
//
#define YEAR_OFFSET (1970)
// registar overview - crtl & status reg
#define RTC_CTRL_1_ADDR (0x00)
#define RTC_CTRL_2_ADDR (0x01)
#define RTC_OFFSET_ADDR (0x02)
#define RTC_RAM_by_ADDR (0x03)
// registar overview - time & data reg
#define RTC_SECOND_ADDR (0x04)
#define RTC_MINUTE_ADDR (0x05)
#define RTC_HOUR_ADDR (0x06)
#define RTC_DAY_ADDR (0x07)
#define RTC_WDAY_ADDR (0x08)
#define RTC_MONTH_ADDR (0x09)
#define RTC_YEAR_ADDR (0x0A) // years 0-99; calculate real year = 1970 + RCC reg year
// registar overview - alarm reg
#define RTC_SECOND_ALARM (0x0B)
#define RTC_MINUTE_ALARM (0x0C)
#define RTC_HOUR_ALARM (0x0D)
#define RTC_DAY_ALARM (0x0E)
#define RTC_WDAY_ALARM (0x0F)
// registar overview - timer reg
#define RTC_TIMER_VAL (0x10)
#define RTC_TIMER_MODE (0x11)
//RTC_CTRL_1 registar
#define RTC_CTRL_1_EXT_TEST (0x80)
#define RTC_CTRL_1_STOP (0x20) //0-RTC clock runs 1- RTC clock is stopped
#define RTC_CTRL_1_SR (0X10) //0-no software reset 1-initiate software rese
#define RTC_CTRL_1_CIE (0X04) //0-no correction interrupt generated 1-interrupt pulses are generated at every correction cycle
#define RTC_CTRL_1_12_24 (0X02) //0-24H 1-12H
#define RTC_CTRL_1_CAP_SEL (0X01) //0-7PF 1-12.5PF
//RTC_CTRL_2 registar
#define RTC_CTRL_2_AIE (0X80) //alarm interrupt 0-disalbe 1-enable
#define RTC_CTRL_2_AF (0X40) //alarm flag 0-inactive/cleared 1-active/unchanged
#define RTC_CTRL_2_MI (0X20) //minute interrupt 0-disalbe 1-enable
#define RTC_CTRL_2_HMI (0X10) //half minute interrupt
#define RTC_CTRL_2_TF (0X08)
//
#define RTC_OFFSET_MODE (0X80)
//
#define RTC_TIMER_MODE_TE (0X04) //timer enable 0-disalbe 1-enable
#define RTC_TIMER_MODE_TIE (0X02) //timer interrupt enable 0-disalbe 1-enable
#define RTC_TIMER_MODE_TI_TP (0X01) //timer interrupt mode 0-interrupt follows timer flag 1-interrupt generates a pulse
// format
#define RTC_ALARM (0x80) // set AEN_x registers
#define RTC_CTRL_1_DEFAULT (0x00)
#define RTC_CTRL_2_DEFAULT (0x00)
#define RTC_TIMER_FLAG (0x08)
typedef struct {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t dotw;
uint8_t hour;
uint8_t minute;
uint8_t second;
}datetime_t;
extern datetime_t datetime;
void PCF85063_Init(void);
void RTC_Loop(void);
void PCF85063_Reset(void);
void PCF85063_Set_Time(datetime_t time);
void PCF85063_Set_Date(datetime_t date);
void PCF85063_Set_All(datetime_t time);
void PCF85063_Read_Time(datetime_t *time);
void PCF85063_Enable_Alarm(void);
uint8_t PCF85063_Get_Alarm_Flag();
void PCF85063_Set_Alarm(datetime_t time);
void PCF85063_Read_Alarm(datetime_t *time);
void datetime_to_str(char *datetime_str,datetime_t time);
// weekday format
// 0 - sunday
// 1 - monday
// 2 - tuesday
// 3 - wednesday
// 4 - thursday
// 5 - friday
// 6 - saturday
+122
View File
@@ -0,0 +1,122 @@
#include "SD_Card.h"
bool SDCard_Flag;
bool SDCard_Finish;
uint16_t SDCard_Size;
uint16_t Flash_Size;
void SD_D3_Dis(){
Set_EXIO(EXIO_PIN4,Low);
vTaskDelay(pdMS_TO_TICKS(10));
}
void SD_D3_EN(){
Set_EXIO(EXIO_PIN4,High);
vTaskDelay(pdMS_TO_TICKS(10));
}
void SD_Init() {
// SD MMC
if(!SD_MMC.setPins(SD_CLK_PIN, SD_CMD_PIN, SD_D0_PIN,-1,-1,-1)){
printf("SD MMC: Pin change failed!\r\n");
return;
}
SD_D3_EN();
if (SD_MMC.begin("/sdcard", true, true)) { // "/sdcard", true, true or "/sdcard", true, false
printf("SD card initialization successful!\r\n");
} else {
printf("SD card initialization failed!\r\n");
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
printf("No SD card attached\r\n");
return;
}
else{
printf("SD Card Type: ");
if(cardType == CARD_MMC){
printf("MMC\r\n");
} else if(cardType == CARD_SD){
printf("SDSC\r\n");
} else if(cardType == CARD_SDHC){
printf("SDHC\r\n");
} else {
printf("UNKNOWN\r\n");
}
uint64_t totalBytes = SD_MMC.totalBytes();
uint64_t usedBytes = SD_MMC.usedBytes();
SDCard_Size = totalBytes/(1024*1024);
printf("Total space: %llu\n", totalBytes);
printf("Used space: %llu\n", usedBytes);
printf("Free space: %llu\n", totalBytes - usedBytes);
}
}
bool File_Search(const char* directory, const char* fileName)
{
File Path = SD_MMC.open(directory);
if (!Path) {
printf("Path: <%s> does not exist\r\n",directory);
return false;
}
File file = Path.openNextFile();
while (file) {
if (strcmp(file.name(), fileName) == 0) {
if (strcmp(directory, "/") == 0)
printf("File '%s%s' found in root directory.\r\n",directory,fileName);
else
printf("File '%s/%s' found in root directory.\r\n",directory,fileName);
Path.close();
return true;
}
file = Path.openNextFile();
}
if (strcmp(directory, "/") == 0)
printf("File '%s%s' not found in root directory.\r\n",directory,fileName);
else
printf("File '%s/%s' not found in root directory.\r\n",directory,fileName);
Path.close();
return false;
}
uint16_t Folder_retrieval(const char* directory, const char* fileExtension, char File_Name[][100],uint16_t maxFiles)
{
File Path = SD_MMC.open(directory);
if (!Path) {
printf("Path: <%s> does not exist\r\n",directory);
return false;
}
uint16_t fileCount = 0;
char filePath[100];
File file = Path.openNextFile();
while (file && fileCount < maxFiles) {
if (!file.isDirectory() && strstr(file.name(), fileExtension)) {
strncpy(File_Name[fileCount], file.name(), sizeof(File_Name[fileCount]));
if (strcmp(directory, "/") == 0) {
snprintf(filePath, 100, "%s%s", directory, file.name());
} else {
snprintf(filePath, 100, "%s/%s", directory, file.name());
}
printf("File found: %s\r\n", filePath);
fileCount++;
}
file = Path.openNextFile();
}
Path.close();
if (fileCount > 0) {
printf("Retrieved %d mp3 files\r\n",fileCount);
return fileCount;
} else {
printf("No files with extension '%s' found in directory: %s\r\n", fileExtension, directory);
return 0;
}
}
void Flash_test()
{
printf("/********** RAM Test**********/\r\n");
// Get Flash size
uint32_t flashSize = ESP.getFlashChipSize();
Flash_Size = flashSize/1024/1024;
printf("Flash size: %d MB \r\n", flashSize/1024/1024);
printf("/******* RAM Test Over********/\r\n\r\n");
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "Arduino.h"
#include <cstring>
#include "FS.h"
#include "SD_MMC.h"
#include "TCA9554PWR.h"
#define SD_CLK_PIN 2
#define SD_CMD_PIN 1
#define SD_D0_PIN 42
extern uint16_t SDCard_Size;
extern uint16_t Flash_Size;
void SD_Init();
void Flash_test();
bool File_Search(const char* directory, const char* fileName);
uint16_t Folder_retrieval(const char* directory, const char* fileExtension, char File_Name[][100],uint16_t maxFiles);
+96
View File
@@ -0,0 +1,96 @@
#include "TCA9554PWR.h"
/***************************************************** Operation register REG ****************************************************/
uint8_t I2C_Read_EXIO(uint8_t REG) // Read the value of the TCA9554PWR register REG
{
Wire.beginTransmission(TCA9554_ADDRESS);
Wire.write(REG);
uint8_t result = Wire.endTransmission();
if (result != 0) {
printf("The I2C transmission fails. - I2C Read EXIO\r\n");
}
Wire.requestFrom(TCA9554_ADDRESS, 1);
uint8_t bitsStatus;
if (Wire.available()) {
bitsStatus = Wire.read();
}
return bitsStatus;
}
uint8_t I2C_Write_EXIO(uint8_t REG,uint8_t Data) // Write Data to the REG register of the TCA9554PWR
{
Wire.beginTransmission(TCA9554_ADDRESS);
Wire.write(REG);
Wire.write(Data);
uint8_t result = Wire.endTransmission();
if (result != 0) {
printf("The I2C transmission fails. - I2C Write EXIO\r\n");
return -1;
}
return 0;
}
/********************************************************** Set EXIO mode **********************************************************/
void Mode_EXIO(uint8_t Pin,uint8_t State) // Set the mode of the TCA9554PWR Pin. The default is Output mode (output mode or input mode). State: 0= Output mode 1= input mode
{
uint8_t bitsStatus = I2C_Read_EXIO(TCA9554_CONFIG_REG);
uint8_t Data = (0x01 << (Pin-1)) | bitsStatus;
uint8_t result = I2C_Write_EXIO(TCA9554_CONFIG_REG,Data);
if (result != 0) {
printf("I/O Configuration Failure !!!\r\n");
}
}
void Mode_EXIOS(uint8_t PinState) // Set the mode of the 7 pins from the TCA9554PWR with PinState
{
uint8_t result = I2C_Write_EXIO(TCA9554_CONFIG_REG,PinState);
if (result != 0) {
printf("I/O Configuration Failure !!!\r\n");
}
}
/********************************************************** Read EXIO status **********************************************************/
uint8_t Read_EXIO(uint8_t Pin) // Read the level of the TCA9554PWR Pin
{
uint8_t inputBits = I2C_Read_EXIO(TCA9554_INPUT_REG);
uint8_t bitStatus = (inputBits >> (Pin-1)) & 0x01;
return bitStatus;
}
uint8_t Read_EXIOS(uint8_t REG = TCA9554_INPUT_REG) // Read the level of all pins of TCA9554PWR, the default read input level state, want to get the current IO output state, pass the parameter TCA9554_OUTPUT_REG, such as Read_EXIOS(TCA9554_OUTPUT_REG);
{
uint8_t inputBits = I2C_Read_EXIO(REG);
return inputBits;
}
/********************************************************** Set the EXIO output status **********************************************************/
void Set_EXIO(uint8_t Pin,uint8_t State) // Sets the level state of the Pin without affecting the other pins
{
uint8_t Data;
if(State < 2 && Pin < 9 && Pin > 0){
uint8_t bitsStatus = Read_EXIOS(TCA9554_OUTPUT_REG);
if(State == 1)
Data = (0x01 << (Pin-1)) | bitsStatus;
else if(State == 0)
Data = (~(0x01 << (Pin-1))) & bitsStatus;
uint8_t result = I2C_Write_EXIO(TCA9554_OUTPUT_REG,Data);
if (result != 0) {
printf("Failed to set GPIO!!!\r\n");
}
}
else
printf("Parameter error, please enter the correct parameter!\r\n");
}
void Set_EXIOS(uint8_t PinState) // Set 7 pins to the PinState state such as :PinState=0x23, 0010 0011 state (the highest bit is not used)
{
uint8_t result = I2C_Write_EXIO(TCA9554_OUTPUT_REG,PinState);
if (result != 0) {
printf("Failed to set GPIO!!!\r\n");
}
}
/********************************************************** Flip EXIO state **********************************************************/
void Set_Toggle(uint8_t Pin) // Flip the level of the TCA9554PWR Pin
{
uint8_t bitsStatus = Read_EXIO(Pin);
Set_EXIO(Pin,(bool)!bitsStatus);
}
/********************************************************* TCA9554PWR Initializes the device ***********************************************************/
void TCA9554PWR_Init(uint8_t PinState) // Set the seven pins to PinState state, for example :PinState=0x23, 0010 0011 State (Output mode or input mode) 0= Output mode 1= Input mode. The default value is output mode
{
Mode_EXIOS(PinState);
}
+50
View File
@@ -0,0 +1,50 @@
#pragma once
#include <stdio.h>
#include "I2C_Driver.h"
#define TCA9554_EXIO1 0x01
#define TCA9554_EXIO2 0x02
#define TCA9554_EXIO3 0x03
#define TCA9554_EXIO4 0x04
#define TCA9554_EXIO5 0x05
#define TCA9554_EXIO6 0x06
#define TCA9554_EXIO7 0x07
/****************************************************** The macro defines the TCA9554PWR information ******************************************************/
#define TCA9554_ADDRESS 0x20 // TCA9554PWR I2C address
// TCA9554PWR寄存器地址
#define TCA9554_INPUT_REG 0x00 // Input register,input level
#define TCA9554_OUTPUT_REG 0x01 // Output register, high and low level output
#define TCA9554_Polarity_REG 0x02 // The Polarity Inversion register (register 2) allows polarity inversion of pins defined as inputs by the Configuration register.
#define TCA9554_CONFIG_REG 0x03 // Configuration register, mode configuration
#define Low 0
#define High 1
#define EXIO_PIN1 1
#define EXIO_PIN2 2
#define EXIO_PIN3 3
#define EXIO_PIN4 4
#define EXIO_PIN5 5
#define EXIO_PIN6 6
#define EXIO_PIN7 7
#define EXIO_PIN8 8
/***************************************************** Operation register REG ****************************************************/
uint8_t I2C_Read_EXIO(uint8_t REG); // Read the value of the TCA9554PWR register REG
uint8_t I2C_Write_EXIO(uint8_t REG,uint8_t Data); // Write Data to the REG register of the TCA9554PWR
/********************************************************** Set EXIO mode **********************************************************/
void Mode_EXIO(uint8_t Pin,uint8_t State); // Set the mode of the TCA9554PWR Pin. The default is Output mode (output mode or input mode). State: 0= Output mode 1= input mode
void Mode_EXIOS(uint8_t PinState); // Set the mode of the 7 pins from the TCA9554PWR with PinState
/********************************************************** Read EXIO status **********************************************************/
uint8_t Read_EXIO(uint8_t Pin); // Read the level of the TCA9554PWR Pin
uint8_t Read_EXIOS(uint8_t REG); // Read the level of all pins of TCA9554PWR, the default read input level state, want to get the current IO output state, pass the parameter TCA9554_OUTPUT_REG, such as Read_EXIOS(TCA9554_OUTPUT_REG);
/********************************************************** Set the EXIO output status **********************************************************/
void Set_EXIO(uint8_t Pin,uint8_t State); // Sets the level state of the Pin without affecting the other pins
void Set_EXIOS(uint8_t PinState); // Set 7 pins to the PinState state such as :PinState=0x23, 0010 0011 state (the highest bit is not used)
/********************************************************** Flip EXIO state **********************************************************/
void Set_Toggle(uint8_t Pin); // Flip the level of the TCA9554PWR Pin
/********************************************************* TCA9554PWR Initializes the device ***********************************************************/
void TCA9554PWR_Init(uint8_t PinState = 0x00); // Set the seven pins to PinState state, for example :PinState=0x23, 0010 0011 State (the highest bit is not used) (Output mode or input mode) 0= Output mode 1= Input mode. The default value is output mode
+157
View File
@@ -0,0 +1,157 @@
#include "Touch_CST820.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// I2C读写
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool I2C_Read_Touch(uint8_t Driver_addr, uint8_t Reg_addr, uint8_t *Reg_data, uint32_t Length)
{
Wire.beginTransmission(Driver_addr);
Wire.write(Reg_addr);
if ( Wire.endTransmission(true)){
printf("The I2C transmission fails. - I2C Read\r\n");
return -1;
}
Wire.requestFrom(Driver_addr, Length);
for (int i = 0; i < Length; i++) {
*Reg_data++ = Wire.read();
}
return 0;
}
bool I2C_Write_Touch(uint8_t Driver_addr, uint8_t Reg_addr, const uint8_t *Reg_data, uint32_t Length)
{
Wire.beginTransmission(Driver_addr);
Wire.write(Reg_addr);
for (int i = 0; i < Length; i++) {
Wire.write(*Reg_data++);
}
if ( Wire.endTransmission(true))
{
printf("The I2C transmission fails. - I2C Write\r\n");
return -1;
}
return 0;
}
struct CST820_Touch touch_data = {0};
uint8_t Touch_Init(void) {
pinMode(CST820_INT_PIN, INPUT_PULLUP);
CST820_Touch_Reset();
CST820_AutoSleep(false);
uint16_t Verification = CST820_Read_cfg();
// attachInterrupt(CST820_INT_PIN, Touch_CST820_ISR, interrupt);
return true;
}
/* Reset controller */
uint8_t CST820_Touch_Reset(void)
{
Set_EXIO(EXIO_PIN2,Low);
vTaskDelay(pdMS_TO_TICKS(10));
Set_EXIO(EXIO_PIN2,High);
vTaskDelay(pdMS_TO_TICKS(50));
return true;
}
uint16_t CST820_Read_cfg(void) {
uint8_t buf[3]={0};
I2C_Read_Touch(CST820_ADDR, CST820_REG_Version,buf, 1);
printf("TouchPad_Version:0x%02x\r\n", buf[0]);
I2C_Read_Touch(CST820_ADDR, CST820_REG_ChipID, buf, 3);
printf("ChipID:0x%02x ProjID:0x%02x FwVersion:0x%02x \r\n",buf[0], buf[1], buf[2]);
return true;
}
/*!
@brief Fall asleep automatically
*/
void CST820_AutoSleep(bool Sleep_State) {
CST820_Touch_Reset();
uint8_t Sleep_State_Set = 0;
if(Sleep_State)
Sleep_State_Set = 0;
else
Sleep_State_Set = 0xFF;
I2C_Write_Touch(CST820_ADDR, CST820_REG_DisAutoSleep, &Sleep_State_Set, 1);
}
// reads sensor and touches
// updates Touch Points
uint8_t Touch_Read_Data(void) {
uint8_t buf[6];
uint8_t touchpad_cnt = 0;
I2C_Read_Touch(CST820_ADDR, CST820_REG_GestureID, buf, 6);
/* touched gesture */
if (buf[0] != 0x00)
touch_data.gesture = (GESTURE)buf[0];
if (buf[1] != 0x00) {
noInterrupts();
/* Number of touched points */
touch_data.points = (uint8_t)buf[1];
if(touch_data.points > CST820_LCD_TOUCH_MAX_POINTS)
touch_data.points = CST820_LCD_TOUCH_MAX_POINTS;
/* Fill coordinates */
touch_data.x = ((buf[2] & 0x0F) << 8) + buf[3];
touch_data.y = ((buf[4] & 0x0F) << 8) + buf[5];
interrupts();
// printf(" points=%d \r\n",touch_data.points);
}
return true;
}
void example_touchpad_read(void){
Touch_Read_Data();
if (touch_data.gesture != NONE || touch_data.points != 0x00) {
// printf("Touch : X=%u Y=%u points=%d\r\n", touch_data.x , touch_data.y,touch_data.points);
} else {
// data->state = LV_INDEV_STATE_REL;
}
}
void Touch_Loop(void){
if(Touch_interrupts){
Touch_interrupts = false;
example_touchpad_read();
}
}
/*!
@brief handle interrupts
*/
uint8_t Touch_interrupts;
void IRAM_ATTR Touch_CST820_ISR(void) {
Touch_interrupts = true;
}
/*!
@brief get the gesture event name
*/
String Touch_GestureName(void) {
switch (touch_data.gesture) {
case NONE:
return "NONE";
break;
case SWIPE_DOWN:
return "SWIPE DOWN";
break;
case SWIPE_UP:
return "SWIPE UP";
break;
case SWIPE_LEFT:
return "SWIPE LEFT";
break;
case SWIPE_RIGHT:
return "SWIPE RIGHT";
break;
case SINGLE_CLICK:
return "SINGLE CLICK";
break;
case DOUBLE_CLICK:
return "DOUBLE CLICK";
break;
case LONG_PRESS:
return "LONG PRESS";
break;
default:
return "UNKNOWN";
break;
}
}
+64
View File
@@ -0,0 +1,64 @@
#pragma once
#include "Arduino.h"
#include "I2C_Driver.h"
#include "TCA9554PWR.h"
#define CST820_ADDR 0x15
#define CST820_INT_PIN 16
#define CST820_LCD_TOUCH_MAX_POINTS (1)
/* CST820 GESTURE */
enum GESTURE {
NONE = 0x00,
SWIPE_UP = 0x01,
SWIPE_DOWN = 0x02,
SWIPE_LEFT = 0x03,
SWIPE_RIGHT = 0x04,
SINGLE_CLICK = 0x05,
DOUBLE_CLICK = 0x0B,
LONG_PRESS = 0x0C
};
//debug info
/****************HYN_REG_MUT_DEBUG_INFO_MODE address start***********/
#define CST820_REG_Mode 0x00
#define CST820_REG_GestureID 0x01
#define CST820_REG_Version 0x15
#define CST820_REG_ChipID 0xA7
#define CST820_REG_ProjID 0xA8
#define CST820_REG_FwVersion 0xA9
#define CST820_REG_AutoSleepTime 0xF9
#define CST820_REG_DisAutoSleep 0xFE
//Interrupt Modes
#define RISING 0x01
#define FALLING 0x02
#define CHANGE 0x03
#define ONLOW 0x04
#define ONHIGH 0x05
#define ONLOW_WE 0x0C
#define ONHIGH_WE 0x0D
#define interrupt RISING
extern uint8_t Touch_interrupts;
extern struct CST820_Touch touch_data;
struct CST820_Touch{
uint8_t points; // Number of touch points
GESTURE gesture; /*!< uint8_t */
uint16_t x; /*!< X coordinate */
uint16_t y; /*!< Y coordinate */
};
uint8_t Touch_Init();
uint8_t CST820_Touch_Reset(void);
void CST820_AutoSleep(bool Sleep_State);
uint16_t CST820_Read_cfg(void);
String Touch_GestureName(void);
uint8_t Touch_Read_Data(void);
void example_touchpad_read(void);
void IRAM_ATTR Touch_CST820_ISR(void);
+199
View File
@@ -0,0 +1,199 @@
#include "Wireless.h"
bool WIFI_Connection = 0;
uint8_t WIFI_NUM = 0;
uint8_t BLE_NUM = 0;
bool Scan_finish = 0;
uint8_t NUM=0;
uint8_t wifi_scan()
{
printf("/**********WiFi Test**********/\r\n");
// Set WiFi to station mode and disconnect from an AP if it was previously connected.
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// WiFi.scanNetworks will return the number of networks found.
int n = WiFi.scanNetworks();
// Serial.println("Scan done");
if (n == 0)
{
printf("no networks found\r\n");
}
else
{
printf("Nr | SSID | RSSI | CH | Encryption\r\n");
for (int i = 0; i < 3; ++i)
{
// Print SSID and RSSI for each network found
printf("%2d | ", i + 1);
printf("%-32.32s | ", WiFi.SSID(i).c_str());
printf("%4d | ", WiFi.RSSI(i));
printf("%2d | ", WiFi.channel(i));
switch (WiFi.encryptionType(i))
{
case WIFI_AUTH_OPEN:
printf("open\r\n");
break;
case WIFI_AUTH_WEP:
printf("WEP\r\n");
break;
case WIFI_AUTH_WPA_PSK:
printf("WPA\r\n");
break;
case WIFI_AUTH_WPA2_PSK:
printf("WPA2\r\n");
break;
case WIFI_AUTH_WPA_WPA2_PSK:
printf("WPA+WPA2\r\n");
break;
case WIFI_AUTH_WPA2_ENTERPRISE:
printf("WPA2-EAP\r\n");
break;
case WIFI_AUTH_WPA3_PSK:
printf("WPA3\r\n");
break;
case WIFI_AUTH_WPA2_WPA3_PSK:
printf("WPA2+WPA3\r\n");
break;
case WIFI_AUTH_WAPI_PSK:
printf("WAPI\r\n");
break;
default:
printf("unknown\r\n");
}
vTaskDelay(10);
}
}
// Delete the scan result to free memory for code below.
WiFi.scanDelete();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
vTaskDelay(100);
printf("/*******WiFi Test Over********/\r\n\r\n");
printf("/**********BLE Test**********/\r\n");
}
BLEScan* pBLEScan;
uint8_t ble_scan()
{
if(NUM == 0){
BLEDevice::init("");
pBLEScan = BLEDevice::getScan();
pBLEScan->setActiveScan(true);
}
BLEScanResults* foundDevices = pBLEScan->start(5);
int count = foundDevices->getCount();
printf("Found %d devices\r\n",count);
for (int i = 0; i < count; i++) {
BLEAdvertisedDevice device = foundDevices->getDevice(i);
if (device.haveName()) {
printf("Bluetooth Name : %s\r\n",device.getName().c_str());
printf("Device address : %s\r\n",device.getAddress().toString().c_str());
printf("Response Length : %d\r\n",device.getPayloadLength());
printf("\r\n");
NUM++;
}
if(NUM == 2)
{
break;
}
}
if(NUM == 2)
{
pBLEScan->stop();
pBLEScan->clearResults();
BLEDevice::deinit(true);
printf("/**********BLE Test Over**********/\r\n\r\n");
}
return NUM;
}
void Wireless_Test1(){
uint8_t Time=0;
pinMode(0, INPUT);
while(digitalRead(0) != 0)
{
vTaskDelay(10);
Time++;
if(Time == 100)
{
printf("Please press the BOOT button \r\n");
Time=0;
}
}
wifi_scan();
uint8_t ble_NUM = ble_scan();
while(ble_NUM != 2)
ble_NUM = ble_scan();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int wifi_scan_number()
{
printf("/**********WiFi Test**********/\r\n");
// Set WiFi to station mode and disconnect from an AP if it was previously connected.
WiFi.mode(WIFI_STA);
WiFi.setSleep(true);
// WiFi.scanNetworks will return the number of networks found.
int count = WiFi.scanNetworks();
if (count == 0)
{
printf("No WIFI device was scanned\r\n");
}
else{
printf("Scanned %d Wi-Fi devices\r\n",count);
}
// Delete the scan result to free memory for code below.
WiFi.scanDelete();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
vTaskDelay(100);
printf("/*******WiFi Test Over********/\r\n\r\n");
return count;
}
int ble_scan_number()
{
printf("/**********BLE Test**********/\r\n");
BLEDevice::init("");
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setActiveScan(true);
BLEScanResults* foundDevices = pBLEScan->start(5);
vTaskDelay(5000);
int count = foundDevices->getCount();
if (count == 0)
{
printf("No Bluetooth device was scanned\r\n");
}
else{
printf("Scanned %d Bluetooth devices\r\n",count);
}
pBLEScan->clearResults();
pBLEScan->stop();
BLEDevice::deinit(true);
vTaskDelay(100);
printf("/**********BLE Test Over**********/\r\n\r\n");
return count;
}
void WirelessScanTask(void *parameter) {
WIFI_NUM = wifi_scan_number();
BLE_NUM = ble_scan_number();
Scan_finish = 1;
vTaskDelete(NULL);
}
void Wireless_Test2(){
xTaskCreatePinnedToCore(
WirelessScanTask,
"WirelessScanTask",
4096,
NULL,
1,
NULL,
0
);
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "WiFi.h"
#include <BLEDevice.h>
extern bool WIFI_Connection;
extern uint8_t WIFI_NUM;
extern uint8_t BLE_NUM;
extern bool Scan_finish;
uint8_t wifi_scan();
uint8_t ble_scan();
void Wireless_Test1();
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int wifi_scan_number();
int ble_scan_number();
void Wireless_Test2();
+67
View File
@@ -0,0 +1,67 @@
#include "I2C_Driver.h"
#include "TCA9554PWR.h"
#include "Display_ST7701.h"
#include "LVGL_Driver.h"
#include "EyeScene.h"
#include "OtaService.h"
#include "../shared/GazeProtocol.h"
#ifndef EYE_BOARD_NUMBER
#define EYE_BOARD_NUMBER 1
#endif
namespace {
constexpr int kGazeRxPin = 44;
constexpr int kGazeBaud = 115200;
HardwareSerial gaze_serial(1);
gaze::Receiver gaze_receiver;
bool gaze_active = false;
uint32_t last_status_ms = 0;
}
void setup() {
I2C_Init();
TCA9554PWR_Init(0x00);
Set_EXIO(EXIO_PIN8, Low);
LCD_Init();
Lvgl_Init();
EyeScene_Create();
Serial.begin(115200);
gaze_serial.begin(kGazeBaud, SERIAL_8N1, kGazeRxPin, -1);
OtaService_Begin();
}
void loop() {
if (millis() - last_status_ms >= 5000) {
last_status_ms = millis();
if (Serial) Serial.printf("GAZE_READY board=%d recent=%d bad_format=%lu bad_sequence=%lu\n",
EYE_BOARD_NUMBER, gaze_receiver.recent(millis()),
static_cast<unsigned long>(gaze_receiver.rejected_format()),
static_cast<unsigned long>(gaze_receiver.rejected_sequence()));
}
gaze::Frame command = {};
while (gaze_serial.available()) {
const uint32_t old_format_rejections = gaze_receiver.rejected_format();
const uint32_t old_sequence_rejections = gaze_receiver.rejected_sequence();
if (gaze_receiver.feed(static_cast<uint8_t>(gaze_serial.read()),
millis(), &command)) {
EyeScene_SetGaze(command.x, command.y, command.valid);
gaze_active = command.valid;
if (Serial) Serial.printf("GAZE_ACCEPT board=%d seq=%u x=%u y=%u valid=%d\n",
EYE_BOARD_NUMBER, command.sequence, command.x,
command.y, command.valid);
}
if (gaze_receiver.rejected_format() != old_format_rejections)
if (Serial) Serial.printf("GAZE_REJECT board=%d reason=format\n", EYE_BOARD_NUMBER);
if (gaze_receiver.rejected_sequence() != old_sequence_rejections)
if (Serial) Serial.printf("GAZE_REJECT board=%d reason=sequence\n", EYE_BOARD_NUMBER);
}
if (gaze_active && !gaze_receiver.recent(millis())) {
EyeScene_SetGaze(500, 500, false);
gaze_active = false;
if (Serial) Serial.printf("GAZE_TIMEOUT board=%d\n", EYE_BOARD_NUMBER);
}
Lvgl_Loop();
OtaService_Loop();
vTaskDelay(pdMS_TO_TICKS(5));
}