add sd card driver
This commit is contained in:
parent
eed5455c8c
commit
6f3345f626
91
main/drivers/sd.hpp
Normal file
91
main/drivers/sd.hpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Adapted from the sd_mmc example (Public Domain)
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
|
||||
static const char *SD_TAG = "sd_driver";
|
||||
|
||||
#define MOUNT_POINT "/sdcard"
|
||||
|
||||
const char mount_point[] = MOUNT_POINT;
|
||||
sdmmc_card_t *card;
|
||||
|
||||
#define SD_PIN_CLK GPIO_NUM_48
|
||||
#define SD_PIN_CMD GPIO_NUM_45
|
||||
#define SD_PIN_D0 GPIO_NUM_47
|
||||
#define SD_PIN_D1 GPIO_NUM_21
|
||||
#define SD_PIN_D2 GPIO_NUM_39
|
||||
#define SD_PIN_D3 GPIO_NUM_38
|
||||
|
||||
void init_sd() {
|
||||
esp_err_t ret;
|
||||
|
||||
// Options for mounting the filesystem.
|
||||
// If format_if_mount_failed is set to true, SD card will be partitioned and
|
||||
// formatted in case when mounting fails.
|
||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = true,
|
||||
.max_files = 5,
|
||||
.allocation_unit_size = 16 * 1024
|
||||
};
|
||||
|
||||
ESP_LOGI(SD_TAG, "Initializing SD card");
|
||||
|
||||
// Use settings defined above to initialize SD card and mount FAT filesystem.
|
||||
// Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
|
||||
// Please check its source code and implement error recovery when developing
|
||||
// production applications.
|
||||
|
||||
ESP_LOGI(SD_TAG, "Using SDMMC peripheral");
|
||||
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
|
||||
|
||||
// This initializes the slot without card detect (CD) and write protect (WP) signals.
|
||||
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
|
||||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
||||
|
||||
// Set bus width to use:
|
||||
slot_config.width = 4;
|
||||
|
||||
// On chips where the GPIOs used for SD card can be configured, set them in
|
||||
// the slot_config structure:
|
||||
slot_config.clk = SD_PIN_CLK;
|
||||
slot_config.cmd = SD_PIN_CMD;
|
||||
slot_config.d0 = SD_PIN_D0;
|
||||
slot_config.d1 = SD_PIN_D1;
|
||||
slot_config.d2 = SD_PIN_D2;
|
||||
slot_config.d3 = SD_PIN_D3;
|
||||
|
||||
// Enable internal pullups on enabled pins. The internal pullups
|
||||
// are insufficient however, please make sure 10k external pullups are
|
||||
// connected on the bus. This is for debug / example purpose only.
|
||||
slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
|
||||
|
||||
ESP_LOGI(SD_TAG, "Mounting filesystem");
|
||||
ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
if (ret == ESP_FAIL) {
|
||||
ESP_LOGE(SD_TAG, "Failed to mount filesystem. "
|
||||
"If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
|
||||
} else {
|
||||
ESP_LOGE(SD_TAG, "Failed to initialize the card (%s). "
|
||||
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
|
||||
}
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(SD_TAG, "Filesystem mounted");
|
||||
|
||||
// Card has been initialized, print its properties
|
||||
sdmmc_card_print_info(stdout, card);
|
||||
}
|
||||
|
||||
void deinit_sd() {
|
||||
esp_vfs_fat_sdcard_unmount(mount_point, card);
|
||||
ESP_LOGI(SD_TAG, "Card unmounted");
|
||||
}
|
||||
@ -1,7 +1,13 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 atanisoft (github.com/atanisoft)
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* Adapted from an example under the MIT license:
|
||||
* Copyright © 2022 atanisoft (github.com/atanisoft)
|
||||
*
|
||||
* MIT LICENSE:
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <driver/gpio.h>
|
||||
@ -25,7 +31,7 @@
|
||||
// data.
|
||||
// #define USE_DOUBLE_BUFFERING 1
|
||||
|
||||
static const char *TAG = "lcd_driver";
|
||||
static const char *TFT_TAG = "tft_driver";
|
||||
|
||||
#define DISPLAY_HORIZONTAL_PIXELS 320
|
||||
#define DISPLAY_VERTICAL_PIXELS 480
|
||||
@ -70,16 +76,17 @@ static void update_meter_value(void *indic, int32_t v)
|
||||
lv_meter_set_indicator_end_value(meter, (lv_meter_indicator_t*)indic, v);
|
||||
}
|
||||
|
||||
static bool notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io,
|
||||
esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
static bool notify_lvgl_flush_ready(
|
||||
esp_lcd_panel_io_handle_t panel_io,
|
||||
esp_lcd_panel_io_event_data_t *edata,
|
||||
void *user_ctx
|
||||
) {
|
||||
lv_disp_drv_t *disp_driver = (lv_disp_drv_t *)user_ctx;
|
||||
lv_disp_flush_ready(disp_driver);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
|
||||
{
|
||||
static void lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map) {
|
||||
esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
|
||||
|
||||
int offsetx1 = area->x1;
|
||||
@ -89,17 +96,15 @@ static void lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t
|
||||
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR lvgl_tick_cb(void *param)
|
||||
{
|
||||
static void IRAM_ATTR lvgl_tick_cb(void *param) {
|
||||
lv_tick_inc(LVGL_UPDATE_PERIOD_MS);
|
||||
}
|
||||
|
||||
void initialize_spi()
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing SPI bus (MOSI:%d, MISO:%d, CLK:%d)",
|
||||
void initialize_spi() {
|
||||
ESP_LOGI(TFT_TAG, "Initializing SPI bus (MOSI:%d, MISO:%d, CLK:%d)",
|
||||
TFT_PIN_MOSI, TFT_PIN_MISO, TFT_PIN_CLK);
|
||||
spi_bus_config_t bus =
|
||||
{
|
||||
|
||||
spi_bus_config_t bus = {
|
||||
.mosi_io_num = TFT_PIN_MOSI,
|
||||
.miso_io_num = TFT_PIN_MISO,
|
||||
.sclk_io_num = TFT_PIN_CLK,
|
||||
@ -118,10 +123,8 @@ void initialize_spi()
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &bus, SPI_DMA_CH_AUTO));
|
||||
}
|
||||
|
||||
void initialize_display()
|
||||
{
|
||||
const esp_lcd_panel_io_spi_config_t io_config =
|
||||
{
|
||||
void initialize_display() {
|
||||
const esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.cs_gpio_num = TFT_PIN_CS,
|
||||
.dc_gpio_num = TFT_PIN_DC,
|
||||
.spi_mode = 0,
|
||||
@ -131,21 +134,19 @@ void initialize_display()
|
||||
.user_ctx = &lv_disp_drv,
|
||||
.lcd_cmd_bits = DISPLAY_COMMAND_BITS,
|
||||
.lcd_param_bits = DISPLAY_PARAMETER_BITS,
|
||||
.flags =
|
||||
{
|
||||
.flags = {
|
||||
.dc_as_cmd_phase = 0,
|
||||
.dc_low_on_data = 0,
|
||||
.octal_mode = 0,
|
||||
.lsb_first = 0
|
||||
}
|
||||
};
|
||||
|
||||
const esp_lcd_panel_dev_config_t lcd_config =
|
||||
{
|
||||
const esp_lcd_panel_dev_config_t lcd_config = {
|
||||
.reset_gpio_num = TFT_PIN_RESET,
|
||||
.color_space = ESP_LCD_COLOR_SPACE_BGR,
|
||||
.bits_per_pixel = 18,
|
||||
.flags =
|
||||
{
|
||||
.flags = {
|
||||
.reset_active_high = 0
|
||||
},
|
||||
.vendor_config = NULL
|
||||
@ -169,20 +170,19 @@ void initialize_display()
|
||||
#endif
|
||||
}
|
||||
|
||||
void initialize_lvgl()
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing LVGL");
|
||||
void initialize_lvgl() {
|
||||
ESP_LOGI(TFT_TAG, "Initializing LVGL");
|
||||
lv_init();
|
||||
ESP_LOGI(TAG, "Allocating %zu bytes for LVGL buffer", LV_BUFFER_SIZE * sizeof(lv_color_t));
|
||||
ESP_LOGI(TFT_TAG, "Allocating %zu bytes for LVGL buffer", LV_BUFFER_SIZE * sizeof(lv_color_t));
|
||||
lv_buf_1 = (lv_color_t *)heap_caps_malloc(LV_BUFFER_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
#if USE_DOUBLE_BUFFERING
|
||||
ESP_LOGI(TAG, "Allocating %zu bytes for second LVGL buffer", LV_BUFFER_SIZE * sizeof(lv_color_t));
|
||||
ESP_LOGI(TFT_TAG, "Allocating %zu bytes for second LVGL buffer", LV_BUFFER_SIZE * sizeof(lv_color_t));
|
||||
lv_buf_2 = (lv_color_t *)heap_caps_malloc(LV_BUFFER_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Creating LVLG display buffer");
|
||||
ESP_LOGI(TFT_TAG, "Creating LVLG display buffer");
|
||||
lv_disp_draw_buf_init(&lv_disp_buf, lv_buf_1, lv_buf_2, LV_BUFFER_SIZE);
|
||||
|
||||
ESP_LOGI(TAG, "Initializing %dx%d display", DISPLAY_HORIZONTAL_PIXELS, DISPLAY_VERTICAL_PIXELS);
|
||||
ESP_LOGI(TFT_TAG, "Initializing %dx%d display", DISPLAY_HORIZONTAL_PIXELS, DISPLAY_VERTICAL_PIXELS);
|
||||
lv_disp_drv_init(&lv_disp_drv);
|
||||
lv_disp_drv.hor_res = DISPLAY_HORIZONTAL_PIXELS;
|
||||
lv_disp_drv.ver_res = DISPLAY_VERTICAL_PIXELS;
|
||||
@ -191,19 +191,20 @@ void initialize_lvgl()
|
||||
lv_disp_drv.user_data = lcd_handle;
|
||||
lv_display = lv_disp_drv_register(&lv_disp_drv);
|
||||
|
||||
ESP_LOGI(TAG, "Creating LVGL tick timer");
|
||||
const esp_timer_create_args_t lvgl_tick_timer_args =
|
||||
{
|
||||
ESP_LOGI(TFT_TAG, "Creating LVGL tick timer");
|
||||
const esp_timer_create_args_t lvgl_tick_timer_args = {
|
||||
.callback = &lvgl_tick_cb,
|
||||
.name = "lvgl_tick"
|
||||
.arg = NULL,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "lvgl_tick",
|
||||
.skip_unhandled_events = false
|
||||
};
|
||||
esp_timer_handle_t lvgl_tick_timer = NULL;
|
||||
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, LVGL_UPDATE_PERIOD_MS * 1000));
|
||||
}
|
||||
|
||||
void create_demo_ui()
|
||||
{
|
||||
void create_demo_ui() {
|
||||
lv_obj_t *scr = lv_disp_get_scr_act(NULL);
|
||||
|
||||
// Set the background color of the display to black.
|
||||
@ -265,5 +266,5 @@ void init_tft() {
|
||||
initialize_display();
|
||||
initialize_lvgl();
|
||||
|
||||
ESP_LOGI(TAG, "TFT initialization Successful");
|
||||
ESP_LOGI(TFT_TAG, "TFT initialization Successful");
|
||||
}
|
||||
@ -1,11 +1,3 @@
|
||||
/* Hello World Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@ -13,11 +5,15 @@
|
||||
#include "esp_system.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "drivers/tft.hpp"
|
||||
#include "drivers/sd.hpp"
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
printf("app_main\n");
|
||||
|
||||
init_sd();
|
||||
deinit_sd();
|
||||
|
||||
init_tft();
|
||||
create_demo_ui();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user