// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "headset.hpp" #include "BoardDefinitions.hpp" #include "DriverI2C.hpp" #include "DriverGPIO.hpp" #include "fsl_common.h" #include "timers.h" namespace bsp { namespace headset { using namespace drivers; static constexpr uint8_t HEADSET_I2C_ADDR = 0x3B; static constexpr uint8_t HEADSET_INT_REG_ADDR = 0x01; static constexpr uint8_t HEADSET_INT_DIS_ADDR = 0x03; static constexpr uint8_t HEADSET_DEV_SET_ADDR = 0x04; static constexpr uint8_t HEADSET_DET_RES_ADDR = 0x0B; static constexpr uint8_t HEADSET_INT_DIS_INT_DIS = 1 << 3; static constexpr uint8_t HEADSET_INT_DIS_INT_ENA = 0 << 3; static constexpr uint8_t HEADSET_INT_DIS_ADC_DIS = 1 << 2; static constexpr uint8_t HEADSET_INT_DIS_ADC_ENA = 0 << 2; static constexpr uint8_t HEADSET_INT_DIS_DC_DIS = 1 << 1; static constexpr uint8_t HEADSET_INT_DIS_DC_ENA = 0 << 1; static constexpr uint8_t HEADSET_INT_DIS_INS_DIS = 1 << 0; static constexpr uint8_t HEADSET_INT_DIS_INS_ENA = 0 << 0; static constexpr uint8_t HEADSET_DEV_SET_DET_EN = 1 << 5; static constexpr uint8_t HEADSET_DEV_SET_DEB_1S = 0x06; static constexpr uint16_t HEADSET_POLL_INTERVAL_MS = 2500; static std::shared_ptr i2c; static std::shared_ptr gpio; static drivers::I2CAddress i2cAddr = {.deviceAddress = HEADSET_I2C_ADDR, .subAddressSize = 0x01}; static TimerHandle_t timerHandle; static xQueueHandle qHandleIrq = nullptr; static bool HeadsetInserted = false; static bool ReadInsertionStatus() { uint8_t reg; bool ret = false; i2cAddr.subAddress = HEADSET_INT_REG_ADDR; auto err = i2c->Read(i2cAddr, (uint8_t *)®, 1); i2cAddr.subAddress = HEADSET_DET_RES_ADDR; i2c->Read(i2cAddr, (uint8_t *)®, 1); if (((reg & 0x08) == 0) && (HeadsetInserted == true)) { HeadsetInserted = false; LOG_INFO("Headset removed"); gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0); ret = true; } if (((reg & 0x08) != 0) && (HeadsetInserted == false)) { HeadsetInserted = true; LOG_INFO("Headset inserted"); if ((reg & 0x01) != 0) { LOG_INFO("Headset 3-pole detected"); gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0); } if ((reg & 0x02) != 0) { LOG_INFO("Headset 4-pole OMTP detected"); gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 1); } if ((reg & 0x04) != 0) { LOG_INFO("Headset 4-pole Standard detected"); gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 1); } ret = true; } return ret; } static void TimerHandler(TimerHandle_t xTimer) { if (qHandleIrq != nullptr) { uint8_t val = 0x01; xQueueSend(qHandleIrq, &val, 0); } } status_t Init(xQueueHandle qHandle) { i2c = DriverI2C::Create( static_cast(BoardDefinitions::HEADSET_I2C), DriverI2CParams{.baudrate = static_cast(BoardDefinitions::HEADSET_I2C_BAUDRATE)}); gpio = DriverGPIO::Create(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_GPIO), DriverGPIOParams{}); gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, .defLogic = 0, .pin = static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN)}); qHandleIrq = qHandle; HeadsetInserted = false; gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0); uint8_t reg = HEADSET_INT_DIS_INT_ENA | HEADSET_INT_DIS_ADC_ENA | HEADSET_INT_DIS_DC_ENA | HEADSET_INT_DIS_INS_ENA; i2cAddr.subAddress = HEADSET_INT_DIS_ADDR; i2c->Write(i2cAddr, (uint8_t *)®, 1); reg = HEADSET_DEV_SET_DET_EN | HEADSET_DEV_SET_DEB_1S; i2cAddr.subAddress = HEADSET_DEV_SET_ADDR; i2c->Write(i2cAddr, (uint8_t *)®, 1); if (timerHandle == nullptr) { timerHandle = xTimerCreate("HeadsetTimer", pdMS_TO_TICKS(HEADSET_POLL_INTERVAL_MS), true, nullptr, TimerHandler); if (timerHandle == nullptr) { LOG_FATAL("Could not create the timer for Headset insertion/removal detection"); return kStatus_Fail; } } xTimerStart(timerHandle, HEADSET_POLL_INTERVAL_MS); return kStatus_Success; } bool Handler(uint8_t notification) { if (notification == 0x01) { return ReadInsertionStatus(); } return false; } bool IsInserted() { return HeadsetInserted; } status_t Deinit() { qHandleIrq = nullptr; HeadsetInserted = false; i2c.reset(); gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0); return kStatus_Success; } } // namespace headset } // namespace bsp