; midi to voltage converter
;revision dd 20/03/2001- error in interrupt routine
;clearing tmr0 flag and loading tmr0 register reversed
;J.Scherpenisse

; midi-control values converted to voltages
; controller numbers starting on selectable number
; numbers starting on 0, 8, 16, etc until 120
; selectable with jumpers (or switches) on port A0, A1, A2, A3
; 16 (max) controller numbers
; processor type PIC16F84
; port B4, B5, B6 en B7 used as selection for midi-channel number
; B4...B7 = 0000 means midichannel 1
; B4...B7 = 1111 means midichannel 16


; port B0: serial in from optocoupler (midi bytes)
; port B1 is followed by 16 DA converters (or less)
; all series connected, with shift and loadpins in parallel
; Converter type LTC1452 (Linear Technology)

; The main routine scans all converterdata en sends them
; as one series of bits to port B1, with a shiftpuls on B2 after each bit,
; followed by a loadpuls on B3
	
	device  pic16f84, wdt_off, hs_osc, pwrt_on
        ID      'JS01'
; cristal osc with 10 MHz cristal!!
loadall equ     portb.3
shfout  equ     portb.2
datout  equ     portb.1


	org     0ch
; variabelen
condata ds      16
teller1 ds      1
teller2 ds      1
nummer  ds      1
data    ds      1
tempc   ds      1
bitcnt  ds      1
tempdat ds      1
inbyte  ds      1
startnr ds      1
channr  ds      1
contch  ds      1
switch  ds      1
convadr ds      1       
stemp   ds      1       ;status during interrupt
wtemp   ds      1       ;w during interrupt
offset  equ     condata            ; start of table

	org     00h
	jmp     start
	org     04h
;interrupt routine for 8 bits of 1 byte
introut mov     wtemp, w        ;save
	swapf   status, 0
	movwf   stemp
	sb      t0ie		;timer interrupt?
	jmp     rb0int		;no, port B0 interrupt
tmrint  mov     tmr0, #187      ;decimal
	clrb    t0if                    ; clear timer flag
	clc                             ;make carry 0
	snb      portb.0
	stc                             ; set carry to 1
	rr      tempdat
	inc     bitcnt          ;increment bitcounter
	cje     bitcnt, #08h, last      ;8 bits completed?
	swapf    stemp, 0
	movwf    status
	swapf   wtemp, 1
	swapf   wtemp,0
	reti
last    mov     inbyte, tempdat
	clrb    t0ie
;here routine to do something with the byte
:p0     mov     w, switch       ;switch contains 0, 1, 2 of 3
	jmp     pc+w
	jmp     :p1
	jmp     :p2
	jmp     :p3
	jmp     :p4
:p1     cje     inbyte, contch, :p11        ;controlchange on sel midich
	clr     switch          ;no control change
	jmp     intend
:p11    mov     switch, #1              ; for the next byte
	jmp     intend
:p2     jb      inbyte.7, :p1   ;sorry, statusbyte...
:p21    sub     inbyte, startnr ; startnumber from jumpers in init routine
	csa     inbyte, #15             ;decimal
	jmp     :p22
        clr     convadr          ;wrong range,
                        ;resulting in a nop while writing the data
                        ;of the third byte
	jmp     intend
:p22    add     inbyte, #0ch    ;add offset to converternumber
	mov     switch, #2              ;for next byte
	mov     convadr, inbyte ;store conv.number+offset
	jmp     intend
:p3     jb      inbyte.7, :p1   ;again statusbyte...
:p31    mov     fsr, convadr    ;setup indirect
	mov     indirect, inbyte        ; store converter data
                                ;a nop results if address was out of range
	mov     switch, #3              ;3 bytes ready, test next time
					;on running status
	jmp     intend
:p4     jb      inbyte.7, :p1   ;normal status
        jmp     :p21            ;running status
;
intend  clrb    t0ie
	clrb    intf
	setb    inte
	swapf    stemp, 0
	movwf    status
	swapf   wtemp, 1
	swapf   wtemp,0
	reti

; B0 interrupt routine starting here
rb0int  clrb    intf            ;clear RB0 interrupt flag!  
	jb      portb.0, :t2    ;false alarm
	clr     bitcnt          ;clear bit counter
	mov     tempc, #12
:t1     djnz    tempc, :t1
	jb      portb.0, :t2    ;false alarm 
        mov     tmr0, #187      ;decimal wait (Timer 0)
	clrb    t0if            ;clear timer flag
	clrb    inte            ;set ready for receiving byte
	setb    t0ie
	swapf    stemp, 0
	movwf    status
	swapf   wtemp, 1
	swapf   wtemp,0
	reti

:t2     clrb    t0ie             ;set ready for receiving startbit.
	setb    inte
	swapf    stemp, 0
	movwf    status
	swapf   wtemp, 1
	swapf   wtemp,0
	reti

start   setb    rp0             ;bank 1
	mov     trisb, #0f1h     ;B0 is input, B4...B7 is input
	mov     trisa, #0fh     ; bit a0, a1, a2 and a3 input
	mov     option, #08h    ;no prescaler on timer0.
	clrb    rp0             ;bank 0
	mov     intcon, #90h    ;inte on port B0 + global int enab.

; all initialisations
inits   clr     condata
	clr     condata+1
	clr     condata+2
	clr     condata+3
	clr     condata+4
	clr     condata+5
	clr     condata+6
	clr     condata+7
	clr     condata+8
	clr     condata+9
	clr     condata+10
	clr     condata+11
	clr     condata+12
	clr     condata+13
	clr     condata+14
	clr     condata+15
; init of address-switch and channel
	mov     channr, portb   ;get 4 bits of portB
	swap    channr
	and     channr, #0fh    ;make midichannel number
	mov     w, channr
	or      w, #10110000b   ;make control change byte
	mov     contch, w       ;and store
	mov     startnr, porta
	rl      startnr
	rl      startnr
	rl      startnr
	and     startnr, #01111000b
	clr     switch
	mov     teller1, #11h   ;(17 decimal) initvalue,
                                ; program starts with decrement!

;main routine with scan over all converters. the converterdata 
; is 7 bits and not shifted to the left bit position!
;converterdata starts in 0Ch
herh    djnz    teller1, :h1
	mov     teller1, #10h           ;16
	setb    loadall
	nop
	clrb    loadall
:h1     mov     nummer, #offset-1
	add     nummer, teller1
:hh     clrb    gie             ;disable interrupt
	mov     fsr, nummer
	mov     data, indirect
	setb    gie             ; interrupt enable again
	mov     teller2, #07h
	rl      data            ; data still 7 bits
:h2     rl      data            ; get bit in carry
	clrb    datout
	snc
	setb    datout
	setb    shfout
	clrb    shfout
	djnz    teller2, :h2
	clrb    datout		;complete data with 5 0-bits
	setb    shfout		;(converter needs 12 bits!)
	clrb    shfout
	setb    shfout
	clrb    shfout
	setb    shfout
	clrb    shfout
	setb    shfout
	clrb    shfout
	setb    shfout
	clrb    shfout
	jmp     herh            ; end of main routine
; estimated duration of total scan (at 10 MHz) 630 uSec for all 16 converters.


	
