; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; * MIDI Merge Box - KTE???                                           8-304_a *
; * "Master - IC1"                                                            *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; * free-verze (c) 1/2003 CHD J.David                                         *
; * Zdrojový text pro makroasembler MetaLink a kompatibilní                   *
; * Kódování češtiny : ANSI                                                   *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

;                                     _\|/_
;                                   ( o   o )
;-------------------------------OOO-----V-----OOO------------------------------
;Hardware:
;krystal 12 MHz (1 sc. = 1 us)
;oba uP 89C2051

            $MOD2051
            $NOPAGING
            $PAGEWIDTH(120)
;           $NOSYMBOLS
;******************************************************************************
;Porty uP
;==============================================================================
BUSIN       EQU   P1    ;osmibitová datová sběrnice - vstup
;                 P3.0   RxD MIDI
;                 P3.1   TxD MIDI
IRQREQ      EQU   P3.2  ;BUS Data Reguest - Interrupt
IRQACK      EQU   P3.3  ;INT1 - BUS Data Acnowledge - Out
RESET1      EQU   P3.4  ;spouštění "error" - In/Out
RESET2      EQU   P3.5  ;řízení blikání LED-ERR - Out
LEDMSG      EQU   P3.7  ;LED - Message (on = 0)
;******************************************************************************
;Konstanty, vyhražená RAM
;==============================================================================
FIFOI       EQU   000Fh ;vstupní FIFO (91 byte)
FIFOO       EQU   006Ah ;výstupní FIFO (12 byte)
STACK       EQU   0076h ;zásobník (10 byte)
;==============================================================================


;******************************************************************************
;Mapa RAM
;==============================================================================
;Banka registrů 0 - používá hl. smyčka
;------------------------------------------------------------------------------
WRPTRO      EQU   R0    ;pointer pro zápis do FIFO-OUT pro main loop
WRPTROD     DATA  00h   ;dtto - direct
RDPTRI      EQU   R1    ;pointer pro čtení z FIFO-IN pro main loop
RDPTRID     DATA  01h   ;dtto - direct
FLTXM       EQU   R2    ;[02h] příznak aktivity vysílání UART
FLTXMD      DATA  02h   ;dtto - direct
;==============================================================================
;Banka registrů 1 - používá přerušení UART
;------------------------------------------------------------------------------
WRPTRI      EQU   R0    ;[08h] pointer pro zápis do FIFO-IN pro UART Rx
WRPTRID     DATA  08h   ;dtto - direct
RDPTRO      EQU   R1    ;[09h] pointer pro čtení z FIFO-OUT pro UART Tx
RDPTROD     DATA  09h   ;dtto - direct
;==============================================================================
;Přímo adresované proměnné
;------------------------------------------------------------------------------
DATABYTE    DATA  03h   ;byte přijatý z UART nebo BUS
DATMPTR     DATA  04h   ;pointer pořadí databyte v MSG - UART
DATBPTR     DATA  05h   ;pointer pořadí databyte v MSG - BUS
TXBYTE      DATA  06h   ;byte pro zápis do FIFO-OUT
STATBYTE    DATA  07h   ;Status byte naposled zapsaný do FIFO-OUT
REGB0       DATA  0Ah   ;registr byte z BUS - status byte (+ pomocný pro error)
REGB1       DATA  0Bh   ;registr byte z BUS - první databyte (+ pomocný pro error)
REGB2       DATA  0Ch   ;pomocný pro časování error
REGM0       DATA  0Dh   ;registr byte z MIDI - status byte
REGM1       DATA  0Eh   ;registr byte z MIDI - první databyte
;==============================================================================


;*******************************************************************************
;Vektory přerušení (a kratší obslužné rutiny)
;===============================================================================
            ORG   0000h
            JMP   init               ;inicializace
            ORG   0003h
            CLR   IRQREQ             ;příjem Request z BUS (vyšší úroveň přerušení)
            RETI
            ORG   000Bh
            SETB  LEDMSG             ;T0 - interval svícení LED-MSG (vyšší úroveň přerušení)
            CLR   TR0
            RETI
            ORG   0023h
            JBC   RI, srcv           ;UART - Rx
            JBC   TI, stxm           ;UART - Tx
            RETI
            ORG   0030h
;===============================================================================


;*******************************************************************************
;Obsluha přerušení UART - MIDI - Tx
;===============================================================================
;vysílá data z FIFO-OUT, po vyprázdnění FIFO-OUT konec vysílání
;-------------------------------------------------------------------------------
stxm:       PUSH  ACC
            PUSH  PSW
            MOV   PSW, #00001000b    ;banka reg. 1
stxm1:      MOV   A, RDPTRO
            CJNE  A, WRPTROD, stxm2
            MOV   FLTXMD, #0
            POP   PSW
            POP   ACC
            RETI
stxm2:      MOV   SBUF, @RDPTRO
            MOV   FLTXMD, #255
            INC   A
            CJNE  A, #STACK, stxm3
            MOV   A, #FIFOO
stxm3:      MOV   RDPTRO, A
            POP   PSW
            POP   ACC
            RETI
;===============================================================================


;*******************************************************************************
;Obsluha přerušení UART - MIDI - Rx
;===============================================================================
;Veškerá data se přesouvají do FIFO-IN, při přeplnění FIFO-IN je vyvolána chyba
;-------------------------------------------------------------------------------
srcv:       PUSH  ACC
            PUSH  PSW
            MOV   PSW, #00001000b    ;banka reg. 1
            MOV   A, WRPTRI
            INC   A
            CJNE  A, #FIFOO, srcv1
            MOV   A, #FIFOI
srcv1:      CJNE  A, RDPTRID, srcv2
            JMP   onerror            ;přetečení - error
srcv2:      MOV   @WRPTRI, SBUF
            MOV   WRPTRI, A
            POP   PSW
            POP   ACC
            RETI
;===============================================================================


;*******************************************************************************
;Inicializace
;===============================================================================
init:       CLR   RESET1             ;nastavení návěští resetovací sekvence
            MOV   R0, #07Fh          ;nulování interní RAM uP
inimem:     MOV   @R0, #0
            DJNZ  R0, inimem
            MOV   SP, #STACK-1       ;hloubka zásobníku (dle konstanty)
            ;------------------------ Proměnné
            MOV   WRPTRID, #FIFOI    ;pointer FIFO-IN
            MOV   RDPTRID, #FIFOI
            MOV   WRPTROD, #FIFOO    ;pointer FIFO-OUT
            MOV   RDPTROD, #FIFOO
            ;------------------------ SFR
            MOV   SCON, #01000000b   ;UART mód 1
            MOV   TH1, #255          ;BdRate=31250
            MOV   TL1, #255
            MOV   TMOD, #00100001b   ;T0 v módu 1, T1 v módu 2
            MOV   TCON, #01000001b   ;T1 běží, INT0 spouštěno hranou
            MOV   IP, #00000011b     ;T0, INT0 vyšší
            ;------------------------ Příprava na činnost
            ANL   TCON, #01010101b   ;smazat příznaky přerušení
            MOV   IE, #10010011b     ;povoleno : Global, UART, INT0, T0
            SETB  RESET1             ;odblokovat reset druhého procesoru
            JNB   RESET1, $          ;čekat na potvrzení konce resetu z druhého procesoru
            SETB  REN                ;povolen příjem MIDI
;===============================================================================


;*******************************************************************************
;Hlavní programová smyčka
;===============================================================================
;Střídavé čtení dat BUS a FIFO-IN, při kompletní Msg přesun do FIFO-OUT
;-------------------------------------------------------------------------------
main:       JB    IRQREQ, main1
            JMP   mb0                ;data z bus
main1:      MOV   A, RDPTRI
            CJNE  A, WRPTRID, mm0
            JB    RESET1, main       ;kontrola ERROR
            JMP   error
;===============================================================================
            ;Data z BUS
mb0:        MOV   DATABYTE, BUSIN
            SETB  IRQREQ
            CLR   IRQACK
            NOP
            SETB  IRQACK
            MOV   A, DATABYTE
            JNB   ACC.7, b_dat
            ANL   A, #0F0h           ;Status Byte
            CJNE  A, #0F0h, b_chn
            ;-------------------------------------------------------------------
            ;System Status Byte
            MOV   A, DATABYTE
            ANL   A, #0Fh
            RL    A
            MOV   DPTR, #dir_bsys
            JMP   @A+DPTR
dir_bsys:   AJMP  bsysn              ;Start SysEx - filtrovat
            AJMP  bsys1              ;MTC Qtr Frame
            AJMP  bsys2              ;Song Position Pointer
            AJMP  bsys1              ;Song Select
            AJMP  bsysn              ;nedefinováno - filtrovat
            AJMP  bsysn              ;nedefinováno - filtrovat
            AJMP  bsys0              ;Tune Request
            AJMP  bsysn              ;End SysEx - filtrovat
            AJMP  bsysx              ;Clock
            AJMP  bsysn              ;nedefinováno - filtrovat
            AJMP  bsysx              ;Start
            AJMP  bsysx              ;Continue
            AJMP  bsysx              ;Stop
            AJMP  bsysn              ;nedefinováno - filtrovat
            AJMP  bsysx              ;Active Sense
            AJMP  bsysx              ;Reset
            ;-------------------------------------------------------------------
b_chn:      ;Channel Status Byte
            MOV   A, DATABYTE
            SWAP  A
            ANL   A, #0Fh            ;číslo Msg
            ADD   A, #0F8h
            RL    A
            MOV   DPTR, #dir_bchn
            JMP   @A+DPTR
dir_bchn:   AJMP  bchn2              ;Note Off
            AJMP  bchn2              ;Note On
            AJMP  bchn2              ;Key Aftertouch
            AJMP  bchn2              ;Control Change
            AJMP  bchn1              ;Program Change
            AJMP  bchn1              ;Channel Aftertouch
            AJMP  bchn2              ;Pitch Wheel
            ;-------------------------------------------------------------------
b_dat:      ;Data Byte
            MOV   A, DATBPTR
            RL    A
            MOV   DPTR, #dir_bdat
            JMP   @A+DPTR
dir_bdat:   AJMP  main1              ;filtrace dat
            AJMP  bdat1              ;jednobytová Chnl Msg
            AJMP  bdat2              ;1. byte dvoubytové Chnl Msg
            AJMP  bdat3              ;2. byte dvoubytové Chnl Msg
            AJMP  bdat4              ;jednobytová System Msg
            AJMP  bdat5              ;1. byte dvoubytové System Msg
            AJMP  bdat6              ;2. byte dvoubytové System Msg
;===============================================================================
            ;Data z FIFO-IN
mm0:        MOV   DATABYTE, @RDPTRI
            INC   RDPTRI
            CJNE  RDPTRI, #FIFOO, mm1
            MOV   RDPTRI, #FIFOI
mm1:        MOV   A, DATABYTE
            JNB   ACC.7, m_dat
            ANL   A, #0F0h           ;Status Byte
            CJNE  A, #0F0h, m_chn
            ;-------------------------------------------------------------------
            ;System Status Byte
            MOV   A, DATABYTE
            ANL   A, #0Fh
            RL    A
            MOV   DPTR, #dir_msys
            JMP   @A+DPTR
dir_msys:   AJMP  msysn              ;Start SysEx - filtrovat
            AJMP  msys1              ;MTC Qtr Frame
            AJMP  msys2              ;Song Position Pointer
            AJMP  msys1              ;Song Select
            AJMP  msysn              ;nedefinováno - filtrovat
            AJMP  msysn              ;nedefinováno - filtrovat
            AJMP  msys0              ;Tune Request
            AJMP  msysn              ;End SysEx - filtrovat
            AJMP  msysx              ;Clock
            AJMP  msysn              ;nedefinováno - filtrovat
            AJMP  msysx              ;Start
            AJMP  msysx              ;Continue
            AJMP  msysx              ;Stop
            AJMP  msysn              ;nedefinováno - filtrovat
            AJMP  msysx              ;Active Sense
            AJMP  msysx              ;Reset
            ;-------------------------------------------------------------------
m_chn:      ;Channel Status Byte
            MOV   A, DATABYTE
            SWAP  A
            ANL   A, #0Fh            ;číslo Msg
            ADD   A, #0F8h
            RL    A
            MOV   DPTR, #dir_mchn
            JMP   @A+DPTR
dir_mchn:   AJMP  mchn2              ;Note Off
            AJMP  mchn2              ;Note On
            AJMP  mchn2              ;Key Aftertouch
            AJMP  mchn2              ;Control Change
            AJMP  mchn1              ;Program Change
            AJMP  mchn1              ;Channel Aftertouch
            AJMP  mchn2              ;Pitch Wheel
            ;-------------------------------------------------------------------
m_dat:      ;Data Byte
            MOV   A, DATMPTR
            RL    A
            MOV   DPTR, #dir_mdat
            JMP   @A+DPTR
dir_mdat:   AJMP  main               ;filtrace dat
            AJMP  mdat1              ;jednobytová Chnl Msg
            AJMP  mdat2              ;1. byte dvoubytové Chnl Msg
            AJMP  mdat3              ;2. byte dvoubytové Chnl Msg
            AJMP  mdat4              ;jednobytová System Msg, přenos
            AJMP  mdat5              ;1. byte dvoubytové System Msg
            AJMP  mdat6              ;2. byte dvoubytové System Msg
;===============================================================================
            ;Provádění Status Byte - BUS
            ;-------------------------------------------------------------------
            ;System
bsysn:      MOV   DATBPTR, #0
            JMP   main1
bsysx:      MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat status
            JMP   main1
bsys0:      MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat status
            MOV   STATBYTE, DATABYTE ;uložit nový aktuální status
            MOV   DATBPTR, #0        ;filtrovat data
            JMP   main1
bsys1:      MOV   DATBPTR, #4        ;na jediný databyte
            MOV   REGB0, DATABYTE
            JMP   main1
bsys2:      MOV   DATBPTR, #5        ;na 1. databyte
            MOV   REGB0, DATABYTE
            JMP   main1
            ;Channel
bchn2:      MOV   DATBPTR, #2        ;na 1. databyte
            MOV   REGB0, DATABYTE
            JMP   main1
bchn1:      MOV   DATBPTR, #1        ;na jediný databyte
            MOV   REGB0, DATABYTE
            JMP   main1
            ;-------------------------------------------------------------------
            ;Provádění Data Byte - BUS
bdat1:      MOV   A, REGB0
            CJNE  A, STATBYTE, bdat1_2
bdat1_1:    ;Running Status
            MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat databyte
            ;DATBPTR se nemění !
            JMP   main1
bdat1_2:    MOV   STATBYTE, A        ;uložit nový aktuální status
            MOV   TXBYTE, A
            CALL  outbuf             ;vyslat status byte
            SJMP  bdat1_1
bdat2:      INC   DATBPTR            ;na 2. databyte
            MOV   REGB1, DATABYTE
            JMP   main1
bdat3:      MOV   A, REGB0
            CJNE  A, STATBYTE, bdat3_2
bdat3_1:    MOV   TXBYTE, REGB1
            CALL  outbuf             ;vyslat první databyte
            MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat druhý databyte
            DEC   DATBPTR            ;zpět na 1. databyte - running status
            JMP   main1
bdat3_2:    MOV   STATBYTE, A        ;uložit nový aktuální status
            MOV   TXBYTE, A
            CALL  outbuf             ;vyslat status byte
            SJMP  bdat3_1
bdat4:      MOV   STATBYTE, REGB0    ;uložit nový aktuální status
            MOV   TXBYTE, REGB0      ;vždy vyslat status byte, neplatí Running Status
            CALL  outbuf
            MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat databyte
            MOV   DATBPTR, #0        ;ukončit přenos databyte - další data filtrovat
            JMP   main1
bdat5:      INC   DATBPTR            ;na 2. databyte
            MOV   REGB1, DATABYTE
            JMP   main1
bdat6:      MOV   STATBYTE, REGB0    ;uložit nový aktuální status
            MOV   TXBYTE, REGB0      ;vždy vyslat status byte, neplatí Running Status
            CALL  outbuf
            MOV   TXBYTE, REGB1
            CALL  outbuf             ;vyslat 1. databyte
            MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat 2. databyte
            MOV   DATBPTR, #0        ;ukončit přenos databyte - další data filtrovat
            JMP   main1
;===============================================================================
            ;Provádění Status Byte - FIFO
            ;System
msysn:      MOV   DATMPTR, #0
            JMP   main
msysx:      MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat status
            MOV   TH0, #0            ;rozsvítit LED
            MOV   TL0, #0
            CLR   LEDMSG
            SETB  TR0
            JMP   main
msys0:      MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat status
            MOV   STATBYTE, DATABYTE ;uložit nový aktuální status
            MOV   DATMPTR, #0        ;filtrovat data
            MOV   TH0, #0            ;rozsvítit LED
            MOV   TL0, #0
            CLR   LEDMSG
            SETB  TR0
            JMP   main
msys1:      MOV   DATMPTR, #4        ;na jediný databyte
            MOV   REGM0, DATABYTE
            JMP   main
msys2:      MOV   DATMPTR, #5        ;na 1. databyte
            MOV   REGM0, DATABYTE
            JMP   main
            ;-------------------------------------------------------------------
            ;Channel
mchn2:      MOV   DATMPTR, #2        ;na 1. databyte
            MOV   REGM0, DATABYTE
            JMP   main
mchn1:      MOV   DATMPTR, #1        ;na jediný databyte
            MOV   REGM0, DATABYTE
            JMP   main
            ;-------------------------------------------------------------------
            ;Provádění Data Byte - FIFO
mdat1:      MOV   A, REGM0
            CJNE  A, STATBYTE, mdat1_2
mdat1_1:    MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat databyte
            MOV   TH0, #0            ;rozsvítit LED
            MOV   TL0, #0
            CLR   LEDMSG
            SETB  TR0
            JMP   main
mdat1_2:    MOV   STATBYTE, A         ;uložit nový aktuální status
            MOV   TXBYTE, A
            CALL  outbuf             ;vyslat status byte
            SJMP  mdat1_1
mdat2:      INC   DATMPTR            ;na 2. databyte
            MOV   REGM1, DATABYTE
            JMP   main
mdat3:      MOV   A, REGM0
            CJNE  A, STATBYTE, mdat3_2
mdat3_1:    MOV   TXBYTE, REGM1
            CALL  outbuf             ;vyslat první databyte
            MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat druhý databyte
            DEC   DATMPTR            ;zpět na 1. databyte - running status
            MOV   TH0, #0            ;rozsvítit LED
            MOV   TL0, #0
            CLR   LEDMSG
            SETB  TR0
            JMP   main
mdat3_2:    MOV   STATBYTE, A        ;uložit nový aktuální status
            MOV   TXBYTE, A
            CALL  outbuf             ;vyslat status byte
            SJMP  mdat3_1
mdat4:      MOV   STATBYTE, REGM0    ;uložit nový aktuální status
            MOV   TXBYTE, REGM0      ;vždy vyslat status byte, neplatí Running Status
            CALL  outbuf
            MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat databyte
            MOV   DATMPTR, #0        ;ukončit přenos databyte - další data filtrovat
            MOV   TH0, #0            ;rozsvítit LED
            MOV   TL0, #0
            CLR   LEDMSG
            SETB  TR0
            JMP   main
mdat5:      INC   DATMPTR            ;na 2. databyte
            MOV   REGM1, DATABYTE
            JMP   main
mdat6:      MOV   STATBYTE, REGM0    ;uložit nový aktuální status
            MOV   TXBYTE, REGM0      ;vždy vyslat status byte, neplatí Running Status
            CALL  outbuf
            MOV   TXBYTE, REGM1
            CALL  outbuf             ;vyslat 1. databyte
            MOV   TXBYTE, DATABYTE
            CALL  outbuf             ;vyslat 2. databyte
            MOV   DATMPTR, #0        ;ukončit přenos databyte - další data filtrovat
            MOV   TH0, #0            ;rozsvítit LED
            MOV   TL0, #0
            CLR   LEDMSG
            SETB  TR0
            JMP   main
;===============================================================================


;*******************************************************************************
;Přesun byte z TXBYTE do FIFO-OUT - pracuje s bankou registrů 0
;===============================================================================
outbuf:     MOV   A, WRPTROD
            INC   A
            CJNE  A, #STACK, obuf_1
            MOV   A, #FIFOO
obuf_1:     CJNE  A, RDPTROD, obuf_2
            SJMP  obuf_1             ;čekat ve smyčce na uvolnění FIFO
obuf_2:     MOV   @WRPTRO, TXBYTE
            MOV   WRPTRO, A
            CJNE  FLTXM, #0, obuf_3
            SETB  TI
obuf_3:     RET
;===============================================================================


;*******************************************************************************
;Obsluha ERROR
;===============================================================================
;Přetečení buferu FIFO-IN
;-------------------------------------------------------------------------------
onerror:    CLR   EA
            CLR   RESET1             ;příznak interní chyby
            MOV   SP, #STACK-1
            MOV   A, #LOW(error)
            PUSH  ACC
            MOV   A, #HIGH(error)
            PUSH  ACC
            RETI
            ;-------------------------------------------------------------------
error:      CLR   EA
            CLR   REN
            CLR   TR0
error0:     MOV   REGB0, #0
            MOV   REGB1, #0
            MOV   REGB2, #4
error1:     DJNZ  REGB0, error1      ;wait 526344 sc.
            DJNZ  REGB1, error1
            DJNZ  REGB2, error1
            MOV   C, RESET2
            MOV   LEDMSG, C
            CPL   RESET2
            SJMP  error0
;===============================================================================


;*******************************************************************************
;Tabulky dat
;===============================================================================
signatura:  DB    ' Merge Box A - freeware (c) 1/2003 J. David ', 0FFh
;===============================================================================
            END