v0.9 - Interrupt driven UART RX for status updates, using raw unilink packets for... master
authorWerner Johansson <wj@xnk.nu>
Mon, 9 Feb 2004 23:33:59 +0000 (15:33 -0800)
committerWerner Johansson <wj@xnk.nu>
Sun, 17 Oct 2010 00:36:39 +0000 (17:36 -0700)
Signed-off-by: Werner Johansson <wj@xnk.nu>

wj-uni.asm

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