diff --git a/README.md b/README.md index a0374480..708c56e4 100644 --- a/README.md +++ b/README.md @@ -70,8 +70,24 @@ forcible remove a couple of GCC-specific build flags. Do this by creating ``` CompileFlags: - Add: [-mlong-calls, -isysroot=/Users/YOU/.espressif/tools/xtensa-clang/VERSION/xtensa-esp32-elf-clang] - Remove: [-fno-tree-switch-conversion, -mtext-section-literals, -mlongcalls, -fstrict-volatile-bitfields] + Add: [ + -ferror-limit=0, + -I/Users/YOU/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32-elf/include, + -I/Users/YOU/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32-elf/xtensa-esp32-elf/include, + -I/Users/YOU/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/8.4.0, + -I/Users/YOU/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/8.4.0/xtensa-esp32-elf, + -isysroot=/Users/YOU/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32-elf/xtensa-esp32-elf, + ] + Remove: [ + -Wduplicated-cond, + -Wduplicated-branches, + -Wlogical-op, + -fno-tree-switch-conversion, + -mtext-section-literals, + -mlongcalls, + -fstrict-volatile-bitfields, + ] + Compiler: /Users/YOU/.espressif/tools/xtensa-clang/esp-clang/bin/clang++ ``` You should then get proper LSP integration via clangd, give or take a couple of diff --git a/src/drivers/display.cpp b/src/drivers/display.cpp index c8d796a8..ba5d08d3 100644 --- a/src/drivers/display.cpp +++ b/src/drivers/display.cpp @@ -21,8 +21,6 @@ #include "display_init.hpp" static const char* kTag = "DISPLAY"; -static const gpio_num_t kCommandOrDataPin = GPIO_NUM_21; -static const gpio_num_t kLedPin = GPIO_NUM_22; static const uint8_t kDisplayWidth = 128; static const uint8_t kDisplayHeight = 160; @@ -76,18 +74,9 @@ static void IRAM_ATTR post_cb(spi_transaction_t* transaction) { auto Display::create(GpioExpander* expander, const displays::InitialisationData& init_data) -> cpp::result, Error> { - // First, set up our GPIOs - gpio_config_t gpio_cfg = { - .pin_bit_mask = GPIO_SEL_22 | GPIO_SEL_21, - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - gpio_config(&gpio_cfg); - gpio_set_level(kLedPin, 1); - gpio_set_level(kCommandOrDataPin, 0); + expander->with( + [&](auto& gpio) { gpio.set_pin(GpioExpander::DISPLAY_LED, 1); }); // Next, init the SPI device spi_device_interface_config_t spi_cfg = { @@ -101,7 +90,7 @@ auto Display::create(GpioExpander* expander, .cs_ena_posttrans = 0, .clock_speed_hz = SPI_MASTER_FREQ_40M, .input_delay_ns = 0, - .spics_io_num = -1, // TODO: change for R2 + .spics_io_num = GPIO_NUM_22, .flags = 0, .queue_size = kTransactionQueueSize, .pre_cb = NULL, @@ -223,14 +212,11 @@ void Display::SendTransaction(TransactionType type, // ServiceTransactions(); - gpio_set_level(kCommandOrDataPin, type); 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)); - } + [&](auto& gpio) { gpio.set_pin(GpioExpander::DISPLAY_DR, type); }); + + ESP_ERROR_CHECK(spi_device_polling_transmit(handle_, transaction)); free(transaction); } diff --git a/src/drivers/gpio_expander.cpp b/src/drivers/gpio_expander.cpp index e33a8079..a7613b2e 100644 --- a/src/drivers/gpio_expander.cpp +++ b/src/drivers/gpio_expander.cpp @@ -54,10 +54,6 @@ esp_err_t GpioExpander::Read() { return ret; } -void GpioExpander::set_pin(ChipSelect cs, bool value) { - set_pin((Pin)cs, value); -} - void GpioExpander::set_pin(Pin pin, bool value) { if (value) { ports_ |= (1 << pin); @@ -70,18 +66,4 @@ bool GpioExpander::get_input(Pin pin) const { return (inputs_ & (1 << pin)) > 0; } -GpioExpander::SpiLock GpioExpander::AcquireSpiBus(ChipSelect cs) { - // TODO: also spi_device_acquire_bus? - return SpiLock(*this, cs); -} - -GpioExpander::SpiLock::SpiLock(GpioExpander& gpio, ChipSelect cs) - : lock_(gpio.cs_mutex_), gpio_(gpio), cs_(cs) { - gpio_.with([&](auto& expander) { expander.set_pin(cs_, 0); }); -} - -GpioExpander::SpiLock::~SpiLock() { - gpio_.with([&](auto& expander) { expander.set_pin(cs_, 1); }); -} - } // namespace drivers diff --git a/src/drivers/include/gpio_expander.hpp b/src/drivers/include/gpio_expander.hpp index de02e659..1faf0f88 100644 --- a/src/drivers/include/gpio_expander.hpp +++ b/src/drivers/include/gpio_expander.hpp @@ -36,27 +36,27 @@ class GpioExpander { // Port A: // 0 - audio power enable - // 1 - usb interface power enable + // 1 - usb interface power enable (active low) // 2 - display power enable - // 3 - sd card power enable - // 4 - charge power ok (active low) + // 3 - touchpad power enable + // 4 - sd card power enable // 5 - sd mux switch - // 6 - sd chip select - // 7 - display chip select - // All power switches low, chip selects high, active-low charge power high - static const uint8_t kPortADefault = 0b11010001; + // 6 - LDO enable + // 7 - charge power ok (active low) + // All power switches low, sd mux pointing away from us, inputs high. + static const uint8_t kPortADefault = 0b10000010; // Port B: // 0 - 3.5mm jack detect (active low) - // 1 - dac soft mute switch - // 2 - GPIO - // 3 - GPIO - // 4 - GPIO - // 5 - GPIO - // 6 - GPIO - // 7 - GPIO - // DAC mute output low, everything else is active-low inputs. - static const uint8_t kPortBDefault = 0b11111111; + // 1 - unused + // 2 - volume up + // 3 - volume down + // 4 - lock switch + // 5 - touchpad interupt + // 6 - display DR + // 7 - display LED + // Inputs all high, all others low. + static const uint8_t kPortBDefault = 0b00111101; /* * Convenience mehod for packing the port a and b bytes into a single 16 bit @@ -102,33 +102,27 @@ class GpioExpander { AUDIO_POWER_ENABLE = 0, USB_INTERFACE_POWER_ENABLE = 1, DISPLAY_POWER_ENABLE = 2, - SD_CARD_POWER_ENABLE = 3, - CHARGE_POWER_OK = 4, // Active-low input + TOUCHPAD_POWER_ENABLE = 3, + SD_CARD_POWER_ENABLE = 4, SD_MUX_SWITCH = 5, - SD_CHIP_SELECT = 6, - DISPLAY_CHIP_SELECT = 7, + LDO_ENABLE = 6, + CHARGE_POWER_OK = 7, // Active-low input // Port B PHONE_DETECT = 8, // Active-high input - DAC_MUTE = 9, - GPIO_1 = 10, - GPIO_2 = 11, - GPIO_3 = 12, - GPIO_4 = 13, - GPIO_5 = 14, - GPIO_6 = 15, - }; - - /* Pins whose access should be guarded by `cs_lock`. */ - enum ChipSelect { - SD_CARD = SD_CHIP_SELECT, - DISPLAY = DISPLAY_CHIP_SELECT, + //UNUSED = 9, + VOL_UP = 10, + VOL_DOWN = 11, + LOCK = 12, + TOUCHPAD_INT = 13, + DISPLAY_DR = 14, + DISPLAY_LED = 15, }; /* Nicer value names for use with the SD_MUX_SWITCH pin. */ enum SdController { - SD_MUX_ESP = 0, - SD_MUX_USB = 1, + SD_MUX_ESP = 1, + SD_MUX_USB = 0, }; /** @@ -145,7 +139,6 @@ class GpioExpander { * is made. */ void set_pin(Pin pin, bool value); - void set_pin(ChipSelect cs, bool value); /** * Returns the input status of each of the ports. The first byte is port a, @@ -159,49 +152,12 @@ class GpioExpander { */ bool get_input(Pin pin) const; - /* Returns the mutex that must be held whilst pulling a CS pin low. */ - std::mutex& cs_mutex() { return cs_mutex_; } - - /* - * Helper class containing an active `cs_mutex` lock. When an instance of - * this class is destroyed (usually by falling out of scope), the associated - * CS pin will be driven high before the lock is released. - */ - class SpiLock { - public: - SpiLock(GpioExpander& gpio, ChipSelect cs); - ~SpiLock(); - - SpiLock(const SpiLock&) = delete; - - private: - std::scoped_lock lock_; - GpioExpander& gpio_; - ChipSelect cs_; - }; - - /* - * Pulls the given CS pin low to signal that we are about to communicate - * with a particular device, after acquiring a lock on `cs_mutex`. The - * recommended way to safely interact with devices on the SPI bus is to have - * a self-contained block like so: - * - * ``` - * { - * auto lock = AcquireSpiBus(WHATEVER); - * // Do some cool things here. - * } - * ``` - */ - SpiLock AcquireSpiBus(ChipSelect cs); - // Not copyable or movable. There should usually only ever be once instance // of this class, and that instance will likely have a static lifetime. GpioExpander(const GpioExpander&) = delete; GpioExpander& operator=(const GpioExpander&) = delete; private: - std::mutex cs_mutex_; std::atomic ports_; std::atomic inputs_; }; diff --git a/src/drivers/storage.cpp b/src/drivers/storage.cpp index 414bfd21..88159744 100644 --- a/src/drivers/storage.cpp +++ b/src/drivers/storage.cpp @@ -51,8 +51,8 @@ static esp_err_t do_transaction(sdspi_dev_handle_t handle, auto SdStorage::create(GpioExpander* gpio) -> cpp::result, Error> { - // Acquiring the bus will also flush the mux switch change. gpio->set_pin(GpioExpander::SD_MUX_SWITCH, GpioExpander::SD_MUX_ESP); + gpio->Write(); sdspi_dev_handle_t handle; std::unique_ptr host; @@ -64,8 +64,7 @@ auto SdStorage::create(GpioExpander* gpio) sdspi_device_config_t config = { .host_id = VSPI_HOST, - // CS handled manually bc it's on the GPIO expander - .gpio_cs = GPIO_NUM_2, + .gpio_cs = GPIO_NUM_21, .gpio_cd = SDSPI_SLOT_NO_CD, .gpio_wp = SDSPI_SLOT_NO_WP, .gpio_int = GPIO_NUM_NC, @@ -87,7 +86,6 @@ auto SdStorage::create(GpioExpander* gpio) host->slot = handle; callback::bootstrap = do_transaction; - auto lock = gpio->AcquireSpiBus(GpioExpander::SD_CARD); // Will return ESP_ERR_INVALID_RESPONSE if there is no card esp_err_t err = sdmmc_card_init(host.get(), card.get()); if (err != ESP_OK) { @@ -142,7 +140,7 @@ SdStorage::~SdStorage() { auto SdStorage::HandleTransaction(sdspi_dev_handle_t handle, sdmmc_command_t* cmdinfo) -> esp_err_t { - auto lock = gpio_->AcquireSpiBus(GpioExpander::SD_CARD); + // TODO: not needed anymore? return do_transaction_(handle, cmdinfo); } diff --git a/src/main/main.cpp b/src/main/main.cpp index a923b683..623d948d 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -97,6 +97,14 @@ extern "C" void app_main(void) { ESP_LOGI(TAG, "Init GPIOs"); drivers::GpioExpander* expander = new drivers::GpioExpander(); + ESP_LOGI(TAG, "Enable power rails for development"); + expander->with( + [&](auto& gpio) { + gpio.set_pin(drivers::GpioExpander::AUDIO_POWER_ENABLE, 1); + gpio.set_pin(drivers::GpioExpander::SD_CARD_POWER_ENABLE, 1); + gpio.set_pin(drivers::GpioExpander::SD_MUX_SWITCH, drivers::GpioExpander::SD_MUX_ESP); + }); + ESP_LOGI(TAG, "Init SD card"); auto storage_res = drivers::SdStorage::create(expander); if (storage_res.has_error()) {