Spark Logic

Hacking the GD32 based ‘Autool X50 OBD2 Monitor and diagnostic Display’

carl0s Wed Apr 11, 2018 5:27 pm

Hi!

I’m Carl

My first project with STM32 will hopefully be to get some code onto this GD32F103 board, and drive the LCD. I first need to figure out what the driver is. It appears to be using 17 pins.. Hopefully the ILI9341.

I will then use this as a screen / controller for my vehicle datalogger that I have already built on an Adafruit Feather M0.

Here’s the thing I want to hack..

Note that the mini-USB on the back here is actually for a vehicle OBD connection, and will be expecting +12v as well as K-Line, L-Line, CAN-Hi/CAN-Lo, etc.. It’s *not* a Mini-USB connection!

(in most web browsers, you can right-click on the images below and choose Open Image in New tab, to view at full resolution).

Image

Image

Image

Image

Image

Replies

carl0s Mon Apr 16, 2018 10:33 am

[ahull – Mon Apr 16, 2018 6:28 am] –
[carl0s – Sun Apr 15, 2018 11:40 pm] –
[RogerClark – Sun Apr 15, 2018 10:01 pm] –
Can’t you just use the SPI.setModule(2)

Then your libraries use SPI 2 even when they think they are using SPI 1

Tried that too! I’ll get back on it tomorrow with the scope to see if the spi is coming out the MCU.

I suspect, since you have that “static” pattern, that you are sending *some* commands to the display. They may be mangled, or they may not apply to that particular controller, so we do need to check the waveforms on the pins.

Hi. The problem is, that was using the ST7735 library. The ST7735 has a max resolution of 132 x 162, so, I presume it’s fairly hopeless to expect that to work with a 240 x 320 display / chip (the ST7789v that I have)? Or is it more likely that being from the same manufacturer it would be easier to tweak that library, than say, the ILI9341 library? As I posted before, somebody said the ILI9341 and ST7789 were compatible other than RGB order (but still works.. just wrong colours), but, I’m not sure if that is only when using 8080 parallel mode instead of SPI.

I tried the ILI9341_STM lib, with the SPIClass mySPI2 as above. I also tried Adafruit’s original ILI9341 latest from GitHub, which accepts additional TFT_CLK, TFT_MISO, and TFT_MOSI parameters. I had to tweak/force a typedef for RwReg that wasn’t being set in order to get this to compile, but still no dice.

My logic analyzer – a Saleae clone, says it’s 24MHz. Does this stand a chance of working, if I set the SPI frequency to 18Mhz? There’s that whole nyquist thing that I don’t know enough about.

Alternatively, my scope is one of those popular hacked Rigols. 100MHz 4 channel with SPI decode.

RogerClark Mon Apr 16, 2018 10:56 am

The main problem I had with the Gd32 was SPI not operating the same as the STM32, so I think you’d need to attach your logic analyser and carefully look at the signals, I suspect it needs some slightly different configuration bit patterns in its SPI control registers.

GigaDevices, in their wisdom, decided that any “reserved” bit in the registers could be used to add additional functionality, which is fine when writing code using their CMSIS etc, but when using code design for the STM32 can leave various “bits” in the registers with values which affect the operation of the peripheral.

Or it could be timing issues, as the GD32 can run with zero wait states in the flash.

ahull Mon Apr 16, 2018 11:05 am

Looking at the datasheets for the ILI9341 and the ST7789V they do appear to be very close in terms of their structure, and the format of the commands. They even use very similar wording in the datasheet, suggesting that one is a derivative of the other.

They also appear to support the same instructions, for example if you look at the “Read CABC Minimum Brightness (5Fh)” instruction in the ILI9341 datasheet, (Page 150) and compare with the same instruction on the ST7789 (page 244) the instruction description, wording and page layout are nearly identical, so I think we can be fairly sure that the two devices are extremely closely related. There may be a difference in the memory geometry which would account for the colour shifts, but I think the underlying design is nearly identical.

Since the interface is simply a method of getting data into the instruction processor, I suspect if we can send valid data to the device, we can expect it to respond in a manner that we can understand, regardless of how that data gets there (SPI, parallel, or whatever).

ahull Mon Apr 16, 2018 11:11 am

My logic analyzer – a Saleae clone, says it’s 24MHz. Does this stand a chance of working, if I set the SPI frequency to 18Mhz? There’s that whole nyquist thing that I don’t know enough about.

Yes, for a logic analysis, your 24MHz Saleae clone should be able to keep up with SPI at 18MHz.

If you use Sigrok you should be able to decode the SPI from your captures. I’m not sure if your scope can decode SPI, you would need to check its spec.

carl0s Mon Apr 16, 2018 11:13 am

[ahull – Mon Apr 16, 2018 11:05 am] –
Looking at the datasheets for the ILI9341 and the ST7789V they do appear to be very close in terms of their structure, and the format of the commands. They even use very similar wording in the datasheet, suggesting that one is a derivative of the other.

They also appear to support the same instructions, for example if you look at the “Read CABC Minimum Brightness (5Fh)” instruction in the ILI9341 datasheet, (Page 150) and compare with the same instruction on the ST7789 (page 244) the instruction description, wording and page layout are nearly identical, so I think we can be fairly sure that the two devices are extremely closely related. There may be a difference in the memory geometry which would account for the colour shifts, but I think the underlying design is nearly identical.

Since the interface is simply a method of getting data into the instruction processor, I suspect if we can send valid data to the device, we can expect it to respond in a manner that we can understand, regardless of how that data gets there (SPI, parallel, or whatever).

OK so maybe the issue is that ILI9341 library is not working on SPI2 with GD32, but the ST7735 library was (but totally incompatible due to different resolution). I will check SPI2 activity with the Scope later.

I was just about to push the button on a better ‘cheap’ logic analyzer. One with an FPGA & storage buffer (DSLogic Plus). Maybe I should calm down and wait though.. try the scope & crappy $5 24MHz logic analyzer that I already have.

carl0s Mon Apr 16, 2018 11:14 am

[ahull – Mon Apr 16, 2018 11:11 am] –
My logic analyzer – a Saleae clone, says it’s 24MHz. Does this stand a chance of working, if I set the SPI frequency to 18Mhz? There’s that whole nyquist thing that I don’t know enough about.

Yes, for a logic analysis, your 24MHz Saleae clone should be able to keep up with SPI at 18MHz.

If you use Sigrok you should be able to decode the SPI from your captures. I’m not sure if your scope can decode SPI, you would need to check its spec.

OK I’ll try it.

Yes my 100MHz scope does SPI. It has all options installed/enabled: https://www.rigol-uk.co.uk/Rigol-DS1104 … s1104z.htm

carl0s Mon Apr 16, 2018 11:24 am

[RogerClark – Mon Apr 16, 2018 10:56 am] –
The main problem I had with the Gd32 was SPI not operating the same as the STM32, so I think you’d need to attach your logic analyser and carefully look at the signals, I suspect it needs some slightly different configuration bit patterns in its SPI control registers.

GigaDevices, in their wisdom, decided that any “reserved” bit in the registers could be used to add additional functionality, which is fine when writing code using their CMSIS etc, but when using code design for the STM32 can leave various “bits” in the registers with values which affect the operation of the peripheral.

Or it could be timing issues, as the GD32 can run with zero wait states in the flash.

Hi Roger. From an old discussion of yours (2.5 years ago).. I’m not sure if this is relevant..
viewtopic.php?t=485&start=30


GD32 When using SPI, IO configuration must be strictly observed master from the input and output mode configuration,
STM32 is no such requirement, the relevant code is as follows:

Host mode IO configuration (host to SPI for example):
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
GPIO_Init (GPIOA, & GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init (GPIOA, & GPIO_InitStructure);

IO configured in slave mode (slave in SPI2 example):
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
GPIO_Init (GPIOB, & GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_Init (GPIOB, & GPIO_InitStructure);

3) In the GD32’s SPI clock signal, idle needs to be configured to a high level, to ensure the stability of data,
Specific code as follows: red font code
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

RogerClark Mon Apr 16, 2018 11:53 am

Ok.

Sounds like there are a number of potential reasons why the STM32 SPI code didn’t work.

I remember doing a loop back test and it worked ok, but it would not send data to an ILI9341 display

So the clock idle state could have been the problem as from what I recall the loop back data looked ok on my analyser

carl0s Mon Apr 16, 2018 11:54 am

[RogerClark – Mon Apr 16, 2018 11:53 am] –
Ok.

Sounds like there are a number of potential reasons why the STM32 SPI code didn’t work.

I remember doing a loop back test and it worked ok, but it would not send data to an ILI9341 display

So the clock idle state could have been the problem as from what I recall the loop back data looked ok on my analyser

Yes I read your discussion on that :)

Hopefully we can get there. I’ll try to have a play later. I’m in danger of upsetting the girlfriend by giving the computer too much attention.

carl0s Mon Apr 16, 2018 11:57 am

I wonder if the GD32 defaults to the high clock speed that they mention in the marketing/data? 108MHz ? That would mean I definitely need to alter clock dividers etc.

Also, I just noticed from the datasheet, that it says the SPI is maximum of 18MHz. I thought (wrongly?) that 36Mhz or even 50MHz was standard, at least for SPI1, on the STM32 ?

Although, I think did already try giving 18MHz frequency as tft.begin(mySPI2, 18000000);

I haven’t done anything with dividers though.

Ooops.. nevermind. it’s 18Mbps SPI, not 18MHz. Same as stm32

ahull Mon Apr 16, 2018 12:42 pm

I’m curious to know when the display changes from a blank backlit display to that “snowy” one.
Does …

tft.begin(mySPI2, 18000000);

carl0s Mon Apr 16, 2018 12:44 pm

I can find out later. Remember the snowy stuff was with the ST7735 code.. All I did was change pin assignments in the example code.

ahull Mon Apr 16, 2018 12:51 pm

The ST7735 code did appear to do something then. What if anything do you see with the ILI9341 lib?

carl0s Mon Apr 16, 2018 12:52 pm

[ahull – Mon Apr 16, 2018 12:51 pm] –
The ST7735 code did appear to do something then. What if anything do you see with the ILI9341 lib?

Nothing at all with the ILI9341 lib :-(

ahull Mon Apr 16, 2018 1:03 pm

[carl0s – Mon Apr 16, 2018 12:52 pm] –
[ahull – Mon Apr 16, 2018 12:51 pm] –
The ST7735 code did appear to do something then. What if anything do you see with the ILI9341 lib?

Nothing at all with the ILI9341 lib :-(

Compare the pinout with the pins in the ST7735 code, I would expect a response if everything else is the same.

At the bare minimum, sending
writedata(0x01);
writedata(0x29);

ahull Mon Apr 16, 2018 2:20 pm

The reset sequence from that lib is similar.

static const uint8_t PROGMEM
Bcmd[] = { // Initialization commands for 7735B screens
18, // 18 commands in list:
ST7735_SWRESET, DELAY, // 1: Software reset, no args, w/delay
50, // 50 ms delay
ST7735_SLPOUT , DELAY, // 2: Out of sleep mode, no args, w/delay
255, // 255 = 500 ms delay
ST7735_COLMOD , 1+DELAY, // 3: Set color mode, 1 arg + delay:
0x05, // 16-bit color
10, // 10 ms delay
ST7735_FRMCTR1, 3+DELAY, // 4: Frame rate control, 3 args + delay:
0x00, // fastest refresh
0x06, // 6 lines front porch
0x03, // 3 lines back porch
10, // 10 ms delay
ST7735_MADCTL , 1 , // 5: Memory access ctrl (directions), 1 arg:
0x08, // Row addr/col addr, bottom to top refresh
ST7735_DISSET5, 2 , // 6: Display settings #5, 2 args, no delay:
0x15, // 1 clk cycle nonoverlap, 2 cycle gate
// rise, 3 cycle osc equalize
0x02, // Fix on VTL
ST7735_INVCTR , 1 , // 7: Display inversion control, 1 arg:
0x0, // Line inversion
ST7735_PWCTR1 , 2+DELAY, // 8: Power control, 2 args + delay:
0x02, // GVDD = 4.7V
0x70, // 1.0uA
10, // 10 ms delay
ST7735_PWCTR2 , 1 , // 9: Power control, 1 arg, no delay:
0x05, // VGH = 14.7V, VGL = -7.35V
ST7735_PWCTR3 , 2 , // 10: Power control, 2 args, no delay:
0x01, // Opamp current small
0x02, // Boost frequency
ST7735_VMCTR1 , 2+DELAY, // 11: Power control, 2 args + delay:
0x3C, // VCOMH = 4V
0x38, // VCOML = -1.1V
10, // 10 ms delay
ST7735_PWCTR6 , 2 , // 12: Power control, 2 args, no delay:
0x11, 0x15,
ST7735_GMCTRP1,16 , // 13: Magical unicorn dust, 16 args, no delay:
0x09, 0x16, 0x09, 0x20, // (seriously though, not sure what
0x21, 0x1B, 0x13, 0x19, // these config values represent)
0x17, 0x15, 0x1E, 0x2B,
0x04, 0x05, 0x02, 0x0E,
ST7735_GMCTRN1,16+DELAY, // 14: Sparkles and rainbows, 16 args + delay:
0x0B, 0x14, 0x08, 0x1E, // (ditto)
0x22, 0x1D, 0x18, 0x1E,
0x1B, 0x1A, 0x24, 0x2B,
0x06, 0x06, 0x02, 0x0F,
10, // 10 ms delay
ST7735_CASET , 4 , // 15: Column addr set, 4 args, no delay:
0x00, 0x02, // XSTART = 2
0x00, 0x81, // XEND = 129
ST7735_RASET , 4 , // 16: Row addr set, 4 args, no delay:
0x00, 0x02, // XSTART = 1
0x00, 0x81, // XEND = 160
ST7735_NORON , DELAY, // 17: Normal display on, no args, w/delay
10, // 10 ms delay
ST7735_DISPON , DELAY, // 18: Main screen turn on, no args, w/delay
255 }, // 255 = 500 ms delay

Rcmd1[] = { // Init for 7735R, part 1 (red or green tab)
15, // 15 commands in list:
ST7735_SWRESET, DELAY, // 1: Software reset, 0 args, w/delay
150, // 150 ms delay
ST7735_SLPOUT , DELAY, // 2: Out of sleep mode, 0 args, w/delay
255, // 500 ms delay
ST7735_FRMCTR1, 3 , // 3: Frame rate ctrl - normal mode, 3 args:
0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D)
ST7735_FRMCTR2, 3 , // 4: Frame rate control - idle mode, 3 args:
0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D)
ST7735_FRMCTR3, 6 , // 5: Frame rate ctrl - partial mode, 6 args:
0x01, 0x2C, 0x2D, // Dot inversion mode
0x01, 0x2C, 0x2D, // Line inversion mode
ST7735_INVCTR , 1 , // 6: Display inversion ctrl, 1 arg, no delay:
0x07, // No inversion
ST7735_PWCTR1 , 3 , // 7: Power control, 3 args, no delay:
0xA2,
0x02, // -4.6V
0x84, // AUTO mode
ST7735_PWCTR2 , 1 , // 8: Power control, 1 arg, no delay:
0xC5, // VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
ST7735_PWCTR3 , 2 , // 9: Power control, 2 args, no delay:
0x0A, // Opamp current small
0x00, // Boost frequency
ST7735_PWCTR4 , 2 , // 10: Power control, 2 args, no delay:
0x8A, // BCLK/2, Opamp current small & Medium low
0x2A,
ST7735_PWCTR5 , 2 , // 11: Power control, 2 args, no delay:
0x8A, 0xEE,
ST7735_VMCTR1 , 1 , // 12: Power control, 1 arg, no delay:
0x0E,
ST7735_INVOFF , 0 , // 13: Don't invert display, no args, no delay
ST7735_MADCTL , 1 , // 14: Memory access control (directions), 1 arg:
0xC8, // row addr/col addr, bottom to top refresh
ST7735_COLMOD , 1 , // 15: set color mode, 1 arg, no delay:
0x05 }, // 16-bit color

Rcmd2green[] = { // Init for 7735R, part 2 (green tab only)
2, // 2 commands in list:
ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay:
0x00, 0x02, // XSTART = 0
0x00, 0x7F+0x02, // XEND = 127
ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay:
0x00, 0x01, // XSTART = 0
0x00, 0x9F+0x01 }, // XEND = 159

Rcmd2red[] = { // Init for 7735R, part 2 (red tab only)
2, // 2 commands in list:
ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x7F, // XEND = 127
ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x9F }, // XEND = 159

Rcmd2green144[] = { // Init for 7735R, part 2 (green 1.44 tab)
2, // 2 commands in list:
ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x7F, // XEND = 127
ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x7F }, // XEND = 127

Rcmd2green160x80[] = { // Init for 7735R, part 2 (mini 160x80)
2, // 2 commands in list:
ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x7F, // XEND = 79
ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x9F }, // XEND = 159

Rcmd3[] = { // Init for 7735R, part 3 (red or green tab)
4, // 4 commands in list:
ST7735_GMCTRP1, 16 , // 1: Magical unicorn dust, 16 args, no delay:
0x02, 0x1c, 0x07, 0x12,
0x37, 0x32, 0x29, 0x2d,
0x29, 0x25, 0x2B, 0x39,
0x00, 0x01, 0x03, 0x10,
ST7735_GMCTRN1, 16 , // 2: Sparkles and rainbows, 16 args, no delay:
0x03, 0x1d, 0x07, 0x06,
0x2E, 0x2C, 0x29, 0x2D,
0x2E, 0x2E, 0x37, 0x3F,
0x00, 0x00, 0x02, 0x10,
ST7735_NORON , DELAY, // 3: Normal display on, no args, w/delay
10, // 10 ms delay
ST7735_DISPON , DELAY, // 4: Main screen turn on, no args w/delay
100 }; // 100 ms delay

carl0s Mon Apr 16, 2018 6:40 pm

On the breadboard, ready to go.. ha

Image

Sign in to reply