; Specs: ; ; - midi input (31250 bps) ; - controlling 8 latches with 8 outputs with note-on / note-off ; ; Fixes : ; - clearing all timer on AllNotesOff ; - moving out pwm init and control list p=18f252 ;list directive to define processor #include ;processor specific definitions #include "../midi.asm" ; #define simulate 1 ; enable simulation ; #define heartbeat 1 ; enable heatbeats ;****************************************************************************** ;Configuration bits CONFIG OSC = HSPLL CONFIG OSCS = OFF CONFIG PWRT = ON CONFIG BOR = ON CONFIG BORV = 27 CONFIG WDT = OFF CONFIG WDTPS = 1 CONFIG CCP2MUX = ON CONFIG STVR = ON CONFIG LVP = ON #define Timer1Out OutsA, 2; #define Timer2Out OutsA, 1; #define Timer3Out OutsA, 0; #define Timer4Out OutsA, 3; #define Timer5Out OutsA, 4; #define Timer6Out OutsA, 5; #define Timer7Out OutsB, 7; #define Timer8Out OutsB, 6; #define Timer9Out OutsB, 5; #define Timer10Out OutsB, 4; #define Timer11Out OutsB, 3; #define Timer12Out OutsB, 2; #define Timer13Out OutsB, 1; #define Timer14Out OutsB, 0; #define Timer15Out OutsC, 5; #define Timer16Out OutsC, 4; ;---------------------------------------------------------------------------- ; Variables ; memory map ;---------------------------------------------------------------------------- CBLOCK 0x000 WREG_TEMP ;to save WREG during interrupt STATUS_TEMP ;to save STATUS during interrupt BSR_TEMP ;to save BSR during interrupt FSR0H_TEMP ;to save FSR0H during interrupt FSR0L_TEMP ;to save FSR0L during interrupt FSR0H_SHADOW ;to save FSR0H during high interrupt FSR0L_SHADOW ;to save FSR0L during high interrupt TmpM ; non-ISR scratch TmpT ; non-ISR scratch OutsA ; output port A internal states OutsB ; output port B internal states OutsC ; output port C internal states LatWriteState ; 0=do nothing ; 1=set data ; 2=set addr ; 2=release addr FifoRdIndx; FifoWrIndx; ErrorLed; TISRData; TISRAddrA; TISRAddrC; ENDC CBLOCK 0xA0 ExtLatAData ; external latch A data ExtLatAAddrA ; external latch A address port A ExtLatAAddrC ; external latch A address port C ExtLatAdummy ; to align data by 4 ExtLatBData ExtLatBAddrA ExtLatBAddrC ExtLatBdummy ExtLatCData ExtLatCAddrA ExtLatCAddrC ExtLatCdummy ExtLatDData ExtLatDAddrA ExtLatDAddrC ExtLatDdummy ExtLatEData ExtLatEAddrA ExtLatEAddrC ExtLatEdummy ExtLatFData ExtLatFAddrA ExtLatFAddrC ExtLatFdummy ExtLatGData ExtLatGAddrA ExtLatGAddrC ExtLatGdummy ExtLatHData ExtLatHAddrA ExtLatHAddrC ExtLatHdummy ENDC CBLOCK 0xF8 ; fifo from main to timer ISR Fifo0LatPtr Fifo1LatPtr Fifo2LatPtr Fifo3LatPtr Fifo4LatPtr Fifo5LatPtr Fifo6LatPtr Fifo7LatPtr ENDC ; ... and incrementing this last adress wraps it to zero. ; don't change this property! ;---------------------------------------------------------------------------- ; end of memory map ;---------------------------------------------------------------------------- ;---------------------------------------------------------------------------- ;This code executes when a reset occurs. ORG 0x0000 ;place code at reset vector ResetVector: bra Main ;go to beginning of program ;---------------------------------------------------------------------------- ;This code executes when a high priority interrupt occurs. ORG 0x0008 HighInt: bra HighIntCode ;go to high priority interrupt routine ;---------------------------------------------------------------------------- ;This code executes when a low priority interrupt occurs. ORG 0x0018 LowInt: movff STATUS,STATUS_TEMP ;save STATUS register movff WREG,WREG_TEMP ;save working register movff BSR,BSR_TEMP ;save BSR register movff FSR0H,FSR0H_TEMP ;save FSR0H register movff FSR0L,FSR0L_TEMP ;save FSR0L register ;test other interrupt flags here btfss PIR1,RCIF ;test for RCIF receive interrupt flag bra LowInt1 ;if RCIF is not set, done with test btfsc PIE1,RCIE ;else test if Rx interrupt enabled bra GetData ;if so, go get received data LowInt1: btfss PIR1,TXIF ;test for TXIF transmit interrupt flag bra LowInt2 ;if TXIF is not set, done with test btfsc PIE1,TXIE ;else test if Tx interrupt is enabled bra PutData ;if so, go transmit data LowInt2: btfss PIR1,TMR1IF ;test for Timer1 interrupt flag bra LowInt3 btfsc PIE1,TMR1IE ;else test if Timer3 interrupt enabled bra Timer1ISR ;if so, go get received data LowInt3: reset ;error if no valid interrupt so reset ; ORG 0x0300 ;place code after midi code ;------------------------------------ ;End of low priority interrupt routine restores context. EndLowInt: movff FSR0L_TEMP,FSR0L ;restore FSR0L register movff FSR0H_TEMP,FSR0H ;restore FSR0H register movff BSR_TEMP,BSR ;restore BSR register movff WREG_TEMP,WREG ;restore working register movff STATUS_TEMP,STATUS ;restore STATUS register retfie ;---------------------------------------------------------------------------- ;High priority interrupt routine. HighIntCode: movff FSR0H,FSR0H_SHADOW ;save FSR0H register movff FSR0L,FSR0L_SHADOW ;save FSR0L register ;test other interrupt flags here btfss PIR2,TMR3IF ;test for Timer3 receive interrupt flag bra HighInt1 ;if RCIF is not set, done with test btfsc PIE2,TMR3IE ;else test if Timer3 interrupt enabled bra Timer3ISR ;if so, go get received data ;can do special error handling here - an unexpected interrupt occurred HighInt1: reset ;error if no valid interrupt so reset ;---------------------------------------------------------------------------- ;Main routine checks for for reception of a and then calls a routine to ; move the data to transmit back. Main: setf LATA ; Address strobes high clrf LATB ; All outputs low setf LATC ; All outputs low clrf TRISA ; Config PORTA as all outputs #ifdef ICD movlw 0xE0; movwf TRISB #else clrf TRISB ; Config PORTB as all outputs #endif movlw 0x80 ; movwf TRISC ; Config PORTC all outputs + tristate for serial rx movlw 0x07 ; init adc movwf ADCON1 ; init adc clrf ADCON0 ; poweroff adc clrf TRISA ; Config PORTA again as all outputs setf LATA ; Address strobes high clrf LATB ; All outputs low setf LATC ; All outputs low nop nop nop nop nop nop nop nop clrf LATA clrf LATB nop nop nop nop nop nop nop nop setf LATA ; Address strobes high setf LATC ; All outputs low clrf ExtLatAData; clrf ExtLatBData; clrf ExtLatCData; clrf ExtLatDData; clrf ExtLatEData; clrf ExtLatFData; clrf ExtLatGData; clrf ExtLatHData; clrf LATC; sfz solenoids off at start movlw 0x3E; movwf ExtLatAAddrA; movlw 0x0A movwf ExtLatAAddrC; movlw 0x3D; movwf ExtLatBAddrA; movlw 0x0A movwf ExtLatBAddrC; movlw 0x3B; movwf ExtLatCAddrA; movlw 0x0A movwf ExtLatCAddrC; movlw 0x37; movwf ExtLatDAddrA; movlw 0x0A movwf ExtLatDAddrC; movlw 0x2F; movwf ExtLatEAddrA; movlw 0x0A movwf ExtLatEAddrC; movlw 0x1F; movwf ExtLatFAddrA; movlw 0x0A movwf ExtLatFAddrC; movlw 0x3F; movwf ExtLatGAddrA; movlw 0x08 movwf ExtLatGAddrC; movlw 0x3F; movwf ExtLatHAddrA; movlw 0x02 movwf ExtLatHAddrC; movlw ExtLatAData; movwf Fifo0LatPtr; movlw ExtLatBData; movwf Fifo1LatPtr; movlw ExtLatCData; movwf Fifo2LatPtr; movlw ExtLatDData; movwf Fifo3LatPtr; movlw ExtLatEData; movwf Fifo4LatPtr; movlw ExtLatFData; movwf Fifo5LatPtr; movlw ExtLatAData; movwf Fifo6LatPtr; movlw ExtLatBData; movwf Fifo7LatPtr; call UserInit; bsf LATC,0 ; Light error LED on powerup ; Wait a second with ALoop and BLoop setf TmpM BLoop1: movlw 0xff; ALoop1: decfsz WREG; goto ALoop1 decfsz TmpM; goto BLoop1 bcf LATC,0 ; Been patient enough, dim error LED and start movlw Fifo0LatPtr; movwf FifoRdIndx; movlw Fifo5LatPtr; movwf FifoWrIndx; lfsr FSR0 ,0000h lfsr FSR1 ,0000h rcall SetupSerial ;set up serial port and buffers rcall SetupTimer3 MainLoop: call PollMidiIn; bra MainLoop ;go wait for more data ;---------------------------------------------------------------------------- ; Timer3 setup SetupTimer3: movlw 0x01 movwf T3CON ; timer3 on, other bits cleared bsf IPR2,1 ; timer3 = high priority interrupt bsf PIE2,1 ; timer3 interrupt enable return Timer3ISR: bcf PIR2,TMR3IF ; clear interrupt flag movlw 0E0h ;0x7F; 0xA0 movwf TMR3L ; preset timer setf TMR3H ; preset timer ; bsf LATC,1; ; LATC:1 = TIMER ISR HEARTBEAT #ifdef heartbeat bsf LATC,0; ; LATC:5 = TIMER ISR HEARTBEAT #endif ; pseudocode: ; if state = 1 ; set data bus ; increment state ; end ; if state = 2 ; set addr bus ; increment state ; end ; if state = 3 ; reset addr bus ; increment state ; end ; ; if data on fifo ; set state=1 ; copy fifo data ; end ; state selector movf LatWriteState,0; bz T3ISRProcessFifo; decf WREG; bz T3ISR_LWS1; decf WREG; bz T3ISR_LWS2; decf WREG; bz T3ISR_LWS3; decf WREG; ; shouldn't get here setf ErrorLed; clrf LatWriteState; bra T3ISRProcessFifo; T3ISR_LWS1: ; bsf LATC,0; ; errorLED heartbeat ; btg LATC,3; ; LATC:1 = TIMER ISR HEARTBEAT incf LatWriteState movff TISRData,LATB; bra TISRDone; T3ISR_LWS2: incf LatWriteState movf TISRAddrA,W andwf LATA; movf TISRAddrC,W andwf LATC; bra TISRDone; T3ISR_LWS3: clrf LatWriteState movlw 03Fh; iorwf LATA; movlw 00Ah; movwf LATC; bra TISRDone; T3ISRProcessFifo: lfsr FSR0 ,0000h movf FifoRdIndx, W; subwf FifoWrIndx, W ; result in w bz TISRDone; no new task on cmd queue movff FifoRdIndx, FSR0L; incf FifoRdIndx; bnz NoWrap; movlw Fifo0LatPtr; Wrap to start movwf FifoRdIndx; NoWrap: movf INDF0, 0; W = ExtLatPtr movwf FSR0L; movff POSTINC0,TISRData; movff POSTINC0,TISRAddrA; movff POSTINC0,TISRAddrC; movlw 1; movwf LatWriteState; TISRDone: #ifdef heartbeat bcf LATC,1; ; heatbeat #endif #ifdef simulate return ; OUTSIDE ISR *WARNING* FOR SIMULATION ONLY #endif bra EndHighInt ; resume MidiInNoteOn: ; lookup timer #, read from table in PM:0Fvv movf MidiByte2,0; bz MidiInNoteOff; ; velocity=0 -> NOTE OFF ; bsf LATC,0; ; errorLED heartbeat movlw 10h; movwf TBLPTRH; page = note number to latch pointer table MOVFF MidiByte1,TBLPTRL TBLRD* ; read into TABLAT movf TABLAT,0 bz MidiInNoteOn2; ; bcf LATC,0; ; errorLED heartbeat movwf TmpT ; TmpT = Latch pointer ; modify data with OR mask lfsr FSR2 ,0000h movff TmpT, FSR2L; incf TBLPTRH; page = note number to OR mask table TBLRD* ; read into TABLAT movf TABLAT,0; iorwf INDF2; ; add to fifo movff FifoWrIndx, FSR2L; movff TmpT,POSTINC2; ; update FifoWrIndex movf FSR2L,0; bz NoWrap2; corrected: was: bnz movff FSR2L, FifoWrIndx; BRA MidiInNoteOn2; return NoWrap2 movlw Fifo0LatPtr; Wrap to start movwf FifoWrIndx; BRA MidiInNoteOn2; return MidiInNoteOff: ;************** ; lookup timer #, read from table in PM:0Fvv movlw 10h; movwf TBLPTRH; page = note number to latch pointer table MOVFF MidiByte1,TBLPTRL TBLRD* ; read into TABLAT movf TABLAT,0 bz MidiInNoteOff2; movwf TmpT ; TmpT = Latch pointer ; modify data with OR mask lfsr FSR2 ,0000h movff TmpT, FSR2L; incf TBLPTRH; page = note number to OR mask table incf TBLPTRH; page = note number to AND mask table TBLRD* ; read into TABLAT movf TABLAT,0; andwf INDF2; ; add to fifo movff FifoWrIndx, FSR2L; movff TmpT,POSTINC2; ; update FifoWrIndex movf FSR2L,0; bz NoWrap3; corrected: was: bnz movff FSR2L, FifoWrIndx; bz MidiInNoteOff2; ; return NoWrap3 movlw Fifo0LatPtr; Wrap to start movwf FifoWrIndx; return MidiInCCAllNotesOff: clrf ExtLatAData; clrf ExtLatBData; clrf ExtLatCData; clrf ExtLatDData; clrf ExtLatEData; clrf ExtLatFData; clrf ExtLatGData; clrf ExtLatHData; movlw ExtLatAData; movwf Fifo0LatPtr; movlw ExtLatBData; movwf Fifo1LatPtr; movlw ExtLatCData; movwf Fifo2LatPtr; movlw ExtLatDData; movwf Fifo3LatPtr; movlw ExtLatEData; movwf Fifo4LatPtr; movlw ExtLatFData; movwf Fifo5LatPtr; movlw ExtLatGData; movwf Fifo6LatPtr; movlw ExtLatHData; movwf Fifo7LatPtr; movlw Fifo0LatPtr; movwf FifoRdIndx; movlw Fifo7LatPtr; movwf FifoWrIndx; movlw Fifo0LatPtr; movwf FifoRdIndx; movlw Fifo7LatPtr; movwf FifoWrIndx; RETURN