; nebogeo corporation ltd 2004 ; CPU configuration processor 16f84 include __config _HS_OSC & _WDT_OFF & _PWRTE_ON temp equ H'1F' xmit equ H'1D' i equ H'1C' j equ H'1B' k equ H'1A' state equ H'20' ; state of the pins note equ H'21' ; current note, offset from root root equ H'22' ; root note pin equ H'23' ; current pin for testing #define PIN 1 ; input pin #define NUM_NOTES 5 ; number of notes in the sequence org 0 ; start at address 0 start: movlw B'00000000' tris PORTA ; init port A as output movlw B'11111111' tris PORTB ; init port B as input bsf PORTA, 0x02 ; init midi out pin state clrf state ; init state movlw NUM_NOTES movwf note ; init start note movlw 0x3C movwf root ; set root to middle C mainloop: call delay movlw B'00000001' ; checking pin one only for now movwf pin call checkinput goto mainloop ;---------------------------------------------------------------- checkinput: btfsc state,PIN ; skip if the state for this pin is clear goto checkforclear ; we are waiting to send a note off ; check to see if there is a signal on this pin ; we are waiting to send a note on btfss PORTB,PIN ; skip if the pin is set return decf note,f ; dec the current note movf note,w btfss STATUS,Z ; if it's reached zero, skip goto skipreset ; skip the note reset movlw NUM_NOTES movwf note ; init start note skipreset: ; we have a signal, so send a note on movlw 0x90 ; note on, channel 1 movwf xmit call sendmidi movf root,w ; get the root note addwf note,w ; add the current note movwf xmit call sendmidi movlw 0x7F ; velocity 127 movwf xmit call sendmidi bsf state,PIN ; set the state for this pin return checkforclear: ; check to see if the signal has gone low on this pin ; we are waiting to send a note off btfsc PORTB,PIN ; skip if the pin is clear return ; we have no signal now, so send a note off movlw 0x80 ; note off, channel 1 movwf xmit call sendmidi movf root,w ; get the root note addwf note,w ; add the current note movwf xmit call sendmidi movlw 0x0 ; velocity 0 movwf xmit call sendmidi bcf state,PIN ; clear the state for this pin return ; delay delay: movlw D'13' movwf i iloop: movlw D'255' movwf j jloop: movlw D'10' movwf k kloop: decfsz k,f goto kloop decfsz j,f goto jloop decfsz i,f goto iloop return ;---------------------------------------------------------------- ; many thanks to Ross Bencina for this function (and portaudio) ; sendmidi transmits one midi byte on RA2 ; at 10mhz there are 80 instructions per midi bit ; xmit contains byte to send ; * this should be rewritten to support variable delays for ; * different clock speeds sendmidi: startb: bcf PORTA, 0x02 ; start bit movlw D'24' ; delay 73 clocks: 2 + (23 * 3 + 1 * 2) movwf temp ; | loop1: decfsz temp,f ; | goto loop1 ; end delay movlw D'8' movwf j sendloop: ; executes 5 instuctions before setting bit rrf xmit,f btfsc STATUS, C goto send1 ; remember midi bits are opposite from our representation send0: nop bcf PORTA, 0x02 ;send a 0 bit goto endloop send1: bsf PORTA, 0x02 ;send a 1 bit nop nop endloop: ; movlw D'23' ;delay 70 instructions 2 + (22 * 3 + 1 * 2) movwf temp ; | loop2: decfsz temp,f ; | goto loop2 ; end delay decfsz j,f ; goto sendloop stopb: nop nop nop nop nop bsf PORTA, 0x02 ; stop bit movlw D'26' ; delay 79 clocks: 2 + (25 * 3 + 1 * 2) movwf temp ; | loop3: decfsz temp,f ; | goto loop3 ; end delay return end