~aleteoryx/muditaos

ref: 8d9719e8b9d3aa0f99af6f7405e63154e46a8d16 muditaos/module-bsp/board/rt1051/bsp/headset/headset.cpp -rw-r--r-- 5.9 KiB
8d9719e8 — Szymon Mroczek [EGD-3510] audio codec configuration for headset microphone (#1004) 5 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// 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<drivers::DriverI2C> i2c;
        static std::shared_ptr<drivers::DriverGPIO> 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 *)&reg, 1);

            i2cAddr.subAddress = HEADSET_DET_RES_ADDR;
            i2c->Read(i2cAddr, (uint8_t *)&reg, 1);

            if (((reg & 0x08) == 0) && (HeadsetInserted == true)) {
                HeadsetInserted = false;
                LOG_INFO("Headset removed");
                gpio->WritePin(static_cast<uint32_t>(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<uint32_t>(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0);
                }
                if ((reg & 0x02) != 0) {
                    LOG_INFO("Headset 4-pole OMTP detected");
                    gpio->WritePin(static_cast<uint32_t>(BoardDefinitions::MIC_BIAS_DRIVER_EN), 1);
                }
                if ((reg & 0x04) != 0) {
                    LOG_INFO("Headset 4-pole Standard detected");
                    gpio->WritePin(static_cast<uint32_t>(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<I2CInstances>(BoardDefinitions::HEADSET_I2C),
                DriverI2CParams{.baudrate = static_cast<uint32_t>(BoardDefinitions::HEADSET_I2C_BAUDRATE)});

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

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

            qHandleIrq = qHandle;

            HeadsetInserted = false;

            gpio->WritePin(static_cast<uint32_t>(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 *)&reg, 1);

            reg                = HEADSET_DEV_SET_DET_EN | HEADSET_DEV_SET_DEB_1S;
            i2cAddr.subAddress = HEADSET_DEV_SET_ADDR;
            i2c->Write(i2cAddr, (uint8_t *)&reg, 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<uint32_t>(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0);

            return kStatus_Success;
        }
    } // namespace headset
} // namespace bsp