diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-06-07 09:50:25 +1000 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-06-07 09:50:25 +1000 |
| commit | 610991455d335663de1dd6c0c6a3e0247ffd46df (patch) | |
| tree | 8022526de2d30ca39386cf72d6fb5752d0c22803 /src/drivers/include | |
| parent | d2e5d2ab3cff0723cd995b0fca62aeb2a681d32d (diff) | |
| download | tangara-fw-610991455d335663de1dd6c0c6a3e0247ffd46df.tar.gz | |
R4 pre-emptive bringup
Includes stripping out the IC-specific I2S stuff, and doing more manual
volume control using pots
Diffstat (limited to 'src/drivers/include')
| -rw-r--r-- | src/drivers/include/dac.hpp | 204 | ||||
| -rw-r--r-- | src/drivers/include/digital_pot.hpp | 49 | ||||
| -rw-r--r-- | src/drivers/include/gpio_expander.hpp | 24 | ||||
| -rw-r--r-- | src/drivers/include/i2s_dac.hpp | 78 |
4 files changed, 139 insertions, 216 deletions
diff --git a/src/drivers/include/dac.hpp b/src/drivers/include/dac.hpp deleted file mode 100644 index 22d6c855..00000000 --- a/src/drivers/include/dac.hpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2023 jacqueline <me@jacqueline.id.au> - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include <stdint.h> - -#include <functional> -#include <memory> -#include <optional> -#include <utility> - -#include "driver/i2s_std.h" -#include "driver/i2s_types.h" -#include "esp_err.h" -#include "freertos/FreeRTOS.h" -#include "freertos/portmacro.h" -#include "freertos/stream_buffer.h" -#include "result.hpp" -#include "span.hpp" - -#include "gpio_expander.hpp" -#include "sys/_stdint.h" - -namespace drivers { - -namespace pcm512x { -class Register { - public: - uint8_t page; - uint8_t reg; - - constexpr Register(uint8_t p, uint8_t r) : page(p), reg(r) {} -}; - -constexpr Register RESET(0, 1); -constexpr Register POWER(0, 2); -constexpr Register MUTE(0, 3); -constexpr Register PLL_EN(0, 4); -constexpr Register SPI_MISO_FUNCTION(0, 6); -constexpr Register DSP(0, 7); -constexpr Register GPIO_EN(0, 8); -constexpr Register BCLK_LRCLK_CFG(0, 9); -constexpr Register DSP_GPIO_INPUT(0, 10); -constexpr Register MASTER_MODE(0, 12); -constexpr Register PLL_REF(0, 13); -constexpr Register DAC_REF(0, 14); -constexpr Register GPIO_DACIN(0, 16); -constexpr Register GPIO_PLLIN(0, 18); -constexpr Register SYNCHRONIZE(0, 19); -constexpr Register PLL_COEFF_0(0, 20); -constexpr Register PLL_COEFF_1(0, 21); -constexpr Register PLL_COEFF_2(0, 22); -constexpr Register PLL_COEFF_3(0, 23); -constexpr Register PLL_COEFF_4(0, 24); -constexpr Register DSP_CLKDIV(0, 27); -constexpr Register DAC_CLKDIV(0, 28); -constexpr Register NCP_CLKDIV(0, 29); -constexpr Register OSR_CLKDIV(0, 30); -constexpr Register MASTER_CLKDIV_1(0, 32); -constexpr Register MASTER_CLKDIV_2(0, 33); -constexpr Register FS_SPEED_MODE(0, 34); -constexpr Register IDAC_1(0, 35); -constexpr Register IDAC_2(0, 36); -constexpr Register ERROR_DETECT(0, 37); -constexpr Register I2S_1(0, 40); -constexpr Register I2S_2(0, 41); -constexpr Register DAC_ROUTING(0, 42); -constexpr Register DSP_PROGRAM(0, 43); -constexpr Register CLKDET(0, 44); -constexpr Register AUTO_MUTE(0, 59); -constexpr Register DIGITAL_VOLUME_1(0, 60); -constexpr Register DIGITAL_VOLUME_2(0, 61); -constexpr Register DIGITAL_VOLUME_3(0, 62); -constexpr Register DIGITAL_MUTE_1(0, 63); -constexpr Register DIGITAL_MUTE_2(0, 64); -constexpr Register DIGITAL_MUTE_3(0, 65); -constexpr Register GPIO_OUTPUT_1(0, 80); -constexpr Register GPIO_OUTPUT_2(0, 81); -constexpr Register GPIO_OUTPUT_3(0, 82); -constexpr Register GPIO_OUTPUT_4(0, 83); -constexpr Register GPIO_OUTPUT_5(0, 84); -constexpr Register GPIO_OUTPUT_6(0, 85); -constexpr Register GPIO_CONTROL_1(0, 86); -constexpr Register GPIO_CONTROL_2(0, 87); -constexpr Register OVERFLOW(0, 90); -constexpr Register RATE_DET_1(0, 91); -constexpr Register RATE_DET_2(0, 92); -constexpr Register RATE_DET_3(0, 93); -constexpr Register RATE_DET_4(0, 94); -constexpr Register CLOCK_STATUS(0, 95); -constexpr Register ANALOG_MUTE_DET(0, 108); -constexpr Register POWER_STATE(0, 118); -constexpr Register GPIN(0, 119); -constexpr Register DIGITAL_MUTE_DET(0, 120); - -constexpr Register OUTPUT_AMPLITUDE(1, 1); -constexpr Register ANALOG_GAIN_CTRL(1, 2); -constexpr Register UNDERVOLTAGE_PROT(1, 5); -constexpr Register ANALOG_MUTE_CTRL(1, 6); -constexpr Register ANALOG_GAIN_BOOST(1, 7); -constexpr Register VCOM_CTRL_1(1, 8); -constexpr Register VCOM_CTRL_2(1, 9); - -constexpr Register CRAM_CTRL(44, 1); - -constexpr Register FLEX_A(253, 63); -constexpr Register FLEX_B(253, 64); - -} // namespace pcm512x - -/** - * Interface for a PCM5122PWR DAC, configured over I2C. - */ -class AudioDac { - public: - enum Error { - FAILED_TO_BOOT, - FAILED_TO_CONFIGURE, - FAILED_TO_INSTALL_I2S, - }; - - static auto create(GpioExpander* expander) -> cpp::result<AudioDac*, Error>; - - AudioDac(GpioExpander* gpio, i2s_chan_handle_t i2s_handle); - ~AudioDac(); - - /** - * Sets the volume on a scale from 0 (loudest) to 254 (quietest). A value of - * 255 engages the soft mute function. - */ - void WriteVolume(uint8_t volume); - - enum PowerState { - POWERDOWN = 0b0, - WAIT_FOR_CP = 0b1, - CALIBRATION_1 = 0b10, - CALIBRATION_2 = 0b11, - RAMP_UP = 0b100, - RUN = 0b101, - SHORT = 0b110, - RAMP_DOWN = 0b111, - STANDBY = 0b1000, - }; - - /* Returns the current boot-up status and internal state of the DAC */ - std::pair<bool, PowerState> ReadPowerState(); - - enum BitsPerSample { - BPS_16 = I2S_DATA_BIT_WIDTH_16BIT, - BPS_24 = I2S_DATA_BIT_WIDTH_24BIT, - BPS_32 = I2S_DATA_BIT_WIDTH_32BIT, - }; - enum SampleRate { - SAMPLE_RATE_11_025 = 11025, - SAMPLE_RATE_16 = 16000, - SAMPLE_RATE_22_05 = 22050, - SAMPLE_RATE_32 = 32000, - SAMPLE_RATE_44_1 = 44100, - SAMPLE_RATE_48 = 48000, - SAMPLE_RATE_96 = 96000, - SAMPLE_RATE_192 = 192000, - }; - - // TODO(jacqueline): worth supporting channels here as well? - auto Reconfigure(BitsPerSample bps, SampleRate rate) -> void; - - auto WriteData(const cpp::span<const std::byte>& data) -> void; - auto SetSource(StreamBufferHandle_t buffer) -> void; - - auto Stop() -> void; - auto LogStatus() -> void; - - // Not copyable or movable. - AudioDac(const AudioDac&) = delete; - AudioDac& operator=(const AudioDac&) = delete; - - private: - GpioExpander* gpio_; - i2s_chan_handle_t i2s_handle_; - bool i2s_active_; - std::optional<uint8_t> active_page_; - - i2s_std_clk_config_t clock_config_; - i2s_std_slot_config_t slot_config_; - - /* - * Pools the power state for up to 10ms, waiting for the given predicate to - * be true. - */ - bool WaitForPowerState(std::function<bool(bool, PowerState)> predicate); - - void WriteRegister(pcm512x::Register r, uint8_t val); - uint8_t ReadRegister(pcm512x::Register r); - - void SelectPage(uint8_t page); - void WriteRegisterRaw(uint8_t reg, uint8_t val); - uint8_t ReadRegisterRaw(uint8_t reg); -}; - -} // namespace drivers diff --git a/src/drivers/include/digital_pot.hpp b/src/drivers/include/digital_pot.hpp new file mode 100644 index 00000000..e2ca00b1 --- /dev/null +++ b/src/drivers/include/digital_pot.hpp @@ -0,0 +1,49 @@ +/* + * Copyright 2023 jacqueline <me@jacqueline.id.au> + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#pragma once + +#include <stdint.h> +#include <functional> + +#include "esp_err.h" +#include "result.hpp" + +#include "gpio_expander.hpp" + +namespace drivers { + +/* + * Driver for a two-channel digital potentiometer, with steps measured in + * decibels. + */ +class DigitalPot { + public: + explicit DigitalPot(GpioExpander* gpios); + ~DigitalPot() {} + + // Not copyable or movable. + DigitalPot(const DigitalPot&) = delete; + DigitalPot& operator=(const DigitalPot&) = delete; + + enum class Channel { + kLeft, + kRight, + }; + + auto SetRelative(int_fast8_t change) -> void; + auto SetRelative(Channel ch, int_fast8_t change) -> void; + + auto SetZeroCrossDetect(bool enabled) -> void; + + auto GetMaxAttenuation() -> int_fast8_t; + auto GetMinAttenuation() -> int_fast8_t; + + private: + GpioExpander* gpios_; +}; + +} // namespace drivers diff --git a/src/drivers/include/gpio_expander.hpp b/src/drivers/include/gpio_expander.hpp index da682848..8231e140 100644 --- a/src/drivers/include/gpio_expander.hpp +++ b/src/drivers/include/gpio_expander.hpp @@ -56,12 +56,12 @@ class GpioExpander { static const uint8_t kPortADefault = 0b10111110; // Port B: - // 0 - trs output enable - // 1 - 3.5mm jack detect (active low) - // 2 - NC - // 3 - NC - // 4 - NC - // 5 - NC + // 0 - 3.5mm jack detect (active low) + // 1 - trs output enable + // 2 - volume zero-cross detection + // 3 - volume direction + // 4 - volume left channel + // 5 - volume right channel // 6 - NC // 7 - NC // Default input high, trs output low @@ -118,12 +118,12 @@ class GpioExpander { SD_CARD_POWER_ENABLE = 7, // Port B - AMP_EN = 8, - PHONE_DETECT = 9, - // UNUSED = 10, - // UNUSED = 11, - // UNUSED = 12, - // UNUSED = 13, + PHONE_DETECT = 8, + AMP_EN = 9, + VOL_Z_CROSS = 10, + VOL_UP_DOWN = 11, + VOL_LEFT = 12, + VOL_RIGHT = 13, // UNUSED = 14, // UNUSED = 15, }; diff --git a/src/drivers/include/i2s_dac.hpp b/src/drivers/include/i2s_dac.hpp new file mode 100644 index 00000000..42c094b1 --- /dev/null +++ b/src/drivers/include/i2s_dac.hpp @@ -0,0 +1,78 @@ +/* + * Copyright 2023 jacqueline <me@jacqueline.id.au> + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#pragma once + +#include <stdint.h> + +#include <functional> +#include <memory> +#include <optional> +#include <utility> + +#include "driver/i2s_std.h" +#include "driver/i2s_types.h" +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "freertos/stream_buffer.h" +#include "result.hpp" +#include "span.hpp" + +#include "gpio_expander.hpp" +#include "sys/_stdint.h" + +namespace drivers { + +/** + * Interface for a DAC that receives PCM samples over I2S. + */ +class I2SDac { + public: + static auto create(GpioExpander* expander) -> std::optional<I2SDac*>; + + I2SDac(GpioExpander* gpio, i2s_chan_handle_t i2s_handle); + ~I2SDac(); + + auto Start() -> void; + auto Stop() -> void; + + enum BitsPerSample { + BPS_16 = I2S_DATA_BIT_WIDTH_16BIT, + BPS_24 = I2S_DATA_BIT_WIDTH_24BIT, + BPS_32 = I2S_DATA_BIT_WIDTH_32BIT, + }; + enum SampleRate { + SAMPLE_RATE_11_025 = 11025, + SAMPLE_RATE_16 = 16000, + SAMPLE_RATE_22_05 = 22050, + SAMPLE_RATE_32 = 32000, + SAMPLE_RATE_44_1 = 44100, + SAMPLE_RATE_48 = 48000, + SAMPLE_RATE_96 = 96000, + SAMPLE_RATE_192 = 192000, + }; + + auto Reconfigure(BitsPerSample bps, SampleRate rate) -> void; + + auto WriteData(const cpp::span<const std::byte>& data) -> void; + auto SetSource(StreamBufferHandle_t buffer) -> void; + + // Not copyable or movable. + I2SDac(const I2SDac&) = delete; + I2SDac& operator=(const I2SDac&) = delete; + + private: + GpioExpander* gpio_; + i2s_chan_handle_t i2s_handle_; + bool i2s_active_; + std::optional<uint8_t> active_page_; + + i2s_std_clk_config_t clock_config_; + i2s_std_slot_config_t slot_config_; +}; + +} // namespace drivers |
