from problemkaputt.de: • Read from Memory Address 0038h - Enable/Disable Currah uSpeech BIOS Reading from this memory address enables/disables the 2K uSpeech BIOS (and probably also the uSpeech command/status register), ie. on each second read it gets enabled (at 0000h..07FFh), on each other read it gets disabled. 0-7 Data/Opcode from the (newly) activated ROM Usually the enable takes place when the CPU jumps to the vblank IRQ handler at 0038h, which is then redirected to the uSpeech BIOS, which does then do it's job, and jumps to 0038h, which re-enables the Spectrum BIOS and executes the normal IRQ handler. There are no further BIOS hooks; initialization (upon reset) is also done from inside of the hooked IRQ handler. • Read from Memory Address 1000h - Currah uSpeech Status (R) This port is probably accessible only when enabled via address 0038h. 0 Load Request (LRQ) (1=Buffer full, 0=Ready to receive data) 1-7 Unknown/unused Bit0 seems to be the /LRQ pin of the SP0256 chip. Unknown if the SBY pin (indicating when all data is finished) is also found in this register? The size of the buffer is unknown, maybe it can only hold only a single value (additionally to the sound being currently played)...? • Write to Memory Address 1000h - Currah uSpeech Output (W) This port is probably accessible only when enabled via address 0038h. 0-5 SP0256-AL2 Allophone Number (00h..3Fh) 6 Intonation (0=Decrease Pitch, 1=Increase Pitch) 7 Unknown/unused (should be zero) Data can be written to this register when the Status.Bit0 indicates ready (not sure happens when it doesn't). The last allophone should be followed by a pause (eg. 00h=Pause10ms), otherwise the SP0256 does reportedly gets stuck repeating the last allophone (not sure what gets repeated exactly, maybe it repeats only the end of the last allophone, ie. "shhhhhhh" for "sh", or maybe the whole last allophone, ie. "shshshsh"?) The intonation bit seems to be a special feature of the Currah hardware (not a feature of the SP0256 voice chip itself). Unknown how it is implemented... it might modify the CLK passed to the SP0256... so, aside from the frequency, this would also alter the durations, ie. the length of a "100ms" pause would vary... or it might modify whatever kind of external low-pass and/or high-pass filter...? The intonation does increase step-by-step (rather than changing abruptly from low to high)... the stepping rate, and the max/min values are unknown? • Currah uSpeech Mirrors of 0038h and 1000h and ROM Reads from memory address 0038h are also mirrored to reads from I/O address 0038h (used by Rockfall to detect the uSpeech), apparently the port is decoded by checking only A0..A15 and /RD. For address 1000h it's still unknown if there are mirrors, possibly, only /RD, /WR, A12, A14, A15 are decoded (probably together with the uSpeech BIOS enable flag which gets set/cleared via 0038h); if so, mirrors would occur at 1000h-1FFFh and 3000h-3FFFh in both memory and I/O region? If so, using the I/O mirrors would be not too recommended since they could conflict with other internal/external I/O ports. For the ROM it's unknown if it's mirrored, too. Might be mirrored to 800h..FFFh and 2000h-2FFFh? Currah uSpeech BIOS/BASIC extension Unlike most or all other speech devices, the Currah hardware includes a BIOS extension. Currah related BASIC commands are: LET keys=0 ;disable spoken keystrokes (recommended for LOAD/SAVE) LET keys=1 ;enable spoken keystrokes (default) LET s$="he(ll)(oo)" ;say hello (normal lowercase) LET s$="hE(ll)(oO)" ;say hello (with raised intonation on "e" and "(oo)") PAUSE 1 ;wait for Vblank IRQ (where s$ is processed) CLEAR n ;change RAMTOP (speech buffer is between RAMTOP and UDG) IF PEEK(65364)=81 ;buffer pointer LSB, [FF54h]=51h=buffer_empty (on 48K) IF s$(TO 1)="*" ;check if s$ was processed (copied to speech buffer) IF s$(TO 1)="?" ;check if s$ was rejected (contained invalid characters) IF s$(TO 1)=other ;check if s$ was not yet processed (or buffer full) On power up, the Currah BIOS allocates 256 bytes between RAMTOP and UDG, containing a 6-byte "header", and a 250-byte buffer; which contains allophone numbers (and intonation flag in bit6), in the format as written to address to 1000h (ie. not in ASCII format as used in the BASIC s$ variable). On the Spectrum this region is at FFxxh (on Spectrum 16K it's at 7Fxxh): FF57h - Flag byte FF56h - Spare (unused general purpose byte; NOT reserved for anything) FF55h - Hi byte of buffer pointer ;\contains FF51h when empty FF54h - Lo byte of buffer pointer ;/ FF53h - Spare (unused general purpose byte; NOT reserved for anything) FF52h - Spare (unused general purpose byte; NOT reserved for anything) FF51h..FE58h - Speech buffer (default size=250) [FF51h]=next allophone In BASIC, the spoken keystrokes and s$ strings are good for a first "oh it does really speak" impression, although after soon, the keystroke feature may become annoying, and the automatic modification of the first character in s$ may cause compatibility problems with various BASIC programs that do use s$ for other purposes. Moreover, allocating 256 bytes between RAMTOP and UDG may cause problems with many machine code programs. And, hooking the IRQ handler changes Vblank handling timings which may also cause problems with a few programs.