; nebogeo corporation ltd 2004 ; CPU configuration processor 16f84 include __config _HS_OSC & _WDT_OFF & _PWRTE_ON temp equ H'2F' xmit equ H'2D' i equ H'2C' j equ H'2B' k equ H'2A' state equ H'40' ; state of the pins note equ H'41' ; current note, offset from root root equ H'42' ; root note pin equ H'43' ; current pin for testing #define NUM_NOTES 5 ; number of notes in the sequence org 0 ; start at address 0 start: clrf PORTA movlw B'00000000' tris PORTA ; init port A as output clrf PORTB movlw B'11111111' tris PORTB ; init port B as input bsf PORTA, 0x02 ; init midi out pin state clrf temp clrf xmit ;clrf state ; init state clrf note ; init start note clrf pin ; init pin movlw 0x3C movwf root ; set root to middle C mainloop: ; clrf note ; movlw B'00000001' ; movwf pin ; call checkinput ; incf note,f movf PORTB,w movwf PORTA call delay ; movlw B'00000010' ; movwf pin ; call checkinput ; incf note,f ; movlw B'00000100' ; movwf pin ; call checkinput ; incf note,f ; movlw B'00001000' ; movwf pin ; call checkinput ; incf note,f goto mainloop ;---------------------------------------------------------------- checkinput: movf pin,w ; load pin value andwf state,w ; and with status btfss STATUS,Z ; if result is zero, pin status is is zero, do next 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 movf PORTB,w andwf pin,w ; and pin to check and input status btfsc STATUS,Z ; skip if pin is set return ; bsf PORTA,0x01 ; 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 ; bcf PORTA,0x01 movf pin,w iorwf state,f ; 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 movf PORTB,w ; load input value andwf pin,w ; and with our pin btfss STATUS,Z ; skip if pin is clear return ; bcf PORTA,0x01 ; 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 PORTA,0x01 movf pin,w xorwf state,f ; clear the state for this pin return ; delay delay: movlw D'1' 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