Go Down

Topic: GxTFT library - modifying it to work on other STM32 boards (Read 756 times) previous topic - next topic

david_prentice

#15
Feb 07, 2021, 10:06 am Last Edit: Feb 07, 2021, 10:47 am by david_prentice
@Jean-Marc,

How do Distributors operate in Switzerland?

In the UK I can order the Nucleo from Farnell before 18.00 and it arrives at my front door at about 11.00 the following morning.
My packet would probably come from the UK Warehouse but sometimes from Belgium.

I have heard conflicting reports that some European Distributors will not sell to the general public.
But UK companies don't mind who they sell to.   As long as they get their money.

Yes,  I have noticed that regular ST Evaluation Boards are sold by Chinese companies on Ebay at extortionate prices.    When you can buy from the official Distributor in your own country.

David.

ZinggJM

@David,

Quote
How do Distributors operate in Switzerland?
I don't have much experience ordering from distributors, except for consumer electronics.
For consumer electronics it is easy, there are several good choices, I have to decide for each order.
For hobby electronics components it is a bit more difficult to find out who has what at which price.
Component prices are often considerably higher than from AliExpress shops.

One shop I order from time to time is conrad.ch (also known conrad.de).
My first Arduino was a "Pretzelboard" Arduino Nano - ESP-01 board in a IoT - Adventskalender from Conrad.
Delivery is a bit slow, some days, unless you order express delivery.

I think Distrelec is a well-known distributor in Switzerland.

But I rarely think of ordering from a local distributor, as I am so much used to look on AliExpress.
AliExpress delivery currently is rather slow and varies considerably, because of COVID-19. Usual was 3 weeks.
Lithium Accus are extremely slow, up to 3 months, because only PostNL transports them.

Quote
I have heard conflicting reports that some European Distributors will not sell to the general public.
One reason is that they need an agreement with swiss customs to collect and deliver VAT.
An other reason may be that factories prefer to force higher prices through retailers in Switzerland.

Jean-Marc
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

ZinggJM

@David,

I just received my Nucleo-144 boards (STM32F767ZIT6 and STM32F746ZGT6) from Digi-Key.
So delivery is quite fast from this distributor. It arrived by UPS.
I bought 2 boards to have free shipping delivery. Price paid in SFr. through PayPal, with VAT already added.

@RGarrett93,

Next step is study the pins, find where the FSMC data pins are, and then create a shield for my (FSMC) TFTs.
This will take some time, from experience double row connectors take time with me, especially when on different side of the proto board.

Jean-Marc
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

RGarrett93

@ZinggJM,

Apologies only just saw your reply (I'm not receiving notification alerts), that's great to hear you have received the nucleo boards.
So things to note, on the STM32F767ZIT6 there is no FSMC but instead it's now known as FMC, all the FSMC stuff just needs to be renamed but it should work much the same.

The STM32F767 FMC pins are exactly the same as the STMF4 FSMC pins, so you should be able to use the exact same registers.

Two of the FMC pins (PD8 & PD9) conflict with the STlink board at the top of the Nucleo, as it is used for virtual serial comms when you plug your nucleo to you PC.
They are easily disconnected via two solder bridge, this can be done by removing SB5 & SB6 link resistors which are in the middle of the Nucleo board.

Most of the pins will be on the morpho connectors, see below.








ZinggJM

@RGarrett93,

thank you for your valuable input! This will help me get started faster.

I just finished my proto-shield. 
It was trickier than expected, as most pins are available on the ST Zio connectors, but not all.
I hope I didn't introduce too many errors.
My first test with the bit-bashed driver just failed, so I need to do some checks.
The FSMC/FMC version will come afterwards, so I didn't notice the name change yet.

From your post it is unclear to me if you got it already working with GxTFT.

Jean-Marc
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

RGarrett93

@ZinggJM

I have not managed to get it working directly with the FSMC/FMC pins, I have merely done baby steps to get where I am: so I get a better understanding of how it all works and goes together etc...
I have wired up to the FMC pins and using part of your library for GxIO F407 registers and cross referencing with the datasheet to test P16 but it didn't work.

On my previous post I used only the zio connector uno equivalent pins D13 to D0 for bitbashing but with just using pinMode, digitalWrite & digitalRead (GxTFT_MCU_Tester.cpp) and it worked with your GxTFT library but with poor performance: I did attempt using the registers instead of pinMode on the same pins with the zio connectors (Nucleo_144.cpp) but it didn't quite work with just a few line flickers, as mentioned previously most probably is a timing issue with that.

The end target is to get it working with FMC and use those pins instead but I wanted a good datum to start off from.

Thanks
Ryan

RGarrett93

GxTFT_MCU_Tester.cpp


Unfortunately unable to test this method of bitbashing with the FMC pins as one of the GPIO has not been assigned on STM32duino core, from memory it was PD10 but I will have to double check that.
So would have to use the registers instead

pin defines
Code: [Select]
// Pin define here

#define CS  PA3
#define RS  PF3
#define RST 0
#define WR  PC3
#define RD  PC0
#define BL  PB1

  // TFT connector to Nucleo 144 pins (Zio Connector)
  // D0   D1   D2   D3   D4   D5   D6  D7   D8   D9  D10  D11 D12 D13 D14 D15
  // PG9 PG14 PF15 PE13 PF14 PE11 PE9 PF13 PF12 PD15 PD14 PA7 PA6 PA5 PB9 PB8

#define _D15  PB8
#define _D14  PB9
#define _D13  PA5
#define _D12  PA6
#define _D11  PA7
#define _D10  PD14
#define _D9   PD15
#define _D8   PF12
#define _D7   PF13
#define _D6   PE9
#define _D5   PE11
#define _D4   PF14
#define _D3   PE13
#define _D2   PF15
#define _D1   PG14
#define _D0   PG9


readData16
Code: [Select]
uint16_t MCU_Tester::readData16()
{
  // Set direction to input
pinMode(_D15, INPUT);  //15
pinMode(_D14, INPUT);  //14
pinMode(_D13, INPUT);  //13
pinMode(_D12, INPUT);  //12
pinMode(_D11, INPUT);  //11
pinMode(_D10, INPUT); //10
pinMode(_D9, INPUT); //9
pinMode(_D8, INPUT); //8
pinMode(_D7, INPUT); //7
pinMode(_D6, INPUT);  //6
pinMode(_D5, INPUT); //5
pinMode(_D4, INPUT); //4
pinMode(_D3, INPUT); //3
pinMode(_D2, INPUT); //2
pinMode(_D1, INPUT); //1
pinMode(_D0, INPUT);  //0

digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);


  uint16_t rv = 0;

  rv |= digitalRead(_D15) ? 0x8000 : 0x0000; //15
  rv |= digitalRead(_D14) ? 0x4000 : 0x0000; // 14
  rv |= digitalRead(_D13) ? 0x2000 : 0x0000; // 13
  rv |= digitalRead(_D12) ? 0x1000 : 0x0000; // 12
  rv |= digitalRead(_D11) ? 0x0800 : 0x0000; // 11
  rv |= digitalRead(_D10) ? 0x0400 : 0x0000; // 10
  rv |= digitalRead(_D9) ? 0x0200 : 0x0000;  // 9
  rv |= digitalRead(_D8) ? 0x0100 : 0x0000;  // 8

  rv |= digitalRead(_D7) ? 0x0080 : 0x0000;  // 7
  rv |= digitalRead(_D6) ? 0x0040 : 0x0000;  // 6
  rv |= digitalRead(_D5) ? 0x0020 : 0x0000;  // 5
  rv |= digitalRead(_D4) ? 0x0010 : 0x0000;  // 4
  rv |= digitalRead(_D3) ? 0x0008 : 0x0000;  // 3
  rv |= digitalRead(_D2) ? 0x0004 : 0x0000;  // 2
  rv |= digitalRead(_D1) ? 0x0002 : 0x0000;  // 1
  rv |= digitalRead(_D0) ? 0x0001 : 0x0000;  // 0

 digitalWrite(_rd, HIGH);
  
  // Set direction output again
pinMode(_D15, OUTPUT);  //15
pinMode(_D14, OUTPUT);  //14
pinMode(_D13, OUTPUT);  //13
pinMode(_D12, OUTPUT);  //12
pinMode(_D11, OUTPUT);  //11
pinMode(_D10, OUTPUT); //10
pinMode(_D9, OUTPUT); //9
pinMode(_D8, OUTPUT); //8
pinMode(_D7, OUTPUT); //7
pinMode(_D6, OUTPUT);  //6
pinMode(_D5, OUTPUT); //5
pinMode(_D4, OUTPUT); //4
pinMode(_D3, OUTPUT); //3
pinMode(_D2, OUTPUT); //2
pinMode(_D1, OUTPUT); //1
pinMode(_D0, OUTPUT);  //0

digitalWrite(_D15, HIGH);  //15
digitalWrite(_D14, HIGH);  //14
digitalWrite(_D13, HIGH);  //13
digitalWrite(_D12, HIGH);  //12
digitalWrite(_D11, HIGH);  //11
digitalWrite(_D10, HIGH); //10
digitalWrite(_D9, HIGH); //9
digitalWrite(_D8, HIGH); //8
digitalWrite(_D7, HIGH); //7
digitalWrite(_D6, HIGH);  //6
digitalWrite(_D5, HIGH); //5
digitalWrite(_D4, HIGH); //4
digitalWrite(_D3, HIGH); //3
digitalWrite(_D2, HIGH); //2
digitalWrite(_D1, HIGH); //1
digitalWrite(_D0, HIGH);  //0

  return rv;
}


writeData16
Code: [Select]
void MCU_Tester::writeData16(uint16_t d, uint32_t num)
{

digitalWrite(_D15, LOW);  //15
digitalWrite(_D14, LOW);  //14
digitalWrite(_D13, LOW);  //13
digitalWrite(_D12, LOW);  //12
digitalWrite(_D11, LOW);  //11
digitalWrite(_D10, LOW); //10
digitalWrite(_D9, LOW); //9
digitalWrite(_D8, LOW); //8
digitalWrite(_D7, LOW); //7
digitalWrite(_D6, LOW);  //6
digitalWrite(_D5, LOW); //5
digitalWrite(_D4, LOW); //4
digitalWrite(_D3, LOW); //3
digitalWrite(_D2, LOW); //2
digitalWrite(_D1, LOW); //1
digitalWrite(_D0, LOW);  //0

  (d & 0x8000) ? digitalWrite(_D15, HIGH) : digitalWrite(_D15, LOW); //15
  (d & 0x4000) ? digitalWrite(_D14, HIGH) : digitalWrite(_D14, LOW); //14
  (d & 0x2000) ? digitalWrite(_D13, HIGH) : digitalWrite(_D13, LOW); //13
  (d & 0x1000) ? digitalWrite(_D12, HIGH): digitalWrite(_D12, LOW); //12
  (d & 0x0800) ? digitalWrite(_D11, HIGH) : digitalWrite(_D11, LOW); //11
  (d & 0x0400) ? digitalWrite(_D10, HIGH) : digitalWrite(_D10, LOW); //10
  (d & 0x0200) ? digitalWrite(_D9, HIGH) : digitalWrite(_D9, LOW);//9
  (d & 0x0100) ? digitalWrite(_D8, HIGH) : digitalWrite(_D8, LOW);//8

  (d & 0x0080) ? digitalWrite(_D7, HIGH) : digitalWrite(_D7, LOW);//7
  (d & 0x0040) ? digitalWrite(_D6, HIGH) : digitalWrite(_D6, LOW);//6
  (d & 0x0020) ? digitalWrite(_D5, HIGH) : digitalWrite(_D5, LOW);//5
  (d & 0x0010) ? digitalWrite(_D4, HIGH) : digitalWrite(_D4, LOW);//4
  (d & 0x0008) ? digitalWrite(_D3, HIGH) : digitalWrite(_D3, LOW);//3
  (d & 0x0004) ? digitalWrite(_D2, HIGH) : digitalWrite(_D2, LOW);//2
  (d & 0x0002) ? digitalWrite(_D1, HIGH) : digitalWrite(_D1, LOW);//1
  (d & 0x0001) ? digitalWrite(_D0, HIGH) : digitalWrite(_D0, LOW); //0

  while (num)
  {
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, HIGH);
    num--;
  }
}




ZinggJM

@RGarrett93,

Version 2.1.2 of library GxTFT is available.

- added support for my Nucleo-144 proto board with FSMC/FMC TFT connector
- supported by class GxIO_STM32Nucleo144_P16 using bit-bashing for F767ZI and F746ZG
- tested with 3.2" ILI9341 on F767ZI
- FSMC/FMC version will follow, expected to be only slightly faster

My first attempts with FSMC/FMC failed. I will need to take a closer look at the STM32F7 docs.

I have opened an issue about the missing pin #defines for Nucleo-144 F767ZI.

I had to use a workaround to create a long enough write pulse with the bit-bashing verrsion:

Code: [Select]
 while (num)
  {
    // this doesn't work. reason unknown. optimized by compiler?
    //GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    //GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    //GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    //GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    //GPIOD->BSRR = (0x1 << 5); // PD5 WR high
    // this does work. compiler can't optimize.
    volatile static uint32_t ttt = 1;
    if (ttt++) GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    if (ttt++) GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    //    if (ttt++) GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    //    if (ttt++) GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    //    if (ttt++) GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    ttt = 1; // don't miss once in 2**32
    GPIOD->BSRR = (0x1 << 5); // PD5 WR high
    // this would also work, but slower
    //digitalWrite(_wr, LOW);
    //digitalWrite(_wr, HIGH);
    num--;
  }


Jean-Marc

No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

RGarrett93

@ZinggJM,

That is great, thank you so much for your help with this!

Look forward to trying it out, I'm going to observe your code as I was yet to the test the registers I wrote on my custom code - still learning but I must of miscounted a bit (assigned the wrong pin).

I will post an example of LVGL on here for others to use with your library as I managed to get the API to draw properly with some tweaking.

Cheers
Ryan

ZinggJM

@RGarrett93,

From post #3:

Quote
ICache & DCache on the F7 is used, so I have disabled that to keep it matching the F4.
Could you please tell me how you do this? It may be related to my current failure with FMC.
I try to continually write the same value through FMC, to check if I see anything on 2*8 pin led rows.
But I see neither data nor CS nor RW. In some search results I saw that may be related to cache, as FMC is also (or mainly) for memories.

I am a bit lost, as searching in the HAL sources is difficult, and searching with Google helps, but requires to read a lot, and results often are incomplete.

Jean-Marc
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

RGarrett93

@ZinggJM

You have to customise the core definitions.

Customize build options using build_opt.h

I have attached the build_opt.h on here with the inline definitions to disable the ICache & DCache: place that file in your sketch directory (if using arduino IDE)... just as a side note if you update the contents of build_opt.h to include other definitions then close the IDE down and open again to get it to force rebuild otherwise it will use the previous build.

If the IDE doesn't see the inline definitions for the Cache then the below is enabled by default.
Code: [Select]
#if (__CORTEX_M == 0x07U)
  // Defined in CMSIS core_cm7.h
#ifndef I_CACHE_DISABLED
  SCB_EnableICache();
#endif
#ifndef D_CACHE_DISABLED
  SCB_EnableDCache();
#endif
#endif


I am just about to test your GxTFT 2.1.2 with my display once I have wired it up  :)

Ryan

RGarrett93

I've just played with the latest version and it works really well, its very fast: fmc optimisation will be interesting, the ICache and DCache from what I have read can cause issues.

I copied how you done your writing strobe to test the custom registers I wrote and it worked for me: I'm pleased so at least I know I was on the right track with them.

I've learnt alot from all of this, thanks again.

ZinggJM

Hi Ryan,

Thank you for the build options. It helped me to verify that my issues were caused by the cache function.

I found a topic that suggested a solution to avoid this by switching FMC address regions:
STM32H743II FMC + 8080 LCD spurious writes
This solution allows to avoid the need for build options for users.
There would also be the possibility to add a memory region, and to disable caching for that region.

Version 2.1.3 of library GxTFT is available.

- added FSMC/FMC support for my Nucleo-144 proto board with FSMC/FMC TFT connector
- supported by class GxIO_STM32Nucleo144_FSMC using FMC for F767ZI and F746ZG
- tested with 3.2" ILI9341 on F767ZI

Jean-Marc
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

david_prentice

No,   I have not studied the FSMC peripheral.   The only advantage would be DMA.    And this would require suitable timing e.g. > 60ns for tWC and > 160ns for tRC.

I only have one 8080-16 raw interface panel.   i.e. a 800x480 SSD1963
So it would be fairly pointless making a FSMC adapter for my Nucleo-F767 board.

David.

ZinggJM

Hi David,

yes, this was maybe more an academic exercise.

FSMC or FMC for TFTs makes sense if both the processor board and the TFT have matching connector.

Code: [Select]
#define ADDSET 15 // (ADDSET+1)*6ns = CS to RW
#define DATAST 30 // (DATAST+1)*6ns = RW length

I have chosen rather conservative timing parameters; can be changed. Oops, 6ns may be for slower clock rate.

Jean-Marc
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

Go Up