updates
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
extern const lv_img_dsc_t kFreddyIris;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void OtaService_Begin();
|
||||
void OtaService_Loop();
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
@@ -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();
|
||||
@@ -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));
|
||||
}
|
||||
Reference in New Issue
Block a user