wwatson
Well-known member
That's great news@watson and @KurtE
got it fixed for 16bit. Have to clean up code and the will post it>
View attachment 35095
That's great news@watson and @KurtE
got it fixed for 16bit. Have to clean up code and the will post it>
View attachment 35095
ru16 RA8876_t41_p::lcdDataRead16(bool finalize) {
uint16_t dummy __attribute__((unused)) = 0;
uint16_t data = 0;
while (WR_IRQTransferDone == false) {
} // Wait for any IRQ transfers to complete
// FlexIO_Clear_Config_SnglBeat();
FlexIO_Config_SnglBeat_Read();
CSLow(); // Must to go low after config above.
DCHigh(); // Set HIGH for data read
RDLow(); // Set RD pin low manually
while (0 == (p->SHIFTSTAT & (1 << 3))) {
}
dummy = p->SHIFTBUFBYS[3];
while (0 == (p->SHIFTSTAT & (1 << 3))) {
}
data = p->SHIFTBUFBYS[3];
RDHigh(); // Set RD pin high manually
CSHigh();
//Serial.printf("lcdDataread(): Dummy 0x%4.4x, data 0x%4.4x\n", dummy, data);
// Set FlexIO back to Write mode
FlexIO_Config_SnglBeat(); // Not sure if this is needed.
return ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
}
ru16 lcdDataRead16(bool finalize = true);
ru16 RA8876_common::getPixel(ru16 x, ru16 y) {
ru16 rdata = 0;
ru16 dummy __attribute__((unused)) = 0;
x += _originx;
y += _originy;
selectScreen(currentPage);
graphicMode(true);
setPixelCursor(x, y); // set memory address
ramAccessPrepare(); // Setup SDRAM Access
dummy = lcdDataRead();
if(_bus_width == 16) {
rdata = lcdDataRead16();
} else {
rdata = (lcdDataRead() & 0xff); // read low byte
rdata |= lcdDataRead() << 8; // add high byte
}
return rdata;
}
virtual ru16 lcdDataRead16(bool finalize = true);
void RA8876_common::drawPixel(ru16 x, ru16 y, ru16 color) {
graphicMode(true);
setPixelCursor(x, y);
ramAccessPrepare();
if(_bus_width == 16) {
lcdDataWrite16(color);
} else {
lcdDataWrite(color);
lcdDataWrite(color >> 8);
#if defined(use_lcdDataWrite16bbp)
lcdDataWrite16bbp(color);
#endif
}
}
Nice work. Tested here on DB5. Works just like in 8bit mode. I will update the TeensyRA8876Combined repo...Quick update.
Just pushed a quick fix for drawPixel - works now for 16/8bit on a T41.
C++:void RA8876_common::drawPixel(ru16 x, ru16 y, ru16 color) { graphicMode(true); setPixelCursor(x, y); ramAccessPrepare(); if(_bus_width == 16) { lcdDataWrite16(color); } else { lcdDataWrite(color); lcdDataWrite(color >> 8); #if defined(use_lcdDataWrite16bbp) lcdDataWrite16bbp(color); #endif } }
I was going to start playing with the Async. Flexio Interrupt version soon. DMA will be after I move the one display over to the DB5.Everything seems to be working in 16Bit mode except for async,
void RA8876_common::CGRAM_initial(uint32_t charAddr, const uint8_t *data, uint16_t count) {
uint16_t i;
uint16_t tmp = 0;
graphicMode(true); // switch to graphic mode
lcdRegWrite(RA8876_AW_COLOR); // 5Eh
lcdDataWrite(RA8876_CANVAS_LINEAR_MODE << 2 | RA8876_CANVAS_COLOR_DEPTH_8BPP); // set memory to 8bpp and linear mode
linearAddressSet(charAddr); // Set linear address (32 bit)
// Set the start address for User Define Font, and write data.
ramAccessPrepare();
if(_bus_width == 8) {
for (i = 0; i < count; i++) {
checkWriteFifoNotFull();
lcdDataWrite(*data);
data++;
}
} else {
for (i = 0; i < count/2; i++) {
checkWriteFifoNotFull();
tmp = (*data++ & 0xff);
tmp |= (*data++ << 8);
lcdDataWrite16(tmp);
}
}
checkWriteFifoEmpty(); // If high speed mcu and without Xnwait check
lcdRegWrite(RA8876_AW_COLOR); // 5Eh
lcdDataWrite(RA8876_CANVAS_BLOCK_MODE << 2 | RA8876_CANVAS_COLOR_DEPTH_16BPP);
}
That is really off. Here is what I am getting in 8-bit mode:Got something strange going on. Just hooked up the DB5 with the RA8876 (8bit) ran both the readPixels and FB test sketches and for some reason Blue is off:
View attachment 35102
Picture bad - only the blue is off solid blue vs wavy blue
Contact #0: Track ID 0, X position 553, Y position 549, area 16
Contact #1: Track ID 1, X position 924, Y position 337, area 28
Contact #2: Track ID 2, X position 766, Y position 149, area 25
Contact #3: Track ID 3, X position 560, Y position 222, area 23
Contact #4: Track ID 4, X position 866, Y position 200, area 28
Number Of Contact Points: 5
Contact #0: Track ID 0, X position 553, Y position 546, area 16
Contact #1: Track ID 1, X position 924, Y position 337, area 28
Contact #2: Track ID 2, X position 766, Y position 150, area 25
Contact #3: Track ID 3, X position 560, Y position 222, area 23
Contact #4: Track ID 4, X position 863, Y position 199, area 28
Number Of Contact Points: 5
Contact #0: Track ID 0, X position 593, Y position 551, area 16
Contact #1: Track ID 1, X position 931, Y position 339, area 28
Contact #2: Track ID 2, X position 782, Y position 154, area 25
Contact #3: Track ID 3, X position 581, Y position 230, area 23
Contact #4: Track ID 4, X position 879, Y position 209, area 28
Number Of Contact Points: 1
Contact #0: Track ID 2, X position 902, Y position 182, area 25
Number Of Contact Points: 0
pinMode(_ctpInt ,INPUT_PULLUP);
Just synched up and tried the latest updates and anomaly is still there - very strange.Ignore the coffee stains on the table Are you using the TeensyRA8876Combined library? That's the one that has all of the latest updates.
https://github.com/wwatson4506/TeensyRA8876Combined
Believe we both have the ER-TFTM070-6 with capacitive touch@mjs515 @KurtE - Just curious as to which CAP touch controller you have on your ER-TFTM101-1 displays. Mine is a GT9271 and I have it working on the DB5. I modified the arduino-goodix library. Here is some output:
If you look in the RA8876_Common it has to be defined using: USE_FT5206_TOUCHIf I remember correctly with the SPI version of your SPI RA8876 library, I think we were able to get this information without using the FT5316 library.
Ditto on this end as well.Yep it was already defined in the header file. I have the touch app building, and it knows when I touch, but not getting the touch
data yet... Not sure if I screwed up which pins... Or software or needs PU...
I did verify that the Wire scanner finds it:Ditto on this end as well.
Scanning Wire...
Device found at address 0x38 (RA8875,FT6206,MAX98390)
done
Think you are a bit ahead of me. Did just notice that there is a function _initializeFT5206, assuming this needs to get called. Not seeing it anywhere. Checked in the orignal as wellI did verify that the Wire scanner finds it:
Unable to start the capacitive touchscreen.
X Coordinate: 422
Y Coordinate: 373
X Coordinate: 460
Y Coordinate: 371
X Coordinate: 502
Y Coordinate: 346
X Coordinate: 537
Y Coordinate: 318
X Coordinate: 545
Y Coordinate: 302
X Coordinate: 471
Y Coordinate: 283
X Coordinate: 432
Y Coordinate: 283
X Coordinate: 417
Y Coordinate: 284
X Coordinate: 417
>> touches:1 | gesture:0 | state:2 (518,271) (57344,57344)
>> touches:1 | gesture:0 | state:2 (535,269) (57344,57344)
>> touches:1 | gesture:0 | state:2 (554,267) (57344,57344)
>> touches:1 | gesture:0 | state:2 (571,267) (57344,57344)
>> touches:1 | gesture:0 | state:2 (585,270) (57344,57344)
>> touches:1 | gesture:0 | state:2 (592,271) (57344,57344)
>> touches:1 | gesture:0 | state:2 (593,271) (57344,57344)
>> touches:1 | gesture:0 | state:2 (592,272) (57344,57344)
>> touches:1 | gesture:0 | state:2 (587,271) (57344,57344)
>> touches:1 | gesture:0 | state:2 (576,267) (57344,57344)
>> touches:1 | gesture:0 | state:2 (562,260) (57344,57344)
>> touches:1 | gesture:0 | state:2 (547,250) (57344,57344)
>> touches:1 | gesture:0 | state:2 (533,241) (57344,57344)
>> touches:1 | gesture:0 | state:2 (520,234) (57344,57344)
>> touches:1 | gesture:0 | state:2 (508,232) (57344,57344)
>> touches:1 | gesture:0 | state:2 (502,233) (57344,57344)
But I always wonder how compatible are they? It must be reasonably compatible, or we would not have most everything working※Controller IC Replacement Notice
Due to the global shortage of IC, the controller RA8876 used in this module has been difficult to purchase. In order not to affect the delivery, we will use the controller LT7683 as replacement which is fully compatible with the same stable performance. (Oct-28-2021)
Just as a note my shows the LT7683 chip as well.My newer RA8876 (7" Buydisplay board) does not have an RA8876 on it but instead has an LT7683.
I saw that notice when I ordered my last display. Mine is still the RA8876. Also downloaded the ref manual but have not had the time to see if there is more info that might pertain to the RA8876 as well...Quick note/question:
My newer RA8876 (7" Buydisplay board) does not have an RA8876 on it but instead has an LT7683.
Which by their product page they show:
But I always wonder how compatible are they? It must be reasonably compatible, or we would not have most everything working
MicroMod Board and RA8876 parallel 8080 mode testing (8Bit/DMA)
Bus speed: 12 MHZ
Bus Width: 16-bits
Wrote 243800 bytes in 188us
Press anykey to continue
MicroMod Board and RA8876 parallel 8080 mode testing (8Bit/DMA)
Bus speed: 20 MHZ
Bus Width: 8-bits
Wrote 243800 bytes in 188us
Press anykey to continue
#include "Teensy41_Cardlike.h"
//#define use_spi
#if defined(use_spi)
#include <SPI.h>
#include <RA8876_t3.h>
#else
//#include <RA8876_t3.h>
#include <RA8876_t41_p.h>
#endif
//#include <math.h>
#if defined(use_spi)
#define RA8876_CS 10
#define RA8876_RESET 9
#define BACKLITE 5 //External backlight control connected to this Arduino pin
RA8876_t3 tft = RA8876_t3(RA8876_CS, RA8876_RESET); //Using standard SPI pins
#else
uint8_t dc = 13;
uint8_t cs = 11;
uint8_t rst = 12;
#define BACKLITE 5 //External backlight control connected to this Arduino pin
//RA8876_t41_p lcd = RA8876_t41_p(dc,cs,rst); //(dc, cs, rst)
RA8876_t41_p lcd = RA8876_t41_p(dc,cs,rst); //(dc, cs, rst)
#endif
uint32_t start = 0;
uint32_t end = 0;
uint8_t busSpeed = 12;
void setup() {
while (!Serial && millis() < 3000) {} //wait for Serial Monitor
Serial.printf("%c MicroMod Board and RA8876 parallel 8080 mode testing (8Bit/DMA)\n\n",12);
// Serial.print(CrashReport);
// pinMode(WINT, INPUT); // For XnWAIT signal if connected and used.
// Set 16bit mode
lcd.setBusWidth(16);
// DB5.0 WR pin, RD pin, D0 pin.
lcd.setFlexIOPins(53,52,40);
#if defined(use_spi)
lcd.begin();
#else
lcd.begin(busSpeed);// 20 is working in 8bit and 16bit mode on T41
#endif
// if(!lcd.begin(busSpeed)) Serial.printf("lcd.begin(busSpeed) FAILED!!!\n");
delay(100);
Serial.print("Bus speed: ");
Serial.print(busSpeed,DEC);
Serial.println(" MHZ");
Serial.print("Bus Width: ");
Serial.print(lcd.getBusWidth(),DEC);
Serial.println("-bits");
lcd.graphicMode(true);
lcd.fillScreen(0x0000);
lcd.setRotation(0);
}
void loop() {
start = micros();
lcd.pushPixels16bitDMA(teensy41_Cardlike,1,1,575,424); // FLASHMEM buffer
end = micros() - start;
Serial.printf("Wrote %d bytes in %dus\n\n",(575*424), end);
waitforInput();
}
void waitforInput()
{
Serial.println("Press anykey to continue");
while (Serial.read() == -1) ;
while (Serial.read() != -1) ;
}
//----------------------------------------------------------------------
// 8/16 BIT DMA STUFF starts here
//----------------------------------------------------------------------
FASTRUN void RA8876_t41_p::FlexIO_Config_DMA_MultiBeat()
{
//----------------------------------------------------------------------
uint16_t MulBeatWR_BeatQty = 0;
//----------------------------------------------------------------------
if (flex_config == CONFIG_DMA_MULTIBEAT)
return;
flex_config = CONFIG_DMA_MULTIBEAT;
DBGPrintf("RA8876_t41_p::FlexIO_Config_DMA_MultiBeat() - Enter\n");
uint32_t i;
//----------------------------------------------------------------------
if(_bus_width == 8) {
MulBeatWR_BeatQty = SHIFTNUM * sizeof(uint32_t) / sizeof(uint8_t); //Number of beats = number of shifters * beats per shifter
} else {
MulBeatWR_BeatQty = SHIFTNUM * sizeof(uint32_t) / sizeof(uint16_t); //Number of beats = number of shifters * beats per shifter
}
//----------------------------------------------------------------------
/* Disable and reset FlexIO */
p->CTRL &= ~FLEXIO_CTRL_FLEXEN;
//p->CTRL |= FLEXIO_CTRL_SWRST;
p->CTRL &= ~FLEXIO_CTRL_SWRST;
pFlex->setIOPinToFlexMode(_wr_pin);
gpioWrite();
for(i=0; i<=SHIFTNUM-1; i++)
{
p->SHIFTCFG[i] =
FLEXIO_SHIFTCFG_INSRC*(1U) /* Shifter input from next shifter's output */
| FLEXIO_SHIFTCFG_SSTOP(0U) /* Shifter stop bit disabled */
| FLEXIO_SHIFTCFG_SSTART(0U) /* Shifter start bit disabled and loading data on enabled */
| FLEXIO_SHIFTCFG_PWIDTH(_bus_width - 1); /* 8 bit shift width */
}
p->SHIFTCTL[0] =
FLEXIO_SHIFTCTL_TIMSEL(0) /* Shifter's assigned timer index */
| FLEXIO_SHIFTCTL_TIMPOL*(0U) /* Shift on posedge of shift clock */
| FLEXIO_SHIFTCTL_PINCFG(3U) /* Shifter's pin configured as output */
| FLEXIO_SHIFTCTL_PINSEL(_flexio_D0) //4 /* Shifter's pin start index */
| FLEXIO_SHIFTCTL_PINPOL*(0U) /* Shifter's pin active high */
| FLEXIO_SHIFTCTL_SMOD(2U); /* shifter mode transmit */
for(i=1; i<=SHIFTNUM-1; i++)
{
p->SHIFTCTL[i] =
FLEXIO_SHIFTCTL_TIMSEL(0) /* Shifter's assigned timer index */
| FLEXIO_SHIFTCTL_TIMPOL*(0U) /* Shift on posedge of shift clock */
| FLEXIO_SHIFTCTL_PINCFG(0U) /* Shifter's pin configured as output disabled */
| FLEXIO_SHIFTCTL_PINSEL(_flexio_D0) /* Shifter's pin start index */
| FLEXIO_SHIFTCTL_PINPOL*(0U) /* Shifter's pin active high */
| FLEXIO_SHIFTCTL_SMOD(2U); /* shifter mode transmit */
}
/* Configure the timer for shift clock */
p->TIMCMP[0] =
((MulBeatWR_BeatQty * 2U - 1) << 8) /* TIMCMP[15:8] = number of beats x 2 – 1 */
| (_baud_div/2U - 1U); /* TIMCMP[7:0] = shift clock divide ratio / 2 - 1 */
p->TIMCFG[0] = FLEXIO_TIMCFG_TIMOUT(0U) /* Timer output logic one when enabled and not affected by reset */
| FLEXIO_TIMCFG_TIMDEC(0U) /* Timer decrement on FlexIO clock, shift clock equals timer output */
| FLEXIO_TIMCFG_TIMRST(0U) /* Timer never reset */
| FLEXIO_TIMCFG_TIMDIS(2U) /* Timer disabled on timer compare */
| FLEXIO_TIMCFG_TIMENA(2U) /* Timer enabled on trigger high */
| FLEXIO_TIMCFG_TSTOP(0U) /* Timer stop bit disabled */
| FLEXIO_TIMCFG_TSTART*(0U); /* Timer start bit disabled */
p->TIMCTL[0] =
FLEXIO_TIMCTL_TRGSEL((0 << 2) | 1U) /* Timer trigger selected as highest shifter's status flag */
| FLEXIO_TIMCTL_TRGPOL*(1U) /* Timer trigger polarity as active low */
| FLEXIO_TIMCTL_TRGSRC*(1U) /* Timer trigger source as internal */
| FLEXIO_TIMCTL_PINCFG(3U) /* Timer' pin configured as output */
| FLEXIO_TIMCTL_PINSEL(_flexio_WR) /* Timer' pin index: WR pin */
| FLEXIO_TIMCTL_PINPOL*(1U) /* Timer' pin active low */
| FLEXIO_TIMCTL_TIMOD(1U); /* Timer mode 8-bit baud counter */
/* Enable FlexIO */
p->CTRL |= FLEXIO_CTRL_FLEXEN;
p->SHIFTSDEN |= 1U << (SHIFTER_DMA_REQUEST); // enable DMA trigger when shifter status flag is set on shifter SHIFTER_DMA_REQUEST
DBGPrintf("RA8876_t41_p::FlexIO_Config_MultiBeat() - Exit\n");
}
FASTRUN void RA8876_t41_p::MulBeatWR_nPrm_DMA(const void *value, uint32_t const length)
{
//----------------------------------------------------------------------
uint32_t BeatsPerMinLoop = 0;
//----------------------------------------------------------------------
while(WR_DMATransferDone == false) {} //Wait for any DMA transfers to complete
//----------------------------------------------------------------------
if(_bus_width == 8) {
BeatsPerMinLoop = SHIFTNUM * sizeof(uint32_t) / sizeof(uint8_t); // Number of shifters * number of 8 bit values per shifter
} else {
BeatsPerMinLoop = SHIFTNUM * sizeof(uint32_t) / sizeof(uint16_t); // Number of shifters * number of 8 bit values per shifter
}
//----------------------------------------------------------------------
uint32_t majorLoopCount, minorLoopBytes;
uint32_t destinationModulo = 31-(__builtin_clz(SHIFTNUM*sizeof(uint32_t))); // defines address range for circular DMA destination buffer
CSLow();
DCHigh();
if (length < 8){
const uint16_t * newValue = (uint16_t*)value;
uint16_t buf;
for(uint32_t i=0; i<length; i++) {
buf = *newValue++;
while(0 == (p->SHIFTSTAT & (1U << 0))) {}
p->SHIFTBUF[0] = generate_output_word(buf >> 8);
while(0 == (p->SHIFTSTAT & (1U << 0))) {}
p->SHIFTBUF[0] = generate_output_word(buf & 0xFF);
}
//Wait for transfer to be completed
while(0 == (p->TIMSTAT & (1U << 0))) {}
CSHigh();
} else {
FlexIO_Config_DMA_MultiBeat();
MulBeatCountRemain = length % BeatsPerMinLoop;
MulBeatDataRemain = (uint16_t*)value + ((length - MulBeatCountRemain)); // pointer to the next unused byte (overflow if MulBeatCountRemain = 0)
TotalSize = (length - MulBeatCountRemain)*2; /* in bytes */
minorLoopBytes = SHIFTNUM * sizeof(uint32_t);
majorLoopCount = TotalSize/minorLoopBytes;
/* Configure FlexIO with multi-beat write configuration */
flexDma.begin();
int destinationAddressOffset, destinationAddressLastOffset, sourceAddressOffset, sourceAddressLastOffset, minorLoopOffset;
volatile void *destinationAddress, *sourceAddress;
DMA_CR |= DMA_CR_EMLM; // enable minor loop mapping
arm_dcache_flush_delete((void *)value, length * 2); // important to flush cache before DMA. Otherwise, DMA will read from cache instead of memory and screen shows "snow" effects.
/* From now on, the SHIFTERS in MultiBeat mode are working correctly. Begin DMA transfer */
sourceAddress = (uint16_t*)value + minorLoopBytes/sizeof(uint16_t) - 1; // last 16bit address within current minor loop
sourceAddressOffset = -sizeof(uint16_t); // read values in reverse order
minorLoopOffset = 2*minorLoopBytes; // source address offset at end of minor loop to advance to next minor loop
sourceAddressLastOffset = minorLoopOffset - TotalSize; // source address offset at completion to reset to beginning
destinationAddress = (void *)&p->SHIFTBUFHWS[SHIFTNUM - 1]; // last 32bit shifter address (with reverse byte order)
destinationAddressOffset = -sizeof(uint32_t); // write words in reverse order
destinationAddressLastOffset = 0;
flexDma.TCD->SADDR = sourceAddress;
flexDma.TCD->SOFF = sourceAddressOffset;
flexDma.TCD->SLAST = sourceAddressLastOffset;
flexDma.TCD->DADDR = destinationAddress;
flexDma.TCD->DOFF = destinationAddressOffset;
flexDma.TCD->DLASTSGA = destinationAddressLastOffset;
flexDma.TCD->ATTR =
DMA_TCD_ATTR_SMOD(0U)
| DMA_TCD_ATTR_SSIZE(DMA_TCD_ATTR_SIZE_16BIT) // 16bit reads
| DMA_TCD_ATTR_DMOD(destinationModulo)
| DMA_TCD_ATTR_DSIZE(DMA_TCD_ATTR_SIZE_32BIT); // 32bit writes
flexDma.TCD->NBYTES_MLOFFYES =
DMA_TCD_NBYTES_SMLOE
| DMA_TCD_NBYTES_MLOFFYES_MLOFF(minorLoopOffset)
| DMA_TCD_NBYTES_MLOFFYES_NBYTES(minorLoopBytes);
flexDma.TCD->CITER = majorLoopCount; // Current major iteration count
flexDma.TCD->BITER = majorLoopCount; // Starting major iteration count
flexDma.triggerAtHardwareEvent(hw->shifters_dma_channel[SHIFTER_DMA_REQUEST]);
flexDma.disableOnCompletion();
flexDma.interruptAtCompletion();
flexDma.clearComplete();
/* Start data transfer by using DMA */
WR_DMATransferDone = false;
flexDma.attachInterrupt(dmaISR);
flexDma.enable();
dmaCallback = this;
}
}
//----------------------------------------------------------------------