; 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 chktst equ H'24' ; value to bit check chkbit equ H'25' ; bit to check in checkbit func setbyte equ H'26' ; byte that gets set #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 ;movlw H'3' ;movwf chkbit ;movlw B'00000100' ;movwf chktmp ;call checkbit movlw H'0' goto mainloop ;---------------------------------------------------------------- checkinput: 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 ; 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 checkbit: ; takes chkbit,w and returns 1 or 0 in w decf chkbit,f ; take one away so we rotate correctly checkbitrotloop: rrf chktst,f ; rotate & overwrite tmp decfsz chkbit,f ; dec until zero goto checkbitrotloop btfsc chktst,H'0' ; skip if the state is clear for bit 0 retlw H'1' retlw H'0' setbit: decf chkbit,f movlw H'1' movwf chktst setbitrotloop: rlf chktst,f decfsz chkbit,f goto setbitrotloop movf chktst,w andwf setbyte,f 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