Conflict/Issue with optimized ILI9341 library and other SPI device

Status
Not open for further replies.

maxbot

Active member
Hello together,
I have a problem which I can not solve on my own. I am using the Teensy3 optimized ILI9341 Display Driver library from: https://github.com/PaulStoffregen/ILI9341_t3
I ported it to use UTFT, which works fine so far. Now I want to communicate with another SPI device. But however, after I called the first function that writes to the display (for ex. DrawRect), I am not receiving valid data from the other SPI device (a sensor) any more.
For the other SPI slave, I am using the following code structure to receive data:
Code:
SPI.beginTransaction(SPISettings(24000000, MSBFIRST, SPI_MODE0));
digitalWrite(CS, LOW);
...
SPI.transfer(0x00);
...
digitalWrite(CS, HIGH);
SPI.endTransaction();
When I use it before calling any LCD function, it works fine. Afterwards, only weird data is coming in. So I think the ILI9341 alters some SPI registers which I have to reset.
Inside the ILI9341 library, there is this in the init:
Code:
void UTFT::InitLCD(byte orientation)
{
    pinMode(LED,OUTPUT);
    
    disp_x_size=319;
    disp_y_size=239;
    
    TFT_BL_ON;
    orient=orientation;

    if (SPI.pinIsChipSelect(CS, DC)) {
       	pcs_data = SPI.setCS(CS);
	pcs_command = pcs_data | SPI.setCS(DC);
    } else {
	pcs_data = 0;
	pcs_command = 0;
	return;
    }
	
    SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
    
    ...
}
And then it uses some functions I do not completely understand to send out data:
Code:
//void waitFifoNotFull(void) __attribute__((always_inline)) {
void waitFifoNotFull(void) {
	uint32_t sr;
	uint32_t tmp __attribute__((unused));
	do {
		sr = SPI0.SR;
		if (sr & 0xF0) tmp = SPI0_POPR;  // drain RX FIFO
	} while ((sr & (15 << 12)) > (3 << 12));
}
//void waitFifoEmpty(void) __attribute__((always_inline)) {
void waitFifoEmpty(void) {
	uint32_t sr;
	uint32_t tmp __attribute__((unused));
	do {
		sr = SPI0.SR;
		if (sr & 0xF0) tmp = SPI0_POPR;  // drain RX FIFO
	} while ((sr & 0xF0F0) > 0);             // wait both RX & TX empty
}
void waitTransmitComplete(void) __attribute__((always_inline)) {
	uint32_t tmp __attribute__((unused));
	while (!(SPI0.SR & SPI_SR_TCF)) ; // wait until final output done
	tmp = SPI0_POPR;                  // drain the final RX FIFO word
}
void writecommand_cont(uint8_t c) __attribute__((always_inline)) {
	SPI0.PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
	waitFifoNotFull();
}
void writedata8_cont(uint8_t c) __attribute__((always_inline)) {
	SPI0.PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
	waitFifoNotFull();
}
void writedata16_cont(uint16_t d) __attribute__((always_inline)) {
	SPI0.PUSHR = d | (pcs_data << 16) | SPI_PUSHR_CTAS(1) | SPI_PUSHR_CONT;
	waitFifoNotFull();
}
void writecommand_last(uint8_t c) __attribute__((always_inline)) {
	waitFifoEmpty();
	SPI0.SR = SPI_SR_TCF;
	SPI0.PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0);
	waitTransmitComplete();
}
void writedata8_last(uint8_t c) __attribute__((always_inline)) {
	waitFifoEmpty();
	SPI0.SR = SPI_SR_TCF;
	SPI0.PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0);
	waitTransmitComplete();
}
void writedata16_last(uint16_t d) __attribute__((always_inline)) {
	waitFifoEmpty();
	SPI0.SR = SPI_SR_TCF;
	SPI0.PUSHR = d | (pcs_data << 16) | SPI_PUSHR_CTAS(1);
	waitTransmitComplete();
}
I think it has something to do with those last functions as the init method alone does not cause the sensor to send weird data, its only happening after for example a call of this:
Code:
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
	setAddr(x1, y1, x1+w-1, y1+h-1);
	writecommand_cont(ILI9341_RAMWR);
	word color = ( fch << 8 | fcl );
	for(int y=h; y>0; y--) {
		for(int x=w; x>1; x--) {
			writedata16_cont(color);
		}
		writedata16_last(color);
	}
	SPI.endTransaction();
Thanks for any help in advantage !
Max
 
It's possible there's a bug in the library. It's also quite possible you've made a mistake somewhere. I just don't know.

If you want me to investigate, you must post a (hopefully small) complete program which demonstrates the problem. These code fragments are not enough. It must be a complete program that can be copied into Arduino and run on a real Teensy.
 
I know that the optimized ILI9241 does update the hardware registers. So for example when I am using it with the Adafruit 2.8"TFT display with touch screen, I have my modified version of the STMPE610 library (https://github.com/KurtE/Adafruit_STMPE610) which I believe Paul earlier modified, but I also have changes in my copy for Intel Edison...

The changes that I am pretty sure that Paul did was in the other library around each call for spi, it too had to call SPI.beginTransaction/SPI.endTransaction, in order for it to reset the registers to what that library needs...

But as Paul said, without seeing more of your actual program/library it is hard to know what is going on.
 
Would love to see your port of UTFT, I tried to use it with the standard ILI9241 library and it was way to slooooow.................
 
@PaulStoffregen: Thanks for your fast reply ! I just wanted to check out if you have a quick solution in your mind what could be the problem. Posting a code could be difficult as you do not own the sensor I use. However, I found a work-around using the alternative SPI Ports (7, 8 & 14) for the sensor and a beta implementation of Teensy3 SPI functions for the SdFat library on the normal SPI pins (https://github.com/greiman/SdFat-beta/blob/master/SdFat/SdSpiTeensy3.cpp).
@KurtE: Thanks for that info. It's hard to identify the actual reason, my touch controller is the XPT2046 and I am using the UTouch library on separate pins for it (it is actually a software SPI implementation).
@cartere: It is a quick & dirty implementation, but here you go: https://www.dropbox.com/s/zn36b4n84xy2f35/UTFT.zip?dl=0
I am using it on portrait mode by calling setRotation(45) after display init. All contributions go of course to Paul Stoffregen for his implementation of the fast ILI9341 library, thanks a lot for that ! I just merged it with UTFT core functions and made some optimizations.
 
Last edited:
I just wanted to check out if you have a quick solution in your mind what could be the problem.

From what you described, it really should work.

ILI9341_t3 has been used in combination with SD and other SPI-based libraries, without conflict. That doesn't necessarily mean all the code is bug-free. But I can tell you with certainty it has worked when used with other libraries.

Posting a code could be difficult as you do not own the sensor I use.

Maybe create a small test program that demonstrates the problem without revealing any proprietary code?
 
Status
Not open for further replies.
Back
Top