From 8391ad465c33bdb16ee5e47d04230687f8d6397e Mon Sep 17 00:00:00 2001 From: Werner Johansson Date: Mon, 9 Feb 2004 15:33:59 -0800 Subject: [PATCH] v0.9 - Interrupt driven UART RX for status updates, using raw unilink packets for everything else, dynamic text Signed-off-by: Werner Johansson --- wj-uni.asm | 262 ++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 209 insertions(+), 53 deletions(-) diff --git a/wj-uni.asm b/wj-uni.asm index 253dbda..c1623e0 100644 --- a/wj-uni.asm +++ b/wj-uni.asm @@ -33,13 +33,13 @@ ;---------------------------------------------------------------- ; TODO ;---------------------------------------------------------------- +; Check how the slave should sense "power off" de-selection. Now it continues to play, as the slave doesn't stop requesting updates! ; Investigate whether I actually have to save PCLATH in ISH, maybe save FSR? - Not saving any of them for now ; Check Overrun errors from the UART -; Implement lots of other Unilink commands (Text display, time display etc.) ; Implement the Watchdog Timer (might be useful even though I haven't seen it hang yet..) ; Make the bit shift routine at the beginning of the ISR timeout if the clock suddenly stops (in the middle of a byte) ; (will keep it from hanging until the next bit gets clocked out, just ignore the faulty bits and carry on) -; Implement command b0 0x (change CD to x (1-a)) +; Implement command b0 0x (change CD to x (1-a))? ; Implement command 08 10 (Tel Mute on) and 08 18 (Tel Mute off)? ;---------------------------------------------------------------- @@ -47,6 +47,7 @@ ;---------------------------------------------------------------- ; Version ; +; 0.9 Interrupt driven UART RX for status updates, using raw unilink packets for everything else, dynamic text ; 0.8 Some text commands implemented, only static text for now though ; 0.7 Debug Serial TX in ISR now, checksum check for incoming packets in place, A/D works, solved the master reset prob ; (by calling the INT handler from TMR2 ISR code (too much interrupt latency when transmitting) @@ -96,7 +97,23 @@ ;---------------------------------------------------------------- ; FILE REGISTER USAGE ;---------------------------------------------------------------- -; Free from 20h-4fh + +; Free from 20h-48h + +TrackName equ 20h +TracknameEnd equ 3eh + +DiscName equ 3fh +DiscNameEnd equ 48h + +CurDisc equ 49h +CurTrack equ 4ah +CurMins equ 4bh +CurSecs equ 4ch + +RecvType equ 4dh +TargetPos equ 4eh +CurRecvPos equ 4fh UnilinkRAD equ 50h ; Beginning of Unilink packet - the Receiving Address UnilinkTAD equ 51h ; Transmitter address @@ -150,8 +167,8 @@ IRQPCLATH equ 7dh ; ISH storage IRQSTATUS equ 7eh ; Needs to be located in a shared area accessible from all register banks IRQW equ 7fh ; -RecvBuf equ 0a0h ; Buffer for received data from PC (31 bytes) -RecvBufLen equ 0bfh ; How many bytes have been received? +RecvBuf equ 0a0h ; Buffer for received data from PC (32 bytes) +RecvBufEnd equ 0bfh ; subtitl "Startup" page @@ -243,7 +260,7 @@ IRQTMR2LowDataOK clrf SlaveBreakState -; incf Counter,f +; incf Counter,f : Debug! btfss DisplayStatus,7 ; Only do this if high bit is set goto IRQAfterTMR2 @@ -287,6 +304,119 @@ IRQAfterTMR2 IRQNotTMR2 + call IRQCheckINT ; Check the Unilink INT as well + + btfss PIR1,RCIF ; Check if it's the UART RX interrupt + goto IRQNotRCIF ; No it's not, check the other sources +;---------------------------------------------------------------- +; This is the UART RX routine, this should be control info from the connected PC we're receiving + + movf CurRecvPos,w ; Load fsr + movwf FSR + movf RCREG,w ; Get the byte + bcf PIR1,RCIF ; Clear current interrupt condition + movwf INDF ; Store the recv byte at the position waiting + movlw RecvType + xorwf FSR,w ; Check if it's the recvtype coming in + bnz NotRecvType + + call IRQCheckINT ; Check the Unilink INT as well + + movf RecvType,w ; Load type + bz RecvTimeUpdate ; Position update + xorlw 1 ; Track Name perhaps? + bz RecvTrackName + xorlw 3 ; this is xor 1 and then xor 2, disc name? + bz RecvDiscName + + call IRQCheckINT ; Check the Unilink INT as well + + btfss RecvType,7 ; Check Hi byte + goto IRQNotRCIF + + movf RecvType,w + xorlw 81h + bnz NotText + + call IRQCheckINT ; Check the Unilink INT as well + + movf RecvType,w + goto TextUpdate +NotText + call IRQCheckINT ; Check the Unilink INT as well + + movf RecvType,w + btfss DisplayStatus,7 ; Only if not updating already! +TextUpdate + movwf DisplayStatus ; Force it into DisplayStatus + goto Finished + +RecvTimeUpdate + movlw CurDisc ; Load DL start here + movwf CurRecvPos + movlw CurSecs+1 ; And stop here + movwf TargetPos + goto IRQNotRCIF + +RecvTrackName + movlw TrackName ; Load DL start here + movwf CurRecvPos + movlw TracknameEnd+1 ; And stop here + movwf TargetPos + goto IRQNotRCIF + +RecvDiscName + movlw DiscName ; Load DL start here + movwf CurRecvPos + movlw DiscNameEnd+1 ; And stop here + movwf TargetPos + goto IRQNotRCIF + +NotRecvType + incf CurRecvPos,f + + call IRQCheckINT ; Check the Unilink INT as well + + movf CurRecvPos,w ; Check if we're done + xorwf TargetPos,w + bnz NotFinished +Finished + call IRQCheckINT ; Check the Unilink INT as well + +; movlw 81h ; Assume we do it from the beginning (text and pos) +; movf RecvType,f ; Just check for time-update cmd +; skpnz ; No adjustment if another cmd +; movlw 85h ; Skip the first 4 display cmds +; movwf DisplayStatus + +; call IRQCheckINT ; Check the Unilink INT as well + + movlw RecvType ; restore for another go + movwf CurRecvPos + +NotFinished + +IRQNotRCIF + + call IRQCheckINT ; Check the Unilink INT as well + + btfss PIR1,TXIF ; Check if it's the UART TX interrupt + goto IRQNotTXIF ; No it's not, check the other sources + bsf STATUS,RP0 ; Reg bank 1 + btfss PIE1,TXIE ; As TXIF is set as long as nothing gets sent, is the interrupt actually enabled? + goto IRQTXIFDisabled +;---------------------------------------------------------------- +; This is the UART TX routine, gets called when TXIE has been set and the TX load register is empty + + + + + +IRQTXIFDisabled + bcf STATUS,RP0 ; Make sure we're going back to reg bank 0 + +IRQNotTXIF + ; Finally restore CPU state and return from the ISR ; If I have to save the FSR in the beginning I also need to restore it here... @@ -571,23 +701,27 @@ IRQINTParseNot0112 movf UnilinkParity1,w ; Carry the parity forward movwf UnilinkParity2M - movf DisplayStatus,w + movf CurTrack,w addwf UnilinkParity2M,f movwf UnilinkData1 - movlw 00h + movf CurMins,w addwf UnilinkParity2M,f movwf UnilinkData2 - movlw 01h + movf CurSecs,w addwf UnilinkParity2M,f movwf UnilinkData3 ; movlw 0c0h - movf DisplayStatus,w - andlw 0f0h - iorlw 0eh + movf CurDisc,w +; andlw 0f0h +; iorlw 0eh addwf UnilinkParity2M,f movwf UnilinkData4 + +; clrf DisplayStatus +; goto IRQINTParseBypassClear ; Don't clear the data, the buffer will be sent as the next packet + goto IRQINTParse0113Complete IRQINTParse0113Not80 @@ -599,34 +733,37 @@ IRQINTParse0113Not80 movlw 0cdh ; Disc name addwf UnilinkParity1,f movwf UnilinkCMD1 - movlw 'N' + movf DiscName,w addwf UnilinkParity1,f movwf UnilinkCMD2 movf UnilinkParity1,w ; Carry the parity forward movwf UnilinkParity2 - movlw 'o' + movf DiscName+1,w addwf UnilinkParity2,f movwf UnilinkData1 - movlw ' ' + movf DiscName+2,w addwf UnilinkParity2,f movwf UnilinkData2 - movlw 'M' + movf DiscName+3,w addwf UnilinkParity2,f movwf UnilinkData3 - movlw 'P' + movf DiscName+4,w addwf UnilinkParity2,f movwf UnilinkData4 - movlw '3' + movf DiscName+5,w addwf UnilinkParity2,f movwf UnilinkData5 - movlw ' ' + movf DiscName+6,w addwf UnilinkParity2,f movwf UnilinkData6 - movlw 'P' + movf DiscName+7,w addwf UnilinkParity2,f movwf UnilinkData7 + movlw 00h + addwf UnilinkParity2,f + movwf UnilinkData8 movlw 0eh addwf UnilinkParity2,f movwf UnilinkData9 @@ -641,34 +778,37 @@ IRQINTParse0113Not81 movlw 0cdh ; Disc name addwf UnilinkParity1,f movwf UnilinkCMD1 - movlw 'l' + movf DiscName+8,w addwf UnilinkParity1,f movwf UnilinkCMD2 movf UnilinkParity1,w ; Carry the parity forward movwf UnilinkParity2 - movlw 'a' + movf DiscName+9,w addwf UnilinkParity2,f movwf UnilinkData1 - movlw 'y' + movlw 0 addwf UnilinkParity2,f movwf UnilinkData2 - movlw 'l' + movlw 0 addwf UnilinkParity2,f movwf UnilinkData3 - movlw 'i' + movlw 0 addwf UnilinkParity2,f movwf UnilinkData4 - movlw 's' + movlw 0 addwf UnilinkParity2,f movwf UnilinkData5 - movlw 't' + movlw 0 addwf UnilinkParity2,f movwf UnilinkData6 - movlw '!' + movlw 0 addwf UnilinkParity2,f movwf UnilinkData7 + movlw 00h + addwf UnilinkParity2,f + movwf UnilinkData8 movlw 1eh addwf UnilinkParity2,f movwf UnilinkData9 @@ -683,34 +823,37 @@ IRQINTParse0113Not82 movlw 0c9h ; Track name 1 addwf UnilinkParity1,f movwf UnilinkCMD1 - movlw 'N' + movf TrackName,w addwf UnilinkParity1,f movwf UnilinkCMD2 movf UnilinkParity1,w ; Carry the parity forward movwf UnilinkParity2 - movlw 'o' + movf TrackName+1,w addwf UnilinkParity2,f movwf UnilinkData1 - movlw ' ' + movf TrackName+2,w addwf UnilinkParity2,f movwf UnilinkData2 - movlw 'M' + movf TrackName+3,w addwf UnilinkParity2,f movwf UnilinkData3 - movlw 'P' + movf TrackName+4,w addwf UnilinkParity2,f movwf UnilinkData4 - movlw '3' + movf TrackName+5,w addwf UnilinkParity2,f movwf UnilinkData5 - movlw ' ' + movf TrackName+6,w addwf UnilinkParity2,f movwf UnilinkData6 - movlw 'T' + movf TrackName+7,w addwf UnilinkParity2,f movwf UnilinkData7 + movlw 00h + addwf UnilinkParity2,f + movwf UnilinkData8 movlw 0eh addwf UnilinkParity2,f movwf UnilinkData9 @@ -726,34 +869,37 @@ IRQINTParse0113Not83 movlw 0c9h ; Track name (2) addwf UnilinkParity1,f movwf UnilinkCMD1 - movlw 'r' + movf TrackName+8,w addwf UnilinkParity1,f movwf UnilinkCMD2 movf UnilinkParity1,w ; Carry the parity forward movwf UnilinkParity2 - movlw 'a' + movf TrackName+9,w addwf UnilinkParity2,f movwf UnilinkData1 - movlw 'c' + movf TrackName+10,w addwf UnilinkParity2,f movwf UnilinkData2 - movlw 'k' + movf TrackName+11,w addwf UnilinkParity2,f movwf UnilinkData3 - movlw 'n' + movf TrackName+12,w addwf UnilinkParity2,f movwf UnilinkData4 - movlw 'a' + movf TrackName+13,w addwf UnilinkParity2,f movwf UnilinkData5 - movlw 'm' + movf TrackName+14,w addwf UnilinkParity2,f movwf UnilinkData6 - movlw 'e' + movf TrackName+15,w addwf UnilinkParity2,f movwf UnilinkData7 + movlw 00h + addwf UnilinkParity2,f + movwf UnilinkData8 movlw 1eh addwf UnilinkParity2,f movwf UnilinkData9 @@ -775,24 +921,25 @@ IRQINTParse0113Not84 movf UnilinkParity1,w ; Carry the parity forward movwf UnilinkParity2M - movf DisplayStatus,w + movf CurTrack,w addwf UnilinkParity2M,f movwf UnilinkData1 - movlw 00h + movf CurMins,w addwf UnilinkParity2M,f movwf UnilinkData2 - movlw 01h + movf CurSecs,w addwf UnilinkParity2M,f movwf UnilinkData3 ; movlw 0c0h - movf DisplayStatus,w - andlw 0f0h - iorlw 0eh + movf CurDisc,w +; andlw 0f0h +; iorlw 0eh addwf UnilinkParity2M,f movwf UnilinkData4 + clrf DisplayStatus ; for now! goto IRQINTParse0113Complete IRQINTParse0113Not85 @@ -951,7 +1098,9 @@ IRQINTParseNot02 movf UnilinkID,w ; Check if I'm currently selected xorwf UnilinkCurID,w skpnz ; No, skip this command - bsf DisplayStatus,7 ; Make sure we update the display again +; bsf DisplayStatus,7 ; Make sure we update the display again + movlw 81h + movwf DisplayStatus goto IRQINTParseComplete IRQINTParseNot80 @@ -983,7 +1132,7 @@ IRQINTParseNot80 ; ; Also bit field of CMD2 for now: ; 7 6 5 4 3 2 1 0 -; X X - These two bits are set when changing color, beep etc, but now when actually powering on/off the system??? +; X X - These two bits are set when changing color, beep etc, but not when actually powering the system on or off??? ; X - Always set to 1 on my headunit ; X - Always set to 0 on my headunit ; X - Set to 1 when power is on, 0 when powering off (last command sent before bus dies is 87 22 on my unit) @@ -1043,7 +1192,9 @@ IRQINTParseNot90 bnz IRQINTParseF0Deselect bsf UnilinkSelected,7 ; Now we're selected - bsf DisplayStatus,7 +; bsf DisplayStatus,7 + movlw 81h + movwf DisplayStatus goto IRQINTParseComplete IRQINTParseF0Deselect @@ -1145,6 +1296,10 @@ Main movlw 0ffh ; Set infinite attenuation to begin with movwf UnilinkAttenuation + clrf RecvType + movlw RecvType + movwf CurRecvPos + clrf UnilinkReInits ; Clear the bus re-initialization counter bsf STATUS,RP0 ; Reg bank 1 @@ -1401,6 +1556,7 @@ IRQInit bsf INTCON,INTE ; Enable the RB0/INT bsf INTCON,PEIE ; Enable the peripheral interrupts bsf PIE1,TMR2IE ; Enable the Timer2 peripheral interrupt + bsf PIE1,RCIE ; Enable the UART receive interrupt bsf INTCON,GIE ; Enable global interrupts bsf TXSTA,TXEN ; Enable UART TX -- 1.7.3