Why NOT Open Source Hardware?

OpenSource Hardware is a trend in recently life or we could say, it is old fashion way. We are all glad to find it makes the world better.

But NOW I must talk on a serious topic: Why NOT Open Source Hardware?

Somebody may ask, is VoCore open source hardware?
Not at all, please give me five minutes to explain.

How to define an open source hardware?
First, let’s check open source software:
they are totally free to use, everybody could modify it, contribute to it, once you have the source code, it is totally under your control.

You might say, I cloned the Arduino from scratch, even from a hand-making PCB, and everything just works well;
Ye, you are right, you made the open source hardware absolutely. We can not agree more, Arduino is an real open source hardware.

NOW, some people is thinking, the hardware is f**king so easy, everybody could make it, just one PCB and some chips, there is nothing “high-tech”… (and might think: the VoCore developer is so black-hearted, the BOM cost is only 6~7USD but he just sell it for $20!!!) It is so easy for ME to reduce the cost!

Then, he started…but failed.

Unfortunately, this is a true story. Even I tried my best to stop this buddy but he do not listen, I try to help him production(PCB is just trash if not working, not friendly to our Earth…), but he rejected because my way will cost much more money…

(I know it very well, many hardware people in ShenZhen force on BOM cost. The lower BOM cost means we can get more money, so why not?)

Here are some issues:
1. PCB quality is very low, for example, solder even covers part of the pad, it should be NG in most factory but cheaper price just let them pass.
2. the impedance matching is bad, a good PCB must be flat, and has a limit for its bend.
3. Bad SMT, some parts are short connected, and some are totally not connected.
4. Bad materials and chips. The chip price is incredible low, the small batch even lower than my mass order…
In ShenZhen, it is so easy to find recycle chips(especially in alibaba & 1688 & taobao), the recycle ones are from used routers(junk), some of the chips still working, but pads are oxidized, maybe work at factory but once client uses it with heavy load, the heat will broke the connection. VoCore new production must use new chips(out of chip factory < six months with vacuum packaging).

PS: that’s why a lot of cheap production from ShenZhen only have a short life. It is not about “Made in China” but “Made by Dishonest”.

And many many details are not in books and hard to show in blog, they are experience of the production engineer.

That is still NOT the end…the story is usually like this:


you find it is hard to get contact with good providers, I introduce them to you;
you find you need a test application to test the production, I send you my code;
you find you need a test bench to test the production, but make one is hard, no problem, I lend mine to you;
you find you can not calibrate the wireless, I can help you;
you find there are tons of Not Good production, do not know how to lead the worker to fix them, I give you a hand.
But at end, you find the cost is doubled or tripled compared with my mass production, you…

PS: actually I can not help even from first steps, that costs too much time. :)

That’s Why NOT Open Source Hardware:
A REAL COMPLEX hardware can not be simply opened as software, it is an art of production, need time to try, to make mistake, need sweat but worth it.

Just hoping the public sch and layout could help people understand how it works, makes it easy to develop board base on it, improves your exists production, provides an example for hardware engineers, also might have some issues notified the people do not make the same. :)

ONE THING FOR SURE: VoCore and VoCore2 are ALWAYS OPEN, but never an open source hardware.

VoCore2: New Features

Coming soon, this June :)

## Interfaces:

1. export all GPIOs. (around 30)
2. export 3x UARTs.
3. export 1x I2C.
4. export 1x I2S.
5. export 1x reference clock.
6. export 1x USB 2.0.
7. export 1x PCIe 1.1
8. export 1x high speed SPI (max to 40Mbps)
9. export 2x antenna (UL.F) for 802.11n (max to 300Mbps)
10. input 3.6~6.0V, output 1.8V, 3.3V.
11. export 2x 10/100 ethernet port.
12. export 1x SDXC (allow high speed SD/TF card)
13. export 1x SPI slave
14. export 2x PWM (hardware PWM)

## Parameters:

* CPU: 580MHz MIPS.
* RAM: 64MB/128MB.(two versions, bigger memory special for who love python :) )
* NORMAL POWER CONSUME: 74mA/5V (wifi on, no data transfer)
* PEAK POWER CONSUME: 233mA/5V (max speed cpu and wireless)

## Compare with VoCore v1.0:

* faster cpu speed.
* bigger RAM.
* lower power consume.
* better wifi signal.
* more interfaces.

We are busy on preparing the mass production, fixing & updating necessary drivers; preorder chips; prepare test process for factory; product the beta version…etc, many works left to do.
Planing stop making VoCore at May, focus on better version VoCore2.
Once June released the mass production, we will focus on software part. Anyway, VoCore is always a geek’s toy.

VoCore2: UART2 for openwrt

Now uboot part works, we need to make openwrt serial also output to UART2.

PS: weird issue, I find /dev/mem gone…is Linux 4.4.6 removed it?

My code based on trunk@49094. It is a develop openwrt version also contains many bugs. :) If my code works please help me commit to openwrt.

If we do not modify anything, just flash uboot firmware to VoCore2, the serial log will end here.

U-Boot 1.1.3 (Mar 28 2016 - 22:54:05)

Board: Ralink APSoC DRAM:  64 MB
relocate_code Pointer at: 83fb8000
Software System Reset Occurred
flash manufacture id: c8, device id 40 18
find flash: GD25Q128C
*** Warning - bad CRC, using default environment

Ralink UBoot Version:
ASIC 7628_MP (Port5<->None)
DRAM component: 512 Mbits DDR, width 16
DRAM bus: 16 bit
Total memory: 64 MBytes
Flash component: SPI Flash
Date:Mar 28 2016  Time:22:54:05
icache: sets:512, ways:4, linesz:32 ,total:65536
dcache: sets:256, ways:4, linesz:32 ,total:32768 

 ##### The CPU freq = 575 MHZ #### 
 estimate memory size =64 Mbytes
RESET MT7628 PHY!!!!!!
Please choose the operation: 
   1: Load system code to SDRAM via TFTP. 
   2: Load system code then write to Flash via TFTP. 
   3: Boot system code via Flash (default).
   4: Entr boot command line interface.
   7: Load Boot Loader code then write to Flash via Serial. 
   9: Load Boot Loader code then write to Flash via TFTP. 
3: System Boot system code via Flash.
## Booting image at bc050000 ...
   Image Name:   MIPS OpenWrt Linux-4.4.6
   Image Type:   MIPS Linux Kernel Image (lzma compressed)
   Data Size:    1270118 Bytes =  1.2 MB
   Load Address: 80000000
   Entry Point:  80000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80000000) ...
## Giving linux memsize in MB, 64

Starting kernel ...

[    0.000000] Linux version 4.4.6 (vocore@ubuntu) (gcc version 5.3.0 (OpenWrt GCC 5.3.0 r49094) ) #7 Fri Apr 1 18:35:11 UTC 2016
[    0.000000] Board has DDR2
[    0.000000] Analog PMU set to hw control
[    0.000000] Digital PMU set to hw control
[    0.000000] SoC Type: MediaTek MT7628AN ver:1 eco:2
[    0.000000] bootconsole [early0] enabled
[    0.000000] CPU0 revision is: 00019655 (MIPS 24KEc)
[    0.000000] MIPS: machine is VoCore2 64MB
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 04000000 @ 00000000 (usable)
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
[    0.000000] Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
[    0.000000] Kernel command line: console=ttyS0,57600 rootfstype=squashfs,jffs2
[    0.000000] PID hash table entries: 256 (order: -2, 1024 bytes)
[    0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Writing ErrCtl register=00073670
[    0.000000] Readback ErrCtl register=00073670
[    0.000000] Memory: 60844K/65536K available (2859K kernel code, 132K rwdata, 692K rodata, 148K init, 195K bss, 4692K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS:256
[    0.000000] intc: using register map from devicetree
[    0.000000] add clock for 10000d00.uart1, rate = 40000000
[    0.000000] add clock for 10000e00.uart2, rate = 40000000
[    0.000000] add clock for cpu, rate = 580000000
[    0.000000] add clock for 10000100.timer, rate = 40000000
[    0.000000] add clock for 10000120.watchdog, rate = 40000000
[    0.000000] add clock for 10000b00.spi, rate = 193333333
[    0.000000] add clock for 10000b40.spi, rate = 193333333
[    0.000000] add clock for 10000c00.uartlite, rate = 40000000
[    0.000000] add clock for 10180000.wmac, rate = 40000000
[    0.000000] CPU Clock: 580MHz
[    0.000000] clocksource_probe: no matching clocksources found
[    0.000000] clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 6590553264 ns
[    0.000011] sched_clock: 32 bits at 290MHz, resolution 3ns, wraps every 7405115902ns
[    0.015349] Calibrating delay loop... 385.84 BogoMIPS (lpj=1929216)
[    0.080520] pid_max: default: 32768 minimum: 301
[    0.089782] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.102736] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.122279] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.141778] pinctrl core: initialized pinctrl subsystem
[    0.152723] NET: Registered protocol family 16
[    0.179323] mt7621_gpio 10000600.gpio: registering 32 gpios
[    0.190412] mt7621_gpio 10000600.gpio: registering 32 gpios
[    0.201416] mt7621_gpio 10000600.gpio: registering 32 gpios
[    0.213941] clocksource: Switched to clocksource MIPS
[    0.225338] NET: Registered protocol family 2
[    0.234765] TCP established hash table entries: 1024 (order: 0, 4096 bytes)
[    0.248470] TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
[    0.260983] TCP: Hash tables configured (established 1024 bind 1024)
[    0.273632] UDP hash table entries: 256 (order: 0, 4096 bytes)
[    0.285086] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[    0.297732] NET: Registered protocol family 1
[    0.307657] futex hash table entries: 256 (order: -1, 3072 bytes)
[    0.338516] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.349983] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
[    0.372014] io scheduler noop registered
[    0.379693] io scheduler deadline registered (default)
[    0.390672] Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
[    0.404112] rt2880-pinmux pinctrl: invalid group "spis" for function "pwm"
[    0.417827] console [ttyS0] disabled
[    0.424820] 10000e00.uart2: ttyS0 at MMIO 0x10000e00 (irq = 30, base_baud = 2500000) is a 16550A
[    0.442151] console [ttyS0] enabled
[    0.442151] console [ttyS0] enabled
[    0.455889] bootconsole [early0] disabled
[    0.455889] bootconsole [early0] disabled
[    0.473336] spi-mt7621 10000b00.spi: sys_freq: 193333333
[    0.487529] m25p80 spi32766.0: using chunked io (size=32)
[    0.498290] m25p80 spi32766.0: gd25q128 (16384 Kbytes)
[    0.508501] 4 ofpart partitions found on MTD device spi32766.0
[    0.520053] Creating 4 MTD partitions on "spi32766.0":
[    0.530233] 0x000000000000-0x000000030000 : "u-boot"
[    0.541846] 0x000000030000-0x000000040000 : "u-boot-env"
[    0.554307] 0x000000040000-0x000000050000 : "factory"
[    0.566168] 0x000000050000-0x000000800000 : "firmware"
[    0.603038] 2 uimage-fw partitions found on MTD device firmware
[    0.614797] 0x000000050000-0x0000001861a6 : "kernel"
[    0.626261] 0x0000001861a6-0x000000800000 : "rootfs"
[    0.637985] mtd: device 5 (rootfs) set to be root filesystem
[    0.649351] 1 squashfs-split partitions found on MTD device rootfs
[    0.661606] 0x000000370000-0x000000800000 : "rootfs_data"
[    0.683669] rt3050-esw 10110000.esw: link changed 0x00
[    0.695347] mtk_soc_eth 10100000.ethernet: generated random MAC address fe:67:bf:04:9d:38
[    0.712449] mtk_soc_eth 10100000.ethernet eth0: mediatek frame engine at 0xb0100000, irq 5
[    0.729378] mt7621_wdt 10000120.watchdog: Initialized
[    0.740958] NET: Registered protocol family 10
[    0.753409] NET: Registered protocol family 17
[    0.762371] bridge: automatic filtering via arp/ip/ip6tables has been deprecated. Update your scripts to load br_netfilter if you need this.
[    0.787379] 8021q: 802.1Q VLAN Support v1.8

Now my fix( as dirty as always 😀 )
1. modify MIWIFI-NANO.dts(I did not create new VoCore2.dts to make test easier)

+++ b/target/linux/ramips/dts/MIWIFI-NANO.dts
@@ -3,11 +3,11 @@
 /include/ "mt7628an.dtsi"
 / {
-       compatible = "xiaomi,MiWifi Nano", "mediatek,mt7628an-soc";
-       model = "MiWiFi Nano";
+       compatible = "vocore2,vocore", "mediatek,mt7628an-soc";
+       model = "VoCore2 64MB";
        chosen {
-               bootargs = "console=ttyS0,115200";
+               bootargs = "console=ttyS0,57600";
        memory@0 {
@@ -18,7 +18,7 @@
        pinctrl {
                state_default: pinctrl0 {
                        gpio {
-                               ralink,group = "refclk", "wled", "gpio";
+                               ralink,group = "refclk", "gpio";
                                ralink,function = "gpio";
@@ -87,5 +87,13 @@
+               uart2@e00 {
+                        status = "okay";
+               };
+               pwm@5000 {
+                        status = "okay";
+               };
diff --git a/target/linux/ramips/dts/mt7628an.dtsi b/target/linux/ramips/dts/mt7628an.dtsi
index e120e56..819ac82 100644
--- a/target/linux/ramips/dts/mt7628an.dtsi
+++ b/target/linux/ramips/dts/mt7628an.dtsi
@@ -170,6 +170,8 @@
                        pinctrl-names = "default";
                        pinctrl-0 = <&uart0_pins>;
+                       status = "disabled";
                uart1@d00 {
@@ -301,8 +303,8 @@
                uart2_pins: uart2 {
                        uart2 {
-                               ralink,group = "uart2";
-                               ralink,function = "uart2";
+                               ralink,group = "spis";
+                               ralink,function = "pwm";

2. modify /linux-4.4.6/arch/mips/ralink/mt7620.c:407

		ralink_clk_add("10000d00.uartlite", periph_rate);
		ralink_clk_add("10000e00.uartlite", periph_rate);

change to

		ralink_clk_add("10000d00.uart1", periph_rate);
		ralink_clk_add("10000e00.uart2", periph_rate);

This just works, but I do not think it is the best way. We should use ttyS2 in dts, but not ttyS0. I still need time to understand how pinctrl works. :)

VoCore2: UART2 for uBoot

New VoCore2 small size blocked UART0 and UART1, so I have to use UART2 for debug.
From datasheet, we have two plans for UART2:

The only valid plan for VoCore2 is SPIS_MODE.
Default uboot is using UART0 as default console port, we must change it.

MTK uboot source code already have it, we just need to modify two lines.
1. serial.h, change RT2880_UART1 in macro MT7628_ASIC_BOARD to RT2880_UART3.
This is to tell uboot, we will use UART3 control register(it is UART2 on chip).
2. serial.c, add one line in function serial_setbrg, ra_or(RALINK_SYSCTL_BASE + 0x0060, (1<<2|1<<3)); This is to change uart2 pins from gpio to real uart in system control. After this, just simply "make menuconfig", remember to choose "ETH One Port", then "make", everything will work. PS: uboot autoconf has a bug in config.in, have to change ETH_ONE_PORT_ONLY to CONFIG_ETH_ONE_PORT_ONLY.

VoCore2: Update

First, we made four versions of beta version, it is in PCB factory now. In beta version we want to pick the best performance one.

The busy days has passed finally. :)

Screen Shot 2016-03-29 at 10.08.56

And also the new site mockup, its backend are totally machine..

Last, new VoCore2+Dock ready, photo will come soon. It contains audio, tf card slot, ethernet, usb, usb2ttl on board, but just same size as current VoCore+Dock.
We also plan to make another ‘super’ version, add a 320×240 screen to it, able to run dosbox. :)

PS: sorry for the junk post in the forum…I must click ‘approve’ instead of ‘disapprove’ by mistake T-T

VoCore2: Wireless


VoCore2 wireless is finally working, but I think there still have some driver issue, looks like only one antenna works, another is still not.
Same place compare to another router HiWiFi, this one has two big antennas :)


RSSI is not as good as the one with big antenna, but TX rate is not bad. Next step is to use special device to check and adjust antenna circuit, modify factory setting part to increase antenna power output.

Beta will come soon, please email to support@vocore.io for preorder if you want to join the test. 😀

VoCore: I2S Sound Card WM8960G 4(End)

Now the tutorial continues, as I promised :)

1. use this firmware, download here: Test Firmware
(This firmware is just used to make sure your VoCore do not have other drivers stop you install the new one. It installed enough tools for this tutorial, so you do not have to find it online)

2. flash this firmware to your VoCore.

3. get two files here:package uncompress and upload them to VoCore /tmp/ folder.
“vocore_gdma.ko” is the driver.
“out” is the test data file, just a part of a wav file, 44100Hz, 16bits, stereo.

4. copy and run the following magic command.

i2cset -y 0 0x1a 0x1e 0x00
i2cset -y 0 0x1a 0x0e 0x02
i2cset -y 0 0x1a 0x08 0x05
i2cset -y 0 0x1a 0x68 0x07
i2cset -y 0 0x1a 0x6a 0x86
i2cset -y 0 0x1a 0x6c 0xc2
i2cset -y 0 0x1a 0x6e 0x26
i2cset -y 0 0x1a 0x32 0xc0
i2cset -y 0 0x1a 0x35 0xe1
i2cset -y 0 0x1a 0x5e 0x0c
i2cset -y 0 0x1a 0x45 0x00
i2cset -y 0 0x1a 0x4b 0x00
i2cset -y 0 0x1a 0x0a 0x00
i2cset -y 0 0x1a 0x05 0xff
i2cset -y 0 0x1a 0x07 0xff

4.1. insert driver to kernel.

insmod /tmp/vocore-gdma.ko

4.2. send data to audio buffer.

cat /tmp/out > /sys/devices/10000000.palmbus/10002800.gdma/data

5. now, everything is ready, final command to play “out”.

echo 1 > /sys/devices/10000000.palmbus/10002800.gdma/play

6. After 5, you can heard some “music” output from your headphone, just a 5.9 seconds dead loop. Call this command to stop it.

echo 0 > /sys/devices/10000000.palmbus/10002800.gdma/play

PS: the music slice is from alan, æ‚Čしみはé›Șă«çœ ă‚‹, a lovely music :)
PSS: the music is weird somewhere…I think I must make some mistake when setting up the wm8960…(i2cset command)

But anyway, there is some music output at last. 😀
Here is the driver source code:vocore-gdma.c

Here is app from Wutong, did not use DMA interrupts, so you can run it under user mode.

VoCore Camera H264 FHD

PS: Sorry about first batch, the plastic dock is not matched very well, current batch fixed such problem. Please contact support@vocore.io to replace your plastic dock.
PSS: better to use 720p/15fps format or less for long time monitor usage(>= 30 minutes).

VoCore FHD H264 Camera Support

Firmware download here: Download

Source code for Linux here: uvc_3.10

1. modify makefile

PWD:=$(shell pwd)

CCFLAGS += -I $(KDIR)/include/

$(TARGET)-objs  := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \
                  uvc_status.o uvc_isight.o uvc_debugfs.o nalu.o


        make $(CCFLAGS) -C $(KDIR) M=$(PWD) ARCH=mips CROSS_COMPILE=mipsel-openwrt-linux- modules
        rm -rf *.o *.ko *.mod.* modules.* Module.* .tmp_versions .*.*.cmd

2. make it to create sonix_uvcvideo.ko
3. run on VoCore

opkg install kmod-input-core kmod-video-uvc
insmod sonix_uvcvideo.ko

/dev/video0 is mjpeg stream, /dev/video1 is h264 stream.
also you will find UAC, the 8K onboard microphone in /dev/ folder.

ls /dev/video*
v4l2-ctl --list-formats -d /dev/video0
v4l2-ctl --list-formats -d /dev/video1

opkg install v4l-utils

root@OpenWrt:~# v4l2-ctl --list-formats -d /dev/video0
    Index       : 0
    Type        : Video Capture
    Pixel Format: 'MJPG' (compressed)
    Name        : MJPEG

    Index       : 1
    Type        : Video Capture
    Pixel Format: 'YUYV'
    Name        : YUV 4:2:2 (YUYV)
root@OpenWrt:~# v4l2-ctl --list-formats -d /dev/video1
    Index       : 0
    Type        : Video Capture
    Pixel Format: 'H264' (compressed)
    Name        : H.264

VoCore Dock2: Package Update

Recently I get some complain about the broken VoCore + Dock during the shipping especially the package to US.
The post office said currently there are too many packages already exceeds their limit, so it is normal some packages are broken…:'(
All new packages will ship with a plastic case, to avoid recently “violence delivery”.
And if your dock is broken during the shipping, please email to support@vocore.io with picture, we will ship a new replacement.