aboutsummaryrefslogtreecommitdiffstats
path: root/boards/base/STM32F469i-Discovery/CubeHAL
diff options
context:
space:
mode:
authorJoel Bodenmann <joel@embedded.pro>2017-10-28 11:58:02 +0200
committerJoel Bodenmann <joel@embedded.pro>2017-10-28 11:58:02 +0200
commit025bc66666401f1a1a9f16ecddf5655141d11839 (patch)
treea9077104e030aa31f9bf62f9d62fbefd9d05865d /boards/base/STM32F469i-Discovery/CubeHAL
parent2a249e6140307c1cfaa1ce6f7775caf3f7be4b79 (diff)
downloaduGFX-025bc66666401f1a1a9f16ecddf5655141d11839.tar.gz
uGFX-025bc66666401f1a1a9f16ecddf5655141d11839.tar.bz2
uGFX-025bc66666401f1a1a9f16ecddf5655141d11839.zip
STM32F469i-Discovery board files
Diffstat (limited to 'boards/base/STM32F469i-Discovery/CubeHAL')
-rw-r--r--boards/base/STM32F469i-Discovery/CubeHAL/STM32_FLASH.ld186
-rw-r--r--boards/base/STM32F469i-Discovery/CubeHAL/board_STM32LTDC.h309
-rw-r--r--boards/base/STM32F469i-Discovery/CubeHAL/ft6x06.h88
-rw-r--r--boards/base/STM32F469i-Discovery/CubeHAL/gmouse_lld_FT6x06_board.h110
4 files changed, 693 insertions, 0 deletions
diff --git a/boards/base/STM32F469i-Discovery/CubeHAL/STM32_FLASH.ld b/boards/base/STM32F469i-Discovery/CubeHAL/STM32_FLASH.ld
new file mode 100644
index 00000000..8cdd7c0e
--- /dev/null
+++ b/boards/base/STM32F469i-Discovery/CubeHAL/STM32_FLASH.ld
@@ -0,0 +1,186 @@
+/*
+ * GCC linker script for STM32 microcontrollers (ARM Cortex-M).
+ *
+ * It exports the symbols needed for the CMSIS assembler startup script for GCC
+ * ARM toolchains (_sidata, _sdata, _edata, _sbss, _ebss) and sets the entry
+ * point to Reset_Handler.
+ *
+ * Adapt FLASH/RAM size for your particular device below.
+ *
+ * @author Bjørn Forsman
+ */
+
+MEMORY
+{
+ flash (rx) : ORIGIN = 0x08000000, LENGTH = 320K
+ ccmram (rw) : ORIGIN = 0x10000000, LENGTH = 64k
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 2048K
+}
+
+ENTRY(Reset_Handler)
+
+/*
+ * Reserve memory for heap and stack. The linker will issue an error if there
+ * is not enough memory.
+ *
+ * NOTE: The reserved heap and stack will be added to the bss column of the
+ * binutils size command.
+ */
+_heap_size = 0x200; /* required amount of heap */
+_stack_size = 0x400; /* required amount of stack */
+
+/*
+ * The stack starts at the end of RAM and grows downwards. Full-descending
+ * stack; decrement first, then store.
+ */
+_estack = ORIGIN(ram) + LENGTH(ram);
+
+SECTIONS
+{
+ /* Reset and ISR vectors */
+ .isr_vector :
+ {
+ __isr_vector_start__ = .;
+ KEEP(*(.isr_vector)) /* without 'KEEP' the garbage collector discards this section */
+ ASSERT(. != __isr_vector_start__, "The .isr_vector section is empty");
+ } >flash
+
+
+ /* Text section (code and read-only data) */
+ .text :
+ {
+ . = ALIGN(4);
+ _stext = .;
+ *(.text*) /* code */
+ *(.rodata*) /* read only data */
+
+ /*
+ * NOTE: .glue_7 and .glue_7t sections are not needed because Cortex-M
+ * only supports Thumb instructions, no ARM/Thumb interworking.
+ */
+
+ /* Static constructors and destructors */
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ . = ALIGN(4);
+ _etext = .;
+ } >flash
+
+
+ /*
+ * Stack unwinding and exception handling sections.
+ *
+ * ARM compilers emit object files with .ARM.extab and .ARM.exidx sections
+ * when using C++ exceptions. Also, at least GCC emits those sections when
+ * dividing large numbers (64-bit) in C. So we have to handle them.
+ *
+ * (ARM uses .ARM.extab and .ARM.exidx instead of the .eh_frame section
+ * used on x86.)
+ */
+ .ARM.extab : /* exception unwinding information */
+ {
+ *(.ARM.extab*)
+ } >flash
+ .ARM.exidx : /* index entries for section unwinding */
+ {
+ *(.ARM.exidx*)
+ } >flash
+
+
+ /*
+ * Newlib and Eglibc (at least) need these for C++ support.
+ *
+ * (Copied from Sourcery CodeBench Lite: arm-none-eabi-gcc -V)
+ */
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN(__preinit_array_start = .);
+ KEEP(*(.preinit_array*))
+ PROVIDE_HIDDEN(__preinit_array_end = .);
+ } >flash
+ .init_array :
+ {
+ PROVIDE_HIDDEN(__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array*))
+ PROVIDE_HIDDEN(__init_array_end = .);
+ } >flash
+ .fini_array :
+ {
+ PROVIDE_HIDDEN(__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array*))
+ PROVIDE_HIDDEN(__fini_array_end = .);
+ } >flash
+
+
+ /*
+ * Initialized data section. This section is programmed into FLASH (LMA
+ * address) and copied to RAM (VMA address) in startup code.
+ */
+ _sidata = .;
+ .data : AT(_sidata) /* LMA address is _sidata (in FLASH) */
+ {
+ . = ALIGN(4);
+ _sdata = .; /* data section VMA address (in RAM) */
+ *(.data*)
+ . = ALIGN(4);
+ _edata = .;
+ } >ram
+
+ /*
+ * CCM-RAM data section. Initialization variables can be placed here
+ * when the initialization code is provided by the user. Else it is used
+ * as an extra piece of memory for heap/stack
+ */
+ _eidata = (_sidata + SIZEOF(.data));
+ .ccm : AT(_sidata + SIZEOF(.data)) /* We want LMA address to be in FLASH (if used for init data) */
+ {
+ . = ALIGN(4);
+ _sccm = .; /* data section VMA address (in CCMRAM) */
+ *(.ccm)
+ . = ALIGN(4);
+ _eccm = .;
+ } >ccmram
+
+
+ /* Uninitialized data section (zeroed out by startup code) */
+ .bss :
+ {
+ . = ALIGN(4);
+ _sbss = .;
+ __bss_start__ = _sbss;
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ __bss_end__ = _ebss;
+ } >ram
+
+
+ /*
+ * Reserve memory for heap and stack. The linker will issue an error if
+ * there is not enough memory.
+ */
+ ._heap :
+ {
+ . = ALIGN(4);
+ _end = .;
+ __end__ = _end;
+ . = . + _heap_size;
+ . = ALIGN(4);
+ } >ram
+ ._stack :
+ {
+ . = ALIGN(4);
+ . = . + _stack_size;
+ . = ALIGN(4);
+ } >ram
+}
+
+/* Nice to have */
+__isr_vector_size__ = SIZEOF(.isr_vector);
+__text_size__ = SIZEOF(.text);
+__data_size__ = SIZEOF(.data);
+__bss_size__ = SIZEOF(.bss);
diff --git a/boards/base/STM32F469i-Discovery/CubeHAL/board_STM32LTDC.h b/boards/base/STM32F469i-Discovery/CubeHAL/board_STM32LTDC.h
new file mode 100644
index 00000000..00a66c21
--- /dev/null
+++ b/boards/base/STM32F469i-Discovery/CubeHAL/board_STM32LTDC.h
@@ -0,0 +1,309 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/* Avoid naming collisions with CubeHAL. */
+#undef Red
+#undef Green
+#undef Blue
+
+/* HAL drivers needed for configuration. */
+#include "stm32f4xx_hal.h"
+#include "stm32f4xx_hal_rcc.h"
+#include "stm32f4xx_hal_gpio.h"
+#include "stm32f4xx_hal_dsi.h"
+/* sdram driver provided by ST. */
+#include "stm32f469i_discovery_sdram.h"
+/* OTM8009A driver provided by ST. */
+#include "otm8009a.h"
+
+/** Manually set the LTDC timing. */
+#ifndef GFX_LTDC_TIMING_SET
+ #define GFX_LTDC_TIMING_SET
+#endif
+
+/** Most boards will be revision A. */
+#ifndef USE_STM32469I_DISCO_REVA
+ #define USE_STM32469I_DISCO_REVA
+#endif
+
+/** @brief Panel parameters
+ *
+ * This panel is a KoD KM-040TMP-02-0621 DSI LCD Display.
+ */
+
+static const ltdcConfig driverCfg = {
+ 800, 480, // Width, Height (pixels)
+ 1, 2, // Horizontal, Vertical sync (pixels)
+ 15, 34, // Horizontal, Vertical back porch (pixels)
+ 16, 34, // Horizontal, Vertical front porch (pixels)
+ 0, // Sync flags
+ 0x000000, // Clear color (RGB888)
+
+ { // Background layer config
+ (LLDCOLOR_TYPE *)SDRAM_DEVICE_ADDR, // Frame buffer address
+ 800, 480, // Width, Height (pixels)
+ 800 * LTDC_PIXELBYTES, // Line pitch (bytes)
+ LTDC_PIXELFORMAT, // Pixel format
+ 0, 0, // Start pixel position (x, y)
+ 800, 480, // Size of virtual layer (cx, cy)
+ LTDC_COLOR_FUCHSIA, // Default color (ARGB8888)
+ 0x980088, // Color key (RGB888)
+ LTDC_BLEND_FIX1_FIX2, // Blending factors
+ 0, // Palette (RGB888, can be NULL)
+ 0, // Palette length
+ 0xFF, // Constant alpha factor
+ LTDC_LEF_ENABLE // Layer configuration flags
+ },
+
+ LTDC_UNUSED_LAYER_CONFIG // Foreground layer config
+};
+
+/** Display timing setting */
+#define KoD_FREQUENCY_DIVIDER 7
+
+/** Global DSI handle to hold DSI parameters. */
+DSI_HandleTypeDef dsiHandle;
+
+static GFXINLINE void reset_lcd(GDisplay* g);
+
+/**
+ * @brief Function to intialize the STM32F46i-DISCO board.
+ *
+ * @param g: Structure holding display parameters.
+ */
+static GFXINLINE void init_board(GDisplay *g) {
+
+ // As we are not using multiple displays we set g->board to NULL as we don't use it
+ g->board = 0;
+
+#ifdef GFX_LTDC_TIMING_SET
+ // KoD LCD clock configuration
+ // PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz
+ // PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 384 Mhz
+ // PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 384/7 = 54.857 Mhz
+ // LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_2 = 54.857/2 = 27.429Mhz
+ #define STM32_SAISRC_NOCLOCK (0 << 23) /**< No clock. */
+ #define STM32_SAISRC_PLL (1 << 23) /**< SAI_CKIN is PLL. */
+ #define STM32_SAIR_DIV2 (0 << 16) /**< R divided by 2. */
+ #define STM32_SAIR_DIV4 (1 << 16) /**< R divided by 4. */
+ #define STM32_SAIR_DIV8 (2 << 16) /**< R divided by 8. */
+ #define STM32_SAIR_DIV16 (3 << 16) /**< R divided by 16. */
+
+ #define STM32_PLLSAIN_VALUE 384
+ #define STM32_PLLSAIQ_VALUE 4
+ #define STM32_PLLSAIR_VALUE KoD_FREQUENCY_DIVIDER
+ #define STM32_PLLSAIR_POST STM32_SAIR_DIV2
+
+ RCC->PLLSAICFGR = (STM32_PLLSAIN_VALUE << 6) | (STM32_PLLSAIR_VALUE << 28) | (STM32_PLLSAIQ_VALUE << 24);
+ RCC->DCKCFGR = (RCC->DCKCFGR & ~RCC_DCKCFGR_PLLSAIDIVR) | STM32_PLLSAIR_POST;
+ RCC->CR |= RCC_CR_PLLSAION;
+#endif
+
+ __HAL_RCC_DSI_CLK_ENABLE();
+
+ DSI_PLLInitTypeDef dsiPllInit;
+ DSI_CmdCfgTypeDef dsiCmdMode;
+ DSI_LPCmdTypeDef dsiAPBCmd;
+ /* Filling the DSI intialization struct. */
+ dsiHandle.Instance = DSI; // There is only one DSI interface
+ dsiHandle.Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_ENABLE; // Automatic clock lane control: powers down the clock lane when not in use
+ /* Highest speed = 500MHz. */
+ uint16_t laneByteClk_kHz = 62500; /* 500 MHz / 8 = 62.5 MHz = 62500 kHz */
+ /* TXEscapeCkdiv = f(LaneByteClk)/15.62 = 4 -> 500MHz/4 = 25MHz datasheet says around 20MHz */
+ dsiHandle.Init.TXEscapeCkdiv = laneByteClk_kHz/15620; // Low power clock relative to the laneByteClock
+ dsiHandle.Init.NumberOfLanes = DSI_TWO_DATA_LANES; // Two data lines for the fastest transfer speed
+
+ /* Fill in the command mode struct. */
+ dsiCmdMode.VirtualChannelID = 0; // The first virtual channel
+
+ /* Select the appropriate color coding. */
+#ifdef GDISP_PIXELFORMAT_RGB565
+ dsiCmdMode.ColorCoding = DSI_RGB565;
+#else
+ dsiCmdMode.ColorCoding = DSI_RGB888;
+#endif
+
+ dsiCmdMode.CommandSize = driverCfg.width; // Amount of pixels sent at once -> one line at a time
+ dsiCmdMode.TearingEffectSource = DSI_TE_EXTERNAL; // Use pin PJ2
+ dsiCmdMode.TearingEffectPolarity = DSI_TE_RISING_EDGE;
+ dsiCmdMode.HSPolarity = DSI_HSYNC_ACTIVE_HIGH;
+ dsiCmdMode.VSPolarity = DSI_VSYNC_ACTIVE_HIGH;
+ dsiCmdMode.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;
+ dsiCmdMode.VSyncPol = DSI_VSYNC_FALLING;
+ dsiCmdMode.AutomaticRefresh = DSI_AR_ENABLE; // Use the automatic refresh mode
+ dsiCmdMode.TEAcknowledgeRequest = DSI_TE_ACKNOWLEDGE_DISABLE; // Not needed when using TE through GPIO
+
+ /* GPIO configuration. */
+ GPIO_InitTypeDef gpioInit;
+ /* PH7 LCD_RESET */
+ __HAL_RCC_GPIOH_CLK_ENABLE();
+ gpioInit.Pin = GPIO_PIN_7;
+ gpioInit.Mode = GPIO_MODE_OUTPUT_OD;
+ gpioInit.Pull = GPIO_NOPULL;
+ gpioInit.Speed = GPIO_SPEED_HIGH;
+ HAL_GPIO_Init(GPIOH, &gpioInit);
+
+ /* PJ2 DSIHOST_TE */
+ __HAL_RCC_GPIOJ_CLK_ENABLE();
+ gpioInit.Pin = GPIO_PIN_2;
+ gpioInit.Mode = GPIO_MODE_AF_PP;
+ gpioInit.Alternate = GPIO_AF13_DSI;
+ HAL_GPIO_Init(GPIOJ, &gpioInit);
+
+ /* PA3 LCD_BL_CTRL This pin is not physically connected. */
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ gpioInit.Pin = GPIO_PIN_3;
+ gpioInit.Mode = GPIO_MODE_OUTPUT_OD;
+ HAL_GPIO_Init(GPIOA, &gpioInit);
+
+ /* Fvco = f(CLKin/IDF) * 2 * NDIV; fPHI = Fvco/(2*ODF) */
+#if !defined(USE_STM32469I_DISCO_REVA)
+ /* fPHI = CLKin*62.5; Fvco = CLKin*125 */
+ dsiPllInit.PLLNDIV = 125;
+ dsiPllInit.PLLIDF = DSI_PLL_IN_DIV2;
+#else
+ /* fPHI = CLKin*20; Fvco = CLKin*40 */
+ dsiPllInit.PLLNDIV = 100;
+ dsiPllInit.PLLIDF = DSI_PLL_IN_DIV5;
+#endif
+ dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1;
+
+ /* Initialize the DSI peripheral. */
+ HAL_DSI_Init(&dsiHandle, &dsiPllInit);
+
+ DSI_PHY_TimerTypeDef PhyTimings;
+ /* Configure DSI PHY HS2LP and LP2HS timings. Datasheet says 95ns max */
+ PhyTimings.ClockLaneHS2LPTime = 35;
+ PhyTimings.ClockLaneLP2HSTime = 35;
+ PhyTimings.DataLaneHS2LPTime = 35;
+ PhyTimings.DataLaneLP2HSTime = 35;
+ PhyTimings.DataLaneMaxReadTime = 0;
+ PhyTimings.StopWaitTime = 10;
+ HAL_DSI_ConfigPhyTimer(&dsiHandle, &PhyTimings);
+
+ /* Configure adapted command mode. */
+ HAL_DSI_ConfigAdaptedCommandMode(&dsiHandle, &dsiCmdMode);
+
+ /* Hardware reset LCD */
+ reset_lcd(g);
+
+ /* Initialize the SDRAM */
+ BSP_SDRAM_Init();
+}
+
+static GFXINLINE void set_backlight(GDisplay* g, uint8_t percent)
+{
+ (void)g;
+ (void)percent;
+}
+
+/**
+ * @brief Perform a hardware reset on the LCD.
+ *
+ * @param g: Display parameter structure.
+ */
+static GFXINLINE void reset_lcd(GDisplay* g)
+{
+ (void)g;
+ /* Hardware display reset. */
+ HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_RESET);
+ gfxSleepMilliseconds(20);
+ HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_SET);
+ gfxSleepMilliseconds(10);
+ /* Turn on backlight. */
+ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
+}
+
+/**
+ * @brief Extra initialization that is performed after the LTDC intialization.
+ *
+ * @param g: Display paramter structure.
+ */
+static GFXINLINE void post_init_board(GDisplay* g)
+{
+ (void)g;
+ DSI_LPCmdTypeDef dsiAPBCmd;
+
+ /* Enable the DSI host and wrapper after the LTDC initialization
+ To avoid any synchronization issue, the DSI shall be started after enabling the LTDC */
+ HAL_DSI_Start(&dsiHandle);
+
+ /* The configuration commands for the LCD have to be send through the dsiAPBCmd
+ * interface as the adapted command mode only supports DCS, WMS and WMC commands. */
+ dsiAPBCmd.LPGenShortWriteNoP = DSI_LP_GSW0P_ENABLE; // Put everything in low power mode
+ dsiAPBCmd.LPGenShortWriteOneP = DSI_LP_GSW1P_ENABLE;
+ dsiAPBCmd.LPGenShortWriteTwoP = DSI_LP_GSW2P_ENABLE;
+ dsiAPBCmd.LPGenShortReadNoP = DSI_LP_GSR0P_ENABLE;
+ dsiAPBCmd.LPGenShortReadOneP = DSI_LP_GSR1P_ENABLE;
+ dsiAPBCmd.LPGenShortReadTwoP = DSI_LP_GSR2P_ENABLE;
+ dsiAPBCmd.LPGenLongWrite = DSI_LP_GLW_ENABLE;
+ dsiAPBCmd.LPDcsShortWriteNoP = DSI_LP_DSW0P_ENABLE;
+ dsiAPBCmd.LPDcsShortWriteOneP = DSI_LP_DSW1P_ENABLE;
+ dsiAPBCmd.LPDcsShortReadNoP = DSI_LP_DSR0P_ENABLE;
+ dsiAPBCmd.LPDcsLongWrite = DSI_LP_DLW_ENABLE;
+ HAL_DSI_ConfigCommand(&dsiHandle, &dsiAPBCmd);
+
+ /* Configure the LCD. */
+#ifdef GDISP_PIXELFORMAT_RGB565
+ OTM8009A_Init(OTM8009A_FORMAT_RBG565, 1);
+#else
+ OTM8009A_Init(OTM8009A_FORMAT_RGB888, 1);
+#endif
+
+ /* Enable the tearing effect line. */
+ HAL_DSI_ShortWrite(&dsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, DSI_SET_TEAR_ON, 0); // Only V-Blanking info
+
+ /* Disable the APB command mode again to go into adapted command mode. (going into high speed mode) */
+ dsiAPBCmd.LPGenShortWriteNoP = DSI_LP_GSW0P_DISABLE;
+ dsiAPBCmd.LPGenShortWriteOneP = DSI_LP_GSW1P_DISABLE;
+ dsiAPBCmd.LPGenShortWriteTwoP = DSI_LP_GSW2P_DISABLE;
+ dsiAPBCmd.LPGenShortReadNoP = DSI_LP_GSR0P_DISABLE;
+ dsiAPBCmd.LPGenShortReadOneP = DSI_LP_GSR1P_DISABLE;
+ dsiAPBCmd.LPGenShortReadTwoP = DSI_LP_GSR2P_DISABLE;
+ dsiAPBCmd.LPGenLongWrite = DSI_LP_GLW_DISABLE;
+ dsiAPBCmd.LPDcsShortWriteNoP = DSI_LP_DSW0P_DISABLE;
+ dsiAPBCmd.LPDcsShortWriteOneP = DSI_LP_DSW1P_DISABLE;
+ dsiAPBCmd.LPDcsShortReadNoP = DSI_LP_DSR0P_DISABLE;
+ dsiAPBCmd.LPDcsLongWrite = DSI_LP_DLW_DISABLE;
+ HAL_DSI_ConfigCommand(&dsiHandle, &dsiAPBCmd);
+
+ HAL_DSI_Refresh(&dsiHandle);
+}
+
+/**
+ * @brief DCS or Generic short/long write command
+ * @param NbrParams: Number of parameters. It indicates the write command mode:
+ * If inferior to 2, a long write command is performed else short.
+ * @param pParams: Pointer to parameter values table.
+ * @retval HAL status
+ */
+void DSI_IO_WriteCmd(uint32_t NbrParams, uint8_t *pParams)
+{
+ if(NbrParams <= 1)
+ {
+ HAL_DSI_ShortWrite(&dsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, pParams[0], pParams[1]);
+ }
+ else
+ {
+ HAL_DSI_LongWrite(&dsiHandle, 0, DSI_DCS_LONG_PKT_WRITE, NbrParams, pParams[NbrParams], pParams);
+ }
+}
+
+/**
+ * @brief Delay function for the OTM8009A driver.
+ *
+ * @param Delay: The requested delay in ms.
+ */
+void OTM8009A_IO_Delay(uint32_t Delay)
+{
+ gfxSleepMilliseconds(Delay);
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
diff --git a/boards/base/STM32F469i-Discovery/CubeHAL/ft6x06.h b/boards/base/STM32F469i-Discovery/CubeHAL/ft6x06.h
new file mode 100644
index 00000000..63545c4b
--- /dev/null
+++ b/boards/base/STM32F469i-Discovery/CubeHAL/ft6x06.h
@@ -0,0 +1,88 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+#ifndef _FT6x06_H
+#define _FT6x06_H
+
+// Slave address
+#define FT6x06_ADDR 0x70//(0x70 >> 1)
+
+// Maximum timeout
+#define FT6x06_TIMEOUT 0x3000
+
+#define FT6x06_DEVICE_MODE 0x00
+#define FT6x06_GESTURE_ID 0x01
+#define FT6x06_TOUCH_POINTS 0x02
+
+#define FT6x06_TOUCH1_EV_FLAG 0x03
+#define FT6x06_TOUCH1_XH 0x03
+#define FT6x06_TOUCH1_XL 0x04
+#define FT6x06_TOUCH1_YH 0x05
+#define FT6x06_TOUCH1_YL 0x06
+#define FT6x06_P1_WEIGHT 0x07
+#define FT6x06_P1_AREA 0x08
+
+#define FT6x06_TOUCH2_EV_FLAG 0x09
+#define FT6x06_TOUCH2_XH 0x09
+#define FT6x06_TOUCH2_XL 0x0A
+#define FT6x06_TOUCH2_YH 0x0B
+#define FT6x06_TOUCH2_YL 0x0C
+#define FT6x06_P2_WEIGHT 0x0D
+#define FT6x06_P2_AREA 0x0E
+
+#define FT6x06_TOUCH3_EV_FLAG 0x0F
+#define FT6x06_TOUCH3_XH 0x0F
+#define FT6x06_TOUCH3_XL 0x10
+#define FT6x06_TOUCH3_YH 0x11
+#define FT6x06_TOUCH3_YL 0x12
+#define FT6x06_P3_WEIGHT 0x13
+#define FT6x06_P3_AREA 0x14
+
+#define FT6x06_TOUCH4_EV_FLAG 0x15
+#define FT6x06_TOUCH4_XH 0x15
+#define FT6x06_TOUCH4_XL 0x16
+#define FT6x06_TOUCH4_YH 0x17
+#define FT6x06_TOUCH4_YL 0x18
+#define FT6x06_P4_WEIGHT 0x19
+#define FT6x06_P4_AREA 0x1A
+
+#define FT6x06_TOUCH5_EV_FLAG 0x1B
+#define FT6x06_TOUCH5_XH 0x1B
+#define FT6x06_TOUCH5_XL 0x1C
+#define FT6x06_TOUCH5_YH 0x1D
+#define FT6x06_TOUCH5_YL 0x1E
+#define FT6x06_P5_WEIGHT 0x1F
+#define FT6x06_P5_AREA 0x20
+
+#define FT6x06_ID_G_THGROUP 0x80
+#define FT6x06_ID_G_THPEAK 0x81
+#define FT6x06_ID_G_THCAL 0x82
+#define FT6x06_ID_G_THWATER 0x83
+#define FT6x06_ID_G_THTEMP 0x84
+#define FT6x06_ID_G_THDIFF 0x85
+#define FT6x06_ID_G_CTRL 0x86
+#define FT6x06_ID_G_TIME_ENTER_MONITOR 0x87
+#define FT6x06_ID_G_PERIODACTIVE 0x88
+#define FT6x06_ID_G_PERIODMONITOR 0x89
+#define FT6x06_RADIAN_VALUE 0x91
+#define FT6x06_OFFSET_LEFT_RIGHT 0x92
+#define FT6x06_OFFSET_UP_DOWN 0x93
+//#define FT6x06_OFFSET_LEFT_RIGHT 0x94
+#define FT6x06_DISTANCE_U_D 0x95
+#define FT6x06_DISTANCE_ZOOM 0x96
+#define FT6x06_ID_G_AUTO_CLB_MODE 0xA0
+#define FT6x06_ID_G_LIB_VERSION_H 0xA1
+#define FT6x06_ID_G_LIB_VERSION_L 0xA2
+#define FT6x06_ID_G_CIPHER 0xA3
+#define FT6x06_ID_G_MODE 0xA4
+#define FT6x06_ID_G_PMODE 0xA5
+#define FT6x06_ID_G_FIRMID 0xA6
+#define FT6x06_ID_G_STATE 0xA7
+#define FT6x06_ID_G_ID 0xA8
+#define FT6x06_ID_G_ERR 0xA9
+
+#endif /* _FT6x06_H */
diff --git a/boards/base/STM32F469i-Discovery/CubeHAL/gmouse_lld_FT6x06_board.h b/boards/base/STM32F469i-Discovery/CubeHAL/gmouse_lld_FT6x06_board.h
new file mode 100644
index 00000000..04f72a72
--- /dev/null
+++ b/boards/base/STM32F469i-Discovery/CubeHAL/gmouse_lld_FT6x06_board.h
@@ -0,0 +1,110 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+#ifndef _GINPUT_LLD_MOUSE_BOARD_H
+#define _GINPUT_LLD_MOUSE_BOARD_H
+
+#include "ft6x06.h"
+#include "stm32f4xx.h"
+#include "stm32f4xx_hal.h"
+
+// Resolution and Accuracy Settings
+#define GMOUSE_FT6x06_PEN_CALIBRATE_ERROR 40
+#define GMOUSE_FT6x06_PEN_CLICK_ERROR 16
+#define GMOUSE_FT6x06_PEN_MOVE_ERROR 14
+#define GMOUSE_FT6x06_FINGER_CALIBRATE_ERROR 50
+#define GMOUSE_FT6x06_FINGER_CLICK_ERROR 28
+#define GMOUSE_FT6x06_FINGER_MOVE_ERROR 24
+
+// How much extra data to allocate at the end of the GMouse structure for the board's use
+#define GMOUSE_FT6x06_BOARD_DATA_SIZE 0
+
+/* The FT6x06 I2C slave address */
+#define FT6x06_SLAVE_ADDR 0x54
+
+I2C_HandleTypeDef i2cHandle;
+/* Maximum speed (400kHz) */
+#define CLOCKSPEED 400000;
+
+static bool_t init_board(GMouse* m, unsigned instance) {
+ (void)m;
+ (void)instance;
+
+ GPIO_InitTypeDef gpioInit;
+ /* I2C1_SCL PB8 */
+ __HAL_RCC_GPIOB_CLK_ENABLE(); // Enable GPIOB clock
+ gpioInit.Pin = GPIO_PIN_8;
+ gpioInit.Mode = GPIO_MODE_AF_OD; // I2C -> Open-drain
+ gpioInit.Pull = GPIO_NOPULL; // Open-drain -> no pull
+ gpioInit.Speed = GPIO_SPEED_FREQ_HIGH; // High speed
+ gpioInit.Alternate = GPIO_AF4_I2C1; // Alternate function 4
+ HAL_GPIO_Init(GPIOB, &gpioInit);
+
+ /* I2C1_SDA PB9 */
+ gpioInit.Pin = GPIO_PIN_9;
+ HAL_GPIO_Init(GPIOB, &gpioInit);
+
+ /* LCD_INT PJ5 */
+ __HAL_RCC_GPIOJ_CLK_ENABLE();
+ gpioInit.Pin = GPIO_PIN_5;
+ gpioInit.Mode = GPIO_MODE_INPUT; // Input mode
+ gpioInit.Pull = GPIO_PULLUP; // Pull-up
+ HAL_GPIO_Init(GPIOJ, &gpioInit);
+
+ /* I2C1 intialization */
+ i2cHandle.Instance = I2C1;
+ i2cHandle.Init.ClockSpeed = CLOCKSPEED;
+ i2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_2; // Normal duty cycle
+ i2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // No dual adressing needed
+ i2cHandle.Init.OwnAddress1 = 0x00;
+ i2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ i2cHandle.Init.OwnAddress2 = 0x00;
+ i2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // All not needed so disabled
+ i2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
+
+ __HAL_RCC_I2C1_CLK_ENABLE();
+
+ if(HAL_I2C_Init(&i2cHandle) == HAL_OK)
+ return TRUE;
+
+ return FALSE;
+}
+
+static GFXINLINE void aquire_bus(GMouse* m) {
+ (void)m;
+}
+
+static GFXINLINE void release_bus(GMouse* m) {
+ (void)m;
+}
+
+static void write_reg(GMouse* m, uint8_t reg, uint8_t val) {
+ (void)m;
+
+ HAL_I2C_Mem_Write(&i2cHandle, FT6x06_SLAVE_ADDR, (uint16_t)reg, I2C_MEMADD_SIZE_8BIT, &val, 1, 1000);
+}
+
+static uint8_t read_byte(GMouse* m, uint8_t reg) {
+ (void)m;
+ uint8_t result;
+
+ HAL_I2C_Mem_Read(&i2cHandle, FT6x06_SLAVE_ADDR, (uint16_t)reg, I2C_MEMADD_SIZE_8BIT, &result, 1, 1000);
+
+ return result;
+}
+
+static uint16_t read_word(GMouse* m, uint8_t reg) {
+ (void)m;
+ uint8_t result[2];
+
+ HAL_I2C_Mem_Read(&i2cHandle, FT6x06_SLAVE_ADDR, (uint16_t)reg, I2C_MEMADD_SIZE_8BIT, result, 2, 1000);
+
+ return (result[0]<<8 | result[1]);
+
+}
+
+#endif /* _GINPUT_LLD_MOUSE_BOARD_H */