Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; Midi programme change filter (c) 1995 Simon Brattel
- ; Revision (#) (c) 1995 Design-Design Technology
- ;
- ; Session 1 started 04:37 am 18/2/95
- ; ended 06:47 am 18/2/95
- ;
- ; This code filters MIDI packets looking for programme-change messages. Everything but these is
- ; passed through, these are not. Feel free to mail me with any questions, as
- ; crem@cix.compulink.co.uk, have fun.
- ;
- ; This code assumes that the midi data stream does not have any high-priority single byte messages
- ; inserted into the programme change message. This is valid for the current application, but won't
- ; be in the general case, these need to be passed through and ignored.
- LIST p=16c54 ;
- ; Equate things
- RTCC equ 1 ; I/O assignments
- PC equ 2 ;
- STATUS equ 3 ;
- FSR equ 4 ;
- Port_A equ 5 ; Port addresses
- Port_B equ 6 ;
- ; Vars
- Ser_State equ 1F ; Bit 0 = rx wait for start
- ; Bit 1 = tx sending
- ; Bit 2 = tx sending byte
- ; Bit 5 = filter flag
- ; Bit 6 = transmit busy
- ; Bit 7 = rx a byte
- Rx_Cnt equ 1E ; Counter used for Rx
- Rx_nBits equ 1D ; Bit counter
- Rx_Byte equ 1C ; The receive buffer
- Rx_New equ 1B ; A new byte
- Tx_Byte equ 1A ; The byte to send
- Tx_State equ 19 ;
- Tx_nBits equ 18 ;
- Tx_Buff equ 17 ; A buffer for the transmit byte
- ; The rest of the memory, 16 and below are free.
- ; Start at the beginning
- org 0 ; Start of ROM
- ; Setup the watchdog
- Start movlw 03 ; 1:8
- option ;
- clrf 1 ; Clear Prescaler
- movlw 0Bh ; 1:8 WDT
- option ;
- clrwdt ; Clear the watchdog
- ; Setup the port directions
- movlw 0Fh ; Outputs high
- movwf Port_A ;
- movlw 001h ; Select port A O O O O O O O I
- tris Port_A ;
- movlw 000h ; Make port B O O O O O O O O
- tris Port_B ;
- ; Now setup the vars
- movlw 01h ; Setup waiting for start-bit
- movwf Ser_State ;
- ; Now the functional loop
- ; This runs at 4 times the midi baud-rate
- ; Ie, 40 T-states per Rx cycle
- Main_Lp: call Do_Rx ; Receive event (Takes exactly 18 T's)
- call Do_Tx ; Transmit event (Takes exactly 17 T's)
- call Wait_3 ; Make it up to 40
- ; Second quarter
- call Do_Rx ; 40 T's
- call Pause ;
- nop ;
- ; Third quarter
- ; Notice this quarter is one clock shorter, this is slightly cunning, it makes our Tx run
- ; marginally faster (1.25%) than the MIDI standard.
- ; Why ? Because this way we know that we'll never have to worry about buffering data, as
- ; we always take less time to send data than to receive it.
- ; Our Rx can easily cope with a slightly faster clock, and it's well within spec.
- ; Obviously this doesn't affect the overall MIDI timing, that's determined by the rate
- ; at which bytes pass through, not the length of each byte.
- call Do_Rx ; 39 T's
- call Pause ;
- ; Fourth quarter
- call Do_Rx ;
- call Filter_It ; Filter it (20-T's)
- goto Main_Lp ; Loop
- ; Wait 21 Ts
- Pause: bsf Port_A,3 ; (+2) Flag it
- nop ; (+3)
- bcf Port_A,3 ; (+4)
- ; Now, setup the ports in case the directions are changed
- ; By EMI
- movlw 001h ; (+5) Select port A O O O O O O O I
- tris Port_A ; (+6)
- movlw 000h ; (+7) Make port B O O O O O O O O
- tris Port_B ; (+8)
- ; Now, kick the watchdog
- clrwdt ; Kick the dog, we're running
- ; Done
- goto Wait_9 ; (+10) Do a total of 21 T's
- ; Examine any new bytes (20T)
- Filter_It: btfss Ser_State,7 ; (+2) Do we have a rxd byte ?
- goto Wait_15 ; (+3) No, exit (20 T's in total)
- ; Now, is this a byte to be ignored ?
- btfsc Ser_State,5 ; (+4) Is this to be filtered ?
- goto Filt_1 ; (+5) Yes, skip
- ; Now, is this a $Cx ?
- movfw Rx_New ; (+6) Get the byte
- andlw 0F0h ; (+7) Mask
- xorlw 0C0h ; (+8) Cx ?
- btfsc STATUS,2 ; (+9) Skip if not Cx
- goto Filt_2 ; (+10) Remove it
- ; We should report this byte
- btfsc Ser_State,6 ; (+11) Tx busy ?
- goto Wait_6 ; (+12) Yes, done
- ; Yes, send this byte
- movfw Rx_New ; (+13) Copy it
- movwf Tx_Buff ; (+14)
- ; Drive the flags
- bcf Ser_State,7 ; (+15) Clear byte waiting flag
- bsf Ser_State,6 ; (+16) Assert byte read flag
- ; Done, exit
- nop ; (+17)
- retlw 0 ; (+18) (20 in total)
- ; We have a Cx, filter it
- ; This sets a flag which tells us to simply disregard the next byte, thus removing the
- ; programme change message.
- Filt_2: bsf Ser_State,5 ; (+12) Filter the next byte
- bcf Ser_State,7 ; (+13) Filter this byte
- ; Done, exit
- goto Wait_4 ; (+14) Done, (20 T's in total)
- ; Filter the next byte
- ; Now, in general this should check to make sure this is the next byte of the programme change
- ; as it could be a single-byte event, but for now we'll assume it isn't and just ignore it.
- Filt_1: bcf Ser_State,5 ; (+7) Don't filter any more
- bcf Ser_State,7 ; (+8) Filter this byte
- ; Done, exit
- goto Wait_9 ; (+9) Done, (20 T's in total)
- ; Cope with a Tx event
- Do_Tx: btfss Ser_State,1 ; (+2) Idle ?
- goto Tx_Idle ; (+3) Yes, skip
- ; Send a bit
- decfsz Tx_nBits ; (+4) Dec the bit count
- goto Tx_Next ; (+5) Do the next bit
- ; This is the stop-bit
- bsf Port_A,1 ; (+6) Stop bit = ON
- ; Clear states
- bcf Ser_State,1 ; (+7) Flag idle
- bcf Ser_State,2 ; (+8) Flag not sending
- ; Done, exit
- goto Wait_6 ; (+9) Done, (17 T's in total)
- ; Send the next bit
- Tx_Next: btfss Tx_Byte,0 ; (+7) LSB
- bcf Port_A,1 ; (+8) Drive it low if clear
- btfsc Tx_Byte,0 ; (+9) LSB
- bsf Port_A,1 ; (+10) Drive it high if set
- ; Align
- rrf Tx_Byte ; (+11) Align the byte
- ; Done, next
- goto Wait_3 ; (+12) Done, (17 T's in total)
- ; We are idle, should we send ?
- Tx_Idle: btfss Ser_State,6 ; (+5) Something waiting ?
- goto Tx_Clr ; (+6) No, skip
- ; We have a byte waiting, start-bit
- bcf Port_A,1 ; (+7) Start bit = OFF
- ; Drive the flags
- bsf Ser_State,1 ; (+8) Assert sending
- movfw Tx_Buff ; (+9) Copy the byte
- movwf Tx_Byte ; (+10)
- bcf Ser_State,6 ; (+11) Remove waiting flag
- ; Setup the count
- movlw 9 ; (+12) 8 bits + stop bit
- movwf Tx_nBits ; (+13)
- ; Done, exit
- nop ; (+14)
- retlw 0 ; (+15) Done (17 T's in total)
- ; Really idle, clear it
- Tx_Clr: bsf Port_A,1 ; (+8) Idle state
- ; Done
- goto Wait_6 ; (+9) Done, (17 T's in total)
- ; Cope with an Rx event
- Do_Rx: btfsc Ser_State,0 ; (+2) Get the state
- goto Rx_GetSB ; (+3) We want a start-bit
- ; We are receiving, is this the middle clock ?
- decfsz Rx_Cnt ; (+4) Dec the clock count
- goto Delay_7 ; (+5) Not yet, (7 T in total)
- ; This is the right clock, done
- decfsz Rx_nBits ; (+6) Dec the number wanted
- goto Rx_NextBit ; (+7) We need another
- ; This is the stop bit, is it high ?
- btfss Port_A,0 ; (+8) Get the input
- goto Rx_Fault ; (+9) No stop bit, ignore
- ; We have a byte, setup for next
- bsf Ser_State,0 ; (+10) Flag waiting for a start-bit
- movlw 2 ; (+11) Start bit length
- movwf Rx_Cnt ; (+12)
- ; Report the byte
- movfw Rx_Byte ; (+13) Get it
- movwf Rx_New ; (+14) Save it
- bsf Ser_State,7 ; (+15) Flag it
- ; Done
- Delay_16: retlw 0 ; (+16) Done (18 T in total)
- ; We have the bit, setup for the next
- Rx_Fault: bsf Ser_State,0 ; (+11) Flag waiting for a start-bit
- movlw 2 ; (+12) Start bit length
- movwf Rx_Cnt ; (+13)
- ; Done, exit
- goto Delay_16 ; (+14) Done (16 T in total)
- ; Get the next bit
- Rx_NextBit: rrf Rx_Byte ; (+9) Align byte
- bcf Rx_Byte,7 ; (+10) Clear the bit
- btfsc Port_A,0 ; (+11) Get the input
- bsf Rx_Byte,7 ; (+12) Set the bit
- ; We have the bit, setup for the next
- movlw 4 ; (+13) Setup the number of clks
- movwf Rx_Cnt ; (+14) to wait till the middle of the bit
- ; Done, exit
- Delay_15: nop ; (+15)
- retlw 0 ; (+16) Done, (18 T in total)
- ; We are waiting for a start bit
- Rx_GetSB: btfsc Port_A,0 ; (+5) Is the input low ?
- goto Rx_SetSB ; (+6) No, reset the counter
- ; The input is low, are we done ?
- decfsz Rx_Cnt ; (+7) Dec the counter, skip if ended
- goto Delay_10 ; (+8) Not yet, done (10 T in total)
- ; We have had 2 lows, setup for receive
- bcf Ser_State,0 ; (+9) Clear the wait for Start counter
- movlw 9 ; (+10) Setup the number of bits + Stop
- movwf Rx_nBits ; (+11)
- movlw 4 ; (+12) Setup the number of clks
- movwf Rx_Cnt ; (+13) to wait till the middle of the bit
- ; Done, exit
- goto Delay_16 ; (+14) Done, (16 T in total)
- ; We don't have a start bit. Reset the counter
- Rx_SetSB: movlw 2 ; (+8) We need at least 2 lows
- movwf Rx_Cnt ; (+9) Setup the counter
- goto Delay_12 ; (+10) Done, (12 T in total)
- ; Make the delay constant
- ; Urgh, this is dreadful.
- Delay_7: nop ; (+7)
- Delay_8: goto Delay_10 ; (+8)
- Delay_10: goto Delay_12 ; (+10)
- Delay_12: goto Delay_14 ; (+12)
- Delay_14: goto Delay_16 ; (+14)
- Wait_19: goto Wait_17 ; Waste 19 T's
- Wait_17: goto Wait_15 ; Waste 17 T's
- Wait_15: goto Wait_13 ; Waste 15 T's
- Wait_14: nop ; Waste 14 T's
- Wait_13: goto Wait_11 ; Waste 13 T's
- Wait_11: nop ; Waste 11 T's
- Wait_10: goto Wait_8 ; Waste 10 T's
- Wait_9: nop ; Waste 9 T's
- Wait_8: goto Wait_6 ; Waste 8 T's
- Wait_6: goto Wait_4 ; Waste 6 T's
- Wait_5: nop ; Waste 5 T's
- Wait_4: goto Wait_2 ; Waste 4 T's
- Wait_3: nop ; Waste 3 T's
- Wait_2: retlw 0 ; Waste 2 T's
- ; Setup the reset vector
- org 01FFh ; Reset vector
- goto Start ;
- END ;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement