Buydisplay 10.1" TFT in parallel 8080 mode and Teensy FlexIO

For a full 1024*600 @ 2bpp frame on an 8 bit bus with a 40Mhz baud rate you should get up to 16fps.
No super fast, but for such a high resolution and narrow bus, that's as good as it will get!
 
For a full 1024*600 @ 2bpp frame on an 8 bit bus with a 40Mhz baud rate you should get up to 16fps.
No super fast, but for such a high resolution and narrow bus, that's as good as it will get!
Awesome. Now to cover any leftover SPI calls with 8080 calls and then onto the MicroMod. I am really trying keep it all in one library...
 
The MicroMod is working with the ER-TFTM101-1 display.
MM8080.png


MM8080-1.png


Still have to get the DMA portion working on the MicroMod. The images were produced in 8-bit mode none DMA, 100ms to display both pictures. I'm sure DMA will speed things up. By the time I am done with the Ra8876LiteTeensy library it will be big and bulky. Not quite sure how I want to approach it. Right now RA8876_t3.cpp is coming up on 300kB. It now supports SPI, 8080 parallel, 8-bit and 16-bit on the T4x and MicroMod.

As @KurtE would say "Now back to playing"
 
I am trying to find the answer to why doing a FlexIO parallel read results in the /RD signal showing 4 pulses as apposed to the /WR signal showing just one pulse. I have looked all over the net and reference manual with no luck. It's probably obvious but not for me :)

Screenshot at 2024-03-29 18-04-30.png



Screenshot at 2024-03-29 18-16-45.png


Appreciate any help...
 
what clock source are you using? And prescalers?

When I was playing with FlexIO initially I found that the clock speed had to be half of the clock source speed.
Eg if the clock source is 480Mhz, the maximum FlexIO clock speed can be 240Mhz.
When the it was set above, I was getting multiple WR pulses for a single beat transfer
 
I am using this:
Code:
pFlex->setClockSettings(3, 1, 0); // (480 MHz source, 1+1, 1+0) >> 480/2/1 >> 240Mhz
and here is the FlexIO read setup:
Code:
FASTRUN void RA8876_t3::FlexIO_Config_SnglBeat_Read() {
#if defined(USE_MM)

    p->CTRL &= ~FLEXIO_CTRL_FLEXEN;
    p->CTRL |= FLEXIO_CTRL_SWRST;
    p->CTRL &= ~FLEXIO_CTRL_SWRST;

    gpioRead();

    /* Configure the shifters */
    p->SHIFTCFG[3] =
        //FLEXIO_SHIFTCFG_INSRC                                                  /* Shifter input */
        FLEXIO_SHIFTCFG_SSTOP(0)                                              /* Shifter stop bit disabled */
       | FLEXIO_SHIFTCFG_SSTART(0)                                             /* Shifter start bit disabled and loading data on enabled */
       | FLEXIO_SHIFTCFG_PWIDTH(7);                                            /* Bus width */
   
    p->SHIFTCTL[3] =
        FLEXIO_SHIFTCTL_TIMSEL(0)                                              /* Shifter's assigned timer index */
      | FLEXIO_SHIFTCTL_TIMPOL*(1)                                             /* Shift on posedge of shift clock */
      | FLEXIO_SHIFTCTL_PINCFG(0)                                              /* Shifter's pin configured as input */
      | FLEXIO_SHIFTCTL_PINSEL(4)  //4                                            /* Shifter's pin start index */
      | FLEXIO_SHIFTCTL_PINPOL*(0) //0                                            /* Shifter's pin active high */
      | FLEXIO_SHIFTCTL_SMOD(1);                                               /* Shifter mode as recieve */

    /* Configure the timer for shift clock */
    p->TIMCMP[0] =
        (((1 * 2) - 1) << 8)                                                   /* TIMCMP[15:8] = number of beats x 2 – 1 */
      | (((_baud_div)/2) - 1);       //30             /* TIMCMP[7:0] = baud rate divider / 2 – 1 ::: 30 = 8Mhz with current controller speed */
   
    p->TIMCFG[0] =
        FLEXIO_TIMCFG_TIMOUT(0)                                                /* Timer output logic one when enabled and not affected by reset */
      | FLEXIO_TIMCFG_TIMDEC(0)                                                /* Timer decrement on FlexIO clock, shift clock equals timer output */
      | FLEXIO_TIMCFG_TIMRST(0)                                                /* Timer never reset */
      | FLEXIO_TIMCFG_TIMDIS(2)                                                /* Timer disabled on timer compare */
      | FLEXIO_TIMCFG_TIMENA(2)                                                /* Timer enabled on trigger high */
      | FLEXIO_TIMCFG_TSTOP(1)                                                 /* Timer stop bit disabled */
      | FLEXIO_TIMCFG_TSTART*(0);                                              /* Timer start bit disabled */
   
    p->TIMCTL[0] =
        FLEXIO_TIMCTL_TRGSEL((((3) << 2) | 1))                                 /* Timer trigger selected as shifter's status flag */
      | FLEXIO_TIMCTL_TRGPOL*(1)                                               /* Timer trigger polarity as active low */
      | FLEXIO_TIMCTL_TRGSRC*(1)                                               /* Timer trigger source as internal */
      | FLEXIO_TIMCTL_PINCFG(3)                                                /* Timer' pin configured as output */
      | FLEXIO_TIMCTL_PINSEL(1)                                                /* Timer' pin index: RD pin */
      | FLEXIO_TIMCTL_PINPOL*(1)                                               /* Timer' pin active low */
      | FLEXIO_TIMCTL_TIMOD(1);                                                /* Timer mode as dual 8-bit counters baud/bit */

 
    /* Enable FlexIO */
   p->CTRL |= FLEXIO_CTRL_FLEXEN;    
}
#else
and the actual read command:
Code:
//**************************************************************//
// Read RA8876 parallel Data (8bit read)
//**************************************************************//
ru8 RA8876_t3::lcdDataRead(bool finalize)
{
  uint16_t dummy = 0;
  uint16_t data = 0;
  while(WR_IRQTransferDone == false) {} //Wait for any DMA transfers to complete

// Check WINT pin (33) active low.
//  while(digitalReadFast(33) == 0);

  FlexIO_Config_SnglBeat_Read();

  CSLow();

  DCHigh(); // Should already be HIGH
delayMicroseconds(1);

  while (0 == (p->SHIFTSTAT & (1 << 3))) {}
  dummy = p->SHIFTBUFBYS[3];

  while (0 == (p->SHIFTSTAT & (1 << 3))) {}
  data = p->SHIFTBUFBYS[3];

delayMicroseconds(1);
  CSHigh();

  //Set FlexIO back to Write mode
  FlexIO_Config_SnglBeat();

//Serial.printf("dummy = %d, data = %d\n",dummy,data);
  return data;
//  return dummy;
}
Lastly the sketch:
Code:
#include "RA8876_t3.h"
#include "flexio_teensy_mm.c"

uint8_t dc = 13;
uint8_t cs = 11;
uint8_t rst = 5;
uint32_t start = 0;
uint32_t end =  0;

uint8_t busSpeed = 8;

RA8876_t3 lcd = RA8876_t3(dc,cs,rst); //(dc, cs, rst)

void setup() {
  while (!Serial && millis() < 3000) {} //wait for Serial Monitor
  Serial.printf("%c Teensy and RA8876 parallel 8080 mode testing (8/16)\n",12);
  Serial.print(CrashReport);
  pinMode(33, INPUT); // For XnWAIT signal if connected and used.

  lcd.begin(busSpeed);
  Serial.print("\nBus speed: ");
  Serial.print(busSpeed,DEC);
  Serial.println(" MHZ");
  lcd.fillScreen(0x0000);
}

uint16_t  rslt = 0;

void loop() {
  lcd.drawLine(0x0000,0x0001,0x00ff, 0x0001,0x0102);
  lcd.graphicMode(true);
//    activeWindowXY(x,y);
//    activeWindowWH(width,height);
  lcd.setPixelCursor(0x0000,0x0001);
  lcd.ramAccessPrepare();
  rslt = lcd.lcdDataRead(false);//RA8876 dummy read
  rslt = (lcd.lcdDataRead(false) << 8); // Read low byte
  rslt |= (lcd.lcdDataRead(false) & 0xff); // or in high byte
  Serial.printf("rslt = 0x%4.4X\n",rslt);
  waitforInput();
}

void waitforInput()
{
  Serial.println("Press anykey to continue");
  while (Serial.read() == -1) ;
  while (Serial.read() != -1) ;
}
The read command works fine when reading the RA8876 registers. But it is inconsistent when trying to read from the RA8876 video memory. One other thing that might be a problem is that there is an external wait pin that is asserted by the RA8876 when it is busy internally. I had this hooked up to pin #33 on the MicroMod and monitored it in the above code but it did not make a difference.
It should be returning 0x0102 and it does most of the time. But sometimes it is returning 0x0201 or 0x0202.
 
Actually you still need these parts in place of gpioRead() and gpioWrite():
Code:
  pFlex->setIOPinToFlexMode(12); // For /RD signal
  pFlex->setIOPinToFlexMode(10); // For /WR signal

So here is a a version of lcdDataRead() that works:
Code:
//**************************************************************//
// Read RA8876 parallel Data (8bit read)
//**************************************************************//
ru8 RA8876_t3::lcdDataRead(bool finalize) {
  uint16_t dummy = 0;
  uint16_t data = 0;

  while(WR_IRQTransferDone == false) {} //Wait for any DMA transfers to complete

  FlexIO_Config_SnglBeat_Read();
  delayNanoseconds(1500); // Seems to be the optimal delay needed

  CSLow();  // Must to go low after config and delay above.
  DCHigh(); // Should already be HIGH

  while (0 == (p->SHIFTSTAT & (1 << 3))) {}
  dummy = p->SHIFTBUFBYS[3];

  while (0 == (p->SHIFTSTAT & (1 << 3))) {}
  data = p->SHIFTBUFBYS[3];

  while(digitalReadFast(3) == 0);  // If monitoring XnWAIT signal from RA8876.

  delayNanoseconds(500);
  CSHigh();

  //Set FlexIO back to Write mode
  FlexIO_Config_SnglBeat();

  return data;
}
and read config without gpioRead():
Code:
FASTRUN void RA8876_t3::FlexIO_Config_SnglBeat_Read() {
#if defined(USE_MM)

    p->CTRL &= ~FLEXIO_CTRL_FLEXEN;
    p->CTRL |= FLEXIO_CTRL_SWRST;
    p->CTRL &= ~FLEXIO_CTRL_SWRST;

//    gpioRead();  // Not used

    /* Configure the shifters */
    p->SHIFTCFG[3] =
        //FLEXIO_SHIFTCFG_INSRC                                                  /* Shifter input */
        FLEXIO_SHIFTCFG_SSTOP(0)                                              /* Shifter stop bit disabled */
       | FLEXIO_SHIFTCFG_SSTART(0)                                             /* Shifter start bit disabled and loading data on enabled */
       | FLEXIO_SHIFTCFG_PWIDTH(7);                                            /* Bus width */
    
    p->SHIFTCTL[3] =
        FLEXIO_SHIFTCTL_TIMSEL(0)                                              /* Shifter's assigned timer index */
      | FLEXIO_SHIFTCTL_TIMPOL*(1)                                             /* Shift on posedge of shift clock */
      | FLEXIO_SHIFTCTL_PINCFG(0)                                              /* Shifter's pin configured as input */
      | FLEXIO_SHIFTCTL_PINSEL(4)  //4                                            /* Shifter's pin start index */
      | FLEXIO_SHIFTCTL_PINPOL*(0) //0                                            /* Shifter's pin active high */
      | FLEXIO_SHIFTCTL_SMOD(1);                                               /* Shifter mode as recieve */

    /* Configure the timer for shift clock */
    p->TIMCMP[0] =
        (((1 * 2) - 1) << 8)                                                   /* TIMCMP[15:8] = number of beats x 2 – 1 */
      | (((_baud_div)/2) - 1);       //30             /* TIMCMP[7:0] = baud rate divider / 2 – 1 ::: 30 = 8Mhz with current controller speed */
    
    p->TIMCFG[0] =
        FLEXIO_TIMCFG_TIMOUT(0)                                                /* Timer output logic one when enabled and not affected by reset */
      | FLEXIO_TIMCFG_TIMDEC(0)                                                /* Timer decrement on FlexIO clock, shift clock equals timer output */
      | FLEXIO_TIMCFG_TIMRST(0)                                                /* Timer never reset */
      | FLEXIO_TIMCFG_TIMDIS(2)                                                /* Timer disabled on timer compare */
      | FLEXIO_TIMCFG_TIMENA(2)                                                /* Timer enabled on trigger high */
      | FLEXIO_TIMCFG_TSTOP(1)                                                 /* Timer stop bit disabled */
      | FLEXIO_TIMCFG_TSTART*(0);                                              /* Timer start bit disabled */
    
    p->TIMCTL[0] =
        FLEXIO_TIMCTL_TRGSEL((((3) << 2) | 1))                                 /* Timer trigger selected as shifter's status flag */
      | FLEXIO_TIMCTL_TRGPOL*(1)                                               /* Timer trigger polarity as active low */
      | FLEXIO_TIMCTL_TRGSRC*(1)                                               /* Timer trigger source as internal */
      | FLEXIO_TIMCTL_PINCFG(3)                                                /* Timer' pin configured as output */
      | FLEXIO_TIMCTL_PINSEL(1)                                                /* Timer' pin index: RD pin */
      | FLEXIO_TIMCTL_PINPOL*(1)                                               /* Timer' pin active low */
      | FLEXIO_TIMCTL_TIMOD(1);                                                /* Timer mode as dual 8-bit counters baud/bit */

  pFlex->setIOPinToFlexMode(12);  //           Added
 
    /* Enable FlexIO */
   p->CTRL |= FLEXIO_CTRL_FLEXEN;     

#else

The LA output reading a value of 0x01:
Screenshot at 2024-03-31 09-31-43.png

Marker "K" is the falling edge of the first /RD pulse. Marker "L" is rising edge of the first wait state applied by the RA8876. The data is valid between the "k" and "L" markers (D0 is high) but not valid between "N" and "M" markers. Then on the third /RD pulse is valid again. The correct value of 0x01 was returned. So which /RD pulse returned the correct value? The first or third? The second /RD pulse is invalid (0x00).
The WINT (XnWAIT) signal happens 42ns after the /RD signal goes low which makes sense but why is there three or sometimes four /RD pulses used for one 8-bit read? That is what is eluding me:confused: Cannot seem to find that information anywhere. As of right now I am getting consistent 8/16 bit reads.
Anyway the next challenge is figuring out why when displaying an image using DMA on the MicroMod shows missed or overlapped vertical lines every few vertical lines of the image.

Bad image displayed using MulBeatWR_nPrm_DMA():
Bad_image.jpg


Good image displayed using the writeRect() function:
Good_image.jpg


Possibly a timing issue again with DMA writes. Need to learn more about DMA usage.
I'll keep plugging away at it:D
 
I had issues just as you have above with the DMA write, but I can't recall what it was.
Worth reading though my comments in this FlexIO thread - my memory is just not good enough to recall what the root cause was. But I have a feeling it's the byte swap in the shifter buffer
 
I had issues just as you have above with the DMA write, but I can't recall what it was.
Worth reading though my comments in this FlexIO thread - my memory is just not good enough to recall what the root cause was. But I have a feeling it's the byte swap in the shifter buffer
Thanks, I'll take a look at it. So far it has been my lack of knowledge of FlexIO and DMA that has slowed me down but I'm starting to understand it more...
 
Back
Top