| Currah μSpeech | Routines |
| Prev: 00000 | Up: Map | Next: 00427 |
|
Any access to HandleInterrupt (including this opcode fetch) pages the μSpeech ROM in or out. The Spectrum IM1 handler lands here, so this ROM runs first. Every exit jumps back to HandleInterrupt, which pages the Spectrum ROM in and lets IM1 finish.
|
||||
| HandleInterrupt | 00056 | PUSH AF | Keep AF unchanged. | |
| 00057 | POP AF | |||
| 00058 | DI | Disable interrupts. | ||
| 00059 | PUSH HL | Stash HL, AF, BC and DE on the stack. | ||
| 00060 | PUSH AF | |||
| 00061 | PUSH BC | |||
| 00062 | PUSH DE | |||
|
The speech workspace is a short block just below *RAMTOP (low byte 87). A 48K machine uses 65367; a 16K machine uses 32599.
|
||||
| 00063 | LD HL,(23730) | Fetch *RAMTOP. | ||
| 00066 | LD A,L | Jump to ProbeWorkspace if the low byte is not 87. | ||
| 00067 | CP 87 | |||
| 00069 | JR NZ,ProbeWorkspace | |||
| 00071 | LD A,H | Jump to InstallWorkspace if this is a 48K machine. | ||
| 00072 | CP 255 | |||
| 00074 | JR Z,InstallWorkspace | |||
| 00076 | CP 127 | Jump to InstallWorkspace if this is a 16K machine. | ||
| 00078 | JR Z,InstallWorkspace | |||
|
*RAMTOP is not the installed workspace yet.
|
||||
| ProbeWorkspace | 00080 | LD A,6 | Call ReadWorkspace for the saved buffer pointer. | |
| 00082 | CALL ReadWorkspace | |||
| 00085 | LD B,H | Copy the workspace address to BC. | ||
| 00086 | LD C,L | |||
| 00087 | CALL CheckMemory | Call CheckMemory and jump to InstallWorkspace if the reserved block is already below *RAMTOP. | ||
| 00090 | JR C,InstallWorkspace | |||
| 00092 | CALL ReadBufferPointer | Call ReadBufferPointer. | ||
| 00095 | CALL CheckMemory | Call CheckMemory. | ||
| 00098 | CALL C,ResetBufferPointer | Call ResetBufferPointer if the pointer is out of range. | ||
| 00101 | XOR A | Call ReadWorkspace for the flags byte. | ||
| 00102 | CALL ReadWorkspace | |||
| 00105 | BIT 2,A | Jump to ServiceSpeech if the workspace is already live. | ||
| 00107 | JR NZ,ServiceSpeech | |||
| 00109 | SET 2,(HL) | Mark the workspace as being installed. | ||
| 00111 | POP DE | Restore DE, BC, AF and HL from the stack. | ||
| 00112 | POP BC | |||
| 00113 | POP AF | |||
| 00114 | POP HL | |||
|
Page the Spectrum ROM back in so IM1 can run.
|
||||
| ReturnToSpectrum | 00115 | PUSH HL | No operation. | |
| 00116 | PUSH HL | |||
| 00117 | POP HL | |||
| 00118 | POP HL | |||
| 00119 | LD HL,56 | Set the return address to HandleInterrupt. | ||
| 00122 | PUSH HL | Stash the return address on the stack. | ||
| 00123 | DEC SP | Move SP down two bytes. | ||
| 00124 | DEC SP | |||
| 00125 | POP HL | Restore HL from the stack. | ||
| 00126 | JP HandleInterrupt | Jump to HandleInterrupt. | ||
|
Wait a few frames, then reserve a page below *RAMTOP for the speech workspace.
|
||||
| InstallWorkspace | 00129 | LD A,(23672) | Jump to ExitInterrupt if *FRAMES is still less than 5. | |
| 00132 | CP 5 | |||
| 00134 | JP C,ExitInterrupt | |||
| 00137 | XOR A | Call ReadWorkspace for the flags byte. | ||
| 00138 | CALL ReadWorkspace | |||
| 00141 | DEC H | Lower *RAMTOP by one page. | ||
| 00142 | LD (23730),HL | |||
| 00145 | INC H | Write 130 to the flags byte. | ||
| 00146 | LD (HL),130 | |||
| 00148 | DEC HL | Clear workspace index 1. | ||
| 00149 | XOR A | |||
| 00150 | LD (HL),A | |||
| 00151 | DEC HL | Store the workspace page in index 2. | ||
| 00152 | LD (HL),H | |||
| 00153 | DEC HL | Write 81 to the buffer pointer (index 3). | ||
| 00154 | LD (HL),81 | |||
| 00156 | DEC HL | Clear workspace indexes 4 and 5. | ||
| 00157 | LD (HL),A | |||
| 00158 | DEC HL | |||
| 00159 | LD (HL),A | |||
| 00160 | LD HL,(23730) | Fetch the new *RAMTOP. | ||
|
Plant a sentinel and move the machine stack below the new *RAMTOP.
|
||||
| InstallWorkspace_Stack | 00163 | LD (HL),62 | Write a 62 sentinel at the new *RAMTOP. | |
| 00165 | DEC HL | |||
| 00166 | LD (HL),A | Write 0 beneath it. | ||
| 00167 | LD SP,HL | Point SP at the new *RAMTOP. | ||
| 00168 | DEC HL | Clear the two bytes below the new stack. | ||
| 00169 | LD (HL),A | |||
| 00170 | DEC HL | |||
| 00171 | LD (HL),A | |||
| 00172 | LD (23613),HL | Write the error stack to *ERR_SP. | ||
| 00175 | LD DE,4777 | Set the return address to MAIN-5. | ||
| 00178 | PUSH DE | Stash the return address on the stack. | ||
| 00179 | EI | Enable interrupts. | ||
| 00180 | JP HandleInterrupt | Jump to HandleInterrupt. | ||
|
The workspace is live. Draw the banner once, then speak.
|
||||
| ServiceSpeech | 00183 | RES 2,(HL) | Clear the "installing" flag. | |
| 00185 | BIT 7,(HL) | Call PrintBanner if the banner has not been drawn yet. | ||
| 00187 | CALL NZ,PrintBanner | |||
|
Keep *FRAMES moving while this ROM owns the interrupt.
|
||||
| 00190 | LD HL,(23672) | Fetch the *FRAMES word. | ||
| 00193 | LD A,H | Jump to ServiceSpeech_Tick if *FRAMES is non-zero. | ||
| 00194 | OR L | |||
| 00195 | JR NZ,ServiceSpeech_Tick | |||
| 00197 | LD HL,23674 | Decrease the third *FRAMES byte. | ||
| 00200 | DEC (HL) | |||
| ServiceSpeech_Tick | 00201 | LD HL,(23672) | Decrease the *FRAMES word. | |
| 00204 | DEC HL | |||
| 00205 | LD (23672),HL | |||
|
Tick the two keyboard-state timer pairs.
|
||||
| 00208 | LD HL,23554 | Point at the keyboard-state timers (4 bytes apart). | ||
| 00211 | LD DE,4 | |||
| 00214 | CALL IncrementPair | Call IncrementPair. | ||
| 00217 | DEC HL | Move back one byte. | ||
| 00218 | CALL IncrementPair | Call IncrementPair. | ||
|
Programs speak by assigning the BASIC string s$. Look it up and expand it into allophones if it exists.
|
||||
| 00221 | LD A,83 | Call FindVariable for "s$". | ||
| 00223 | CALL FindVariable | |||
| 00226 | CALL Z,ParseSpeechString | Call ParseSpeechString if s$ exists. | ||
| 00229 | CALL TestKeysVariable | Call TestKeysVariable. | ||
| 00232 | JP Z,FeedAllophone | Jump to FeedAllophone if key speech is enabled. | ||
| 00235 | XOR A | Call ReadWorkspace for the flags byte. | ||
| 00236 | CALL ReadWorkspace | |||
| 00239 | LD A,(23611) | Fetch *FLAGS. | ||
| 00242 | BIT 5,A | Jump to ServiceSpeech_NoKey if no new key was pressed. | ||
| 00244 | JR Z,ServiceSpeech_NoKey | |||
| 00246 | BIT 4,(HL) | Jump to FeedAllophone if this key is already being spoken. | ||
| 00248 | JR NZ,FeedAllophone | |||
| 00250 | JR ServiceSpeech_Key | Jump to ServiceSpeech_Key. | ||
| ServiceSpeech_NoKey | 00252 | RES 4,(HL) | Clear the "key held" flag and jump to FeedAllophone. | |
| 00254 | JR FeedAllophone | |||
|
A new key is in *LAST_K; turn it into allophones.
|
||||
| ServiceSpeech_Key | 00256 | SET 4,(HL) | Set the "key held" flag. | |
| 00258 | LD A,(23560) | Fetch *LAST_K. | ||
| 00261 | CP 123 | Jump to ServiceSpeech_NotLetter if the code is 123 or higher. | ||
| 00263 | JR NC,ServiceSpeech_NotLetter | |||
| 00265 | CP 97 | Jump to ServiceSpeech_NotLetter if the code is below "a". | ||
| 00267 | JR C,ServiceSpeech_NotLetter | |||
| 00269 | SUB 32 | Convert a lowercase letter to uppercase and jump to ServiceSpeech_Lookup. | ||
| 00271 | JR ServiceSpeech_Lookup | |||
|
Not a letter. Block graphics share key 128; other symbols go through PunctuationKeys.
|
||||
| ServiceSpeech_NotLetter | 00273 | CP 165 | Jump to ServiceSpeech_Punctuation if the code is 165 or higher. | |
| 00275 | JR NC,ServiceSpeech_Punctuation | |||
| 00277 | CP 128 | Jump to ServiceSpeech_Punctuation if the code is below 128. | ||
| 00279 | JR C,ServiceSpeech_Punctuation | |||
| 00281 | LD A,128 | Use dictionary key 128 and jump to ServiceSpeech_Lookup. | ||
| 00283 | JR ServiceSpeech_Lookup | |||
| ServiceSpeech_Punctuation | 00285 | LD HL,1069 | Search PunctuationKeys for this character. | |
| 00288 | LD BC,13 | |||
| 00291 | CPIR | Jump to ServiceSpeech_Lookup if there is no mapping. | ||
| 00293 | JR NZ,ServiceSpeech_Lookup | |||
| 00295 | LD BC,12 | Fetch the replacement from PunctuationValues. | ||
| 00298 | ADD HL,BC | |||
| 00299 | LD A,(HL) | |||
|
Look the key up in AllophoneDictionary.
|
||||
| ServiceSpeech_Lookup | 00300 | LD HL,1095 | Point at AllophoneDictionary. | |
| 00303 | LD B,A | Keep the key in B. | ||
| ServiceSpeech_FindKey | 00304 | BIT 7,(HL) | Jump to ServiceSpeech_NextKey if this byte ends an allophone list. | |
| 00306 | JR NZ,ServiceSpeech_NextKey | |||
| 00308 | INC HL | Move to the next dictionary byte. | ||
| 00309 | JR ServiceSpeech_FindKey | Jump to ServiceSpeech_FindKey. | ||
| ServiceSpeech_NextKey | 00311 | INC HL | Move to the next dictionary key. | |
| 00312 | XOR A | Jump to FeedAllophone if the table has ended. | ||
| 00313 | CP (HL) | |||
| 00314 | JR Z,FeedAllophone | |||
| 00316 | LD A,B | Jump to ServiceSpeech_Copy if this key matches. | ||
| 00317 | CP (HL) | |||
| 00318 | JR Z,ServiceSpeech_Copy | |||
| 00320 | INC HL | Move to the next dictionary byte. | ||
| 00321 | JR ServiceSpeech_FindKey | Jump to ServiceSpeech_FindKey. | ||
|
Copy the matching allophones into the speech buffer.
|
||||
| ServiceSpeech_Copy | 00323 | INC HL | Move to the first allophone of this entry. | |
| 00324 | CALL CompareBuffer | Call CompareBuffer and jump to ServiceSpeech_Store if the buffer pointers already match. | ||
| 00327 | JR Z,ServiceSpeech_Store | |||
| 00329 | INC BC | Step the buffer pointer on one byte. | ||
| 00330 | LD A,(BC) | Jump to FeedAllophone if the previous allophone is not a terminator. | ||
| 00331 | RLA | |||
| 00332 | JR NC,FeedAllophone | |||
| 00334 | CALL ResetBufferPointer | Call ResetBufferPointer. | ||
| ServiceSpeech_Store | 00337 | LD A,(HL) | Queue this allophone in the speech buffer. | |
| 00338 | LD (BC),A | |||
| 00339 | DEC BC | |||
| 00340 | CALL CheckMemory | Call CheckMemory and jump to ServiceSpeech_Flush if the buffer has hit *RAMTOP. | ||
| 00343 | JR C,ServiceSpeech_Flush | |||
| 00345 | BIT 7,(HL) | Jump to ServiceSpeech_Commit if this was the last allophone of the word. | ||
| 00347 | JR NZ,ServiceSpeech_Commit | |||
| 00349 | INC HL | Move to the next allophone. | ||
| 00350 | JR ServiceSpeech_Store | Jump to ServiceSpeech_Store. | ||
| ServiceSpeech_Flush | 00352 | CALL ReadBufferPointer | Call ReadBufferPointer. | |
| ServiceSpeech_Commit | 00355 | CALL WriteBufferPointer | Call WriteBufferPointer. | |
|
The SP0256 is the speech-synthesiser chip. Read its busy flag at 4096 and send the next queued allophone if it is idle.
|
||||
| FeedAllophone | 00358 | LD A,(4096) | Read the SP0256 status from 4096. | |
| 00361 | BIT 0,A | Jump to ExitInterrupt if the chip is still busy. | ||
| 00363 | JR NZ,ExitInterrupt | |||
| 00365 | LD A,(23610) | Fetch *ERR_NR. | ||
| 00368 | RLA | Call ResetBufferPointer if BASIC is not reporting an error. | ||
| 00369 | CALL NC,ResetBufferPointer | |||
| 00372 | CALL CompareBuffer | Call CompareBuffer and jump to FeedAllophone_Write if there is something left to say. | ||
| 00375 | JR NZ,FeedAllophone_Write | |||
| 00377 | XOR A | Silence the SP0256 and jump to ExitInterrupt. | ||
| 00378 | LD (4096),A | |||
| 00381 | JR ExitInterrupt | |||
|
The SP0256 is idle; write the next queued allophone.
|
||||
| FeedAllophone_Write | 00383 | LD A,6 | Call ReadWorkspace for the next allophone. | |
| 00385 | CALL ReadWorkspace | |||
| 00388 | LD DE,12288 | Use the low-intonation port (12288). | ||
| 00391 | BIT 6,A | Jump to FeedAllophone_Port if bit 6 is reset. | ||
| 00393 | JR Z,FeedAllophone_Port | |||
| 00395 | INC DE | Use the high-intonation port instead (12289). | ||
| FeedAllophone_Port | 00396 | LD (DE),A | Select the intonation. | |
| 00397 | LD (4096),A | Write the allophone to the SP0256. | ||
| 00400 | OR A | Work out how many bytes remain in the queue. | ||
| 00401 | SBC HL,BC | |||
| 00403 | INC BC | Step the queue pointer on one byte. | ||
| 00404 | PUSH HL | Stash the remaining length on the stack. | ||
| 00405 | CALL WriteBufferPointer | Call WriteBufferPointer. | ||
| 00408 | LD A,6 | Call ReadWorkspace for the queue start. | ||
| 00410 | CALL ReadWorkspace | |||
| 00413 | LD D,H | Point the copy at the previous queue byte. | ||
| 00414 | LD E,L | |||
| 00415 | DEC HL | |||
| 00416 | POP BC | Restore the remaining length from the stack. | ||
| 00417 | LDDR | Shuffle the queued allophones down. | ||
|
Restore the Spectrum registers and page its ROM back in.
|
||||
| ExitInterrupt | 00419 | POP DE | Restore DE, BC, AF and HL from the stack. | |
| 00420 | POP BC | |||
| 00421 | POP AF | |||
| 00422 | POP HL | |||
| 00423 | EI | Enable interrupts. | ||
| 00424 | JP HandleInterrupt | Jump to HandleInterrupt. | ||
| Prev: 00000 | Up: Map | Next: 00427 |