;-------------------------------------------------
;
;	AKI-H8 VCF module : November 1998
;
;-------------------------------------------------

;##### 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
pbddr	.equ	h'0fffd4
pbdr	.equ	h'0fffd6
iprb	.equ	h'0ffff8
tstr	.equ	h'0fff60
tsnc	.equ	h'0fff61
tmdr	.equ	h'0fff62
tfcr	.equ	h'0fff63
toer	.equ	h'0fff90
tocr	.equ	h'0fff91
tcr0	.equ	h'0fff64
tior0	.equ	h'0fff65
tier0	.equ	h'0fff66
tsr0	.equ	h'0fff67
tcnt0	.equ	h'0fff68
gra0	.equ	h'0fff6a
grb0	.equ	h'0fff6c
dadr0	.equ	h'0fffdc
dadr1	.equ	h'0fffdd
dacr	.equ	h'0fffde
dastcr	.equ	h'0fff5c
addra	.equ	h'0fffe0
adcsr	.equ	h'0fffe8
adcr	.equ	h'0fffe9

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

;##### Work RAM Data Defines #####
	.section ram,data,locate=h'0fef10
timer1	.res.w	1
timer2	.res.w	1
rx_top	.res.w	1
rx_end	.res.w	1
old	.res.w	1
oldold	.res.w	1
rsb	.res.b	1
channel	.res.b	1
dcb	.res.b	1
keyno	.res.b	1
data	.res.b	1
led	.res.b	1
flag	.res.b	1
cutoff	.res.b	1
mode	.res.b	1
remain	.res.b	1
phase	.res.b	1

	.org	h'0ff400
rx_fifo	.res.b	1024

;***** Constant Table Defines *****
	.section rom,data,locate=h'001000
table_c:
        .data.w 15446,-5462,12796,25593,12796,0,0,0
        .data.w 16095,-5697,11968,23937,11968,0,0,0
        .data.w 16747,-5944,11158,22317,11158,0,0,0
        .data.w 17403,-6204,10366,20733,10366,0,0,0
        .data.w 18063,-6477,9594,19188,9594,0,0,0
        .data.w 18726,-6764,8841,17682,8841,0,0,0
        .data.w 19059,-6913,8472,16945,8472,0,0,0
        .data.w 19393,-7065,8109,16218,8109,0,0,0
        .data.w 19728,-7221,7751,15502,7751,0,0,0
        .data.w 20064,-7381,7398,14797,7398,0,0,0
        .data.w 20401,-7544,7051,14103,7051,0,0,0
        .data.w 20739,-7712,6710,13421,6710,0,0,0
        .data.w 21078,-7883,6375,12751,6375,0,0,0
        .data.w 21418,-8058,6046,12093,6046,0,0,0
        .data.w 21759,-8238,5723,11447,5723,0,0,0
        .data.w 22101,-8422,5407,10814,5407,0,0,0
        .data.w 22444,-8610,5097,10194,5097,0,0,0
        .data.w 22788,-8802,4793,9587,4793,0,0,0
        .data.w 23133,-8999,4497,8995,4497,0,0,0
        .data.w 23479,-9200,4208,8416,4208,0,0,0
        .data.w 23826,-9406,3926,7852,3926,0,0,0
        .data.w 24174,-9617,3651,7303,3651,0,0,0
        .data.w 24523,-9832,3384,6769,3384,0,0,0
        .data.w 24873,-10052,3125,6251,3125,0,0,0
        .data.w 25223,-10278,2874,5749,2874,0,0,0
        .data.w 25575,-10508,2632,5264,2632,0,0,0
        .data.w 25928,-10744,2398,4796,2398,0,0,0
        .data.w 26282,-10985,2173,4346,2173,0,0,0
        .data.w 26636,-11232,1957,3915,1957,0,0,0
        .data.w 26991,-11484,1751,3502,1751,0,0,0
        .data.w 27348,-11742,1554,3108,1554,0,0,0
        .data.w 27705,-12005,1367,2734,1367,0,0,0
        .data.w 28063,-12275,1190,2381,1190,0,0,0
        .data.w 28421,-12551,1025,2050,1025,0,0,0
        .data.w 28781,-12833,870,1740,870,0,0,0
        .data.w 29141,-13121,726,1452,726,0,0,0
        .data.w 29501,-13416,594,1189,594,0,0,0
        .data.w 29863,-13717,474,949,474,0,0,0
        .data.w 30224,-14025,367,734,367,0,0,0
        .data.w 30587,-14340,272,545,272,0,0,0
        .data.w 30949,-14662,191,382,191,0,0,0

;***** Reset --> Initialize --> Main Loop *****
	.section program,code,locate=h'002000
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'00100011,r0l
	mov.b	r0l,@tcr0		; Timer0 init : 2MHz clock
	bclr	#0,@tsr0		; Clear IMFA
	bset	#0,@tier0		; timer INT set
	mov.w	#99,r0			; 50usec INT
	mov.w	r0,@gra0
	mov.b	#b'11111111,r0l
	mov.b	r0l,@pbddr		; set : Port[B] all output
	mov.b	#b'01100000,r0l
	mov.b	r0l,@dacr		; D/A 0 enable !
	mov.b	#b'00000000,r0l
	mov.b	r0l,@adcsr		; A/D port0
	bclr.b	#7,@adcr		; non trigger
	jsr	@wait_500msec
	mov.b	#b'01110000,r0l		; tx/rx start !
	mov.b	r0l,@scr
	bset	#0,@tstr		; timer start !
	bset.b	#5,@adcsr		; A/D Start !
	andc.b	#b'01111111,ccr		; interrupt enable
	mov.b	#0,r0l
	mov.b	r0l,@cutoff
	mov.b	r0l,@remain
	mov.b	#1,r0l
	mov.b	r0l,@mode
	mov.b	#30,r0l
	mov.b	r0l,@phase
loop:
	jsr	@timer_check
	jsr	@rx_midi_check
	jmp	@loop

;***** SCI init / MIDI Transmit 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
	mov.b	#b'00001000,r0l
	mov.b	r0l,@iprb		; SCI0-int priority UP !
	rts

;***** 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
int_timer0:
	push.w	r0
	mov.b	#1,r0l
	mov.b	r0l,@flag
	btst	#0,@tsr0
	bclr	#0,@tsr0		; Clear IMFA
	pop.w	r0
	rte
timer_check:
	mov.b	@flag,r0l
	cmp.b	#0,r0l
	bne	_timer_event
	rts
_timer_event:
	mov.b	#0,r0l
	mov.b	r0l,@flag
	btst.b	#7,@adcsr		; dummy
	mov.w	@addra,r0		; now data
	bclr.b	#7,@adcsr
	bset.b	#5,@adcsr		; next A/D Start !
	xor.b	#b'10000000,r0h
	mov.w	@old,r1			; old -> r1
	mov.w	@oldold,r2		; oldold -> r2
	mov.w	r1,@oldold		; next oldold
	mov.b	@cutoff,r3l
	mov.b	#0,r3h
	shal.w	r3
	shal.w	r3
	shal.w	r3
	shal.w	r3
	bset.b	#4,r3h
	mov.w	#0,e3			; coef addressing -> er3
	mov.w	@er3,r6			; a1 -> r6
	mulxs.w	r1,er6			; old * a1 -> er6
	inc.w	#2,r3			; next coef
	mov.w	@er3,r5			; a2 -> r5
	mulxs.w	r2,er5			; oldold * a2 -> er5
	add.w	e5,e6			; e5 + e6 -> e6
	add.w	e6,r0			; e6 + now -> r0
	mov.w	r0,@old			; next old
	inc.w	#2,r3			; next coef
	mov.w	@er3,r4			; b0 -> r4
	mulxs.w	r0,er4			; r0 * r4 -> er4
	inc.w	#2,r3			; next coef
	mov.w	@er3,r6			; b1 -> r6
	mulxs.w	r1,er6			; old * b1 -> er6
	inc.w	#2,r3			; next coef
	mov.w	@er3,r5			; b2 -> r5
	mulxs.w	r2,er5			; oldold * b2 -> er5
	add.w	e5,e6			; e5 + e6 -> e6
	add.w	e6,e4			; e6 + e4 -> e4
	mov.w	e4,r0
	xor.b	#b'10000000,r0h
	mov.b	r0h,@dadr0
	jsr	@trigger
	rts

trigger:
	mov.w	@timer1,r0
	inc.w	#1,r0
	mov.w	r0,@timer1
	cmp.w	#350,r0
	beq	_tim_hit
	rts
_tim_hit:
	mov.w	#0,r0
	mov.w	r0,@timer1
	mov.b	@mode,r0l
	cmp.b	#1,r0l
	beq	_trig_go
	rts
_trig_go:
	mov.b	@phase,r0h
	cmp.b	#30,r0h
	bne	_trig_2
	rts
_trig_2:
	inc.b	r0h
	mov.b	r0h,@phase
	mov.b	r0h,@cutoff
	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'd0,r0l		; D0 cutoff change ?
	beq	_2_d0
	cmp.b	#h'c0,r0l		; C0 trigger mode ?
	beq	_2_c0
	rts
_2_d0:
	mov.b	@data,r0l
	mov.b	r0l,@cutoff
	mov.b	#0,r0l
	mov.b	r0l,@mode
	rts
_2_c0:
	mov.b	#1,r0l
	mov.b	r0l,@mode
	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		; 90 note event ?
	beq	_3_hit
	cmp.b	#h'80,r0l		; 80 note event ?
	beq	_3_off
	rts
_3_hit:
	cmp.b	#0,r0h			; velociry > 0 ?
	bne	_3_cont
_3_off:
	mov.b	@remain,r0l
	dec.b	r0l
	mov.b	r0l,@remain
	rts
_3_pass:
	rts
_3_cont:
	mov.b	@keyno,r0l
	cmp.b	#24,r0l
	bmi	_3_pass
	cmp.b	#97,r0l
	bpl	_3_pass
	mov.b	@keyno,r0l
	mov.b	r0l,@pbdr		; write to Port[B]
	mov.b	@remain,r0l
	inc.b	r0l
	mov.b	r0l,@remain
	cmp.b	#1,r0l
	bne	_3_pass
	mov.b	#0,r0l
	mov.b	r0l,@phase
	rts

	.end
