BRT Community

Please login or register.

Login with username, password and session length
Advanced search  


Welcome to the Bridgetek Community!

Please read our Welcome Note

Technical Support enquires
please contact the team
@ Bridgetek Support

Please refer to our website for detailed information on all our products - Bridgetek - Bridging Technology

Author Topic: SPI comm between PIC32 chip on UBW32 board and FT810 chip on VM81050A-D board  (Read 14232 times)


  • Newbie
  • *
  • Posts: 4
    • View Profile

Hello All,
I've been trying to get  SPI working between PIC32 on UBW32 and FT810 chip on VM81050A-D board. I have worked with SPI on PIC32 + MPLAB X IDE etc before this and never faced this issue.
#define SPI_CSELECT             LATGbits.LATG9
#define SPI_SCLK_DIR           TRISGbits.TRISG6 //SPI SCLK (SCK2)
#define SPI_SCLK                  PORTGbits.RG6
#define SPI_OUT_DIR            TRISGbits.TRISG8 //SPI DATA (SD02)
#define SPI_OUT                    LATGbits.LATG8
#define SPI_IN_DIR               TRISGbits.TRISG7 //SPI DATA (SDI2)
#define SPI_IN                       LATGbits.LATG7 //LATGbits.LATG7
#define SPI_PD_DIR               TRISBbits.TRISB8 //SPI PD pin
#define SPI_PD                      LATBbits.LATB8
#define SPI_INT_DIR              TRISBbits.TRISB5 //SPI INT pin
#define SPI_INT                     LATBbits.LATB5
ODCG = 0;                                       //Turn OFF open-drain outputs on PORTG
RE1_LED_DIR = OUTPUT;                  //Debug LED RE1 present on MCU board
SPI_CSELECT_DIR = OUTPUT;           //Chip select for SPI
SPI_SCLK_DIR = OUTPUT;                //Serial Clock
SPI_OUT_DIR = OUTPUT;                 //Data byte MOSI
//0x200|0x80: Change Notice Enable for RG7 (CNEN9) and RB5 (CNEN7)
//0x200|0x80: Internal pull-up Enable for RG7 (CNPUE9) and RB5 (CNPUE7)
SPI_IN_DIR = INPUT;                     //Data byte MISO
SPI_PD_DIR = OUTPUT;                  //Controls PD pin
SPI_INT_DIR = INPUT;                   //Comes from FT810
I am using the example project referenced in BRT_AN_006 by Bridgetek (it uses 8 bit PIC but I changed the config bits to use a PIC32 instead).
SD0 pin of PIC32 is connected to MOSI of FT810.
SDI pin of PIC32 is connected to MISO of FT810.
I am able to drive the MOSI pin with no issues(verified using a picoscope).
MISO pin is not being driven properly (Attached an image) - the signal is pulled down to the ground but it doesn't go back up to 3.3 V.
Any suggestions?
I tried adding a pullup resistor to the slave side (but SPI is not open drain but I still tried) but didn't help.
I tried SPI loopback test by connecting SDO pin to SDI pin and it works. So, I am assuming that my SPI configuration is correct.
SPI config:
SPI clk frequencies tried: 10 MHZ, 5 MHz
//Disable All SPI 2 Interrupts
//Clear All SPI 2 Interrupt Flags
//Stop and Reset the SPI Module by clearing the ON bit
SPI2CONbits.ON = 0; //Disable SPI 2
//Clear the SPI2 receive buffer
SPI2BUF = 0;
//SPI2 Interrupts --------------------------------------------------------
IPC7CLR = _IPC7_SPI2IP_MASK; //Clear Interrupt Priority
//Set SPI2 Priority to 1
IPC7CLR = _IPC7_SPI2IS_MASK; //Clear Sub Priority
//Set SPI2 Sub-Priority to 0
//Do not enable SPI2 interrupts here
//Clear All SPI 2 Interrupt Flags
//SPI2 Interrupts --------------------------------------------------------
//SET Clock Frequency
//Clear SPI receive buffer overflow indication bit
//Bit 28 MSSEN: Master Mode Slave Select Enable bit
SPI2CONbits.MSSEN = 1; //(1=SS Pin Controlled by SPI Module)
//Bit 16 ENHBUF : Enhanced Buffer Enable bit
//Bit 12 DISSDO : Disable SDOx pin bit
SPI2CONbits.DISSDO = 0; //Pin controlled by SPI
//Bit 10-11 MODE <32,16> : 32/16-bit Communication Select bits
SPI2CONbits.MODE16 = 0; //8 - Bit Mode if Both Zeros
SPI2CONbits.MODE32 = 0; //8 - Bit Mode if Both Zeros
//Bit 8 CKE: SPI Clock Edge Select Bit
SPI2CONbits.CKE = 1; //(0=serial o/p data changes on clk trans from idle to active)
//Bit 6 CKP : Polarity Select bit
SPI2CONbits.CKP = 0; //(0=Idle State Low)
//Bit 5 MSTEN : Master Mode Enable bit
SPI2CONbits.MSTEN = 1; //(1=Master Mode)
//Bit 0-1 SRXISEL <1:0> : SPI Receive Buffer Full Interrupt Mode bits
Clock settings:
#ifdef    MAIN_FREQ_80_MHZ
* Physical SYS BCLK Freq = 8 MHZ
* Required SYS CLK Freq = 80 Mhz
* So, Req. SYS CLK Freq = (8 MHZ / 2 * 20 / 1) = 80 MHZ
//DEVCFG2 - Clock Dividers
//Divides physical i/p SYS CLK frequency (8MHZ) by 2
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider (2x Divider)
//Multiplies the i/p SYS CLK freq (8 MHZ/2 in prev line) by 20
#pragma config FPLLMUL = MUL_20 // PLL Multiplier (20x Multiplier)
//Divides the o/p SYS CLK freq from the prev steps by 1
#pragma config FPLLODIV = DIV_1 // System PLL Output Clock Divider (PLL Divide by 1)
#ifdef PB_FREQ_10_MHZ
#pragma config FPBDIV = DIV_8 //Peripheral Clock Divisor (Pb_Clk is Sys_Clk/8)
* SPI 2
* if PB F = 10 MHZ, SPI REG = 0, SCK Freq. = 5 MHz
#ifdef PB_FREQ_10_MHZ
#define SPI_SCK_FREQ 0 //PBF=10MHZ, divider of 2 to produce SCK = 5MHz
Config Bits:
#pragma config FSRSSEL = PRIORITY_7 // SRS Select (SRS Priority 7)
#pragma config FMIIEN = OFF // Ethernet RMII/MII Enable (RMII Enabled)
#pragma config FETHIO = OFF // Ethernet I/O Pin Select (Alternate Ethernet I/O)
#pragma config FCANIO = ON // CAN I/O Pin Select (Default CAN I/O)
#pragma config FUSBIDIO = OFF // USB USID Selection (Controlled by Port Function)
#pragma config FVBUSONIO = OFF // USB VBUS ON Selection (Controlled by Port Function)
#pragma config UPLLIDIV = DIV_1 // USB PLL Input Divider (1x Divider)
#pragma config UPLLEN = OFF // USB PLL Enable (Disabled and Bypassed)
#pragma config FNOSC = FRCPLL // Oscillator Selection Bits
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Disabled)
#pragma config IESO = ON // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = EC // Primary Oscillator Configuration (External clock mode) EC = Clean oscillator signal
#pragma config OSCIOFNC = ON // CLKO Output Signal Active on the OSCO Pin (Enabled)
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS256 // Watchdog Timer Postscaler (1:256) i.e. WDT Period = 1 ms * 2^Prescaler = 256 mS
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls)). It can be enabled in SW
#pragma config DEBUG = OFF // Background Debugger Disable (Debugger is enabled)
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (ICE EMUC2/EMUD2 pins shared with PGC2/PGD2)
#pragma config PWP = OFF // Program Flash Write Protect (Disable)
#pragma config BWP = OFF // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF // Code Protect (Protection Disabled)
The power supply that I am using can support up to 2 A and so that is not causing the issue.
I've been sitting on this for weeks, I would be eternally grateful for any help or a direction to debug further. Thanks for tolerating my superlong post.

Also I already checked the following on my setup:
1) MISO pin is not shorted to ground.
2) MISO pin is not floating when idle. One thing I noticed is that with CKP = 0 OR 1 and CKE = 0, MOSI line is low when idle and goes high when sending data and MISO is held at 3.3 V when idle and pulled down when clock pulse starts to send data and it is not pulled back up properly. Does this give any clues that I am missing to catch?
3) PD_N pin is pulled high during operation (After turning ON SPI mode and before starting communication, I pulled PD low, waited 20 ms and back high, waited 20 ms as the example has a comment that says that this step is required), CS# is toggled as appropriate i.e., coincides with the clock pulses that the master sends as expected. I also played around with this delay duration and it doesn't make a difference.
4) I just verified - debug setting is OFF in the config bit settings.
5) I tried different combinations of CKE and CKP as well and the issue is still present.
And FT81x is supposed to be woken up by sending 0x00 0x00 0x00 first. I am not sure if this step doesn't wake up FT81x for some reason? I am not sure if I am missing something here...
This is my initialization sequence:
// ----------------------- Cycle PD pin to reset device --------------------
MCU_PDlow(); // PD low to reset device
delay_ms(20); //atleast 20 ms delay
MCU_PDhigh(); // PD high again
delay_ms(20); //atleast 20 ms delay
// ---------------------- Delay to allow start-up --------------------
//EVE_CmdWrite(0x00, 0x00);
EVE_CmdWrite(FT81x_ACTIVE, 0x00); // Sends 00 00 00 to wake FT8xx
delay_ms(500); // 500ms delay (EVE requires at least 300ms here)

// --------------- Check that FT8xx ready and SPI comms OK -----------------
while (EVE_MemRead8(REG_ID) != 0x7C)    //Execution is stuck here as MISO pin looks like it is not driven properly
// Ensure CPUreset register reads 0 and so FT8xx is ready
while (EVE_MemRead8(REG_CPURESET) != 0x00)
Function definition:
extern void EVE_CmdWrite(Uint8 EVECmd, Uint8 Param)   //Sends 0x00 0x00 0x00 to wake up FT81x
Uint8 dummyRead = 0;
MCU_CSlow(); // CS low begins the SPI transfer

dummyRead = SPI_Read_Write( (char) (EVECmd) ); // Send command
dummyRead = SPI_Read_Write( (char) (Param) ); // followed by parameter
dummyRead = SPI_Read_Write( 0x00 ); // and a dummy 00 byte
MCU_CShigh(); // CS high terminates the SPI transfer
}//End EVE_CmdWrite()


BRT Community

  • Administrator
  • Hero Member
  • *****
  • Posts: 752
    • View Profile

Hello Mahdu,

Thank you for the details on your configuration.

I cannot see any glaring issues with the configuration of your PIC, but I ill reference the datasheet if you can provide the exact part number you are using.

I note in your SPI config block you have disabled the SPI interface (SPI2CONbits.ON = 0; //Disable SPI 2) but not re-enabled it. I assume you have omitted the line where this is re-enabled as you note a successful loopback test.

Please be aware that the EVE series of graphics controllers support only SPI mode 0, so please utilise this configuration in any subsequent testing.

Your initialization code for EVE looks correct, however its appears that your capture of the MOSI pins behaviour has not attached to this post. Would it be possible to take a logic capture of the MOSI/MISO PD_N and CS# lines  up to can including the "while (EVE_MemRead8(REG_ID) != 0x7C)" during boot?

Best Regards,
BRT Community


  • Newbie
  • *
  • Posts: 4
    • View Profile

Hello BRT Community Member,
Thanks for responding.
Yes, though I did not include it in my first post, I am indeed turning ON the SPI module at the end of "SPI config:" code snippet.
I am using the UBW32 board with PIC32MX795F512L MCU on it:

Some observations:
1) During the first post, I let PIC32 MCU SPI master drive the CS line in sync with the SPI clock pulses (low when the clock is active and high when the clock is idle so CS was asserted/disasserted multiple times during a single multi-byte read/write operation). Now, I am manually asserting CS so the CS line is held down for the whole multi-byte read/write operation during an SPI TX/RX operation. Now, I can see data coming out of the MISO pin and it is always 0x00 0x4A 0x43 0x42 0xEF 0xBE 0xAD 0xDE 0xEF (the last byte is decoded as 0x77 sometimes but I think it is a shortcoming of the scope?). I have attached a screenshot of the corresponding picoscope capture.
2) I pull down PD and pull it back high during initialization. I do not do a Power Down of the SPI module after that until it is power cycled. So, I am expecting the PD line to stay high but it toggles multiple times when CS is low. Any ideas on why this is happening?
3) According to FT810 documentation/example code:
"while (EVE_MemRead8(0X302000) != 0x7C)"
But the code decodes the last byte as "0xDF" on the MISO line. Picoscope decodes it as "0xEF". The SPI read/write is supposed to be MSB first and I selected that option on the picoscope as well. I can't figure out why the SPI data is decoded differently by the code/picoscope and both versions are different from what is mentioned in the FT810 prohg guide.

I double-checked all my connections, soldered parts, etc and they are intact (checked impedances and the SPI related pins are isolated from each other. Both PIC32 and FT810 boards have decoupling capacitors. I haven't added any bypass capacitors as the signals are clean and I don't feel like they are required). Any suggestions about this decision are welcome.

I have read the PIC32 and FT810 chip/VM810C50A-D b0oard datasheet and programmer's guide more than once now and I haven't yet figured out why PD line is doing that or why picoscope and the FT810 example code decode the data differently (both of them don't match 0x7C like the FT810 programmer's guide mentions).
I attached the scope capture that you requested for your reference. I wish the website allowed for a bigger attachment size, I had to compress the image, etc before I could add an attachment and I was able to add only 1 attachment.
Any ideas/suggestions will be very useful (I have been working on this for a while)  :).

Thanks again,

BRT Community

  • Administrator
  • Hero Member
  • *****
  • Posts: 752
    • View Profile


Thank you for the updates.

Unfortunately the second sparkfun link seems to be broken.

Thank you for the clarification on the CS# signal, in our libraries we utilise a similar approach (holding the CS# low for a full read/write operation). however from your capture it looks like there is an errant CS# toggle between transactions. When are you asserting this signal in your code.

As for the PD# signal this is an input and shouldn't be toggling during SPI transactions. There is nothing internal to EVE which would cause this behaviour, can you double check your code to see if your are inadvertently toggling this line? I can see from the scope capture this seems to be happening, as a result EVE will be reset every time this signal toggles. This is likely to be an issue, you may want to try adjusting the driver strength on this pin.

As for the REG_ID read returning incorrectly, this could be related to the either of the above. But can you please clarify which SPI mode you are using with the SPI master interface? (I cannot zoom in enough onto the capture to establish this, please send a zoomed in capture of the MISO/MOSO and CLK lines if possible). The PIC should be configure to use SPI mode 0.

I have attached a SPI capture  for reference of the following code being used within the BRT_AN_025 library:

Code: [Select]
void eve_display(void)

                uint32_t dlOffset;
                uint32_t x = 0;

//            uint32_t xoffset, yoffset, xoffset2, yoffset2;
                uint32_t FT_DispWidth1 = 800;
                uint32_t FT_Dispheight1 = 480;
//    xoffset = FT_DispWidth1 / 2;                             // Variables to hold coordinates where the static text will be placed
//    yoffset = FT_DispHeight1 / 2;
//    xoffset2 = FT_DispWidth1 / 3;                            // Variables to hold coordinates where the dynamic text will be placed
//    yoffset2 = FT_DispHeight1 / 3;


    EVE_CLEAR_COLOR_RGB(0, 0, 0);
    EVE_CMD_TEXT(10, 50, 31, 0, "abc");
    EVE_CMD_TEXT(10, 100, 31, 0, "123456789456123123");
    EVE_CMD_TEXT(10, 200, 31, 0, "456");
    EVE_CMD_TEXT(10, 300, 31, 0, "456");
    EVE_CMD_TEXT(10, 400, 31, 0, "456");


    dlOffset = HAL_MemRead16(EVE_REG_CMD_DL);


                do {

                    EVE_CMD_TEXT(FT_DispWidth1/3 , FT_Dispheight1/3, 31, 0, "Dynamic");
                 EVE_CMD_TEXT(FT_DispWidth1/2 , FT_Dispheight1/2, 31, 0, "Dynamic");
                 EVE_CMD_NUMBER(200,100,31,EVE_OPT_CENTER | EVE_OPT_RIGHTX | 6 , x);


                } while (1);

This code utilises the following boot sequence (see the BRT_AN_025 source):

Code: [Select]

       MCU_PDlow();                                                                // PD low to reset device                                                               
    MCU_PDhigh();                                                               // PD high again

    // ---------------------- Delay to allow FT81x start-up --------------------   
    EVE_CmdWrite(FT81x_ACTIVE, 0x00);                                           // Sends 00 00 00 to wake FT8xx
    MCU_Delay_500ms();                                                          // 500ms delay (EVE requires at least 300ms here))
    // --------------- Check that FT8xx ready and SPI comms OK -----------------
    while (EVE_MemRead8(REG_ID) != 0x7C)                                        // Read REG_ID register until reads 0x7C
    while (EVE_MemRead8(REG_CPURESET) != 0x00)                                  // Ensure CPUreset register reads 0 and so FT8xx is ready   
    // ------------------------- Display settings ------------------------------

    // WQVGA display parameters
    lcdWidth   = 800;                                                           // Active width of LCD display
    lcdHeight  = 480;                                                           // Active height of LCD display
    lcdHcycle  = 928;                                                           // Total number of clocks per line
    lcdHoffset = 88;                                                            // Start of active line
    lcdHsync0  = 0;                                                             // Start of horizontal sync pulse
    lcdHsync1  = 48;                                                            // End of horizontal sync pulse
    lcdVcycle  = 525;                                                           // Total number of lines per screen
    lcdVoffset = 32;                                                            // Start of active screen
    lcdVsync0  = 0;                                                             // Start of vertical sync pulse
    lcdVsync1  = 3;                                                             // End of vertical sync pulse
    lcdPclk    = 2;                                                             // Pixel Clock
    lcdSwizzle = 0;                                                             // Define RGB output pins
    lcdPclkpol = 1;                                                             // Define active edge of PCLK
    EVE_MemWrite16(REG_HSIZE,   lcdWidth);     
    EVE_MemWrite16(REG_HCYCLE,  lcdHcycle);     
    EVE_MemWrite16(REG_HOFFSET, lcdHoffset);   
    EVE_MemWrite16(REG_HSYNC0,  lcdHsync0);     
    EVE_MemWrite16(REG_HSYNC1,  lcdHsync1);     
    EVE_MemWrite16(REG_VSIZE,   lcdHeight);     
    EVE_MemWrite16(REG_VCYCLE,  lcdVcycle);     
    EVE_MemWrite16(REG_VOFFSET, lcdVoffset);   
    EVE_MemWrite16(REG_VSYNC0,  lcdVsync0);     
    EVE_MemWrite16(REG_VSYNC1,  lcdVsync1);     
    EVE_MemWrite8(REG_SWIZZLE,  lcdSwizzle);   
    EVE_MemWrite8(REG_PCLK_POL, lcdPclkpol);   
    // ---------------------- Touch and Audio settings -------------------------

    EVE_MemWrite16(REG_TOUCH_RZTHRESH, 1200);                                   // Eliminate any false touches

    EVE_MemWrite8(REG_VOL_PB, ZERO);                                            // turn recorded audio volume down
    EVE_MemWrite8(REG_VOL_SOUND, ZERO);                                         // turn volume down
    EVE_MemWrite16(REG_SOUND, 0x6000);                                          // set volume mute
    // ---------------- Configure the GPIO and PWM  --------------------
    EVE_MemWrite8(REG_PWM_DUTY, 0);                                             // Backlight off
    FT81x_GPIO_DAT = EVE_MemRead16(REG_GPIOX);                                  // Read the FT81x GPIO register for a read/modify/write operation
    FT81x_GPIO_DAT = FT81x_GPIO_DAT | 0x8000;                                   // set bit 15 of GPIO register (DISP). If using audio, also enable the amplifier shutdown GPIO line here
    EVE_MemWrite16(REG_GPIOX, FT81x_GPIO_DAT);                                  // Enable the DISP signal to the LCD panel

    FT81x_GPIO_DIR = EVE_MemRead16(REG_GPIOX_DIR);                              // Read the FT81x GPIO DIR register for a read/modify/write operation
    FT81x_GPIO_DIR = FT81x_GPIO_DIR | 0x8000;                                   // DISP is output, if using audio, also set the associated shutdown line as output (check your Eval module schematic))
    EVE_MemWrite16(REG_GPIOX_DIR, FT81x_GPIO_DIR);                              // Enable the DISP signal to the LCD panel

    // ---------------------- Create an initial screen before we enable the display -------------------------

    ramDisplayList = RAM_DL;                                                    // start of Display List
    EVE_MemWrite32(ramDisplayList, 0x02000000);                                 // Clear Color RGB sets the colour to clear screen to

    ramDisplayList += 4;                                                        // point to next location
    EVE_MemWrite32(ramDisplayList, (0x26000000 | 0x00000007));                  // Clear 00100110 -------- -------- -----CST  (C/S/T define which parameters to clear)

    ramDisplayList += 4;                                                        // point to next location
    EVE_MemWrite32(ramDisplayList, 0x00000000);                                 // DISPLAY command 00000000 00000000 00000000 00000000 (end of display list)

    EVE_MemWrite32(REG_DLSWAP, DLSWAP_FRAME);                                   // Swap display list to make the edited one active

    // -------------------- Now turn on PCLK and ramp the PWM up  -------------------------------------
    // ---------------- This provides a clean start-up for the application ----------------------------
    EVE_MemWrite8(REG_PCLK, lcdPclk);                                           // Now start clocking data to the LCD panel

    for(PWM = 0; PWM <= 127; PWM ++)
        EVE_MemWrite8(REG_PWM_DUTY, PWM);     

This capture can be viewed using Saleae's Logic software:

Note: channel 4 in this capture represents the PD# pin.

This was a general example for another customer however in this case the 'config' section in the 'capture.jpg' image attached should be useful as it provides a set of known good SPI transactions to EVE for comparison in your set up. It may be worth comparing this section with the SPI data you are seeing in your configuration.

The first SPI transaction should be the "while (EVE_MemRead8(0X302000) != 0x7C)" call, so I have included a zoom of this attached as 'REG_ID.jpg'. Could you share a zoomed scope capture of your REG_ID read?

Best Regards,
BRT Community
« Last Edit: April 05, 2021, 03:26:54 PM by BRT Community »