From ff30b27f0d042972b4777c43dbdfccb7641be0f2 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 9 Nov 2022 13:33:50 +1100 Subject: [PATCH] First test cases :) --- src/drivers/CMakeLists.txt | 2 +- src/drivers/display.cpp | 5 +- src/drivers/i2c.cpp | 37 +++++++++++++++ src/drivers/include/i2c.hpp | 3 ++ src/drivers/include/spi.hpp | 10 ++++ src/drivers/spi.cpp | 48 +++++++++++++++++++ src/drivers/test/CMakeLists.txt | 2 +- src/drivers/test/test_example.cpp | 9 ---- src/drivers/test/test_storage.cpp | 74 ++++++++++++++++++++++++++++++ src/main/main.cpp | 76 +++---------------------------- 10 files changed, 183 insertions(+), 83 deletions(-) create mode 100644 src/drivers/include/spi.hpp create mode 100644 src/drivers/spi.cpp delete mode 100644 src/drivers/test/test_example.cpp create mode 100644 src/drivers/test/test_storage.cpp diff --git a/src/drivers/CMakeLists.txt b/src/drivers/CMakeLists.txt index f57fbc2e..3b3c4a65 100644 --- a/src/drivers/CMakeLists.txt +++ b/src/drivers/CMakeLists.txt @@ -1,6 +1,6 @@ idf_component_register( SRCS "dac.cpp" "gpio-expander.cpp" "battery.cpp" "storage.cpp" "i2c.cpp" - "playback.cpp" "display.cpp" "display-init.cpp" + "playback.cpp" "display.cpp" "display-init.cpp" "spi.cpp" INCLUDE_DIRS "include" REQUIRES "esp_adc_cal" "fatfs" "audio_pipeline" "audio_stream" "result" "lvgl") target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) diff --git a/src/drivers/display.cpp b/src/drivers/display.cpp index 68bf41f5..dd9005cb 100644 --- a/src/drivers/display.cpp +++ b/src/drivers/display.cpp @@ -222,9 +222,8 @@ void Display::SendTransaction(TransactionType type, ServiceTransactions(); gpio_set_level(kCommandOrDataPin, type); - gpio_->with([&](auto& gpio) { - gpio.set_pin(GpioExpander::DISPLAY_CHIP_SELECT, 0); - }); + gpio_->with( + [&](auto& gpio) { gpio.set_pin(GpioExpander::DISPLAY_CHIP_SELECT, 0); }); { // auto lock = gpio_->AcquireSpiBus(GpioExpander::DISPLAY); ESP_ERROR_CHECK(spi_device_polling_transmit(handle_, transaction)); diff --git a/src/drivers/i2c.cpp b/src/drivers/i2c.cpp index d3378df6..0c195a25 100644 --- a/src/drivers/i2c.cpp +++ b/src/drivers/i2c.cpp @@ -3,11 +3,48 @@ #include "assert.h" #include "driver/i2c.h" +#include "esp_err.h" namespace drivers { +static const i2c_port_t kI2CPort = I2C_NUM_0; +static const gpio_num_t kI2CSdaPin = GPIO_NUM_2; +static const gpio_num_t kI2CSclPin = GPIO_NUM_4; +static const uint32_t kI2CClkSpeed = 400'000; + static constexpr int kCmdLinkSize = I2C_LINK_RECOMMENDED_SIZE(12); +esp_err_t init_i2c(void) { + i2c_config_t config = { + .mode = I2C_MODE_MASTER, + .sda_io_num = kI2CSdaPin, + .scl_io_num = kI2CSclPin, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master = + { + .clk_speed = kI2CClkSpeed, + }, + // No requirements for the clock. + .clk_flags = 0, + }; + + if (esp_err_t err = i2c_param_config(kI2CPort, &config)) { + return err; + } + if (esp_err_t err = i2c_driver_install(kI2CPort, config.mode, 0, 0, 0)) { + return err; + } + + // TODO: INT line + + return ESP_OK; +} + +esp_err_t deinit_i2c(void) { + return i2c_driver_delete(kI2CPort); +} + I2CTransaction::I2CTransaction() { // Use a fixed size buffer to avoid many many tiny allocations. buffer_ = (uint8_t*)calloc(sizeof(uint8_t), kCmdLinkSize); diff --git a/src/drivers/include/i2c.hpp b/src/drivers/include/i2c.hpp index a4c71767..3704509d 100644 --- a/src/drivers/include/i2c.hpp +++ b/src/drivers/include/i2c.hpp @@ -7,6 +7,9 @@ namespace drivers { +esp_err_t init_i2c(void); +esp_err_t deinit_i2c(void); + /* * Convenience wrapper for performing an I2C transaction with a reasonable * preconfigured timeout, automatic management of a heap-based command buffer, diff --git a/src/drivers/include/spi.hpp b/src/drivers/include/spi.hpp new file mode 100644 index 00000000..e58656a2 --- /dev/null +++ b/src/drivers/include/spi.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "esp_err.h" + +namespace drivers { + +esp_err_t init_spi(void); +esp_err_t deinit_spi(void); + +} // namespace drivers diff --git a/src/drivers/spi.cpp b/src/drivers/spi.cpp new file mode 100644 index 00000000..66c78e8a --- /dev/null +++ b/src/drivers/spi.cpp @@ -0,0 +1,48 @@ +#include "spi.hpp" + +#include "driver/sdspi_host.h" +#include "driver/spi_common.h" +#include "driver/spi_master.h" +#include "esp_err.h" +#include "hal/spi_types.h" + +namespace drivers { + +static const spi_host_device_t kSpiHost = VSPI_HOST; +static const gpio_num_t kSpiSdoPin = GPIO_NUM_23; +static const gpio_num_t kSpiSdiPin = GPIO_NUM_19; +static const gpio_num_t kSpiSclkPin = GPIO_NUM_18; + +esp_err_t init_spi(void) { + spi_bus_config_t config = { + .mosi_io_num = kSpiSdoPin, + .miso_io_num = kSpiSdiPin, + .sclk_io_num = kSpiSclkPin, + .quadwp_io_num = -1, // SPI_QUADWP_IO, + .quadhd_io_num = -1, // SPI_QUADHD_IO, + + // Unused + .data4_io_num = -1, + .data5_io_num = -1, + .data6_io_num = -1, + .data7_io_num = -1, + + // Use the DMA default size. The display requires larger buffers, but it + // manages its down use of DMA-capable memory. + .max_transfer_sz = 128 * 16 * 2, // TODO: hmm + .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_IOMUX_PINS, + .intr_flags = 0, + }; + + if (esp_err_t err = spi_bus_initialize(kSpiHost, &config, SPI_DMA_CH_AUTO)) { + return err; + } + + return ESP_OK; +} + +esp_err_t deinit_spi(void) { + return spi_bus_free(kSpiHost); +} + +} // namespace drivers diff --git a/src/drivers/test/CMakeLists.txt b/src/drivers/test/CMakeLists.txt index f6690c4d..83904339 100644 --- a/src/drivers/test/CMakeLists.txt +++ b/src/drivers/test/CMakeLists.txt @@ -1 +1 @@ -idf_component_register(SRC_DIRS "." INCLUDE_DIRS "." REQUIRES catch2 cmock drivers) +idf_component_register(SRCS "test_storage.cpp" INCLUDE_DIRS "." REQUIRES catch2 cmock drivers) diff --git a/src/drivers/test/test_example.cpp b/src/drivers/test/test_example.cpp deleted file mode 100644 index ef90cf8f..00000000 --- a/src/drivers/test/test_example.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "catch2/catch.hpp" - -TEST_CASE("Example test case", "[cooltag]") { - REQUIRE ( 1 == 1 ); -} - -TEST_CASE("test that doesn't run", "[cooltag][!mayfail]") { - REQUIRE ( 0 == 1 ); -} diff --git a/src/drivers/test/test_storage.cpp b/src/drivers/test/test_storage.cpp new file mode 100644 index 00000000..178ec815 --- /dev/null +++ b/src/drivers/test/test_storage.cpp @@ -0,0 +1,74 @@ +#include +#include +#include +#include + +#include "gpio-expander.hpp" +#include "storage.hpp" +#include "i2c.hpp" +#include "spi.hpp" + +#include "catch2/catch.hpp" + +namespace drivers { + +static const std::string kTestFilename = "test"; +static const std::string kTestFilePath = + std::string(kStoragePath) + "/" + kTestFilename; + +TEST_CASE("sd card storage", "[integration]") { + REQUIRE( drivers::init_i2c() == ESP_OK ); + REQUIRE( drivers::init_spi() == ESP_OK ); + GpioExpander expander; + + { + std::unique_ptr result = SdStorage::create(&expander).value(); + + SECTION("write to a file") { + + { + std::ofstream test_file; + test_file.open(kTestFilePath.c_str()); + test_file << "hello here is some test"; + test_file.close(); + } + + SECTION("read from a file") { + std::ifstream test_file; + test_file.open(kTestFilePath.c_str()); + + std::string line; + REQUIRE(std::getline(test_file, line)); + REQUIRE(line == "hello here is some test"); + + test_file.close(); + } + + SECTION("list files") { + DIR* dir; + struct dirent* ent; + + dir = opendir(kStoragePath); + REQUIRE(dir != nullptr); + + bool found_test_file = false; + while (ent = readdir(dir)) { + if (ent->d_name == kTestFilename) { + found_test_file = true; + } + } + closedir(dir); + + REQUIRE(found_test_file); + + } + + REQUIRE(remove(kTestFilePath.c_str()) == 0); + } + } + + REQUIRE( drivers::deinit_i2c() == ESP_OK ); + REQUIRE( drivers::deinit_spi() == ESP_OK ); +} + +} // namespace drivers diff --git a/src/main/main.cpp b/src/main/main.cpp index 97be7de6..d13a7407 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -7,9 +7,11 @@ #include "esp_freertos_hooks.h" #include "freertos/portmacro.h" #include "gpio-expander.hpp" +#include "i2c.hpp" #include "misc/lv_color.h" #include "misc/lv_timer.h" #include "playback.hpp" +#include "spi.hpp" #include "storage.hpp" #include @@ -33,68 +35,8 @@ #include "lvgl/lvgl.h" #include "widgets/lv_label.h" -#define I2C_SDA_IO (GPIO_NUM_2) -#define I2C_SCL_IO (GPIO_NUM_4) -#define I2C_CLOCK_HZ (400000) - -#define SPI_SDI_IO (GPIO_NUM_19) -#define SPI_SDO_IO (GPIO_NUM_23) -#define SPI_SCLK_IO (GPIO_NUM_18) -#define SPI_QUADWP_IO (GPIO_NUM_22) -#define SPI_QUADHD_IO (GPIO_NUM_21) - static const char* TAG = "MAIN"; -esp_err_t init_i2c(void) { - i2c_port_t port = I2C_NUM_0; - i2c_config_t config = { - .mode = I2C_MODE_MASTER, - .sda_io_num = I2C_SDA_IO, - .scl_io_num = I2C_SCL_IO, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master = - { - .clk_speed = I2C_CLOCK_HZ, - }, - // No requirements for the clock. - .clk_flags = 0, - }; - - ESP_ERROR_CHECK(i2c_param_config(port, &config)); - ESP_ERROR_CHECK(i2c_driver_install(port, config.mode, 0, 0, 0)); - - // TODO: INT line - - return ESP_OK; -} - -esp_err_t init_spi(void) { - spi_bus_config_t config = { - .mosi_io_num = SPI_SDO_IO, - .miso_io_num = SPI_SDI_IO, - .sclk_io_num = SPI_SCLK_IO, - .quadwp_io_num = -1, // SPI_QUADWP_IO, - .quadhd_io_num = -1, // SPI_QUADHD_IO, - - // Unused - .data4_io_num = -1, - .data5_io_num = -1, - .data6_io_num = -1, - .data7_io_num = -1, - - // Use the DMA default size. The display requires larger buffers, but it - // manages its down use of DMA-capable memory. - .max_transfer_sz = 128 * 16 * 2, // TODO: hmm - .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_IOMUX_PINS, - .intr_flags = 0, - }; - - ESP_ERROR_CHECK(spi_bus_initialize(VSPI_HOST, &config, SPI_DMA_CH_AUTO)); - - return ESP_OK; -} - void IRAM_ATTR tick_hook(void) { lv_tick_inc(1); } @@ -149,17 +91,13 @@ extern "C" void app_main(void) { ESP_LOGI(TAG, "Initialising peripherals"); ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_LOWMED)); - init_i2c(); - init_spi(); + ESP_ERROR_CHECK(drivers::init_i2c()); + ESP_ERROR_CHECK(drivers::init_spi()); ESP_ERROR_CHECK(drivers::init_adc()); ESP_LOGI(TAG, "Init GPIOs"); drivers::GpioExpander* expander = new drivers::GpioExpander(); - // for debugging usb ic - // expander.set_sd_mux(drivers::GpioExpander::USB); - - /* ESP_LOGI(TAG, "Init SD card"); auto storage_res = drivers::SdStorage::create(expander); if (storage_res.has_error()) { @@ -184,15 +122,15 @@ extern "C" void app_main(void) { } std::unique_ptr playback = std::move(playback_res.value()); - */ ESP_LOGI(TAG, "Everything looks good! Waiting a mo for debugger."); vTaskDelay(pdMS_TO_TICKS(1500)); LvglArgs* lvglArgs = (LvglArgs*)calloc(1, sizeof(LvglArgs)); lvglArgs->gpio_expander = expander; - xTaskCreateStaticPinnedToCore(&lvgl_main, "LVGL", kLvglStackSize, (void*)lvglArgs, - 1, sLvglStack, &sLvglTaskBuffer, 1); + xTaskCreateStaticPinnedToCore(&lvgl_main, "LVGL", kLvglStackSize, + (void*)lvglArgs, 1, sLvglStack, + &sLvglTaskBuffer, 1); while (1) { // TODO: Find owners for everything so we can quit this task safely.