;-------------------------------------------------
;
;	CQ-Book2 TTL-DSP controller : January 1999
;
;-------------------------------------------------

;##### Port Defines #####
smr	.equ	h'0fffb0
brr	.equ	h'0fffb1
scr	.equ	h'0fffb2
tdr	.equ	h'0fffb3
ssr	.equ	h'0fffb4
rdr	.equ	h'0fffb5
p1ddr	.equ	h'0fffc0
p1dr	.equ	h'0fffc2
p2ddr	.equ	h'0fffc1
p2dr	.equ	h'0fffc3
p3ddr	.equ	h'0fffc4
p3dr	.equ	h'0fffc6
paddr	.equ	h'0fffd1
padr	.equ	h'0fffd3
pbddr	.equ	h'0fffd4
pbdr	.equ	h'0fffd6
iscr	.equ	h'0ffff4
ier	.equ	h'0ffff5

;##### Vector Defines #####
	.section vector,data,locate=h'000000
	.data.l	start
	.org	h'000030
	.data.l	int_irq0
	.org	h'0000d0
	.data.l	int_rx_error
	.data.l	int_rx_full

;##### Work RAM Data Defines #####
	.section ram,data,locate=h'0fef10
rx_top	.res.w	1
rx_end	.res.w	1
ev_top	.res.w	1
ev_end	.res.w	1
timer1	.res.w	1
timer2	.res.w	1
rsb	.res.b	1
dcb	.res.b	1
channel	.res.b	1
keyno	.res.b	1
data	.res.b	1
counter	.res.b	1
led	.res.b	1
ch	.res.b	1
prog	.res.b	1
flag	.res.b	1
init	.res.b	1
enum	.res.b	1
result	.res.b	1
active	.res.b	1
ctr	.res.b	1
assign	.res.b	16
	.org	h'0ff400
rx_fifo	.res.b	1024
ev_fifo	.res.b	1024

;***** Reset --> Initialize --> Main Loop *****
	.section program,code,locate=h'000100
start:
	mov.l	#h'0fff0f,er7		; stack pointer set
	mov.l	#h'0fef10,er2
	mov.w	#h'0fe0,r1
	mov.b	#0,r0l
_ram_clear:
	mov.b	r0l,@er2
	inc.l	#1,er2
	dec.w	#1,r1
	bne	_ram_clear
	jsr	@sci0_init		; SCI initialize
	mov.b	#b'11111111,r0l
	mov.b	r0l,@p1ddr		; set : Port[1] all output
	mov.b	r0l,@p2ddr		; set : Port[2] all output
	mov.b	r0l,@p3ddr		; set : Port[3] all output
	mov.b	r0l,@pbddr		; set : Port[B] all output
	mov.b	#b'10111111,r0l
	mov.b	r0l,@paddr		; set : Port[A] bit6=input
	mov.b	#0,r0l
	mov.b	r0l,@p1dr
	mov.b	r0l,@p2dr		; all key bit = OFF
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr
	mov.b	#b'00000001,r0l
	mov.b	r0l,@ier
	mov.b	r0l,@iscr		; IRQ0 down edge enable
	mov.b	#3,r0l
	mov.b	r0l,@enum		; default Envelope Speed
	mov.b	#b'10000000,r1h
	mov.l	#0,er0
_init_assign:
	mov.b	r1h,@(assign,er0)
	inc.b	r1h
	inc.b	r0l
	cmp.b	#16,r0l
	bne	_init_assign
	jsr	@wait_500msec
	mov.b	#b'01010000,r0l		; rx start !
	mov.b	r0l,@scr
	andc	#b'01111111,ccr		; interrupt enable
	jsr	@dsp_initial
loop:
	jsr	@timer_check
	jsr	@event_check
	jsr	@rx_midi_check
	bra	loop

;***** SCI init Routines *****
sci0_init:
	mov.b	#b'00000000,r0l
	mov.b	r0l,@scr
	mov.b	#b'00000000,r0l
	mov.b	r0l,@smr
	mov.b	#15,r0l
	mov.b	r0l,@brr
	mov.w	#500,r0
_sci0_wait:
	dec.w	#1,r0
	bne	_sci0_wait
	mov.b	@ssr,r0l		; (dummy read)
	mov.b	#0,r0l
	mov.b	r0l,@ssr
	rts

;***** Hand-Shake IRQ0 *****
int_irq0:
	push.w	r0
	mov.b	@flag,r0l
	beq	_irq_exit
	mov.b	#b'01111111,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr
	mov.b	@padr,r0l
	btst	#6,r0l
	bne	_irq_exit
	mov.b	#0,r0l
	mov.b	r0l,@flag
_irq_exit:
	pop.w	r0
	rte

;***** Timer / Counter Routines *****
wait_500msec:
	mov.l	#500,er1
_wait_1:
	jsr	@wait_1msec
	sub.l	#1,er1
	bne	_wait_1
	rts
wait_1msec:
	mov.l	#2048,er2
_wait_2:
	sub.l	#1,er2
	bne	_wait_2
	rts
timer_check:
	mov.w	@timer1,r1
	inc.w	#1,r1
	mov.w	r1,@timer1
	beq	_timer_1
	rts
_timer_1:
	mov.w	@timer2,r1
	inc.w	#1,r1
	mov.w	r1,@timer2
	cmp.w	#50,r1
	bne	_timer_2
	mov.w	#0,r1
	mov.w	r1,@timer2
_timer_2:
	mov.b	@counter,r0l
	inc.b	r0l
	mov.b	r0l,@counter
	mov.b	@led,r0l
	bnot	#7,r0l
	mov.b	r0l,@led
	mov.b	r0l,@p3dr		; write to Port[3]
	rts
led_monitor:
	mov.b	@led,r0l
	mov.b	r0l,r2l
	and.b	#b'10000000,r2l
	mov.b	r0h,r2h
	and.b	#b'01111111,r2h
	or.b	r2l,r2h
	mov.b	r2h,@led
	mov.b	r2h,@p3dr		; write to Port[3]
	rts

;***** Rx Interrupt / MIDI Receive Routines *****
int_rx_error:
	bclr	#5,@ssr
	bclr	#4,@ssr
	rte
int_rx_full:
	push.w	r0
	push.l	er5
	btst	#6,@ssr
	bclr	#6,@ssr
	mov.w	@rx_top,r5
	mov.w	#0,e5
	mov.b	@rdr,r0l
	mov.b	r0l,@(rx_fifo,er5)
	inc.w	#1,r5
	bclr	#2,r5h
	mov.w	r5,@rx_top
	pop.l	er5
	pop.w	r0
	rte
rx_midi_check:
	mov.w	@rx_top,r1
	mov.w	@rx_end,r5
	cmp.w	r1,r5
	bne	_rx_exist
	rts
_rx_exist:
	mov.w	#0,e5
	mov.b	@(rx_fifo,er5),r0h	; received data = [r0h]
	inc.w	#1,r5
	bclr	#2,r5h
	mov.w	r5,@rx_end
	btst	#7,r0h
	beq	running
	mov.b	r0h,r0l
	and.b	#b'11111000,r0l
	cmp.b	#b'11111000,r0l
	bne	_lower_f8
	rts
_lower_f8:
	and.b	#b'11110000,r0l
	cmp.b	#b'11110000,r0l
	bne	_lower_f0
	mov.b	#0,r0l
	mov.b	r0l,@rsb
	rts
_lower_f0
	mov.b	r0h,r0l
	and.b	#b'00001111,r0l
	mov.b	r0l,@channel
	mov.b	r0h,r0l
	and.b	#b'11110000,r0l
	mov.b	r0l,@rsb
	mov.b	#0,r0l
	mov.b	r0l,@dcb
	rts
running:
	mov.b	@rsb,r0l
	bne	_normal
	rts
_normal:
	cmp.b	#b'11000000,r0l
	beq	_2byte
	cmp.b	#b'11010000,r0l
	beq	_2byte
	mov.b	@dcb,r1l
	bne	_3byte
	inc.b	r1l
	mov.b	r1l,@dcb
	mov.b	r0h,@keyno
	rts
_2byte:
	mov.b	r0h,@data
	mov.b	@channel,r1l
	or.b	r1l,r0l
	cmp.b	#h'c0,r0l		; MIDI 1CH Prog ?
	beq	_program
	cmp.b	#h'cf,r0l		; MIDI 16CH Envelope Speed ?
	beq	_envelope
	rts
_program:
	mov.b	@data,r0l
	and.b	#b'00000111,r0l
	shll.b	r0l
	shll.b	r0l
	shll.b	r0l
	shll.b	r0l
	mov.b	r0l,@prog
	mov.b	r0l,r0h
	jsr	@led_monitor
	mov.b	@data,r0l
	and.b	#b'00000111,r0l
	mov.b	#0,r0h
	mov.w	#0,e0
	mov.b	@(env_speed,er0),r1h
	mov.b	r1h,@enum		; Envelope Speed
	rts
env_speed:
	.data.b	3,4,2,6,5,4,3,1
_envelope:
	mov.b	@data,r0l
	inc.b	r0l
	mov.b	r0l,@enum
	mov.b	r0l,r0h
	jsr	@led_monitor
	rts
_3byte:
	mov.b	#0,r1h
	mov.b	r1h,@dcb
	mov.b	r0h,@data
	mov.b	@channel,r1l
	or.b	r1l,r0l
	cmp.b	#h'90,r0l		; MIDI 1CH On ?
	beq	_90
	cmp.b	#h'80,r0l		; MIDI 1CH off ?
	beq	_off
	rts
_90:
	cmp.b	#0,r0h			; velocity=0 ?
	beq	_off
_on:
	jsr	@on_event_sequence
	rts
_off:
	jsr	@off_event_sequence
	rts

;***** Assigner / Handling for DSP Interface *****
off_event_sequence:
	mov.b	#1,r0l
	mov.b	r0l,@result
	jsr	@off_assigner
	mov.b	@result,r0l
	beq	_off_key
	rts
_off_key:
	mov.b	@ch,r0l
	btst	#3,r0l
	bne	_off_8
	mov.b	#0,r0h
	mov.w	#0,e0
	mov.b	@(off_key_bit,er0),r1l
	mov.b	@p1dr,r0l
	and.b	r1l,r0l
	mov.b	r0l,@p1dr
	rts
_off_8:
	and.b	#b'00000111,r0l
	mov.b	#0,r0h
	mov.w	#0,e0
	mov.b	@(off_key_bit,er0),r1l
	mov.b	@p2dr,r0l
	and.b	r1l,r0l
	mov.b	r0l,@p2dr
	rts
off_key_bit:
	.data.b	b'11111110,b'11111101,b'11111011,b'11110111
	.data.b	b'11101111,b'11011111,b'10111111,b'01111111
on_event_sequence:
	mov.b	#1,r0l
	mov.b	r0l,@result
	jsr	@on_assigner
	mov.b	@result,r0l
	beq	_on_key
	rts
_on_key:
	jsr	@ev_fifo_set
	mov.b	@keyno,r0h
	jsr	@led_monitor
	mov.b	@ch,r0l
	btst	#3,r0l
	bne	_on_8
	mov.b	#0,r0h
	mov.w	#0,e0
	mov.b	@(on_key_bit,er0),r1l
	mov.b	@p1dr,r0l
	or.b	r1l,r0l
	mov.b	r0l,@p1dr
	rts
_on_8:
	and.b	#b'00000111,r0l
	mov.b	#0,r0h
	mov.w	#0,e0
	mov.b	@(on_key_bit,er0),r1l
	mov.b	@p2dr,r0l
	or.b	r1l,r0l
	mov.b	r0l,@p2dr
	rts
on_key_bit:
	.data.b	1,2,4,8,16,32,64,128
off_assigner:
	mov.b	@keyno,r2l		; [R2L] MIDI off Keyno
	mov.l	#0,er0			; [R0L] check assigner ch
_off_loop_1:
	mov.b	@(assign,er0),r1l
	cmp.b	r2l,r1l
	beq	_off_hit_1
	inc.b	r0l
	cmp.b	#16,r0l
	bne	_off_loop_1
	rts
_off_hit_1:
	mov.b	r0l,@ch			; this CH !
	mov.b	#16,r1h
	mov.b	@active,r2h
	sub.b	r2h,r1h			; 16 - active
	or.b	#b'10000000,r1h
	mov.b	r1h,@(assign,er0)	; newest empty CH
	mov.b	@active,r0l
	dec.b	r0l
	mov.b	r0l,@active
	mov.b	#0,r0l
	mov.b	r0l,@result		; normal return
	rts
on_assigner:
	mov.b	@active,r0l
	cmp.b	#16,r0l			; 16 CH full ?
	bne	_on_empty
	rts
_on_empty:
	mov.b	@keyno,r2l		; [R2L] MIDI ON Keyno
	mov.l	#0,er0			; [R0L] check assigner ch
_on_loop_1:
	mov.b	@(assign,er0),r1l
	cmp.b	r2l,r1l
	beq	_on_error
	inc.b	r0l
	cmp.b	#16,r0l
	bne	_on_loop_1
	mov.b	#0,r0l			; [R0L] check assigner ch
_on_loop_2:
	mov.b	@(assign,er0),r1l
	btst	#7,r1l
	beq	_on_next
	cmp.b	#b'10000000,r1l		; oldest empty CH ?
	beq	_on_hit_1
	dec.b	r1l
	mov.b	r1l,@(assign,er0)	; shift to older CH
	bra	_on_next
_on_hit_1:
	mov.b	r0l,@ch			; this CH !
	mov.b	r2l,@(assign,er0)	; Keyno set to [assign]
_on_next:
	inc.b	r0l
	cmp.b	#16,r0l
	bne	_on_loop_2
	mov.b	@active,r0l
	inc.b	r0l
	mov.b	r0l,@active
	mov.b	#0,r0l
	mov.b	r0l,@result		; normal return
_on_error:
	rts
ev_fifo_set:
	mov.w	@ev_top,r4
	mov.w	#0,e4
	mov.b	@ch,r1l
	mov.b	r1l,@(ev_fifo,er4)	; MSB=0 : (1) CH
	inc.w	#1,r4
	bclr	#2,r4h
	mov.b	@keyno,r0l
	shal.b	r0l
	mov.b	#0,r0h
	mov.w	#0,e0
	mov.w	@(f_number,er0),r1
	mov.b	r1h,@(ev_fifo,er4)	; (2) fnum H
	inc.w	#1,r4
	bclr	#2,r4h
	mov.b	r1l,@(ev_fifo,er4)	; (3) fnum L
	inc.w	#1,r4
	bclr	#2,r4h
	mov.b	@ch,r1l
	or.b	#b'10000000,r1l
	mov.b	r1l,@(ev_fifo,er4)	; MSB=1 : (1) CH
	inc.w	#1,r4
	bclr	#2,r4h
	mov.b	@data,r1l
	shlr.b	r1l
	shlr.b	r1l
	shlr.b	r1l
	mov.b	@prog,r1h
	or.b	r1h,r1l
	mov.b	r1l,@(ev_fifo,er4)	; (2) prg,touch
	inc.w	#1,r4
	bclr	#2,r4h
	mov.b	@enum,r1l
	mov.b	r1l,@(ev_fifo,er4)	; (3) ENVnum
	inc.w	#1,r4
	bclr	#2,r4h
	mov.w	r4,@ev_top
	rts
f_number:
        .data.w 21,23,24,26,27,29,31,32				; 0-8
        .data.w 34,36,39,41,43,46,49,52				; 9-15
        .data.w 55,58,62,65,69,73,78,82				; 16-23
        .data.w 87,93,98,104,110,117,124,131			; 24-31
        .data.w 139,147,156,165,175,186,197,208			; 32-39
        .data.w 221,234,248,263,278,295,312,331			; 40-47
        .data.w 351,372,394,417,442,468,496,526			; 48-55
        .data.w 557,590,625,662,702,744,788,835			; 56-63
        .data.w 884,937,993,1052,1114,1181,1251,1325		; 64-71
        .data.w 1404,1488,1576,1670,1769,1874,1986,2104		; 72-79
        .data.w 2229,2362,2502,2651,2809,2976,3153,3340		; 80-87
        .data.w 3539,3749,3972,4209,4459,4724,5005,5303		; 88-95
        .data.w 5618,5952,6306,6681,7078,7499,7945,8418		; 96-103
        .data.w 8918,9448,10010,10606,11236,11904,12612,13362	; 104-111
        .data.w 14157,14999,15891,16836,17837,18897,20021,21212	; 112-119
        .data.w 22473,23809,25225,26725,28314,29998,31782,32767	; 120-127

;***** Event Check / DSP transfer *****
event_check:
	mov.b	@flag,r0l
	beq	_event_go
	rts
_event_go:
	mov.w	@ev_top,r1
	mov.w	@ev_end,r3
	cmp.w	r1,r3
	bne	_ev_exist
	rts
_ev_exist:
	mov.w	#0,e3
	mov.b	@(ev_fifo,er3),r1h	; data (1) -> [r1h]
	inc.w	#1,r3
	bclr	#2,r3h
	mov.b	@(ev_fifo,er3),r1l	; data (2) -> [r1l]
	inc.w	#1,r3
	bclr	#2,r3h
	mov.b	@(ev_fifo,er3),r2h	; data (3) -> [r2h]
	inc.w	#1,r3
	bclr	#2,r3h
	mov.w	r3,@ev_end
	btst	#7,r1h			; fnum / Enum ?
	bne	_ev_env
_ev_fn:
	mov.b	r1h,@pbdr
	mov.b	#b'11111011,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; mode = 00 latch
	mov.b	r1l,@pbdr
	mov.b	#b'11111101,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; fnum H latch
	mov.b	r2h,@pbdr
	mov.b	#b'11111110,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; fnum L latch
	mov.b	#1,r0l
	mov.b	r0l,@flag
	rts
_ev_env:
	and.b	#b'00001111,r1h
	or.b	#b'00100000,r1h
	mov.b	r1h,@pbdr
	mov.b	#b'11111011,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; mode = 10 latch
	mov.b	r1l,@pbdr
	mov.b	#b'11111101,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; prog+touch
	mov.b	r2h,@pbdr
	mov.b	#b'11111110,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; ENV speed
	mov.b	#1,r0l
	mov.b	r0l,@flag
	rts

;***** DSP Initialize Routine *****
dsp_initial:
	mov.b	#0,r0l
	mov.b	r0l,@init
_dsp_loop_1:
	jsr	@init_check_1
	mov.b	@init,r0l
	inc.b	r0l
	mov.b	r0l,@init
	cmp.b	#16,r0l
	bne	_dsp_loop_1
	mov.b	#0,r0l
	mov.b	r0l,@init
_dsp_loop_2:
	jsr	@init_check_2
	mov.b	@init,r0l
	inc.b	r0l
	mov.b	r0l,@init
	cmp.b	#16,r0l
	bne	_dsp_loop_2
	mov.b	#0,r0l
	mov.b	r0l,@init
_dsp_loop_3:
	jsr	@init_check_3
	mov.b	@init,r0l
	inc.b	r0l
	mov.b	r0l,@init
	cmp.b	#16,r0l
	bne	_dsp_loop_3
	mov.b	#0,r0l
	mov.b	r0l,@init
_dsp_loop_4:
	jsr	@init_check_4
	mov.b	@init,r0l
	inc.b	r0l
	mov.b	r0l,@init
	cmp.b	#16,r0l
	bne	_dsp_loop_4
	rts
init_check_1:
	mov.b	@flag,r0l
	bne	init_check_1
	mov.b	@init,r2h
	mov.b	r2h,@pbdr
	mov.b	#b'11111011,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; mode = 00 latch
	mov.b	#0,r1h
	mov.b	r1h,@pbdr
	mov.b	#b'11111110,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; data L
	mov.b	r1h,@pbdr
	mov.b	#b'11111101,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; data H
	mov.b	#1,r0l
	mov.b	r0l,@flag
_init_wait_1:
	mov.b	@flag,r0l
	bne	_init_wait_1
	rts
init_check_2:
	mov.b	@flag,r0l
	bne	init_check_2
	mov.b	@init,r2h
	or.b	#b'00010000,r2h
	mov.b	r2h,@pbdr
	mov.b	#b'11111011,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; mode = 01 latch
	mov.b	#0,r1h
	mov.b	r1h,@pbdr
	mov.b	#b'11111110,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; data L
	mov.b	r1h,@pbdr
	mov.b	#b'11111101,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; data H
	mov.b	#1,r0l
	mov.b	r0l,@flag
_init_wait_2:
	mov.b	@flag,r0l
	bne	_init_wait_2
	rts
init_check_3:
	mov.b	@flag,r0l
	bne	init_check_3
	mov.b	@init,r2h
	or.b	#b'00100000,r2h
	mov.b	r2h,@pbdr
	mov.b	#b'11111011,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; mode = 10 latch
	mov.b	#0,r1h
	mov.b	r1h,@pbdr
	mov.b	#b'11111110,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; data L
	mov.b	r1h,@pbdr
	mov.b	#b'11111101,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; data H
	mov.b	#1,r0l
	mov.b	r0l,@flag
_init_wait_3:
	mov.b	@flag,r0l
	bne	_init_wait_3
	rts
init_check_4:
	mov.b	@flag,r0l
	bne	init_check_4
	mov.b	@init,r2h
	or.b	#b'00110000,r2h
	mov.b	r2h,@pbdr
	mov.b	#b'11111011,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; mode = 11 latch
	mov.b	#0,r1h
	mov.b	r1h,@pbdr
	mov.b	#b'11111110,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; data L
	mov.b	r1h,@pbdr
	mov.b	#b'11111101,r0l
	mov.b	r0l,@padr
	mov.b	#b'11111111,r0l
	mov.b	r0l,@padr		; data H
	mov.b	#1,r0l
	mov.b	r0l,@flag
_init_wait_4:
	mov.b	@flag,r0l
	bne	_init_wait_4
	rts

	.end

