Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LYWSD002MMC - TLSR8250 based! #5

Closed
danergo opened this issue Oct 7, 2024 · 38 comments
Closed

LYWSD002MMC - TLSR8250 based! #5

danergo opened this issue Oct 7, 2024 · 38 comments

Comments

@danergo
Copy link

danergo commented Oct 7, 2024

Hi.

I found many articles only about the LYWSD002MMC. It was based on DA14585 from Dialog (Renesas).

But now I opened mine and it is now a new version (seems like), and this is based on the TLSR8250.

I wish to create a new firmware which prints the temperature onto the large display segments.

But I'm a little bit stucked: pins available are:

  • GND
  • VCC
  • RESET
  • SWS
  • RX
  • TX

Is it possible to flash this device via these pins? If so - what programmer is needed? (J-Segger?)

By any chance can I do OTA?

Any help would be much appreciated.

@pvvx
Copy link
Owner

pvvx commented Oct 8, 2024

Minimal programmer (Telink Swire emulator via USB-COM port)
https://github.com/pvvx/TlsrComSwireWriter -> https://github.com/pvvx/TlsrComSwireWriter/blob/master/TLSR825xComFlasher.py

A programmer using a bootloader loaded via the Telink Swire interface, then running via UART
https://github.com/pvvx/TlsrComProg825x

Normal programmer using Telink Swire hardware interface
https://github.com/pvvx/TLSRPGM

First you need to read the entire Flash (512 kilobytes) and save it for recovery.

It is impossible to block programming (reading - writing) of the chip. If the programmer is working properly - then you can always restore the program. This chip does not have protection against reading and writing firmware.

@danergo
Copy link
Author

danergo commented Oct 8, 2024

Thanks.

Minimal programmer (Telink Swire emulator via USB-COM port) https://github.com/pvvx/TlsrComSwireWriter -> https://github.com/pvvx/TlsrComSwireWriter/blob/master/TLSR825xComFlasher.py

This is using only SWS and RESET pins on the board, and I need to connect those by your drawing, I assume, please correct me if I'm wrong.
By default, these chips are open to receive (and send) firmware via Swire protocol?

One more thing: I need to send BLE Ads, and official Telink SDK doesn't seem to know this chip: https://wiki.telink-semi.cn/wiki/chip-series/TLSR825x-Series/

Do you have any idea where can we access the SDK for this TLSR8250?

@pvvx
Copy link
Owner

pvvx commented Oct 8, 2024

All Chips TLSR8250, 8251, 8253, 8258 have the same crystal and volume RAM = 64 kilobytes, and a built -in Flash crystal from 512 kilobytes. And only one of several versions of TLSR8258 one megabyte Flash.
The difference between the TLSR825X chips lies in the chip body and what pins are made from the crystal. There is no more difference.

Use TLSR8258 settings with 512 KB Flash.

@danergo
Copy link
Author

danergo commented Oct 12, 2024

What is the correct reading command? The chip involved is TLSR8250F512ET32. It has internal 512K memory.

Command

./TLSR825xComFlasher.py -d -p /dev/ttyUSB0 rf 0 524288 default.flash
=======================================================
TLSR825x Flasher version 00.00.05
-------------------------------------------------------
Open /dev/ttyUSB0, 921600 baud...
Debug: default swdiv for 24 MHz = 52 (0x34)
Debug (read data):
000023: Debug (read data):
000024: Debug (read data):
000025: Debug (read data):
000026: Debug (read data):
000027: Debug (read data):
000028: Debug (read data):
000029: Debug (read data):
00002a: Debug (read data):
00002b: Debug (read data):
00002c: Debug (read data):
00002d: Debug (read data):
00002e: Debug (read data):
00002f: Debug (read data):
000030: Debug (read data):
000031: Debug (read data):
000032: Debug (read data):
000033: Debug (read data):
000034: Debug (read data):
000035: Debug (read data):
000036: Debug (read data):
000037: Debug (read data):
000038: Debug (read data):
000039: Debug (read data):
00003a: Debug (read data):
00003b: Debug (read data):
00003c: Debug (read data):
00003d: Debug (read data):
00003e: Debug (read data):
00003f: Debug (read data):
000040: Debug (read data):
000041: Debug (read data):
000042: Debug (read data):
000043: Debug (read data):
000044: Debug (read data):
000045: Debug (read data):
000046: Debug (read data):
000047: Debug (read data):
000048: Debug (read data):
000049: Debug (read data):
00004a: Debug (read data):
00004b: Debug (read data):
00004c: Debug (read data):
00004d: Debug (read data):
00004e: Debug (read data):
00004f: Debug (read data):
000050: Debug (read data):
000051: Debug (read data):
000052: Debug (read data):
000053: Debug (read data):
000054: Debug (read data):
000055: Debug (read data):
000056: Debug (read data):
000057: Debug (read data):
000058: Debug (read data):
000059: Debug (read data):
00005a: Debug (read data):
00005b: Debug (read data):
00005c: Debug (read data):
00005d: Debug (read data):
00005e: Debug (read data):
00005f: Debug (read data):
000060: Debug (read data):
000061: Debug (read data):
000062: Debug (read data):
000063: Debug (read data):
000064: Debug (read data):
000065: Debug (read data):
000066: Debug (read data):
000067: Debug (read data):
000068: Chip sleep? -> Use reset chip (RTS-RST): see option --tact

Chip pinout

Screenshot from 2024-10-12 18-04-48

Wiring

USB-Serial TLSR8250
GND GND
VCC (3.3V) VCC
RX Pin#5 (SWS)
RTS Pin#25 (RESETB)

What am I doing wrong?

@pvvx
Copy link
Owner

pvvx commented Oct 12, 2024

@danergo
Copy link
Author

danergo commented Oct 13, 2024

Okay, I added a 1K resistor and attached everything as your wiring (and VCC and GND):

$ ./TLSR825xComFlasher.py -d -p /dev/ttyUSB0 rf 0 524288 default.flash
=======================================================
TLSR825x Flasher version 00.00.05
-------------------------------------------------------
Open /dev/ttyUSB0, 921600 baud...
Debug: default swdiv for 24 MHz = 52 (0x34)
Debug (read data):
000023: fe 
Debug (read data):
000024: fe 
Debug (read data):
000025: fe 
Debug (read data):
000026: fe 
Debug (read data):
000027: fe 
Debug (read data):
000028: fe 
Debug (read data):
000029: fe 
Debug (read data):
00002a: fe 
Debug (read data):
00002b: fe 
Debug (read data):
00002c: fe 
Debug (read data):
00002d: fe 
Debug (read data):
00002e: fe 
Debug (read data):
00002f: fe 
Debug (read data):
000030: fe 
Debug (read data):
000031: fe 
Debug (read data):
000032: fe 
Debug (read data):
000033: fe 
Debug (read data):
000034: fe 
Debug (read data):
000035: fe 
Debug (read data):
000036: fe 
Debug (read data):
000037: fe 
Debug (read data):
000038: fe 
Debug (read data):
000039: fe 
Debug (read data):
00003a: fe 
Debug (read data):
00003b: fe 
Debug (read data):
00003c: fe 
Debug (read data):
00003d: fe 
Debug (read data):
00003e: fe 
Debug (read data):
00003f: fe 
Debug (read data):
000040: fe 
Debug (read data):
000041: fe 
Debug (read data):
000042: fe 
Debug (read data):
000043: fe 
Debug (read data):
000044: fe 
Debug (read data):
000045: fe 
Debug (read data):
000046: fe 
Debug (read data):
000047: fe 
Debug (read data):
000048: fe 
Debug (read data):
000049: fe 
Debug (read data):
00004a: fe 
Debug (read data):
00004b: fe 
Debug (read data):
00004c: fe 
Debug (read data):
00004d: fe 
Debug (read data):
00004e: fe 
Debug (read data):
00004f: fe 
Debug (read data):
000050: fe 
Debug (read data):
000051: fe 
Debug (read data):
000052: fe 
Debug (read data):
000053: fe 
Debug (read data):
000054: fe 
Debug (read data):
000055: fe 
Debug (read data):
000056: fe 
Debug (read data):
000057: fe 
Debug (read data):
000058: fe 
Debug (read data):
000059: fe 
Debug (read data):
00005a: fe 
Debug (read data):
00005b: fe 
Debug (read data):
00005c: fe 
Debug (read data):
00005d: fe 
Debug (read data):
00005e: fe 
Debug (read data):
00005f: fe 
Debug (read data):
000060: fe 
Debug (read data):
000061: fe 
Debug (read data):
000062: fe 
Debug (read data):
000063: fe 
Debug (read data):
000064: fe 
Debug (read data):
000065: fe 
Debug (read data):
000066: fe 
Debug (read data):
000067: fe 
Debug (read data):
000068: fe 
Chip sleep? -> Use reset chip (RTS-RST): see option --tact

@danergo
Copy link
Author

danergo commented Oct 13, 2024

Another test with "-t 2000":

$ ./TLSR825xComFlasher.py -d -t 2000 -p /dev/ttyUSB0 rf 0 524288 default.flash
=======================================================
TLSR825x Flasher version 00.00.05
-------------------------------------------------------
Open /dev/ttyUSB0, 921600 baud...
Reset module (RTS low)...
Activate (2000 ms)...
Debug: default swdiv for 24 MHz = 52 (0x34)
Debug (read data):
000023: fe fe fe 80 fe fe fe 80 80 
Debug (read data):
000024: 80 fe fe fe 80 80 80 80 80 
Debug (read data):
000025: fe 80 80 80 80 80 80 80 80 
Debug (read data):
000026: 80 80 80 80 80 80 fe 80 fe 
Debug (check data):
0ccc26: 80 fe fe 80 fe fe 80 80 fe fe 
bit mask: 0xc0
Debug (read data):
000027: 80 80 80 fe 80 fe 80 fe 80 
Debug (read data):
000028: fe 80 fe 80 fe 80 80 fe 80 
Debug (read data):
000029: 80 fe 80 80 fe 80 fe fe fe 
Debug (check data):
0ccc29: 80 fe fe 80 fe 80 fe fe 80 fe 
bit mask: 0xc0
Debug (read data):
00002a: 80 fe 80 fe fe fe fe fe fe 
Debug (check data):
0ccc2a: 80 fe fe 80 fe 80 fe 80 fe fe 
bit mask: 0xc0
Debug (read data):
00002b: fe fe fe fe fe fe fe fe fe 
Debug (check data):
0ccc2b: 80 fe fe 80 fe 80 fe 80 80 fe 
bit mask: 0xc0
Debug (read data):
00002c: fe fe fe fe fe fe fe fe fe 
Debug (check data):
0ccc2c: 80 fe fe 80 fe 80 80 fe fe fe 
bit mask: 0xc0
Debug (read data):
00002d: fe fe fe fe fe fe fe fe fe 
Debug (check data):
0ccc2d: 80 fe fe 80 fe 80 80 fe 80 fe 
bit mask: 0xc0
Debug (read data):
00002e: fe fe fe fe fe fe fe fe fe 
Debug (check data):
0ccc2e: 80 fe fe 80 fe 80 80 80 fe fe 
bit mask: 0xc0
Debug (read data):
00002f: fe fe fe fe fe fe fe fe fe 
Debug (check data):
0ccc2f: 80 fe fe 80 fe 80 80 80 80 fe 
bit mask: 0xc0
Debug (read data):
000030: fe 80 80 fe fe 80 fe fe fe 
Debug (check data):
0ccc30: 80 fe fe 80 80 fe fe fe fe fe 
bit mask: 0xc0
Debug (read data):
000031: 80 fe fe 80 fe fe fe 80 fe 
Debug (check data):
0ccc31: 80 fe fe 80 80 fe fe fe 80 fe 
bit mask: 0xc0
Debug (read data):
000032: fe 80 fe fe fe 80 fe fe fe 
Debug (check data):
0ccc32: 80 fe fe 80 80 fe fe 80 fe fe 
bit mask: 0xc0
Debug (read data):
000033: fe fe fe 80 fe fe fe fe fe 
Debug (check data):
0ccc33: 80 fe fe 80 80 fe fe 80 80 fe 
bit mask: 0xc0
Debug (read data):
000034: fe 80 fe fe fe fe fe fe fe 
Debug (check data):
0ccc34: 80 fe fe 80 80 fe 80 fe fe fe 
bit mask: 0xc0
Debug (read data):
000035: 80 fe fe fe fe fe fe fe fe 
Debug (check data):
0ccc35: 80 fe fe 80 80 fe 80 fe 80 fe 
bit mask: 0xc0
Debug (read data):
000036: fe fe fe fe fe fe fe fe e6 
Debug (read data):
000037: fe fe fe fe fe fe fe fe e6 
Debug (read data):
000038: fe fe fe fe fe fe fe fe e6 
Debug (read data):
000039: fe fe fe fe fe fe fe fe e6 
Debug (read data):
00003a: fe fe fe fe fe fe fe fe e6 
Debug (read data):
00003b: fe fe fe fe fe fe fe fe e6 
Debug (read data):
00003c: fe fe fe fe fe fe fe fe e6 
Debug (read data):
00003d: fe fe fe fe fe fe fe fe e6 
Debug (read data):
00003e: fe fe fe fe fe fe fe fe e6 
Debug (read data):
00003f: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000040: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000041: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000042: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000043: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000044: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000045: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000046: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000047: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000048: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000049: fe fe fe fe fe fe fe fe c6 
Debug (read data):
00004a: fe fe fe fe fe fe fe fe c6 
Debug (read data):
00004b: fe fe fe fe fe fe fe fe c6 
Debug (read data):
00004c: fe fe fe fe fe fe fe fe c6 
Debug (read data):
00004d: fe fe fe fe fe fe fe fe c6 
Debug (read data):
00004e: fe fe fe fe fe fe fe fe c6 
Debug (read data):
00004f: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000050: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000051: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000052: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000053: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000054: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000055: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000056: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000057: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000058: fe fe fe fe fe fe fe fe c6 
Debug (read data):
000059: fe fe fe fe fe fe fe fe c6 
Debug (read data):
00005a: fe fe fe fe fe fe fe fe c6 
Debug (read data):
00005b: fe fe fe fe fe fe fe fe 86 
Debug (read data):
00005c: fe fe fe fe fe fe fe fe 86 
Debug (read data):
00005d: fe fe fe fe fe fe fe fe 86 
Debug (read data):
00005e: fe fe fe fe fe fe fe fe 86 
Debug (read data):
00005f: fe fe fe fe fe fe fe fe 86 
Debug (read data):
000060: fe fe fe fe fe fe fe fe 86 
Debug (read data):
000061: fe fe fe fe fe fe fe fe 86 
Debug (read data):
000062: fe fe fe fe fe fe fe fe 86 
Debug (read data):
000063: fe fe fe fe fe fe fe fe 86 
Debug (read data):
000064: fe fe fe fe fe fe fe fe 86 
Debug (read data):
000065: fe fe fe fe fe fe fe fe 86 
Debug (read data):
000066: fe fe fe fe fe fe fe 86 00 
Debug (read data):
000067: fe fe fe fe fe fe fe 86 00 
Debug (read data):
000068: fe fe fe fe fe fe fe 86 00 
Chip sleep? -> Use reset chip (RTS-RST): see option --tact

@danergo
Copy link
Author

danergo commented Oct 13, 2024

And another with "-t 5000":

$ ./TLSR825xComFlasher.py -d -t 5000 -p /dev/ttyUSB0 rf 0 524288 default.flash
=======================================================
TLSR825x Flasher version 00.00.05
-------------------------------------------------------
Open /dev/ttyUSB0, 921600 baud...
Reset module (RTS low)...
Activate (5000 ms)...
Debug: default swdiv for 24 MHz = 52 (0x34)
Debug (read data):
000023: e6 1f fa df 10 fa 
Debug (read data):
000024: e6 1f fa 1f fa df 
Debug (read data):
000025: e6 1f f2 1f f2 90 
Debug (read data):
000026: e6 3f f4 3f 04 bf 
Debug (read data):
000027: e6 3f e4 3f 04 a0 
Debug (read data):
000028: e6 3f ec a0 bf ff 
Debug (read data):
000029: e6 3f ec 20 3f ec 
Debug (read data):
00002a: e6 3e c8 20 20 ff 
Debug (read data):
00002b: e6 7e d8 60 60 d8 
Debug (read data):
00002c: e6 7e 98 60 d8 7e 
Debug (read data):
00002d: e6 7e 90 60 90 60 
Debug (read data):
00002e: e6 7e b0 60 30 c8 fe 
Debug (read data):
00002f: e6 7e 30 40 30 18 e4 
Debug (read data):
000030: e6 7e 20 90 7e 3f fe 
Debug (read data):
000031: e6 fe 60 b0 fe 7f b0 
Debug (read data):
000032: e6 fe 60 20 fe 60 fe 
Debug (read data):
000033: e6 fe 40 60 fe 40 60 
Debug (read data):
000034: e6 fe c0 40 7f 60 fe ff 
Debug (read data):
000035: e6 fe c0 c0 ff 40 7f 60 
Debug (read data):
000036: e6 fe 80 c0 fe c0 c0 fe ff 
Debug (read data):
000037: e6 fe 80 80 fe 80 80 80 fe 
Debug (check data):
0ccc37: 80 fe fe 80 80 fe 80 80 80 fe 
bit mask: 0xc0
UART-SWS 92160 baud. SW-CLK ~25.3 MHz(?)
Outfile: default.flash
Read Flash from 0x000000 to 0x080000...
Read from 0x000100...
Debug: read swire byte:
00005c: 06 04 0c 0c 0c 0c 0c 0c c8 
Error Read Flash data at 0x000100! 

@danergo
Copy link
Author

danergo commented Oct 13, 2024

In case I manually skip 0x000100:

$ ./TLSR825xComFlasher.py -d -t 5000 -p /dev/ttyUSB0 rf 0x200 0x80000 default.flash
=======================================================
TLSR825x Flasher version 00.00.05
-------------------------------------------------------
Open /dev/ttyUSB0, 921600 baud...
Reset module (RTS low)...
Activate (5000 ms)...
Debug: default swdiv for 24 MHz = 52 (0x34)
Debug (read data):
000023: e6 1f fa df 10 fa 
Debug (read data):
000024: e6 1f fa 1f fa df 
Debug (read data):
000025: e6 1f f2 3f f6 b0 
Debug (read data):
000026: e6 3f f4 3f 04 bf 
Debug (read data):
000027: e6 3f e4 3f 04 a0 
Debug (read data):
000028: e6 3f ec a0 bf ff 
Debug (read data):
000029: e6 3f ec 20 3f ec 
Debug (read data):
00002a: e6 3e c8 20 20 ff 
Debug (read data):
00002b: e6 7e d8 60 60 d8 
Debug (read data):
00002c: e6 7e d8 60 d8 7e 
Debug (read data):
00002d: e6 7e 90 60 90 60 
Debug (read data):
00002e: e6 7e b0 60 30 c8 fe 
Debug (read data):
00002f: e6 7e 30 40 30 18 e4 
Debug (read data):
000030: e6 7e 20 90 7e 3f fe 
Debug (read data):
000031: e6 fe 60 30 fe 7f 30 
Debug (read data):
000032: e6 fe 60 20 fe 60 fe 
Debug (read data):
000033: e6 fe 40 60 fe 40 60 
Debug (read data):
000034: e6 fe c0 40 7f 60 fe ff 
Debug (read data):
000035: e6 fe c0 c0 ff 60 7f 60 
Debug (read data):
000036: e6 fe 80 80 fe c0 c0 fe fe 
Debug (check data):
0ccc36: 80 fe fe 80 80 fe 80 80 fe fe 
bit mask: 0xc0
Debug (read data):
000037: e6 fe 80 80 fe 80 80 80 fe 
Debug (check data):
0ccc37: 80 fe fe 80 80 fe 80 80 80 fe 
bit mask: 0xc0
UART-SWS 92160 baud. SW-CLK ~25.3 MHz(?)
Outfile: default.flash
Read Flash from 0x000200 to 0x080200...
Read from 0x000400...
Debug: read swire byte:
0000da: 06 04 0c 0c 0c 0c 0c 0c cc 
Error Read Flash data at 0x000400! 

I got error at 0x000400.

@danergo
Copy link
Author

danergo commented Oct 13, 2024

I used a 1K resistor between RX and TX as per your wiring.

@danergo
Copy link
Author

danergo commented Oct 13, 2024

This chip does not have protection against reading and writing firmware.

Are you sure?

Shot from TLSR8250F512ET32's datasheet:

Screenshot_20241013_152039_Samsung Notes

@pvvx
Copy link
Owner

pvvx commented Oct 14, 2024

You have problems with your USB-COM adapter.

SWS is a Single Wire Slave. It works on the Telink SWire hardware protocol. It has nothing in common with UART.
The Telink Swire protocol is emulated on Chinese USB-COM adapter chips:

  • Does not work on FTDI chips.
  • It does not work well if LEDs are soldered to the RX input of the USB-COM/UART adapter. You need to unsolder or cut out the LED.

The hardware version of the Telink SWire protocol, without emulation, is only possible on Telink chips.

Normal programmer using Telink Swire hardware interface
https://github.com/pvvx/TLSRPGM

Programmer from Telink - Telink EVK:
https://wiki.telink-semi.cn/wiki/IDE-and-Tools/Burning-and-Debugging-Tools-for-all-Series/


Are you sure?

This is just code encryption. It has nothing to do with reading the firmware.

@danergo
Copy link
Author

danergo commented Oct 14, 2024

CP2102 seems working (even with LEDs installed).

@danergo
Copy link
Author

danergo commented Oct 14, 2024

$ ./TLSR825xComFlasher.py -d -b 460800 -t 2000 -p /dev/ttyUSB0 rf 0x0 0x80000 default_1.flash
...
UART-SWS 46080 baud. SW-CLK ~25.3 MHz(?)
Outfile: default_1.flash
Read Flash from 0x000000 to 0x080000...
-------------------------------------------------------
Worked Time: 670.692 sec
Done!

$ ./TLSR825xComFlasher.py -d -b 460800 -t 2000 -p /dev/ttyUSB0 rf 0x0 0x80000 default_2.flash
$ diff default1.flash default2.flash
UART-SWS 46080 baud. SW-CLK ~25.3 MHz(?)
Outfile: default_2.flash
Read Flash from 0x000000 to 0x080000...
-------------------------------------------------------
Worked Time: 670.834 sec
Done!

$ diff -s default_1.flash default_2.flash
Files default_1.flash and default_2.flash are identical

Perfect. (Anyway, without -b 460800: 3 runs produced 3 different dumps, due to long wires. Once I switched to shorter wires, -b 460800 ruined the process, so I had to omit it => one might have to play with it!).

Now, for a very basic, simple hello-world example, which sdk would you suggest?

while(1) {
  gpioxy = 0x01; //turn PB<5> on (it's the "Reset" pad)
  delay(5000); //5s wait
  gpioxy = 0x00; //turn PB<5> off
  delay(5000);
}

Thank you!

@danergo
Copy link
Author

danergo commented Oct 22, 2024

Ok, managed to make:

  • GPIOs working
  • SWUART on SWS pin, to reuse the UART-USB for simple, one-way logging

Todo:

  • Read temperature & humidity from SHT
  • Read battery voltage
  • Bluetooth LE ads
  • Bluetooth OTA
  • Reverse engineer the screen (hardest)
  • Display data on the screen

@pvvx
Copy link
Owner

pvvx commented Oct 22, 2024

You need to:

  1. Set the number for the LYWSD002MMC device in https://github.com/pvvx/ATC_MiThermometer/blob/master/src/app_config.h
  2. Set the GPIO and sensor type
  3. Set approximately the same type of screen controller.

Then load the resulting firmware and use the "60" function to create a map of screen segments.
Rewrite some of the screen output functions.

@danergo
Copy link
Author

danergo commented Oct 22, 2024

Thx!

Will 60 work even when it's an epd with (most probably) spi controller?

@danergo
Copy link
Author

danergo commented Oct 22, 2024

Where shall I set device_type? in app_config I did, but app.c complains

@danergo
Copy link
Author

danergo commented Oct 22, 2024

okay, app.c and also app_att.c also have to be modified

@danergo
Copy link
Author

danergo commented Oct 22, 2024

my_HardStr, my_SerialStr needs to be adjusted in app_att.c. Where are those data coming from?

Besides of this, compiled, and flashing now. Bluetooth seems working, sensor seems working. Need to play more with gpios for the EPD.

17:04:33: Searching for devices
17:04:38: Connecting to: ATC_00048F
17:04:46: Hardware Revision String:
17:04:46: Software Revision String: V4.8
17:04:46: Firmware Revision String: github.com/pvvx
17:04:46: Detected custom Firmware
17:04:46: Hardware Version: Unknown or DIY (30) , Software Version: 4.8
17:04:46: Custom config HEX string: 55071000002804a931311e00

@danergo
Copy link
Author

danergo commented Nov 18, 2024

SPI_DO, SPI_CK seems matching, but how can I know which is EPD_BUSY, EPD_SHD, EPD_RST and EPD_CSB?

PA0, PA1, PB1, PC3 is connected to the FPC (among SPI_DO and SPI_CK). So I need to match PA0, PA1, PB1, PC3 to BUSY, SHD, RST, CSB. I have oscilloscope, but some guidance would be great to know what to check.

@pvvx
Copy link
Owner

pvvx commented Nov 19, 2024

All data from other thermometers was obtained using a logic analyzer. The original firmware was not decompiled, and there was no documentation for the EPD drivers. There were closely matching datasheets, and everything was selected by similarity and by examining protocol dumps.

@danergo
Copy link
Author

danergo commented Nov 19, 2024

OK, can you please help me with this?

Here are 8pins of the FPC with my logic analyser:

image

PA1 seems the SPI_CS? Although SPI_CK seems a bit odd at the beginning:
image

For PA0, maybe some kindof Enable?
image

@danergo
Copy link
Author

danergo commented Nov 20, 2024

Configured GPIO like below:

#define USE_EPD			(550/50 - 1) // min update time ms

#define EPD_RST				GPIO_PB1
#define PULL_WAKEUP_SRC_PB1 PM_PIN_PULLUP_1M
#define PB1_INPUT_ENABLE	1
#define PB1_DATA_OUT		1
#define PB1_OUTPUT_ENABLE	1
#define PB1_FUNC			AS_GPIO

#define EPD_SCL				GPIO_PD7
#define PULL_WAKEUP_SRC_PD7 PM_PIN_PULLDOWN_100K // PM_PIN_PULLUP_1M
#define PD7_INPUT_ENABLE	1
#define PD7_DATA_OUT		0
#define PD7_OUTPUT_ENABLE	1
#define PD7_FUNC			AS_GPIO

#define EPD_SDA				GPIO_PB7
#define PULL_WAKEUP_SRC_PB7 PM_PIN_PULLDOWN_100K // PM_PIN_PULLUP_1M
#define PB7_INPUT_ENABLE	1
#define PB7_DATA_OUT		1
#define PB7_OUTPUT_ENABLE	1
#define PB7_FUNC			AS_GPIO

#define EPD_CSB				GPIO_PA1
#define PULL_WAKEUP_SRC_PA1 PM_PIN_PULLUP_1M
#define PA1_INPUT_ENABLE	1
#define PA1_DATA_OUT		1
#define PA1_OUTPUT_ENABLE	1
#define PA1_FUNC			AS_GPIO

#define EPD_BUSY			GPIO_PA0
#define PULL_WAKEUP_SRC_PA0 PM_PIN_PULLUP_1M
#define PA0_INPUT_ENABLE	1
#define PA0_FUNC			AS_GPIO

/*
#define EPD_SHD				GPIO_PA1 // should be high
#define PULL_WAKEUP_SRC_PA1 PM_PIN_PULLUP_10K
*/

But screen doesn't change at all. Any suggestion?

@danergo
Copy link
Author

danergo commented Nov 26, 2024

ping?

@danergo
Copy link
Author

danergo commented Nov 27, 2024

Do you have some idea what shall I check/log to get some results on the screen?

@danergo
Copy link
Author

danergo commented Nov 30, 2024

anything? :)

@pvvx
Copy link
Owner

pvvx commented Nov 30, 2024

For example, the CGG1 protocol was obtained as follows: Scans Saleae Logic

If you find the TLSR8250 difficult to work with, follow jonathonlui example:
https://github.com/jonathonlui/MHO-C201

@danergo
Copy link
Author

danergo commented Dec 3, 2024

Okay, thank you.

I understand every bit of your CGG1 protocol obtaining process.

However this device has some really uncommon waveforms, please take a look at this attachment.

Done with Logic, with my USBee AX PRO Mini Logic Analyzer (24MHz).

But SPI's signals are weird:

image

FactoryFW_Startup.zip

@pvvx
Copy link
Owner

pvvx commented Dec 4, 2024

Nothing strange. Regular soft SPI on 9 bits by means of GPIO operation.

The first CLK cycles are extended when calling a procedure from Flash while loading code into cache. Perhaps the code is written in such a way - the first bit indicates a command or data. And the processing of the first bit is described by a separate procedure...

image

Similar to the controller used in epd_mho_c401n.c or epd_cgg1n.c.

The main table T_LUT_init[] is completely identical:
image

That is, you are lucky - the driver is already ready.
All that remains is the segments map...

@danergo
Copy link
Author

danergo commented Dec 4, 2024

YESSSS!

20241204_085051

Can you tell me: is there a way in Logic, to start and SPI decoder from a certain marker (without deleting that data)?

In the beginning of my recording there were some noise (IMHO), which ruined my SPI decoder, and it dumped invalid data (until You point my attention on what exactly shall I see).

Also, I kindof see T_LUT_ping[5] = {0x07B, 0x081, 0x0E4, 0x0E7, 0x008}:

image

But last byte is 00E instead of 008. Are these numbers coming from display controller's datasheet?

In epd_mho_c401n.c, T_LUT_ping is the first data being sent to the display.

But in my recording there are 10 bytes before this ping pattern:

02b 0a7 0e0 082 068 050 0e8 0d0 0a8 065 | 07b ...

Are these bytes not needed?

@pvvx
Copy link
Owner

pvvx commented Dec 4, 2024

There are two types of EPD.

Old ones - they need to be regenerated - for this, the controller is temporarily reprogrammed and a cycle with reverse polarity is performed (sometimes flashes a negative image or completely black and then white) ... For this, another T_LUT_init[] and settings are used. If you do not occasionally perform regenerations - the display degrades - it will become gray forever.

New ones - they do not need to be regenerated.

I don't know what display you have.

@danergo
Copy link
Author

danergo commented Dec 4, 2024

Okay thanks. And do you know what are those 10bytes before ping LUT?

@pvvx
Copy link
Owner

pvvx commented Dec 4, 2024

Don't know.

If the display works correctly, then why this additional initialization?
There may be settings transferred that are already equal to the default values ​​after resetting the controller.

@danergo
Copy link
Author

danergo commented Dec 4, 2024

Nah, I have mapped all segments :)

image

If the display works correctly, then why this additional initialization?

It only works correctly, in case I have this setup:

(ORIGINAL_PCB) --fpc-- (FPC_to_PINHEADER) --dupont_cables-- (PINHEADER_to_FPC) --fpc-- (ORIGINAL_DISPLAY)
                                            \---Logic Analyzer --usb_cable-- PC

However, if I remove the Logic Analyzer, it stops working:

(ORIGINAL_PCB) --fpc-- (FPC_to_PINHEADER) --dupont_cables-- (PINHEADER_to_FPC) --fpc-- (ORIGINAL_DISPLAY)

I also tried getting rid of the FPC_to_PINHEADERs:

(ORIGINAL_PCB) --fpc-- (ORIGINAL_DISPLAY)

But it is not initializing the screen.

Only way to make it work is to connect the logic analyzer to it and also to PC. Note: same PC is used to power the original pcb.

Do you maybe have any idea what is causing this?

@danergo
Copy link
Author

danergo commented Dec 4, 2024

I have done some voltage measurements on all of the 10pins of the FPC:

No# MCU Pin Assumed function Original fw Voltage (V) Custom fw voltage with analyzer attached Custom fw voltage without analyzer
1 PA0 BUSY_N 3.4 3.3 2.5 (!)
2 PA1 CSB 3.4 3.3 1.8 (!)
3 PD7 SPI_CK 3.4 2.0 1.0 (!)
4 PB7 SPI_DATA 3.4 2.0 1.0 (!)
5 PB1 RST_N 3.4 3.2 1.8 (!)
6 PC3 SHD_N 3.4 3.4 2.4 (!)
7 VCC VCC 3.4 3.4 3.3
8 GND GND 0 0 0
9 X X 0 0 0
10 X X 0 0 0

This seems some GPIO issue to me. I'm using your original repo, with minor mods for this screen only (copied the epd_mho_c401n.c to epd_mjwsd02.c).

In case you have any ideas, please share with me. It seems I'll have to dig myself into your custom gpio setting in main.c.

It's pretty strange it works with logic analyzer attached, and not without it.

@pvvx
Copy link
Owner

pvvx commented Dec 4, 2024

You're looking in the wrong place.
Correctly enable "PULL_WAKEUP_SRC_xx" in "app_config.h".

  1. And it is possible that the power or "enable" of the EPD controller is connected through some GPIO.
  2. Short controller reset duration.
  3. High SPI frequency.
  4. Secondly, TLSR825x can be powered from any GPIO. The reason is low current consumption and most of the time the SoC is in sleep mode (current consumption < 2 µA (2 megaohm resistor at 3.3V))

_gpio_init() in main.c is a fix for the gpio_init() routine from the SDK. In the SDK, gpio_init() causes pulses on the GPIO at startup.
This is partially fixed by _gpio_init().

PS: I don't speak English and it's difficult and time-consuming for me to describe everything through Google Translate - it doesn't understand Russian well.

In case you have any ideas, please share with me.

Teach everything about electronics and microcontroller programming in a "github issue"?

@danergo
Copy link
Author

danergo commented Dec 5, 2024

I appreciate your inputs and help.

Correctly enable "PULL_WAKEUP_SRC_xx" in "app_config.h".

I copied this from other devices (and corrected the numbers for this board):

#define EPD_SHD			GPIO_PC3 // should be high
#define PULL_WAKEUP_SRC_PC3	PM_PIN_PULLUP_10K

#define EPD_RST			GPIO_PB1
#define PULL_WAKEUP_SRC_PB1	PM_PIN_PULLUP_1M
#define PB1_INPUT_ENABLE	1
#define PB1_DATA_OUT		1
#define PB1_OUTPUT_ENABLE	1
#define PB1_FUNC		AS_GPIO

#define EPD_SDA			GPIO_PB7
#define PULL_WAKEUP_SRC_PB7	PM_PIN_PULLDOWN_100K // PM_PIN_PULLUP_1M
#define PB7_INPUT_ENABLE	1
#define PB7_DATA_OUT		1
#define PB7_OUTPUT_ENABLE	1
#define PB7_FUNC		AS_GPIO

#define EPD_SCL			GPIO_PD7
#define PULL_WAKEUP_SRC_PD7	PM_PIN_PULLDOWN_100K // PM_PIN_PULLUP_1M
#define PD7_INPUT_ENABLE	1
#define PD7_DATA_OUT		0
#define PD7_OUTPUT_ENABLE	1
#define PD7_FUNC		AS_GPIO

#define EPD_CSB			GPIO_PA1
#define PULL_WAKEUP_SRC_PA1	PM_PIN_PULLUP_1M
#define PA1_INPUT_ENABLE	1
#define PA1_DATA_OUT		1
#define PA1_OUTPUT_ENABLE	1
#define PA1_FUNC		AS_GPIO

#define EPD_BUSY		GPIO_PA0
#define PULL_WAKEUP_SRC_PA0	PM_PIN_PULLUP_1M
#define PA0_INPUT_ENABLE	1
#define PA0_FUNC		AS_GPIO

But, for SCL and SDA we need PULLUP to work correctly. Thank you!

@danergo danergo closed this as completed Dec 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants