/******************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Quick Ultralite module.
**
** $QT_BEGIN_LICENSE:COMM$
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** $QT_END_LICENSE$
**
******************************************************************************/
#include <platforminterface/printf.h>

#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"

#include "fsl_gpio.h"
#include "fsl_lpi2c.h"
#include "fsl_gt911.h"
#include "fsl_common.h"
#include "fsl_elcdif.h"
#include "fsl_display.h"
#include "fsl_debug_console.h"
#include "fsl_dc_fb_lcdifv2.h"
#include "display_support.h"

#if IS_MIPI_TOUCH_SUPPORTED()

static void BOARD_PullMIPIPanelTouchResetPin(bool pullUp);
static void BOARD_ConfigMIPIPanelTouchIntPin(gt911_int_pin_mode_t mode);
void nxp_frameDone();

gt911_handle_t s_touchHandle;
extern const dc_fb_t g_dc;
static const gt911_config_t s_touchConfig = {
    .I2C_SendFunc = BOARD_MIPIPanelTouch_I2C_Send,
    .I2C_ReceiveFunc = BOARD_MIPIPanelTouch_I2C_Receive,
    .pullResetPinFunc = BOARD_PullMIPIPanelTouchResetPin,
    .intPinFunc = BOARD_ConfigMIPIPanelTouchIntPin,
    .timeDelayMsFunc = VIDEO_DelayMs,
    .touchPointNum = 1,
    .i2cAddrMode = kGT911_I2cAddrMode0,
    .intTrigMode = kGT911_IntRisingEdge,
};

static void BOARD_Touch_Init(void)
{
    status_t status;

    const gpio_pin_config_t touch_config = {.direction = kGPIO_DigitalInput,
                                            .outputLogic = 0,
                                            .interruptMode = kGPIO_IntRisingEdge};

    const gpio_pin_config_t resetPinConfig = {.direction = kGPIO_DigitalOutput,
                                              .outputLogic = 0,
                                              .interruptMode = kGPIO_NoIntmode};

    GPIO_PinInit(BOARD_MIPI_PANEL_TOUCH_RST_GPIO, BOARD_MIPI_PANEL_TOUCH_RST_PIN, &resetPinConfig);

    status = GT911_Init(&s_touchHandle, &s_touchConfig);
    if (kStatus_Success != status) {
        qul_printf("Touch IC initialization failed\r\n");
    }

    /* Init touch GPIO. */
    GPIO_PinInit(BOARD_MIPI_PANEL_TOUCH_INT_GPIO, BOARD_MIPI_PANEL_TOUCH_INT_PIN, &touch_config);
    GPIO_PortEnableInterrupts(BOARD_MIPI_PANEL_TOUCH_INT_GPIO, 1U << BOARD_MIPI_PANEL_TOUCH_INT_PIN);

    NVIC_SetPriority(BOARD_MIPI_PANEL_TOUCH_IRQ, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
    EnableIRQ(BOARD_MIPI_PANEL_TOUCH_IRQ);
}
#endif

int init_nxp(void)
{
    BOARD_ConfigMPU();
    BOARD_BootClockRUN();
    BOARD_InitMipiPanelPins();
#if IS_MIPI_TOUCH_SUPPORTED()
    BOARD_MIPIPanelTouch_I2C_Init();
#endif
    BOARD_InitDebugConsole();

    // Do not enter WAIT or STOP state during WFI.
    // That would stop systicks and is currently not supported.

    // TODO: To be uncommented once SDK has implementation for CLOCK_SetMode
    // CLOCK_SetMode(kCLOCK_ModeRun);
    return 0;
}

void init_nxp_late(void)
{
#if IS_MIPI_TOUCH_SUPPORTED()
    BOARD_Touch_Init();
#elif IS_HDMI_TOUCH_SUPPORTED()
    BOARD_HDMI_Touch_Init();
#else
    qul_printf("Touch is not supported on the selected display (%s)\r\n", DEMO_PANEL_NAME);
#endif
}

#if IS_MIPI_TOUCH_SUPPORTED()
static void BOARD_PullMIPIPanelTouchResetPin(bool pullUp)
{
    if (pullUp) {
        GPIO_PinWrite(BOARD_MIPI_PANEL_TOUCH_RST_GPIO, BOARD_MIPI_PANEL_TOUCH_RST_PIN, 1);
    } else {
        GPIO_PinWrite(BOARD_MIPI_PANEL_TOUCH_RST_GPIO, BOARD_MIPI_PANEL_TOUCH_RST_PIN, 0);
    }
}

static void BOARD_ConfigMIPIPanelTouchIntPin(gt911_int_pin_mode_t mode)
{
    if (mode == kGT911_IntPinInput) {
        BOARD_MIPI_PANEL_TOUCH_INT_GPIO->GDIR &= ~(1UL << BOARD_MIPI_PANEL_TOUCH_INT_PIN);
    } else {
        if (mode == kGT911_IntPinPullDown) {
            GPIO_PinWrite(BOARD_MIPI_PANEL_TOUCH_INT_GPIO, BOARD_MIPI_PANEL_TOUCH_INT_PIN, 0);
        } else {
            GPIO_PinWrite(BOARD_MIPI_PANEL_TOUCH_INT_GPIO, BOARD_MIPI_PANEL_TOUCH_INT_PIN, 1);
        }

        BOARD_MIPI_PANEL_TOUCH_INT_GPIO->GDIR |= (1UL << BOARD_MIPI_PANEL_TOUCH_INT_PIN);
    }
}
#endif

int _write(int file, char *ptr, int len)
{
    (void) file;

    for (int i = 0; i < len; i++) {
        DbgConsole_Putchar(*ptr++);
    }

    return len;
}
