~aleteoryx/muditaos

caa5d70e8450462c341e95b3e22b76cff3614bc6 — Tigran Soghbatyan 4 years ago 285ca53
[BH-1169] Fix multiple issues with switches

Fix incorrect first latch switch
Fix missing first light click
Refactor switches code
M module-bsp/board/rt1051/bellpx/bsp/switches/switches.cpp => module-bsp/board/rt1051/bellpx/bsp/switches/switches.cpp +103 -82
@@ 34,7 34,7 @@ namespace bsp::bell_switches
    constexpr std::chrono::milliseconds contactOscillationTimeout{30ms};
    constexpr std::chrono::milliseconds centerKeyPressValidationTimeout{30ms};

    enum class DebounceTimerId : unsigned int
    enum class KeyId : unsigned int
    {
        leftSideSwitch = 0,
        rightSideSwitch,


@@ 48,11 48,10 @@ namespace bsp::bell_switches

    struct DebounceTimerState
    {
        const DebounceTimerId id{DebounceTimerId::Invalid};
        const NotificationSource notificationSource{NotificationSource::Invalid};
        const KeyId id{KeyId::Invalid};
        const std::shared_ptr<drivers::DriverGPIO> gpio;
        const BoardDefinitions pin{-1};
        KeyEvents lastState{KeyEvents::Pressed};
        volatile KeyEvents lastState{KeyEvents::Pressed};
        TimerHandle_t timer{nullptr};

        void createTimer(TimerCallback callback, const std::chrono::milliseconds timeout)


@@ 71,18 70,19 @@ namespace bsp::bell_switches
        bool changeFlag = false;

      public:
        void setPressed()
        static constexpr bool NO_STATE_CHANGE_INDICATION{false};
        void setPressed(bool changed = true)
        {
            cpp_freertos::LockGuard lock(latchFlagMutex);
            pressed    = true;
            changeFlag = true;
            changeFlag = changed;
        }

        void setReleased()
        void setReleased(bool changed = true)
        {
            cpp_freertos::LockGuard lock(latchFlagMutex);
            pressed    = false;
            changeFlag = true;
            changeFlag = changed;
        }

        bool isPressed()


@@ 105,12 105,60 @@ namespace bsp::bell_switches

    } latchEventFlag;

    static std::map<DebounceTimerId, DebounceTimerState> debounceTimers;
    static std::map<KeyId, DebounceTimerState> debounceTimers;

    static xQueueHandle qHandleIrq{};
    std::shared_ptr<DriverGPIO> gpio_sw;
    std::shared_ptr<DriverGPIO> gpio_wakeup;

    NotificationSource getNotificationSource(KeyId keyId, KeyEvents state)
    {
        auto val = NotificationSource::Invalid;
        if (state == KeyEvents::Released) {
            switch (keyId) {
            case KeyId::leftSideSwitch:
                val = NotificationSource::leftSideKeyRelease;
                break;
            case KeyId::rightSideSwitch:
                val = NotificationSource::rightSideKeyRelease;
                break;
            case KeyId::lightCenterSwitch:
                val = NotificationSource::lightCenterKeyRelease;
                break;
            case KeyId::latchSwitch:
                val = NotificationSource::latchKeyRelease;
                break;
            case KeyId::wakeup:
                val = NotificationSource::wakeupEventRelease;
                break;
            default:
                break;
            }
        }
        else {
            switch (keyId) {
            case KeyId::leftSideSwitch:
                val = NotificationSource::leftSideKeyPress;
                break;
            case KeyId::rightSideSwitch:
                val = NotificationSource::rightSideKeyPress;
                break;
            case KeyId::lightCenterSwitch:
                val = NotificationSource::lightCenterKeyPress;
                break;
            case KeyId::latchSwitch:
                val = NotificationSource::latchKeyPress;
                break;
            case KeyId::wakeup:
                val = NotificationSource::wakeupEvent;
                break;
            default:
                break;
            }
        }
        return val;
    }

    void debounceTimerCallback(TimerHandle_t timerHandle)
    {
        auto timerState                     = static_cast<DebounceTimerState *>(pvTimerGetTimerID(timerHandle));


@@ 119,43 167,17 @@ namespace bsp::bell_switches

        auto currentState = timerState->gpio->ReadPin(static_cast<uint32_t>(timerState->pin)) ? KeyEvents::Released
                                                                                              : KeyEvents::Pressed;

        if (currentState == timerState->lastState && qHandleIrq != nullptr) {
            if (currentState == KeyEvents::Pressed) {
                if (timerState->notificationSource == NotificationSource::latchKeyPress) {
            if (timerState->id == KeyId::latchSwitch) {
                if (currentState == KeyEvents::Pressed) {
                    latchEventFlag.setPressed();
                }
                auto val = static_cast<std::uint16_t>(timerState->notificationSource);
                xQueueSend(qHandleIrq, &val, 0);
                timerState->lastState = KeyEvents::Released;
            }
            else {
                if (timerState->notificationSource == NotificationSource::latchKeyPress) {
                else {
                    latchEventFlag.setReleased();
                }
                auto val = NotificationSource::Invalid;
                switch (timerState->notificationSource) {
                case NotificationSource::leftSideKeyPress:
                    val = NotificationSource::leftSideKeyRelease;
                    break;
                case NotificationSource::rightSideKeyPress:
                    val = NotificationSource::rightSideKeyRelease;
                    break;
                case NotificationSource::lightCenterKeyPress:
                    val = NotificationSource::lightCenterKeyRelease;
                    break;
                case NotificationSource::latchKeyPress:
                    val = NotificationSource::latchKeyRelease;
                    break;
                case NotificationSource::wakeupEvent:
                    val = NotificationSource::wakeupEventRelease;
                    break;
                default:
                    break;
                }
                xQueueSend(qHandleIrq, &val, 0);
                timerState->lastState = KeyEvents::Pressed;
            }
            auto val = static_cast<std::uint16_t>(getNotificationSource(timerState->id, currentState));
            xQueueSend(qHandleIrq, &val, 0);
        }

        timerState->gpio->EnableInterrupt(1U << static_cast<uint32_t>(timerState->pin));


@@ 172,7 194,7 @@ namespace bsp::bell_switches
                latchEventFlag.clearChangedMark();
            }
            else {
                auto val = static_cast<std::uint16_t>(timerState->notificationSource);
                auto val = static_cast<std::uint16_t>(getNotificationSource(timerState->id, KeyEvents::Released));
                xQueueSend(qHandleIrq, &val, 0);
            }
        }


@@ 192,21 214,26 @@ namespace bsp::bell_switches
        debounceTimers.insert({timerState.id, timerState});
        DebounceTimerState &state = debounceTimers.find(timerState.id)->second;

        if (timerState.notificationSource == NotificationSource::lightCenterKeyPress) {
        if (timerState.id == KeyId::lightCenterSwitch) {
            state.createTimer(debounceTimerCenterClickCallback, centerKeyPressValidationTimeout);
        }
        else if (timerState.notificationSource == NotificationSource::latchKeyPress) {
        else {
            state.createTimer(debounceTimerCallback, contactOscillationTimeout);
            state.lastState = getLatchState();
            if (state.lastState == KeyEvents::Released) {
                latchEventFlag.setReleased();
            }
            else {
                latchEventFlag.setPressed();
            }
        }
    }

    void addLatchDebounceTimer(DebounceTimerState timerState)
    {
        debounceTimers.insert({timerState.id, timerState});
        DebounceTimerState &state = debounceTimers.find(timerState.id)->second;

        state.createTimer(debounceTimerCallback, contactOscillationTimeout);
        state.lastState = getLatchState();
        if (state.lastState == KeyEvents::Released) {
            latchEventFlag.setReleased(LatchEventFlag::NO_STATE_CHANGE_INDICATION);
        }
        else {
            state.createTimer(debounceTimerCallback, contactOscillationTimeout);
            latchEventFlag.setPressed(LatchEventFlag::NO_STATE_CHANGE_INDICATION);
        }
    }



@@ 240,33 267,20 @@ namespace bsp::bell_switches
        configureSwitch(BoardDefinitions::BELL_SWITCHES_CENTER, DriverGPIOPinParams::InterruptMode::IntRisingEdge);
        configureSwitch(BoardDefinitions::BELL_WAKEUP, DriverGPIOPinParams::InterruptMode::IntFallingEdge);

        addDebounceTimer(DebounceTimerState{DebounceTimerId::leftSideSwitch,
                                            NotificationSource::leftSideKeyPress,
                                            gpio_sw,
                                            BoardDefinitions::BELL_SWITCHES_LEFT});
        addDebounceTimer(DebounceTimerState{DebounceTimerId::rightSideSwitch,
                                            NotificationSource::rightSideKeyPress,
                                            gpio_sw,
                                            BoardDefinitions::BELL_SWITCHES_RIGHT});
        addDebounceTimer(DebounceTimerState{DebounceTimerId::lightCenterSwitch,
                                            NotificationSource::lightCenterKeyPress,
                                            gpio_sw,
                                            BoardDefinitions::BELL_SWITCHES_CENTER});
        addDebounceTimer(DebounceTimerState{DebounceTimerId::latchSwitch,
                                            NotificationSource::latchKeyPress,
                                            gpio_sw,
                                            BoardDefinitions::BELL_SWITCHES_LATCH,
                                            KeyEvents::Released});
        addDebounceTimer(DebounceTimerState{
            DebounceTimerId::wakeup, NotificationSource::wakeupEvent, gpio_wakeup, BoardDefinitions::BELL_WAKEUP});
        addDebounceTimer(DebounceTimerState{KeyId::leftSideSwitch, gpio_sw, BoardDefinitions::BELL_SWITCHES_LEFT});
        addDebounceTimer(DebounceTimerState{KeyId::rightSideSwitch, gpio_sw, BoardDefinitions::BELL_SWITCHES_RIGHT});
        addDebounceTimer(DebounceTimerState{KeyId::lightCenterSwitch, gpio_sw, BoardDefinitions::BELL_SWITCHES_CENTER});
        addLatchDebounceTimer(DebounceTimerState{
            KeyId::latchSwitch, gpio_sw, BoardDefinitions::BELL_SWITCHES_LATCH, KeyEvents::Released});
        addDebounceTimer(DebounceTimerState{KeyId::wakeup, gpio_wakeup, BoardDefinitions::BELL_WAKEUP});

        if (getLatchState() == KeyEvents::Pressed) {
            latchEventFlag.setPressed();
            auto timerState = static_cast<DebounceTimerState *>(
                pvTimerGetTimerID(debounceTimers[DebounceTimerId::latchSwitch].timer));
            latchEventFlag.setPressed(LatchEventFlag::NO_STATE_CHANGE_INDICATION);
            auto timerState =
                static_cast<DebounceTimerState *>(pvTimerGetTimerID(debounceTimers[KeyId::latchSwitch].timer));
            timerState->lastState = KeyEvents::Released;
        }

        clearStartupLatchInterrupt();
        enableIRQ();

        return kStatus_Success;


@@ 288,13 302,14 @@ namespace bsp::bell_switches
        return kStatus_Success;
    }

    void getDebounceTimer(BaseType_t xHigherPriorityTaskWoken, DebounceTimerId timerId)
    void getDebounceTimer(BaseType_t xHigherPriorityTaskWoken, KeyId timerId)
    {
        if (debounceTimers.find(timerId) == debounceTimers.end()) {
            LOG_ERROR("Could not find debouncer timer for: %s", magic_enum::enum_name(timerId).data());
            return;
        }
        auto debounceTimerState = debounceTimers.at(timerId);
        DebounceTimerState &debounceTimerState = debounceTimers.at(timerId);
        auto temp                              = &debounceTimerState;
        debounceTimerState.gpio->DisableInterrupt(1U << static_cast<uint32_t>(debounceTimerState.pin));
        debounceTimerState.lastState = debounceTimerState.gpio->ReadPin(static_cast<uint32_t>(debounceTimerState.pin))
                                           ? KeyEvents::Released


@@ 307,21 322,21 @@ namespace bsp::bell_switches
    BaseType_t IRQHandler(uint32_t mask)
    {
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        auto timerId                        = DebounceTimerId::Invalid;
        auto timerId                        = KeyId::Invalid;

        gpio_sw->ClearPortInterrupts(1U << mask);

        if (mask & (1 << magic_enum::enum_integer(BoardDefinitions::BELL_SWITCHES_LEFT))) {
            timerId = DebounceTimerId::leftSideSwitch;
            timerId = KeyId::leftSideSwitch;
        }
        else if (mask & (1 << magic_enum::enum_integer(BoardDefinitions::BELL_SWITCHES_RIGHT))) {
            timerId = DebounceTimerId::rightSideSwitch;
            timerId = KeyId::rightSideSwitch;
        }
        else if (mask & (1 << magic_enum::enum_integer(BoardDefinitions::BELL_SWITCHES_CENTER))) {
            timerId = DebounceTimerId::lightCenterSwitch;
            timerId = KeyId::lightCenterSwitch;
        }
        else if (mask & (1 << magic_enum::enum_integer(BoardDefinitions::BELL_SWITCHES_LATCH))) {
            timerId = DebounceTimerId::latchSwitch;
            timerId = KeyId::latchSwitch;
        }

        getDebounceTimer(xHigherPriorityTaskWoken, timerId);


@@ 334,7 349,7 @@ namespace bsp::bell_switches
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        gpio_wakeup->ClearPortInterrupts(1U << static_cast<uint32_t>(BoardDefinitions::BELL_WAKEUP));

        getDebounceTimer(xHigherPriorityTaskWoken, DebounceTimerId::wakeup);
        getDebounceTimer(xHigherPriorityTaskWoken, KeyId::wakeup);

        return xHigherPriorityTaskWoken;
    }


@@ 426,4 441,10 @@ namespace bsp::bell_switches
        return latchEventFlag.isPressed();
    }

    void clearStartupLatchInterrupt()
    {
        // Knob sets up interrupt on startup because of hw design
        gpio_sw->ClearPortInterrupts(1 << static_cast<uint32_t>(BoardDefinitions::BELL_SWITCHES_LATCH));
    }

} // namespace bsp::bell_switches

M module-bsp/board/rt1051/bellpx/bsp/switches/switches.hpp => module-bsp/board/rt1051/bellpx/bsp/switches/switches.hpp +3 -0
@@ 24,4 24,7 @@ namespace bsp::bell_switches
    BaseType_t IRQHandler(uint32_t mask);

    BaseType_t wakeupIRQHandler();

    void clearStartupLatchInterrupt();

} // namespace bsp::bell_switches