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 Tue Apr 17, 2018 12:55 am

[RogerClark – Tue Apr 17, 2018 12:50 am] –
Ah OK

I thought it was the GD32F103C8 which only has 64k flash (and it only has 64k shadow / program RAM)

Apparently not! :)

I just fixed the BGR / RGB colours now, so I’m happy. I might go to bed finally :-)

I changed MADCTL_BGR to MADCTL_RGB in Adafruit_ILI9341_STM::setRotation(uint8_t m)

carl0s Tue Apr 17, 2018 1:02 am

[RogerClark – Tue Apr 17, 2018 12:53 am] –
See

https://github.com/rogerclarkmelbourne/ … 9e1aa8c15a

Change that to zero wait states, as only the STM32 need wait states

Done :)

How will I know if it’s doing anything? The screen is spinning faster than I can see anyway, and I guess I’m limited by my 32MHz SPI clock for this?

RogerClark Tue Apr 17, 2018 1:24 am

SPI clock won’t change

Programs just run a bit faster i.e raw computation speed increases

ahull Tue Apr 17, 2018 3:24 am

:D That only leaves the CAN/ODB hardware to hack and we have full control. This has been slightly easier than I expected. I’m impressed.

carl0s Tue Apr 17, 2018 10:40 am

[ahull – Tue Apr 17, 2018 3:24 am] –
:D That only leaves the CAN/ODB hardware to hack and we have full control. This has been slightly easier than I expected. I’m impressed.

:D

I will trace out the CAN transceiver, and LM393 pins soon.

Given that PA11 and PA12 are labelled as CAN TX/RX on Maple, *but*, PA11 is used for LCD D/C on this board, I expect the CAN tranceiver will instead be wired to PD0 and PD1, as the datasheet says these are remap-able as such.

The LM393 will be going into a UART, for K/L Line serial-like data (iso 9141) which is good, because if I want a UART connection of some kind, I can change out that IC, or hookup in its place.

It doesn’t look like connecting to unused pins on the GD32 is going to be possible because the pitch is so fine on the LQFP64, so I must re-use what’s already broken out into other functions.

I suppose it would be good to have a look at the 2MB flash, check that I can read/write from it. Maybe get a bitmap on there and display it as a startup picture on the LCD.

ahull Tue Apr 17, 2018 2:38 pm

Funnily enough I was going to remind you we hadn’t dumped the 2Mb Flash chip.

There is a possibility that they have doubled up on pin PA11, since the display will ignore everything until it is selected, and they may be enabling the CAn transceiver only when it is needed, but your idea that they are using PD0 and PD1 sounds more likely. Which pins does the 2Mb flash use?

carl0s Tue Apr 17, 2018 8:13 pm

[ahull – Tue Apr 17, 2018 2:38 pm] –
Funnily enough I was going to remind you we hadn’t dumped the 2Mb Flash chip.

There is a possibility that they have doubled up on pin PA11, since the display will ignore everything until it is selected, and they may be enabling the CAn transceiver only when it is needed, but your idea that they are using PD0 and PD1 sounds more likely. Which pins does the 2Mb flash use?

I’m not sure yet. I suppose it’s going to be i2c or SPI is it? It’s been a while since I had to read an eeprom chip. As I mentioned earlier, my SOFI SP8a failed to read it in-circuit. I do have a black magic probe on its way though, and I believe the other set of pin-headers on this PCB do go directly to that chip, so if I figure out what’s going on (something being held low or high or whatever), then I should be able to read it through those header pins, as I expect this is how it’s programmed at the factory. J2 header pins for SWD-debug to program the MCU, and J1 header pins to program the 2Mb (is it 2mbit or 2mbyte. I think it’s 2MB.. it says 25c16 or something, 16megabit).

I also realised I know nothing about using external flash with the Arduino. Clearly there’s no filesystem i.e. fat or anything. I guess you just store variables at address locations manually and read them back from there, and it’s mapped to the external flash. I’ll find some demo code to try out anyway.

I’ve not done the 3-way jog-button thing yet. That’s key, but easy !

I do have one big worry though. You know all along my plan is to use the other model of this thing – the Autool X60, which is in a gauge style rather than a pod style. Well, I am sure it is going to be very much the same inside, but I won’t know until it arrives from China as there were no UK sellers for it, but look.. that screen is clearly 1:1 square and not rectangle or 4:3. I’m worried that after all this effort to get the ST7789 LCD working, well, it will have a different TFT panel and driver chip after all :-/

See for yourself..

Image

Image

Also, this is obviously a brand new piece of kit, because the only YouTube video I could find for it, is from yesterday, and is in Russian:

ahull Wed Apr 18, 2018 10:43 am

25c16 sounds more like a 16kbit eeprom https://www.bucek.name/pdf/24c16.pdf

Here is a sketch that should read it and dump it to the serial port. See this post if you want to know *why* I have been recently dumping 24C16 eeproms. -> http://stm32duino.com/viewtopic.php?f=45&t=3322

I suspect it will work without any modification other than to set up the correct serial port (it uses USB serial by default) and the correct pins for the eeprom.

// --------------------------------------
// Modified i2c_scanner to find, dump and update a SOR/T SOR/R Dosimeter 24C16 EEPROM (and probably related devices).
// to hack in missing features.
//
// See http://stm32duino.com/viewtopic.php?f=45&t=3322
// for more about hacking these devices
// Latest code should be checked out with git sith something on the lones of...
// git clone https://github.com/pingumacpenguin/SOR-T-SOR-R-Dosimeter-24C16-EEROM-dumper-and-updater..git
//
// The i2c scanner code came with the following comments.
// Version 1
// This program (or code that looks like it)
// can be found in many places.
// For example on the Arduino.cc forum.
// The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
// Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26 2013
// V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
// by Arduino.cc user Krodal.
// Changes by louarnold removed.
// Scanning addresses changed from 0...127 to 1...119,
// according to the i2c scanner by Nick Gammon
// http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
// As version 4, but address scans now to 127.
// A sensor seems to use address 120.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address will not be seen properly.
//
// Additional i2c hints from http://playground.arduino.cc/Code/I2CEEPROM
//

// This code was written for and teseted on and STM32F103C8T6 - the so called BluePill - see http://wiki.stm32duino.com/index.php?title=Blue_Pill
// but should work pretty much unmodified on most 'duinos.

// Thanks to the many coding giants, who's shoulders this sketch stands upon.
//

// The hexdump of the 24c16 will appear as a set of C++ byte Arrayson the STM32 USB serial device, or UART1, depending on the settings in the IDE.
// See http://stm32duino.com for details of how the serial ports on the STM32F103XX devices are defined.

// For connection to the EEPROM, you should be able to use a SOC8 clamp to connect without the inconvenience of soldering to the board.
// WARNING: Do not leave the battery in the dosimeter and accidentally power it from the STLINK V2 or the USB port at the same time, the battery will pop.
// Search Ebay for "SOIC8 SOP8 Flash Chip IC Test Clips Socket Adpter BIOS" or similar.

// Include RTC for timestamps
#include "RTClock.h"
RTClock rt (RTCSEL_LSE); // initialise
uint32 tt;

// Define the Base address of the RTC registers (battery backed up CMOS Ram), so we can use them for config of touch screen and other calibration.
// See http://stm32duino.com/viewtopic.php?f=15&t=132&hilit=rtc&start=40 for a more details about the RTC NVRam
// 10x 16 bit registers are available on the STM32F103CXXX more on the higher density device.

#define BKP_REG_BASE (uint32_t *)(0x40006C00 +0x04)

// Time library - https://github.com/PaulStoffregen/Time
#include "Time.h"
#define TZ "BST"
#include <Wire.h>

// Somne sane ish defaults in case the RTC battery has been disconnected or run flat.
int thisYear = 2018;
int thisMonth = 3;
int thisDay = 28;
int lastDay = 0;
int thisHour = 12;
int thisMinute = 0;
int thisSecond = 0;

// Set to a recent value - Wed March 28 1028 22:43
#define RESET_TO_TIMESTAMP 1522273406

#define BLINK_PIN PC13 // Unused.. Can be used to assist with debugging.

#define BOARD_POWER PB9 // This can theoretically be used to power the 24c64 since the board draws a few miliamps.
// In the end, I just opted to power the board from 3v3 directly, as this makes life easier.

#define BOARD_WP PB8 // Pull down WP pin to allow us to write to the 24c64

void setup()
{

// Check time, and set a sensible time, if this board has no battery, or the time is unset
long int tt = rt.getTime();
// Check to see if we are close to the epoch, and if so, bad things must have happened to the RTC backup power domain.
if ( tt < RESET_TO_TIMESTAMP )
{
rt.setTime(RESET_TO_TIMESTAMP);
}

// Allow the USB to re-enumerate before we attempt to talk. You can probably shorten this delay considerably.
delay(15000);

// Using the BluePill, or other STM32F103XX boards, PB6 is SCL => Pin 6 on the 24C02
// PB7 is SDA => Pin 5 on the 24C02

// PB8 is GPOI used to pull WP (Write Protect) (Pin7) low on the 24C02 to allow writing to the chip.
// There is a pullup on WP on the Victor VC921 and probably most other devices, so we need to pull low to write.

//pinMode(PB6,OUTPUT_OPEN_DRAIN);
//pinMode(PB7,INPUT);

// Power up the multimeter if connected to the BOARD_POWER
//pinMode(BOARD_POWER, OUTPUT);
//digitalWrite(BOARD_POWER, HIGH);

//Enable writing to the eerom
//pinMode(BOARD_WP, OUTPUT);
//digitalWrite(BOARD_WP, LOW);

Serial.println("// SOR/T SOR/R Dosimeter 24C16 EEROM dumper and updater.");
//TwoWire Wire(PB6, PB7, SOFT_STANDARD);
Wire.begin();
Serial.println("// Waiting for Device to POST and i2c Bus to settle.");
delay(3000);
}

void loop()
{
byte error, address;
int nDevices;
serialCurrentTime();
Serial.println("//Scanning...");

nDevices = 0;
for (address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();

if (error == 0)
{
Serial.print("\n");
serialCurrentTime();
Serial.print("\n// I2C device found at address 0x");
if (address < 16) {
Serial.print("0");
}
Serial.print(address, HEX);
Serial.println(" ");

// Dump the current rom values, so we have somthing to fall back on if it all goes pear shaped.
// NOTE: The 24c16 also contains calibration values, so should be unique to the dosimeter, simply pasting the hexdump from
// one dosimeter to another will almost certainly screw up the calibration.

dump24c02(address);

// delay(1000);
nDevices++;
}
else if (error == 4)
{
Serial.print("//Unknow error at address 0x");
if (address < 16)
Serial.print("0");
Serial.println(address, HEX);
}
}
if (nDevices == 0)
Serial.println("//No I2C devices found\n");
else

Serial.println("\n//Done.\n");

// Put any changes to bytes immediately after the dump, since that will ensure they hit the found i2c device.

delay(60000); // Wait n seconds then re-scan.
}

void dump24c02(byte i2cAddress)
{
int hexDumpWidth = 0x10;
int addrPointer = 0;
//int romLength = 0xff; // 24c02 - 256x8 bits (256 bytes)
int romLength = 0xff; // 24c04 - 512x8 bits (512 bytes)
byte b = 0;

// Spit out each 256 byte page of the eeprom contents as a byte array
Serial.print("static const byte eeprom");
Serial.print(i2cAddress, HEX);
Serial.println("[][0x10] =");
Serial.println("{");

while (addrPointer <= romLength)
{

if ((addrPointer % hexDumpWidth) == 0 ) {

if (addrPointer == 0) {
Serial.print(" {");
} else {
Serial.print("} //0x0");
Serial.println(addrPointer, HEX);
Serial.print(",{");
}
} else {
Serial.print(",");

}

b = i2c_eeprom_read_byte(i2cAddress, addrPointer); // Read byte
addrPointer++; // increment address pointer
Serial.print("0x");
if (b < 0x10) {
Serial.print("0");
}

Serial.print(b, HEX); // Print byte
//Serial.print(",");
}
Serial.print("} //End of page 0x");

// Serial.print("// ");
Serial.print((i2cAddress - 0x50), HEX);
Serial.println();

if (!(addrPointer % hexDumpWidth)) {
Serial.println("};");

} else {
Serial.println("");
}

}

byte i2c_eeprom_read_byte( int deviceaddress, int eeaddress ) {

//Wire.beginTransmission(deviceaddress & ((eeaddress & (int)0x100 ) >> 9));
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress & 0xff));
// Wire.write(address & 0xFF);
//Wire.write((int)(eeaddress >> 8)); // MSB
//Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(deviceaddress, 1);

if (Wire.available()) {
return Wire.read();
} else {
return 0xff;
}

}

void i2c_eeprom_write_byte( int deviceaddress, int eeaddress, byte data ) {
digitalWrite(BOARD_WP, LOW);
delay(100);
int rdata = data;
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress)); //
Wire.write(rdata);
Wire.endTransmission();
//digitalWrite(BOARD_WP, HIGH);
}

void serialCurrentTime() {
long int tt = rt.getTime();
Serial.print("// Current time - ");
if (hour(tt) < 10) {
Serial.print("0");
}
Serial.print(hour(tt));
Serial.print(":");
if (minute(tt) < 10) {
Serial.print("0");
}
Serial.print(minute(tt));
Serial.print(":");
if (second(tt) < 10) {
Serial.print("0");
}
Serial.print(second(tt));
Serial.print(" ");
Serial.print(day(tt));
Serial.print("/");
Serial.print(month(tt));
Serial.print("/");
Serial.print(year(tt));
Serial.println("("TZ")");

}

carl0s Wed Apr 18, 2018 10:47 am

Thanks Andy!

Well, the thing is, a blog post elsewhere on the Internet showed the v4.3 of this PCB with everything identical except the flash part being a Spansion S25FL216KIF which is 16MBit.
However my board (v4.4) has a part labelled C25Q16SN (or it might be C25016SN). I can’t find info on that p/n.

carl0s Wed Apr 18, 2018 10:55 am

Here’s the chip:

Image

carl0s Wed Apr 18, 2018 11:02 am

You can see the picture from that other blog here.

As you can see, my part is physically smaller, but is soldered to the same pads (hence the large silver pcb tracks showing next to the IC legs), and also the white line shows that a wider chip was originally supposed to be fitted there, like in the other person’s photo.

My part:
Image

Image

Other person’s part:
Image

You would think that the parts are pin-compatible.. maybe. Unless they use different software settings. Mine is more like the size of an i2c eeprom or something isn’t it. Whereas the other Spansion part looks wide like flash memory.

ahull Wed Apr 18, 2018 12:15 pm

[carl0s – Wed Apr 18, 2018 11:45 am] –
[ahull – Wed Apr 18, 2018 11:24 am] –
Looks like this beast here.-> https://www.qdatasheet.com/pdf/Spansion/185048.pdf

I wonder if my physically smaller part is compatible though?

Yes, I suspect it is.

The device comes in two different packages, if you look at the end of the datasheet you will see it is available as both …

8-Pin SOIC 150-mil Package (SOA 008) ( approx 6mm between opposite pads)

and

8-Pin SOIC 208-mil Package (SOC 008) (approx 8mm between opposite pads)

Exact dimensions are in the datasheet.
The problem is that your clip on adapter might have trouble grasping the smaller part. You should still be able to read the data directly with the GD32 obviously.

carl0s Thu Apr 19, 2018 11:07 am

[ahull – Wed Apr 18, 2018 12:15 pm] –
[carl0s – Wed Apr 18, 2018 11:45 am] –
[ahull – Wed Apr 18, 2018 11:24 am] –
Looks like this beast here.-> https://www.qdatasheet.com/pdf/Spansion/185048.pdf

I wonder if my physically smaller part is compatible though?

Yes, I suspect it is.

The device comes in two different packages, if you look at the end of the datasheet you will see it is available as both …

8-Pin SOIC 150-mil Package (SOA 008) ( approx 6mm between opposite pads)

and

8-Pin SOIC 208-mil Package (SOC 008) (approx 8mm between opposite pads)

Exact dimensions are in the datasheet.
The problem is that your clip on adapter might have trouble grasping the smaller part. You should still be able to read the data directly with the GD32 obviously.

Thanks Andy. I should be able to have a look at this tonight!

carl0s Thu Apr 19, 2018 9:13 pm

[carl0s – Thu Apr 19, 2018 11:07 am] –
[ahull – Wed Apr 18, 2018 12:15 pm] –
[carl0s – Wed Apr 18, 2018 11:45 am] –

I wonder if my physically smaller part is compatible though?

Yes, I suspect it is.

The device comes in two different packages, if you look at the end of the datasheet you will see it is available as both …

8-Pin SOIC 150-mil Package (SOA 008) ( approx 6mm between opposite pads)

and

8-Pin SOIC 208-mil Package (SOC 008) (approx 8mm between opposite pads)

Exact dimensions are in the datasheet.
The problem is that your clip on adapter might have trouble grasping the smaller part. You should still be able to read the data directly with the GD32 obviously.

Thanks Andy. I should be able to have a look at this tonight!

Just trying again with my SP8a to read the SPI flash. You’re right that the clamp thing is no good, but (according to the foreign blog post), the SPI pins are broken out onto J1 of the PCB.

carl0s Thu Apr 19, 2018 9:43 pm

Oooh this is interesting.

J1 header on the PCB doesn’t go to the flash at all.

J1 is a 4 pin header (well, it is after you solder headers in there..)

Pin1 = GND
Pin2 = Nothing (it would go to collector of missing transistor Q5. I’m going to trace out where the B/E might lead to if one was fitted.)
Pin3 = PB10
Pin4 = PB11

This means PB10 and PB11 are broken out onto header J1!
These are I2C-2 clock and data, or USART3 TX and RX. They can be remapped to TM2 CH3 and CH4.

So it means we have a UART available for use right away on the board without having to remove the K/L line transceiver chip (LM393) or try to solder wires to MCU legs or anything. That’s great news.

Regarding the SPI flash:
Pin 1 (CS) goes to PB0
Pin 2 (MISO) goes to PA6
Pin 3 (WP) shows as going to VDD so is high. Not sure of the implications of this without reading the datasheet properly. Have only looked at pinouts so far.
Pin 4 is GND
Pin 5 (MOSI) goes to PA7
Pin 6 (SCLK) goes to PA5
Pin 7 (HOLD) goes to VDD. Again not sure what this does.
Pin 8 is VCC.

So it is connected to SPI1 as per the GD32 datasheet. Should be all good!

I think my next move will be to connect to UART3 and get something on my terminal, maybe display stuff on the LCD that I type.

carl0s Thu Apr 19, 2018 10:06 pm

Pin outs for the headers, looking from the top of the board where the LCD FFC socket is, with the buzzer at the bottom right.

J2
1 (left) – SWDIO
2 – SWDCLK
3 – GND
4 (right)- VDD

Board needs external power to use STLink though. VDD should just be connected to ‘target vcc detection’ pin of STLink (pin #1)

J1
1 (top) – GND
2 – nothing
3 – PB10
4 (bottom) – PB11

With the board still in the same orientation, 3 way switch / jog thingy pinouts:

Rotate Left: PC14
Push Middle: PC15
Rotate Right: PC13

carl0s Fri Apr 20, 2018 12:09 am

Serial3 just works. No changes anywhere. Yay.

Sign in to reply