Author Archives: vonger

Screen: 5inch upgrade

New 5inch screen comes, old version will keep production for a while for compatible, but later we consider move to new version.

New screen(D500FPC9373-C) we have four improvements.

  1. stronger border, this is in order to provide better protection of the screen.
  2. increase backlight brightness.
  3. better color for display.
  4. better supply, old version screen driver chip is pretty shortage.

Also these improvements caused shape adjust. The display screen thickness increased 0.2mm, and border is wider 0.2mm. Touch screen and display area still same size.

PS: new screen currently only test with our screen_test and SimHub, rest application might not compatible, need to upgrade. For non-developer, recommend to keep using the old stable version to avoid any mystery problem.

Why shitty like PayPal still exists?!

This happens more than one time. I think we have already stand enough to use PayPal and need to find an alter one asap. It is too risk to use it for online shop.

Case is like this: some people go to our store and purchase something, suddenly they think they buy wrong items. And did not email us but open a disputes case and ask for refund. All in 5 minutes.

Once case is open, whatever we reply or we do not reply, it will be automaticlly submit and of course, buyer’s favor.

I really understand and willing to refund people for mistake buying from our store, but why the paypal charge us 8USD for dispute fee?! It is terrible.

I think move our store to and use alipay is the only choice…

Screen: hand solder driver board to customized board

Some DIYers complained it is pretty hard for hand solder the small screen driver board on their designed board. So I find a way for them easier hand solder screen driver board to their board.

On the screen driver board bottom, we have some test points which is used for test at production also for SMT the board to other customized board. It is not designed for hand solder. We need some tricky for hand solder.

We can design like this, add a oval hole on the PCB, size should be enough for the thin iron

Then we can directly solder through the hole to the pads. This way we do not need use pins or other connectors, low cost and simple. 🙂

Attach the position of the pads(KiCAD), one note is they are on the bottom side.

For mass production, I still recommend directly use SMT machine solder it. :p

Code Tricky: why not optimize is_digit

Recently I need a super small bootloader for an arm chip, every bit need to be very careful used. When I read the code, I find an interesting function is_digit in printf.c, this blog will show common code and old expert code difference.

This function is used to check if a char is in the range of ‘0’ ~’9′, ascii is 48~57.

The common code is like this:

bool _is_digit_a(char ch)
    return (ch >= '0') && (ch <= '9');

This way is easy to read, but normally old fashion will write in another way, like this

bool _is_digit_b(char ch)
    return ((unsigned char)(ch - '0') <= 9);

Haha, actually they are same function, but second way looks like much smaller and faster.

Let’s do a simple test by gcc and its toolchain, first for x86 system:

call gcc -c test.c -o test.x86.o, then objdump -DSx test.x86.o, we can get machine code

0000000000000000 <_is_digit_a>:
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: 89 f8 mov %edi,%eax
a: 88 45 fc mov %al,-0x4(%rbp)
d: 80 7d fc 2f cmpb $0x2f,-0x4(%rbp)
11: 7e 0d jle 20 <_is_digit_a+0x20>
13: 80 7d fc 39 cmpb $0x39,-0x4(%rbp)
17: 7f 07 jg 20 <_is_digit_a+0x20>
19: b8 01 00 00 00 mov $0x1,%eax
1e: eb 05 jmp 25 <_is_digit_a+0x25>
20: b8 00 00 00 00 mov $0x0,%eax
25: 83 e0 01 and $0x1,%eax
28: 5d pop %rbp
29: c3 retq
000000000000002a <_is_digit_b>:
2a: f3 0f 1e fa endbr64
2e: 55 push %rbp
2f: 48 89 e5 mov %rsp,%rbp
32: 89 f8 mov %edi,%eax
34: 88 45 fc mov %al,-0x4(%rbp)
37: 0f b6 45 fc movzbl -0x4(%rbp),%eax
3b: 83 e8 30 sub $0x30,%eax
3e: 3c 09 cmp $0x9,%al
40: 0f 96 c0 setbe %al
43: 5d pop %rbp
44: c3 retq

so A takes around 15 commands and 42 bytes, and B takes 11 commands and 27 bytes, save approx 30%.

Then check arm, call arm-none-eabi-gcc -c test.c -o test.arm.o, then arm-none-eabi-objdump -Dsx test.arm.o

00000000 <_is_digit_a>:
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e24dd00c sub sp, sp, #12
c: e1a03000 mov r3, r0
10: e54b3005 strb r3, [fp, #-5]
14: e55b3005 ldrb r3, [fp, #-5]
18: e353002f cmp r3, #47 ; 0x2f
1c: 9a000004 bls 34 <_is_digit_a+0x34>
20: e55b3005 ldrb r3, [fp, #-5]
24: e3530039 cmp r3, #57 ; 0x39
28: 8a000001 bhi 34 <_is_digit_a+0x34>
2c: e3a03001 mov r3, #1
30: ea000000 b 38 <_is_digit_a+0x38>
34: e3a03000 mov r3, #0
38: e2033001 and r3, r3, #1
3c: e20330ff and r3, r3, #255 ; 0xff
40: e1a00003 mov r0, r3
44: e28bd000 add sp, fp, #0
48: e49db004 pop {fp} ; (ldr fp, [sp], #4)
4c: e12fff1e bx lr
00000050 <_is_digit_b>:
50: e52db004 push {fp} ; (str fp, [sp, #-4]!)
54: e28db000 add fp, sp, #0
58: e24dd00c sub sp, sp, #12
5c: e1a03000 mov r3, r0
60: e54b3005 strb r3, [fp, #-5]
64: e55b3005 ldrb r3, [fp, #-5]
68: e2433030 sub r3, r3, #48 ; 0x30
6c: e20330ff and r3, r3, #255 ; 0xff
70: e3530009 cmp r3, #9
74: 93a03001 movls r3, #1
78: 83a03000 movhi r3, #0
7c: e20330ff and r3, r3, #255 ; 0xff
80: e1a00003 mov r0, r3
84: e28bd000 add sp, fp, #0
88: e49db004 pop {fp} ; (ldr fp, [sp], #4)
8c: e12fff1e bx lr

A uses 20 instructions and B uses 16 instructions, saves 20%. Also no branch, more friendly to CPU workflow.

Final, try riscv, call riscv-none-embed-gcc -c test.c -o test.riscv.o, then riscv-none-embed-objdump -Dsx test.riscv.o

00000000 <_is_digit_a>:
0: 1101 addi sp,sp,-32
2: ce22 sw s0,28(sp)
4: 1000 addi s0,sp,32
6: 87aa mv a5,a0
8: fef407a3 sb a5,-17(s0)
c: fef44703 lbu a4,-17(s0)
10: 02f00793 li a5,47
14: 00e7fa63 bgeu a5,a4,28 <.L2>
18: fef44703 lbu a4,-17(s0)
1c: 03900793 li a5,57
20: 00e7e463 bltu a5,a4,28 <.L2>
24: 4785 li a5,1
26: a011 j 2a <.L3>
00000028 <.L2>:
28: 4781 li a5,0
0000002a <.L3>:
2a: 8b85 andi a5,a5,1
2c: 0ff7f793 andi a5,a5,255
30: 853e mv a0,a5
32: 4472 lw s0,28(sp)
34: 6105 addi sp,sp,32
36: 8082 ret
00000038 <_is_digit_b>:
38: 1101 addi sp,sp,-32
3a: ce22 sw s0,28(sp)
3c: 1000 addi s0,sp,32
3e: 87aa mv a5,a0
40: fef407a3 sb a5,-17(s0)
44: fef44783 lbu a5,-17(s0)
48: fd078793 addi a5,a5,-48
4c: 0ff7f793 andi a5,a5,255
50: 00a7b793 sltiu a5,a5,10
54: 0ff7f793 andi a5,a5,255
58: 853e mv a0,a5
5a: 4472 lw s0,28(sp)
5c: 6105 addi sp,sp,32
5e: 8082 ret

A takes 54bytes and 20 instructions; B takes 38bytes and 14 instructions, save 30%. Also no branch, more friendly to CPU workflow.

test source code like this:

#include <stdbool.h>
#include <stdio.h>

bool _is_digit_a(char ch)
    return (ch >= '0') && (ch <= '9');

bool _is_digit_b(char ch)
    return ((unsigned char)(ch - '0') <= 9);

void main(void)
    for (unsigned char i = 0; i < 255; i++) {
        printf("%d is%s digit\r\n", i, _is_digit_a((char)i) ? "" : " not");
        printf("%d is%s digit\r\n", i, _is_digit_b((char)i) ? "" : " not");

PS: actually for modern compiler, any optimize will make both same code, only 1/3 of not optimized size. 🙂 nothing really need to improve now. Way A is the better way for it is more readable.

So final note, do not forget -O when you use gcc :p

VoCore2: OpenWrt 21.02 Patch/Compile-2

This blog focus on microSD support.

Because I already know it is cd-polling problem, so directly go to source code, see if the polling is supported in this version.

Source code position is at openwrt-21.02.1/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/sd.c

... line 2249 ...
if (of_property_read_bool(pdev->dev.of_node, "mediatek,cd-poll"))
    mmc->caps |= MMC_CAP_NEEDS_POLL;

... line 442 ...
if (host->mmc->caps & MMC_CAP_NEEDS_POLL)
    inserted = 1;

... line 1862 ...
if (host->mmc->caps & MMC_CAP_NEEDS_POLL)
    present = 1;

Looks like my patch is already combined to 21.02, so once I add this mediatek,cd-poll to VoCore2 Ultimate DTS it will just works.

We can directly modify openwrt-21.02.1/target/linux/ramips/dts/mt7628an_vocore_vocore2.dts to make VoCore2 support SD card. For simple, attach four lines to end of the dts file.

&sdhci {
	status = "okay";

Now, after this patch, make sure kmod-mmc, kmod-sdhci-mt7620 is selected in kernel.

Compile OpenWrt, then upload to VoCore2, it just works.

PS: if your VoCore do not have SD card slot, enable sdhci polling mode will cause it output error log every two seconds. So this driver is not default enable in VoCore2 device tree.

VoCore2: OpenWrt 21.02 Patch/Compile-1

OpenWrt 21.02.2 is pretty stable, the even better part is it supports WPA3. Official OpenWrt 21.02.2 release directly work with VoCore2 SBC version, but for VoCore2 Ultimate version, we have some external devices need to be supported, so this blog and following blogs I will write down the process I patch OpenWrt 21.02.

There are three main parts:

  1. microSD card can not detect or read.
  2. ES8388 sound card can not work.
  3. DTS(device tree) need to update add 1,2 setting.

In my experience, microSD problem is mainly caused by default mmc driver who do not support cd-polling. cd-polling is used to scan the microSD card insert into the slot but not using card detect pin. Actually I have already submit this patch to 18.06 and 19.07, so I just need to copy and paste the patch to make it work on 21.02.

ES8388 sound card driver code is already in Linux system. For 19.07 I have a dirty patch. The better way is to write a simple clock control driver, and use DTS to setup it. For this version, I will try to make it.

DTS, this is pretty painful to learn because current tutorial is not very friendly for beginner. I will try to write another not that painful tutorial…

Screen: WinUSB Install + New Test App

I find libusbk sometimes crash the system, so maybe winusb is a good choice. Before you install WinUSB, remember to install libusbK first.

Here is a simple tutorial about install winusb driver.

First download zadig, it is include in, in folder v2scrtest.

Plug in the screen and run zadig.exe

Select USB2.0 Screen from the list. Then click Install Driver. (If already installed, it will be Reinstall Driver, normally do not need install again).

Install will take around 2 minutes.

After that, for win10 or upper system can directly run v2scrctl.exe for test the screen.

You can drag and drop test.jpg or any other picture file to the window to let it show on the screen. Also it can show the touch points from the screen.

Have fun!


Tool: Convert PDF to PNG

My boss today asked me convert a PDF file to PNG file because they can not use mspaint to edit any PDF file… Of course I know it is very simple by using xpdf, but I also know the cleaver boss will never learn using command line tool. 🙂

So I have to write a simple tool to avoid they ask me again.

After two hours, it is done. Just drag and drop the PDF to the window, then it will create PNG files into desktop/pdf2png folder. Bosss do not have to type a word.

Download link:

PS: not sure if it will work on other windows computer, but at least it works on my win10 and another win7 system.

Hope it helps 🙂

VoCore2: Compile OpenWrt 21.02 in MacOS

Finally OpenWrt new version comes to stable. There are many great new feature for new Linux kernel and also improve stable for OpenWrt, why not have a try?

First, everything is same as usual, make an image by Disk Utility, 10GB is enough.

Clone from OpenWrt, I use github version, it is faster than openwrt server: git clone -b openwrt-21.02

We can not use make, because it will throw error: /Volumns/OpenWrt21/include/ *** Please use a newer version of GNU make. The version shipped by Apple is not supported.  Stop.

Use brew install make, then call gmake menuconfig will fix such problem.

After menuconfig select correct settings, we can directly call gmake V=s to start the make process.

After a while, it will stop at “Checking for c++filt…“, it is for libstdc++-v3, we need to go to build_dir libstdc++-v3 folder, modify configure file, delete from line 79170 to 79296 to avoid checking such command. No idea why it stuck there…and c++filt seems not critical if not exists.

Then just keep building, rest seems smoothly.

Next blog I will check if there is any bug need to patch for this new version.

VoCore2: Compile Latest Wifi Driver 2

Because of the macro is pretty complex, have to use a trick. The old version Makefile works fine, so we can use its macro define.

Grab the Makefile command line first:

mipsel-openwrt-linux-musl-gcc -Wp,-MD,/Volumes/OpenWrt18/build_dir/target-mipsel_24kc_musl/linux-ramips_mt76x8/mt7628-p4rev-120395/build/../src/embedded/os/linux/.rt_pci_rbus.o.d  -nostdinc -isystem /Volumes/OpenWrt18/staging_dir/toolchain-mipsel_24kc_gcc-7.3.0_musl/bin/../lib/gcc/mipsel-openwrt-linux-musl/7.3.0/include -I./arch/mips/include -I./arch/mips/include/generated  -I./include -I./arch/mips/include/uapi -I./arch/mips/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -D__KERNEL__ -DVMLINUX_LOAD_ADDRESS=0xffffffff80000000 -DLINKER_LOAD_ADDRESS=0x80000000 -DDATAOFFSET=0 -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -fno-PIE -mno-check-zero-division -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely -msoft-float -DGAS_HAS_SET_HARDFLOAT -Wa,-msoft-float -ffreestanding -fno-stack-check -march=mips32r2 -mtune=34kc -Wa,--trap -DTOOLCHAIN_SUPPORTS_VIRT -I./arch/mips/include/asm/mach-ralink -I./arch/mips/include/asm/mach-ralink/mt7620 -I./arch/mips/include/asm/mach-generic -fno-asynchronous-unwind-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-int-in-bool-context -Os -fno-caller-saves --param=allow-store-data-races=0 -DCC_HAVE_ASM_GOTO -Wframe-larger-than=1024 -fstack-protector -Wno-unused-but-set-variable -Wno-unused-const-variable -fomit-frame-pointer -fno-var-tracking-assignments -g -femit-struct-debug-baseonly -fno-var-tracking -Wdeclaration-after-statement -Wno-pointer-sign -Wno-array-bounds -Wno-stringop-overflow -Wno-restrict -Wno-maybe-uninitialized -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fno-stack-check -fconserve-stack -Werror=implicit-int -Werror=strict-prototypes -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -I/Volumes/OpenWrt18/build_dir/target-mipsel_24kc_musl/linux-ramips_mt76x8/mt7628-p4rev-120395/build/../src/include -I/Volumes/OpenWrt18/build_dir/target-mipsel_24kc_musl/linux-ramips_mt76x8/mt7628-p4rev-120395/build/../src/embedded/include -I/Volumes/OpenWrt18/build_dir/target-mipsel_24kc_musl/linux-ramips_mt76x8/mt7628-p4rev-120395/build/../src/ate/include -DCONFIG_SUPPORT_OPENWRT=y -DCONFIG_RALINK_MT7628=y -DNEW_RATE_ADAPT_SUPPORT -DUAPSD_SUPPORT -DUAPSD_DEBUG -DMT_PS -DWSC_INCLUDED -DWSC_SINGLE_TRIGGER -DWSC_AP_SUPPORT -DWSC_V2_SUPPORT -DDOT11W_PMF_SUPPORT -DSOFT_ENCRYPT -DMBSS_SUPPORT -DMT7628 -DMT_BBP -DMT_RF -DRTMP_RBUS_SUPPORT -DRTMP_RF_RW_SUPPORT -DMT_MAC -DRTMP_MAC_PCI -DRTMP_PCI_SUPPORT -DRTMP_FLASH_SUPPORT -DDMA_SCH_SUPPORT -DRTMP_EFUSE_SUPPORT -DCONFIG_ANDES_SUPPORT -DRESOURCE_PRE_ALLOC -DNEW_MBSSID_MODE -DENHANCE_NEW_MBSSID_MODE -DENHANCED_STAT_DISPLAY -DFIFO_EXT_SUPPORT -DMCS_LUT_SUPPORT -DUSE_BMC -DTHERMAL_PROTECT_SUPPORT -DCAL_FREE_IC_SUPPORT -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX -Wall -Wstrict-prototypes -Wno-trigraphs -DCONFIG_AP_SUPPORT -DSCAN_SUPPORT -DAP_SCAN_SUPPORT -DDOT11_N_SUPPORT -DDOT11N_DRAFT3 -DSTATS_COUNT_SUPPORT -DIAPP_SUPPORT -DDOT1X_SUPPORT -DCONFIG_RA_NAT_NONE -DDBG -DIP_ASSEMBLY  -DMODULE -mno-long-calls  -DKBUILD_BASENAME='"rt_pci_rbus"'  -DKBUILD_MODNAME='"mt7628"' -c -o /Volumes/OpenWrt18/build_dir/target-mipsel_24kc_musl/linux-ramips_mt76x8/mt7628-p4rev-120395/build/../src/embedded/os/linux/rt_pci_rbus.o /Volumes/OpenWrt18/build_dir/target-mipsel_24kc_musl/linux-ramips_mt76x8/mt7628-p4rev-120395/build/../src/embedded/os/linux/rt_pci_rbus.c


Compare Makefile, we can get the defines. Update Makefile…

    CONFIG_RALINK_MT7628=y \
    CONFIG_MT7628_UAPSD=y \
    CONFIG_MT7628_MAC=y \

Then call “make package/mt7628/compile V=s”

Because there is no patch, we will get a lot of errors…I find most of the problem is not critical…Like this:

/Volumes/OpenWrt/build_dir/target-mipsel_24kc_musl/linux-ramips_mt76x8/mt7628-wifi/mt7628_wifi_ap/../mt7628_wifi/embedded/common/wsc.c:9903:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if

The driver internal Makefile default has -Werror, so such warning from new compiler gcc are dealed as error. That can be removed. Rest problem is because of new Linux kernel modify, so final patch like this:

--- a/mt7628_wifi_ap/Makefile
+++ b/mt7628_wifi_ap/Makefile
@@ -533,7 +533,7 @@
-               -Wall -Wstrict-prototypes -Wno-trigraphs -Werror -Wframe-larger-than=4096
+               -Wall -Wstrict-prototypes -Wno-trigraphs -Wframe-larger-than=4096
--- a/mt7628_wifi/embedded/common/cmm_info.c
+++ b/mt7628_wifi/embedded/common/cmm_info.c
@@ -97,7 +97,6 @@
-		MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("Driver version-%s %s %s\n", AP_DRIVER_VERSION, __DATE__, __TIME__));
 #endif /* CONFIG_AP_SUPPORT */
--- a/mt7628_wifi/embedded/os/linux/rt_profile.c
+++ b/mt7628_wifi/embedded/os/linux/rt_profile.c
@@ -236,7 +236,7 @@
 			// TODO: need to roll back when convert into OSABL code
-				 fsize = (ULONG)srcf->f_dentry->d_inode->i_size;
+				 fsize = (ULONG)srcf->f_path.dentry->d_inode->i_size;
 				if (buf_size < (fsize + 1))
 					buf_size = fsize + 1;
 #endif /* OS_ABL_SUPPORT */
--- a/mt7628_wifi/embedded/common/wsc.c
+++ b/mt7628_wifi/embedded/common/wsc.c
@@ -9847,7 +9847,7 @@
 	UCHAR		apIdx;
-#ifdef LINUX
+#ifdef LINUX_SIG
 /* +++  added by YYHuang@Ralink, 08/03/12 */
--- a/mt7628_wifi/embedded/os/linux/rt_proc.c
+++ b/mt7628_wifi/embedded/os/linux/rt_proc.c
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "rt_config.h"

Then we can successfully get the mt7628.ko file.