SPI read returns 'JCB'
part #: NHD-3.5-320240FT-CSXP-T that has FT81x processor.
Master SPI clock is running at 1 MHz. Using an ARM mcu.
TFT processor always returns 'JCB'.
Here's the steps taken:
Power on
Power Down pin is cleared, to low
Power Down pin is set, to high
Write 'Active' command
Read Chip ID { it returns "JCB0" }
Read Reg_ID { it returns "JCB0" }
Have tried setting some registers (like REG_HSIZE) and reading them back and "JCB0" is always returned.
Have tried transmit/read (transfer) with extra dummy bytes.
Please tell me what this code indicates.
Thank You
-
Hi Randall,
Could you please provide your wiring diagram or schematic you are using to connect to the display? As well as the code you used to communicate with the display.
0 -
0 -
#include "em_gpio.h"
#include "app_timer.h"
#include <stdint.h>
#include "sl_spidrv_instances.h"
#include "app_assert.h"
#include "FT81x_defines.h"void FT81x_PD_init(void);
uint8_t FT81x_rd8(const uint32_t address);
uint32_t FT81x_rd32(const uint32_t address);
void FT81x_wr8(uint32_t address, uint8_t data);
void FT81x_wr16(const uint32_t address, const uint16_t data);
void FT81x_wr32(const uint32_t address, const uint32_t data);uint32_t FT81x_rd_test(void);
void ft81x_power_on(void);
void FT81x_host_command(const uint32_t cmd);
uint32_t FT81x_readID(void);
void NHD_config(void);
uint32_t FT81x_readID(void);
void wr_DL_1(void);// i3_timer used for test, Start, 1, or stop, 0, periodic timer
static app_timer_t test_timer;static void test_timer_cb(app_timer_t *timer, void *data);
// Start or stop periodic timer
void test_timer_start_stop(uint8_t start_stop);
uint16_t sec_count = 0;/***************************************************************************//**
* Initialize application.
******************************************************************************/
void app_init(void)
{
volatile uint32_t chip_id = 0xffffffff;
volatile uint8_t reg_id = 0xffffffff;sl_spidrv_init_instances();
FT81x_PD_init(); // set port C pin 6 to push pull output
sl_sleeptimer_delay_millisecond(1000);
ft81x_power_on(); // cycle power down pin
sl_sleeptimer_delay_millisecond(2000);//test_timer_start_stop(1);
FT81x_host_command(ACTIVE);
sl_sleeptimer_delay_millisecond(9000);reg_id = FT81x_rd8(REG_ID);
sl_sleeptimer_delay_millisecond(2000);chip_id = FT81x_readID();
sl_sleeptimer_delay_millisecond(2000);//chip_id = FT81x_readID();
sl_sleeptimer_delay_millisecond(2000);NHD_config();
sl_sleeptimer_delay_millisecond(2000);//chip_id = FT81x_readID();
sl_sleeptimer_delay_millisecond(1000);FT81x_rd_test();
sl_sleeptimer_delay_millisecond(2000);
}/***************************************************************************//**
* App ticking function.
******************************************************************************/
void app_process_action(void)
{
}
uint8_t FT81x_rd8(const uint32_t address)
{
//uint32_t cmd = address;
volatile uint32_t cmd = address | READ;
volatile uint8_t tx_data[4];
//uint8_t rx_data = 0xff;
uint8_t rx_data[4];tx_data[0] = cmd >> 16;
tx_data[1] = cmd >> 8;
tx_data[2] = cmd & 0xff;
tx_data[3] = 0x00;
/*
// send the address
SPIDRV_MTransmitB(sl_spidrv_TFT_handle, &tx_data, 4);
// receive the data
SPIDRV_MReceiveB(sl_spidrv_TFT_handle, &rx_data, 1);
*/
SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_data[0], &rx_data[0]);
SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_data[1], &rx_data[1]);
SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_data[2], &rx_data[2]);
SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_data[3], &rx_data[3]);return rx_data[0];
}
uint16_t FT81x_rd16(const uint32_t address)
{
Ecode_t success;
//uint32_t cmd = address;
volatile uint32_t cmd = address | READ;
uint8_t tx_data[4];
//uint8_t rx_data = 0xff;
uint8_t rx_data[8];
volatile uint16_t result = 0x0000;rx_data[2] = 0xffffffff;
tx_data[0] = cmd >> 16;
tx_data[1] = cmd >> 8;
tx_data[2] = cmd;
tx_data[3] = 0x00;// send the address
//SPIDRV_MTransmitB(sl_spidrv_TFT_handle, &tx_data, 4);
SPIDRV_MTransferB(sl_spidrv_TFT_handle, &tx_data, &rx_data, 4);// receive the data
//SPIDRV_MReceiveB(sl_spidrv_TFT_handle, &rx_data, 2);
//SPIDRV_MTransferB(sl_spidrv_TFT_handle, &tx_data[3], &rx_data, 2);success = SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_data[3], &rx_data[4]);
success = SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_data[3], &rx_data[5]);
success = SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_data[3], &rx_data[6]);
success = SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_data[3], &rx_data[7]);result = result | rx_data[0] | (rx_data[1] << 8);
return result;
}
/*
* read 4 bytes from specified address
*
*/
uint32_t FT81x_rd32(const uint32_t address)
{
volatile uint32_t cmd = address | READ;
Ecode_t success;
uint8_t rx_data[4];
uint8_t tx_data[4];
volatile uint32_t result;// wait for ready
tx_data[0] = (cmd>>16);
//SPIDRV_MTransmitB(sl_spidrv_usart_TFTspi_handle, &tx_buff[0], 1);
tx_data[1] = (cmd>>8);
//SPIDRV_MTransmitB(sl_spidrv_usart_TFTspi_handle, &tx_buff[1], 1);
tx_data[2] = (cmd & 0xff);
//SPIDRV_MTransmitB(sl_spidrv_usart_TFTspi_handle, &tx_buff[2], 1);
tx_data[3] = 0x00; // dummy byte
//SPIDRV_MTransmitB(sl_spidrv_usart_TFTspi_handle, &tx_buff[3], 1);rx_data[0] = 0x00; // read byte
rx_data[1] = 0x00; // read byte
rx_data[2] = 0x00; // read byte
rx_data[3] = 0x00; // read byte// send the address
//success = SPIDRV_MTransmitB(sl_spidrv_usart_TFTspi_handle, &tx_buff, 4);// receive the data
//success = SPIDRV_MReceiveB(sl_spidrv_usart_TFTspi_handle, &rx_data, 4);// GPIO_PinOutClear(gpioPortC, 3); // CS low
success = SPIDRV_MTransferB(sl_spidrv_TFT_handle, &tx_data, &rx_data, 4);
// GPIO_PinOutSet(gpioPortC, 3); // CS highif(!success) {
//result = result | rx_data[0] << 24 | rx_data[1] << 16 | rx_data[2] << 8 | rx_data[3];
result = result | rx_data[0] | (rx_data[1] << 8) | (rx_data[2] << 16) | (rx_data[3] << 24);
return result;
}
else {
return 0;
}
}
/*
* write 8 bit value to TFT
*/
//Ecode_t TFT_wr8(uint32_t offset, uint8_t data)
void FT81x_wr8(const uint32_t address, uint8_t data)
{
//Ecode_t success;
uint32_t cmd = address | WRITE;
uint8_t tx_buff[4];tx_buff[0] = cmd >> 16;
tx_buff[1] = cmd >> 8;
tx_buff[2] = cmd;
tx_buff[3] = data;SPIDRV_MTransmitB(sl_spidrv_TFT_handle, &tx_buff, 4);
//return success;
}
/*
* write 16 bits of data to FT81x address
*
* example: FT81x_wr16(FT81x_REG_VSIZE, 240);
*/
void FT81x_wr16(const uint32_t address, uint16_t data)
{
//Ecode_t success;
uint32_t cmd = address | WRITE;
uint8_t tx_buff[5];
uint8_t rx_buff[5];tx_buff[0] = cmd >> 16;
tx_buff[1] = cmd >> 8;
tx_buff[2] = cmd;
tx_buff[3] = data;
tx_buff[4] = data >> 8;// SPIDRV_MTransmitB(sl_spidrv_TFT_handle, &tx_buff, 5);
SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_buff[0], &rx_buff[0]);
SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_buff[1], &rx_buff[1]);
SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_buff[2], &rx_buff[2]);
SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_buff[3], &rx_buff[3]);
SPIDRV_MTransferSingleItemB(sl_spidrv_TFT_handle, tx_buff[4], &rx_buff[4]);//return success;
sl_sleeptimer_delay_millisecond(2000);
}
void FT81x_wr32(const uint32_t address, const uint32_t data)
{
uint32_t cmd = address | WRITE;
//Ecode_t success;
uint8_t tx_buff[7];tx_buff[0] = cmd>>16;
tx_buff[1] = cmd>>8;
tx_buff[2] = cmd;
tx_buff[3] = data;
tx_buff[4] = data>>8;
tx_buff[5] = data>>16;
tx_buff[6] = data>>24;// send the data
SPIDRV_MTransmitB(sl_spidrv_TFT_handle, &tx_buff, 7);
}
/*************************************
Start timer , 1 second periodic timer
called from app_init
*************************************/
void test_timer_start_stop(uint8_t start_stop)
{
sl_status_t sc;if (start_stop) {
// Start timer used for testing.
sc = app_timer_start(&test_timer,
1 * 1000,
test_timer_cb,
NULL,
true);
app_assert_status(sc);
test_timer_cb(&test_timer, NULL);
}
// stop timer
else {
// Stop timer used for periodic indications.
sc = app_timer_stop(&test_timer);
}
}/**************************************************************************//**
* Timer callback
* Called periodically to time periodic temperature measurements.
*****************************************************************************/
static void test_timer_cb(app_timer_t *timer, void *data)
{
(void)data;
(void)timer;sec_count++;
}
void FT81x_PD_init(void)
{
GPIO_PinModeSet(gpioPortC, 6, gpioModePushPull, 0);
}
/*
* power ON TFT
* ref FT81x datasheet p. 37, 4.8.3 Power Modes
*
*/
void ft81x_power_on(void)
{
GPIO_PinOutClear(gpioPortC, 6); // power down tft
sl_sleeptimer_delay_millisecond(1000);
GPIO_PinOutSet(gpioPortC, 6); // power ON, sleep mode
sl_sleeptimer_delay_millisecond(1000);}
/*
* host command
* ref FT81x.pdf page 16, 4.1.5 Host Command
* 3 byte command followed by dummy byte
* prefix is b'01
*
*/
void FT81x_host_command(const uint32_t cmd)
{
uint8_t txbuff[3];
uint8_t rxbuff[4];txbuff[0] = cmd >> 16;
txbuff[1] = cmd >> 8;
txbuff[2] = cmd;// wait for ready
//SPIDRV_MTransmitB(sl_spidrv_TFT_handle, &rxbuff, 3);
SPIDRV_MTransferB(sl_spidrv_TFT_handle, &txbuff, &rxbuff, 3);
}/*
* read chip ID from address 0xC0000 - 0xC0003
*
*/
uint32_t FT81x_readID(void)
{
uint32_t ret_val = 0x00000000;ret_val = FT81x_rd32(0xC0000);
return ret_val;
}/*
* Configure display registers - for NHD part
* NHD part # NHD-3.5-320240FT-SCXP-T
*
*/
void NHD_config(void)
{
// horizontal timing
FT81x_wr16(REG_HSIZE, 320);
FT81x_wr16(REG_HCYCLE, 408);
FT81x_wr16(REG_HOFFSET, 70);
FT81x_wr16(REG_HSYNC0, 0);
FT81x_wr16(REG_HSYNC1, 10);// vertical timing
FT81x_wr16(REG_VSIZE, 240);
FT81x_wr16(REG_VCYCLE, 263);
FT81x_wr16(REG_VOFFSET, 13);
FT81x_wr16(REG_VSYNC0, 0);
FT81x_wr16(REG_VSYNC1, 2);// clock settings
FT81x_wr16(REG_PCLK,8);//after this display is visible on the LCD //wr8
FT81x_wr8(REG_SWIZZLE, 2); //wr8
FT81x_wr8(REG_PCLK_POL, 0); //wr8
FT81x_wr8(REG_CSPREAD, 0); //wr8}
/*
* write first display list
*
*/
void wr_DL_1(void)
{
FT81x_wr32(RAM_DL+0, 0x02000000); // set clear color
FT81x_wr32(RAM_DL+4, 0x26000003); // clear screen
FT81x_wr32(RAM_DL+8,0x00000000);
FT81x_wr16(REG_DLSWAP,DLSWAP_FRAME); //display list swap //wr8
FT81x_wr16(REG_GPIO_DIR,0x80 | FT81x_rd8(REG_GPIO_DIR)); //wr8
FT81x_wr16(REG_GPIO,0x080 | FT81x_rd8(REG_GPIO));//enable display bit //wr8
FT81x_wr16(REG_PCLK,8);//after this display is visible on the LCD //wr8
}
/*
* read some registers for test
*
*/
uint32_t FT81x_rd_test(void)
{
volatile uint16_t hsize = 0x00000000;
volatile uint16_t hcycle = 0x00000000;
volatile uint16_t hoffset = 0x00000000;
volatile uint16_t hsync0 = 0x00000000;
volatile uint16_t hsync1 = 0x00000000;hsize = FT81x_rd16(REG_HSIZE);
hcycle = FT81x_rd16(REG_HCYCLE);
hoffset = FT81x_rd16(REG_HOFFSET);
hsync0 = FT81x_rd16(REG_HSYNC0);
hsync1 = FT81x_rd16(REG_HSYNC1);return hsize;
}0 -
Hi Randall,
The wiring diagram seems correct to me.
Could you confirm if your SPI timing characteristics and setup is configured properly based on the datasheet?

I would also check if the structure of the data sent for host commands is following this format:

I would also check if the data write follows this format:

The SPI mode should be mode 0 and MSB first.
0
Please sign in to leave a comment.
Comments
4 comments