
Author: scruss
-
Trumpeter swan got harmonics

Isolated Trumpeter swan «parp» call, recorded at Bluffer’s Park, Toronto at 2025-01-09, 13:41 via Merlin app on Google Pixel 8 -
BASIC-52 on tiny CH552 boards via Linux
draft post, published for usefulness not polish
- Hackaday project that introduced me to the CH552 and BASIC-52: Single Chip Computer | Hackaday.io
- Boards that I’ve got this working with:
- CH552 Stick from DeqingSun/ch55xduino (DIY, surface-mount);
- WeAct Studio CH552T Mini Core Board;
- WAVGAT CH552G core board.
- You’ll need an external USB UART with 5 V power, as this port doesn’t support serial over the USB
- Project source (yes, it’s a Google Drive link, and any docs are in Japanese): CH55x. If that doesn’t work, the original redirect is from CH552Eでモニタプログラムを動かしてみました | きょうのかんぱぱ. If neither of those work, here’s my download of the archive: CH552T&G-20240805T141304Z-001.zip
- Binary file (zip): basic52s.bin (hiyodori5, version 7th May 2023, converted from hex so you don’t have to mess with srec_cat or makebin)
- Build cjacker/ch55x-isptool to upload the code (which doesn’t accept hex)
- Plug in the CH552 board. You may have to do something with the boot/reset button to make it turn up as the right USB ID (4348:55e0 WinChipHead).
- Program the board:
sudo ch55xisptool basic52s.bin - Disconnect the board, and wire it up to the USB UART (5 V, GND, TX → RXD [P3.0], RX → TXD [P3.1])
- Hit return a few times to get a prompt
- PWM is on P1.2, INT1 is on P3.3. See Hackaday project to see how to access I²C, and also do things with SFR values using RDSFR / WRSFR. PORT3 is at SFR(0B0H)
please ignore the following for now …
Who wouldn’t want to run a solid BASIC interpreter on a $3 development board? So maybe there are a couple of drawbacks:
- there’s no way to save the program to non-volatile storage: you have to be connected through a serial terminal at all times; and
- you’ve got about 600 bytes for the whole program, with no way to expand it.
Despite these limitations, there’s some futile fun to be had. I’ll show you how to flash BASIC-52 onto one of these development boards, and give a quick intro to what you can do with it.
BASIC-52
Intel released the first version of BASIC-52 for their 8051 family of microcontrollers in 1984. They produced a chip (8052AH-BASIC) with the interpreter burnt into mask ROM in 1985. The source code was released into the public domain, and various features such as I²C support were added by the community around 2000.
As befits an embedded language, BASIC-52 supports pin management, timers and interrupts. It’s also a fairly full-featured BASIC interpreter with floating point support and mostly familiar keywords and functions. Because it’s designed for very limited memory use, its string handling is quite unlike any other BASIC dialect. It has one character array that you can treat as a string, and a few functions to work with characters, but that’s about all.
A most useful reference is Intel’s MCS BASIC-52 Versions 1 & 1.1 Operating and Reference Manual. Another helpful guide is Jan Axelson’s The Microcontroller Idea Book. I found out about both of these references from Single Chip Computer — Hackaday.io, which also introduced me the possibilities of running BASIC-52 on the CH552.
CH552

Deqing Sun’s CH552 Stick, from the ch55xduino project You might know WCH (aka QinHeng Electronics) from their inexpensive CH341 USB serial adapters and other interface boards. What you might not realize is that all of their older interface chips are based on an optimized 8051 design
-
Cheap NeoPixels at the Dollar Store
Exhibit A:

also known as “Monster BASICS Sound reactive RGB+IC Color Flow LED strip”. It’s $5 or so at Dollarama, and includes a USB cable for power and a remote control. It’s two metres long and includes 60 RGB LEDs. Are these really super-cheap NeoPixel clones?
I’m going to keep the USB power so I can power it from a power bank, but otherwise convert it to a string of smart LEDs. We lose the remote control capability.
Pull back the heatshrink at the USB end:

… and there are our connectors. We want to disconnect the blue Din (Data In) line from the built in controller, and solder new wires to Din and GND to run from a microcontroller board.

Maybe not the best solder job, but there are new wires feeding through the heatshrink and soldered onto the strip.

Here’s the heatshrink pushed back, and everything secured with a cable tie.
Now to feed it from standard MicroPython NeoPixel code, suitably jazzed up for 60 pixels.

A pretty decent result for $5!
-
Brother Canada laser cartridge return label
April 2025: got a slightly different label, so maybe use this:
So you bought that Brother laser printer like everyone told you to. And now it’s out of toner, so you replaced the cartridge. If you were in the USA, you could return the cartridge for free using the included label. But in Canada … it’s a whole deal including registering with Brother and giving away your contact details and, and, and …
I’m pretty sure this is a generic label, since:
- the file is dated sometime in 2023, and wasn’t generated directly for my download;
- I got a different tracking number when I handed the thing in at the post office.
But if they do complain, you know what to do: brother.ca/en/environment
-
Thousand Days: Concept
reference copy: Thousand Days: Concept on github.
Stewart Russell – scruss.com — 2024-03-26, at age 19999 days …
Summary
One’s thousand day(s) celebration occurs every thousand days of a person’s life. They are meant to be a recognition of getting this far, and are celebrated at the person’s own discretion.
Who is this for?
- Maybe your birthday’s on a day associated with an unpleasant event. Your thousand day will never coincide with your birthday.
- Maybe your birthday’s in the middle of winter, or in another part of the year that you’re not keen on. Your thousand day is every 2 years and 3 seasons, so it shifts back by a season every time it happens.
Quantities and scale
1000 days is approximately:
- 2.738 years
- 2 years 269 days
- 2 years 8.85 months
- 2 years, 3 seasons.
4000 days is just shy of 11 years.
Disadvantages
Compared to regular birthdays, thousand days:
- must be calculated; they’re not intuitive when they’re going to happen. But we have computers and calendar reminders for that …
- can be used to work out your actual date of birth, if someone knows that you’re going to be x000 days old on a particular day. It’s possible to know someone’s birthday, but not know their age.
Implementations
Web
My ancient Your 1000 Day Birthday Calculator, first published in 2002 and untouched since 2010.
Shell
So it turns out that GNU date can handle arbitrary date maths quite well. For example:
date --iso-8601=date --date="1996-11-09 + 10000 days"
returns 2024-03-27.
Other Ways
Excel or any other spreadsheet will do, too. Although not for too many years back
People with the same thousand day as you
This is an idea for finding people who have a thousand day on the same day as you. I suggest using 1851-10-01 as a datum, because:
- nothing particularly interesting happened that day;
- it’s conveniently 43000 days before my birthday.
then calculate
( (birth_date - 1851-10-01) mod 1000 ) + 1
This results in a number 1 – 1000. Everyone with the same number shares a 1000 day birthday with you.
Why not 0 – 999?
- No-one deserves to be a zero;
- Wouldn’t be much of a thousand day if it only went up to 999, would it?
Incomplete list of people with day = 1
There are more, but these were found from Wikipedia’s year pages
- Momo Hirai, born 1996-11-09 (-10000 days)
- Memphis Depay, born 1994-02-13 (-9000 days)
- Mikhail Surenovich Aloyan, born 1988-08-23 (-7000 days)
- Segundo Cernadas, born 1972-03-20 (-1000 days)
- Sissel Kyrkjebø, born 1969-06-24 (0 days)
- Maria Canals-Barrera, born 1966-09-28 (+1000 days)
- Pernell Whitaker, born 1964-01-02 (+2000 days)
- [DONDI](https://en.wikipedia.org/wiki/Dondi_(graffiti_artist%29), born 1961-04-07 (+3000 days)
- Richard Legendre, born 1953-01-19 (+6000 days)
- Arnold Schwarzenegger, born 1947-07-30 (+8000 days)
- Keith Emerson, born 1944-11-02 (+9000 days)
- Harvey Keitel, born 1939-05-13 (+11000 days)
- Agnès Varda, born 1928-05-30 (+15000 days)
- Shoista Mullojonova, born 1925-09-03 (+16000 days)
- Lucian Freud, born 1922-12-08 (+17000 days)
- Huang Feili, born 1917-06-17 (+19000 days)
- Kikuko, Princess Takamatsu, born 1911-12-26 (+21000 days)
- Walter O’Malley, born 1903-10-09 (+24000 days)
- León de Greiff, born 1895-07-22 (+27000 days)
- Geoffrey Fisher, born 1887-05-05 (+30000 days)
- Sara Teasdale, born 1884-08-08 (+31000 days)
- Lee de Forest, born 1873-08-26 (+35000 days)
- Carl Nielsen, born 1865-06-09 (+38000 days)
Licence
🅭 2024, Stewart Russell, scruss.com
This work is licensed under CC BY-SA 4.0.
There are no trademarks, patents, official websites, social media or official anythings attached to this concept. Please take the idea and do good with it.
So why aren’t you implementing this further?
I’ve had this idea kicking around my head for at least the last 20 years. For $REASONS, it turns out I’m not very good at implementing stuff. I’d far rather someone else took this idea and ran with it than let it sit undeveloped.
-
We used to have to *wait* for our memes …
It must be Wednesday somewhere … If you really must try this on your on Amstrad CPC:
-
“… that Chinese instruction manual font”
(this is an old post from 2021 that got caught in my drafts somehow)
Mike asked:
To which I suggested:

Not very helpful links, more of a thought-dump:
- Why does Chinese printing of Latin characters always use the same font? – writing fonts curiosity | Ask MetaFilter
- The Roman typefaces used in Chinese and Japanese text | Hacker News
First PostScript font: STSong (华文宋体) was released in 1991, making it the first PostScript font by a Chinese foundry [ref: Typekit blog — Pan-CJK Partner Profile: SinoType]. But STSong looks like Garamond(ish).
![A table of the latin characters @, A-Z, [, \, ], ^, _, `, a-z and { in STSong half-width latin, taken from fontforge](https://scruss.com/wordpress/wp-content/uploads/2024/01/Screenshot-from-2024-01-07-11-44-09.png)
Maybe source: GB 5007.1-85 24×24 Bitmap Font Set of Chinese Characters for Information Exchange. Originally from 1985, this is a more recent version: GB 5007.1-2010: Information technology—Chinese ideogram coded character set (basic set)—24 dot matrix font.

-
The Potato
… is a thing to help soldering DIN connectors. I had some made at JLCPCB, and will have them for sale at World of Commodore tomorrow.

Sven Petersen’s “The Potato” – front. DIN7 connector not included 
Sven Petersen’s “The Potato” – back You can get the source from svenpetersen1965/DIN-connector_soldering-aid-The-Potato. I had the file Rev. 0/Gerber /gerber_The_Potato_noFrame_v0a.zip made, and it seems to fit connector pins well.
Each Potato is made up of two PCBs, spaced apart by a nylon washer and held together by M3 nylon screws.
-
can we…?
This is a mini celebratory post to say that I’ve fixed the database encoding problems on this blog. It looks like I will have to go through the posts manually to correct the errors still, but at least I can enter, store and display UTF-8 characters as expected.
“? µ ° × — – ½ ¾ £ é?êè”, he said with some relief.
Postmortem: For reasons I cannot explain or remember, the database on this blog flipped to an archaic character set: latin1, aka ISO/IEC 8859-1. A partial fix was effected by downloading the entire site’s database backup, and changing all the following references in the SQL:
- CHARSET=latin1 → CHARSET=utf8mb4
- COLLATE=latin1_german2_ci → COLLATE=utf8mb4_general_ci
- COLLATE utf8mb4_general_ci → COLLATE utf8mb4_general_ci
- latin1_general_ci → utf8mb4_general_ci
- COLLATE latin1_german2_ci → COLLATE utf8mb4_general_ci
- CHARACTER SET latin1 → CHARACTER SET utf8mb4
For additional annoyance, the entire SQL dump was too big to load back into phpmyadmin, so I had to split it by table. Thank goodness for awk!
#!/usr/bin/awk -f BEGIN { outfile = "nothing.sql"; } /^# Table: / { # very special comment in WP backup that introduces a new table # last field is table_name, # which we use to create table_name.sql t = $NF gsub(/`/, "", t); outfile = t ".sql"; } { print > outfile; }The data still appears to be confused. For example, in the post Compose yourself, Raspberry Pi!, what should appear as “That little key marked “Compose”” appears as “That little key marked “Composeâ€Â”. This isn’t a straight conversion of one character set to another. It appears to have been double-encoded, and wrongly too.
Still, at least I can now write again and have whatever new things I make turn up the way I like. Editing 20 years of blog posts awaits … zzz
-
Autumn in Canada: NAPLPS
NAPLPS rendered in PP3 My OpenProcessing demo “autumn in canada”, redone as a NAPLPS playback file. Yes, it would have been nice to have outlined leaves, but I’ve only got four colours to play with that are vaguely autumnal in NAPLPS’s limited 2-bit RGB.
Played back via dosbox and PP3, with help from John Durno‘s very useful Displaying NAPLPS Graphics on a Modern Computer: Technical Note.
This file only displays 64 leaves, as more leaves caused the emulated Commodore 64 NAPLPS viewer I was running to crash.
-
The glorious futility of generating NAPLPS in 2023
Yeah! Actual real NAPLPS made by me! NAPLPS — an almost-forgotten videotex vector graphics format with a regrettable pronunciation (/nap-lips/, no really) — was really hard to create. Back in the early days when it was a worthwhile Canadian initiative called Telidon (see Inter/Access’s exhibit Remember Tomorrow: A Telidon Story) it required a custom video workstation costing $$$$$$. It got cheaper by the time the 1990s rolled round, but it was never easy and so interest waned.
I don’t claim what I made is particularly interesting:

suspiciously canadian but even decoding the tutorial and standards material was hard. NAPLPS made heavy use of bitfields interleaved and packed into 7 and 8-bit characters. It was kind of a clever idea (lower resolution data could be packed into fewer bytes) but the implementation is quite unpleasant.
A few of the references/tools/resources I relied on:
- The NAPLPS: videotex/teletext presentation level protocol syntax standard. Long. Quite dull and abstract, but it is the reference
- The 1983 BYTE Magazine article series NAPLPS: A New Standard for Text and Graphics. Also long and needlessly wordy, with digressions into extensions that were never implemented. Contains a commented byte dump of an image that explains most concepts by example
- Technical specifications for NAPLPS graphics — aka NAPLPS.ASC. A large text file explaining how NAPLPS works. Fairly clear, but the ASCII art diagrams aren’t the most obvious
- TelidonP5 — an online NAPLPS viewer. Not perfect, but helpful for proofing work
- Videotex – NAPLPS Client for the Commodore 64 Archived — a terminal for the C64 that supports (some) NAPLPS. Very limited in the size of file it can view
- John Durno has spent years recovering Telidon / NAPLPS works. He has published many useful resources on the subject
Here’s the fragment of code I wrote to generate the NAPLPS:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # draw a disappointing maple leaf in NAPLPS - scruss, 2023-09 # stylized maple leaf polygon, quite similar to # the coordinates used in the Canadian flag ... maple = [ [62, 2], [62, 35], [94, 31], [91, 41], [122, 66], [113, 70], [119, 90], [100, 86], [97, 96], [77, 74], [85, 114], [73, 108], [62, 130], [51, 108], [39, 114], [47, 74], [27, 96], [24, 86], [5, 90], [11, 70], [2, 66], [33, 41], [30, 31], [62, 35], ] def colour(r, g, b): # r, g and b are limited to the range 0-3 return chr(0o74) + chr( 64 + ((g & 2) << 4) + ((r & 2) << 3) + ((b & 2) << 2) + ((g & 1) << 2) + ((r & 1) << 1) + (b & 1) ) def coord(x, y): # if you stick with 256 x 192 integer coordinates this should be okay xsign = 0 ysign = 0 if x < 0: xsign = 1 x = x * -1 x = ((x ^ 255) + 1) & 255 if y < 0: ysign = 1 y = y * -1 y = ((y ^ 255) + 1) & 255 return ( chr( 64 + (xsign << 5) + ((x & 0xC0) >> 3) + (ysign << 2) + ((y & 0xC0) >> 6) ) + chr(64 + ((x & 0x38)) + ((y & 0x38) >> 3)) + chr(64 + ((x & 7) << 3) + (y & 7)) ) f = open("maple.nap", "w") f.write(chr(0x18) + chr(0x1B)) # preamble f.write(chr(0o16)) # SO: into graphics mode f.write(colour(0, 0, 0)) # black f.write(chr(0o40) + chr(0o120)) # clear screen to current colour f.write(colour(3, 0, 0)) # red # *** STALK *** f.write( chr(0o44) + coord(maple[0][0], maple[0][1]) ) # point set absolute f.write( chr(0o51) + coord(maple[1][0] - maple[0][0], maple[1][1] - maple[0][1]) ) # line relative # *** LEAF *** f.write( chr(0o67) + coord(maple[1][0], maple[1][1]) ) # set polygon filled # append all the relative leaf vertices for i in range(2, len(maple)): f.write( coord( maple[i][0] - maple[i - 1][0], maple[i][1] - maple[i - 1][1] ) ) f.write(chr(0x0F) + chr(0x1A)) # postamble f.close()There are a couple of perhaps useful routines in there:
colour(r, g, b)spits out the code for two bits per component RGB. Inputs are limited to the range 0–3 without error checkingcoord(x, y)converts integer coordinates to a NAPLPS output stream. Best limited to a 256 × 192 size. Will also work with positive/negative relative coordinates.
Here’s the generated file:
-
SYN6288 TTS board from AliExpress
After remarkable success with the SYN-6988 TTS module, then somewhat less success with the SYN-6658 and other modules, I didn’t hold out much hope for the YuTone SYN-6288, which – while boasting a load of background tunes that could play over speech – can only convert Chinese text to speech

as bought from quason official store: SYN6288 speech synthesis module The wiring is similar to the SYN-6988: a serial UART connection at 9600 baud, plus a Busy (BY) line to signal when the chip is busy. The serial protocol is slightly more complicated, as the SYN-6288 requires a checksum byte at the end.
As I’m not interested in the text-to-speech output itself, here’s a MicroPython script to play all of the sounds:
# very crude MicroPython demo of SYN6288 TTS chip # scruss, 2023-07 import machine import time ### setup device ser = machine.UART( 0, baudrate=9600, bits=8, parity=None, stop=1 ) # tx=Pin(0), rx=Pin(1) busyPin = machine.Pin(2, machine.Pin.IN, machine.Pin.PULL_UP) def sendspeak(u2, data, busy): # modified from https://github.com/TPYBoard/TPYBoard_lib/ # u2 = UART(uart, baud) eec = 0 buf = [0xFD, 0x00, 0, 0x01, 0x01] # buf = [0xFD, 0x00, 0, 0x01, 0x79] # plays with bg music 15 buf[2] = len(data) + 3 buf += list(bytearray(data, "utf-8")) for i in range(len(buf)): eec ^= int(buf[i]) buf.append(eec) u2.write(bytearray(buf)) while busy.value() != True: # wait for busy line to go high time.sleep_ms(5) while busy.value() == True: # wait for it to finish time.sleep_ms(5) for s in "abcdefghijklmnopqrstuvwxy": playstr = "[v10][x1]sound" + s print(playstr) sendspeak(ser, playstr, busyPin) time.sleep(2) for s in "abcdefgh": playstr = "[v10][x1]msg" + s print(playstr) sendspeak(ser, playstr, busyPin) time.sleep(2) for s in "abcdefghijklmno": playstr = "[v10][x1]ring" + s print(playstr) sendspeak(ser, playstr, busyPin) time.sleep(2)Each sound starts and stops with a very loud click, and the sound quality is not great. I couldn’t get a good recording of the sounds (some of which of which are over a minute long) as the only way I could get reliable audio output was through tiny headphones. Any recording came out hopelessly distorted:
I’m not too disappointed that this didn’t work well. I now know that the SYN-6988 is the good one to get. It also looks like I may never get to try the XFS5152CE speech synthesizer board: AliExpress has cancelled my shipment for no reason. It’s supposed to have some English TTS function, even if quite limited.
Here’s the auto-translated SYN-6288 manual, if you do end up finding a use for the thing
-
Adding speech to MMBasic
Yup, it’s another “let’s wire up a SYN6988 board” thing, this time for MMBasic running on the Armmite STM32F407 Module (aka ‘Armmite F4’). This board is also known as the BLACK_F407VE, which also makes a nice little MicroPython platform.
Uh, let’s not dwell too much on how the SYN6988 seems to parse 19:51 as “91 minutes to 20” …
Wiring
SYN6988 Armmite F4 RX PA09 (COM1 TX) TX PA10 (COM1 RX) RDY PA08 your choice of 3.3 V and GND connections, of course Where to buy: AliExpress — KAIKAI Electronics Wholesale Store : High-end Speech Synthesis Module Chinese/English Speech Synthesis XFS5152 Real Pronunciation TTS
Yes, I know it says it’s an XFS5152, but I got a SYN6988 and it seems to be about as reliable a source as one can find. The board is marked YS-V6E-V1.03, and even mentions SYN6988 on the rear silkscreen:


Code
REM SYN6988 speech demo - MMBasic / Armmite F4 REM scruss, 2023-07 OPEN "COM1:9600" AS #5 REM READY line on PA8 SETPIN PA8, DIN, PULLUP REM you can ignore font/text commands CLS FONT 1 TEXT 0,15,"[v1]Hello - this is a speech demo." say("[v1]Hello - this is a speech demo.") TEXT 0,30,"[x1]soundy[d]" say("[x1]soundy[d]"): REM chimes TEXT 0,45,"The time is "+LEFT$(TIME$,5)+"." say("The time is "+LEFT$(TIME$,5)+".") END SUB say(a$) LOCAL dl%,maxlof% REM data length is text length + 2 (for the 1 and 0 bytes) dl%=2+LEN(a$) maxlof%=LOF(#5) REM SYN6988 simple data packet REM byte 1 : &HFD REM byte 2 : data length (high byte) REM byte 3 : data length (low byte) REM byte 4 : &H01 REM byte 5 : &H00 REM bytes 6-: ASCII string data PRINT #5, CHR$(&hFD)+CHR$(dl%\256)+CHR$(dl% MOD 256)+CHR$(1)+CHR$(0)+a$; DO WHILE LOF(#5)<maxlof% REM pause while sending text PAUSE 5 LOOP DO WHILE PIN(PA8)<>1 REM wait until RDY is high PAUSE 5 LOOP DO WHILE PIN(PA8)<>0 REM wait until SYN6988 signals READY PAUSE 5 LOOP END SUBFor more commands, please see Embedded text commands
Heres the auto-translated manual for the SYN6988:
-

Markedly less success with three TTS boards from AliExpress
The other week’s success with the SYN6988 TTS chip was not repeated with three other modules I ordered, alas. Two of them I couldn’t get a peep out of, the other didn’t support English text-to-speech.
SYN6658
This one looks remarkably like the SYN6988:

Yes, I added the 6658 label so I could tell the boards apart Apart from the main chip, the only difference appears to be that the board’s silkscreen says YS-V6 V1.15 where the SYN6988’s said YS-V6E V1.02.
To be fair to YuTone (the manufacturer), they claim this only supports Chinese as an input language. If you feed it English, at best you’ll get it spelling out the letters. It does have quite a few amusing sounds, though, so at least you can make it beep and chime. My MicroPython library for the VoiceTX SYN6988 text to speech module can drive it as far as I understand it.
Here are the sounds:
Name Type Link msga Polyphonic Chord Beep msgb Polyphonic Chord Beep msgc Polyphonic Chord Beep msgd Polyphonic Chord Beep msge Polyphonic Chord Beep msgf Polyphonic Chord Beep msgg Polyphonic Chord Beep msgh Polyphonic Chord Beep msgi Polyphonic Chord Beep msgj Polyphonic Chord Beep msgk Polyphonic Chord Beep msgl Polyphonic Chord Beep msgm Polyphonic Chord Beep msgn Polyphonic Chord Beep sound101 Prompt Tone sound102 Prompt Tone sound103 Prompt Tone sound104 Prompt Tone sound105 Prompt Tone sound106 Prompt Tone sound107 Prompt Tone sound108 Prompt Tone sound109 Prompt Tone sound110 Prompt Tone sound111 Prompt Tone sound112 Prompt Tone sound113 Prompt Tone sound114 Prompt Tone sound115 Prompt Tone sound116 Prompt Tone sound117 Prompt Tone sound118 Prompt Tone sound119 Prompt Tone sound120 Prompt Tone sound121 Prompt Tone sound122 Prompt Tone sound123 Prompt Tone sound124 Prompt Tone sound201 phone ringtone sound202 phone ringtone sound203 phone ringtone sound204 phone ringing sound205 phone ringtone sound206 door bell sound207 door bell sound208 doorbell sound209 door bell sound210 alarm sound211 alarm sound212 alarm sound213 alarm sound214 wind chimes sound215 wind chimes sound216 wind chimes sound217 wind chimes sound218 wind chimes sound219 wind chimes sound301 alarm sound302 alarm sound303 alarm sound304 alarm sound305 alarm sound306 alarm sound307 alarm sound308 alarm sound309 alarm sound310 alarm sound311 alarm sound312 alarm sound313 alarm sound314 alarm sound315 alert-emergency sound316 alert-emergency sound317 alert-emergency sound318 alert-emergency sound319 alert-emergency sound401 credit card successful sound402 credit card successful sound403 credit card successful sound404 credit card successful sound405 credit card successful sound406 credit card successful sound407 credit card successful sound408 successfully swiped the card sound501 cuckoo sound502 error sound503 applause sound504 laser sound505 laser sound506 landing sound507 gunshot sound601 alarm sound / air raid siren (long) sound602 prelude to weather forecast (long) SYN-6658 Sound Reference Where I bought it: Electronic Component Module Store : Chinese-to-real-life Speech Synthesis Playing Module TTS Announcer SYN6658 of Bank Bus Broadcasting.
Auto-translated manual:
Unknown “TTS Text-to-speech Broadcast Synthesis Module”
All I could get from this one was a power-on chime. The main chip has had its markings ground off, so I’ve no idea what it is.

Red and black wires seem to be standard 5 V power. Yellow seems to be serial in, white is not connected.
Where I bought it: Electronic Component Module Store / Chinese TTS Text-to-speech Broadcast Synthesis Module MCU Serial Port Robot Plays Prompt Advertising Board
HLK-V40 Speech Synthesis Module
In theory, this little board has a lot going for it: wifi, bluetooth, commands sent by AT commands. In practice, I couldn’t get it to do a thing.

Where I bought it: HI-LINK Component Store / HLK-V40 Speech Synthesis Module TTS Pure Text to Speech Playback Hailinco AI intelligent Speech Synthesis Broadcast
I’ve still got a SYN6288 to look at, plus a XFS5152CE TTS
that’s in the mailthat may or may not be in the mail. The SYN6988 is the best of the bunch so far. -
SYN-6988 Speech with MicroPython
Full repo, with module and instructions, here: scruss/micropython-SYN6988: MicroPython library for the VoiceTX SYN6988 text to speech module
(and for those that CircuitPython is the sort of thing they like, there’s this: scruss/circuitpython-SYN6988: CircuitPython library for the YuTone VoiceTX SYN6988 text to speech module.)
I have a bunch of other boards on order to see if the other chips (SYN6288, SYN6658, XF5152) work in the same way. I really wonder which I’ll end up receiving!
Update (2023-07-09): Got the SYN6658. It does not support English TTS and thus is not recommended. It does have some cool sounds, though.
Embedded Text Command Sound Table
The github repo references Embedded text commands, but all of the sound references were too difficult to paste into a table there. So here are all of the ones that the SYN-6988 knows about:
- Name is the string you use to play the sound, eg: [x1]sound101
- Alias is an alternative name by which you can call some of the sounds. This is for better compatibility with the SYN6288 apparently. So [x1]sound101 is exactly the same as specifying [x1]sounda
- Type is the sound description from the manual. Many of these are blank
- Link is a playable link for a recording of the sound.
Name Alias Type Link sound101 sounda sound102 soundb sound103 soundc sound104 soundd sound105 sounde sound106 soundf sound107 soundg sound108 soundh sound109 soundi sound110 soundj sound111 soundk sound112 soundl sound113 soundm sound114 soundn sound115 soundo sound116 soundp sound117 soundq sound118 soundr sound119 soundt sound120 soundu sound121 soundv sound122 soundw sound123 soundx sound124 soundy sound201 phone ringtone sound202 phone ringtone sound203 phone ringtone sound204 phone rings sound205 phone ringtone sound206 doorbell sound207 doorbell sound208 doorbell sound209 doorbell sound301 alarm sound302 alarm sound303 alarm sound304 alarm sound305 alarm sound306 alarm sound307 alarm sound308 alarm sound309 alarm sound310 alarm sound311 alarm sound312 alarm sound313 alarm sound314 alarm sound315 alert/emergency sound316 alert/emergency sound317 alert/emergency sound318 alert/emergency sound401 credit card successful sound402 credit card successful sound403 credit card successful sound404 credit card successful sound405 credit card successful sound406 credit card successful sound407 credit card successful sound408 successfully swiped the card SYN-6988 Sound Reference -
Speech from Python with the SYN6988 module
I’ve had one of these cheap(ish – $15) sound modules from AliExpress for a while. I hadn’t managed to get much out of it before, but I poked about at it a little more and found I was trying to drive the wrong chip. Aha! Makes all the difference.
So here’s a short narration from my favourite Richard Brautigan poem, read by the SYN6988.
Sensitive listener alert! There is a static click midway through. I edited out the clipped part, but it’s still a little jarring. It would always do this at the same point in playback, for some reason.
The only Pythonish code I could find for these chips was meant for the older SYN6288 and MicroPython (syn6288.py). I have no idea what I’m doing, but with some trivial modification, it makes sound.
I used the simple serial UART connection: RX -> TX, TX -> RX, 3V3 to 3V3 and GND to GND. My board is hard-coded to run at 9600 baud. I used the USB serial adapter that came with the board.
Here’s the code that read that text:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import serial import time # NB via MicroPython and old too! Also for a SYN6288, which I don't have # nabbed from https://github.com/TPYBoard/TPYBoard_lib/ def sendspeak(port, data): eec = 0 buf = [0xFD, 0x00, 0, 0x01, 0x01] buf[2] = len(data) + 3 buf += list(bytearray(data, encoding='utf-8')) for i in range(len(buf)): eec ^= int(buf[i]) buf.append(eec) port.write(bytearray(buf)) ser = serial.Serial("/dev/ttyUSB1", 9600) sendspeak(ser, "[t5]I like to think [p100](it [t7]has[t5] to be!)[p100] of a cybernetic ecology [p100]where we are free of our labors and joined back to nature, [p100]returned to our mammal brothers and sisters, [p100]and all watched over by machines of loving grace") time.sleep(8) ser.close()This code is bad. All I did was prod stuff until it stopped not working. Since all I have to work from includes a datasheet in Chinese (from here: ??????-SYN6988???TTS????) there’s lots of stuff I could do better. I used the tone and pause tags to give the reading a little more life, but it’s still a bit flat. For $15, though, a board that makes a fair stab at reading English is not bad at all. We can’t all afford vintage DECtalk hardware.
The one thing I didn’t do is used the SYN6988’s Busy/Ready line to see if it was still busy reading. That means I could send it text as soon as it was ready, rather than pausing for 8 seconds after the speech. This refinement will come later, most likely when I port this to MicroPython.
More resources:
- Board front image (labelled YS-V6E V1.02)
- Board back image
- Auto-translated programming manual (thanks, Google Translate!): SYN6988-translated.pdf















































