NXP Touch Cursor example for LPCXpresso54608, modified for use with Mbed OS.

The tutorial for this example can be found here: https://os.mbed.com/blog/entry/How-to-LPCXpresso54608-touch-panel/

main.cpp

Committer:
jplunkett
Date:
2018-04-11
Revision:
0:c107a6f8c368

File content as of revision 0:c107a6f8c368:

/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2017 NXP
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*  Standard C Included Files */
#include "mbed.h"
#include <stdio.h>
#include <string.h>
#include "stdio_thread.h"
#include "fsl_lcdc.h"
#include "fsl_ft5406.h"
#include "fsl_sctimer.h"
#include "fsl_gpio.h"
#include "fsl_i2c.h"
#include "board.h"
#include "pin_mux.h"
#include "image.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define APP_LCD LCD
#define LCD_PANEL_CLK 9000000
#define LCD_PPL 480
#define LCD_HSW 2
#define LCD_HFP 8
#define LCD_HBP 43
#define LCD_LPP 272
#define LCD_VSW 10
#define LCD_VFP 4
#define LCD_VBP 12
#define LCD_POL_FLAGS kLCDC_InvertVsyncPolarity | kLCDC_InvertHsyncPolarity
#define IMG_HEIGHT 272
#define IMG_WIDTH 480
#define LCD_INPUT_CLK_FREQ CLOCK_GetFreq(kCLOCK_LCD)
#define APP_LCD_IRQHandler LCD_IRQHandler
#define APP_LCD_IRQn LCD_IRQn
#define EXAMPLE_I2C_MASTER_BASE (I2C2_BASE)
#define I2C_MASTER_CLOCK_FREQUENCY (12000000)
#define APP_PIXEL_PER_BYTE 8

#define EXAMPLE_I2C_MASTER ((I2C_Type *)EXAMPLE_I2C_MASTER_BASE)
#define I2C_MASTER_SLAVE_ADDR_7BIT 0x7EU
#define I2C_BAUDRATE 100000U

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/

#if (defined(__CC_ARM) || defined(__GNUC__))
__attribute__((aligned(8)))
#elif defined(__ICCARM__)
#pragma data_alignment = 8
#else
#error Toolchain not support.
#endif

void *vram_ptr = s_frameBufs;

/* Frame end flag. */
static volatile bool s_frameEndFlag;

/* Color palette. */
static const uint32_t palette[] = { 0x001F00000 }; //{0x0000001F}; //{0x001F0000U, 0x7C0003E0U};

/* 32x32 pixel cursor image. */
#if (defined(__CC_ARM) || defined(__GNUC__))
__attribute__((aligned(4)))
#elif defined(__ICCARM__)
#pragma data_alignment = 4
#else
#error Toolchain not support.
#endif
static const uint8_t cursor32Img0[] = {
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 1.  */
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 2.  */
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 3.  */
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 4.  */
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 5.  */
    0xAA, 0xAA, 0xAA, 0xFA, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 6.  */
    0xAA, 0xAA, 0xAB, 0xFE, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 7.  */
    0xAA, 0xAA, 0xAB, 0xFE, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 8.  */
    0xAA, 0xAA, 0xAB, 0xFE, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 9.  */
    0xAA, 0xAA, 0xAB, 0xFE, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 10  */
    0xAA, 0xAA, 0xAB, 0xFF, 0xEA,
    0xAA, 0xAA, 0xAA, /* Line 11. */
    0xAA, 0xAA, 0xAB, 0xFF, 0xFF,
    0xAA, 0xAA, 0xAA, /* Line 12. */
    0xAA, 0xAA, 0xAB, 0xFF, 0xFF,
    0xFA, 0xAA, 0xAA, /* Line 13. */
    0xAA, 0xAA, 0xAB, 0xFF, 0xFF,
    0xFE, 0xAA, 0xAA, /* Line 14. */
    0xAA, 0xAB, 0xFB, 0xFF, 0xFF,
    0xFF, 0xAA, 0xAA, /* Line 15. */
    0xAA, 0xAB, 0xFF, 0xFF, 0xFF,
    0xFF, 0xAA, 0xAA, /* Line 16. */
    0xAA, 0xAB, 0xFF, 0xFF, 0xFF,
    0xFF, 0xAA, 0xAA, /* Line 17. */
    0xAA, 0xAA, 0xFF, 0xFF, 0xFF,
    0xFF, 0xAA, 0xAA, /* Line 18. */
    0xAA, 0xAA, 0xBF, 0xFF, 0xFF,
    0xFF, 0xAA, 0xAA, /* Line 19. */
    0xAA, 0xAA, 0xBF, 0xFF, 0xFF,
    0xFF, 0xAA, 0xAA, /* Line 20. */
    0xAA, 0xAA, 0xAF, 0xFF, 0xFF,
    0xFF, 0xAA, 0xAA, /* Line 21. */
    0xAA, 0xAA, 0xAF, 0xFF, 0xFF,
    0xFE, 0xAA, 0xAA, /* Line 22. */
    0xAA, 0xAA, 0xAB, 0xFF, 0xFF,
    0xFE, 0xAA, 0xAA, /* Line 23. */
    0xAA, 0xAA, 0xAB, 0xFF, 0xFF,
    0xFE, 0xAA, 0xAA, /* Line 24. */
    0xAA, 0xAA, 0xAA, 0xFF, 0xFF,
    0xFA, 0xAA, 0xAA, /* Line 25. */
    0xAA, 0xAA, 0xAA, 0xFF, 0xFF,
    0xFA, 0xAA, 0xAA, /* Line 26. */
    0xAA, 0xAA, 0xAA, 0xFF, 0xFF,
    0xFA, 0xAA, 0xAA, /* Line 27. */
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 28. */
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 29. */
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 30. */
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, /* Line 31. */
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA /* Line 32. */
};

/*******************************************************************************
 * Code
 ******************************************************************************/
static void BOARD_InitPWM(void)
{
    sctimer_config_t config;
    sctimer_pwm_signal_param_t pwmParam;
    uint32_t event;

    CLOCK_AttachClk(kMCLK_to_SCT_CLK);

    CLOCK_SetClkDiv(kCLOCK_DivSctClk, 2, true);

    SCTIMER_GetDefaultConfig(&config);

    SCTIMER_Init(SCT0, &config);

    pwmParam.output = kSCTIMER_Out_5;
    pwmParam.level = kSCTIMER_HighTrue;
    pwmParam.dutyCyclePercent = 5;

    SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 1000U, CLOCK_GetFreq(kCLOCK_Sct), &event);
}

void APP_LCD_IRQHandler(void)
{
    uint32_t intStatus = LCDC_GetEnabledInterruptsPendingStatus(APP_LCD);

    LCDC_ClearInterruptsStatus(APP_LCD, intStatus);

    if (intStatus & kLCDC_VerticalCompareInterrupt)
    {
        s_frameEndFlag = true;
    }
    __DSB();
}

status_t APP_LCDC_Init(void)
{
    /* Initialize the display. */
    lcdc_config_t lcdConfig;
    lcdc_cursor_config_t cursorConfig;

    LCDC_GetDefaultConfig(&lcdConfig);

    lcdConfig.panelClock_Hz = LCD_PANEL_CLK;
    lcdConfig.ppl = LCD_PPL;
    lcdConfig.hsw = LCD_HSW;
    lcdConfig.hfp = LCD_HFP;
    lcdConfig.hbp = LCD_HBP;
    lcdConfig.lpp = LCD_LPP;
    lcdConfig.vsw = LCD_VSW;
    lcdConfig.vfp = LCD_VFP;
    lcdConfig.vbp = LCD_VBP;
    lcdConfig.polarityFlags = LCD_POL_FLAGS;
    lcdConfig.upperPanelAddr = (uint32_t)s_frameBufs;
    lcdConfig.bpp = kLCDC_1BPP;
    lcdConfig.display = kLCDC_DisplayTFT;
    lcdConfig.swapRedBlue = true;  //false;
    lcdConfig.dataFormat = kLCDC_WinCeMode;

    LCDC_Init(APP_LCD, &lcdConfig, LCD_INPUT_CLK_FREQ);

    LCDC_SetPalette(APP_LCD, palette, ARRAY_SIZE(palette));

    /* Setup the Cursor. */
    LCDC_CursorGetDefaultConfig(&cursorConfig);

    cursorConfig.size = kLCDC_CursorSize32;
    cursorConfig.syncMode = kLCDC_CursorSync;
    cursorConfig.image[0] = (uint32_t *)cursor32Img0;

    LCDC_SetCursorConfig(APP_LCD, &cursorConfig);
    LCDC_ChooseCursor(APP_LCD, 0);

    /* Trigger interrupt at start of every vertical back porch. */
    LCDC_SetVerticalInterruptMode(APP_LCD, kLCDC_StartOfBackPorch);
    LCDC_EnableInterrupts(APP_LCD, kLCDC_VerticalCompareInterrupt);
    // NVIC_EnableIRQ(APP_LCD_IRQn);

    LCDC_EnableCursor(APP_LCD, true);

    LCDC_Start(APP_LCD);
    LCDC_PowerUp(APP_LCD);

    return kStatus_Success;
}

status_t APP_I2C_Init(void)
{
    i2c_master_config_t masterConfig;

    I2C_MasterGetDefaultConfig(&masterConfig);

    /* Change the default baudrate configuration */
    masterConfig.baudRate_Bps = I2C_BAUDRATE;

    /* Initialize the I2C master peripheral */
    I2C_MasterInit(EXAMPLE_I2C_MASTER, &masterConfig, I2C_MASTER_CLOCK_FREQUENCY);

    return kStatus_Success;
}

void APP_SetCursorPosition(int posX, int posY)
{
    posX -= 12;
    posY -= 5;

    LCDC_SetCursorPosition(APP_LCD, posX, posY);
}

int main(void)
{
    int cursorPosX = 0U;
    int cursorPosY = 0U;

    ft5406_handle_t touch_handle;
    touch_event_t touch_event;

    status_t status;

    gpio_pin_config_t pin_config = {
        kGPIO_DigitalOutput, 0,
    };

    /* Board pin, clock, debug console init */
    /* attach 12 MHz clock to FLEXCOMM0 (debug console) */
    CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);

    /* Route Main clock to LCD. */
    CLOCK_AttachClk(kMCLK_to_LCD_CLK);

    /* attach 12 MHz clock to FLEXCOMM2 (I2C master for touch controller) */
    CLOCK_AttachClk(kFRO12M_to_FLEXCOMM2);

    CLOCK_EnableClock(kCLOCK_Gpio2);

    CLOCK_SetClkDiv(kCLOCK_DivLcdClk, 1, true);

    BOARD_InitPins();
    BOARD_BootClockFROHF48M();
    // BOARD_InitDebugConsole();

    /* Set the back light PWM. */
    BOARD_InitPWM();

    // APP_FillBuffer((void *)(s_frameBufs));

    status = APP_LCDC_Init();
    if (status != kStatus_Success)
    {
        safe_printf("LCD init failed\n");
    }
    assert(status == kStatus_Success);

    status = APP_I2C_Init();
    if (status != kStatus_Success)
    {
        safe_printf("I2C init failed\n");
    }
    assert(status == kStatus_Success);

    GPIO_PinInit(GPIO, 2, 27, &pin_config);
    // GPIO_WritePinOutput(GPIO, 2, 27, 1);
    GPIO->B[2][27] = 1;

    status = FT5406_Init(&touch_handle, EXAMPLE_I2C_MASTER);
    if (status != kStatus_Success)
    {
        safe_printf("Touch panel init failed\n");
    }
    assert(status == kStatus_Success);

    uint32_t xMin = 0xbd;
    uint32_t xMax = 0xea;
    uint32_t yMin = 0xb7;
    uint32_t yMax = 0x12f;

    for (;;)
    {
        if (kStatus_Success == FT5406_GetSingleTouch(&touch_handle, &touch_event, &cursorPosX, &cursorPosY))
        {
            if ((touch_event == kTouch_Down) || (touch_event == kTouch_Contact))
            {
                /* Update cursor position */
                APP_SetCursorPosition(cursorPosY, cursorPosX);
                if (xMin < cursorPosX && cursorPosX < xMax && yMin < cursorPosY && cursorPosY < yMax) {
                  safe_printf("You've clicked the button! (0x%2x, 0x%2x)\r\n", cursorPosX, cursorPosY);
                }
            }
        }
        else
        {
            safe_printf("error reading touch controller\r\n");
        }
    }
}