Author Archives: vonger

Screen: Firmware CHANGELOG(v0.20)

This change log is copied from https://vocore.io/misc/v2scrctl.zip, README.txt.

From v0.16 to v0.20, the main upgrades include:

  • Increased FPS by approximately 30% for all types of screens.
  • Support for JPG compressed frames.
  • Support for 10-inch screens (1024×600 resolution).
  • Reduced 70% MPRO startup time.
  • Support for using as the main or extended screen for Windows/Linux (Raspberry Pi/Ubuntu, mpro_drm driver).

2024.09.02

  • fix v2scrctl touch trace for 6.8inch screens.

2024.08.19

  • support 10inch screen, display/touch.

2024.08.08

  • add fwcust.exe, it use old version customized logo firmware to generate latest version customized logo firmware.

2024.08.02

  • firmware version upgrade to v0.20
  • boot up speed reduce 1.5s.
  • speed up v2scrctl scan for screen.

2024.07.30

  • firmware version upgrade to v0.19
  • firmware increase 28% fps for full draw.
  • fix v2scrctl can not find correct firmware.

2024.07.20

  • fix touch screen miss hover signal sometimes.
  • add nologo firmware.
  • fix v2scrctl show wrong touch trace for some screens.

2024.07.17

  • add notify at v2scrctl monitor mode.
  • add extmon.exe, this is for specified screen for monitor mode.
  • add extmon source code.
  • move source code to source folder.

2024.07.10

  • firmware support baseline jpeg compress. convert: ffmpeg -i 800x480.bmp -v:q 3 -pix_fmt yuvj420p out.jpg
  • fix partily draw not align data cannot show.

2024.06.04

  • update v2scrctl, automatically choose firmware at Upgrade.

2024.06.02

  • tutorial/win10.mkv is for windows10 indirect display driver install.
  • add Windows 11 indirect display driver tutorial and pictures to driver/mprodrv/tutorial.

2024.05.25

  • add tutorial for install WinUSB/Extend screen driver(tutorial.mkv).
  • add Windows extend screen driver.

2024.05.18

  • add flip/mirror for most V7B VoCore screens and all MPRO VoCore screens.
  • upgrade firmware version to v0.17.

Screen: Run on RaspberryPi(DRM)

Framebuffer driver is out of date, so our latest driver DRM might be better for raspberrypi user to use VoCore Screen. This tutorial is for new MPRO version screen which support paritialy draw, it is very fast to show raspberry desktop and can easily reach 60FPS.

Source code at https://github.com/Vonger/mpro_drm/tree/6.6.y-dma

Framebuffer driver tutorial: https://vonger.cn/?p=15349 (out of date, not easy to run on new raspi)

VoCore2: Serial Port Transfer Small File

When I develop, sometimes wifi or network not working, or ssh can not connect, only way to fix it to use serial port, but serial port do not support transfer file…there are no way to transfer small files, like a simple driver or small application, have to reboot and use uboot to reload everything, and kermit load new firmware to uboot is really slow.

PS: I know somebody can use kermit or sz/lz, but first of all, you need to have them in firmware already, that is a chicken-and-egg problem 🙂

I find default busybox shell(sh) support command “echo -ne”, this is a amazing way to transfer binary data by serial port, and do not need any depends, so I write a simple application, hope this helps.

Usage Example, save TEST.ko to VoCore2 /tmp/TEST.ko: sspdt TEST.ko /dev/ttyACM0

Note: after transfer, remember to run md5sum to check if the data transfer is correct and complete, serial port do not guarantee that. From my test, < 100KB file normally do not have problem, and speed approx 1.5KB/s

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libserialport.h>

// apt install libserialport-dev
// gcc sspdt.c -o sspdt -lserialport
// speed is approx 1.5KB/s

#define min(a, b) ((a) < (b) ? (a) : (b))

uint8_t *alloc_from_file(const char *name, int *size)
{
    FILE *fp = fopen(name, "rb");
    if (fp == NULL)
        return NULL;

    fseek(fp, 0, SEEK_END);

    *size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    uint8_t *buf = malloc(*size);
    if (buf)
        fread(buf, 1, *size, fp);
    fclose(fp);

    return buf;
}

struct sp_port *ssport_open(const char *name)
{
    struct sp_port *port;
    int baudrate = 115200, res;

    res = sp_get_port_by_name(name, &port);
    if (SP_OK != res)
        return NULL;

    res = sp_open(port, SP_MODE_READ_WRITE);
    if (SP_OK != res) {
        printf("sp_open=%d, %s\n", res, sp_last_error_message());
        return NULL;
    }

    // clear input/output buffer.
    sp_flush(port, SP_BUF_BOTH);

    // gd32f150 supported protocol 115200, 8n1.
    sp_set_baudrate(port, baudrate);
    sp_set_bits(port, 8);
    sp_set_parity(port, SP_PARITY_NONE);
    sp_set_stopbits(port, 1);

    // necessary, or system will drop 0x11 and 0x13.
    sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE);

    return port;
}

void ssport_close(struct sp_port *port)
{
    sp_flush(port, SP_BUF_BOTH);
    sp_close(port);
    sp_free_port(port);
}

int ssport_write(struct sp_port *port, const void *buf, size_t count)
{
    int wbyte;
    wbyte = sp_blocking_write(port, buf, count, 600);
    //print_hex("wr", buf, wbyte);
    return wbyte;
}

int ssport_read(struct sp_port *port, void *buf, size_t count)
{
    int rbyte;
    rbyte = sp_blocking_read(port, buf, count, 600);
    //print_hex("rd", buf, rbyte);
    return rbyte;
}

void process(int cur, int total)
{
    printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
    printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
    printf("%9dB / %9dB [%3.1f%%]", cur, total, (float)cur / total * 100);
    fflush(stdout);
}

void get_file_name(const char *name, char *out)
{
    int i = strlen(name) - 1;
    for (; i >= 0; i--) {
        if (name[i] == '/' || name[i] == '\\')
            break;
    }
    strcpy(out, name + i);
}

int main(int argc, char *argv[])
{
    if (argc != 3) {
        printf("sspdt [input file] [serial port]\r\n");
        printf("send small files to device term by serial port.\r\n");
        return 0;
    }

    int size = 0;
    uint8_t *buf = alloc_from_file(argv[1], &size);
    struct sp_port *sp = ssport_open(argv[2]);

    ssport_write(sp, "\n\n", 2);
    usleep(1000);

    char name[128] = {0};
    get_file_name(argv[1], name);
    printf("file %s will save to device /tmp/%s\r\n", argv[1], name);

    // each time read 16 bytes
    for (int i = 0; i < size; i += 16) {
        char cmd[0x100] = {0};
        sprintf(cmd, "echo -ne '");
        for (int j = 0; j < min(size - i, 16); j++) {
            char tmp[16];
            sprintf(tmp, "\\x%02x", buf[i + j]);
            strcat(cmd, tmp);
        }
        strcat(cmd, "' >> /tmp/");
        strcat(cmd, name);
        strcat(cmd, "\n");

        ssport_write(sp, cmd, strlen(cmd));
        process(i, size);
        usleep(10000);
    }
    process(size, size);
    ssport_close(sp);

    printf("\r\nDONE!\r\n");
    return 1;
}

MPro: Support 60Hz FPS

We are proud to announce that MPRO now supports a refresh rate of 60Hz.

show jpeg on 5inch screen

Please download and try the following: https://vocore.io/misc/v2scrctl.zip. Use the latest firmware and the screen_test.c file.

The main upgrade is that the MPRO firmware now supports baseline JPEG compression, which is typically much smaller than bitmap. For example, an 800×480 16-bit bitmap is approximately 800KB, but a high-quality JPEG image is only 100~200KB. This reduction in size can increase the refresh speed by 300%~500%, allowing us to easily achieve a 60Hz refresh rate.

Note: The software part(like Simhub) may still need some time to adjust, so this feature will take some time to be implemented for dashboard users.

MPRO: Partially Draw

To increase FPS for bigger screens, partially draw is necessary and important.

MPRO driver board now support this.

Before send the frame, need to setup a “window”, then data will only write to this window.

Here is example code(download full code at https://vocore.io/misc/v2scrctl-release.zip, tools/screen_test.partily.c)

uint8_t cmd3[] = {0x00, 0x2c, 0x20, 0x4e, 0x00, 0x00, 0x63, 0x00, 0x65, 0x00, 0x64, 0x00};
res = libusb_control_transfer(handle, 0x40, 0xb0, 0, 0, cmd3, sizeof(cmd3), 100);
res = libusb_bulk_transfer(handle, 0x02, partily_frame1, sizeof(partily_frame1), NULL, 100);

cmd3[6] = cmd3[8] = 250;
res = libusb_control_transfer(handle, 0x40, 0xb0, 0, 0, cmd3, sizeof(cmd3), 100);
res = libusb_bulk_transfer(handle, 0x02, partily_frame1, sizeof(partily_frame1), NULL, 100);

explain cmd3:

  • 0x00, 0x2c: write to memory command code.
  • 0x20, 0x4e, 0x00, 0x00: write size is 0x00004e20(20000) bytes, this is because our paritly draw image is 100×100 resolution, and bitmap16, so it is 100x100x2 = 20000bytes.
  • 0x63, 0x00: start position X, in example it is 0x0063(99) pixels.
  • 0x65, 0x00: start position Y, in example it is 0x0064(101) pixels.
  • 0x64, 0x00: image window width or line width, in example it is 0x65(100) pixels.
  • no image window height, it can be calculated from [write size] / [window width] / 2

After this call, it will write 100×100 image block to screen position left top corner = (99,101)

PS: another block at (250, 250).

VoCore2: OpenWrt 23.05 Sound Part

Finally sound part works. Thanks to contributor patches.

The problem is caused by DMA did not correctly stopped before I2S stop, then DMA write to invalid memory address then casued watch dog reset the hole system, no oops.

Patches has upload to: https://github.com/Vonger/vocore2/tree/master/openwrt.2305

OpenWrt source code patch openwrt.patch folder, linux kernel patch at kernel.sound folder, need to copy to target/linux/ramips/patches-5.15

https://github.com/Vonger/vocore2/blob/master/openwrt.2305/sound/patch-5.15/900-ASoC-soc-pcm-add-option-to-start-DMA-after-DAI.patch

In menuconfig, need to select kmod-mt7628-es8388, kmod-i2c-mt7628 etc… For simple just copy menu.config to .config in your openwrt folder, will compile everything.

VoCore2: OpenWrt 23.05 Part2

Continuing with my last blog, the sound part. Last time I found there was a problem, some kernel code was broken because I could patch and compile it but once I ran aplay the kernel would crash.

I checked openwrt 18 and openwrt 19, the patch worked well for both of them, but from openwrt 20, the latest version, none of them worked.

I compared their source code about the sound card main reference clock, its output 12M was normal; I2C, I2S, which were used to control and send data, this part was normal too; sound card part driver es8328.c and es8328-i2c.c both seemed fine to me. Only one doubt was the DMA driver, we sent data to memory and it carried data to I2S then the sound card played sound. One more thing was DMA driver was moved to staging in linux kernel, that meant somebody found the problem too. If DMA has any bug like writing data to a place that surprises the kernel, the unhappy kernel crashes with no apparent reason and reboots itself.

So its time to hack the linux kernel again…Good luck to me.

I think the DMA driver’s source code has not changed, but the linux kernel somehow has changed. That brought a new problem. The code is in drivers/staging/ralink-gdma/ralink-gdma.c, this linux kernel is 5.15.137.

6.8inch Screen CH32V003+WS2812 DEMO

In order to simplify the development of dashboards based on the VoCore MPRO screen, CH32V003, and WS2812, we have created a simple demo that is now available for order at vocore.io/store.

The shell was designed using FreeCAD. We are not experts in design, so please feel free to modify it. 🙂

Download here https://github.com/vonger/6IN8SHELL

Reference link: https://github.com/Vonger/V7B_WS2812B

Reference link: https://vonger.cn/?p=15457

back side
front side

Note: This demo is designed to show how MPRO works with WS2812 LEDs. I am not skilled in design, so it is not recommended for DDU users. However, if you wish to use it as a low-cost DDU, I cannot stop you. 🙂

Setup in Simhub: Devices => Add new device => Create standard device => Generic VoCore Screen with I2C LEDs

Note: if you have exists arduino LED profile, export then import to Generic VoCore Screen with I2C LEDs, it will work.

VoCore2: OpenWrt 23.05

It is pretty straight to use OpenWrt 23.05. It works very smoothly. If you do not need to customize such as default IP, WiFi default enable, almost do not need to patch anything.

  • WiFi — works normal, 72Mbps for one antenna.
  • Ethernet — works normal, 100Mbps.
  • USB 2.0 — works normal.
  • SD card — works normal, need to patch dts.
  • Sound — need to check.

note: patch sdcard, add the following code to end of mt7628an_vocore2.dts

&sdhci {
        mediatek,cd-poll;
        status = "okay";
};

PS: download feeds is very slow for openwrt, maybe it is because its source code do not add –depth 1. Patch ./scripts/feeds:157, add depth 1 to init_commit, after that, feed update speed increase 10 times. Or directly download from openwrt feeds, then move to openwrt/feeds folder then call ./script/feeds install -a