#sp0256aal2
I've stuck my SP0256A-AL2 circuit onto an Uno shield format board.

It has an option for a fixed oscillator or the SI5351 programmable clock and should make any further messing around a bit easier.

https://diyelectromusic.com/2025/09/23/arduino-sp0256a-al2-shield-design/

#arduino #sp0256aal2
September 23, 2025 at 8:28 PM
Using a Raspberry Pi Pico as a programmable clock for an Arduino-driven SP0256A-AL2 speech synthesizer chip.

https://diyelectromusic.com/2025/09/06/arduino-and-sp0256a-al2-part-3/

#arduino #RaspberryPiPico #sp0256aal2
September 6, 2025 at 10:11 AM
Programming a SP0256A-AL2 speech synthesis chip from an Arduino Uno.

https://diyelectromusic.com/2025/08/03/arduino-and-sp0256a-al2/

#arduino #sp0256aal2
August 3, 2025 at 9:18 PM
Driving the SP0256A-AL2 from an Arduino with a SI5351 I2C programmable clock.

This is starting to get useful now (finally) :)

https://diyelectromusic.com/2025/09/08/arduino-and-sp0256a-al2-part-5/
Arduino and SP0256A-AL2 – Part 5
This looks at another of the options from Part 4 – the I2C programmable Si5351 clock source. _**Warning!** I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!_ If you are new to microcontrollers, see the Getting Started pages. ### I2C Si5351 Programmable Clock From the datasheet of the Si5351: _“The Si5351 is an I2C configurable clock generator that is ideally suited for replacing crystals, crystal oscillators, VCXOs, phase-locked loops (PLLs), and fanout buffers in cost-sensitive applications. Based on a PLL/VCXO + high resolution MultiSynth fractional divider architecture, the Si5351 can generate any frequency up to 160 MHz on each of its outputs with 0 ppm error.”_ The device itself requires a 3V to 3.6V supply, but typical breakouts seem to include a LDO regulator meaning it can be powered from 3V to 5V. Logic outputs are always 3V but the I2C lines will be the same as the power supply. ### The Circuit I’m using a breakout board like the one shown above. This has header pins for the three clock outputs, power and ground, and I2C. Although the si5351 device itself is a 3V3 device, most breakouts like this seem to include components to allow them to be powered by either 3V3 or 5V. I’m using 5V in my circuit. I’m only using one of the clocks, so output 0 is fed into the OSC1 input of the SP0256A-AL2. Otherwise the rest of the SP0256A-AL2/Arduino circuit is the same as for part 1. ### The Code There are two libraries I’ve found for this: * https://github.com/adafruit/Adafruit_Si5351_Library * https://github.com/etherkit/Si5351Arduino The Adafruit library is a fairly low-level interface to the device. The device basically has a multiplier which is used to set a PLL clock to somewhere between 600 and 900MHZ; and then a divisor to drop that back down to something useful. But the reality of setting the parameters is actually quite complicated. There is a full discussion of how to do it, with some example Arduino code, here: https://rfzero.net/tutorials/si5351a/ It is not for the faint hearted! Thankfully the second library mentioned above, by “EtherKit”, has a ‘set_freq()’ function that does it all for us. The code to use it is therefore fairly straight forward: #include <si5351.h> #include <Wire.h> Si5351 si5351; void clockSetup () { si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); si5351.set_freq(300000000ULL, SI5351_CLK0); si5351.update_status(); } void setClock (uint64_t freq) { si5351.set_freq(freq, SI5351_CLK0); si5351.update_status(); delay(300); } The initialisation function requires three things: * Which of 6, 8 or 10pF capacitors are used with the external oscillator. * Frequency of the external oscillator. Passing in 0 uses the default, 25MHz. * A parameter for frequency correction. I’m just using 0. The set_freq() function takes a 64-bit value which gives a frequency in 0.01Hz units, so 3MHz is 3 followed by 8 zeros. This is an “unsigned long long” type, hence the “ULL” initialiser after the value in the code above. The other parameter states which clock to use – I’m just using clock 0. It is possible to wire up a pot to an analog input and set the frequency using something like the following: int alglast = 0; void checkClock (void) { int algval = analogRead(ALG_IN); if (algval != alglast) { uin64_t freq = 1000 + 5 * analogRead(ALG_IN); // in kHz setClock(freq*100000); // Convert to 0.01Hz units } alglast = algval; } This maps a pot reading onto frequency values between 1MHz and just over 6MHz in units of 5kHz. Alternatively, it is possible to set pitches for individual allophones. I’ve found that loosely speaking, 3MHz seems to correspond to talking at the pitch of G#2 (MIDI note 44) which is an audio pitch frequency of round 98Hz. 6MHz is, as you might expect, G#3 (MIDI note 56 at 196Hz). This means that the I can calculate the required clock frequency for a MIDI note M using the formula: * Freq = 3MHz * 2 ^ (M – 44)/12 This function will set the clock based on the MIDI note number: void midi2clock (int m) { if (m < 36 || m > 56) { return; } freq = 300000000 * pow (2.0, (((double)m-44.0)/12.0)); setClock (freq); } Note how I’ve limited the range to between C2 (36) and G#3 (56), which means frequencies of 1.889MHz to 6MHz. It would probably go a bit lower – down to 1MHz is probably practical from the point of view of the chip functioning, but not so useful from the point of view of how long it would take to say a single allophone. Anything higher will cause the SP0256A-AL2 to lock up in a funny state. But that gives me a good octave and a fifth, which is quite a useful and practical range. ### Closing Thoughts This is the most accurate and simplest to set up manner of providing a programmable clock I’ve found so far. The device itself is actually quite complex to use, but all that complexity has been hidden away in the Si5351 library published by EtherKit. The device sometimes seemed to get stuck in a weird state where is wasn’t recognised on the I2C bus. A power cycle or reset, or some combination of both, was usually required to get it going again. I don’t know if that was dodgy cables somewhere, but when it got stuck, curiously my nearby FM radio receiver lost its signal… Hmm. The downside of using the Arduino for both clock and speech control is that it isn’t possible to adjust the clock whilst the speech is happening. That would need some kind of parallel execution to manage that – either adding in another microcontroller, or maybe moving to a dual-core microcontroller. But as you can hear from the end of the video, this could still be pretty useful and I wish I’d had it for my Electric Lo-Fi Orchestra Concerto for a Rainy Day. Kevin ### Share this: * Click to share on X (Opens in new window) X * Click to share on Facebook (Opens in new window) Facebook * Like Loading... ### _Related_
diyelectromusic.com
September 8, 2025 at 9:13 PM
SP0256A-AL2 Speech Synthesis
I had one of those moments recently when reading an article online sent me into a bit of a major tangent. The article in question was talking about the SP0256-AL2 speech synthesizer chip. And if you heard a computer talking in the 1980s, then chances are it was probably this chip doing all the hard work. These aren’t very easy to come by these days, but you might get lucky with the usual places and find a legit, used, working one, but apparently an awful lot of those that can be found online are likely to be fake (see: https://www.smbaker.com/counterfeitfakejustplainbad-sp0256a-al2-chips). But a number of peripherals for home computers in the 1980s included it and as luck would have it, the wonderful “MR GELÉE’S TECH” has a PCB, supplied with the chip included, for the RC2014 here: https://www.tindie.com/products/mrgelee/mg005-speech-synthesiser-designed-for-rc2014/ So whilst on particularly a musical project (at least, not at the moment), this details how I got it up and running. _**Warning!** I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!_ If you are new to microcontollers, see the Getting Started pages. ### The SP0256A-AL2 This is a pretty amazing device. It was present in the Currah uSpeech peripheral (that unfortunately I never had myself) back “in the day” and a whole load of other cheap(ish) add-ons for 1980s computers. It works by having a set of samples encoded in ROM for the basic phonetic sounds of the English language (called “allophones”). Then it is told which to sound by a controlling CPU, or these days MCU probably. Of course, text to speech has come on enormously since then, and there are all sorts of nuance now possible. It will be interesting to see if the recent rounds of AI use become a pinnacle of text to speech or a curse, but we shall see. But there is something pretty nostalgic about hearing an allophone-based, lo-fi (by today’s standards) chip in action. And this style of voice is iconic for the sounds of computer voices used in films such as War Games, 2001, and The Forbin Project, among many others. There is a complete run-down of the family of these devices here: https://en.wikipedia.org/wiki/General_Instrument_SP0256 _“The SP0256-AL2 is perhaps the most commonly encountered variant. It contains 59 allophones primarily intended for use with English language phrases and five pauses in its internal 16 Kb (2 KB) ROM.”_ There are full technical details in a datasheet and application manual available online, for example, from here: https://www.cpcwiki.eu/index.php/SP0256 Here is the full allophone table from the datasheet: The datasheet also includes some words that show how the allophones can be used, for example: I sort of imagined that somewhere there might be a library that has the data structures that represent the details provided in the datasheet, but I’ve not found it yet if it exists. But thankfully there are means of getting allophones from English Text, which I’ll get to shortly. ### The Basic Code The code to drive the chip from BASIC is pretty straight forward. This is my code based on the example provided in the manual: 10 DATA 18,12,55,12,43,18,51,35,5,55,0 15 DATA 24,35,46,52,45,21,41,51,11,13,14,53,45,0 20 LET LE=11+14 30 DIM XX(LE) 40 FOR Y = 1 TO LE 50 READ XX (Y) 60 NEXT Y 70 FOR Z=1 TO LE 80 IF (INP(31) AND 2) = 2 THEN GOTO 100 90 GOTO 80 100 OUT 31,XX(Z) 105 NEXT Z There is a list of the phonemes required and they are sent to the chip in turn. As already mentioned of course, the real trick is how to get that list of allophones. Whilst it is possible to walk through the datasheet for the SP0256A-AL2 and pick out the correct ones in turn, that is a lot more difficult that it might initially seem, as it perhaps highlighted above. ### Text to Allophone Data Workflow As with may of these things we are fortunately that there are tools out there that can do all this for us. In this case, two tools are required: * lexconvert: https://github.com/ssb22/lexconvert * espeak or espeak-ng: https://github.com/espeak-ng/espeak-ng I used espeak-ng which has a MSI installer for Windows, and lexconverter which is a python script. Install steps: * Install espeak-ng as required. This is a command line utility for Linux or Windows and instructions for installation can be found in “Documentation” -> “User Guide”. * Grab the lexconvert.py script. I had to ensure that the location of espeak-ng was present in my system PATH, but also had to edit lexconvert.py to change several instances of espeak to espeak-ng. There were three places that looked like they would need changing, all associated with “os.system”, “os.popen” or “subprocess.Popen” calls or similar. I suspect copying the original executable to a more handy location and renaming it to “espeak” would probably work too. To get allophones suitable for use with the SP0256A-AL2 requires the “cheetah” option to lexconvert, as detailed below: cheetah : Allophone codes for the 1983 "Cheetah Sweet Talker" SP0256-based hardware add-on for ZX Spectrum and BBC Micro home computers. The conversion from phonemes to allophones might need tweaking. Set the CHEETAH_SYM environment variable to see the mnemonic symbols from the instruction sheet (not actually used by the system). The command I used was as follows, which then waits for keyboard input and creates a data structure of allophones which can be used almost directly in the BASIC program. C:\Users\Kevin\Stuff>python lexconvert.py --phones cheetah Enter text (EOF when done) Hello World DATA 27,51,45,53,46,52,45,21,0 Greetings Professor Falcon DATA 36,14,19,13,12,44,43,9,14,51,40,7,55,52,40,26,45,41,51,11,0 Would you like to play a game? DATA 46,30,21,25,22,45,6,41,13,51,9,45,20,51,36,20,16,0 This is the Voice of World Control DATA 18,12,55,12,43,18,51,35,5,55,24,35,46,52,45,21,41,51,11,13,14,53,45,0 C:\Users\Kevin\Stuff> One issue I had in using these DATA statements directly is that they get capped when pasted into the RC2014 terminal, hence using two DATA statements in my final code. But in general terms, this works surprisingly well. ### Closing Thoughts I now feel like I should build up DATA statements of allophones for well-known quotes from computers in films. I also now want to work out how to drive the SP0256A-AL2 directly from a microcontroller myself, so that will probably be next. Then I would like to tie this up to MIDI somehow, but my initial thought, of linking allophones to MIDI notes, seems to have been done already: https://rarewaves.net/products/midi-narrator/ But I still might have to overdub it saying “Concerto for a Rainy Day”. Getting it in time with the music might be an interesting challenge, but maybe there might be a computer-voice-vocoder-like thing possible now. And of course, this now presents all sorts of interesting possibilities for some more Philip Glass… Kevin ### Share this: * Click to share on X (Opens in new window) X * Click to share on Facebook (Opens in new window) Facebook * Like Loading... ### _Related_
diyelectromusic.com
August 2, 2025 at 3:08 PM
And this one is using a 74HC4046 PLL/VCO as an adjustable clock.

https://diyelectromusic.com/2025/09/06/arduino-and-sp0256a-al2-part-4/

#arduino #sp0256aal2
September 6, 2025 at 8:52 PM
Arduino and SP0256A-AL2 – Part 2
After getting the Arduino and SP0256A-AL2 working I wondered if I could repeat the trick from the Arduino and AY-3-8910 and have the Arduino generate the required clock signal for the SP0256A-AL2. This post starts to look at that question. _**Warning!** I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!_ If you are new to Arduino, see the Getting Started pages. ### Parts list * Arduino Uno * SP0256A-AL2 speech synthesizer chip * 2x 1KΩ resistors * 2x 100nF capacitors * 1x 1uF capacitor * 1x 3.5mm jack socket * Breadboard and jumper wires ### The Circuit This is basically the same setup as the previous post, but instead of the 3.579345 MHz oscillator, the clock input of the SP0256A-AL2 is connected to the Arduino D10 pin. D10 is internally connected to OC1B, or the “B” compare match output of Timer 1 of the ATMega328P. ### The Code To get a clock signal of any kind on one of the output pins requires use of the ATMega328’s timers – in this case Timer 1. This is a 16-bit timer. To generate an automatic (i.e. with no code driving it once it is set up) square wave signal on the Arduino’s output pin requires the timer to be connected to an output pin to generate a 50% duty cycle PWM signal. The PWM peripherals can be configured to toggle an output pin when the timer expires, but that therefore requires the PWM to be running at least twice as fast as the required frequency. From the SP0256A-AL2 datasheet, it has this to say about clocks. There isn’t a lot to go on here – basically it assumes a 3.12MHz clock with a 48-52% duty cycle for the square wave. A typical application circuit would be the following (again from the datasheet): And the final word on oscillators is in the pin descriptions: The options for creating a 3.12 MHz clock with an Arduino PWM output are pretty limited, due to the following: * The faster clock for PWM is related to the system IO clock speed of 16MHz, when running with no “prescalar” to drop it down in frequency. * When running at 16MHz, lower frequencies are obtained by using the “compare match” approach. The timer will reset and the output pin will toggle when a counter match occurs. The counter will count in integer units of the core 16MHz frequency. * As the output pin will toggle on compare match, the timer must run at twice the frequency of the required clock signal. This allows one period for a HIGH output and one period for a LOW output to generate the required square wave output. The PWM square wave frequency is given by the following formula (as per the ATMega328P datasheet for Timer 1,3,4): * Freq = FreqClk / (2 * prescalar * (OCR1B + 1)) Given the above, with a FreqClk of 16MHz, the following are the only real options for a PWM-driven square wave as a clock for this application: OCR1B compare value| Resulting clock frequency ---|--- 0| 8 MHz 1| 4 MHz 2| 2.7 MHz 3| 2 MHz 4| 1.6 MHz 5| 1.3 MHz So there isn’t a lot of choice, and nothing particularly close to the required 3.12 MHz, although 2.7 MHz is the closest and would probably do if required. To configure the above requires the following code: #define SP0_CLOCK 10 // D10 void clockSetup () { pinMode(SP0_CLOCK, OUTPUT); digitalWrite(SP0_CLOCK, LOW); TCCR1A = (1 << COM1B0); TCCR1B = (1 << WGM12) | (1 << CS10); TCCR1C = 0; TIMSK1 = 0; OCR1AH = 0; OCR1AL = 1; } This configures Timer 1 in Clear-Timer-on-Compare (CTC) mode with no prescalar, toggling OC1B on compare match with the value in OCR1A. Note: even though there are two pin outputs – OC1A on D9 and OC1B on D10 – which is used is determined by the COM1A/COM1B settings. Even when using OC1B, as I am here, it is still the match value in OCR1A that determines when the counter has reached its “top” value. I updated the code to try each of the above values for OCR1A in turn and the result is the video at the start of this post. void setClock (int clock) { OCR1AH = 0; OCR1AL = clock; } ### Closing Thoughts It is interesting to note that the Arduino can in fact provide a clock that allows the SP0256A-AL2 to function, even if it is not particularly true to the original at this point. But it does mean that there isn’t as much control over the pitch as I’d hoped. If I want to get to more of that granularity between 4 MHz and 2 MHz, I’ll have to find another way. Kevin ### Share this: * Click to share on X (Opens in new window) X * Click to share on Facebook (Opens in new window) Facebook * Like Loading... ### _Related_
diyelectromusic.com
August 7, 2025 at 8:58 PM
Testing out the SP0256A-AL2 emulation on the RP2040 now.

#rp2040 #sp0256aal2 #shallweplayagame
August 5, 2025 at 8:55 PM