diff --git a/mocktest/speech.h b/mocktest/speech.h index 4bc798e..d9d1263 100644 --- a/mocktest/speech.h +++ b/mocktest/speech.h @@ -13,10 +13,9 @@ extern uint8_t *speechData; extern uint16_t speechLen; extern uint8_t speechBusy; -extern uint16_t outptr; -extern uint16_t endptr; extern void setupSpeech(void); +extern void unsetupSpeech(void); #endif /* speech_h */ diff --git a/mocktest/speech.s b/mocktest/speech.s index a8b388e..341ad82 100644 --- a/mocktest/speech.s +++ b/mocktest/speech.s @@ -7,139 +7,169 @@ ; - .export _setupSpeech, _speechData, _speechLen, _speechBusy - .export _outptr, _endptr -; .interruptor speechIRQ + .export _setupSpeech, _unsetupSpeech + .export _speechData, _speechLen, _speechBusy -OUTPTR := $FB ;START OF DATA POINTER -IRQL := $03FE ;INTERRUPT VECTOR, LOW BYTE -IRQH := $03FF ;INTERRUPT VECTOR, HIGH BYTE -BASE := $C440 ;FIRST SPEECH CHIP -DURPHON := BASE ;REGISTER 0 OF SPEECH CHIP -INFLECT := BASE+$01 ;REGISTER 1 OF SPEECH CHIP -RATEINF := BASE+$02 ;REGISTER 2 OF SPEECH CHIP -CTTRAMP := BASE+$03 ;REGISTER 3 OF SPEECH CHIP -FILFREQ := BASE+$04 ;REGISTER 4 OF SPEECH CHIP +TMPPTR := $FB ; Temporary pointer used in interrupt handler +IRQL := $03FE ; Interrupt vector, low byte +IRQH := $03FF ; Interrupt vector, high byte +BASE := $C440 ; First speech chip +DURPHON := BASE ; Register 0 of speech chip +INFLECT := BASE+$01 ; Register 1 of speech chip +RATEINF := BASE+$02 ; Register 2 of speech chip +CTTRAMP := BASE+$03 ; Register 3 of speech chip +FILFREQ := BASE+$04 ; Register 4 of speech chip DDRB := $C402 DDRA := $C403 -PCR := $C48C ;PERIPHERAL CONTROL REG-6522 -IFR := $C48D ;INTERRUPT FLAG REG-6522 +PCR := $C48C ; Peripheral control register, 6522 +IFR := $C48D ; Interrupt flag register, 6522 IER := $C48E .DATA -speechIRQ: .byte $60, <_interr, >_interr ; RTS plus two dummy bytes _speechData: .byte $00, $00 _speechLen: .byte $00, $00 _outptr: .byte $00, $00 _endptr: .byte $00, $00 _speechBusy: .byte $00 +_irqLandingPad: .byte $4C, $00, $00 .CODE .proc _setupSpeech - SEI ;DISABLE INTERRUPTS - LDA #<_interr ;SET INTERRUPT VECTOR - STA IRQL ;TO POINT TO INTERRUPT - LDA #>_interr ;SERVICE ROUTINE - STA IRQH -; LDA #$4C ; JMP opcode -; STA speechIRQ - LDA #$00 - STA DDRA - STA DDRB + sei ; Disable interrupts - LDA _speechData+1 ;GET HIGH ADDRESS OF DATA - STA OUTPTR+1 ;STORE IN WORK POINTER - LDA _speechData ;GET LOW ADDRESS OF DATA - STA OUTPTR ;STORE LOW BYTE + lda IRQL ; Store the old interrupt vector + sta _irqLandingPad+1 + lda IRQH + sta _irqLandingPad+2 - LDA _speechLen+1 ;GET HIGH LENGTH BYTE - CLC - ADC _speechData+1 ;AND ADD TO BASE ADDRESS - STA _endptr+1 ;STORE END ADDRESS - LDA _speechLen ;GET LOW LENGTH BYTE - CLC - ADC _speechData ;AND ADD TO BASE ADDRESS - BCC @L2 ;CHECK FOR PAGE BOUNDARY - INC _endptr+1 + lda #<_interr ; Set interrupt vector + sta IRQL ; to point to interrupt + lda #>_interr ; service routine + sta IRQH + lda #$00 + sta DDRA + sta DDRB + + lda _speechData+1 ; Get high address of data + sta _outptr+1 ; Store in work pointer + lda _speechData ; Get low address of data + sta _outptr ; Store low byte + + lda _speechLen+1 ; Get high length byte + clc + adc _speechData+1 ; And add to base address + sta _endptr+1 ; Store end address + lda _speechLen ; Get low length byte + clc + adc _speechData ; And add to base address + bcc @L2 ; Check for page boundary + inc _endptr+1 @L2: - STA _endptr ;STORE END ADDRESS + sta _endptr ; Store end address - LDA #$FF ;SET BUSY FLAG - STA _speechBusy ;AND SET PERIPHERAL CONTROL - LDA #$0C ;REGISTER TO RECOGNIZE - STA PCR ;SIGNAL FROM SPEECH CHIP - LDA #$80 ;RAISE CTRL BIT IN REGISTER 3 - STA CTTRAMP - LDA #$C0 ;SET TRANSITIONED INFLECTION - STA DURPHON ;MODE IN REGISTER 0 - LDA #$70 ;LOWER CTRL BIT - STA CTTRAMP - LDA #$82 ;ENABLE 6522 INTERRUPTS - STA IER - CLI ;CLEAR INTERRUPT MASK - RTS ;RETURN TO CALLER + lda #$FF ; Set busy flag + sta _speechBusy ; And set peripheral control + lda #$0C ; Register to recognize + sta PCR ; Signal from speech chip + lda #$80 ; Raise control bit in register 3 + sta CTTRAMP + lda #$C0 ; Set transitioned inflection + sta DURPHON ; Mode in register 0 + lda #$70 ; Lower control bit + sta CTTRAMP + lda #$82 ; Enable 6522 interrupts + sta IER + cli ; Clear interrupt mask + rts ; Return to caller +.endproc + + +.proc _unsetupSpeech + sei ; Restore the old interrupt vector + lda _irqLandingPad+1 + sta IRQL + lda _irqLandingPad+2 + sta IRQH + cli + rts .endproc .proc _interr - PHA - TXA ;SAVE REGISTERS - PHA - TYA - PHA - LDA IFR - BPL @L2 - LDA #$02 ;CLEAR INTERRUPT FLAG - STA IFR - LDY #$00 ;INIT REGISTERS - LDX #$04 - LDA OUTPTR+1 - CMP _endptr+1 - BCC @L1 - BNE @L5 - LDA OUTPTR ;CHECK FOR END OF DATA FILE - CMP _endptr - BCC @L1 ;IF NOT THEN CONTINUE + pha ; Save accumulator + lda IFR + bmi @L4 ; If we have 6522 interrupt jump to L4 + pla ; Otherwise restore the accumulator + jmp _irqLandingPad ; And jump to the old interrupt handler +@L4: + txa ; Save other registers + pha + tya + pha + lda #$02 ; Clear interrupt flag + sta IFR + ldy #$00 ; Init registers + ldx #$04 + lda _outptr+1 + cmp _endptr+1 + bcc @L1 + bne @L5 + lda _outptr ; Check for end of data file + cmp _endptr + bcc @L1 ; If not, then continue @L5: - LDA #$00 ;IF END, TURN EVERYTHING OFF - STA DURPHON ;STORE PAUSE PHONEME - LDA #$70 ;ZERO AMPLITUDE - STA CTTRAMP - LDA #$00 ;CLEAR BUSY FLAG - STA _speechBusy - LDA #$02 ;CLEAR INTERRUPT ENABLE - STA IER ;IN 6522 - LDA #$FF - STA DDRA - LDA #$07 - STA DDRB + lda #$00 ; If end, turn everything off + sta DURPHON ; Store pause phoneme + lda #$70 ; Zero amplitude + sta CTTRAMP + lda #$00 ; Clear busy flag + sta _speechBusy + lda #$02 ; Clear interrupt enable + sta IER ; In 6522 + lda #$FF + sta DDRA + lda #$07 + sta DDRB @L2: - LDA OUTPTR - STA _outptr - LDA OUTPTR+1 - STA _outptr+1 - PLA ;RESTORE REGISTERS - TAY - PLA - TAX - PLA - RTI ;RETURN FROM INTERRUPT + pla ; Restore registers + tay + pla + tax + pla + rti ; Return from interrupt @L1: - LDA (OUTPTR),Y ;GET DATA - STA BASE,X ;STORE IN SPEECH CHIP - INC OUTPTR ;NEXT DATA - BNE @L3 - INC OUTPTR+1 + lda TMPPTR ; Save the value in the tmp pointer + pha + lda TMPPTR+1 + pha + lda _outptr ; Move the _outptr into the tmp pointer + sta TMPPTR + lda _outptr+1 + sta TMPPTR+1 +@L6: + lda (TMPPTR),Y ; Get data + sta BASE,X ; Store in speech chip + inc TMPPTR ; Next data + bne @L3 + inc TMPPTR+1 @L3: - DEX ;NEXT REGISTER - CPX #$FF ;LAST REGISTER? - BNE @L1 ;NO, CONTINUE - BEQ @L2 ;YES, RETURN + dex ; Next register + cpx #$FF ; Last register? + bne @L6 ; No, then continue + lda TMPPTR ; We are done, move tmp pointer to _outptr + sta _outptr + lda TMPPTR+1 + sta _outptr+1 + pla ; Restore the tmp pointer + sta TMPPTR+1 + pla + sta TMPPTR + jmp @L2 ; Finish the interrupt handler .endproc diff --git a/mocktest/speech_api.c b/mocktest/speech_api.c index 9ab78cb..bdcb0d4 100644 --- a/mocktest/speech_api.c +++ b/mocktest/speech_api.c @@ -15,15 +15,6 @@ bool speechIsBusy(void) { - static uint16_t old_outptr = 0; - if (old_outptr == 0) { - printf("endptr=%x\n", endptr); - } - if (old_outptr != outptr) { - old_outptr = outptr; - printf("%x ", old_outptr); - } - //printf("busy=0x%x, outptr=0x%x, endptr=0x%x\n", speechBusy, outptr, endptr); return (speechBusy != 0); }