~aleteoryx/muditaos

e942a94958a6822b5cc5906e504e977cf8b04214 — Marcin Smoczyński 4 years ago d9f8c4c
[BH-807] Add Bell audio device

Interface hardware audio codec to the audio subsystem.

Co-authored-by: Lukasz Skrzypczak <lukasz.skrzypczak@mudita.com>
Signed-off-by: Marcin Smoczyński <smoczynski.marcin@gmail.com>
M config/format-config.sh => config/format-config.sh +1 -0
@@ 29,6 29,7 @@ export declare ignore_paths=(
    'module-bluetooth/Bluetooth/glucode/btstack_uart_block_rt1051.h'
    'module-bluetooth/Bluetooth/glucode/hal_time_ms.c'
    'module-bluetooth/lib/btstack/'
    'module-bsp/board/rt1051/bellpx/bsp/audio/AW8898regs.hpp'
    'module-bsp/board/rt1051/bsp/eMMC/'
    'module-bsp/board/rt1051/bsp/pwr/'
    'module-bsp/board/rt1051/common/board.cpp'

A image/assets/audio/bell/bg_sounds/test_440Hz_16B_44k1_PCM.wav => image/assets/audio/bell/bg_sounds/test_440Hz_16B_44k1_PCM.wav +0 -0
A module-audio/board/rt1051/bellpx/BellPxAudioCodec.cpp => module-audio/board/rt1051/bellpx/BellPxAudioCodec.cpp +249 -0
@@ 0,0 1,249 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BellPxAudioCodec.hpp"
#include "board.h"
#include "dma_config.h"
#include <log/log.hpp>

#include "board/BoardDefinitions.hpp"
#include "board/rt1051/common/audio.hpp"

using audio::codec::Configuration;

namespace audio
{
    sai_edma_handle_t BellPxAudioCodec::txHandle = {};
    sai_edma_handle_t BellPxAudioCodec::rxHandle = {};

    BellPxAudioCodec::BellPxAudioCodec(const Configuration &format)
        : SAIAudioDevice(BELL_AUDIOCODEC_SAIx, &rxHandle, &txHandle), saiInFormat{}, saiOutFormat{},
          codecParams{}, codec{},
          formats(audio::AudioFormat::makeMatrix(supportedSampleRates, supportedBitWidths, supportedChannelModes)),
          currentFormat(format)
    {}

    BellPxAudioCodec::~BellPxAudioCodec()
    {
        Stop();
        DeinitBsp();
    }

    AudioDevice::RetCode BellPxAudioCodec::Start()
    {
        if (state == State::Running) {
            return AudioDevice::RetCode::Failure;
        }

        auto sampleRate = CodecParams::ValToSampleRate(currentFormat.sampleRate_Hz);
        if (sampleRate == CodecParams::SampleRate::Invalid) {
            LOG_ERROR("Unsupported sample rate");
            return AudioDevice::RetCode::Failure;
        };

        InitBsp();

        saiInFormat.bitWidth      = currentFormat.bitWidth;
        saiInFormat.sampleRate_Hz = currentFormat.sampleRate_Hz;

        saiOutFormat.bitWidth      = currentFormat.bitWidth;
        saiOutFormat.sampleRate_Hz = currentFormat.sampleRate_Hz;

        if (currentFormat.flags & static_cast<uint32_t>(audio::codec::Flags::InputLeft)) {
            saiInFormat.stereo = kSAI_MonoLeft;
            InStart();
        }
        else if (currentFormat.flags & static_cast<uint32_t>(audio::codec::Flags::InputRight)) {
            saiInFormat.stereo = kSAI_MonoRight;
            InStart();
        }
        else if (currentFormat.flags & static_cast<uint32_t>(audio::codec::Flags::InputStereo)) {
            saiInFormat.stereo = kSAI_Stereo;
            InStart();
        }

        if (currentFormat.flags & static_cast<uint32_t>(audio::codec::Flags::OutputMono)) {
            saiOutFormat.stereo = kSAI_MonoLeft;
            OutStart();
        }
        else if (currentFormat.flags & static_cast<uint32_t>(audio::codec::Flags::OutputStereo)) {
            saiOutFormat.stereo = kSAI_Stereo;
            OutStart();
        }

        codecParams.sampleRate = sampleRate;
        codecParams.outVolume  = currentFormat.outputVolume;
        codecParams.inGain     = currentFormat.inputGain;

        txEnabled = true;
        initiateTxTransfer();
        codec.Start(codecParams);

        state = State::Running;

        return AudioDevice::RetCode::Success;
    }

    AudioDevice::RetCode BellPxAudioCodec::Stop()
    {
        if (state == State::Stopped) {
            return AudioDevice::RetCode::Failure;
        }

        InStop();
        OutStop();

        codec.Stop();

        state = State::Stopped;
        vTaskDelay(codecSettleTime);

        return AudioDevice::RetCode::Success;
    }

    AudioDevice::RetCode BellPxAudioCodec::setOutputVolume(float vol)
    {
        currentFormat.outputVolume = vol;
        CodecParams params;
        params.outVolume = vol;
        params.opCmd     = CodecParams::Cmd::SetOutVolume;
        codec.Ioctrl(params);
        return AudioDevice::RetCode::Success;
    }

    AudioDevice::RetCode BellPxAudioCodec::setInputGain(float gain)
    {
        currentFormat.inputGain = gain;
        CodecParams params;
        params.inGain = gain;
        params.opCmd  = CodecParams::Cmd::SetInGain;
        codec.Ioctrl(params);
        return AudioDevice::RetCode::Success;
    }

    void BellPxAudioCodec::InitBsp()
    {
        bsp::audio::init();
    }

    void BellPxAudioCodec::DeinitBsp()
    {
        bsp::audio::deinit();
    }

    void BellPxAudioCodec::InStart()
    {
        sai_transfer_format_t sai_format;
        auto audioCfg = bsp::audio::AudioConfig::get();

        /* Configure the audio format */
        sai_format.bitWidth           = saiInFormat.bitWidth;
        sai_format.channel            = 0U;
        sai_format.sampleRate_Hz      = saiInFormat.sampleRate_Hz;
        sai_format.masterClockHz      = audioCfg->mclkSourceClockHz;
        sai_format.isFrameSyncCompact = false;
        sai_format.protocol           = audioCfg->config.protocol;
        sai_format.stereo             = saiInFormat.stereo;
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
        sai_format.watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U;
#endif

        SAI_TransferRxCreateHandleEDMA(BELL_AUDIOCODEC_SAIx,
                                       &rxHandle,
                                       rxAudioCodecCallback,
                                       this,
                                       reinterpret_cast<edma_handle_t *>(audioCfg->rxDMAHandle->GetHandle()));

        SAI_TransferRxSetFormatEDMA(
            BELL_AUDIOCODEC_SAIx, &rxHandle, &sai_format, audioCfg->mclkSourceClockHz, audioCfg->mclkSourceClockHz);

        DisableIRQ(BELL_AUDIOCODEC_SAIx_RX_IRQ);

        /* Reset SAI Rx internal logic */
        SAI_RxSoftwareReset(BELL_AUDIOCODEC_SAIx, kSAI_ResetTypeSoftware);
    }

    void BellPxAudioCodec::OutStart()
    {
        sai_transfer_format_t sai_format;
        auto audioCfg = bsp::audio::AudioConfig::get();

        /* Configure the audio format */
        sai_format.bitWidth           = saiOutFormat.bitWidth;
        sai_format.channel            = 0U;
        sai_format.sampleRate_Hz      = saiOutFormat.sampleRate_Hz;
        sai_format.masterClockHz      = audioCfg->mclkSourceClockHz;
        sai_format.isFrameSyncCompact = true;
        sai_format.protocol           = audioCfg->config.protocol;
        sai_format.stereo             = saiOutFormat.stereo;
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
        sai_format.watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U;
#endif

        SAI_TransferTxCreateHandleEDMA(BELL_AUDIOCODEC_SAIx,
                                       &txHandle,
                                       txAudioCodecCallback,
                                       this,
                                       reinterpret_cast<edma_handle_t *>(audioCfg->txDMAHandle->GetHandle()));
        SAI_TransferTxSetFormatEDMA(
            BELL_AUDIOCODEC_SAIx, &txHandle, &sai_format, audioCfg->mclkSourceClockHz, audioCfg->mclkSourceClockHz);

        SAI_TxSetBitClockPolarity(BELL_AUDIOCODEC_SAIx, kSAI_PolarityActiveLow);

        DisableIRQ(BELL_AUDIOCODEC_SAIx_TX_IRQ);

        /* Reset SAI Tx internal logic */
        SAI_TxSoftwareReset(BELL_AUDIOCODEC_SAIx, kSAI_ResetTypeSoftware);
    }

    void BellPxAudioCodec::OutStop()
    {
        SAI_TxDisableInterrupts(BELL_AUDIOCODEC_SAIx, kSAI_FIFOErrorInterruptEnable);
        if (txHandle.dmaHandle) {
            SAI_TransferTerminateSendEDMA(BELL_AUDIOCODEC_SAIx, &txHandle);
        }
        memset(&txHandle, 0, sizeof(txHandle));
    }

    void BellPxAudioCodec::InStop()
    {
        SAI_RxDisableInterrupts(BELL_AUDIOCODEC_SAIx, kSAI_FIFOErrorInterruptEnable);
        if (rxHandle.dmaHandle) {
            SAI_TransferAbortReceiveEDMA(BELL_AUDIOCODEC_SAIx, &rxHandle);
        }
        memset(&rxHandle, 0, sizeof(rxHandle));
    }

    auto BellPxAudioCodec::getSupportedFormats() -> std::vector<AudioFormat>
    {
        return formats;
    }

    auto BellPxAudioCodec::getTraits() const -> Traits
    {
        return Traits{.usesDMA = true};
    }

    auto BellPxAudioCodec::getSourceFormat() -> audio::AudioFormat
    {
        if (currentFormat.flags == 0) {
            return audio::nullFormat;
        }

        auto isMono = (currentFormat.flags & static_cast<unsigned int>(audio::codec::Flags::InputStereo)) == 0;
        return audio::AudioFormat{currentFormat.sampleRate_Hz, currentFormat.bitWidth, isMono ? 1U : 2U};
    }

    void rxAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
    {
        auto self = static_cast<BellPxAudioCodec *>(userData);
        self->onDataReceive();
    }

    void txAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
    {
        auto self = static_cast<BellPxAudioCodec *>(userData);
        self->onDataSend();
    }

} // namespace audio

A module-audio/board/rt1051/bellpx/BellPxAudioCodec.hpp => module-audio/board/rt1051/bellpx/BellPxAudioCodec.hpp +86 -0
@@ 0,0 1,86 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "SAIAudioDevice.hpp"
#include "fsl_sai_edma.h"

#include "FreeRTOS.h"
#include "task.h"
#include "macros.h"

#include <bsp/audio/CodecAW8898.hpp>

#include "drivers/pll/DriverPLL.hpp"
#include "drivers/dmamux/DriverDMAMux.hpp"
#include "drivers/dma/DriverDMA.hpp"

#include <Audio/codec.hpp>

#include <initializer_list>
#include <vector>

namespace audio
{

    void txAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);
    void rxAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);

    class BellPxAudioCodec : public SAIAudioDevice
    {

      public:
        friend void txAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);
        friend void rxAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);

        BellPxAudioCodec(const audio::codec::Configuration &format);
        virtual ~BellPxAudioCodec();

        AudioDevice::RetCode Start() final;
        AudioDevice::RetCode Stop() final;
        AudioDevice::RetCode setOutputVolume(float vol) final;
        AudioDevice::RetCode setInputGain(float gain) final;
        auto getSupportedFormats() -> std::vector<AudioFormat> final;
        auto getTraits() const -> Traits final;
        auto getSourceFormat() -> AudioFormat final;

      private:
        constexpr static TickType_t codecSettleTime                               = 20 * portTICK_PERIOD_MS;
        constexpr static std::initializer_list<unsigned int> supportedSampleRates = {
            8000, 16000, 32000, 44100, 48000, 96000};
        constexpr static std::initializer_list<unsigned int> supportedBitWidths    = {16};
        constexpr static std::initializer_list<unsigned int> supportedChannelModes = {1, 2};

        enum class State
        {
            Running,
            Stopped
        };

        struct SAIFormat
        {
            uint32_t sampleRate_Hz;   /*!< Sample rate of audio data */
            uint32_t bitWidth;        /*!< Data length of audio data, usually 8/16/24/32 bits */
            sai_mono_stereo_t stereo; /*!< Mono or stereo */
        };

        State state = State::Stopped;
        SAIFormat saiInFormat;
        SAIFormat saiOutFormat;
        CodecParams codecParams;
        CodecAW8898 codec;
        std::vector<audio::AudioFormat> formats;
        audio::codec::Configuration currentFormat;

        static AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t txHandle);
        static AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t rxHandle);

        void InitBsp();
        void DeinitBsp();
        void OutStart();
        void InStart();
        void OutStop();
        void InStop();
    };
} // namespace audio

M module-audio/board/rt1051/bellpx/BellPxAudioDeviceFactory.cpp => module-audio/board/rt1051/bellpx/BellPxAudioDeviceFactory.cpp +2 -1
@@ 2,6 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BellPxAudioDeviceFactory.hpp"
#include "BellPxAudioCodec.hpp"

#include <Audio/Profiles/Profile.hpp>



@@ 18,7 19,7 @@ std::shared_ptr<AudioDevice> BellPxAudioDeviceFactory::getDevice(const audio::Pr

    switch (profile.GetAudioDeviceType()) {
    case AudioDevice::Type::Audiocodec: {
        LOG_ERROR("Bell audio codec support is not yet implemented.");
        device = std::make_shared<BellPxAudioCodec>(profile.GetAudioConfiguration());
    } break;

    default:

M module-audio/board/rt1051/bellpx/CMakeLists.txt => module-audio/board/rt1051/bellpx/CMakeLists.txt +2 -0
@@ 1,7 1,9 @@
target_sources(${AUDIO_BOARD_LIBRARY}
    PRIVATE
        BellPxAudioDeviceFactory.cpp
        BellPxAudioCodec.cpp
    
    PUBLIC
        BellPxAudioCodec.hpp
        BellPxAudioDeviceFactory.hpp
)

M module-audio/board/rt1051/puretx/PureTxAudioCodec.cpp => module-audio/board/rt1051/puretx/PureTxAudioCodec.cpp +4 -4
@@ 175,18 175,18 @@ namespace audio

    void PureTxAudioCodec::InitBsp()
    {
        bsp::audioInit();
        bsp::audio::init();
    }

    void PureTxAudioCodec::DeinitBsp()
    {
        bsp::audioDeinit();
        bsp::audio::deinit();
    }

    void PureTxAudioCodec::InStart()
    {
        sai_transfer_format_t sai_format;
        auto audioCfg = bsp::AudioConfig::get();
        auto audioCfg = bsp::audio::AudioConfig::get();

        /* Configure the audio format */
        sai_format.bitWidth           = saiInFormat.bitWidth;


@@ 218,7 218,7 @@ namespace audio
    void PureTxAudioCodec::OutStart()
    {
        sai_transfer_format_t sai_format;
        auto audioCfg = bsp::AudioConfig::get();
        auto audioCfg = bsp::audio::AudioConfig::get();

        /* Configure the audio format */
        sai_format.bitWidth           = saiOutFormat.bitWidth;

M module-bsp/board/rt1051/CMakeLists.txt => module-bsp/board/rt1051/CMakeLists.txt +0 -1
@@ 31,7 31,6 @@ target_sources(module-bsp
		bsp/torch/torch.cpp
		bsp/vibrator/vibrator.cpp
		bsp/watchdog/watchdog.cpp
		common/audio.cpp
		common/board.cpp
		common/chip.cpp
		common/startup_mimxrt1052.cpp

M module-bsp/board/rt1051/bellpx/CMakeLists.txt => module-bsp/board/rt1051/bellpx/CMakeLists.txt +14 -9
@@ 10,20 10,25 @@ target_sources(
        module-bsp

    PRIVATE
        hal/temperature_source/TemperatureSource.cpp
        hal/battery_charger/BatteryCharger.cpp
        hal/key_input/KeyInput.cpp
        bsp/eink/eink_pin_config.cpp
        bsp/switches/switches.cpp
        bsp/rotary_encoder/rotary_encoder.cpp
        bsp/bell_temp_sensor/bell_temp_sensor.cpp
        bsp/audio/AW8898driver.cpp
        bsp/audio/CodecAW8898.cpp
        bsp/battery-charger/battery-charger.cpp
        bsp/bell_temp_sensor/bell_temp_sensor.cpp
        bsp/eink/eink_pin_config.cpp
        bsp/fuel_gauge/fuel_gauge.cpp
        bsp/lpm/PowerProfile.cpp
        pin_mux.c
        bsp/rotary_encoder/rotary_encoder.cpp
        bsp/switches/switches.cpp

        hal/battery_charger/BatteryCharger.cpp
        hal/key_input/KeyInput.cpp
        hal/temperature_source/TemperatureSource.cpp

        audio.cpp
        clock_config.cpp
        irq_gpio.cpp
        debug_console.cpp
        irq_gpio.cpp
        pin_mux.c


    PUBLIC

A module-bsp/board/rt1051/bellpx/audio.cpp => module-bsp/board/rt1051/bellpx/audio.cpp +74 -0
@@ 0,0 1,74 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "audio.hpp"

#include "board/BoardDefinitions.hpp"

extern "C"
{
#include "board.h"
#include "dma_config.h"
}

using namespace bsp::audio;
using namespace drivers;

AudioConfig audioConfig;

void bsp::audio::init()
{
    audioConfig.pllAudio =
        DriverPLL::Create(static_cast<PLLInstances>(BoardDefinitions ::AUDIO_PLL), DriverPLLParams{});
    audioConfig.dmamux =
        DriverDMAMux::Create(static_cast<DMAMuxInstances>(BoardDefinitions ::AUDIOCODEC_DMAMUX), DriverDMAMuxParams{});
    audioConfig.dma =
        DriverDMA::Create(static_cast<DMAInstances>(BoardDefinitions ::AUDIOCODEC_DMA), DriverDMAParams{});

    // Enable MCLK clock
    IOMUXC_GPR->GPR1 |= BELL_AUDIOCODEC_SAIx_MCLK_MASK;

    audioConfig.txDMAHandle =
        audioConfig.dma->CreateHandle(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_TX_DMA_CHANNEL));
    audioConfig.rxDMAHandle =
        audioConfig.dma->CreateHandle(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_RX_DMA_CHANNEL));
    audioConfig.dmamux->Enable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_TX_DMA_CHANNEL),
                               BSP_AUDIOCODEC_SAIx_DMA_TX_SOURCE);
    audioConfig.dmamux->Enable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_RX_DMA_CHANNEL),
                               BSP_AUDIOCODEC_SAIx_DMA_RX_SOURCE);

    audioConfig.mclkSourceClockHz = GetPerphSourceClock(PerphClock_SAI1);

    // Initialize SAI Tx module
    SAI_TxGetDefaultConfig(&audioConfig.config);
    audioConfig.config.masterSlave = kSAI_Master;
    SAI_TxInit(BELL_AUDIOCODEC_SAIx, &audioConfig.config);

    // Initialize SAI Rx module
    SAI_RxGetDefaultConfig(&audioConfig.config);

    audioConfig.config.masterSlave = kSAI_Master;
    SAI_RxInit(BELL_AUDIOCODEC_SAIx, &audioConfig.config);
}

void bsp::audio::deinit()
{
    memset(&audioConfig.config, 0, sizeof(audioConfig.config));
    SAI_Deinit(BELL_AUDIOCODEC_SAIx);
    if (audioConfig.dmamux) {
        audioConfig.dmamux->Disable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_TX_DMA_CHANNEL));
        audioConfig.dmamux->Disable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_RX_DMA_CHANNEL));
    }

    // force order of destruction
    audioConfig.txDMAHandle.reset();
    audioConfig.rxDMAHandle.reset();
    audioConfig.dma.reset();
    audioConfig.dmamux.reset();
    audioConfig.pllAudio.reset();
}

AudioConfig *bsp::audio::AudioConfig::get()
{
    return &audioConfig;
}

M module-bsp/board/rt1051/bellpx/board/BoardDefinitions.hpp => module-bsp/board/rt1051/bellpx/board/BoardDefinitions.hpp +21 -2
@@ 26,8 26,8 @@ enum class BoardDefinitions
    AUDIOCODEC_I2C            = static_cast<int>(drivers::I2CInstances ::I2C2),
    AUDIOCODEC_DMAMUX         = static_cast<int>(drivers::DMAMuxInstances ::DMAMUX0),
    AUDIOCODEC_DMA            = static_cast<int>(drivers::DMAInstances ::DMA_0),
    AUDIOCODEC_TX_DMA_CHANNEL = 6,
    AUDIOCODEC_RX_DMA_CHANNEL = 7,
    AUDIOCODEC_TX_DMA_CHANNEL = 2,
    AUDIOCODEC_RX_DMA_CHANNEL = 3,
    AUDIOCODEC_IRQ            = 31, // GPIO_B1_15  requires pull-up 10kΩ
    AUDIOCODEC_IRQ_GPIO       = static_cast<int>(drivers::GPIOInstances ::GPIO_2),



@@ 168,4 168,23 @@ enum class BoardDefinitions

    BELL_TEMP_SENSOR_PWR_GPIO = static_cast<int>(drivers::GPIOInstances ::GPIO_1),
    BELL_TEMP_SENSOR_PWR_PIN  = 27,

    BELL_AUDIOCODEC_GPIO        = static_cast<int>(drivers::GPIOInstances ::GPIO_1),
    BELL_AUDIOCODEC_RSTN_PA_PIN = 14,
    BELL_AUDIOCODEC_INTN_PA_PIN = 24,

/**
 * BELL AUDIOCODEC DEFINITIONS
 */

/* SAI */
#define BELL_AUDIOCODEC_SAIx           SAI1
#define BELL_AUDIOCODEC_SAIx_MUX       kCLOCK_Sai1Mux
#define BELL_AUDIOCODEC_SAIx_PREDIV    kCLOCK_Sai1PreDiv
#define BELL_AUDIOCODEC_SAIx_DIV       kCLOCK_Sai1Div
#define BELL_AUDIOCODEC_SAIx_MCLK_MASK IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK

/* IRQ */
#define BELL_AUDIOCODEC_SAIx_TX_IRQ SAI1_IRQn
#define BELL_AUDIOCODEC_SAIx_RX_IRQ SAI1_IRQn
};

M module-bsp/board/rt1051/bellpx/board/pin_mux.h => module-bsp/board/rt1051/bellpx/board/pin_mux.h +3 -0
@@ 108,6 108,9 @@ extern "C"
#define PINMUX_AUDIOCODEC_SCL IOMUXC_GPIO_B0_04_LPI2C2_SCL
#define PINMUX_AUDIOCODEC_SDA IOMUXC_GPIO_B0_05_LPI2C2_SDA

#define PINMUX_AUDIOCODEC_RSTN_PA IOMUXC_GPIO_AD_B0_14_GPIO1_IO14
#define PINMUX_AUDIOCODEC_INTN_PA IOMUXC_GPIO_AD_B1_08_GPIO1_IO24

    void PINMUX_InitAudioCodec(void);
/**
 * EINK PINMUX DEFINITIONS

A module-bsp/board/rt1051/bellpx/bsp/audio/AW8898driver.cpp => module-bsp/board/rt1051/bellpx/bsp/audio/AW8898driver.cpp +534 -0
@@ 0,0 1,534 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "AW8898driver.hpp"
#include "board/BoardDefinitions.hpp"
#include <log/log.hpp>

extern "C"
{
#include "FreeRTOS.h"
#include "task.h"
}

#include <memory>

namespace
{
    constexpr auto softResetCommand = 0x55aa;
    constexpr auto readRetries      = 5;
    constexpr auto expectedReadSize = sizeof(std::uint16_t);
} // namespace

namespace bsp::audio::AW8898
{
    std::shared_ptr<drivers::DriverI2C> i2c;
    std::shared_ptr<drivers::DriverGPIO> gpio;
    drivers::I2CAddress i2cAddr;

    inline void FlipBytes(uint16_t *val)
    {
        std::uint16_t tmp = *val << 8;
        *val              = (*val >> 8) | tmp;
    }

    // internal typedefs & variables

    struct aw8898_reg_cfg
    {
        std::uint8_t addr;
        std::uint16_t data;
    };

    enum class aw8898_init
    {
        AW8898_INIT_ST = 0,
        AW8898_INIT_OK = 1,
        AW8898_INIT_NG = 2,
    };

    struct aw8898
    {
        aw8898_init init;
        aw_sel_mode mode;
    };

    struct aw8898 g_aw8898 = {
        .init = aw8898_init::AW8898_INIT_ST,
        .mode = aw_sel_mode::OFF_MODE,
    };

    namespace
    {
        constexpr std::size_t configurationSize                                      = 16;
        constexpr std::array<aw8898_reg_cfg, configurationSize> initialConfiguration = {{
            {0x06, 0x0330},
            {0x08, 0xa00e},
            {0x09, 0x424a},
            {0x0a, 0x03c2},
            {0x0b, 0x03c2},
            {0x0c, 0x3007},
            {0x0d, 0x011b},
            {0x0e, 0x0329},
            {0x20, 0x0001},
            {0x60, 0x1cbc},
            {0x61, 0x0f0e},
            {0x62, 0xf5b6},
            {0x63, 0x307f},
            {0x67, 0x007c},
            {0x69, 0x0245},
            {0x04, 0x0044},
        }};

        constexpr std::uint8_t availableRegisters[] = {
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0f, 0x21, 0x60, 0x61, 0x62};
    } // namespace

    /*******************************************************************************
     * Code
     ******************************************************************************/
    status_t WriteReg(std::uint8_t reg, std::uint16_t val)
    {
        i2cAddr.subAddress = reg;
        std::uint16_t tval = val;
        FlipBytes(reinterpret_cast<std::uint16_t *>(&tval));
        auto sent = i2c->Write(i2cAddr, reinterpret_cast<std::uint8_t *>(&tval), expectedReadSize);
        if (sent == expectedReadSize)
            return kStatus_Success;
        else
            return kStatus_Fail;
    }

    status_t ReadReg(std::uint8_t reg, std::uint16_t *val)
    {
        std::uint16_t tval;

        i2cAddr.subAddress = reg;

        auto received = i2c->Read(i2cAddr, reinterpret_cast<std::uint8_t *>(&tval), expectedReadSize);
        if (received != expectedReadSize)
            return kStatus_Fail;

        FlipBytes(reinterpret_cast<std::uint16_t *>(&tval));
        *val = tval;

        return kStatus_Success;
    }

    status_t ModifyReg(std::uint8_t reg, std::uint16_t mask, std::uint16_t val)
    {
        status_t retval       = 0;
        std::uint16_t reg_val = 0;
        retval                = ReadReg(reg, &reg_val);
        if (retval != kStatus_Success) {
            return kStatus_Fail;
        }
        reg_val &= mask;
        reg_val |= val;
        retval = WriteReg(reg, reg_val);
        if (retval != kStatus_Success) {
            return kStatus_Fail;
        }
        return kStatus_Success;
    }

    status_t HwReset(void)
    {
        gpio->WritePin(static_cast<std::uint32_t>(BoardDefinitions::BELL_AUDIOCODEC_RSTN_PA_PIN),
                       LogicLow); // reset chip
        HAL_Delay(OperationWaitTimeMS);
        gpio->WritePin(static_cast<std::uint32_t>(BoardDefinitions::BELL_AUDIOCODEC_RSTN_PA_PIN),
                       LogicHigh); // clear reset
        HAL_Delay(OperationWaitTimeMS);

        g_aw8898.init = aw8898_init::AW8898_INIT_ST;

        return kStatus_Success;
    }

    void SoftReset(void)
    {
        WriteReg(AW8898_REG_ID, softResetCommand);

        LOG_DEBUG("enter %s end", __func__);
    }

    status_t ReadChipid(void)
    {
        std::uint8_t cnt      = 0;
        std::uint16_t reg_val = 0;

        while (cnt < readRetries) {
            ReadReg(AW8898_REG_ID, &reg_val);
            if (reg_val == AW8898_CHIP_ID) {
                LOG_DEBUG("this chip is Aw8898 chipid=0x%x", reg_val);
                return kStatus_Success;
            }
            LOG_DEBUG("%s: aw8898 chipid=0x%x error\n", __func__, reg_val);
            cnt++;
            HAL_Delay(OperationWaitTimeMS);
        }

        return kStatus_Fail;
    }

    status_t Init(const aw_i2s_channel chsel, aw_i2s_frequency rate)
    {
        status_t ret = kStatus_Success;

        HwReset();
        HAL_Delay(OperationWaitTimeMS);

        ret = ReadChipid();
        if (ret == kStatus_Fail) {
            LOG_DEBUG("please check hardware ad_pin && i2c config!!!");
            return ret;
        }

        RunPwd(false);
        HAL_Delay(OperationWaitTimeMS);

        SetMode(aw_sel_mode::SPK_MODE);

        HwParams(chsel, rate, aw_i2s_width::WIDTH_16BITS, aw_i2s_fs::I2SBCK_32FS);
        HAL_Delay(OperationWaitTimeMS);

        CtrlState(aw_codec_mode::AW_DECODE, aw_ctrl::START);

        Start();

        ReadAllReg();

        return ret;
    }

    void setChannelSelection(aw_i2s_channel chsel)
    {
        std::uint16_t reg_value;

        switch (chsel) {
        case aw_i2s_channel::CHSEL_LEFT:
            reg_value = AW8898_BIT_I2SCTRL_CHS_LEFT;
            break;
        case aw_i2s_channel::CHSEL_RIGHT:
            reg_value = AW8898_BIT_I2SCTRL_CHS_RIGHT;
            break;
        case aw_i2s_channel::CHSEL_MONO:
            reg_value = AW8898_BIT_I2SCTRL_CHS_MONO;
            break;
        default:
            reg_value = AW8898_BIT_I2SCTRL_CHS_MONO;
            LOG_DEBUG("%s: chsel can not support ", __func__);
            break;
        }

        // set chsel
        ModifyReg(AW8898_REG_I2SCTRL, AW8898_BIT_I2SCTRL_CHS_MASK, reg_value);
    }

    void setSampleRate(aw_i2s_frequency rate)
    {
        std::uint16_t reg_value;

        switch (rate) {
        case aw_i2s_frequency::FREQUENCY_08K:
            reg_value = AW8898_BIT_I2SCTRL_SR_8K;
            break;
        case aw_i2s_frequency::FREQUENCY_11K:
            reg_value = AW8898_BIT_I2SCTRL_SR_11K;
            break;
        case aw_i2s_frequency::FREQUENCY_16K:
            reg_value = AW8898_BIT_I2SCTRL_SR_16K;
            break;
        case aw_i2s_frequency::FREQUENCY_22K:
            reg_value = AW8898_BIT_I2SCTRL_SR_22K;
            break;
        case aw_i2s_frequency::FREQUENCY_24K:
            reg_value = AW8898_BIT_I2SCTRL_SR_24K;
            break;
        case aw_i2s_frequency::FREQUENCY_32K:
            reg_value = AW8898_BIT_I2SCTRL_SR_32K;
            break;
        case aw_i2s_frequency::FREQUENCY_44K:
            reg_value = AW8898_BIT_I2SCTRL_SR_44P1K;
            break;
        case aw_i2s_frequency::FREQUENCY_48K:
            reg_value = AW8898_BIT_I2SCTRL_SR_48K;
            break;
        default:
            reg_value = AW8898_BIT_I2SCTRL_SR_48K;
            LOG_DEBUG("%s: rate can not support", __func__);
            break;
        }

        // set rate
        ModifyReg(AW8898_REG_I2SCTRL, AW8898_BIT_I2SCTRL_SR_MASK, reg_value);
    }

    void setBitWidth(aw_i2s_width width)
    {
        std::uint16_t reg_value;

        switch (width) {
        case aw_i2s_width::WIDTH_16BITS:
            reg_value = AW8898_BIT_I2SCTRL_FMS_16BIT;
            break;
        case aw_i2s_width::WIDTH_24BITS:
            reg_value = AW8898_BIT_I2SCTRL_FMS_24BIT;
            break;
        case aw_i2s_width::WIDTH_32BITS:
            reg_value = AW8898_BIT_I2SCTRL_FMS_32BIT;
            break;
        default:
            reg_value = AW8898_BIT_I2SCTRL_FMS_16BIT;
            LOG_DEBUG("%s: width can not support ", __func__);
            break;
        }
        // set width
        ModifyReg(AW8898_REG_I2SCTRL, AW8898_BIT_I2SCTRL_FMS_MASK, reg_value);
    }

    void setFs(aw_i2s_fs fs)
    {
        std::uint16_t reg_value;

        switch (fs) {
        case aw_i2s_fs::I2SBCK_32FS:
            reg_value = AW8898_BIT_I2SCTRL_BCK_32FS;
            break;
        case aw_i2s_fs::I2SBCK_48FS:
            reg_value = AW8898_BIT_I2SCTRL_BCK_48FS;
            break;
        case aw_i2s_fs::I2SBCK_64FS:
            reg_value = AW8898_BIT_I2SCTRL_BCK_64FS;
            break;
        default:
            reg_value = AW8898_BIT_I2SCTRL_BCK_64FS;
            LOG_DEBUG("%s: fs can not support ", __func__);
            break;
        }

        // set fs
        ModifyReg(AW8898_REG_I2SCTRL, AW8898_BIT_I2SCTRL_BCK_MASK, reg_value);
    }

    status_t HwParams(aw_i2s_channel chsel, aw_i2s_frequency rate, aw_i2s_width width, aw_i2s_fs fs)
    {
        LOG_DEBUG("[chsel]=%i, [rate]=%i", static_cast<int>(chsel), static_cast<int>(rate));

        setChannelSelection(chsel);
        setSampleRate(rate);
        setBitWidth(width);
        setFs(fs);

        return kStatus_Success;
    }

    void LoadRegCfg(void)
    {
        for (unsigned int i = 0; i < configurationSize; i++) {
            WriteReg(initialConfiguration[i].addr, initialConfiguration[i].data);
        }
    }

    status_t RunPwd(bool pwd)
    {
        if (pwd) {
            ModifyReg(AW8898_REG_SYSCTRL, AW8898_BIT_SYSCTRL_PW_MASK, AW8898_BIT_SYSCTRL_PW_PDN);
        }
        else {
            ModifyReg(AW8898_REG_SYSCTRL, AW8898_BIT_SYSCTRL_PW_MASK, AW8898_BIT_SYSCTRL_PW_ACTIVE);
            ModifyReg(AW8898_REG_SYSCTRL, AW8898_BIT_SYSCTRL_I2SEN_MASK, AW8898_BIT_SYSCTRL_I2S_ENABLE);
        }

        return kStatus_Success;
    }

    status_t RunMute(bool mute)
    {
        if (mute) {
            ModifyReg(AW8898_REG_PWMCTRL, AW8898_BIT_PWMCTRL_HMUTE_MASK, AW8898_BIT_PWMCTRL_HMUTE_ENABLE);
        }
        else {
            ModifyReg(AW8898_REG_PWMCTRL, AW8898_BIT_PWMCTRL_HMUTE_MASK, AW8898_BIT_PWMCTRL_HMUTE_DISABLE);
        }

        return kStatus_Success;
    }

    void ColdStart(void)
    {
        LoadRegCfg();
        g_aw8898.init = aw8898_init::AW8898_INIT_OK;

        if ((g_aw8898.mode == aw_sel_mode::SPK_MODE) || (g_aw8898.mode == aw_sel_mode::MUSIC_MODE)) {
            LOG_DEBUG("SPK MODE");
            ModifyReg(AW8898_REG_SYSCTRL, AW8898_BIT_SYSCTRL_MODE_MASK, AW8898_BIT_SYSCTRL_SPK_MODE);
        }
        else {
            LOG_DEBUG("RCV MODE");
            ModifyReg(AW8898_REG_SYSCTRL, AW8898_BIT_SYSCTRL_MODE_MASK, AW8898_BIT_SYSCTRL_RCV_MODE);
        }
    }

    status_t Start(void)
    {
        std::uint16_t reg_val = 0;

        RunPwd(false);
        HAL_Delay(OperationWaitTimeMS);

        for (unsigned int i = 0; i < readRetries; i++) {
            ReadReg(AW8898_REG_SYSST, &reg_val);
            if ((reg_val & AW8898_BIT_SYSST_PLLS)) {
                RunMute(false);
                LOG_DEBUG("%s iis signal check pass!", __func__);
                return kStatus_Success;
            }

            HAL_Delay(OperationWaitTimeMS);
        }
        RunPwd(true);

        LOG_DEBUG("%s: iis signal check error[0x%04X]", __func__, reg_val);

        return kStatus_Fail;
    }

    status_t Stop(void)
    {
        RunMute(true);
        RunPwd(true);

        return kStatus_Success;
    }

    status_t SmartpaCfg(bool play_flag)
    {
        int ret = kStatus_Fail;

        LOG_DEBUG("%s: flag = %d", __func__, play_flag);

        if (play_flag == true && g_aw8898.mode != aw_sel_mode::OFF_MODE) {
            if ((g_aw8898.init == aw8898_init::AW8898_INIT_ST) || (g_aw8898.init == aw8898_init::AW8898_INIT_NG)) {
                LOG_DEBUG("%s: init = %d", __func__, static_cast<int>(g_aw8898.init));
                ColdStart();
            }
            else {
                ret = Start();
                LOG_DEBUG("%s: init = %d", __func__, static_cast<int>(g_aw8898.init));
                if (ret < 0) {
                    LOG_DEBUG("%s: start fail, ret=%d\n", __func__, ret);
                }
                else {
                    LOG_DEBUG("%s: start success", __func__);
                }
            }
        }
        else {
            Stop();
        }

        return kStatus_Success;
    }

    status_t CtrlState(aw_codec_mode mode, aw_ctrl aw_ctrl)
    {
        switch (mode) {
        case aw_codec_mode::AW_ENCODE:
            break;
        case aw_codec_mode::AW_DECODE:
            SmartpaCfg(aw_ctrl != aw_ctrl::STOP);
            break;
        case aw_codec_mode::AW_MODE_BOTH:
            break;
        case aw_codec_mode::AW_MODE_LINE_IN:
            break;
        default:
            break;
        }

        return kStatus_Success;
    }

    status_t SetVolume(std::uint8_t gain)
    {
        status_t res      = kStatus_Success;
        std::uint16_t reg = 0, reg_val = 0;

        res = ReadReg(AW8898_REG_HAGCCFG7, &reg);
        if (res != 0) {
            LOG_DEBUG("reg read err(%ld)", res);
            return res;
        }

        reg_val = (gain << 8) | (reg & 0x00ff);
        res     = WriteReg(AW8898_REG_HAGCCFG7, reg_val);
        LOG_DEBUG("Vol 0x%04X", reg_val);

        return res;
    }

    status_t GetVolume(std::uint8_t *gian)
    {
        status_t res      = kStatus_Success;
        std::uint16_t reg = 0;

        res = ReadReg(AW8898_REG_HAGCCFG7, &reg);
        if (res != kStatus_Success) {
            LOG_DEBUG("reg read err(%ld)", res);
            return res;
        }

        *gian = reg >> 8;
        return res;
    }

    int SetMode(aw_sel_mode mode)
    {
        if ((mode == aw_sel_mode::SPK_MODE) && (g_aw8898.mode != mode)) {
            g_aw8898.mode = aw_sel_mode::SPK_MODE;
            g_aw8898.init = aw8898_init::AW8898_INIT_ST;
        }
        else if ((mode == aw_sel_mode::VOICE_MODE) && (g_aw8898.mode != mode)) {
            g_aw8898.mode = aw_sel_mode::VOICE_MODE;
            g_aw8898.init = aw8898_init::AW8898_INIT_ST;
        }
        else if ((mode == aw_sel_mode::MUSIC_MODE) && (g_aw8898.mode != mode)) {
            g_aw8898.mode = aw_sel_mode::MUSIC_MODE;
            g_aw8898.init = aw8898_init::AW8898_INIT_ST;
        }
        else if (mode == aw_sel_mode::OFF_MODE) {
            g_aw8898.mode = aw_sel_mode::OFF_MODE;
        }
        else {
            LOG_DEBUG("Mode not changed!");
        }
        return 0;
    }

    bool CheckPllStatus(void)
    {
        std::uint16_t reg_val = 0;

        ReadReg(AW8898_REG_SYSST, &reg_val);

        return (reg_val & AW8898_BIT_SYSST_PLLS) != 0;
    }

    void HAL_Delay(std::uint32_t count)
    {
        extern std::uint32_t SystemCoreClock;
        vTaskDelay(pdMS_TO_TICKS(count));
    }

    void ReadAllReg(void)
    {
        std::uint16_t val = 0;
        for (std::uint8_t i = 0; i < sizeof(availableRegisters); i++) {
            ReadReg(availableRegisters[i], &val);
            LOG_DEBUG("reg[%x] = 0x%x", availableRegisters[i], val);
        }
    }

}; // namespace bsp::audio::AW8898

A module-bsp/board/rt1051/bellpx/bsp/audio/AW8898driver.hpp => module-bsp/board/rt1051/bellpx/bsp/audio/AW8898driver.hpp +120 -0
@@ 0,0 1,120 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "AW8898regs.hpp"
#include "drivers/i2c/DriverI2C.hpp"
#include "drivers/gpio/DriverGPIO.hpp"

extern "C"
{
#include "fsl_common.h"
}

#include <memory>

#include <cstdint>

namespace bsp::audio::AW8898
{
    extern std::shared_ptr<drivers::DriverI2C> i2c;
    extern std::shared_ptr<drivers::DriverGPIO> gpio;
    extern drivers::I2CAddress i2cAddr;

    constexpr inline auto LogicLow            = 0;
    constexpr inline auto LogicHigh           = 1;
    constexpr inline auto OperationWaitTimeMS = 2;

    constexpr inline auto AW8898_CHIP_ID = 0x1702;

    enum class aw_i2s_channel
    {
        CHSEL_LEFT  = 0,
        CHSEL_RIGHT = 1,
        CHSEL_MONO  = 2,
    };

    enum class aw_i2s_frequency
    {
        FREQUENCY_08K = 0,
        FREQUENCY_11K = 1,
        FREQUENCY_16K = 2,
        FREQUENCY_22K = 3,
        FREQUENCY_24K = 4,
        FREQUENCY_32K = 5,
        FREQUENCY_44K = 6,
        FREQUENCY_48K = 7,

    };

    enum class aw_i2s_width
    {
        WIDTH_16BITS = 0,
        WIDTH_24BITS = 1,
        WIDTH_32BITS = 2,

    };

    enum class aw_i2s_fs
    {
        I2SBCK_32FS = 0,
        I2SBCK_48FS = 1,
        I2SBCK_64FS = 2,
    };

    enum class aw_sel_mode
    {
        OFF_MODE   = 0,
        SPK_MODE   = 1,
        VOICE_MODE = 2,
        MUSIC_MODE = 3,
    };

    enum class aw_codec_mode
    {
        AW_ENCODE       = 0,
        AW_DECODE       = 1,
        AW_MODE_BOTH    = 2,
        AW_MODE_LINE_IN = 3,
    };

    enum class aw_ctrl
    {
        STOP  = 0,
        START = 1,
    };

    status_t WriteReg(std::uint8_t reg, std::uint16_t val);
    status_t ReadReg(std::uint8_t reg, std::uint16_t *val);
    status_t ModifyReg(std::uint8_t reg, std::uint16_t mask, std::uint16_t val);

    status_t HwReset(void);
    void SoftReset(void);

    status_t ReadChipid(void);
    status_t Init(const aw_i2s_channel chsel, aw_i2s_frequency rate);

    status_t HwParams(aw_i2s_channel chsel, aw_i2s_frequency rate, aw_i2s_width width, aw_i2s_fs fs);
    status_t RunPwd(bool pwd);
    status_t RunMute(bool mute);
    void LoadRegCfg(void);

    void ColdStart(void);

    status_t Stop(void);

    status_t SmartpaCfg(bool play_flag);
    status_t CtrlState(aw_codec_mode mode, aw_ctrl aw_ctrl);

    int SetMode(aw_sel_mode mode);
    bool CheckPllStatus(void);

    void ReadAllReg(void);
    void HAL_Delay(std::uint32_t count);

    status_t SetVolume(std::uint8_t gain);
    status_t GetVolume(std::uint8_t *gain);

    status_t Start(void);
}; // namespace bsp::audio::AW8898

A module-bsp/board/rt1051/bellpx/bsp/audio/AW8898regs.hpp => module-bsp/board/rt1051/bellpx/bsp/audio/AW8898regs.hpp +597 -0
@@ 0,0 1,597 @@
/*
 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 * Copyright 2016-2019 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#pragma once

extern "C"
{
#include "fsl_common.h"
}

/********************************************
 * Register List
 *******************************************/
#define AW8898_REG_ID           0x00
#define AW8898_REG_SYSST        0x01
#define AW8898_REG_SYSINT       0x02
#define AW8898_REG_SYSINTM      0x03
#define AW8898_REG_SYSCTRL      0x04
#define AW8898_REG_I2SCTRL      0x05
#define AW8898_REG_I2STXCFG     0x06
#define AW8898_REG_PWMCTRL      0x08
#define AW8898_REG_HAGCCFG1     0x09
#define AW8898_REG_HAGCCFG2     0x0A
#define AW8898_REG_HAGCCFG3     0x0B
#define AW8898_REG_HAGCCFG4     0x0C
#define AW8898_REG_HAGCCFG5     0x0D
#define AW8898_REG_HAGCCFG6     0x0E
#define AW8898_REG_HAGCCFG7     0x0F
#define AW8898_REG_HAGCST       0x10
#define AW8898_REG_DBGCTRL      0x20
#define AW8898_REG_I2SCFG       0x21
#define AW8898_REG_I2SSTAT      0x22
#define AW8898_REG_I2SCAPCNT    0x23
#define AW8898_REG_GENCTRL      0x60
#define AW8898_REG_BSTCTRL1     0x61
#define AW8898_REG_BSTCTRL2     0x62
#define AW8898_REG_PLLCTRL1     0x63
#define AW8898_REG_PLLCTRL2     0x64
#define AW8898_REG_TESTCTRL     0x65
#define AW8898_REG_AMPDBG1      0x66
#define AW8898_REG_AMPDBG2      0x67
#define AW8898_REG_BSTDBG1      0x68
#define AW8898_REG_CDACTRL1     0x69
#define AW8898_REG_CDACTRL2     0x6A
#define AW8898_REG_TESTCTRL2    0x6B

#define AW8898_REG_MAX          0x6F

/********************************************
 * Register Access
 *******************************************/
#define REG_NONE_ACCESS 0
#define REG_RD_ACCESS  1 << 0
#define REG_WR_ACCESS  1 << 1

/******************************************************
 * Register Detail
 *****************************************************/
// SYSST
#define AW8898_BIT_SYSST_UVLOS                      ( 1<<14)
#define AW8898_BIT_SYSST_ADPS                       ( 1<<13)
#define AW8898_BIT_SYSST_DSPS                       ( 1<<12)
#define AW8898_BIT_SYSST_BSTOCS                     ( 1<<11)
#define AW8898_BIT_SYSST_OVPS                       ( 1<<10)
#define AW8898_BIT_SYSST_BSTS                       ( 1<< 9)
#define AW8898_BIT_SYSST_SWS                        ( 1<< 8)
#define AW8898_BIT_SYSST_CLIPS                      ( 1<< 7)
#define AW8898_BIT_SYSST_WDS                        ( 1<< 6)
#define AW8898_BIT_SYSST_NOCLKS                     ( 1<< 5)
#define AW8898_BIT_SYSST_CLKS                       ( 1<< 4)
#define AW8898_BIT_SYSST_OCDS                       ( 1<< 3)
#define AW8898_BIT_SYSST_OTLS                       ( 1<< 2)
#define AW8898_BIT_SYSST_OTHS                       ( 1<< 1)
#define AW8898_BIT_SYSST_PLLS                       ( 1<< 0)

// SYSINT
#define AW8898_BIT_SYSINT_UVLOI                     ( 1<<14)
#define AW8898_BIT_SYSINT_ADPI                      ( 1<<13)
#define AW8898_BIT_SYSINT_DSPI                      ( 1<<12)
#define AW8898_BIT_SYSINT_BSTOCI                    ( 1<<11)
#define AW8898_BIT_SYSINT_OVPI                      ( 1<<10)
#define AW8898_BIT_SYSINT_BSTI                      ( 1<< 9)
#define AW8898_BIT_SYSINT_SWI                       ( 1<< 8)
#define AW8898_BIT_SYSINT_CLIPI                     ( 1<< 7)
#define AW8898_BIT_SYSINT_WDI                       ( 1<< 6)
#define AW8898_BIT_SYSINT_NOCLKI                    ( 1<< 5)
#define AW8898_BIT_SYSINT_CLKI                      ( 1<< 4)
#define AW8898_BIT_SYSINT_OCDI                      ( 1<< 3)
#define AW8898_BIT_SYSINT_OTLI                      ( 1<< 2)
#define AW8898_BIT_SYSINT_OTHI                      ( 1<< 1)
#define AW8898_BIT_SYSINT_PLLI                      ( 1<< 0)

// SYSINTM
#define AW8898_BIT_SYSINTM_UVLOM                    ( 1<<14)
#define AW8898_BIT_SYSINTM_ADPM                     ( 1<<13)
#define AW8898_BIT_SYSINTM_DSPM                     ( 1<<12)
#define AW8898_BIT_SYSINTM_BSTOCM                   ( 1<<11)
#define AW8898_BIT_SYSINTM_OVPM                     ( 1<<10)
#define AW8898_BIT_SYSINTM_BSTM                     ( 1<< 9)
#define AW8898_BIT_SYSINTM_SWM                      ( 1<< 8)
#define AW8898_BIT_SYSINTM_CLIPM                    ( 1<< 7)
#define AW8898_BIT_SYSINTM_WDM                      ( 1<< 6)
#define AW8898_BIT_SYSINTM_NOCLKM                   ( 1<< 5)
#define AW8898_BIT_SYSINTM_CLKM                     ( 1<< 4)
#define AW8898_BIT_SYSINTM_OCDM                     ( 1<< 3)
#define AW8898_BIT_SYSINTM_OTLM                     ( 1<< 2)
#define AW8898_BIT_SYSINTM_OTHM                     ( 1<< 1)
#define AW8898_BIT_SYSINTM_PLLM                     ( 1<< 0)

// SYSCTRL
#define AW8898_BIT_SYSCTRL_INTMODE_MASK             (~( 3<< 8))
#define AW8898_BIT_SYSCTRL_INT_HIGH_PP              ( 3<< 8)
#define AW8898_BIT_SYSCTRL_INT_LOW_PP               ( 2<< 8)
#define AW8898_BIT_SYSCTRL_INT_HIGH_OD              ( 1<< 8)
#define AW8898_BIT_SYSCTRL_INT_LOW_OD               ( 0<< 8)
#define AW8898_BIT_SYSCTRL_MODE_MASK                (~( 1<< 7))
#define AW8898_BIT_SYSCTRL_RCV_MODE                 ( 1<< 7)
#define AW8898_BIT_SYSCTRL_SPK_MODE                 ( 0<< 7)
#define AW8898_BIT_SYSCTRL_I2SEN_MASK               (~( 1<< 6))
#define AW8898_BIT_SYSCTRL_I2S_ENABLE               ( 1<< 6)
#define AW8898_BIT_SYSCTRL_I2S_DISABLE              ( 0<< 6)
#define AW8898_BIT_SYSCTRL_WSINV_MASK               (~( 1<< 5))
#define AW8898_BIT_SYSCTRL_WS_INVERT                ( 1<< 5)
#define AW8898_BIT_SYSCTRL_WS_NO_INVERT             ( 0<< 5)
#define AW8898_BIT_SYSCTRL_BCKINV_MASK              (~( 1<< 4))
#define AW8898_BIT_SYSCTRL_BCK_INVERT               ( 1<< 4)
#define AW8898_BIT_SYSCTRL_BCK_NO_INVERT            ( 0<< 4)
#define AW8898_BIT_SYSCTRL_IPLL_MASK                (~( 1<< 3))
#define AW8898_BIT_SYSCTRL_PLL_WORD                 ( 1<< 3)
#define AW8898_BIT_SYSCTRL_PLL_BIT                  ( 0<< 3)
#define AW8898_BIT_SYSCTRL_DSPBY_MASK               (~( 1<< 2))
#define AW8898_BIT_SYSCTRL_DSP_BYPASS               ( 1<< 2)
#define AW8898_BIT_SYSCTRL_DSP_WORK                 ( 0<< 2)
#define AW8898_BIT_SYSCTRL_CP_MASK                  (~( 1<< 1))
#define AW8898_BIT_SYSCTRL_CP_PDN                   ( 1<< 1)
#define AW8898_BIT_SYSCTRL_CP_ACTIVE                ( 0<< 1)
#define AW8898_BIT_SYSCTRL_PW_MASK                  (~( 1<< 0))
#define AW8898_BIT_SYSCTRL_PW_PDN                   ( 1<< 0)
#define AW8898_BIT_SYSCTRL_PW_ACTIVE                ( 0<< 0)

// I2SCTRL
#define AW8898_BIT_I2SCTRL_INPLEV_MASK              (~( 1<<13))
#define AW8898_BIT_I2SCTRL_INPLEV_0DB               ( 1<<13)
#define AW8898_BIT_I2SCTRL_INPLEV_NEG_6DB           ( 0<<13)
#define AW8898_BIT_I2SCTRL_STEREO_MASK              (~( 1<<12))
#define AW8898_BIT_I2SCTRL_STEREO_ENABLE            ( 1<<12)
#define AW8898_BIT_I2SCTRL_STEREO_DISABLE           ( 0<<12)
#define AW8898_BIT_I2SCTRL_CHS_MASK                 (~( 3<<10))
#define AW8898_BIT_I2SCTRL_CHS_MONO                 ( 3<<10)
#define AW8898_BIT_I2SCTRL_CHS_RIGHT                ( 2<<10)
#define AW8898_BIT_I2SCTRL_CHS_LEFT                 ( 1<<10)
#define AW8898_BIT_I2SCTRL_MD_MASK                  (~( 3<< 8))
#define AW8898_BIT_I2SCTRL_MD_LSB                   ( 2<< 8)
#define AW8898_BIT_I2SCTRL_MD_MSB                   ( 1<< 8)
#define AW8898_BIT_I2SCTRL_MD_STD                   ( 0<< 8)
#define AW8898_BIT_I2SCTRL_FMS_MASK                 (~( 3<< 6))
#define AW8898_BIT_I2SCTRL_FMS_32BIT                ( 3<< 6)
#define AW8898_BIT_I2SCTRL_FMS_24BIT                ( 2<< 6)
#define AW8898_BIT_I2SCTRL_FMS_20BIT                ( 1<< 6)
#define AW8898_BIT_I2SCTRL_FMS_16BIT                ( 0<< 6)
#define AW8898_BIT_I2SCTRL_BCK_MASK                 (~( 3<< 4))
#define AW8898_BIT_I2SCTRL_BCK_64FS                 ( 2<< 4)
#define AW8898_BIT_I2SCTRL_BCK_48FS                 ( 1<< 4)
#define AW8898_BIT_I2SCTRL_BCK_32FS                 ( 0<< 4)
#define AW8898_BIT_I2SCTRL_SR_MASK                  (~(15<< 0))
#define AW8898_BIT_I2SCTRL_SR_192K                  (10<< 0)
#define AW8898_BIT_I2SCTRL_SR_96K                   ( 9<< 0)
#define AW8898_BIT_I2SCTRL_SR_48K                   ( 8<< 0)
#define AW8898_BIT_I2SCTRL_SR_44P1K                 ( 7<< 0)
#define AW8898_BIT_I2SCTRL_SR_32K                   ( 6<< 0)
#define AW8898_BIT_I2SCTRL_SR_24K                   ( 5<< 0)
#define AW8898_BIT_I2SCTRL_SR_22K                   ( 4<< 0)
#define AW8898_BIT_I2SCTRL_SR_16K                   ( 3<< 0)
#define AW8898_BIT_I2SCTRL_SR_12K                   ( 2<< 0)
#define AW8898_BIT_I2SCTRL_SR_11K                   ( 1<< 0)
#define AW8898_BIT_I2SCTRL_SR_8K                    ( 0<< 0)


// I2STXCFG
#define AW8898_BIT_I2STXCFG_FSYNC_MASK              (~( 1<<15))
#define AW8898_BIT_I2STXCFG_FSYNC_BCK_CYCLE         ( 1<<15)
#define AW8898_BIT_I2STXCFG_FSYNC_ONE_SLOT          ( 0<<15)
#define AW8898_BIT_I2STXCFG_SLOT_NUM_MASK           (~( 1<<14))
#define AW8898_BIT_I2STXCFG_SLOT_NUM_4_TIMES        ( 1<<14)
#define AW8898_BIT_I2STXCFG_SLOT_NUM_2_TIMES        ( 0<<14)
#define AW8898_BIT_I2STXCFG_TX_SLOT_VLD_MASK        (~(15<<12))
#define AW8898_BIT_I2STXCFG_TX_SLOT_VLD_3           ( 3<<12)
#define AW8898_BIT_I2STXCFG_TX_SLOT_VLD_2           ( 2<<12)
#define AW8898_BIT_I2STXCFG_TX_SLOT_VLD_1           ( 1<<12)
#define AW8898_BIT_I2STXCFG_TX_SLOT_VLD_0           ( 0<<12)
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_MASK        (~(15<< 8))
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_3_2         (12<< 8)
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_3_1         (10<< 8)
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_3_0         ( 9<< 8)
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_2_1         ( 6<< 8)
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_2_0         ( 5<< 8)
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_1_0         ( 3<< 8)
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_3           ( 8<< 8)
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_2           ( 4<< 8)
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_1           ( 2<< 8)
#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_0           ( 1<< 8)
#define AW8898_BIT_I2STXCFG_DRVSTREN_MASK           (~( 1<< 5))
#define AW8898_BIT_I2STXCFG_DRVSTREN_8MA            ( 1<< 5)
#define AW8898_BIT_I2STXCFG_DRVSTREN_2MA            ( 0<< 5)
#define AW8898_BIT_I2STXCFG_DOHZ_MASK               (~( 1<< 4))
#define AW8898_BIT_I2STXCFG_DOHZ_HIZ                ( 1<< 4)
#define AW8898_BIT_I2STXCFG_DOHZ_GND                ( 0<< 4)
#define AW8898_BIT_I2STXCFG_DSEL_MASK               (~( 3<< 2))
#define AW8898_BIT_I2STXCFG_DSEL_DSP                ( 2<< 2)
#define AW8898_BIT_I2STXCFG_DSEL_GAIN               ( 1<< 2)
#define AW8898_BIT_I2STXCFG_DSEL_ZERO               ( 0<< 2)
#define AW8898_BIT_I2STXCFG_CHS_MASK                (~( 1<< 1))
#define AW8898_BIT_I2STXCFG_CHS_RIGHT               ( 1<< 1)
#define AW8898_BIT_I2STXCFG_CHS_LEFT                ( 0<< 1)
#define AW8898_BIT_I2STXCFG_TX_MASK                 (~( 1<< 0))
#define AW8898_BIT_I2STXCFG_TX_ENABLE               ( 1<< 0)
#define AW8898_BIT_I2STXCFG_TX_DISABLE              ( 0<< 0)

// PWMCTRL
#define AW8898_BIT_PWMCTRL_DSMZTH_MASK              (~(15<<12))
#define AW8898_BIT_PWMCTRL_DSMZTH_UNIT              ( 1<<12)
#define AW8898_BIT_PWMCTRL_PWMDELA_MASK             (~(15<< 8))
#define AW8898_BIT_PWMCTRL_PWMDELA_UNIT             ( 1<< 8)
#define AW8898_BIT_PWMCTRL_PWMDELB_MASK             (~(15<< 4))
#define AW8898_BIT_PWMCTRL_PWMDELB_UNIT             ( 1<< 4)
#define AW8898_BIT_PWMCTRL_PWMSH_MASK               (~( 1<< 3))
#define AW8898_BIT_PWMCTRL_PWMSH_TRIANGLE           ( 1<< 3)
#define AW8898_BIT_PWMCTRL_PWMSH_SAWTOOTH           ( 0<< 3)
#define AW8898_BIT_PWMCTRL_PWMRES_MASK              (~( 1<< 2))
#define AW8898_BIT_PWMCTRL_PWMRES_8BIT              ( 1<< 2)
#define AW8898_BIT_PWMCTRL_PWMRES_7BIT              ( 0<< 2)
#define AW8898_BIT_PWMCTRL_HDCCE_MASK               (~( 1<< 1))
#define AW8898_BIT_PWMCTRL_HDCCE_ENABLE             ( 1<< 1)
#define AW8898_BIT_PWMCTRL_HDCCE_DISABLE            ( 0<< 1)
#define AW8898_BIT_PWMCTRL_HMUTE_MASK               (~( 1<< 0))
#define AW8898_BIT_PWMCTRL_HMUTE_ENABLE             ( 1<< 0)
#define AW8898_BIT_PWMCTRL_HMUTE_DISABLE            ( 0<< 0)

// HAGCCFG1
#define AW8898_BIT_HAGCCFG1_RVTH_MASK               (~(255<<8))
#define AW8898_BIT_HAGCCFG1_RVTH_UNIT               ( 1<< 8)
#define AW8898_BIT_HAGCCFG1_AVTH_MASK               (~(255<<0))
#define AW8898_BIT_HAGCCFG1_AVTH_UNIT               ( 1<< 0)

// HAGCCFG2
#define AW8898_BIT_HAGCCFG2_ATTH_UNIT               ( 1<< 0)

// HAGCCFG3
#define AW8898_BIT_HAGCCFG3_RTTH_UNIT               ( 1<< 0)

// HAGCCFG4
#define AW8898_BIT_HAGCCFG4_MPD_MASK                (~( 1<<14))
#define AW8898_BIT_HAGCCFG4_MPD_ENABLE              ( 1<<14)
#define AW8898_BIT_HAGCCFG4_MPD_DISABLE             ( 0<<14)
#define AW8898_BIT_HAGCCFG4_MPD_TTH_MASK            (~( 3<<12))
#define AW8898_BIT_HAGCCFG4_MPD_TTH_0P047           ( 3<<12)
#define AW8898_BIT_HAGCCFG4_MPD_TTH_0P032           ( 2<<12)
#define AW8898_BIT_HAGCCFG4_MPD_TTH_0P016           ( 1<<12)
#define AW8898_BIT_HAGCCFG4_MPD_TTH_0P008           ( 0<<12)
#define AW8898_BIT_HAGCCFG4_MPD_RTH_MASK            (~( 3<<10))
#define AW8898_BIT_HAGCCFG4_MPD_RTH_0P047           ( 3<<10)
#define AW8898_BIT_HAGCCFG4_MPD_RTH_0P032           ( 2<<10)
#define AW8898_BIT_HAGCCFG4_MPD_RTH_0P016           ( 1<<10)
#define AW8898_BIT_HAGCCFG4_MPD_RTH_0P008           ( 0<<10)
#define AW8898_BIT_HAGCCFG4_MPD_ATH_MASK            (~( 3<< 8))
#define AW8898_BIT_HAGCCFG4_MPD_ATH_0P047           ( 3<< 8)
#define AW8898_BIT_HAGCCFG4_MPD_ATH_0P032           ( 2<< 8)
#define AW8898_BIT_HAGCCFG4_MPD_ATH_0P016           ( 1<< 8)
#define AW8898_BIT_HAGCCFG4_MPD_ATH_0P008           ( 0<< 8)
#define AW8898_BIT_HAGCCFG4_HOLDTH_MASK             (~(255<< 0))

// HAGCCFG5

// HAGCCFG6

// HAGCCFG7
#define AW8898_BIT_HAGCCFG7_VOL_MASK                (~(255< 8))
#define AW8898_VOLUME_MAX                           (0)
#define AW8898_VOLUME_MIN                           (-255)
#define AW8898_VOL_REG_SHIFT                        (8)

// HAGCST
#define AW8898_BIT_BSTVOUT_ST_10P25V                (15<< 0)
#define AW8898_BIT_BSTVOUT_ST_10V                   (14<< 0)
#define AW8898_BIT_BSTVOUT_ST_9P75V                 (13<< 0)
#define AW8898_BIT_BSTVOUT_ST_9P5V                  (12<< 0)
#define AW8898_BIT_BSTVOUT_ST_9P25V                 (11<< 0)
#define AW8898_BIT_BSTVOUT_ST_9V                    (10<< 0)
#define AW8898_BIT_BSTVOUT_ST_8P75V                 ( 9<< 0)
#define AW8898_BIT_BSTVOUT_ST_8P5V                  ( 8<< 0)
#define AW8898_BIT_BSTVOUT_ST_8P25V                 ( 7<< 0)
#define AW8898_BIT_BSTVOUT_ST_8V                    ( 6<< 0)
#define AW8898_BIT_BSTVOUT_ST_7P75V                 ( 5<< 0)
#define AW8898_BIT_BSTVOUT_ST_7P5V                  ( 4<< 0)
#define AW8898_BIT_BSTVOUT_ST_7P25V                 ( 3<< 0)
#define AW8898_BIT_BSTVOUT_ST_7V                    ( 2<< 0)
#define AW8898_BIT_BSTVOUT_ST_6P75V                 ( 1<< 0)
#define AW8898_BIT_BSTVOUT_ST_6P5V                  ( 0<< 0)

// DBGCTRL
#define AW8898_BIT_DBGCTRL_LPBK_FAR_MASK            (~( 1<<15))
#define AW8898_BIT_DBGCTRL_LPBK_FAR_ENABLE          ( 1<<15)
#define AW8898_BIT_DBGCTRL_LPBK_FAR_DISABLE         ( 0<<15)
#define AW8898_BIT_DBGCTRL_LPBK_NEAR_MASK           (~( 1<<14))
#define AW8898_BIT_DBGCTRL_LPBK_NEAR_ENABLE         ( 1<<14)
#define AW8898_BIT_DBGCTRL_LPBK_NEAR_DISABLE        ( 0<<14)
#define AW8898_BIT_DBGCTRL_PDUVL_MASK               (~( 1<<13))
#define AW8898_BIT_DBGCTRL_PDUVL_DISABLE            ( 1<<13)
#define AW8898_BIT_DBGCTRL_PDUVL_ENABLE             ( 0<<13)
#define AW8898_BIT_DBGCTRL_MUTE_MASK                (~( 1<<12))
#define AW8898_BIT_DBGCTRL_MUTE_NO_AUTO             ( 1<<12)
#define AW8898_BIT_DBGCTRL_MUTE_AUTO                ( 0<<12)
#define AW8898_BIT_DBGCTRL_NOCLK_RESET_MASK         (~( 1<<11))
#define AW8898_BIT_DBGCTRL_NOCLK_NO_RESET           ( 1<<11)
#define AW8898_BIT_DBGCTRL_NOCLK_RESET              ( 0<<11)
#define AW8898_BIT_DBGCTRL_PLL_UNLOCK_RESET_MASK    (~( 1<<10))
#define AW8898_BIT_DBGCTRL_PLL_UNLOCK_NO_RESET      ( 1<<10)
#define AW8898_BIT_DBGCTRL_PLL_UNLOCK_RESET         ( 0<<10)
#define AW8898_BIT_DBGCTRL_CLKMD_MASK               (~( 1<< 9))
#define AW8898_BIT_DBGCTRL_CLKMD_HALF               ( 1<< 9)
#define AW8898_BIT_DBGCTRL_CLKMD_NORMAL             ( 0<< 9)
#define AW8898_BIT_DBGCTRL_OSCPD_MASK               (~( 1<< 8))
#define AW8898_BIT_DBGCTRL_OSCPD_ENABLE             ( 1<< 8)
#define AW8898_BIT_DBGCTRL_OSCPD_DISABLE            ( 0<< 8)
#define AW8898_BIT_DBGCTRL_AMPPD_MASK               (~( 1<< 7))
#define AW8898_BIT_DBGCTRL_AMPPD_PDN                ( 1<< 7)
#define AW8898_BIT_DBGCTRL_AMPPD_ACTIVE             ( 0<< 7)
#define AW8898_BIT_DBGCTRL_PLLPD_MASK               (~( 1<< 6))
#define AW8898_BIT_DBGCTRL_PLLPD_PDN                ( 1<< 6)
#define AW8898_BIT_DBGCTRL_PLLPD_ACTIVE             ( 0<< 6)
#define AW8898_BIT_DBGCTRL_I2SRST_MASK              (~( 1<< 5))
#define AW8898_BIT_DBGCTRL_I2SRST_RESET             ( 1<< 5)
#define AW8898_BIT_DBGCTRL_I2SRST_WORK              ( 0<< 5)
#define AW8898_BIT_DBGCTRL_SYSRST_MASK              (~( 1<< 4))
#define AW8898_BIT_DBGCTRL_SYSRST_RESET             ( 1<< 4)
#define AW8898_BIT_DBGCTRL_SYSRST_WORK              ( 0<< 4)
#define AW8898_BIT_DBGCTRL_SYSCE_MASK               (~( 1<< 0))
#define AW8898_BIT_DBGCTRL_SYSCE_ENABLE             ( 1<< 0)
#define AW8898_BIT_DBGCTRL_SYSCE_DISABLE            ( 0<< 0)


// I2SCFG
#define AW8898_BIT_I2SCFG_I2SRX_MASK                (~( 1<< 0))
#define AW8898_BIT_I2SCFG_I2SRX_ENABLE              ( 1<< 0)
#define AW8898_BIT_I2SCFG_I2SRX_DISABLE             ( 0<< 0)

// I2SSAT
#define AW8898_BIT_I2SSAT_DPSTAT                    ( 1<< 2)
#define AW8898_BIT_I2SSAT_I2SROVS                   ( 1<< 1)
#define AW8898_BIT_I2SSAT_I2STOVS                   ( 1<< 0)

// GENCTRL
#define AW8898_BIT_GENCTRL_BURST_PEAK_MASK          (~( 3<<14))
#define AW8898_BIT_GENCTRL_BURST_PEAK_200MA         ( 3<<14)
#define AW8898_BIT_GENCTRL_BURST_PEAK_160MA         ( 2<<14)
#define AW8898_BIT_GENCTRL_BURST_PEAK_100MA         ( 1<<14)
#define AW8898_BIT_GENCTRL_BURST_PEAK_130MA         ( 0<<14)
#define AW8898_BIT_GENCTRL_BST_TDEG2_MASK           (~( 7<< 9))
#define AW8898_BIT_GENCTRL_BST_TDEG2_2P7S           ( 7<< 9)
#define AW8898_BIT_GENCTRL_BST_TDEG2_1P3S           ( 6<< 9)
#define AW8898_BIT_GENCTRL_BST_TDEG2_672MS          ( 5<< 9)
#define AW8898_BIT_GENCTRL_BST_TDEG2_336MS          ( 4<< 9)
#define AW8898_BIT_GENCTRL_BST_TDEG2_168MS          ( 3<< 9)
#define AW8898_BIT_GENCTRL_BST_TDEG2_84MS           ( 2<< 9)
#define AW8898_BIT_GENCTRL_BST_TDEG2_42MS           ( 1<< 9)
#define AW8898_BIT_GENCTRL_BST_TDEG2_21MS           ( 0<< 9)
#define AW8898_BIT_GENCTRL_BST_OCAP_MASK            (~( 1<< 8))
#define AW8898_BIT_GENCTRL_BST_OCAP_SLOW            ( 1<< 8)
#define AW8898_BIT_GENCTRL_BST_OCAP_FAST            ( 0<< 8)
#define AW8898_BIT_GENCTRL_BST_EN_MASK              (~( 1<< 7))
#define AW8898_BIT_GENCTRL_BST_ENABLE               ( 1<< 7)
#define AW8898_BIT_GENCTRL_BST_DISABLE              ( 0<< 7)
#define AW8898_BIT_GENCTRL_BST_ILIMIT_MASK          (~( 7<< 4))
#define AW8898_BIT_GENCTRL_BST_ILIMIT_4P5A          ( 7<< 4)
#define AW8898_BIT_GENCTRL_BST_ILIMIT_4P25A         ( 6<< 4)
#define AW8898_BIT_GENCTRL_BST_ILIMIT_4A            ( 5<< 4)
#define AW8898_BIT_GENCTRL_BST_ILIMIT_3P75A         ( 4<< 4)
#define AW8898_BIT_GENCTRL_BST_ILIMIT_3P5A          ( 3<< 4)
#define AW8898_BIT_GENCTRL_BST_ILIMIT_3P25A         ( 2<< 4)
#define AW8898_BIT_GENCTRL_BST_ILIMIT_3A            ( 1<< 4)
#define AW8898_BIT_GENCTRL_BST_ILIMIT_2P75A         ( 0<< 4)
#define AW8898_BIT_GENCTRL_BST_VOUT_MASK            (~(15<< 0))
#define AW8898_BIT_GENCTRL_BST_VOUT_10P25V          (15<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_10V             (14<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_9P75V           (13<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_9P5V            (12<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_9P25V           (11<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_9V              (10<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_8P75V           ( 9<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_8P5V            ( 8<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_8P25V           ( 7<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_8V              ( 6<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_7P75V           ( 5<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_7P5V            ( 4<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_7P25V           ( 3<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_7V              ( 2<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_6P75V           ( 1<< 0)
#define AW8898_BIT_GENCTRL_BST_VOUT_6P5V            ( 0<< 0)

// BSTCTRL1
#define AW8898_BIT_BSTCTRL1_RTH_MASK                (~(64<< 8))
#define AW8898_BIT_BSTCTRL1_ATH_MASK                (~(64<< 0))

// BSTCTRL2
#define AW8898_BIT_BST_MODE_MASK                    (~( 7<< 3))
#define AW8898_BIT_BST_MODE_SMART_BOOST             ( 6<< 3)
#define AW8898_BIT_BST_MODE_ADAPT_BOOST             ( 5<< 3)
#define AW8898_BIT_BST_MODE_FORCE_BOOST             ( 1<< 3)
#define AW8898_BIT_BST_MODE_TRANSP_BOOST            ( 0<< 3)
#define AW8898_BIT_BST_TDEG_MASK                    (~( 7<< 0))
#define AW8898_BIT_BST_TDEG_2P7S                    ( 7<< 0)
#define AW8898_BIT_BST_TDEG_1P3S                    ( 6<< 0)
#define AW8898_BIT_BST_TDEG_672MS                   ( 5<< 0)
#define AW8898_BIT_BST_TDEG_336MS                   ( 4<< 0)
#define AW8898_BIT_BST_TDEG_168MS                   ( 3<< 0)
#define AW8898_BIT_BST_TDEG_84MS                    ( 2<< 0)
#define AW8898_BIT_BST_TDEG_42MS                    ( 1<< 0)
#define AW8898_BIT_BST_TDEG_21MS                    ( 0<< 0)

/*! @brief Define the register address of AW8898. */
#define AW8898_LINVOL  0x0U
#define AW8898_RINVOL  0x1U
#define AW8898_LOUT1   0x2U
#define AW8898_ROUT1   0x3U
#define AW8898_CLOCK1  0x4U
#define AW8898_DACCTL1 0x5U
#define AW8898_DACCTL2 0x6U
#define AW8898_IFACE1  0x7U
#define AW8898_CLOCK2  0x8U
#define AW8898_IFACE2  0x9U
#define AW8898_LDAC    0xaU
#define AW8898_RDAC    0xbU

#define AW8898_RESET   0xfU
#define AW8898_3D      0x10U
#define AW8898_ALC1    0x11U
#define AW8898_ALC2    0x12U
#define AW8898_ALC3    0x13U
#define AW8898_NOISEG  0x14U
#define AW8898_LADC    0x15U
#define AW8898_RADC    0x16U
#define AW8898_ADDCTL1 0x17U
#define AW8898_ADDCTL2 0x18U
#define AW8898_POWER1  0x19U
#define AW8898_POWER2  0x1aU
#define AW8898_ADDCTL3 0x1bU
#define AW8898_APOP1   0x1cU
#define AW8898_APOP2   0x1dU

#define AW8898_LINPATH 0x20U
#define AW8898_RINPATH 0x21U
#define AW8898_LOUTMIX 0x22U

#define AW8898_ROUTMIX  0x25U
#define AW8898_MONOMIX1 0x26U
#define AW8898_MONOMIX2 0x27U
#define AW8898_LOUT2    0x28U
#define AW8898_ROUT2    0x29U
#define AW8898_MONO     0x2aU
#define AW8898_INBMIX1  0x2bU
#define AW8898_INBMIX2  0x2cU
#define AW8898_BYPASS1  0x2dU
#define AW8898_BYPASS2  0x2eU
#define AW8898_POWER3   0x2fU
#define AW8898_ADDCTL4  0x30U
#define AW8898_CLASSD1  0x31U

#define AW8898_CLASSD3 0x33U
#define AW8898_PLL1    0x34U
#define AW8898_PLL2    0x35U
#define AW8898_PLL3    0x36U
#define AW8898_PLL4    0x37U

/*! @brief Cache register number */
#define AW8898_CACHEREGNUM 56U

/*! @brief AW8898_IFACE1 FORMAT bits */
#define AW8898_IFACE1_FORMAT_MASK  0x03U
#define AW8898_IFACE1_FORMAT_SHIFT 0x00U
#define AW8898_IFACE1_FORMAT_RJ    0x00U
#define AW8898_IFACE1_FORMAT_LJ    0x01U
#define AW8898_IFACE1_FORMAT_I2S   0x02U
#define AW8898_IFACE1_FORMAT_DSP   0x03U
#define AW8898_IFACE1_FORMAT(x)    (((x) << AW8898_IFACE1_FORMAT_SHIFT) & AW8898_IFACE1_FORMAT_MASK)

/*! @brief AW8898_IFACE1 WL bits */
#define AW8898_IFACE1_WL_MASK   0x0CU
#define AW8898_IFACE1_WL_SHIFT  0x02U
#define AW8898_IFACE1_WL_16BITS 0x00U
#define AW8898_IFACE1_WL_20BITS 0x01U
#define AW8898_IFACE1_WL_24BITS 0x02U
#define AW8898_IFACE1_WL_32BITS 0x03U
#define AW8898_IFACE1_WL(x)     (((x) << AW8898_IFACE1_WL_SHIFT) & AW8898_IFACE1_WL_MASK)

/*! @brief AW8898_IFACE1 LRP bit */
#define AW8898_IFACE1_LRP_MASK         0x10U
#define AW8898_IFACE1_LRP_SHIFT        0x04U
#define AW8898_IFACE1_LRCLK_NORMAL_POL 0x00U
#define AW8898_IFACE1_LRCLK_INVERT_POL 0x01U
#define AW8898_IFACE1_DSP_MODEA        0x00U
#define AW8898_IFACE1_DSP_MODEB        0x01U
#define AW8898_IFACE1_LRP(x)           (((x) << AW8898_IFACE1_LRP_SHIFT) & AW8898_IFACE1_LRP_MASK)

/*! @brief AW8898_IFACE1 DLRSWAP bit */
#define AW8898_IFACE1_DLRSWAP_MASK  0x20U
#define AW8898_IFACE1_DLRSWAP_SHIFT 0x05U
#define AW8898_IFACE1_DACCH_NORMAL  0x00U
#define AW8898_IFACE1_DACCH_SWAP    0x01U
#define AW8898_IFACE1_DLRSWAP(x)    (((x) << AW8898_IFACE1_DLRSWAP_SHIFT) & AW8898_IFACE1_DLRSWAP_MASK)

/*! @brief AW8898_IFACE1 MS bit */
#define AW8898_IFACE1_MS_MASK  0x40U
#define AW8898_IFACE1_MS_SHIFT 0x06U
#define AW8898_IFACE1_SLAVE    0x00U
#define AW8898_IFACE1_MASTER   0x01U
#define AW8898_IFACE1_MS(x)    (((x) << AW8898_IFACE1_MS_SHIFT) & AW8898_IFACE1_MS_MASK)

/*! @brief AW8898_IFACE1 BCLKINV bit */
#define AW8898_IFACE1_BCLKINV_MASK   0x80U
#define AW8898_IFACE1_BCLKINV_SHIFT  0x07U
#define AW8898_IFACE1_BCLK_NONINVERT 0x00U
#define AW8898_IFACE1_BCLK_INVERT    0x01U
#define AW8898_IFACE1_BCLKINV(x)     (((x) << AW8898_IFACE1_BCLKINV_SHIFT) & AW8898_IFACE1_BCLKINV_MASK)

/*! @brief AW8898_IFACE1 ALRSWAP bit */
#define AW8898_IFACE1_ALRSWAP_MASK  0x100U
#define AW8898_IFACE1_ALRSWAP_SHIFT 0x08U
#define AW8898_IFACE1_ADCCH_NORMAL  0x00U
#define AW8898_IFACE1_ADCCH_SWAP    0x01U
#define AW8898_IFACE1_ALRSWAP(x)    (((x) << AW8898_IFACE1_ALRSWAP_SHIFT) & AW8898_IFACE1_ALRSWAP_MASK)

/*! @brief AW8898_POWER1 */
#define AW8898_POWER1_VREF_MASK  0x40U
#define AW8898_POWER1_VREF_SHIFT 0x06U

#define AW8898_POWER1_AINL_MASK  0x20U
#define AW8898_POWER1_AINL_SHIFT 0x05U

#define AW8898_POWER1_AINR_MASK  0x10U
#define AW8898_POWER1_AINR_SHIFT 0x04U

#define AW8898_POWER1_ADCL_MASK  0x08U
#define AW8898_POWER1_ADCL_SHIFT 0x03U

#define AW8898_POWER1_ADCR_MASK  0x0U
#define AW8898_POWER1_ADCR_SHIFT 0x02U

#define AW8898_POWER1_MICB_MASK  0x02U
#define AW8898_POWER1_MICB_SHIFT 0x01U

#define AW8898_POWER1_DIGENB_MASK  0x01U
#define AW8898_POWER1_DIGENB_SHIFT 0x00U

/*! @brief AW8898_POWER2 */
#define AW8898_POWER2_DACL_MASK  0x100U
#define AW8898_POWER2_DACL_SHIFT 0x08U

#define AW8898_POWER2_DACR_MASK  0x80U
#define AW8898_POWER2_DACR_SHIFT 0x07U

#define AW8898_POWER2_LOUT1_MASK  0x40U
#define AW8898_POWER2_LOUT1_SHIFT 0x06U

#define AW8898_POWER2_ROUT1_MASK  0x20U
#define AW8898_POWER2_ROUT1_SHIFT 0x05U

#define AW8898_POWER2_SPKL_MASK  0x10U
#define AW8898_POWER2_SPKL_SHIFT 0x04U

#define AW8898_POWER2_SPKR_MASK  0x08U
#define AW8898_POWER2_SPKR_SHIFT 0x03U

#define AW8898_POWER3_LMIC_MASK   0x20U
#define AW8898_POWER3_LMIC_SHIFT  0x05U
#define AW8898_POWER3_RMIC_MASK   0x10U
#define AW8898_POWER3_RMIC_SHIFT  0x04U
#define AW8898_POWER3_LOMIX_MASK  0x08U
#define AW8898_POWER3_LOMIX_SHIFT 0x03U
#define AW8898_POWER3_ROMIX_MASK  0x04U
#define AW8898_POWER3_ROMIX_SHIFT 0x02U
/*! @brief AW8898 I2C address. */
#define AW8898_I2C_ADDR 0x34
/*! @brief AW8898 I2C baudrate */
#define AW8898_I2C_BAUDRATE (100000U)
/*! @brief AW8898 maximum volume value */
#define AW8898_ADC_MAX_VOLUME_vALUE       0xFFU
#define AW8898_DAC_MAX_VOLUME_vALUE       0xFFU
#define AW8898_HEADPHONE_MAX_VOLUME_vALUE 0xFFU
#define AW8898_HEADPHONE_MIN_VOLUME_vALUE 0x0U
#define AW8898_LINEIN_MAX_VOLUME_vALUE    0x3FU
#define AW8898_SPEAKER_MAX_VOLUME_vALUE   0x7FU
#define AW8898_SPEAKER_MIN_VOLUME_vALUE   0x30U

A module-bsp/board/rt1051/bellpx/bsp/audio/CodecAW8898.cpp => module-bsp/board/rt1051/bellpx/bsp/audio/CodecAW8898.cpp +201 -0
@@ 0,0 1,201 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "CodecAW8898.hpp"
#include "AW8898regs.hpp"
#include "AW8898driver.hpp"
#include "board/BoardDefinitions.hpp"

#include <log/log.hpp>

extern "C"
{
#include "FreeRTOS.h"
#include "task.h"
}

#include <cstdint>

using namespace drivers;
using namespace bsp::audio;

namespace
{
    constexpr auto ReadStatusRetries  = 5;
    constexpr auto OneByteAddressing  = 1;
    constexpr auto PositiveLogic      = 0;
    constexpr auto defaultVolumeLevel = 3.0f;
} // namespace

CodecAW8898::CodecAW8898()
{
    LOG_INFO("Initializing AW8898 audio codec");
    AW8898::i2cAddr.deviceAddress  = AW8898_I2C_ADDR;
    AW8898::i2cAddr.subAddressSize = OneByteAddressing; // AW8898 uses 1byte addressing
    AW8898::i2c                    = DriverI2C::Create(
        static_cast<I2CInstances>(BoardDefinitions::AUDIOCODEC_I2C),
        DriverI2CParams{.baudrate = static_cast<uint32_t>(BoardDefinitions::AUDIOCODEC_I2C_BAUDRATE)});

    AW8898::gpio =
        DriverGPIO::Create(static_cast<GPIOInstances>(BoardDefinitions::BELL_AUDIOCODEC_GPIO), DriverGPIOParams{});

    AW8898::gpio->ConfPin(
        DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Output,
                            .irqMode  = DriverGPIOPinParams::InterruptMode::NoIntmode,
                            .defLogic = PositiveLogic,
                            .pin      = static_cast<uint32_t>(BoardDefinitions::BELL_AUDIOCODEC_RSTN_PA_PIN)});

    AW8898::gpio->ConfPin(
        DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Input,
                            .irqMode  = DriverGPIOPinParams::InterruptMode::IntFallingEdge,
                            .defLogic = PositiveLogic,
                            .pin      = static_cast<uint32_t>(BoardDefinitions::BELL_AUDIOCODEC_INTN_PA_PIN)});

    AW8898::gpio->ClearPortInterrupts(1 << static_cast<uint32_t>(BoardDefinitions::BELL_AUDIOCODEC_INTN_PA_PIN));
    AW8898::gpio->DisableInterrupt(1 << static_cast<uint32_t>(BoardDefinitions::BELL_AUDIOCODEC_INTN_PA_PIN));

    AW8898::gpio->WritePin(static_cast<std::uint32_t>(BoardDefinitions::BELL_AUDIOCODEC_RSTN_PA_PIN),
                           AW8898::LogicLow); // reset chip
    vTaskDelay(pdMS_TO_TICKS(AW8898::OperationWaitTimeMS));
    AW8898::gpio->WritePin(static_cast<std::uint32_t>(BoardDefinitions::BELL_AUDIOCODEC_RSTN_PA_PIN),
                           AW8898::LogicHigh); // clear reset
    vTaskDelay(pdMS_TO_TICKS(AW8898::OperationWaitTimeMS));

    LOG_DEBUG("Probing AW8898 ...");
    auto ret = Probe();
    LOG_DEBUG("AW8898 Probe: 0x%04lX", ret.value());
}

CodecAW8898::~CodecAW8898()
{
    Reset();
}

CodecRetCode CodecAW8898::Start(const CodecParams &param)
{
    CodecParamsAW8898 params;
    params.opCmd      = static_cast<CodecParamsAW8898::Cmd>(param.opCmd);
    params.outVolume  = param.outVolume;
    params.sampleRate = static_cast<CodecParamsAW8898::SampleRate>(param.sampleRate);

    AW8898::Init(params.MonoStereoToCodecChsel(), params.SampleRateToCodecFreq());

    // Store param configuration
    currentParams = params;

    auto currVol = currentParams.outVolume;
    // remove this once volume control in application is working
    currVol = defaultVolumeLevel;
    SetOutputVolume(currVol);

    AW8898::ReadAllReg();

    return CodecRetCode::Success;
}

CodecRetCode CodecAW8898::Pause()
{
    AW8898::Stop();

    return CodecRetCode::Success;
}

CodecRetCode CodecAW8898::Resume()
{
    AW8898::Start();

    return CodecRetCode::Success;
}

CodecRetCode CodecAW8898::Stop()
{
    AW8898::Stop();
    return CodecRetCode::Success;
}

CodecRetCode CodecAW8898::Ioctrl(const CodecParams &param)
{

    const CodecParamsAW8898 &params = static_cast<const CodecParamsAW8898 &>(param);

    CodecRetCode ret = CodecRetCode::Success;

    switch (params.opCmd) {
    case CodecParamsAW8898::Cmd::SetOutVolume:
        ret = SetOutputVolume(params.outVolume);
        break;

    case CodecParamsAW8898::Cmd::SetInGain:
        ret = CodecRetCode::Success;
        break;
    case CodecParamsAW8898::Cmd::SetInput:
        ret = CodecRetCode::Success;
        break;
    case CodecParamsAW8898::Cmd::SetOutput:
        ret = CodecRetCode::Success;
        break;
    case CodecParamsAW8898::Cmd::MicBiasCtrl:
        ret = CodecRetCode::Success;
        break;
    case CodecParamsAW8898::Cmd::Reset:
        ret = Reset();
        break;
    case CodecParamsAW8898::Cmd::SetMute:
        ret = SetMute(true);
        break;
    default:
        break;
    }

    return ret;
}

std::uint8_t CodecAW8898::VolumeTo8Bit(const float vol)
{
    static constexpr auto maxVolumeLevel  = 10.0f;
    static constexpr auto conversionRatio = static_cast<float>(UINT8_MAX) / maxVolumeLevel;

    if (vol < 0) {
        return 0;
    }

    if (vol > maxVolumeLevel) {
        return UINT8_MAX;
    }

    return static_cast<uint8_t>(conversionRatio * vol);
}

CodecRetCode CodecAW8898::SetOutputVolume(const float vol)
{
    uint8_t mute = 0;

    // If volume set to 0 then mute output
    AW8898::RunMute(vol == 0); //(PWMCTRL.HMUTE=0) - disable mute

    AW8898::SetVolume(VolumeTo8Bit(vol));
    currentParams.outVolume = vol;
    return CodecRetCode::Success;
}

CodecRetCode CodecAW8898::Reset()
{
    AW8898::HwReset();
    return CodecRetCode::Success;
}

CodecRetCode CodecAW8898::SetMute(const bool enable)
{
    AW8898::RunMute(enable);
    return CodecRetCode::Success;
}

std::optional<uint32_t> CodecAW8898::Probe()
{
    if (AW8898::ReadChipid() == kStatus_Success) {
        return AW8898::AW8898_CHIP_ID;
    }
    else {
        return std::nullopt;
    }
}

A module-bsp/board/rt1051/bellpx/bsp/audio/CodecAW8898.hpp => module-bsp/board/rt1051/bellpx/bsp/audio/CodecAW8898.hpp +131 -0
@@ 0,0 1,131 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "AW8898driver.hpp"

#include <bsp/audio/Codec.hpp>

extern "C"
{
#include "fsl_common.h"
}

#include <cstdint>

class CodecParamsAW8898 : public CodecParams
{
  public:
    enum class Cmd
    {
        SetOutVolume,
        SetInGain,
        SetMute,
        SetOutput,
        SetInput,
        Reset,
        MicBiasCtrl,
        None
    };

    enum class SampleRate
    {
        Rate8KHz   = 8000,
        Rate16KHz  = 16000,
        Rate44K1Hz = 44100,
        Rate48KHz  = 48000,
        Rate32KHz  = 32000,
        Rate96KHz  = 96000,
        Invalid
    };

    enum class MonoStereo
    {
        Left,
        Right,
        Mono
    };

    bsp::audio::AW8898::aw_i2s_channel MonoStereoToCodecChsel() const
    {
        switch (monoStereo) {
        case MonoStereo::Left:
            return bsp::audio::AW8898::aw_i2s_channel::CHSEL_LEFT;
        case MonoStereo::Right:
            return bsp::audio::AW8898::aw_i2s_channel::CHSEL_RIGHT;
        default:
            return bsp::audio::AW8898::aw_i2s_channel::CHSEL_MONO;
        }
    }

    bsp::audio::AW8898::aw_i2s_frequency SampleRateToCodecFreq() const
    {
        switch (sampleRate) {
        case SampleRate::Rate8KHz:
            return bsp::audio::AW8898::aw_i2s_frequency::FREQUENCY_08K;
        case SampleRate::Rate16KHz:
            return bsp::audio::AW8898::aw_i2s_frequency::FREQUENCY_16K;
        case SampleRate::Rate32KHz:
            return bsp::audio::AW8898::aw_i2s_frequency::FREQUENCY_32K;
        case SampleRate::Rate44K1Hz:
            return bsp::audio::AW8898::aw_i2s_frequency::FREQUENCY_44K;
        case SampleRate::Rate48KHz:
            return bsp::audio::AW8898::aw_i2s_frequency::FREQUENCY_48K;
        default:
            return bsp::audio::AW8898::aw_i2s_frequency::FREQUENCY_44K;
        }
    }

    uint32_t GetSampleRateVal()
    {
        switch (sampleRate) {
        case SampleRate::Rate8KHz:
            return 8000;
        case SampleRate::Rate16KHz:
            return 16000;
        case SampleRate::Rate32KHz:
            return 32000;
        case SampleRate::Rate44K1Hz:
            return 44100;
        case SampleRate::Rate48KHz:
            return 48000;
        case SampleRate::Rate96KHz:
            return 96000;
        default:
            return 0;
        }
    }

    Cmd opCmd             = Cmd::None;
    float outVolume       = 0;
    MonoStereo monoStereo = MonoStereo::Mono;
    SampleRate sampleRate = SampleRate ::Rate44K1Hz;
};

class CodecAW8898 : public Codec
{
  public:
    CodecAW8898();
    ~CodecAW8898();

    std::optional<uint32_t> Probe() override final;

    CodecRetCode Start(const CodecParams &param) override final;

    CodecRetCode Pause() override final;

    CodecRetCode Resume() override final;

    CodecRetCode Stop() override final;

    CodecRetCode Ioctrl(const CodecParams &param) override final;

  private:
    CodecParamsAW8898 currentParams;

    std::uint8_t VolumeTo8Bit(const float vol);
    CodecRetCode SetOutputVolume(const float vol);
    CodecRetCode SetMute(const bool enable);
    CodecRetCode Reset();
};

A module-bsp/board/rt1051/bellpx/dma_config.h => module-bsp/board/rt1051/bellpx/dma_config.h +79 -0
@@ 0,0 1,79 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#ifndef MODULE_BSP_BOARD_RT1051_EINK_DMA_CONFIG_H_
#define MODULE_BSP_BOARD_RT1051_EINK_DMA_CONFIG_H_

#ifdef __cplusplus
extern "C"
{
#endif

/*
 *   **********************************************************************************************************************
 *   * *
 *   *                                              DMA FOR EINK *
 *   * *
 *   **********************************************************************************************************************
 */

/**
 *   Eink SPI TX DMA config
 */
#define BSP_EINK_LPSPI_DMA_TX_DMAMUX_BASE DMAMUX
#define BSP_EINK_LPSPI_DMA_TX_DMA_BASE    DMA0
#define BSP_EINK_LPSPI_DMA_TX_PERI_SEL    (uint8_t) kDmaRequestMuxLPSPI1Tx
#define BSP_EINK_LPSPI_DMA_TX_CH          0

/**
 *   Eink SPI RX DMA config
 */
#define BSP_EINK_LPSPI_DMA_RX_DMAMUX_BASE DMAMUX
#define BSP_EINK_LPSPI_DMA_RX_DMA_BASE    DMA0
#define BSP_EINK_LPSPI_DMA_RX_PERI_SEL    (uint8_t) kDmaRequestMuxLPSPI1Rx
#define BSP_EINK_LPSPI_DMA_RX_CH          1

    /*
     *   **********************************************************************************************************************
     *   * *
     *   *                                              DMA FOR CELLULAR *
     *   * *
     *   **********************************************************************************************************************
     */

    /* DMA */

#define BSP_CELLULAR_AUDIO_SAIx_DMA_TX_SOURCE kDmaRequestMuxSai1Tx
#define BSP_CELLULAR_AUDIO_SAIx_DMA_RX_SOURCE kDmaRequestMuxSai1Rx

/*
 *   **********************************************************************************************************************
 *   * *
 *   *                                              DMA FOR AUDIOCODEC *
 *   * *
 *   **********************************************************************************************************************
 */
#define BSP_AUDIOCODEC_SAIx_DMA_TX_SOURCE kDmaRequestMuxSai1Tx
#define BSP_AUDIOCODEC_SAIx_DMA_RX_SOURCE kDmaRequestMuxSai1Rx

/*
 *   **********************************************************************************************************************
 *   * *
 *   *                                              DMA FOR BLUETOOTH *
 *   * *
 *   **********************************************************************************************************************
 */
#define BSP_BLUETOOTH_UART_TX_DMA_DMAMUX_BASE DMAMUX
#define BSP_BLUETOOTH_UART_TX_DMA_BASE        DMA0
#define BSP_BLUETOOTH_UART_TX_DMA_CH          8

    /**
     * @brief This function initializes the entire DMA peripheral
     */
    void BOARD_InitDMA();

#ifdef __cplusplus
}
#endif

#endif /* MODULE_BSP_BOARD_RT1051_EINK_DMA_CONFIG_H_ */

M module-bsp/board/rt1051/bellpx/pin_mux.c => module-bsp/board/rt1051/bellpx/pin_mux.c +32 -0
@@ 1030,6 1030,38 @@ void PINMUX_InitAudioCodec(void)
                        PAD_CONFIG_DRIVER_STRENGTH_LVL_1 | PAD_CONFIG_SELECT_PULL | PAD_CONFIG_PULL_UP_100kOhm);
    IOMUXC_SetPinConfig(PINMUX_AUDIOCODEC_SAIx_TX_SYNC, /* GPIO_AD_B1_15 PAD functional properties : */
                        PAD_CONFIG_DRIVER_STRENGTH_LVL_1 | PAD_CONFIG_SELECT_PULL | PAD_CONFIG_PULL_UP_100kOhm);

    IOMUXC_SetPinMux(PINMUX_AUDIOCODEC_SCL,
                     1U); /* Software Input On Field: Input Path is determined by functionality */

    IOMUXC_SetPinConfig(PINMUX_AUDIOCODEC_SCL,

                        PAD_CONFIG_SLEW_RATE_SLOW | PAD_CONFIG_DRIVER_STRENGTH_LVL_6 |
                            PAD_CONFIG_SPEED_MEDIUM_2_100MHz | PAD_CONFIG_PULL_KEEPER_ENABLED |
                            PAD_CONFIG_SELECT_KEEPER | PAD_CONFIG_PULL_UP_22kOhm);

    IOMUXC_SetPinMux(PINMUX_AUDIOCODEC_SDA,
                     1U); /* Software Input On Field: Input Path is determined by functionality */

    IOMUXC_SetPinConfig(PINMUX_AUDIOCODEC_SDA,

                        PAD_CONFIG_SLEW_RATE_SLOW | PAD_CONFIG_DRIVER_STRENGTH_LVL_6 |
                            PAD_CONFIG_SPEED_MEDIUM_2_100MHz | PAD_CONFIG_PULL_KEEPER_ENABLED |
                            PAD_CONFIG_SELECT_KEEPER | PAD_CONFIG_PULL_UP_22kOhm);

    IOMUXC_SetPinMux(PINMUX_AUDIOCODEC_RSTN_PA, 0U);
    IOMUXC_SetPinConfig(PINMUX_AUDIOCODEC_RSTN_PA,

                        PAD_CONFIG_SLEW_RATE_SLOW | PAD_CONFIG_DRIVER_STRENGTH_LVL_6 |
                            PAD_CONFIG_SPEED_MEDIUM_2_100MHz | PAD_CONFIG_PULL_KEEPER_ENABLED |
                            PAD_CONFIG_SELECT_KEEPER | PAD_CONFIG_PULL_UP_22kOhm);

    IOMUXC_SetPinMux(PINMUX_AUDIOCODEC_INTN_PA, 0U);
    IOMUXC_SetPinConfig(PINMUX_AUDIOCODEC_INTN_PA,

                        PAD_CONFIG_SLEW_RATE_SLOW | PAD_CONFIG_DRIVER_STRENGTH_LVL_6 |
                            PAD_CONFIG_SPEED_MEDIUM_2_100MHz | PAD_CONFIG_PULL_KEEPER_ENABLED | PAD_CONFIG_SELECT_PULL |
                            PAD_CONFIG_PULL_UP_100kOhm);
}

void PINMUX_InitEINK(void)

M module-bsp/board/rt1051/bsp/audio/Codec.hpp => module-bsp/board/rt1051/bsp/audio/Codec.hpp +67 -0
@@ 10,6 10,73 @@
class CodecParams
{
  public:
    enum class SampleRate
    {
        Rate8KHz   = 8000,
        Rate16KHz  = 16000,
        Rate44K1Hz = 44100,
        Rate48KHz  = 48000,
        Rate32KHz  = 32000,
        Rate96KHz  = 96000,
        Invalid
    };

    enum class Cmd
    {
        SetOutVolume,
        SetInGain,
        SetMute,
        SetOutput,
        SetInput,
        Reset,
        MicBiasCtrl,
        None
    };

    static SampleRate ValToSampleRate(uint32_t rate)
    {
        switch (rate) {
        case 8000:
            return SampleRate ::Rate8KHz;
        case 16000:
            return SampleRate::Rate16KHz;
        case 32000:
            return SampleRate::Rate32KHz;
        case 44100:
            return SampleRate::Rate44K1Hz;
        case 48000:
            return SampleRate::Rate48KHz;
        case 96000:
            return SampleRate::Rate96KHz;
        default:
            return SampleRate ::Invalid;
        }
    }

    uint32_t GetSampleRateVal()
    {
        switch (sampleRate) {
        case SampleRate::Rate8KHz:
            return 8000;
        case SampleRate::Rate16KHz:
            return 16000;
        case SampleRate::Rate32KHz:
            return 32000;
        case SampleRate::Rate44K1Hz:
            return 44100;
        case SampleRate::Rate48KHz:
            return 48000;
        case SampleRate::Rate96KHz:
            return 96000;
        default:
            return 0;
        }
    }

    Cmd opCmd             = Cmd::None;
    float outVolume       = 0;
    float inGain          = 0;
    SampleRate sampleRate = SampleRate ::Rate44K1Hz;
};

enum class CodecRetCode

M module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp => module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp +1 -68
@@ 10,33 10,10 @@
class CodecParamsMAX98090 : public CodecParams
{
  public:
    enum class Cmd
    {
        SetOutVolume,
        SetInGain,
        SetMute,
        SetOutput,
        SetInput,
        Reset,
        MicBiasCtrl,
        None
    };

    enum class SampleRate
    {
        Rate8KHz   = 8000,
        Rate16KHz  = 16000,
        Rate44K1Hz = 44100,
        Rate48KHz  = 48000,
        Rate32KHz  = 32000,
        Rate96KHz  = 96000,
        Invalid
    };

    enum class MonoStereo
    {
        Mono,
        Stereoq
        Stereo
    };

    enum class DigitalMicrophoneCompensationFilter


@@ 83,55 60,11 @@ class CodecParamsMAX98090 : public CodecParams
        None
    };

    static SampleRate ValToSampleRate(uint32_t rate)
    {
        switch (rate) {
        case 8000:
            return SampleRate ::Rate8KHz;
        case 16000:
            return SampleRate::Rate16KHz;
        case 32000:
            return SampleRate::Rate32KHz;
        case 44100:
            return SampleRate::Rate44K1Hz;
        case 48000:
            return SampleRate::Rate48KHz;
        case 96000:
            return SampleRate::Rate96KHz;
        default:
            return SampleRate ::Invalid;
        }
    }

    uint32_t GetSampleRateVal()
    {
        switch (sampleRate) {
        case SampleRate::Rate8KHz:
            return 8000;
        case SampleRate::Rate16KHz:
            return 16000;
        case SampleRate::Rate32KHz:
            return 32000;
        case SampleRate::Rate44K1Hz:
            return 44100;
        case SampleRate::Rate48KHz:
            return 48000;
        case SampleRate::Rate96KHz:
            return 96000;
        default:
            return 0;
        }
    }

    Cmd opCmd             = Cmd::None;
    float outVolume       = 0;
    float inGain          = 0;
    bool muteEnable       = false;
    bool resetEnable      = false;
    bool micBiasEnable    = false;
    InputPath inputPath   = InputPath::None;
    OutputPath outputPath = OutputPath::None;
    SampleRate sampleRate = SampleRate ::Rate44K1Hz;
};

class CodecMAX98090 : public Codec

M module-bsp/board/rt1051/common/audio.hpp => module-bsp/board/rt1051/common/audio.hpp +4 -4
@@ 12,10 12,10 @@
#include <memory>
#include <cstdint>

namespace bsp
namespace bsp::audio
{
    void audioInit();
    void audioDeinit();
    void init();
    void deinit();

    struct AudioConfig
    {


@@ 30,4 30,4 @@ namespace bsp

        static AudioConfig *get();
    };
}; // namespace bsp
}; // namespace bsp::audio

M module-bsp/board/rt1051/puretx/CMakeLists.txt => module-bsp/board/rt1051/puretx/CMakeLists.txt +3 -1
@@ 16,11 16,13 @@ target_sources(
        bsp/eink/eink_pin_config.cpp
        bsp/keyboard/keyboard.cpp
        bsp/lpm/PowerProfile.cpp

        audio.cpp
        pin_mux.c
        clock_config.cpp
        irq_gpio.cpp
        debug_console.cpp
        

    PUBLIC
        eink-config.h
        board/pin_mux.h

R module-bsp/board/rt1051/common/audio.cpp => module-bsp/board/rt1051/puretx/audio.cpp +5 -5
@@ 11,12 11,12 @@ extern "C"
#include "dma_config.h"
}

using namespace bsp;
using namespace bsp::audio;
using namespace drivers;

bsp::AudioConfig audioConfig;
bsp::audio::AudioConfig audioConfig;

void bsp::audioInit()
void bsp::audio::init()
{
    audioConfig.pllAudio =
        DriverPLL::Create(static_cast<PLLInstances>(BoardDefinitions ::AUDIO_PLL), DriverPLLParams{});


@@ 51,7 51,7 @@ void bsp::audioInit()
    SAI_RxInit(BOARD_AUDIOCODEC_SAIx, &audioConfig.config);
}

void bsp::audioDeinit()
void bsp::audio::deinit()
{
    memset(&audioConfig.config, 0, sizeof(audioConfig.config));
    SAI_Deinit(BOARD_AUDIOCODEC_SAIx);


@@ 68,7 68,7 @@ void bsp::audioDeinit()
    audioConfig.pllAudio.reset();
}

AudioConfig *bsp::AudioConfig::get()
AudioConfig *AudioConfig::get()
{
    return &audioConfig;
}

R module-bsp/board/rt1051/common/dma_config.h => module-bsp/board/rt1051/puretx/dma_config.h +0 -0