ILI948x_t41_p - a parallel display driver for Teensy 4.1

Found the problem.
I was able to confirm the upper 8 bits were not being set be using "p->SHIFTBUF[0] = 0xFFFF", then measuring the pins with a multimeter. Lower 8bits read 3.3v, upper 0.3v. This suggested a config issue. Had a look at FlexIO_Config_SnglBeat() where I noticed "FLEXIO_SHIFTCFG_PWIDTH(7);". That's the problem!.
R61529 is now fine with the 16bit writes. Time to try the RM68120.
 
Oh! I always miss something haha
So the RM will only take a max of 20Mhz?
The data sheet says min of 10ns for frequency cycle.. with should be around 50Mhz for a full pulse width.

EDIT
RM is max 33ns between WR cycles
The ILI9806g is 30ns

So a max of around 30MHz for both
Thats around 70ish fps on a 16 bit bus
 
Last edited:
From my observation, 20mhz was the max under the conditions it was operating. I've since discovered the RM to be quite sensitive to poor grounding, a-lah my setup, which was inhibiting proper timing. Teensy 4.1s have 3 ground pins available, the display has two. I was using a single ground pin, via a Dupont connector, of course. After removing all Duponts, soldering everything directly and hooking up another ground has resulted in a jitter free display, allowing faster clocking.

_IMG_1.jpg
_IMG_3.jpg

As for performance. I'm seeing ~32MByte throughput on USB allowing for around ~38-40fps. More than enough.
 
From my observation, 20mhz was the max under the conditions it was operating. I've since discovered the RM to be quite sensitive to poor grounding, a-lah my setup, which was inhibiting proper timing. Teensy 4.1s have 3 ground pins available, the display has two. I was using a single ground pin, via a Dupont connector, of course. After removing all Duponts, soldering everything directly and hooking up another ground has resulted in a jitter free display, allowing faster clocking.

View attachment 31315
View attachment 31316

As for performance. I'm seeing ~32MByte throughput on USB allowing for around ~38-40fps. More than enough.

This looks amazing! Do you have any video's of it running?
What color depth is it running? 16 bits?

Would you mind sharing the init code as well as rotation code you used for this?

I'm wiring up mine on a 24 bit bus and modifying my MicroMod library to work with 32 bit color data (dropping the last 8 bits as they represent opacity)
 
Bit depth is 16 565, I never use anything else. I'll try to grab a video later.

Code:
FASTRUN void RM68120_t41_p::sendCmd16Arg8 (const uint16_t cmd, const uint8_t arg)
{
	uint16_t arg16[2] = {arg, 0};

   	SglBeatWR_nPrm_16(cmd, arg16, 1);
}

FASTRUN void RM68120_t41_p::sendCmd16 (const uint16_t cmd)
{
   	SglBeatWR_nPrm_16(cmd, 0, 0);
}



    sendCmd16(0x0100); // Software Reset
    delay(120);

    sendCmd16Arg8(0xF000, 0x55);
    sendCmd16Arg8(0xF001, 0xAA);
    sendCmd16Arg8(0xF002, 0x52);
    sendCmd16Arg8(0xF003, 0x08);
    sendCmd16Arg8(0xF004, 0x01);

    //GAMMA SETING  RED
    sendCmd16Arg8(0xD100, 0x00);
    sendCmd16Arg8(0xD101, 0x00);
    sendCmd16Arg8(0xD102, 0x1b);
    sendCmd16Arg8(0xD103, 0x44);
    sendCmd16Arg8(0xD104, 0x62);
    sendCmd16Arg8(0xD105, 0x00);
    sendCmd16Arg8(0xD106, 0x7b);
    sendCmd16Arg8(0xD107, 0xa1);
    sendCmd16Arg8(0xD108, 0xc0);
    sendCmd16Arg8(0xD109, 0xee);
    sendCmd16Arg8(0xD10A, 0x55);
    sendCmd16Arg8(0xD10B, 0x10);
    sendCmd16Arg8(0xD10C, 0x2c);
    sendCmd16Arg8(0xD10D, 0x43);
    sendCmd16Arg8(0xD10E, 0x57);
    sendCmd16Arg8(0xD10F, 0x55);
    sendCmd16Arg8(0xD110, 0x68);
    sendCmd16Arg8(0xD111, 0x78);
    sendCmd16Arg8(0xD112, 0x87);
    sendCmd16Arg8(0xD113, 0x94);
    sendCmd16Arg8(0xD114, 0x55);
    sendCmd16Arg8(0xD115, 0xa0);
    sendCmd16Arg8(0xD116, 0xac);
    sendCmd16Arg8(0xD117, 0xb6);
    sendCmd16Arg8(0xD118, 0xc1);
    sendCmd16Arg8(0xD119, 0x55);
    sendCmd16Arg8(0xD11A, 0xcb);
    sendCmd16Arg8(0xD11B, 0xcd);
    sendCmd16Arg8(0xD11C, 0xd6);
    sendCmd16Arg8(0xD11D, 0xdf);
    sendCmd16Arg8(0xD11E, 0x95);
    sendCmd16Arg8(0xD11F, 0xe8);
    sendCmd16Arg8(0xD120, 0xf1);
    sendCmd16Arg8(0xD121, 0xfa);
    sendCmd16Arg8(0xD122, 0x02);
    sendCmd16Arg8(0xD123, 0xaa);
    sendCmd16Arg8(0xD124, 0x0b);
    sendCmd16Arg8(0xD125, 0x13);
    sendCmd16Arg8(0xD126, 0x1d);
    sendCmd16Arg8(0xD127, 0x26);
    sendCmd16Arg8(0xD128, 0xaa);
    sendCmd16Arg8(0xD129, 0x30);
    sendCmd16Arg8(0xD12A, 0x3c);
    sendCmd16Arg8(0xD12B, 0x4A);
    sendCmd16Arg8(0xD12C, 0x63);
    sendCmd16Arg8(0xD12D, 0xea);
    sendCmd16Arg8(0xD12E, 0x79);
    sendCmd16Arg8(0xD12F, 0xa6);
    sendCmd16Arg8(0xD130, 0xd0);
    sendCmd16Arg8(0xD131, 0x20);
    sendCmd16Arg8(0xD132, 0x0f);
    sendCmd16Arg8(0xD133, 0x8e);
    sendCmd16Arg8(0xD134, 0xff);
    //GAMMA SETING GREEN
    sendCmd16Arg8(0xD200, 0x00);
    sendCmd16Arg8(0xD201, 0x00);
    sendCmd16Arg8(0xD202, 0x1b);
    sendCmd16Arg8(0xD203, 0x44);
    sendCmd16Arg8(0xD204, 0x62);
    sendCmd16Arg8(0xD205, 0x00);
    sendCmd16Arg8(0xD206, 0x7b);
    sendCmd16Arg8(0xD207, 0xa1);
    sendCmd16Arg8(0xD208, 0xc0);
    sendCmd16Arg8(0xD209, 0xee);
    sendCmd16Arg8(0xD20A, 0x55);
    sendCmd16Arg8(0xD20B, 0x10);
    sendCmd16Arg8(0xD20C, 0x2c);
    sendCmd16Arg8(0xD20D, 0x43);
    sendCmd16Arg8(0xD20E, 0x57);
    sendCmd16Arg8(0xD20F, 0x55);
    sendCmd16Arg8(0xD210, 0x68);
    sendCmd16Arg8(0xD211, 0x78);
    sendCmd16Arg8(0xD212, 0x87);
    sendCmd16Arg8(0xD213, 0x94);
    sendCmd16Arg8(0xD214, 0x55);
    sendCmd16Arg8(0xD215, 0xa0);
    sendCmd16Arg8(0xD216, 0xac);
    sendCmd16Arg8(0xD217, 0xb6);
    sendCmd16Arg8(0xD218, 0xc1);
    sendCmd16Arg8(0xD219, 0x55);
    sendCmd16Arg8(0xD21A, 0xcb);
    sendCmd16Arg8(0xD21B, 0xcd);
    sendCmd16Arg8(0xD21C, 0xd6);
    sendCmd16Arg8(0xD21D, 0xdf);
    sendCmd16Arg8(0xD21E, 0x95);
    sendCmd16Arg8(0xD21F, 0xe8);
    sendCmd16Arg8(0xD220, 0xf1);
    sendCmd16Arg8(0xD221, 0xfa);
    sendCmd16Arg8(0xD222, 0x02);
    sendCmd16Arg8(0xD223, 0xaa);
    sendCmd16Arg8(0xD224, 0x0b);
    sendCmd16Arg8(0xD225, 0x13);
    sendCmd16Arg8(0xD226, 0x1d);
    sendCmd16Arg8(0xD227, 0x26);
    sendCmd16Arg8(0xD228, 0xaa);
    sendCmd16Arg8(0xD229, 0x30);
    sendCmd16Arg8(0xD22A, 0x3c);
    sendCmd16Arg8(0xD22B, 0x4a);
    sendCmd16Arg8(0xD22C, 0x63);
    sendCmd16Arg8(0xD22D, 0xea);
    sendCmd16Arg8(0xD22E, 0x79);
    sendCmd16Arg8(0xD22F, 0xa6);
    sendCmd16Arg8(0xD230, 0xd0);
    sendCmd16Arg8(0xD231, 0x20);
    sendCmd16Arg8(0xD232, 0x0f);
    sendCmd16Arg8(0xD233, 0x8e);
    sendCmd16Arg8(0xD234, 0xff);

    //GAMMA SETING BLUE
    sendCmd16Arg8(0xD300, 0x00);
    sendCmd16Arg8(0xD301, 0x00);
    sendCmd16Arg8(0xD302, 0x1b);
    sendCmd16Arg8(0xD303, 0x44);
    sendCmd16Arg8(0xD304, 0x62);
    sendCmd16Arg8(0xD305, 0x00);
    sendCmd16Arg8(0xD306, 0x7b);
    sendCmd16Arg8(0xD307, 0xa1);
    sendCmd16Arg8(0xD308, 0xc0);
    sendCmd16Arg8(0xD309, 0xee);
    sendCmd16Arg8(0xD30A, 0x55);
    sendCmd16Arg8(0xD30B, 0x10);
    sendCmd16Arg8(0xD30C, 0x2c);
    sendCmd16Arg8(0xD30D, 0x43);
    sendCmd16Arg8(0xD30E, 0x57);
    sendCmd16Arg8(0xD30F, 0x55);
    sendCmd16Arg8(0xD310, 0x68);
    sendCmd16Arg8(0xD311, 0x78);
    sendCmd16Arg8(0xD312, 0x87);
    sendCmd16Arg8(0xD313, 0x94);
    sendCmd16Arg8(0xD314, 0x55);
    sendCmd16Arg8(0xD315, 0xa0);
    sendCmd16Arg8(0xD316, 0xac);
    sendCmd16Arg8(0xD317, 0xb6);
    sendCmd16Arg8(0xD318, 0xc1);
    sendCmd16Arg8(0xD319, 0x55);
    sendCmd16Arg8(0xD31A, 0xcb);
    sendCmd16Arg8(0xD31B, 0xcd);
    sendCmd16Arg8(0xD31C, 0xd6);
    sendCmd16Arg8(0xD31D, 0xdf);
    sendCmd16Arg8(0xD31E, 0x95);
    sendCmd16Arg8(0xD31F, 0xe8);
    sendCmd16Arg8(0xD320, 0xf1);
    sendCmd16Arg8(0xD321, 0xfa);
    sendCmd16Arg8(0xD322, 0x02);
    sendCmd16Arg8(0xD323, 0xaa);
    sendCmd16Arg8(0xD324, 0x0b);
    sendCmd16Arg8(0xD325, 0x13);
    sendCmd16Arg8(0xD326, 0x1d);
    sendCmd16Arg8(0xD327, 0x26);
    sendCmd16Arg8(0xD328, 0xaa);
    sendCmd16Arg8(0xD329, 0x30);
    sendCmd16Arg8(0xD32A, 0x3c);
    sendCmd16Arg8(0xD32B, 0x4A);
    sendCmd16Arg8(0xD32C, 0x63);
    sendCmd16Arg8(0xD32D, 0xea);
    sendCmd16Arg8(0xD32E, 0x79);
    sendCmd16Arg8(0xD32F, 0xa6);
    sendCmd16Arg8(0xD330, 0xd0);
    sendCmd16Arg8(0xD331, 0x20);
    sendCmd16Arg8(0xD332, 0x0f);
    sendCmd16Arg8(0xD333, 0x8e);
    sendCmd16Arg8(0xD334, 0xff);


    //GAMMA SETING  RED
    sendCmd16Arg8(0xD400, 0x00);
    sendCmd16Arg8(0xD401, 0x00);
    sendCmd16Arg8(0xD402, 0x1b);
    sendCmd16Arg8(0xD403, 0x44);
    sendCmd16Arg8(0xD404, 0x62);
    sendCmd16Arg8(0xD405, 0x00);
    sendCmd16Arg8(0xD406, 0x7b);
    sendCmd16Arg8(0xD407, 0xa1);
    sendCmd16Arg8(0xD408, 0xc0);
    sendCmd16Arg8(0xD409, 0xee);
    sendCmd16Arg8(0xD40A, 0x55);
    sendCmd16Arg8(0xD40B, 0x10);
    sendCmd16Arg8(0xD40C, 0x2c);
    sendCmd16Arg8(0xD40D, 0x43);
    sendCmd16Arg8(0xD40E, 0x57);
    sendCmd16Arg8(0xD40F, 0x55);
    sendCmd16Arg8(0xD410, 0x68);
    sendCmd16Arg8(0xD411, 0x78);
    sendCmd16Arg8(0xD412, 0x87);
    sendCmd16Arg8(0xD413, 0x94);
    sendCmd16Arg8(0xD414, 0x55);
    sendCmd16Arg8(0xD415, 0xa0);
    sendCmd16Arg8(0xD416, 0xac);
    sendCmd16Arg8(0xD417, 0xb6);
    sendCmd16Arg8(0xD418, 0xc1);
    sendCmd16Arg8(0xD419, 0x55);
    sendCmd16Arg8(0xD41A, 0xcb);
    sendCmd16Arg8(0xD41B, 0xcd);
    sendCmd16Arg8(0xD41C, 0xd6);
    sendCmd16Arg8(0xD41D, 0xdf);
    sendCmd16Arg8(0xD41E, 0x95);
    sendCmd16Arg8(0xD41F, 0xe8);
    sendCmd16Arg8(0xD420, 0xf1);
    sendCmd16Arg8(0xD421, 0xfa);
    sendCmd16Arg8(0xD422, 0x02);
    sendCmd16Arg8(0xD423, 0xaa);
    sendCmd16Arg8(0xD424, 0x0b);
    sendCmd16Arg8(0xD425, 0x13);
    sendCmd16Arg8(0xD426, 0x1d);
    sendCmd16Arg8(0xD427, 0x26);
    sendCmd16Arg8(0xD428, 0xaa);
    sendCmd16Arg8(0xD429, 0x30);
    sendCmd16Arg8(0xD42A, 0x3c);
    sendCmd16Arg8(0xD42B, 0x4A);
    sendCmd16Arg8(0xD42C, 0x63);
    sendCmd16Arg8(0xD42D, 0xea);
    sendCmd16Arg8(0xD42E, 0x79);
    sendCmd16Arg8(0xD42F, 0xa6);
    sendCmd16Arg8(0xD430, 0xd0);
    sendCmd16Arg8(0xD431, 0x20);
    sendCmd16Arg8(0xD432, 0x0f);
    sendCmd16Arg8(0xD433, 0x8e);
    sendCmd16Arg8(0xD434, 0xff);

    //GAMMA SETING GREEN
    sendCmd16Arg8(0xD500, 0x00);
    sendCmd16Arg8(0xD501, 0x00);
    sendCmd16Arg8(0xD502, 0x1b);
    sendCmd16Arg8(0xD503, 0x44);
    sendCmd16Arg8(0xD504, 0x62);
    sendCmd16Arg8(0xD505, 0x00);
    sendCmd16Arg8(0xD506, 0x7b);
    sendCmd16Arg8(0xD507, 0xa1);
    sendCmd16Arg8(0xD508, 0xc0);
    sendCmd16Arg8(0xD509, 0xee);
    sendCmd16Arg8(0xD50A, 0x55);
    sendCmd16Arg8(0xD50B, 0x10);
    sendCmd16Arg8(0xD50C, 0x2c);
    sendCmd16Arg8(0xD50D, 0x43);
    sendCmd16Arg8(0xD50E, 0x57);
    sendCmd16Arg8(0xD50F, 0x55);
    sendCmd16Arg8(0xD510, 0x68);
    sendCmd16Arg8(0xD511, 0x78);
    sendCmd16Arg8(0xD512, 0x87);
    sendCmd16Arg8(0xD513, 0x94);
    sendCmd16Arg8(0xD514, 0x55);
    sendCmd16Arg8(0xD515, 0xa0);
    sendCmd16Arg8(0xD516, 0xac);
    sendCmd16Arg8(0xD517, 0xb6);
    sendCmd16Arg8(0xD518, 0xc1);
    sendCmd16Arg8(0xD519, 0x55);
    sendCmd16Arg8(0xD51A, 0xcb);
    sendCmd16Arg8(0xD51B, 0xcd);
    sendCmd16Arg8(0xD51C, 0xd6);
    sendCmd16Arg8(0xD51D, 0xdf);
    sendCmd16Arg8(0xD51E, 0x95);
    sendCmd16Arg8(0xD51F, 0xe8);
    sendCmd16Arg8(0xD520, 0xf1);
    sendCmd16Arg8(0xD521, 0xfa);
    sendCmd16Arg8(0xD522, 0x02);
    sendCmd16Arg8(0xD523, 0xaa);
    sendCmd16Arg8(0xD524, 0x0b);
    sendCmd16Arg8(0xD525, 0x13);
    sendCmd16Arg8(0xD526, 0x1d);
    sendCmd16Arg8(0xD527, 0x26);
    sendCmd16Arg8(0xD528, 0xaa);
    sendCmd16Arg8(0xD529, 0x30);
    sendCmd16Arg8(0xD52A, 0x3c);
    sendCmd16Arg8(0xD52B, 0x4a);
    sendCmd16Arg8(0xD52C, 0x63);
    sendCmd16Arg8(0xD52D, 0xea);
    sendCmd16Arg8(0xD52E, 0x79);
    sendCmd16Arg8(0xD52F, 0xa6);
    sendCmd16Arg8(0xD530, 0xd0);
    sendCmd16Arg8(0xD531, 0x20);
    sendCmd16Arg8(0xD532, 0x0f);
    sendCmd16Arg8(0xD533, 0x8e);
    sendCmd16Arg8(0xD534, 0xff);

    //GAMMA SETING BLUE
    sendCmd16Arg8(0xD600, 0x00);
    sendCmd16Arg8(0xD601, 0x00);
    sendCmd16Arg8(0xD602, 0x1b);
    sendCmd16Arg8(0xD603, 0x44);
    sendCmd16Arg8(0xD604, 0x62);
    sendCmd16Arg8(0xD605, 0x00);
    sendCmd16Arg8(0xD606, 0x7b);
    sendCmd16Arg8(0xD607, 0xa1);
    sendCmd16Arg8(0xD608, 0xc0);
    sendCmd16Arg8(0xD609, 0xee);
    sendCmd16Arg8(0xD60A, 0x55);
    sendCmd16Arg8(0xD60B, 0x10);
    sendCmd16Arg8(0xD60C, 0x2c);
    sendCmd16Arg8(0xD60D, 0x43);
    sendCmd16Arg8(0xD60E, 0x57);
    sendCmd16Arg8(0xD60F, 0x55);
    sendCmd16Arg8(0xD610, 0x68);
    sendCmd16Arg8(0xD611, 0x78);
    sendCmd16Arg8(0xD612, 0x87);
    sendCmd16Arg8(0xD613, 0x94);
    sendCmd16Arg8(0xD614, 0x55);
    sendCmd16Arg8(0xD615, 0xa0);
    sendCmd16Arg8(0xD616, 0xac);
    sendCmd16Arg8(0xD617, 0xb6);
    sendCmd16Arg8(0xD618, 0xc1);
    sendCmd16Arg8(0xD619, 0x55);
    sendCmd16Arg8(0xD61A, 0xcb);
    sendCmd16Arg8(0xD61B, 0xcd);
    sendCmd16Arg8(0xD61C, 0xd6);
    sendCmd16Arg8(0xD61D, 0xdf);
    sendCmd16Arg8(0xD61E, 0x95);
    sendCmd16Arg8(0xD61F, 0xe8);
    sendCmd16Arg8(0xD620, 0xf1);
    sendCmd16Arg8(0xD621, 0xfa);
    sendCmd16Arg8(0xD622, 0x02);
    sendCmd16Arg8(0xD623, 0xaa);
    sendCmd16Arg8(0xD624, 0x0b);
    sendCmd16Arg8(0xD625, 0x13);
    sendCmd16Arg8(0xD626, 0x1d);
    sendCmd16Arg8(0xD627, 0x26);
    sendCmd16Arg8(0xD628, 0xaa);
    sendCmd16Arg8(0xD629, 0x30);
    sendCmd16Arg8(0xD62A, 0x3c);
    sendCmd16Arg8(0xD62B, 0x4A);
    sendCmd16Arg8(0xD62C, 0x63);
    sendCmd16Arg8(0xD62D, 0xea);
    sendCmd16Arg8(0xD62E, 0x79);
    sendCmd16Arg8(0xD62F, 0xa6);
    sendCmd16Arg8(0xD630, 0xd0);
    sendCmd16Arg8(0xD631, 0x20);
    sendCmd16Arg8(0xD632, 0x0f);
    sendCmd16Arg8(0xD633, 0x8e);
    sendCmd16Arg8(0xD634, 0xff);

    sendCmd16Arg8(0xB000, 0x05);	//AVDD VOLTAGE SETTING
    sendCmd16Arg8(0xB001, 0x05);
    sendCmd16Arg8(0xB002, 0x05);
    
    sendCmd16Arg8(0xB100, 0x05);	//AVEE VOLTAGE SETTING
    sendCmd16Arg8(0xB101, 0x05);
    sendCmd16Arg8(0xB102, 0x05);

    sendCmd16Arg8(0xB600, 0x34);	//AVDD Boosting
    sendCmd16Arg8(0xB601, 0x34);
    sendCmd16Arg8(0xB603, 0x34);
    
    sendCmd16Arg8(0xB700, 0x24);	//AVEE Boosting
    sendCmd16Arg8(0xB701, 0x24);
    sendCmd16Arg8(0xB702, 0x24);
    
    sendCmd16Arg8(0xB800, 0x24);	//VCL Boosting
    sendCmd16Arg8(0xB801, 0x24);
    sendCmd16Arg8(0xB802, 0x24);
    
    sendCmd16Arg8(0xBA00, 0x14);	//VGLX VOLTAGE SETTING
    sendCmd16Arg8(0xBA01, 0x14);
    sendCmd16Arg8(0xBA02, 0x14);
    
    sendCmd16Arg8(0xB900, 0x24);	//VCL Boosting
    sendCmd16Arg8(0xB901, 0x24);
    sendCmd16Arg8(0xB902, 0x24);
   
    sendCmd16Arg8(0xBc00, 0x00);	//Gamma Voltage
    sendCmd16Arg8(0xBc01, 0xa0);	//vgmp=5.0
    sendCmd16Arg8(0xBc02, 0x00);
    sendCmd16Arg8(0xBd00, 0x00);
    sendCmd16Arg8(0xBd01, 0xa0);	//vgmn=5.0
    sendCmd16Arg8(0xBd02, 0x00);
    
    sendCmd16Arg8(0xBe01, 0x3d);	//VCOM Setting  3
    
    sendCmd16Arg8(0xF000, 0x55);	//ENABLE PAGE 0
    sendCmd16Arg8(0xF001, 0xAA);
    sendCmd16Arg8(0xF002, 0x52);
    sendCmd16Arg8(0xF003, 0x08);
    sendCmd16Arg8(0xF004, 0x00);
    
    sendCmd16Arg8(0xB400, 0x10);	//Vivid Color Function Control

    sendCmd16Arg8(0xBC00, 0x05);	//Z-INVERSION
    sendCmd16Arg8(0xBC01, 0x05);
    sendCmd16Arg8(0xBC02, 0x05);

    sendCmd16Arg8(0xB700, 0x22);	//GATE EQ CONTROL
    sendCmd16Arg8(0xB701, 0x22);	//GATE EQ CONTROL
    sendCmd16Arg8(0xC80B, 0x2A);	//DISPLAY TIMING CONTROL
    sendCmd16Arg8(0xC80C, 0x2A);	//DISPLAY TIMING CONTROL
    sendCmd16Arg8(0xC80F, 0x2A);	//DISPLAY TIMING CONTROL
    sendCmd16Arg8(0xC810, 0x2A);	//DISPLAY TIMING CONTROL
    
    
    sendCmd16Arg8(0xd000, 0x01);	//PWM_ENH_OE =1
    sendCmd16Arg8(0xb300, 0x10);	//DM_SEL =1
    sendCmd16Arg8(0xBd02, 0x07);	//VBPDA=07h
    sendCmd16Arg8(0xBe02, 0x07);	//VBPDb=07h
    sendCmd16Arg8(0xBf02, 0x07);	//VBPDc=07h
    
    sendCmd16Arg8(0xF000, 0x55);	//ENABLE PAGE 2
    sendCmd16Arg8(0xF001, 0xAA);
    sendCmd16Arg8(0xF002, 0x52);
    sendCmd16Arg8(0xF003, 0x08);
    sendCmd16Arg8(0xF004, 0x02);
    
    sendCmd16Arg8(0xc301, 0xa9);	//SDREG0 =0
    sendCmd16Arg8(0xfe01, 0x94);	//DS=14
    sendCmd16Arg8(0xf600, 0x60);	//OSC =60h
    //sendCmd16Arg8(0x3500, 0x00);	//TE ON

    sendCmd16Arg8(0xF000, 0x55);	//ENABLE PAGE 0
    sendCmd16Arg8(0xF001, 0xAA);
    sendCmd16Arg8(0xF002, 0x52);
    sendCmd16Arg8(0xF003, 0x08);
    sendCmd16Arg8(0xF004, 0x00);
    
    sendCmd16(0x1100);					// SLEEP OUT 
    delay(100);

    sendCmd16Arg8(0x3A00, 0x55);		// Bitdepth = RGB565
    delay(50);
    sendCmd16Arg8(0x3600, MADCTL[3]);	// Rotation
	delay(50);
    sendCmd16(0x2900);					// Display ON
    delay(50);

And for orientation:

Code:
#define MADCTL_MY  0x80  // Bottom to top
#define MADCTL_MX  0x40  // Right to left
#define MADCTL_MV  0x20  // Row/Column exchange
#define MADCTL_ML  0x10  // LCD refresh Bottom to top
#define MADCTL_RGB 0x00  // Red-Green-Blue pixel order
#define MADCTL_BGR 0x08  // Blue-Green-Red pixel order
#define MADCTL_MH  0x04  // LCD refresh right to left
#define MADCTL_GS  0x01
#define MADCTL_SS  0x02

//MADCTL 0,1,2,3 for setting rotation
#define MADCTL_ARRAY { 	MADCTL_MX | MADCTL_RGB, 							\
						MADCTL_MV | MADCTL_RGB, 							\
						MADCTL_MY | MADCTL_RGB,								\
						MADCTL_MY | MADCTL_MV | MADCTL_RGB } 


sendCmd16Arg8(RM68120_MADCTL, MADCTL[_rotation]);  // _rotation == 3
 
Anyone: Can we embed videos here?
Yes you just press the Insert Video button and follow the prompts.
It looks likle this:z.png

If you NEED to see what the other buttons do just hover over them in turn.
 
Yes you just press the Insert Video button and follow the prompts.
It looks likle this:View attachment 31334

If you NEED to see what the other buttons do just hover over them in turn.

Thank you. Don't know how I missed that.

Rezo, This is the RM driver is full: View attachment RM68120_220623.zip

It's probably worth mentioning that, on my board (AC1590), RGB24 and RGB888 are marked as different interfaces. RGB24 is the micro bus interface, whereas RGB888 is the h/v sync display interface. This requires a different resistor config for the IM0/1/2/3 signals for each interface.

Edit:
You may need to use 'sendCmd16Arg8(0x3A00, 0x77)' to setup 24bit colour, not 0x55, as per page 200 of the RM68120 v2 PDF
 
Last edited:
Lets try this again..

This is a video of the TGX library's Mars demo, rendered at 16bit on desktop and streamed directly to a Teensy 4.1 @720mhz via a RawHid USB interface (modified).
Display is a 432x240 IPS S6D04D1 driven via 16bit FlexIo and rendered in strips of 80 rows.
FPS is around 125-130fps. Display refresh is set to 68.
 
Looks good!

Cheers!.

As promised, here is a driver for the 960x540 NT35516 display (IPS1P1399) as found on Aliexpress.
This controller has been nothing but frustrating to get working, to say the least. I have spent the past three days attempting to resolve what appears to be an inherent horizontal jitter from within the display, which appears only when writing any colour component value to full brightness. Odd.

Running with a theory that this could be an artefact of a voltage tolerance (between the controller and the teensy) being a little tighter than what we can normally get away with - Perhaps an internal DAC is overflowing? Vcc spec for the controller is 1.8v to 3.3v - The Teensy 4.1 Vcc this is soldered to: ~3.28v & within spec.
To test this, I began removing bits in sequence from each of the RGB components. Surprisingly this worked. Eventually discovered only the LSB (of RGB) needed be removed to maintain a stable image.
Admittedly this is a glorified hack and doesn't actually answer to what is going on, but if anyone can expand on this, please do.

The workaround. For each frame:
Code:
  for (int i = 0; i < area; i++)
    pcolors[i] &= 0xF7DE;     // mask off each LSB (1111011111011110)

I would recommend clocking the Teensy to 720mhz to get best performance from this.
View attachment NT35516_280623.zip
 
Have this working on an ILI9486 with the below modification to the initialisation sequence. I found that with my particular display, only baud 30mhz would function as anything else would result in display corruption. Probably the length the 20+cm wires are the cause. Using pushPixels16bitAsync() would cause the image to jitter across the display, which again, is probably down to the length of the wiring. Will give this a try on an S6D04D1 240x432, see how that fairs.

(Using CS:11, RS:13 & RST:12)

Code:
PROGMEM static const uint8_t initCommands[] = 
{
	// ... snipped
};

I'm also trying to get this running with an ILI9486, but on a Teensy 4.0.
From what I understand, I have to pick different pins because I have less than a Teensy 4.1 and it should be FlexIO 3 pins.
Please bear in mind that I only understand maybe 20% of what is going on with FlexIO... ;)

I changed the configuration to be like this:
Code:
    pinMode(19, OUTPUT); // FlexIO3:0 D0
    pinMode(18, OUTPUT); // FlexIO3:1 |
    pinMode(14, OUTPUT); // FlexIO3:2 |
    pinMode(15, OUTPUT); // FlexIO3:3 |
[COLOR="#FF0000"][B]    pinMode(11, OUTPUT); // FlexIO3:4 |   (this was pin 40)
    pinMode(10, OUTPUT); // FlexIO3:5 |   (this was pin 41)[/B][/COLOR]
    pinMode(17, OUTPUT); // FlexIO3:6 |
    pinMode(16, OUTPUT); // FlexIO3:7 D7

[COLOR="#FF0000"][B]    pinMode(8, OUTPUT); // FlexIO3:18 WR  (this was 36)
    pinMode(9, OUTPUT); // FlexIO3:19 RD   (this was 37)[/B][/COLOR]

I also updated any other references to those pins to match my new pin numbers.
But should that just work or am I missing something here?
I have a feeling that the order in which the pin numbers were chosen for the T4.1 may be relevant?

Right now, the code compiles and runs without crashing, but I am not seeing anything on the display.
The displayInfo() function returns 0x00 for all the properties.

Any help would be greatly appreciated!
 
The Teensy 4.0 does not have enough consecutive FlexIO pins to support the
Library as it is.
Only thing I see possible is to bit shift 8/16 bits into the 32bit FlexIO register each time you write to the shifter buffer.
Let me see if I can work a code example up during the week
 
The Teensy 4.0 does not have enough consecutive FlexIO pins to support the
Library as it is.
Only thing I see possible is to bit shift 8/16 bits into the 32bit FlexIO register each time you write to the shifter buffer.
Let me see if I can work a code example up during the week

Does it help that I’m only using 8 data bits and not 16?
 
Makes no difference to the code - still have to modify for the T4.0
Are you using 8 bit color depth? Or 16 bit color depth?
 
Makes no difference to the code - still have to modify for the T4.0
Are you using 8 bit color depth? Or 16 bit color depth?

I didnt change that, so that would be 16 bit, but I would be more than happy with 8 bit!
It will be used to render graphics coming from a retro game console that only has 4 bit per pixel :)
 
Okay, not a problem

What size frame buffer buffer will you be using then?
1 byte * 320*480 and load 4 bits per pixel and the other 4 bits go to waste, or load two pixels per byte and save on size (320*240)?
Just remember you can place it in RAM2 (DMAMEM) to keep RAM1 free for your program.

Regarding pins, these are what you need for the data bus:
Pin 19 - D0
Pin 18 - D1
Pin 14 - D2
Pin 15 - D3
Pin 17 - D4
Pin 16 - D5
Pin 22 - D6
Pin 23 - D7

For WRX/RDX you can use any of the following Teensy pins: 20, 21, 7, 8 - Which two do you prefer?

Once I have this info, I can make a modified library for the T4 that you can test.
 
Let’s go with 1bytes*320x480 and use the full 8 bits.
When generating the framebuffer, I will make the translation from 4bpp to 8bpp myself.
That way the library is a bit more versatile.

I have no preference for pins, so choose what is easiest to work with for you.

Thanks so much for putting time into this. Really appreciate it!
 
Let’s go with 1bytes*320x480 and use the full 8 bits.
When generating the framebuffer, I will make the translation from 4bpp to 8bpp myself.
That way the library is a bit more versatile.

I have no preference for pins, so choose what is easiest to work with for you.

Thanks so much for putting time into this. Really appreciate it!

No worries!|
Here is a very initial library bases on my Teensy MM display driver library.
https://github.com/david-res/LI948x_t40_p

I did not test it at all, but it compiles fine.
Try out the example sketch.

I chose Teensy pin 21 for WRX and pin 20 for RDX

Lets make sure this can read/write as we expect, then we can see how to get it to display 8 bit data fed from a 4 bit deep pixel (I have some ideas)
 
It's compiling, but I don't see anything happen on the screen.
Double checked all the pins.

Serial output is (I added a call to displayInfo()):

No Crash Data To Report
Hopefully all is well, but certain types of crashes can't be reported:
stuck in an infinite loop (technically, hardware still running properly)
remaining in a low power sleep mode
access to certain peripherals without their clock enabled (eg, FlexIO)
change of CPU or bus clock speed without use of glitchless mux
Breadcrumb #3 was 4107523036 (0xF4D3D3DC)
Breadcrumb #4 was 158618861 (0x97454ED)
Breadcrumb #6 was 1398346850 (0x53591462)
ILI9486 Initialized
Manufacturer ID: 0x00
Module Version ID: 0x00
Module ID: 0x00
Display Power Mode: 0x00
MADCTL Mode: 0x00
Pixel Format: 0x00
Image Format: 0x00
Signal Mode: 0x00
Self Diagnostic: Failed (0x00)

unnamed.jpg
 
Yes, DC (which is RS on my unit I believe) to 13, CS to 11 and RST to 12.
Here is a picture of my TFT unit.

I left the F_CS pin unconnected. I don't know what it is for?
All the SD pins are unconnected.
RESET is left unconnected too, but just to be sure I tried to connect that to +5V and to GND but it made no difference.
5V is connected to Teensy 5V line and of course GND to Teensy GND.

I tested continuity between all TFT pins and the Teensy and it is all connected.

unnamed (1).jpg
 
Thanks for confirming!
I have the same LCD here so what ever I get working you can replicate!
I need to dig up one of my spare T4.0 and solder on some headers and then I will be able to test as well.

Will post when I have an update (might take a few days in between kids, work and packing up the house for an upcoming move)
 
Back
Top