Author Topic: FT800  (Read 14294 times)

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3239
    • View Profile
    • uTasker
FT800
« on: July 22, 2017, 11:19:16 AM »
Hi All

This topic has been deviated from a more general thread (based on K64F) and continued here.

Original announcement:
3. Non-blocking FT800 support (this is an FTDI graphics controller which can be connected between an SPI interface and various display types to off-load graphic processing) has been added to the project along with full integration of FTDI's FT800 emulator in the the uTasker simulator so that the graphics controller/display is also simulated. Powerful graphics applications are thus possible with small, cheap Kinetis parts since little RAM and just the SPI is required.

Original additional question:
Also does the library already support FT81X too? If not do you plan on supporting those in the future?

Specific technical question:
You use "FLUSH_LCD_SPI_RX(4);" when writing/reading from the coprocessor but I had to comment it out for my software to work as there were never 4 bytes to flush (only 2).
I haven't found this flush in other FT81X libraries can you explain if and why it is needed?


Continues here....

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3239
    • View Profile
    • uTasker
Re: FT800
« Reply #1 on: July 22, 2017, 11:33:47 AM »
Paul

This is the macro:

#define FLUSH_LCD_SPI_RX(count)             {int i = count; while (i != 0) {WAIT_LCD_SPI_RECEPTION_END(); (void)SPI0_POPR; CLEAR_LCD_SPI_RECEPTION_FLAG(); i--;}}

It is used to read "count" dummy received bytes from the SPI. Of course the count value must match with the number of bytes that have been sent (and will be received) and if greater it will wait forever and thus fail.

There are 6 locations in the code where 4 bytes are flushed - for example (any typical)
    WRITE_LCD_SPI_CMD0_FIRST(ucCommand);                                 // assert the CS line and send the command
    WRITE_LCD_SPI_CMD0(0);                                               // send three further dummy bytes
    WRITE_LCD_SPI_CMD0(0);
    WRITE_LCD_SPI_CMD0_LAST(0);                                          // remove the CS line after final byte
    FLUSH_LCD_SPI_RX(4);                                                 // ensure that the activity has terminated before quitting so that further reads/writes can't disturb


Here 4 bytes have been sent previous to executing this. In all cases there are 4 bytes that have been transmitted and so I don't find any location where there were only 2 that needed flushing.


Note that the macros are specifically for a Kinetis DSPI with a FIFO depth of 4 and using automatic chip select control (as in the K64F, which was used as test vehicle). The idea is that the macros can be easily adapted for other SPIs (without FIFO ad/or without CS control). In the case of no FIFO the flush macro would be dummy.
WRITE_LCD_SPI_CMD0_FIRST() would first manually assert the CS line and sent a byte.
WRITE_LCD_SPI_CMD0() would first wait for the transmission/reception to complete, send the next byte and flush the previous.
WRITE_LCD_SPI_CMD0_LAST() would do the same as WRITE_LCD_SPI_CMD0() but then also negate the CS line manually.
Theoretically the code should thus accommodate all SPI types with only macro adjustments to suit.

Regards

Mark


Following thread entry:

Hi Mark,

just wanted to inform you that my colleague got it working!

He is not in the office yet so I can't give you the details but he told me yesterday that it had to do mainly with wrong SPI timings.

Regards

Paul





Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3239
    • View Profile
    • uTasker
Re: FT800
« Reply #2 on: July 22, 2017, 11:35:53 AM »
Hi Paul

Thank you for the feedback. I am pleased to hear that the FT811 is operating.
I would be interested in knowing what needed to be adapted to get the SPI timing correct for it - that is, if it needed macro changes or just a different SPI controller setup (phases, speeds, CS delays etc.).

Regards

Mark

Offline kingston

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: FT800
« Reply #3 on: August 07, 2017, 09:38:34 AM »
Hi Mark,

I will talk to my colleague as soon as I see him and let you know the details :)

Regards

Paul

Offline kingston

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: FT800
« Reply #4 on: August 14, 2017, 07:36:45 AM »
Hi Mark,

here are the SPI changes needed to make the display work on our KBED64 (set config to FRDMK64):

app_hw_kinetis.h:

Code: [Select]
#if defined FT800_GLCD_MODE                                              // {31}
    #define ENABLE_BACKLIGHT()

#define LCD_SPI_MCR SPI1_MCR
#define LCD_SPI_SR SPI1_SR
#define LCD_SPI_POPR SPI1_POPR

    //#define FLUSH_LCD_SPI_FIFO_AND_FLAGS()      SPI1_MCR |= SPI_MCR_CLR_RXF; SPI1_SR = (SPI_SR_EOQF | SPI_SR_TFUF | SPI_SR_TFFF | SPI_SR_RFOF | SPI_SR_RFDF)
#define FLUSH_LCD_SPI_FIFO() LCD_SPI_MCR |= (SPI_MCR_CLR_RXF | SPI_MCR_CLR_TXF); //clear fifo and fifo-counter of rx/tx fifo
#define FLUSH_LCD_SPI_FLAGS() LCD_SPI_SR = (SPI_SR_TCF | SPI_SR_EOQF | SPI_SR_TFUF | SPI_SR_TFFF | SPI_SR_RFOF | SPI_SR_RFDF);
#define FLUSH_LCD_SPI_FIFO_AND_FLAGS() FLUSH_LCD_SPI_FIFO();FLUSH_LCD_SPI_FLAGS();

#define CLEAR_LCD_SPI_RECEPTION_FLAG()      LCD_SPI_SR |= SPI_SR_RFDF

#define WAIT_LCD_SPI_RECEPTION_END()        while (!(SPI1_SR & SPI_SR_RFDF)) {};
#define READ_LCD_SPI_FLUSH_DATA()           (unsigned char)LCD_SPI_POPR
#define FLUSH_LCD_SPI_DATA() (void) LCD_SPI_POPR

#define FT800_SPI_CTAR_CSSCK 0x000002000 //time cs enable ->sck
#define FT800_SPI_CTAR_ASC 0x000000200 //time sck ->cs disable (time after sck)
#define FT800_SPI_CTAR_DT 0x000000020 //time cs min. disabled (required 0)

    #define CONFIGURE_GLCD()          POWER_UP(6, SIM_SCGC6_SPI1);\
                                      _CONFIG_PORT_OUTPUT(A, PORTA_BIT2,PORT_SRE_FAST);_CLEARBITS(A, PORTA_BIT2);\
                                      _CONFIG_PERIPHERAL(E, 4, (PE_4_SPI1_PCS0 | PORT_SRE_FAST | PORT_DSE_HIGH));\
                                      _CONFIG_PERIPHERAL(E, 2, (PE_2_SPI1_SCK | PORT_SRE_FAST | PORT_DSE_HIGH));\
                                      _CONFIG_PERIPHERAL(E, 1, (PE_1_SPI1_SOUT | PORT_SRE_FAST | PORT_DSE_HIGH));\
                                      _CONFIG_PERIPHERAL(E, 3, PE_3_SPI1_SIN);\
                                      SPI1_MCR = (SPI_MCR_MSTR | SPI_MCR_DCONF_SPI | SPI_MCR_CLR_RXF | SPI_MCR_CLR_TXF | SPI_MCR_PCSIS_CS0 | SPI_MCR_PCSIS_CS1 | SPI_MCR_PCSIS_CS2 | SPI_MCR_PCSIS_CS3 | SPI_MCR_PCSIS_CS4 | SPI_MCR_PCSIS_CS5);\
                                      SPI1_CTAR0 = (SPI_CTAR_FMSZ_8 | SPI_CTAR_PDT_7 | SPI_CTAR_BR_4 | FT800_SPI_CTAR_CSSCK | FT800_SPI_CTAR_ASC | FT800_SPI_CTAR_DT);
    #if !defined _WINDOWS
        #define _FT8XXEMU_cs(x)
        #define _FT8XXEMU_transfer(x)
    #endif
#define WRITE_LCD_SPI_CMD0_FIRST(byte)      FLUSH_LCD_SPI_FIFO_AND_FLAGS(); _FT8XXEMU_cs(1); WRITE_LCD_SPI_CMD0(byte); // assert the chip select line and send a byte
    #define WRITE_LCD_SPI_CMD0(byte)            SPI1_PUSHR = (byte | SPI_PUSHR_CONT | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0); _FT8XXEMU_transfer(byte); WAIT_LCD_SPI_RECEPTION_END(); FLUSH_LCD_SPI_DATA(); CLEAR_LCD_SPI_RECEPTION_FLAG();// write a single byte to the output FIFO - assert CS line
    #define WRITE_LCD_SPI_CMD0_LAST(byte)       SPI1_PUSHR = (byte | SPI_PUSHR_EOQ | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0); WAIT_LCD_SPI_RECEPTION_END(); FLUSH_LCD_SPI_DATA(); _FT8XXEMU_transfer(byte); _FT8XXEMU_cs(1); // write final byte to output FIFO - this will negate the CS line when complete




    #if defined _WINDOWS
        #define READ_LCD_SPI_CMD0(byte, value) SPI1_PUSHR = (byte | SPI_PUSHR_CONT | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0); value = _FT8XXEMU_transfer(byte)
        #define READ_LCD_SPI_CMD0_LAST(byte, value) SPI1_PUSHR = (byte | SPI_PUSHR_EOQ | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0); value = _FT8XXEMU_transfer(byte); _FT8XXEMU_cs(1)
    #else
        #define READ_LCD_SPI_CMD0(byte, value)  SPI1_PUSHR = (byte | SPI_PUSHR_CONT | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0); WAIT_LCD_SPI_RECEPTION_END(); value = READ_LCD_SPI_FLUSH_DATA(); CLEAR_LCD_SPI_RECEPTION_FLAG()
        #define READ_LCD_SPI_CMD0_LAST(byte, value) SPI1_PUSHR = (byte | SPI_PUSHR_EOQ | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0); WAIT_LCD_SPI_RECEPTION_END(); value = READ_LCD_SPI_FLUSH_DATA(); CLEAR_LCD_SPI_RECEPTION_FLAG()
    #endif
    #define FLUSH_LCD_SPI_RX(count)    //  (void)SPI1_POPR; CLEAR_LCD_SPI_RECEPTION_FLAG();     //{int i = count; while (i != 0) {WAIT_LCD_SPI_RECEPTION_END(); (void)SPI1_POPR; CLEAR_LCD_SPI_RECEPTION_FLAG(); i--;}}
    #define GLCD_RST_L()              _CLEARBITS(A, PORTA_BIT2);
    #define GLCD_RST_H()              _SETBITS(A, PORTA_BIT2);
    #if defined _WINDOWS
        #define MAX_GLCD_WRITE_BURST   10000                             // the maximum number of writes to the GLCD before the task yields
    #else
        #define MAX_GLCD_WRITE_BURST   1000                              // the maximum number of writes to the GLCD before the task yields
    #endif

  //#define GLCD_BACKLIGHT_CONTROL                                       // (requires SUPPORT_PWM_MODULE)
  //#define TEMP_HUM_TEST
  //#define VARIABLE_PIXEL_COLOUR                                        // support control of background and pixel colors

    #define _GLCD_BACKLIGHT_TIMER         6                              // PWM channel 6 (TC)
    #define _GLCD_TIMER_MODE_OF_OPERATION (PWM_PRESCALER_128 | PWM_SCALED_CLOCK_INPUT | PWM_POLARITY)
    #define _GLCD_BACKLIGHT_PWM_FREQUENCY (unsigned char)(PWM_US_DELAY(PWM_FREQUENCY_VALUE(2000 * 128)))
#endif

Thank you for your hard work!

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3239
    • View Profile
    • uTasker
Re: FT800
« Reply #5 on: August 14, 2017, 03:06:00 PM »
Thank your

I have put this in the code as reference!

Regards

Mark