Advertisement
Cremulus

Two hours of PIC assembly coding.

Oct 13th, 2023
1,997
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pic 16 17.18 KB | Source Code | 0 0
  1. ; Midi programme change filter (c) 1995 Simon Brattel
  2. ; Revision (#)                 (c) 1995 Design-Design Technology
  3. ;
  4. ; Session 1 started  04:37 am 18/2/95
  5. ;           ended    06:47 am 18/2/95
  6. ;
  7. ; This code filters MIDI packets looking for programme-change messages. Everything but these is
  8. ; passed through, these are not. Feel free to mail me with any questions, as
  9. ; crem@cix.compulink.co.uk, have fun.
  10. ;
  11. ; This code assumes that the midi data stream does not have any high-priority single byte messages
  12. ; inserted into the programme change message. This is valid for the current application, but won't
  13. ; be in the general case, these need to be passed through and ignored.
  14.  
  15.                         LIST p=16c54                    ;
  16.  
  17. ; Equate things
  18.  
  19. RTCC                    equ 1                           ; I/O assignments
  20. PC                      equ 2                           ;
  21. STATUS                  equ 3                           ;
  22. FSR                     equ 4                           ;
  23.  
  24. Port_A                  equ 5                           ; Port addresses
  25. Port_B                  equ 6                           ;
  26.  
  27. ; Vars
  28.  
  29. Ser_State               equ 1F                          ; Bit 0 = rx wait for start
  30.                                                         ; Bit 1 = tx sending
  31.                                                         ; Bit 2 = tx sending byte
  32.                                                         ; Bit 5 = filter flag
  33.                                                         ; Bit 6 = transmit busy
  34.                                                         ; Bit 7 = rx a byte
  35.  
  36. Rx_Cnt                  equ 1E                          ; Counter used for Rx
  37. Rx_nBits                equ 1D                          ; Bit counter
  38. Rx_Byte                 equ 1C                          ; The receive buffer
  39. Rx_New                  equ 1B                          ; A new byte
  40.  
  41. Tx_Byte                 equ 1A                          ; The byte to send
  42. Tx_State                equ 19                          ;
  43. Tx_nBits                equ 18                          ;
  44. Tx_Buff                 equ 17                          ; A buffer for the transmit byte
  45.  
  46. ; The rest of the memory, 16 and below are free.
  47.  
  48.                         ; Start at the beginning
  49.  
  50.                         org 0                           ; Start of ROM
  51.  
  52.                         ; Setup the watchdog
  53.  
  54. Start                   movlw 03                        ; 1:8
  55.                         option                          ;
  56.  
  57.                         clrf 1                          ; Clear Prescaler
  58.  
  59.                         movlw 0Bh                       ; 1:8 WDT
  60.                         option                          ;
  61.  
  62.                         clrwdt                          ; Clear the watchdog
  63.  
  64.                         ; Setup the port directions
  65.  
  66.                         movlw 0Fh                       ; Outputs high
  67.                         movwf Port_A                    ;
  68.  
  69.                         movlw 001h                      ; Select port A O O O O O O O I
  70.                         tris Port_A                     ;
  71.  
  72.                         movlw 000h                      ; Make port   B O O O O O O O O
  73.                         tris Port_B                     ;
  74.  
  75.                         ; Now setup the vars
  76.  
  77.                         movlw 01h                       ; Setup waiting for start-bit
  78.                         movwf Ser_State                 ;
  79.  
  80.                         ; Now the functional loop
  81.  
  82.                         ; This runs at 4 times the midi baud-rate
  83.                         ; Ie, 40 T-states per Rx cycle
  84.  
  85. Main_Lp:                call Do_Rx                      ; Receive event (Takes exactly 18 T's)
  86.                         call Do_Tx                      ; Transmit event (Takes exactly 17 T's)
  87.                         call Wait_3                     ; Make it up to 40
  88.  
  89.                         ; Second quarter
  90.  
  91.                         call Do_Rx                      ; 40 T's
  92.                         call Pause                      ;
  93.                         nop                             ;
  94.  
  95.                         ; Third quarter
  96.  
  97.                         ; Notice this quarter is one clock shorter, this is slightly cunning, it makes our Tx run
  98.                         ; marginally faster (1.25%) than the MIDI standard.
  99.  
  100.                         ; Why ? Because this way we know that we'll never have to worry about buffering data, as
  101.                         ; we always take less time to send data than to receive it.
  102.  
  103.                         ; Our Rx can easily cope with a slightly faster clock, and it's well within spec.
  104.  
  105.                         ; Obviously this doesn't affect the overall MIDI timing, that's determined by the rate
  106.                         ; at which bytes pass through, not the length of each byte.
  107.  
  108.                         call Do_Rx                      ; 39 T's
  109.                         call Pause                      ;
  110.  
  111.                         ; Fourth quarter
  112.  
  113.                         call Do_Rx                      ;
  114.                         call Filter_It                  ; Filter it (20-T's)
  115.  
  116.                         goto Main_Lp                    ; Loop
  117.  
  118. ; Wait 21 Ts
  119.  
  120. Pause:                  bsf Port_A,3                    ; (+2) Flag it
  121.                         nop                             ; (+3)
  122.                         bcf Port_A,3                    ; (+4)
  123.  
  124.                         ; Now, setup the ports in case the directions are changed
  125.                         ; By EMI
  126.  
  127.                         movlw 001h                      ; (+5) Select port A O O O O O O O I
  128.                         tris Port_A                     ; (+6)
  129.  
  130.                         movlw 000h                      ; (+7) Make port   B O O O O O O O O
  131.                         tris Port_B                     ; (+8)
  132.  
  133.                         ; Now, kick the watchdog
  134.  
  135.                         clrwdt                          ; Kick the dog, we're running
  136.  
  137.                         ; Done
  138.  
  139.                         goto Wait_9                     ; (+10) Do a total of 21 T's
  140.  
  141. ; Examine any new bytes (20T)
  142.  
  143. Filter_It:              btfss Ser_State,7               ; (+2) Do we have a rxd byte ?
  144.                         goto Wait_15                    ; (+3) No, exit (20 T's in total)
  145.  
  146.                         ; Now, is this a byte to be ignored ?
  147.  
  148.                         btfsc Ser_State,5               ; (+4) Is this to be filtered ?
  149.                         goto Filt_1                     ; (+5) Yes, skip
  150.  
  151.                         ; Now, is this a $Cx ?
  152.  
  153.                         movfw Rx_New                    ; (+6) Get the byte
  154.                         andlw 0F0h                      ; (+7) Mask
  155.                         xorlw 0C0h                      ; (+8) Cx ?
  156.  
  157.                         btfsc STATUS,2                  ; (+9) Skip if not Cx
  158.                         goto Filt_2                     ; (+10) Remove it
  159.  
  160.                         ; We should report this byte
  161.  
  162.                         btfsc Ser_State,6               ; (+11) Tx busy ?
  163.                         goto Wait_6                     ; (+12) Yes, done
  164.  
  165.                         ; Yes, send this byte
  166.  
  167.                         movfw Rx_New                    ; (+13) Copy it
  168.                         movwf Tx_Buff                   ; (+14)
  169.  
  170.                         ; Drive the flags
  171.  
  172.                         bcf Ser_State,7                 ; (+15) Clear byte waiting flag
  173.                         bsf Ser_State,6                 ; (+16) Assert byte read flag
  174.  
  175.                         ; Done, exit
  176.  
  177.                         nop                             ; (+17)
  178.                         retlw 0                         ; (+18) (20 in total)
  179.  
  180.         ; We have a Cx, filter it
  181.  
  182.         ; This sets a flag which tells us to simply disregard the next byte, thus removing the
  183.         ; programme change message.
  184.  
  185. Filt_2:                 bsf Ser_State,5                 ; (+12) Filter the next byte
  186.  
  187.                         bcf Ser_State,7                 ; (+13) Filter this byte
  188.  
  189.                         ; Done, exit
  190.  
  191.                         goto Wait_4                     ; (+14) Done, (20 T's in total)
  192.  
  193.         ; Filter the next byte
  194.  
  195.         ; Now, in general this should check to make sure this is the next byte of the programme change
  196.         ; as it could be a single-byte event, but for now we'll assume it isn't and just ignore it.
  197.  
  198. Filt_1:                 bcf Ser_State,5                 ; (+7) Don't filter any more
  199.  
  200.                         bcf Ser_State,7                 ; (+8) Filter this byte
  201.  
  202.                         ; Done, exit
  203.  
  204.                         goto Wait_9                     ; (+9) Done, (20 T's in total)
  205.  
  206. ; Cope with a Tx event
  207.  
  208. Do_Tx:                  btfss Ser_State,1               ; (+2) Idle ?
  209.                         goto Tx_Idle                    ; (+3) Yes, skip
  210.  
  211.                         ; Send a bit
  212.  
  213.                         decfsz Tx_nBits                 ; (+4) Dec the bit count
  214.                         goto Tx_Next                    ; (+5) Do the next bit
  215.  
  216.                         ; This is the stop-bit
  217.  
  218.                         bsf Port_A,1                    ; (+6) Stop bit = ON
  219.  
  220.                         ; Clear states
  221.  
  222.                         bcf Ser_State,1                 ; (+7) Flag idle
  223.                         bcf Ser_State,2                 ; (+8) Flag not sending
  224.  
  225.                         ; Done, exit
  226.  
  227.                         goto Wait_6                     ; (+9) Done, (17 T's in total)
  228.  
  229.         ; Send the next bit
  230.  
  231. Tx_Next:                btfss Tx_Byte,0                 ; (+7) LSB
  232.                         bcf Port_A,1                    ; (+8) Drive it low if clear
  233.                         btfsc Tx_Byte,0                 ; (+9) LSB
  234.                         bsf Port_A,1                    ; (+10) Drive it high if set
  235.  
  236.                         ; Align
  237.  
  238.                         rrf Tx_Byte                     ; (+11) Align the byte
  239.  
  240.                         ; Done, next
  241.  
  242.                         goto Wait_3                     ; (+12) Done, (17 T's in total)
  243.  
  244.         ; We are idle, should we send ?
  245.  
  246. Tx_Idle:                btfss Ser_State,6               ; (+5) Something waiting ?
  247.                         goto Tx_Clr                     ; (+6) No, skip
  248.  
  249.                         ; We have a byte waiting, start-bit
  250.  
  251.                         bcf Port_A,1                    ; (+7) Start bit = OFF
  252.  
  253.                         ; Drive the flags
  254.  
  255.                         bsf Ser_State,1                 ; (+8) Assert sending
  256.  
  257.                         movfw Tx_Buff                   ; (+9) Copy the byte
  258.                         movwf Tx_Byte                   ; (+10)
  259.  
  260.                         bcf Ser_State,6                 ; (+11) Remove waiting flag
  261.  
  262.                         ; Setup the count
  263.  
  264.                         movlw 9                         ; (+12) 8 bits + stop bit
  265.                         movwf Tx_nBits                  ; (+13)
  266.  
  267.                         ; Done, exit
  268.  
  269.                         nop                             ; (+14)
  270.                         retlw 0                         ; (+15) Done (17 T's in total)
  271.  
  272.         ; Really idle, clear it
  273.  
  274. Tx_Clr:                 bsf Port_A,1                    ; (+8) Idle state
  275.  
  276.                         ; Done
  277.  
  278.                         goto Wait_6                     ; (+9) Done, (17 T's in total)
  279.  
  280. ; Cope with an Rx event
  281.  
  282. Do_Rx:                  btfsc Ser_State,0               ; (+2) Get the state
  283.                         goto Rx_GetSB                   ; (+3) We want a start-bit
  284.  
  285.                         ; We are receiving, is this the middle clock ?
  286.  
  287.                         decfsz Rx_Cnt                   ; (+4) Dec the clock count
  288.                         goto Delay_7                    ; (+5) Not yet, (7 T in total)
  289.  
  290.                         ; This is the right clock, done
  291.  
  292.                         decfsz Rx_nBits                 ; (+6) Dec the number wanted
  293.                         goto Rx_NextBit                 ; (+7) We need another
  294.  
  295.                         ; This is the stop bit, is it high ?
  296.  
  297.                         btfss Port_A,0                  ; (+8) Get the input
  298.                         goto Rx_Fault                   ; (+9) No stop bit, ignore
  299.  
  300.                         ; We have a byte, setup for next
  301.  
  302.                         bsf Ser_State,0                 ; (+10) Flag waiting for a start-bit
  303.  
  304.                         movlw 2                         ; (+11) Start bit length
  305.                         movwf Rx_Cnt                    ; (+12)
  306.  
  307.                         ; Report the byte
  308.  
  309.                         movfw Rx_Byte                   ; (+13) Get it
  310.                         movwf Rx_New                    ; (+14) Save it
  311.  
  312.                         bsf Ser_State,7                 ; (+15) Flag it
  313.  
  314.                         ; Done
  315.  
  316. Delay_16:               retlw 0                         ; (+16) Done (18 T in total)
  317.  
  318.         ; We have the bit, setup for the next
  319.  
  320. Rx_Fault:               bsf Ser_State,0                 ; (+11) Flag waiting for a start-bit
  321.  
  322.                         movlw 2                         ; (+12) Start bit length
  323.                         movwf Rx_Cnt                    ; (+13)
  324.  
  325.                         ; Done, exit
  326.  
  327.                         goto Delay_16                   ; (+14) Done (16 T in total)
  328.  
  329.         ; Get the next bit
  330.  
  331. Rx_NextBit:             rrf Rx_Byte                     ; (+9) Align byte
  332.                         bcf Rx_Byte,7                   ; (+10) Clear the bit
  333.  
  334.                         btfsc Port_A,0                  ; (+11) Get the input
  335.                         bsf Rx_Byte,7                   ; (+12) Set the bit
  336.  
  337.                         ; We have the bit, setup for the next
  338.  
  339.                         movlw 4                         ; (+13) Setup the number of clks
  340.                         movwf Rx_Cnt                    ; (+14) to wait till the middle of the bit
  341.  
  342.                         ; Done, exit
  343.  
  344. Delay_15:               nop                             ; (+15)
  345.                         retlw 0                         ; (+16) Done, (18 T in total)
  346.  
  347. ; We are waiting for a start bit
  348.  
  349. Rx_GetSB:               btfsc Port_A,0                  ; (+5) Is the input low ?
  350.                         goto Rx_SetSB                   ; (+6) No, reset the counter
  351.  
  352.                         ; The input is low, are we done ?
  353.  
  354.                         decfsz Rx_Cnt                   ; (+7) Dec the counter, skip if ended
  355.                         goto Delay_10                   ; (+8) Not yet, done (10 T in total)
  356.  
  357.                         ; We have had 2 lows, setup for receive
  358.  
  359.                         bcf Ser_State,0                 ; (+9) Clear the wait for Start counter
  360.  
  361.                         movlw 9                         ; (+10) Setup the number of bits + Stop
  362.                         movwf Rx_nBits                  ; (+11)
  363.  
  364.                         movlw 4                         ; (+12) Setup the number of clks
  365.                         movwf Rx_Cnt                    ; (+13) to wait till the middle of the bit
  366.  
  367.                         ; Done, exit
  368.  
  369.                         goto Delay_16                   ; (+14) Done, (16 T in total)
  370.  
  371.         ; We don't have a start bit. Reset the counter
  372.  
  373. Rx_SetSB:               movlw 2                         ; (+8) We need at least 2 lows
  374.                         movwf Rx_Cnt                    ; (+9) Setup the counter
  375.  
  376.                         goto Delay_12                   ; (+10) Done, (12 T in total)
  377.  
  378. ; Make the delay constant
  379.  
  380. ; Urgh, this is dreadful.
  381.  
  382. Delay_7:                nop                             ; (+7)
  383. Delay_8:                goto Delay_10                   ; (+8)
  384. Delay_10:               goto Delay_12                   ; (+10)
  385. Delay_12:               goto Delay_14                   ; (+12)
  386. Delay_14:               goto Delay_16                   ; (+14)
  387.  
  388. Wait_19:                goto Wait_17                    ; Waste 19 T's
  389. Wait_17:                goto Wait_15                    ; Waste 17 T's
  390. Wait_15:                goto Wait_13                    ; Waste 15 T's
  391. Wait_14:                nop                             ; Waste 14 T's
  392. Wait_13:                goto Wait_11                    ; Waste 13 T's
  393. Wait_11:                nop                             ; Waste 11 T's
  394. Wait_10:                goto Wait_8                     ; Waste 10 T's
  395. Wait_9:                 nop                             ; Waste 9 T's
  396. Wait_8:                 goto Wait_6                     ; Waste 8 T's
  397. Wait_6:                 goto Wait_4                     ; Waste 6 T's
  398. Wait_5:                 nop                             ; Waste 5 T's
  399. Wait_4:                 goto Wait_2                     ; Waste 4 T's
  400. Wait_3:                 nop                             ; Waste 3 T's
  401. Wait_2:                 retlw 0                         ; Waste 2 T's
  402.  
  403.                         ; Setup the reset vector
  404.  
  405.                         org 01FFh                       ; Reset vector
  406.                         goto Start                      ;
  407.  
  408.                         END                             ;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement