ssi263: add initial sc-02 test

This commit is contained in:
Vince Weaver 2021-09-14 00:33:45 -04:00
parent 55c0fc8e1b
commit 62a64808eb
6 changed files with 583 additions and 0 deletions

33
music/ssi-263/Makefile Normal file
View File

@ -0,0 +1,33 @@
include ../../Makefile.inc
DOS33 = ../../utils/dos33fs-utils/dos33
TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft
EMPTY_DISK = ../../empty_disk/empty.dsk
all: speech.dsk
speech.dsk: HELLO SSI263_TEST
cp $(EMPTY_DISK) speech.dsk
$(DOS33) -y speech.dsk SAVE A HELLO
$(DOS33) -y speech.dsk BSAVE -a 0x1000 SSI263_TEST
###
SSI263_TEST: ssi263_test.o
ld65 -o SSI263_TEST ssi263_test.o -C ../../linker_scripts/apple2_1000.inc
ssi263_test.o: ssi263_test.s ssi263.inc ssi263_detect.s ssi263_speech.s
ca65 -o ssi263_test.o ssi263_test.s -l ssi263_test.lst
###
HELLO: hello.bas
$(TOKENIZE) < hello.bas > HELLO
####
clean:
rm -f *~ *.o *.lst HELLO SSI263_TEST

102
music/ssi-263/hardware.inc Normal file
View File

@ -0,0 +1,102 @@
; HARDWARE LOCATIONS
KEYPRESS = $C000
KEYRESET = $C010
; SOFT SWITCHES
CLR80COL = $C000 ; PAGE1/PAGE1 normal
SET80COL = $C001 ; PAGE1/PAGE2 switches PAGE1 in Aux instead
EIGHTYCOLOFF = $C00C
EIGHTYCOLON = $C00D
TBCOLOR = $C022 ; IIgs text foreground / background colors
NEWVIDEO = $C029 ; IIgs graphics modes
SPEAKER = $C030
CLOCKCTL = $C034 ; bits 0-3 are IIgs border color
SET_GR = $C050
SET_TEXT = $C051
FULLGR = $C052
TEXTGR = $C053
PAGE1 = $C054
PAGE2 = $C055
LORES = $C056 ; Enable LORES graphics
HIRES = $C057 ; Enable HIRES graphics
AN3 = $C05E ; Annunciator 3
PADDLE_BUTTON0 = $C061
PADDL0 = $C064
PTRIG = $C070
; APPLESOFT BASIC ROUTINES
;NORMAL = $F273
HGR2 = $F3D8
;HGR = $F3E2
;BKGND0 = $F3F4 ; clear current page to A
HPOSN = $F411 ; (Y,X),(A) (values stores in HGRX,XH,Y)
HPLOT0 = $F457 ; plot at (Y,X), (A)
;COLOR_SHIFT = $F47E
;HLINRL = $F530 ; (X,A),(Y)
;HGLIN = $F53A ; line to (X,A),(Y)
;COLORTBL = $F6F6
; MONITOR ROUTINES
;HLINE = $F819 ; HLINE Y,$2C at A
;VLINE = $F828 ; VLINE A,$2D at Y
;CLRSCR = $F832 ; Clear low-res screen
;CLRTOP = $F836 ; clear only top of low-res screen
;SETCOL = $F864 ; COLOR=A
;ROM_TEXT2COPY = $F962 ; iigs
TEXT = $FB36 ; qboot
;TABV = $FB5B ; VTAB to A
;ROM_MACHINEID = $FBB3 ; iigs
;BELL = $FBDD ; ring the bell
;BASCALC = $FBC1 ;
;VTAB = $FC22 ; VTAB to CV
HOME = $FC58 ; Clear the text screen ; qboot
WAIT = $FCA8 ; delay 1/2(26+27A+5A^2) us
;CROUT1 = $FD8B
;SETINV = $FE80 ; INVERSE
;SETNORM = $FE84 ; NORMAL
COUT = $FDED ; output A to screen ; qboot
COUT1 = $FDF0 ; output A to screen ; qload
COLOR_BLACK = 0
COLOR_RED = 1
COLOR_DARKBLUE = 2
COLOR_PURPLE = 3
COLOR_DARKGREEN = 4
COLOR_GREY = 5
COLOR_MEDIUMBLUE = 6
COLOR_LIGHTBLUE = 7
COLOR_BROWN = 8
COLOR_ORANGE = 9
COLOR_GREY2 = 10
COLOR_PINK = 11
COLOR_LIGHTGREEN = 12
COLOR_YELLOW = 13
COLOR_AQUA = 14
COLOR_WHITE = 15
COLOR_BOTH_BLACK = $00
COLOR_BOTH_RED = $11
COLOR_BOTH_DARKBLUE = $22
COLOR_BOTH_DARKGREEN = $44
COLOR_BOTH_GREY = $55
COLOR_BOTH_MEDIUMBLUE = $66
COLOR_BOTH_LIGHTBLUE = $77
COLOR_BOTH_BROWN = $88
COLOR_BOTH_ORANGE = $99
COLOR_BOTH_PINK = $BB
COLOR_BOTH_LIGHTGREEN = $CC
COLOR_BOTH_YELLOW = $DD
COLOR_BOTH_AQUA = $EE
COLOR_BOTH_WHITE = $FF

4
music/ssi-263/hello.bas Normal file
View File

@ -0,0 +1,4 @@
5 HOME
100 PRINT "TRYING TO GET SPEECH ON"
110 PRINT "MOCKINGBOARD"
120 PRINT CHR$(4);"CATALOG"

100
music/ssi-263/ssi263.inc Normal file
View File

@ -0,0 +1,100 @@
SPEECH_PTRL = $FE
SPEECH_PTRH = $FF
SSI263_BASE = $40 ; First speech chip
SSI263_DRP = SSI263_BASE+$00 ; Reg0, Duration/Phoneme
SSI263_I = SSI263_BASE+$01 ; Reg1, Inflection
SSI263_RI = SSI263_BASE+$02 ; Reg2, Rate/Inflection
SSI263_CAA = SSI263_BASE+$03 ; Reg3, Control/Articulation/Amplitude
SSI263_F = SSI263_BASE+$04 ; Reg4, Filter Frequency
VIA6522_DDRB1 = $02 ; 6522 Data direction port B register
VIA6522_DDRA1 = $03 ; 6522 Data direction port A register
VIA6522_PCR2 = $8C ; 6522 #2 Peripheral control register
VIA6522_IFR2 = $8D ; 6522 #2 Interrupt flag register
VIA6522_IER2 = $8E ; 6522 #2 Interrupt enable register
VIA6522_IFR2_CA1 = $02
VIA6522_IER2_SET = $80
VIA6522_IER2_CA1 = $02
VIA6522_PCR2_CA2_LOW = $0C
VIA6522_PCR2_CA2_HI = $0E
VIA6522_PCR2_CA1_NEG = $00
VIA6522_PCR2_CA1_POS = $01
SSI263_CAA_CTL = $80 ; control bit
SSI263_DRP_TRANSITIONED_INFLECTION = $C0
SSI263_DRP_PHONEME_TIMING_IMMEDIATE_INFLECTION = $80
SSI263_DRP_FRAME_TIMING_IMMEDIATE_INFLECTION = $40
SSI263_DRP_DISABLE_AR = $00
DURATION_LONG = $00
PHONEME_PAUSE = $00 ; Pause
PHONEME_E = $01 ; mEEt
PHONEME_E1 = $02 ; bEnt
PHONEME_Y = $03 ; bEfore
PHONEME_YI = $04 ; Year
PHONEME_AY = $05 ; plEAse
PHONEME_IE = $06 ; anY
PHONEME_I = $07 ; sIx
PHONEME_A = $08 ; mAde
PHONEME_AI = $09 ; cAre
PHONEME_EH = $0A ; nEst
PHONEME_EH1 = $0B ; bElt
PHONEME_AE = $0C ; dAd
PHONEME_AE1 = $0D ; After
PHONEME_AH = $0E ; gOt
PHONEME_AH1 = $0F ; fAther
PHONEME_AW = $10 ; Office
PHONEME_O = $11 ; stOre
PHONEME_OU = $12 ; bOAt
PHONEME_OO = $13 ; lOOk
PHONEME_IU = $14 ; yOU
PHONEME_IU1 = $15 ; cOUld
PHONEME_U = $16 ; tUne
PHONEME_U1 = $17 ; cartOOn
PHONEME_UH = $18 ; wOnder
PHONEME_UH1 = $19 ; lOve
PHONEME_UH2 = $1A ; whAt
PHONEME_UH3 = $1B ; nUt
PHONEME_ER = $1C ; bIRd
PHONEME_R = $1D ; Roof
PHONEME_R1 = $1E ; Rug
PHONEME_R2 = $1F ; muetteR (German)
PHONEME_L = $20 ; Lift
PHONEME_L1 = $21 ; pLay
PHONEME_LF = $22 ; falL (final)
PHONEME_W = $23 ; Water
PHONEME_B = $24 ; Bag
PHONEME_D = $25 ; paiD
PHONEME_KV = $26 ; taG (glottal stop)
PHONEME_P = $27 ; Pen
PHONEME_T = $28 ; Tart
PHONEME_K = $29 ; Kit
PHONEME_HV = $2A ; (hold vocal)
PHONEME_HVC = $2B ; (hold vocal closure)
PHONEME_HF = $2C ; Heart
PHONEME_HFC = $2D ; (hold frictive closure)
PHONEME_HN = $2E ; (hold nasal)
PHONEME_Z = $2F ; Zero
PHONEME_S = $30 ; Same
PHONEME_J = $31 ; meaSure
PHONEME_SCH = $32 ; SHip
PHONEME_V = $33 ; Very
PHONEME_F = $34 ; Four
PHONEME_THV = $35 ; THere
PHONEME_TH = $36 ; wiTH
PHONEME_M = $37 ; More
PHONEME_N = $38 ; NiNe
PHONEME_NG = $39 ; raNG
PHONEME_CA = $3A ; mAerchen (German)
PHONEME_COH = $3B ; lOwe (French)
PHONEME_CU = $3C ; fUenf (German)
PHONEME_CUH = $3D ; menU (French)
PHONEME_E2 = $3E ; bittE (German)
PHONEME_LB = $3F ; Lube

View File

@ -0,0 +1,128 @@
;=============================
;=============================
; detect SSI263
;=============================
;=============================
; A = slot of mockingboard
detect_ssi263:
and #$7
ora #$c0 ; turn slot number into address
sta ssid_wc_smc1+2 ; update the read/write routines
sei ; disable IRQ
lda $3fe ; backup the IRQ handler
sta irq1backup
lda $3ff
sta irq2backup
lda #<mb_irq ; point IRQ handler to our code
sta $3fe
lda #>mb_irq
sta $3ff
; Set 6522#2 peripheral control register to recognize the signal
; from the speech chip.
lda #(VIA6522_PCR2_CA2_LOW|VIA6522_PCR2_CA1_NEG)
ldx #VIA6522_PCR2
jsr ssi263_d_write_chip
; Raise control bit in register 3 of SSI-263
lda #SSI263_CAA_CTL
ldx #SSI263_CAA
jsr ssi263_d_write_chip
; Transitioned inflection (when CTL is toggled)
lda #SSI263_DRP_TRANSITIONED_INFLECTION
ldx #SSI263_DRP
jsr ssi263_d_write_chip
; Lower control bit in SSI-263
lda #$70 ; CTL=0, T=6, AMP=0
ldx #SSI263_CAA
jsr ssi263_d_write_chip
; Enable 6522 interrupt on input CA2
lda #(VIA6522_IER2_SET|VIA6522_IER2_CA1)
ldx #VIA6522_IER2
jsr ssi263_d_write_chip
ldx #0 ; clear counts
ldy #0
cli ; enable interrupts
wait_irq:
lda irq_count ; see if irq happened
bne got_irq
iny ; otherwise increase counts
bne wait_irq
inx ;
bne wait_irq
got_irq:
sei ; disable interrupts
rts
;========================
; detection IRQ handler
;========================
mb_irq:
txa ; save X
pha
; Clear the 6522 interrupt flag
lda #VIA6522_IFR2_CA1
ldx #VIA6522_IFR2
jsr ssi263_d_write_chip
; disable speech
; Raise control bit in register 3 of SSI-263
lda #SSI263_CAA_CTL
ldx #SSI263_CAA
jsr ssi263_d_write_chip
; Disable talking on SSI-263 (when CTL is toggled)
lda #SSI263_DRP_DISABLE_AR
ldx #SSI263_DRP
jsr ssi263_d_write_chip
; Lower control bit in SSI-263
lda #$70 ; also T=7?
ldx #SSI263_CAA
jsr ssi263_d_write_chip
; increment our irq count
inc irq_count
; Disable 6522 interrupts
lda #VIA6522_IER2_CA1
ldx #VIA6522_IER2
jsr ssi263_d_write_chip
pla ; restore X
tax
lda $45 ; restore accumulator
rti ; return from interrupt
;========================
; write_chip
;========================
ssi263_d_write_chip:
ssid_wc_smc1:
sta $C000,X
rts
irq_count: .byte $00
irq1backup: .byte $00
irq2backup: .byte $00

View File

@ -0,0 +1,216 @@
;========================
; ssi263_write_chip
;========================
ssi263_write_chip:
wc_smc1:
sta $C000,X
rts
;========================
; read_chip
;========================
ssi263_read_chip:
rc_smc1:
lda $C000,X
rts
;========================
; ssi263_speech_init
;========================
; A = slot number of mockingboard
ssi263_speech_init:
sei ; disable interrupts
and #$7
ora #$c0 ; turn slot number into address
sta wc_smc1+2 ; update the read/write routines
sta rc_smc1+2
lda #<ssi263_speech_irq ; point IRQ handler to our code
sta $3fe
lda #>ssi263_speech_irq
sta $3ff
cli ; enable interrupts
rts
;============================
; ssi263_speech_shutdown
;============================
ssi263_speech_shutdown:
sei
rts
;=========================
; ssi263_speak
;=========================
; pointer to data in SPEECH_PTRL/H
ssi263_speak:
sei ; disable interrupts
; Set the busy flag
lda #$FF
sta speech_busy
; Set peripheral control register to recognize the signal from the
; speech chip.
lda #(VIA6522_PCR2_CA2_LOW|VIA6522_PCR2_CA1_NEG)
ldx #VIA6522_PCR2
jsr ssi263_write_chip
; Se transitioned inflection by setting value while toggling CTL
lda #SSI263_CAA_CTL
ldx #SSI263_CAA
jsr ssi263_write_chip
; Set transitioned inflection mode in register 0
lda #SSI263_DRP_TRANSITIONED_INFLECTION
ldx #SSI263_DRP
jsr ssi263_write_chip
; Lower control bit
lda #$70 ; also T=7
ldx #SSI263_CAA
jsr ssi263_write_chip
; Enable 6522 interrupts
lda #(VIA6522_IER2_SET|VIA6522_IER2_CA1)
ldx #VIA6522_IER2
jsr ssi263_write_chip
cli ; re-enable interrupts
rts
;====================
; speech interrupt
;====================
ssi263_speech_irq:
php ; save flags
cld
pha ; save A
txa
pha ; save X
tya
pha ; save Y
inc $0404 ; irq indicator on screen
; be sure it was a 6522#2 interrupt
ldx #VIA6522_IFR2
jsr ssi263_read_chip
bmi have_interrupt
; wasn't us, return to caller
; this assumes we can handle multiple interrupt sources
jmp end_interrupt
have_interrupt:
; Clear the 6522#2 CA interrupt flag
lda #VIA6522_IFR2_CA1
ldx #VIA6522_IFR2
jsr ssi263_write_chip
; Check if done with speech
ldy #0
lda (SPEECH_PTRL),Y
cmp #$ff
beq speech_end
not_end:
; Set the speech playing flag
lda #$ff
sta speech_playing
; Init registers
ldy #$00
ldx #SSI263_F ; start at end
register_loop:
; Get the next data
lda (SPEECH_PTRL),Y
; Store in the speech chip
jsr ssi263_write_chip
; Next data (inc 16 bit)
inc SPEECH_PTRL
bne no_oflo
inc SPEECH_PTRH
no_oflo:
; Go to next register
dex
; If we are not done the last register, then loop back to register loop
cpx #SSI263_BASE-1
bne register_loop
; Finish the interrupt handler
jmp end_interrupt
speech_end:
; If at the end, turn everything off
; Toggle CTL while DR set to disable A/!R
lda #SSI263_CAA_CTL
ldx #SSI263_CAA
jsr ssi263_write_chip
lda #SSI263_DRP_DISABLE_AR
ldx #SSI263_DRP
jsr ssi263_write_chip
; Zero amplitude
lda #$70
ldx #SSI263_CAA
jsr ssi263_write_chip
; Clear busy and playing flags
lda #$00
sta speech_busy
sta speech_playing
; Re-enable interrupt in 6522
lda #VIA6522_IER2_CA1
ldx #VIA6522_IER2
jsr ssi263_write_chip
end_interrupt:
pla
tay ; restore Y
pla
tax ; restore X
pla ; restore A
interrupt_smc:
lda $45 ; restore A (II+/IIe)
plp ; restore flags
rti ; return from interrupt
speech_busy: .byte $00
speech_playing: .byte $00