; File MIDISEND.ASM
; Assembly code for a 10MHz PIC16F84 microcontroller
;
; Description: Send a midi message once every second
; Author: Ross Bencina
; Last Modified: 25 / 8 / 99

; 
; CPU configuration
	processor 16f84
	include	  <p16f84.inc>
	__config  _HS_OSC & _WDT_OFF & _PWRTE_ON

; variables

	
temp	equ	H'1F'
xmit	equ	H'1D'
i	equ	H'1C'
j	equ	H'1B'
k	equ	H'1A'


; Program

	org	0	  ; start at address 0

	
start:	
	movlw	B'00000000'	
	tris	PORTA		; init port A as output

	bsf	PORTA, 0x02	; init midi out pin state 

mainloop:

	call	secdelay
	
	movlw	0x90		; note on, channel 1
	movwf	xmit
	call	sendmidi
	
	movlw	0x3C		; middle C
	movwf	xmit
	call	sendmidi

	movlw	0x7F		; velocity 127
	movwf	xmit
	call	sendmidi

	call	secdelay

	movlw	0x80		; note off, channel 1
	movwf	xmit
	call	sendmidi
	
	movlw	0x3C		; middle C
	movwf	xmit
	call	sendmidi

	movlw	0x7F		; velocity 127
	movwf	xmit
	call	sendmidi

	goto	mainloop
  
; 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

; secdelay delays for one second ( 2500000 instructions )
; kloop = (2 + 254 * 3 + 1 * 2) = 766
; jloop = 2 + kloop * 255 + (3 * 254 + 1 * 2) = 196096
; iloop = 2 + jloop * 13 + (3*254 + 1*2) = 2550014 = 1.02 seconds
; x = 
secdelay:
	movlw	D'13'
	movwf	i
iloop:	movlw	D'255'
	movwf	j
jloop:	movlw	D'255'
	movwf	k
kloop:	decfsz	k,f
	goto	kloop
	decfsz	j,f
	goto	jloop
	decfsz	i,f
	goto	iloop
	return
	
	end
