C

Qt Quick Ultralite Automotive Cluster Demo

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial
#include "hmi_input.h"
#include "r_typedefs.h"
#include "r_gpio_api.h"
#include "r_bsp_hmi_knob.h"
#include "r_bsp_hmi_api.h"

template<HMIInputEvent::Type type, HMIInputEvent::Key keyCode>
static void keyEventHandler()
{
    HMIInput::instance().postEvent(HMIInputEvent(keyCode, type));
}

static void qulButtonLeftAction(void)
{
    uint8_t level = R_GPIO_ReadIntPin(BSP_BTN_LEFT_INTP);

    // The buttons are low-active
    if (level == 0u) {
        R_BSP_BtnAction(BSP_BTN_LEFT_PRESS);
    } else {
        R_BSP_BtnAction(BSP_BTN_LEFT_RELEASE);
    }
}

static void qulButtonUpAction(void)
{
    uint8_t level = R_GPIO_ReadIntPin(BSP_BTN_UP_INTP);

    if (level == 0u) {
        R_BSP_BtnAction(BSP_BTN_UP_PRESS);
    } else {
        R_BSP_BtnAction(BSP_BTN_UP_RELEASE);
    }
}

#if USE_FOUT_INSTEAD_BSP_BTN_DOWN != 1
static void qulButtonDownAction(void)
{
    uint8_t level = R_GPIO_ReadIntPin(BSP_BTN_DOWN_INTP);

    if (level == 0u) {
        R_BSP_BtnAction(BSP_BTN_DOWN_PRESS);
    } else {
        R_BSP_BtnAction(BSP_BTN_DOWN_RELEASE);
    }
}
#endif // USE_FOUT_INSTEAD_BSP_BTN_DOWN

static void qulButtonRightAction(void)
{
    uint8_t level = R_GPIO_ReadIntPin(BSP_BTN_RIGHT_INTP);

    if (level == 0u) {
        R_BSP_BtnAction(BSP_BTN_RIGHT_PRESS);
    } else {
        R_BSP_BtnAction(BSP_BTN_RIGHT_RELEASE);
    }
}

static void qulButtonCenterAction(void)
{
    uint8_t level = R_GPIO_ReadIntPin(BSP_BTN_CENTER_INTP);

    if (level == 0u) {
        R_BSP_BtnAction(BSP_BTN_CENTER_PRESS);
    } else {
        R_BSP_BtnAction(BSP_BTN_CENTER_RELEASE);
    }
}

static void overrideButtonActions()
{
    //Disable interrupts
    R_GPIO_DeInitInt(BSP_BTN_LEFT_INTP);
    R_GPIO_DeInitInt(BSP_BTN_UP_INTP);
#if USE_FOUT_INSTEAD_BSP_BTN_DOWN != 1
    R_GPIO_DeInitInt(BSP_BTN_DOWN_INTP);
#endif /* USE_FOUT_INSTEAD_BSP_BTN_DOWN */
    R_GPIO_DeInitInt(BSP_BTN_RIGHT_INTP);
    R_GPIO_DeInitInt(BSP_BTN_CENTER_INTP);

    //Assign custom buttons actions
    r_gpio_IntConfig_t cfg;

    cfg.Port = BSP_BTN_LEFT_PORT;
    cfg.Pin = BSP_BTN_LEFT_PIN;
    cfg.Trigger = R_GPIO_INT_BOTH_EDGES;
    cfg.Callback = &qulButtonLeftAction;
    R_GPIO_InitInt(BSP_BTN_LEFT_INTP, &cfg);

    cfg.Port = BSP_BTN_UP_PORT;
    cfg.Pin = BSP_BTN_UP_PIN;
    cfg.Trigger = R_GPIO_INT_BOTH_EDGES;
    cfg.Callback = &qulButtonUpAction;
    R_GPIO_InitInt(BSP_BTN_UP_INTP, &cfg);

#if USE_FOUT_INSTEAD_BSP_BTN_DOWN != 1
    cfg.Port = BSP_BTN_DOWN_PORT;
    cfg.Pin = BSP_BTN_DOWN_PIN;
    cfg.Trigger = R_GPIO_INT_BOTH_EDGES;
    cfg.Callback = &qulButtonDownAction;
    R_GPIO_InitInt(BSP_BTN_DOWN_INTP, &cfg);
#endif /* USE_FOUT_INSTEAD_BSP_BTN_DOWN */

    cfg.Port = BSP_BTN_RIGHT_PORT;
    cfg.Pin = BSP_BTN_RIGHT_PIN;
    cfg.Trigger = R_GPIO_INT_BOTH_EDGES;
    cfg.Callback = &qulButtonRightAction;
    R_GPIO_InitInt(BSP_BTN_RIGHT_INTP, &cfg);

    cfg.Port = BSP_BTN_CENTER_PORT;
    cfg.Pin = BSP_BTN_CENTER_PIN;
    cfg.Trigger = R_GPIO_INT_BOTH_EDGES;
    cfg.Callback = &qulButtonCenterAction;
    R_GPIO_InitInt(BSP_BTN_CENTER_INTP, &cfg);

    //Enable interrupts
    R_GPIO_EnableInt(BSP_BTN_LEFT_INTP);
    R_GPIO_EnableInt(BSP_BTN_UP_INTP);
#if USE_FOUT_INSTEAD_BSP_BTN_DOWN != 1
    R_GPIO_EnableInt(BSP_BTN_DOWN_INTP);
#endif /* USE_FOUT_INSTEAD_BSP_BTN_DOWN */
    R_GPIO_EnableInt(BSP_BTN_RIGHT_INTP);
    R_GPIO_EnableInt(BSP_BTN_CENTER_INTP);
}

static void hmiInputInit()
{
    R_BSP_HMI_Init();

    overrideButtonActions();

    R_BSP_SetButtonCallback(BSP_BTN_UP_PRESS, keyEventHandler<HMIInputEvent::KeyPress, HMIInputEvent::HMI_BTN_UP>);
    R_BSP_SetButtonCallback(BSP_BTN_UP_RELEASE, keyEventHandler<HMIInputEvent::KeyRelease, HMIInputEvent::HMI_BTN_UP>);
    R_BSP_SetButtonCallback(BSP_BTN_DOWN_PRESS, keyEventHandler<HMIInputEvent::KeyPress, HMIInputEvent::HMI_BTN_DOWN>);
    R_BSP_SetButtonCallback(BSP_BTN_DOWN_RELEASE,
                            keyEventHandler<HMIInputEvent::KeyRelease, HMIInputEvent::HMI_BTN_DOWN>);
    R_BSP_SetButtonCallback(BSP_BTN_LEFT_PRESS, keyEventHandler<HMIInputEvent::KeyPress, HMIInputEvent::HMI_BTN_LEFT>);
    R_BSP_SetButtonCallback(BSP_BTN_LEFT_RELEASE,
                            keyEventHandler<HMIInputEvent::KeyRelease, HMIInputEvent::HMI_BTN_LEFT>);
    R_BSP_SetButtonCallback(BSP_BTN_RIGHT_PRESS, keyEventHandler<HMIInputEvent::KeyPress, HMIInputEvent::HMI_BTN_RIGHT>);
    R_BSP_SetButtonCallback(BSP_BTN_RIGHT_RELEASE,
                            keyEventHandler<HMIInputEvent::KeyRelease, HMIInputEvent::HMI_BTN_RIGHT>);
    R_BSP_SetButtonCallback(BSP_BTN_CENTER_PRESS,
                            keyEventHandler<HMIInputEvent::KeyPress, HMIInputEvent::HMI_BTN_CENTER>);
    R_BSP_SetButtonCallback(BSP_BTN_CENTER_RELEASE,
                            keyEventHandler<HMIInputEvent::KeyRelease, HMIInputEvent::HMI_BTN_CENTER>);

    // The knob alternates between sending left and right turn events
    // no matter which way you turn it, so let's just send BTN_LEFT_TURN events
    // to make it sort of useful.
    R_BSP_SetButtonCallback(BSP_BTN_LEFT_TURN,
                            keyEventHandler<HMIInputEvent::KeyRelease, HMIInputEvent::HMI_KNOB_TURN_RIGHT>);
    R_BSP_SetButtonCallback(BSP_BTN_RIGHT_TURN,
                            keyEventHandler<HMIInputEvent::KeyRelease, HMIInputEvent::HMI_KNOB_TURN_RIGHT>);

    R_BSP_SetButtonCallback(BSP_BTN_OK_PRESS, keyEventHandler<HMIInputEvent::KeyPress, HMIInputEvent::HMI_KNOB_CENTER>);
    R_BSP_SetButtonCallback(BSP_BTN_OK_RELEASE,
                            keyEventHandler<HMIInputEvent::KeyRelease, HMIInputEvent::HMI_KNOB_CENTER>);
}

extern void (*hmiInputInitRoutine)();
static struct Init
{
    Init() { hmiInputInitRoutine = hmiInputInit; }
} init;