@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "headset.hpp"
@@ 21,6 21,10 @@ namespace bsp
static constexpr uint8_t HEADSET_DEV_SET_ADDR = 0x04;
static constexpr uint8_t HEADSET_DET_RES_ADDR = 0x0B;
+ static constexpr uint8_t HEADSET_DET_THRESH1_ADDR = 0x0D;
+ static constexpr uint8_t HEADSET_DET_THRESH2_ADDR = 0x0E;
+ static constexpr uint8_t HEADSET_DET_THRESH3_ADDR = 0x0F;
+
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;
@@ 30,6 34,10 @@ namespace bsp
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_DET_THRESH1_VAL = 0x22;
+ static constexpr uint8_t HEADSET_DET_THRESH2_VAL = 0x23;
+ static constexpr uint8_t HEADSET_DET_THRESH3_VAL = 0x6C;
+
static constexpr uint8_t HEADSET_DEV_SET_DET_EN = 1 << 5;
static constexpr uint8_t HEADSET_DEV_SET_DEB_1S = 0x06;
@@ 99,15 107,23 @@ namespace bsp
if (qHandleIrq != nullptr) {
uint8_t val = 0x01;
xQueueSend(qHandleIrq, &val, 0);
+ xTimerDelete(xTimer, 0);
}
}
- status_t Init(xQueueHandle qHandle)
+ BaseType_t headset_IRQHandler()
{
- i2c = DriverI2C::Create(
- static_cast<I2CInstances>(BoardDefinitions::HEADSET_I2C),
- DriverI2CParams{.baudrate = static_cast<uint32_t>(BoardDefinitions::HEADSET_I2C_BAUDRATE)});
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ if (qHandleIrq != nullptr) {
+ uint8_t val = 0x01;
+ xQueueSendFromISR(qHandleIrq, &val, &xHigherPriorityTaskWoken);
+ }
+ return xHigherPriorityTaskWoken;
+ }
+ status_t Init(xQueueHandle qHandle)
+ {
+ // Microphone jack external GPIO pin configuration
gpio = DriverGPIO::Create(static_cast<GPIOInstances>(BoardDefinitions::MIC_BIAS_DRIVER_GPIO),
DriverGPIOParams{});
@@ 116,25 132,59 @@ namespace bsp
.defLogic = 0,
.pin = static_cast<uint32_t>(BoardDefinitions::MIC_BIAS_DRIVER_EN)});
+ gpio->WritePin(static_cast<uint32_t>(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0);
+
+ // Jack detection I2C and GPIO configuration
+
+ // Init input JACKDET IRQ
+ gpio->ClearPortInterrupts(1 << static_cast<uint32_t>(BoardDefinitions::HEADSET_IRQ_PIN));
+ gpio->DisableInterrupt(1 << static_cast<uint32_t>(BoardDefinitions::HEADSET_IRQ_PIN));
+
+ gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Input,
+ .irqMode = DriverGPIOPinParams::InterruptMode::IntFallingEdge,
+ .defLogic = 0,
+ .pin = static_cast<uint32_t>(BoardDefinitions::HEADSET_IRQ_PIN)});
+
+ // Enable GPIO pin interrupt
+ gpio->EnableInterrupt(1 << static_cast<uint32_t>(BoardDefinitions::HEADSET_IRQ_PIN));
+
+ i2c = DriverI2C::Create(
+ static_cast<I2CInstances>(BoardDefinitions::HEADSET_I2C),
+ DriverI2CParams{.baudrate = static_cast<uint32_t>(BoardDefinitions::HEADSET_I2C_BAUDRATE)});
+
qHandleIrq = qHandle;
HeadsetInserted = false;
MicrophoneInserted = false;
- gpio->WritePin(static_cast<uint32_t>(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0);
-
+ // Turn off DC and ADC conversion interrupt
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);
+ i2c->Write(i2cAddr, static_cast<uint8_t *>(®), 1);
+ // Set Insertion de-bounce time to 1s, enable auto-detection
reg = HEADSET_DEV_SET_DET_EN | HEADSET_DEV_SET_DEB_1S;
i2cAddr.subAddress = HEADSET_DEV_SET_ADDR;
- i2c->Write(i2cAddr, (uint8_t *)®, 1);
+ i2c->Write(i2cAddr, static_cast<uint8_t *>(®), 1);
+
+ // Set detection thresholds
+ reg = HEADSET_DET_THRESH1_VAL;
+ i2cAddr.subAddress = HEADSET_DET_THRESH1_ADDR;
+ i2c->Write(i2cAddr, static_cast<uint8_t *>(®), 1);
+
+ reg = HEADSET_DET_THRESH2_VAL;
+ i2cAddr.subAddress = HEADSET_DET_THRESH2_ADDR;
+ i2c->Write(i2cAddr, static_cast<uint8_t *>(®), 1);
+
+ reg = HEADSET_DET_THRESH3_VAL;
+ i2cAddr.subAddress = HEADSET_DET_THRESH3_ADDR;
+ i2c->Write(i2cAddr, static_cast<uint8_t *>(®), 1);
if (timerHandle == nullptr) {
timerHandle =
- xTimerCreate("HeadsetTimer", pdMS_TO_TICKS(HEADSET_POLL_INTERVAL_MS), true, nullptr, TimerHandler);
+ xTimerCreate("HeadsetTimer", pdMS_TO_TICKS(HEADSET_POLL_INTERVAL_MS), false, nullptr, TimerHandler);
if (timerHandle == nullptr) {
LOG_FATAL("Could not create the timer for Headset insertion/removal detection");
return kStatus_Fail;
@@ 12,6 12,7 @@
#include "bsp/battery-charger/battery_charger.hpp"
#include "bsp/cellular/bsp_cellular.hpp"
#include "bsp/keyboard/keyboard.hpp"
+#include "bsp/headset/headset.hpp"
#include "bsp/BoardDefinitions.hpp"
#include "bsp/magnetometer/magnetometer.hpp"
#include "bsp/light_sensor/light_sensor.hpp"
@@ 149,6 150,7 @@ namespace bsp
}
if (irq_mask & (1 << BOARD_JACKDET_IRQ_GPIO_PIN)) {
+ xHigherPriorityTaskWoken |= bsp::headset::headset_IRQHandler();
}
if (irq_mask & (1 << BSP_CELLULAR_RI_PIN)) {
@@ 43,10 43,10 @@ enum class BoardDefinitions
KEYBOARD_IRQ_PIN = 28,
KEYBOARD_RESET_PIN = 29,
- HEADSET_I2C_BAUDRATE = AUDIOCODEC_I2C_BAUDRATE,
- HEADSET_I2C = AUDIOCODEC_I2C,
- HEADSET_GPIO = static_cast<int >(drivers::GPIOInstances ::GPIO_2),
- HEADSET_IRQ_PIN = 30,
+ HEADSET_I2C_BAUDRATE = AUDIOCODEC_I2C_BAUDRATE,
+ HEADSET_I2C = AUDIOCODEC_I2C,
+ HEADSET_GPIO = static_cast<int >(drivers::GPIOInstances ::GPIO_2),
+ HEADSET_IRQ_PIN = 30,
BATTERY_CHARGER_I2C_BAUDRATE = AUDIOCODEC_I2C_BAUDRATE,
BATTERY_CHARGER_I2C = AUDIOCODEC_I2C,