;-----------------------------------------------------------
;
;	2 voice MIDI chime : September 1998
;
;		MIDI = 1ch, 2ch
;		PWM = program Change 0/1 (0-127)
;		Decay Speed = program Change 2/3 (0-127)
;
;-----------------------------------------------------------

;##### 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
TCR1	.equ	h'0fff6E
TIOR1	.equ	h'0fff6F
TIER1	.equ	h'0fff70
TSR1	.equ	h'0fff71
TCNT1	.equ	h'0fff72
GRA1	.equ	h'0fff74
GRB1	.equ	h'0fff76
TCR2	.equ	h'0fff78
TIOR2	.equ	h'0fff79
TIER2	.equ	h'0fff7A
TSR2	.equ	h'0fff7B
TCNT2	.equ	h'0fff7C
GRA2	.equ	h'0fff7E
GRB2	.equ	h'0fff80
TCR3	.equ	h'0fff82
TIOR3	.equ	h'0fff83
TIER3	.equ	h'0fff84
TSR3	.equ	h'0fff85
TCNT3	.equ	h'0fff86
GRA3	.equ	h'0fff88
GRB3	.equ	h'0fff8A
BRA3	.equ	h'0fff8C
BRB3	.equ	h'0fff8E
TCR4	.equ	h'0fff92
TIOR4	.equ	h'0fff93
TIER4	.equ	h'0fff94
TSR4	.equ	h'0fff95
TCNT4	.equ	h'0fff96
GRA4	.equ	h'0fff98
GRB4	.equ	h'0fff9A
BRA4	.equ	h'0fff9C
BRB4	.equ	h'0fff9E
dadr0	.equ	h'0fffdc
dadr1	.equ	h'0fffdd
dacr	.equ	h'0fffde
dastcr	.equ	h'0fff5c

;##### Vector Defines #####
	.section vector,data,locate=h'000000
	.data.l	start
	.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
timer3		.res.w	1
rx_top		.res.w	1
rx_end		.res.w	1
pitch0		.res.w	1
pitch1		.res.w	1
env0		.res.w	1
env1		.res.w	1
rsb		.res.b	1
channel		.res.b	1
dcb		.res.b	1
keyno		.res.b	1
data		.res.b	1
counter		.res.b	1
led		.res.b	1
tone0		.res.b	1
tone1		.res.b	1
speed0		.res.b	1
speed1		.res.b	1
	.org	h'0ff400
rx_fifo		.res.b	512

;***** Constant Table Defines *****
	.section rom,data,locate=h'001000
table_p:
	.data.w	61156,57722,54482,51424,48538,45814,43242,40816,38524,36362,34322,32396		; 00-11
	.data.w	61156,57722,54482,51424,48538,45814,43242,40816,38524,36362,34322,32396		; 12-23
	.data.w	61156,57722,54482,51424,48538,45814,43242,40816,38524,36362,34322,32396		; 24-35
        .data.w 30578,28861,27241,25712,24269,22907,21621,20408,19262,18181,17161,16198		; 36-47
        .data.w 15289,14430,13620,12856,12134,11453,10810,10204,9631,9090,8580,8099		; 48-59
        .data.w 7644,7215,6810,6428,6067,5726,5405,5102,4815,4545,4290,4049			; 60-71
        .data.w 3822,3607,3405,3214,3033,2863,2702,2551,2407,2272,2145,2024			; 72-83
        .data.w 1911,1803,1702,1607,1516,1431,1351,1275,1203,1136,1072,1012			; 84-95
        .data.w 955,901,851,803,758,715,675,637,601,568,536,506					; 96-107
        .data.w 477,450,425,401,379,357,337,318,300,284,268,253					; 108-119
        .data.w 238,225,212,200,189,178,168,159							; 120-127

;***** 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		; SCI0 initialize
	mov.b	#b'11111111,r0l
	mov.b	r0l,@pbddr		; set : Port[B] all output
	jsr	@wait_500msec
	mov.b	#b'01110000,r0l		; tx/rx start !
	mov.b	r0l,@scr
	andc	#b'01111111,ccr		; interrupt enable
	mov.b	#b'01000011,r0l		; Initialize TCR0
	mov.b	r0l,@TCR0		; clock= 2MHz
	mov.b	#b'01000011,r0l		; Initialize TCR1
	mov.b	r0l,@TCR1		; clock= 2MHz
	mov.b	#b'00000011,r0l
	mov.b	r0l,@tmdr		; PWM mode
	mov.b	#b'00010010,r0l		; Initialize TIOR0
	mov.b	r0l,@TIOR0		; 
	mov.b	#b'00010010,r0l		; Initialize TIOR1
	mov.b	r0l,@TIOR1		; 
	bset	#0,@tstr		; Start ITU ch0
	bset	#1,@tstr		; Start ITU ch1
	mov.b	#b'11100000,r0l
	mov.b	r0l,@dacr
	mov.b	#64,r0l
	mov.b	r0l,@tone0
	mov.b	r0l,@tone1
	mov.b	r0l,@speed0
	mov.b	r0l,@speed1
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
	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
timer_check:
	mov.w	@timer1,r1
	inc.w	#1,r1
	mov.w	r1,@timer1
	beq	_timer_1
	rts
_timer_1:
	jsr	@envelope_check
	mov.w	@timer2,r1
	inc.w	#1,r1
	mov.w	r1,@timer2
	cmp.w	#80,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,@pbdr		; write to Port[B]
	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	#1,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	#1,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	@channel,r1l
	or.b	r1l,r0l
	cmp.b	#h'0c0,r0l
	beq	_tc0
	cmp.b	#h'0c1,r0l
	beq	_tc1
	cmp.b	#h'0c2,r0l
	beq	_tc2
	cmp.b	#h'0c3,r0l
	beq	_tc3
	rts
_tc0:
	mov.b	r0h,@tone0
	mov.w	@pitch0,r2
	mov.b	r0h,r3h
	shal.b	r3h
	bset	#0,r3h
	mov.b	#h'ff,r3l
	extu.l	er3
	mulxu.w	r2,er3
	mov.w	e3,@GRA0		; New Frequency !
	rts
_tc1:
	mov.b	r0h,@tone1
	mov.w	@pitch1,r2
	mov.b	r0h,r3h
	shal.b	r3h
	bset	#0,r3h
	mov.b	#h'ff,r3l
	extu.l	er3
	mulxu.w	r2,er3
	mov.w	e3,@GRA1		; New Frequency !
	rts
_tc2:
	mov.b	r0h,@speed0
	rts
_tc3:
	mov.b	r0h,@speed1
	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'090,r0l
	beq	_ch0
	cmp.b	#h'091,r0l
	beq	_ch1
	rts
_ch0:
	cmp.b	#0,r0h
	bne	_ok_ch0
	rts
_ch1:
	cmp.b	#0,r0h
	bne	_ok_ch1
	rts
_ok_ch0:
	mov.b	@keyno,r0l
	shal.b	r0l
	extu.w	r0
	extu.l	er0
	mov.w	@(table_p,er0),r2
	mov.w	r2,@GRB0		; New Frequency !
	mov.w	r2,@pitch0
	mov.b	@tone0,r3h
	shal.b	r3h
	bset	#0,r3h
	mov.b	#h'ff,r3l
	extu.l	er3
	mulxu.w	r2,er3
	mov.w	e3,@GRA0		; New Frequency !
	mov.w	#h'FFFF,r1
	mov.w	r1,@env0		; New Envelope !
	rts
_ok_ch1:
	mov.b	@keyno,r0l
	shal.b	r0l
	extu.w	r0
	extu.l	er0
	mov.w	@(table_p,er0),r2
	mov.w	r2,@GRB1		; New Frequency !
	mov.w	r2,@pitch1
	mov.b	@tone1,r3h
	shal.b	r3h
	bset	#0,r3h
	mov.b	#h'ff,r3l
	extu.l	er3
	mulxu.w	r2,er3
	mov.w	e3,@GRA1		; New Frequency !
	mov.w	#h'FFFF,r1
	mov.w	r1,@env1		; New Envelope !
	rts

;***** Envelope check *****
envelope_check:
	mov.w	@env0,r2
	mov.b	@speed0,r3h
	shal.b	r3h
	bset	#0,r3h
	mov.b	#h'ff,r3l
	extu.l	er3
	mulxu.w	r2,er3
	mov.w	e3,@env0		; New Envelope !
	mov.w	@env1,r2
	mov.b	@speed1,r3h
	shal.b	r3h
	bset	#0,r3h
	mov.b	#h'ff,r3l
	extu.l	er3
	mulxu.w	r2,er3
	mov.w	e3,@env1		; New Envelope !
	mov.w	@env0,r1
	mov.b	r1h,@dadr0
	mov.w	@env1,r1
	mov.b	r1h,@dadr1		; D/A output !
	rts

	.end

