Prev: 00000 Up: Map Next: 00427
00056: Handle Interrupt
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