first go at r2 bringup. waiting on mosfets.
This commit is contained in:
+6
-20
@@ -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<std::unique_ptr<Display>, 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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<std::mutex> 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<uint16_t> ports_;
|
||||
std::atomic<uint16_t> inputs_;
|
||||
};
|
||||
|
||||
@@ -51,8 +51,8 @@ static esp_err_t do_transaction(sdspi_dev_handle_t handle,
|
||||
|
||||
auto SdStorage::create(GpioExpander* gpio)
|
||||
-> cpp::result<std::unique_ptr<SdStorage>, 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<sdmmc_host_t> 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,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()) {
|
||||
|
||||
Reference in New Issue
Block a user