;-----------------------------------------------------------
;       8 channel universal A/D to MIDI : May 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
addrah  .equ    h'0fffe0
addrbh  .equ    h'0fffe2
addrch  .equ    h'0fffe4
addrdh  .equ    h'0fffe6
adcsr   .equ    h'0fffe8
adcr    .equ    h'0fffe9
iprb    .equ    h'0ffff8

;##### 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
tx_top  .res.w  1
tx_end  .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
ad_no   .res.b  1
ad_data .res.b  8
        .org    h'0ff400
rx_fifo .res.b  1024
        .org    h'0ff800
tx_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'00001000,r0l
        mov.b   r0l,@adcsr              ; A/D setting
        bclr.b  #7,@adcr                ; TRGE = 0
        mov.b   #b'11111111,r0l
        mov.b   r0l,@pbddr              ; set : Port[B] all output
        jsr     @wait_500msec
        bset.b  #5,@adcsr               ; A/D start !
        mov.b   #b'01110000,r0l         ; tx/rx start !
        mov.b   r0l,@scr
;;;;    andc    #b'01111111,ccr         ; interrupt enable
loop:
        jsr     @ad_check
        jsr     @timer_check
        jsr     @tx_midi_check
;;;;    jsr     @rx_midi_check
        jmp     @loop

;***** A/D Check Routine *****
ad_check:
        mov.w   @timer3,r1
        inc.w   #1,r1
        mov.w   r1,@timer3
        cmp.w   #h'0100,r1
        beq     _ad_in
        rts
_ad_in:
        mov.w   #0,r1
        mov.w   r1,@timer3
        btst.b  #7,@adcsr               ; A/D conv end ?
        bne     _ad_go
        rts
_ad_go:
        mov.b   @ad_no,r0l
        mov.b   r0l,r4l                 ; [r4l] = Data channel
        cmp.b   #0,r0l
        beq     _ad_1
        cmp.b   #4,r0l
        beq     _ad_1
        cmp.b   #1,r0l
        beq     _ad_2
        cmp.b   #5,r0l
        beq     _ad_2
        cmp.b   #2,r0l
        beq     _ad_3
        cmp.b   #6,r0l
        beq     _ad_3
        cmp.b   #3,r0l
        beq     _ad_4
        cmp.b   #7,r0l
        beq     _ad_4
_ad_1:
        mov.b   @addrah,r3h             ; Get A/D data
        bra     _ad_next
_ad_2:
        mov.b   @addrbh,r3h             ; Get A/D data
        bra     _ad_next
_ad_3:
        mov.b   @addrch,r3h             ; Get A/D data
        bra     _ad_next
_ad_4:
        mov.b   @addrdh,r3h             ; Get A/D data
        bra     _ad_next
_ad_next:
        inc.b   r0l
        and.b   #b'00000111,r0l
        mov.b   r0l,@ad_no
        bclr.b  #7,@adcsr               ; ADF clear
        mov.b   r0l,@adcsr              ; A/D setting
        bset.b  #3,@adcsr               ; speed
        bset.b  #5,@adcsr               ; A/D start !
        extu.w  r4
        extu.l  er4
;;;     xor.b   #h'ff,r3h
        shlr.b  r3h                     ; R3H = now
        mov.b   r3h,r3l                 ;  --> r3l
        mov.b   @(ad_data,er4),r2h      ; R2H = old
        cmp.b   r2h,r3l                 ; r3l-r2h
        bmi     _minus                  ; if minus
        sub.b   r2h,r3l                 ; r3l-r2h -> r3l
        cmp.b   #2,r3l                  ; r3l>2 ?
        bpl     _ad_ok
        rts
_minus:
        sub.b   r3l,r2h                 ; r2h-r3l -> r2h
        cmp.b   #2,r2h                  ; r2h>2 ?
        bpl     _ad_ok
        rts
_ad_ok:
        mov.b   r3h,@(ad_data,er4)      ; now -> old
        mov.b   #h'd0,r0h
        add.b   r4l,r0h
        jsr     @tx_fifo_set
        mov.b   r3h,r0h
        jsr     @tx_fifo_set
        jsr     @led_monitor
        rts

;***** 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
tx_midi_check:
        mov.w   @tx_top,r1
        mov.w   @tx_end,r6
        cmp.w   r1,r6
        bne     _tx_exist
        rts
_tx_exist:
        btst    #7,@ssr                 ; test TRDE
        bne     _tx_seq
        rts
_tx_seq:
        mov.w   #0,e6
        mov.b   @(tx_fifo,er6),r0l
        mov.b   r0l,@tdr
        bclr    #7,@ssr                 ; Transmit !
        inc.w   #1,r6
        bclr    #2,r6h
        mov.w   r6,@tx_end
        rts
tx_fifo_set:
        mov.w   @tx_top,r6
        mov.w   #0,e6
        mov.b   r0h,@(tx_fifo,er6)      ; transmit data = [r0h]
        inc.w   #1,r6
        bclr    #2,r6h
        mov.w   r6,@tx_top
        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:
        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    #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
        mov.b   r0l,r0h
        jsr     @tx_fifo_set
        mov.b   @data,r0h
        jsr     @tx_fifo_set
        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
        mov.b   r0l,r0h
        jsr     @tx_fifo_set
        mov.b   @keyno,r0h
        jsr     @tx_fifo_set
        jsr     @led_monitor
        mov.b   @data,r0h
        jsr     @tx_fifo_set
        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,@pbdr               ; write to Port[B]
        rts

        .end
