HX8357D TFT + STMPE610 Touch drivers for 480x320 Adafruit featherwing

I wrote a pair of drivers for the HX8357D TFT controller and STMPE610 Resistive touch controller for the lv_port_esp32 project. It’s currently in my own fork of this project but apparently I can’t post a link here. The HX8357D driver is based on Adafruit’s arduino driver. The hardware was built using a Sparkfun ESP32 Thing Plus and the Adafruit 3.5" 480x320 TFT Featherwing.

Performance is quite reasonable with a 26 MHz SPI bus to the TFT. One thing to note is that both the TFT and touchscreen controllers are on the same bus. I had to add a mutex to protect the touchscreen controller because, like the XPT2046, the SPI CS is handled in code and can be interrupted by a TFT SPI transfer that screws up the touch controller.

2 Likes

Recently I updated the forum settings to only allow new users to post links to certain sites. I did that to try and combat some of the recent robot spam posts I’ve been seeing. What site were you trying to link to? https://github.com/danjulio/lv_port_esp32?

Ah! That makes sense. Yes, a link to the repository in case others wanted to try it out as well as links to sparkfun and adafruit (but those are in the respository). Thanks for clarifying.

It’s not supposed to be blocking links to GitHub. I’ll take a look at the settings.

@danjulio @app-z It turns out I had configured the wrong setting for the new user link whitelist. I’ve changed the appropriate setting, so you should be able to post links now.

@danjulio are you willing to add support for those drivers in the littlevgl/lv_port_esp32 repo? There’s a PR to support sharing the same SPI bus for both tft and touch controllers here, it’s soon to be merged.

Also, anything on the littlevgl/lv_port_esp32 that we can improve?

Regards

@Carlos_Diaz - sure, I’ll wait for the merge and then I can test and try to add these drivers. I looked at the PR and saw the CS moved to the tp_spi code. I think this should work as well with the STMPE610 (although it has a maximum 1 MHz SPI clock).

Great, I will try to test that PR to merge it this weekend.

About the SPI clock being slower, yes, I see that caveat with shared SPI bus, on the PR the OP says the SPI clock halves its speed because the SPI bus must be configured as full duplex. I will try to take a look at the touch controller code because is something il not as familiar as I would like.

Carlos, I’m not sure what the OP meant. I haven’t seen the clock rate halved by setting full duplex. My understanding is that full duplex is used because the drivers have to clock a byte into a touch controller as they are clocking one out while the LCD displays can be one-way and need to be fast so setting half duplex lets the ESP32 library use DMA driven SPI transmissions offloading the CPU. The touch drivers are written like (and probably ported from) Arduino libraries where the SPI.write() function both writes via MOSI and reads via MISO simultaneously.

The current XPT2046 driver runs at 2 MHz because the chip can support that clock rate. Unfortunately the STMPE610 can only support a maximum 1 MHz clock. If you look at my tp_spi code you’ll see I added a project config to set 1 MHz for that chip while leaving 2 MHz for the XPT2046. I was planning to use that same config mechanism in the ported code unless you have another way you’d like me to use.

Hi @danjulio ,

Yesterday i merged the pull request that shows how to share the spi bus between the tft and touch controllers. I’ve also added a new file named touch_driver, which try to abstract the touch controllers.

On lvgl_tft/disp_driver.h file i’ve added some defines:

/* Add a new define entry at the end for new controllers */
#define TFT_CONTROLLER_ILI9341 0
#define TFT_CONTROLLER_ILI9488 1
#define TFT_CONTROLLER_ST7789 2

So we don’t use magic numbers when trying to figure out what controller was configured, as the comment says you should add the name of the new tft controller at the end of the enum for adding support for new controllers. I did the same on lvgl_touch/touch_driver.h for the touch controllers.

I would like to know your feedback on this, so you can add the code for the HX8357D and STMPE610 more easily. Can you push your commits to this new branch so we can merge it all at once to master?

I think i saw it on your repo, did you added an option on the Kconfig to choose the SPI bus to be used?

Regards

@Carlos_Diaz -

I spent the day trying to merge and get my stuff running again. Unfortunately I only went by the email I received from the forum so I merged it with the “update_comments_in_main” fork. I didn’t see that you’d edited the post until tonight when I logged in to make an update for you.

I did fix the enum stuff myself and made other changes to get it to compile. Unfortunately at the moment I cannot get the touch controller working with the new SPI setup. For some reason I cannot get all the read bytes. I see using my oscilloscope that the touch controller is driving the correct data on MISO and I also see the SPI bus is in the expected mode (now mode 0). But the read data doesn’t make it back to the code correctly. It is very frustrating.

I’m continuing to debug. This is just an update to let you know I’m working on this.

Have you gotten the new code to work with the XPT2046 driver? Another issue I saw were error messages if the touch pad buffer was not a multiple of 32-bits because the DMA engine requires that (see https://www.esp32.com/viewtopic.php?t=7921).

I also have a question about the Kconfig files. I am new to that but I don’t think they are working as expected. I think the goal is that things like TFT_WIDTH auto adjust based on LVGL_PREDEFINED_DISPLAY_XXX. However I never see the width change based on the selecting a predefined display configuration (I’d like to add one for the Adafruit board). Am I missing some fundamental understanding about Kconfig operation?

P.S. I am integrating support to select the SPI busses for TFT & Touch. I slightly re-arranged the way you implemented main to reduce some dependencies on the device type and make the TFT and Touch drivers work identically.

Hi @danjulio,

Yes, sorry about that, I merged the update_comments_in_main branch into main after doing the first post here. Are you still using the branch you posted earlier on this post?

I had to change from enum to defines :confused:, I will check the touch controller code once I arrive home, i don’t have any kits with me at work.

Did you have the display controller working? We could merge that and continue the debug on the touch controller code.

To be honest I haven’t tested the touch controllers, thanks for the link, i will check it out. The test code that shares the SPI bus between the tft and touch controllers works only with the ILI9341 controller as is. Maybe we could remove the CONFIG_LVGL_TOUCH_CONTROLLER == 1 part of the #if.

#if CONFIG_LVGL_TOUCH_CONTROLLER == 1 && TP_SPI_MOSI == DISP_SPI_MOSI && TP_SPI_CLK == DISP_SPI_CLK
/* Example function that configure two spi devices (tft and touch controllers) into the same spi bus */
static void configure_shared_spi_bus(void);
#endif

As a user what would expect by default? Share the SPI bus between the tft and touch controllers, each controller on it’s separated SPI bus? Ask the user on the menuconfig?

Right now the TFT_WIDTH option can be edited by the user because there are tft displays of different sizes but with the same controller. We could automatically set TFT_WIDTH based on the PREDEFINED_DISPLAY selected option as you mention, but only with a few TFT display modules, like yours or the one available on the Wrover kit v4.1 because we know the dimensions of the display doesn’t change. Can you open an issue on the lv_port_esp32 repo about this?

Great, thank you, yesterday I added support for the ST7789 tft controller, and I will test it tomorrow night.

I’m also working on be able to configure lvgl from the menuconfig, right now i can enable built in fonts and choose the default one, and also enable themes, those changes are available on the lvgl_kconfig branch of the repo.

Thanks a lot for the help :smiley:, sorry about the mess on the repository, maybe we can find a better communication channel.

Regards

@Carlos_Diaz - glad to help. I really like lvgl and use it in various projects so this is a way to help out a bit.

I did get the touch working. I had to move away from full duplex transactions and am now using the cmd field for reads (cmd has the register address and the main SPI transaction gets the read data). Based on some reading online it seems others have had trouble with full duplex SPI reads and DMA (I did try without DMA and it worked but, of course, the display cycles using the same SPI bus failed because they were too big). If necessary the XPT2046 controller can also be made to work using the same read methodology. I will try to test it tonight.

My original fork has now been integrated with your “update_comments_in_fork”. As soon as I tidy up the tp_spi module, I can issue a pull request to that or maybe I can try to merge with another fork if you like (but that’ll take a bit longer as this week is busy for me). Also if you’re ok with it, I’ll include my changes to the Kconfig files for you to look at.

Same for me.

Great to know you got the touch working, I am not as familiar as i would like to the esp internals, so I’m sure you can get this working before me.

Sure, there’s no rush. I can check the Kconfig changes when you’re done with it.

Will you include the tft controller support until you finish the work on the tp_spi?

Regards

@Carlos_Diaz - I updated my repository with changes below. You can check them out.
Would you like me to issue a pull request against the master or lvgl_kconfig?

  1. My drivers now conform to the new way (using disp_driver & touch_driver).
  2. I modified tp_spi to use half-duplex operations and updated the XPT2046 driver (I tested it). I also fixed a small bug in that driver (scaling was 1-bit to short) and updated the my Kconfig with new scaling values that at least work with my generic HiLetGo ILI9341/TSC2046 2.8" LCD module.
  3. I added support for selecting SPI busses.
  4. Small modifications to main.c to push a little more to the drivers and support the SPI bus selection.
  5. Modified the Kconfig files to try to give a predefined board for the Adafruit TFT Featherwing (it should work identically with either the Adafruit or Sparkfun ESP32 featherwing). Also other support for the drivers. But I’m not sure this is right and would appreciate you looking at it.
  6. Small clean-up here and there.
  7. I realize as I’m typing this that I changed the display SPI frequency to 26 MHz from 40 MHz because the HX8357D doesn’t seem to be able to handle that. I think it’s reasonable since it’s still good performance for the smaller resolution displays and is friendlier for breadboard wiring. But if you want we can qualify that with a conditional and let the other two displays run at 40 MHz again.

Regards, Dan

@danjulio,

Thanks for your work and improvements on the main file, your pull request should go against the master branch. Right now I have ILI9341, ILI9488 and ST7789 tft controller based displays to do some tests tests, so i can check the point 7 on your list.

And sure, i can check the new Kconfig options.

Regards,
Carlos