Screen: Firmware CHANGELOG(v0.23)

test compression and partial drawing. source code is partest.c in v2scrctl.zip.

The main upgrade in the new version v0.23 is LZ4 compression. With this compression and partial drawing, we can greatly increase the FPS, making it stable at 60Hz or even higher for high-resolution screens like 10-inch (1024×600). With VoCore and USBIP (VirtualHere), it is also possible to make the screen wireless via WiFi.

New firmware, upgrade tool and sample code, download at https://vocore.io/misc/v2scrctl.zip

PS: end of this month we will make a demo board with 3.4 inch round screen and wireless function.

vocore.io: the site is temporarily offline

🙁 Very bad, vocore.io is offline. I have no idea what is happening; it just won’t turn on (maybe physical damage). Over the past ten years, the server has been offline many times. Sometimes heavy snow crashes the power supply, sometimes floods get into the server room, and sometimes there is a shortage of power supply.

Double hot backup and automatic switching are very important. After the server recovers, I must find a good way to make it more stable. I cannot rely solely on the server provider.

For now, I need to spend several hours recovering the site backup to another server first.

PS: for new order please directly email to sales@vocore.io, our sales will help you handle it directly.

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.