Lib for FTDI FT800 Graphic Controller EVE Support up to 512 x 512 pixel resolution. Resistive touch sense Mono audio output SPI Interface
Dependents: FT800_touch_track FT800_JPG
Library for the FT800 Display,Audio and Touch Controller from FTDI. The Code is based on the sample code from FTDI.
FT800 is a graphics chip with added features such as audio playback and touch capabilities. FT800 graphics consist of a rich set of graphics objects (primitive and widgets) that can be used for displaying various menus and screen shots.
http://www.ftdichip.com/Products/ICs/FT800.html
The mbed is talking thru the SPI interface with the graphic engine. We have to set up a list of Commands and send them to the FT800 to get graphics.
Hardware
1. VM800C development modules from FTDI : http://www.ftdichip.com/Products/Modules/VM800C.html
The modules come with different size lcd. 3.5", 4.3" or 5" or without. The picture shows a modified board, because my lcd had a different pinout. The mbed is connected to the pin header on the bottom.
2. EVBEVE-FT800 board from GLYN: http://www.glyn.com/News-Events/Newsletter/Newsletter-2013/October-2013/A-quick-start-for-EVE-Requires-no-basic-knowledge-graphics-sound-and-touch-can-all-be-learned-in-minutes
The module has a 40 pin flex cable connector to connect a display out of the EDT series.
The mbed is connected via the pin header on the left. If you use this board with a EDT display you have to uncomment the #define Inv_Backlite in FT_LCD_Type.h, because the backlight dimming is inverted.
3. ConnectEVE board from MikroElektronika http://www.mikroe.com/add-on-boards/display/connecteve/#headers_10 The board has also a pin header to connect the mbed. - not tested, but it looks like the other boards.
Connection
We need 5 signals to connect to the mbed. SCK, MOSI and MISO are connected to a SPI channel. SS is the chip select signal and PD work as powerdown. The additional INT signal is not used at the moment. It is possible to generate a interrupt signal, but at the moment you have to poll the status register of the FT800 to see if a command is finished.
Software
This lib is based on the demo code from FTDI. If you want to use it, you have to read the programming manual : http://www.ftdichip.com/Support/Documents/ProgramGuides/FT800%20Programmers%20Guide.pdf
See my demo : http://mbed.org/users/dreschpe/code/FT800_touch_track/
or the demo code from FTDI : http://www.ftdichip.com/Support/SoftwareExamples/EVE/FT800_SampleApp_1.0.zip
Diff: FT_Gpu_Hal.cpp
- Revision:
- 0:5e013296b353
- Child:
- 1:bd671a31e765
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FT_Gpu_Hal.cpp Fri Jan 03 15:26:10 2014 +0000 @@ -0,0 +1,537 @@ +#include "FT_Platform.h" +#include "mbed.h" +#include "FT_LCD_Type.h" + + +FT800::FT800(PinName mosi, + PinName miso, + PinName sck, + PinName ss, + PinName intr, + PinName pd) + :_spi(mosi, miso, sck), + _ss(ss), + _f800_isr(InterruptIn(intr)), + _pd(pd) + { + _spi.format(8,0); // 8 bit spi mode 0 + _spi.frequency(10000000); // start with 10 Mhz SPI clock + _ss = 1; // cs high + _pd = 1; // PD high + Bootup(); + } + + +ft_bool_t FT800::Bootup(void){ + Ft_Gpu_Hal_Open(); + BootupConfig(); + + return(1); + } + + +ft_void_t FT800::BootupConfig(void){ + ft_uint8_t chipid; + /* Do a power cycle for safer side */ + Ft_Gpu_Hal_Powercycle( FT_TRUE); + + /* Access address 0 to wake up the FT800 */ + Ft_Gpu_HostCommand( FT_GPU_ACTIVE_M); + Ft_Gpu_Hal_Sleep(20); + + /* Set the clk to external clock */ + Ft_Gpu_HostCommand( FT_GPU_EXTERNAL_OSC); + Ft_Gpu_Hal_Sleep(10); + + + /* Switch PLL output to 48MHz */ + Ft_Gpu_HostCommand( FT_GPU_PLL_48M); + Ft_Gpu_Hal_Sleep(10); + + /* Do a core reset for safer side */ + Ft_Gpu_HostCommand( FT_GPU_CORE_RESET); + + //Read Register ID to check if FT800 is ready. + chipid = Ft_Gpu_Hal_Rd8( REG_ID); + while(chipid != 0x7C) + chipid = Ft_Gpu_Hal_Rd8( REG_ID); + + + // Speed up + _spi.frequency(30000000); // 30 Mhz SPI clock + + /* Configuration of LCD display */ + FT_DispHCycle = my_DispHCycle; + Ft_Gpu_Hal_Wr16( REG_HCYCLE, FT_DispHCycle); + FT_DispHOffset = my_DispHOffset; + Ft_Gpu_Hal_Wr16( REG_HOFFSET, FT_DispHOffset); + FT_DispWidth = my_DispWidth; + Ft_Gpu_Hal_Wr16( REG_HSIZE, FT_DispWidth); + FT_DispHSync0 = my_DispHSync0; + Ft_Gpu_Hal_Wr16( REG_HSYNC0, FT_DispHSync0); + FT_DispHSync1 = my_DispHSync1; + Ft_Gpu_Hal_Wr16( REG_HSYNC1, FT_DispHSync1); + FT_DispVCycle = my_DispVCycle; + Ft_Gpu_Hal_Wr16( REG_VCYCLE, FT_DispVCycle); + FT_DispVOffset = my_DispVOffset; + Ft_Gpu_Hal_Wr16( REG_VOFFSET, FT_DispVOffset); + FT_DispHeight = my_DispHeight; + Ft_Gpu_Hal_Wr16( REG_VSIZE, FT_DispHeight); + FT_DispVSync0 = my_DispVSync0; + Ft_Gpu_Hal_Wr16( REG_VSYNC0, FT_DispVSync0); + FT_DispVSync1 = my_DispVSync1; + Ft_Gpu_Hal_Wr16( REG_VSYNC1, FT_DispVSync1); + FT_DispSwizzle = my_DispSwizzle; + //Ft_Gpu_Hal_Wr8( REG_SWIZZLE, FT_DispSwizzle); + FT_DispPCLKPol = my_DispPCLKPol; + //Ft_Gpu_Hal_Wr8( REG_PCLK_POL, FT_DispPCLKPol); + FT_DispPCLK = my_DispPCLK; + //Ft_Gpu_Hal_Wr8( REG_PCLK,FT_DispPCLK);//after this display is visible on the LCD + + Ft_Gpu_Hal_Wr16( REG_PWM_HZ, 1000); + +#ifdef Inv_Backlite + Ft_Gpu_Hal_Wr16( REG_PWM_DUTY, 0); +#else + Ft_Gpu_Hal_Wr16( REG_PWM_DUTY, 100); +#endif + + Ft_Gpu_Hal_Wr8( REG_GPIO_DIR,0x80); //| Ft_Gpu_Hal_Rd8( REG_GPIO_DIR)); + Ft_Gpu_Hal_Wr8( REG_GPIO,0x080); //| Ft_Gpu_Hal_Rd8( REG_GPIO)); + + Ft_Gpu_Hal_Wr32( RAM_DL, CLEAR(1,1,1)); + Ft_Gpu_Hal_Wr32( RAM_DL+4, DISPLAY()); + Ft_Gpu_Hal_Wr32( REG_DLSWAP,1); + + Ft_Gpu_Hal_Wr16( REG_PCLK, FT_DispPCLK); + + /* Touch configuration - configure the resistance value to 1200 - this value is specific to customer requirement and derived by experiment */ + Ft_Gpu_Hal_Wr16( REG_TOUCH_RZTHRESH,1200); + +} + + + +/* API to initialize the SPI interface */ +ft_bool_t FT800::Ft_Gpu_Hal_Init() +{ + // is done in constructor + return 1; +} + + +ft_bool_t FT800::Ft_Gpu_Hal_Open() +{ + ft_cmd_fifo_wp = ft_dl_buff_wp = 0; + status = FT_GPU_HAL_OPENED; + return 1; +} + +ft_void_t FT800::Ft_Gpu_Hal_Close( ) +{ + status = FT_GPU_HAL_CLOSED; +} + +ft_void_t FT800::Ft_Gpu_Hal_DeInit() +{ + +} + +/*The APIs for reading/writing transfer continuously only with small buffer system*/ +ft_void_t FT800::Ft_Gpu_Hal_StartTransfer( FT_GPU_TRANSFERDIR_T rw,ft_uint32_t addr) +{ + if (FT_GPU_READ == rw){ + _ss = 0; // cs low + _spi.write(addr >> 16); + _spi.write(addr >> 8); + _spi.write(addr & 0xff); + _spi.write(0); //Dummy Read Byte + status = FT_GPU_HAL_READING; + }else{ + _ss = 0; // cs low + _spi.write(0x80 | (addr >> 16)); + _spi.write(addr >> 8); + _spi.write(addr & 0xff); + status = FT_GPU_HAL_WRITING; + } +} + + +/*The APIs for writing transfer continuously only*/ +ft_void_t FT800::Ft_Gpu_Hal_StartCmdTransfer( FT_GPU_TRANSFERDIR_T rw, ft_uint16_t count) +{ + Ft_Gpu_Hal_StartTransfer( rw, ft_cmd_fifo_wp + RAM_CMD); +} + +ft_uint8_t FT800::Ft_Gpu_Hal_TransferString( const ft_char8_t *string) +{ + ft_uint16_t length = strlen(string); + while(length --){ + Ft_Gpu_Hal_Transfer8( *string); + string ++; + } + //Append one null as ending flag + Ft_Gpu_Hal_Transfer8( 0); +} + + +ft_uint8_t FT800::Ft_Gpu_Hal_Transfer8( ft_uint8_t value) +{ + return _spi.write(value); +} + + +ft_uint16_t FT800::Ft_Gpu_Hal_Transfer16( ft_uint16_t value) +{ + ft_uint16_t retVal = 0; + + if (status == FT_GPU_HAL_WRITING){ + Ft_Gpu_Hal_Transfer8( value & 0xFF);//LSB first + Ft_Gpu_Hal_Transfer8( (value >> 8) & 0xFF); + }else{ + retVal = Ft_Gpu_Hal_Transfer8( 0); + retVal |= (ft_uint16_t)Ft_Gpu_Hal_Transfer8( 0) << 8; + } + + return retVal; +} + +ft_uint32_t FT800::Ft_Gpu_Hal_Transfer32( ft_uint32_t value) +{ + ft_uint32_t retVal = 0; + if (status == FT_GPU_HAL_WRITING){ + Ft_Gpu_Hal_Transfer16( value & 0xFFFF);//LSB first + Ft_Gpu_Hal_Transfer16( (value >> 16) & 0xFFFF); + }else{ + retVal = Ft_Gpu_Hal_Transfer16( 0); + retVal |= (ft_uint32_t)Ft_Gpu_Hal_Transfer16( 0) << 16; + } + return retVal; +} + +ft_void_t FT800::Ft_Gpu_Hal_EndTransfer( ) +{ + _ss = 1; + status = FT_GPU_HAL_OPENED; +} + + +ft_uint8_t FT800::Ft_Gpu_Hal_Rd8( ft_uint32_t addr) +{ + ft_uint8_t value; + Ft_Gpu_Hal_StartTransfer( FT_GPU_READ,addr); + value = Ft_Gpu_Hal_Transfer8( 0); + Ft_Gpu_Hal_EndTransfer( ); + return value; +} +ft_uint16_t FT800::Ft_Gpu_Hal_Rd16( ft_uint32_t addr) +{ + ft_uint16_t value; + Ft_Gpu_Hal_StartTransfer( FT_GPU_READ,addr); + value = Ft_Gpu_Hal_Transfer16( 0); + Ft_Gpu_Hal_EndTransfer( ); + return value; +} +ft_uint32_t FT800::Ft_Gpu_Hal_Rd32( ft_uint32_t addr) +{ + ft_uint32_t value; + Ft_Gpu_Hal_StartTransfer( FT_GPU_READ,addr); + value = Ft_Gpu_Hal_Transfer32( 0); + Ft_Gpu_Hal_EndTransfer( ); + return value; +} + +ft_void_t FT800::Ft_Gpu_Hal_Wr8( ft_uint32_t addr, ft_uint8_t v) +{ + Ft_Gpu_Hal_StartTransfer( FT_GPU_WRITE,addr); + Ft_Gpu_Hal_Transfer8( v); + Ft_Gpu_Hal_EndTransfer( ); +} +ft_void_t FT800::Ft_Gpu_Hal_Wr16( ft_uint32_t addr, ft_uint16_t v) +{ + Ft_Gpu_Hal_StartTransfer( FT_GPU_WRITE,addr); + Ft_Gpu_Hal_Transfer16( v); + Ft_Gpu_Hal_EndTransfer( ); +} +ft_void_t FT800::Ft_Gpu_Hal_Wr32( ft_uint32_t addr, ft_uint32_t v) +{ + Ft_Gpu_Hal_StartTransfer( FT_GPU_WRITE,addr); + Ft_Gpu_Hal_Transfer32( v); + Ft_Gpu_Hal_EndTransfer( ); +} + +ft_void_t FT800::Ft_Gpu_HostCommand( ft_uint8_t cmd) +{ + _ss = 0; + _spi.write(cmd); + _spi.write(0); + _spi.write(0); + _ss = 1; +} + +ft_void_t FT800::Ft_Gpu_ClockSelect( FT_GPU_PLL_SOURCE_T pllsource) +{ + Ft_Gpu_HostCommand( pllsource); +} + +ft_void_t FT800::Ft_Gpu_PLL_FreqSelect( FT_GPU_PLL_FREQ_T freq) +{ + Ft_Gpu_HostCommand( freq); +} + +ft_void_t FT800::Ft_Gpu_PowerModeSwitch( FT_GPU_POWER_MODE_T pwrmode) +{ + Ft_Gpu_HostCommand( pwrmode); +} + +ft_void_t FT800::Ft_Gpu_CoreReset( ) +{ + Ft_Gpu_HostCommand( 0x68); +} + + +ft_void_t FT800::Ft_Gpu_Hal_Updatecmdfifo( ft_uint16_t count) +{ + ft_cmd_fifo_wp = ( ft_cmd_fifo_wp + count) & 4095; + //4 byte alignment + ft_cmd_fifo_wp = ( ft_cmd_fifo_wp + 3) & 0xffc; + Ft_Gpu_Hal_Wr16( REG_CMD_WRITE, ft_cmd_fifo_wp); +} + + +ft_uint16_t FT800::Ft_Gpu_Cmdfifo_Freespace( ) +{ + ft_uint16_t fullness,retval; + + fullness = ( ft_cmd_fifo_wp - Ft_Gpu_Hal_Rd16( REG_CMD_READ)) & 4095; + retval = (FT_CMD_FIFO_SIZE - 4) - fullness; + return (retval); +} + +ft_void_t FT800::Ft_Gpu_Hal_WrCmdBuf( ft_uint8_t *buffer,ft_uint16_t count) +{ + ft_uint32_t length =0, SizeTransfered = 0; + +#define MAX_CMD_FIFO_TRANSFER Ft_Gpu_Cmdfifo_Freespace( ) + do { + length = count; + if (length > MAX_CMD_FIFO_TRANSFER){ + length = MAX_CMD_FIFO_TRANSFER; + } + Ft_Gpu_Hal_CheckCmdBuffer( length); + + Ft_Gpu_Hal_StartCmdTransfer( FT_GPU_WRITE,length); + + SizeTransfered = 0; + while (length--) { + Ft_Gpu_Hal_Transfer8( *buffer); + buffer++; + SizeTransfered ++; + } + length = SizeTransfered; + + Ft_Gpu_Hal_EndTransfer( ); + Ft_Gpu_Hal_Updatecmdfifo( length); + + Ft_Gpu_Hal_WaitCmdfifo_empty( ); + + count -= length; + }while (count > 0); +} + + +ft_void_t FT800::Ft_Gpu_Hal_WrCmdBufFromFlash( FT_PROGMEM ft_prog_uchar8_t *buffer,ft_uint16_t count) +{ + ft_uint32_t length =0, SizeTransfered = 0; + +#define MAX_CMD_FIFO_TRANSFER Ft_Gpu_Cmdfifo_Freespace( ) + do { + length = count; + if (length > MAX_CMD_FIFO_TRANSFER){ + length = MAX_CMD_FIFO_TRANSFER; + } + Ft_Gpu_Hal_CheckCmdBuffer( length); + + Ft_Gpu_Hal_StartCmdTransfer( FT_GPU_WRITE,length); + + + SizeTransfered = 0; + while (length--) { + Ft_Gpu_Hal_Transfer8( ft_pgm_read_byte_near(buffer)); + buffer++; + SizeTransfered ++; + } + length = SizeTransfered; + + Ft_Gpu_Hal_EndTransfer( ); + Ft_Gpu_Hal_Updatecmdfifo( length); + + Ft_Gpu_Hal_WaitCmdfifo_empty( ); + + count -= length; + }while (count > 0); +} + + +ft_void_t FT800::Ft_Gpu_Hal_CheckCmdBuffer( ft_uint16_t count) +{ + ft_uint16_t getfreespace; + do{ + getfreespace = Ft_Gpu_Cmdfifo_Freespace( ); + }while(getfreespace < count); +} + +ft_void_t FT800::Ft_Gpu_Hal_WaitCmdfifo_empty( ) +{ + while(Ft_Gpu_Hal_Rd16( REG_CMD_READ) != Ft_Gpu_Hal_Rd16( REG_CMD_WRITE)); + + ft_cmd_fifo_wp = Ft_Gpu_Hal_Rd16( REG_CMD_WRITE); +} + +ft_void_t FT800::Ft_Gpu_Hal_WaitLogo_Finish( ) +{ + ft_int16_t cmdrdptr,cmdwrptr; + + do{ + cmdrdptr = Ft_Gpu_Hal_Rd16( REG_CMD_READ); + cmdwrptr = Ft_Gpu_Hal_Rd16( REG_CMD_WRITE); + }while ((cmdwrptr != cmdrdptr) || (cmdrdptr != 0)); + ft_cmd_fifo_wp = 0; +} + + +ft_void_t FT800::Ft_Gpu_Hal_ResetCmdFifo( ) +{ + ft_cmd_fifo_wp = 0; +} + + +ft_void_t FT800::Ft_Gpu_Hal_WrCmd32( ft_uint32_t cmd) +{ + Ft_Gpu_Hal_CheckCmdBuffer( sizeof(cmd)); + + Ft_Gpu_Hal_Wr32( RAM_CMD + ft_cmd_fifo_wp,cmd); + + Ft_Gpu_Hal_Updatecmdfifo( sizeof(cmd)); +} + + +ft_void_t FT800::Ft_Gpu_Hal_ResetDLBuffer( ) +{ + ft_dl_buff_wp = 0; +} + +/* Toggle PD_N pin of FT800 board for a power cycle*/ +ft_void_t FT800::Ft_Gpu_Hal_Powercycle( ft_bool_t up) +{ + if (up) + { + //Toggle PD_N from low to high for power up switch + _pd = 0; + Ft_Gpu_Hal_Sleep(20); + + _pd = 1; + Ft_Gpu_Hal_Sleep(20); + }else + { + //Toggle PD_N from high to low for power down switch + _pd = 1; + Ft_Gpu_Hal_Sleep(20); + + _pd = 0; + Ft_Gpu_Hal_Sleep(20); + } +} + +ft_void_t FT800::Ft_Gpu_Hal_WrMemFromFlash( ft_uint32_t addr,const ft_prog_uchar8_t *buffer, ft_uint32_t length) +{ + ft_uint32_t SizeTransfered = 0; + + Ft_Gpu_Hal_StartTransfer( FT_GPU_WRITE,addr); + + while (length--) { + Ft_Gpu_Hal_Transfer8( ft_pgm_read_byte_near(buffer)); + buffer++; + } + + Ft_Gpu_Hal_EndTransfer( ); +} + +ft_void_t FT800::Ft_Gpu_Hal_WrMem( ft_uint32_t addr,const ft_uint8_t *buffer, ft_uint32_t length) +{ + ft_uint32_t SizeTransfered = 0; + + Ft_Gpu_Hal_StartTransfer( FT_GPU_WRITE,addr); + + while (length--) { + Ft_Gpu_Hal_Transfer8( *buffer); + buffer++; + } + + Ft_Gpu_Hal_EndTransfer( ); +} + + +ft_void_t FT800::Ft_Gpu_Hal_RdMem( ft_uint32_t addr, ft_uint8_t *buffer, ft_uint32_t length) +{ + ft_uint32_t SizeTransfered = 0; + + Ft_Gpu_Hal_StartTransfer( FT_GPU_READ,addr); + + while (length--) { + *buffer = Ft_Gpu_Hal_Transfer8( 0); + buffer++; + } + + Ft_Gpu_Hal_EndTransfer( ); +} + +ft_int32_t FT800::Ft_Gpu_Hal_Dec2Ascii(ft_char8_t *pSrc,ft_int32_t value) +{ + ft_int16_t Length; + ft_char8_t *pdst,charval; + ft_int32_t CurrVal = value,tmpval,i; + ft_char8_t tmparray[16],idx = 0; + + Length = strlen(pSrc); + pdst = pSrc + Length; + + if(0 == value) + { + *pdst++ = '0'; + *pdst++ = '\0'; + return 0; + } + + if(CurrVal < 0) + { + *pdst++ = '-'; + CurrVal = - CurrVal; + } + /* insert the value */ + while(CurrVal > 0){ + tmpval = CurrVal; + CurrVal /= 10; + tmpval = tmpval - CurrVal*10; + charval = '0' + tmpval; + tmparray[idx++] = charval; + } + + for(i=0;i<idx;i++) + { + *pdst++ = tmparray[idx - i - 1]; + } + *pdst++ = '\0'; + + return 0; +} + + +ft_void_t FT800::Ft_Gpu_Hal_Sleep(ft_uint16_t ms) +{ + wait_ms(ms); +} + + + +