MainInfoSeg MACRO ;******************************************************************************** ; Main Code ;******************************************************************************** ENDM MainCodeSeg MACRO ;******************************************************************************** ; Main Code ;******************************************************************************** ledRX = ra.0 ledTX = ra.1 ledCON = ra.2 ledERR = ra.3 Startup mov m, #TRIS mov ra, #%0000 ;init Port A mov !ra, #%0000 ;Port A (LEDs) - Outputs mov rb, #%00001100 ;init rb - UartTx (bit 2) and UartCTS (bit 3) = idle high mov !rb, #%01110011 ;Direction mov m, #PLP mov !rb, #%11001111 ;Enable pullup on unused pins (bits 4 and 5) mov m, #WKED mov !rb, #%11111110 ;IrRx (bit 6) = falling edge, UartRx (bit0) = rising edge clr rc ;Init output to 0 mov m, #TRIS mov !rc, #%10101011 ;Port C (IO Port) direction - set for jumper use mov m, #PLP mov !rc, #%01010100 ;Port C (IO Port) pullup - enabled on input pins clr fsr ;reset all ram banks :loop setb fsr.4 clr ind ijnz fsr,:loop call @IsrInit call @a2flReset call @a2plReset call @a2lapReset call @a2lmpReset call @a2appReset Asynchronous ;Note: flags are global snb IrdaRxAvail ;Irda byte received ? call @a2flRxAvail snb IrdaTxEmpty ;Irda TxEmpty flag set ? call @a2flTxEmpty snb UartRxAvail ;Uart byte received ? call @a2appRxAvail snb TimerOverflow ;Timer Overflow flag set ? call @a2lapTimer jmp Asynchronous ;******************************************************************************** ENDM IsrInfoSeg MACRO ;******************************************************************************** ; Interrupt Service Routine ;******************************************************************************** ; Updated 19 November 1999 - Nick Kelsey ; * Fixed fault in IrdaTxData and UartTxData where the stop bit was one ; interrupt cycle too long. ; Updated 6 December 1999 - Nick Kelsey ; * Added RTS/CTS defines for debug UART. ;******************************************************************************** ENDM IsrDataSeg MACRO ;******************************************************************************** ; Interrupt Service Routine ;******************************************************************************** org $10 IsrBank = $10 IsrTime50MHz = -108 ;50Mhz * 2.17us = 108.5 IsrTime = IsrTime50MHz ;Constant = MHz * 2.17us ;**** Isr **** IsrMReg ds 1 IsrIntFlags ds 1 ;**** IsrStatus **** (Global varible providing an interface to the Isr) TimerOverflow = IsrStatus.0 IrdaTxStart = IsrStatus.1 IrdaTxEmpty = IsrStatus.2 ;1 = finished sending byte IrdaRxAvail = IsrStatus.3 ;1 = received byte available to be read UartTxStart = IsrStatus.4 UartTxEmpty = IsrStatus.5 UartRxAvail = IsrStatus.6 ;1 = received byte available to be read DebugSend = UartTxStart ;**** Irda & Uart Status **** IrdaUartStatus ds 1 IrdaRxPulse = IrdaUartStatus.0 IrdaRxMode = IrdaUartStatus.1 ;1 = currently receiving a byte, 0 = idle IrdaTxMode = IrdaUartStatus.2 ;1 = currently transmitting a byte, 0 = idle UartRxMode = IrdaUartStatus.3 ;1 = currently receiving a byte, 0 = idle UartTxMode = IrdaUartStatus.4 ;1 = currently transmitting a byte, 0 = idle ;**** Irda **** IrdaTxPin = rb.7 ;Output - Idle Low IrdaRxPin = rb.6 ;Input - Idle High IrdaRxInt = 6 ;Interrupt = bit 6 Irda9600 = 48 ;+0.47% Irda19200 = 24 ;+0.47% Irda38400 = 12 ;+0.47% Irda57600 = 8 ;+0.47% Irda115200 = 4 ;+0.47% IrdaSpeed ds 1 IrdaData ds 1 IrdaRxBits ds 1 IrdaBitCount ds 1 IrdaDivide ds 1 ;**** Uart **** UartTxPin = rb.2 ;Output - Idle High UartRxPin = rb.0 ;Input - Idle High UartRtsPin = rb.1 ;Output UartCtsPin = rb.3 ;Input Uart9600 = 48 ;+0.47% Uart19200 = 24 ;+0.47% Uart38400 = 12 ;+0.47% Uart57600 = 8 ;+0.47% Uart115200 = 4 ;+0.47% UartSpeed = Uart115200 UartTxData = DebugData ;Global Variable UartTxBits ds 1 UartTxBitCount ds 1 UartTxDivide ds 1 UartRxData ds 1 UartRxBits ds 1 UartRxBitCount ds 1 UartRxDivide ds 1 org $30 TimerBank = $30 ;Shared with Framing layer Random ds 1 ;Increments every timer interrupt (108 cycles @ 50MHz) Timer1 ds 1 ;Resetable, Increments every timer interrupt (108 cycles @ 50MHz) Timer2 ds 1 ;Resetable, Increments every Timer1 overflow (27648 cycles @ 50MHz) Timer3 ds 1 ;Resetable, Increments every Timer2 overflow (7077888 cycles @ 50MHz) ;******************************************************************************** ENDM IsrCodeSeg MACRO ;******************************************************************************** ; Interrupt Service Routine ;******************************************************************************** GlobalIsr ;Interrupt = Timer bank TimerBank inc Random ;1 Random increment (Note: The main code is synchronous with RTCC and so RTCC is not a random number) inc Timer1 ;1 Timer: increment snz ;1/2 Timer: overflow ? inc Timer2 ;1 Timer: Yes => increment snz ;1/2 Timer: overflow ? inc Timer3 ;1 Timer: Yes => increment snz ;1/2 Timer: overflow ? setb TimerOverflow ;1 Timer: Yes => set flag (Timer = 7 cycles) bank IsrBank ;1 mov IsrMReg, m ;2 Backup M register mov m, #WKPND ;1 Set mode to examine port b interrupt flags mov w, #0 ;1 Clear W mov !rb, w ;1 Swap contents of W and WKPEN_B (interrupt flags are cleared) mov IsrIntFlags, w ;1 Store cause of interrupt IrdaIsr ; Irda -> IrdaRet: Idle = 6 cycles, Tx = 9/19/23 cycles, Rx = 12/21/27 cycles, RxStart = 18 cycles snb IrdaTxMode ;1/2 Irda Tx ? jmp IrdaTxDataIsr ;3 Yes => IrdaTxDataIsr snb IrdaTxStart ;1/2 Irda Tx ? jmp IrdaTxStartIsr ;3 Yes => IrdaTxStartIsr snb IrdaRxMode ;1/2 Irda Rx ? jmp IrdaRxDataIsr ;3 Yes => IrdaRxDataIsr snb IsrIntFlags.IrdaRxInt ;1/2 Falling edge of Rx pin indicating start bit ? jmp IrdaRxStartIsr ;3 Yes => IrdaRxStartIsr IrdaRet ; Irda -> IrdaRet: Idle = 6 cycles, Tx = 9/19/23 cycles, Rx = 12/21/27 cycles, RxStart = 18 cycles UartTxIsr snb UartTxMode ;1/2 Transmitting ? jmp UartTxDataIsr ;3 Yes => UartTxDataIsr snb UartTxStart ;1/2 Start transmit ? jmp UartTxStartIsr ;3 Yes => UartTxStartIsr UartTxRet UartRxIsr snb UartRxMode ;1/2 Receiving ? jmp UartRxDataIsr ;3 Yes => UartRxDataIsr sb UartRxPin ;1/2 Start bit ? (start bit = 0) jmp UartRxStartIsr ;3 Yes => UartRxStartIsr UartRxRet mov m, IsrMReg ;2 Restore M register mov w, #IsrTime ;1 Interrupt in 108 @ 50Mhz cycles retiw ;3 Total Isr Time = x cycles IrdaTxDataIsr ; Time = 5/13/16/20 cycles clrb IrdaTxPin ;1 return to idle decsz IrdaDivide ;1/2 jmp IrdaRet ;3 Isr Time = +5 cycles from IrdaTxIsr decsz IrdaBitCount ;1/2 Sent all bits? jmp :Bit ;3 No => output next bit :End snb IrdaTxStart ;1/2 Yes => complete, Another byte to transmit? jmp IrdaTxStartIsr ;3 Yes => IrdaTxStartIsr clrb IrdaTxMode ;1 Finished setb IrdaTxEmpty ;1 Flag to indicate that the transmission is complete clrb ledTX ;1 Turn off TX LED (indication LED not actual IR emitter) jmp IrdaRet ;3 Isr Time = +19 cycles from IrdaTxIsr :Bit sb IrdaData.0 ;1/2 Output next bit setb IrdaTxPin ;1 Output next bit stc ;1 Stop bit (idle = 1) rr IrdaData ;1 mov IrdaDivide, IrdaSpeed ;2 Apply baud rate jmp IrdaRet ;3 Isr Time = +16 cycles from IrdaTxIsr IrdaTxStartIsr clrb IrdaTxStart ;1 Clear start mode setb ledTX ;1 Turn on TX LED (indication LED not actual IR emitter) setb IrdaTxPin ;1 Output start pulse (note position of this instruction is such that it matches the setb of the TxDataIsr) mov IrdaDivide, IrdaSpeed ;2 Apply baud rate mov IrdaBitCount, #10 ;2 Bit count = 8 data + 1 stop + 1 for stop bit to complete setb IrdaTxMode ;1 Enter Tx mode jmp IrdaRet ;3 Isr Time = +n cycles IrdaRxDataIsr ; Time = 4/13/19 cycles snb IsrIntFlags.IrdaRxInt ;1/2 Was a pulse received ? setb IrdaRxPulse ;1 Yes => Flag pulse decsz IrdaDivide ;1/2 jmp IrdaRet ;3 Isr Time = +4 cycles from IrdaRxIsr clc ;1 Determine bit sb IrdaRxPulse ;1/2 Determine bit stc ;1 Determine bit rr IrdaRxBits ;1 Record bit clrb IrdaRxPulse ;1 Reset pulse flag mov IrdaDivide, IrdaSpeed ;2 Apply baud rate decsz IrdaBitCount ;1/2 jmp IrdaRet ;3 Isr Time = +13 cycles from IrdaRxIsr mov IrdaData, IrdaRxBits ;2 Copy bits into IrdaData clrb IrdaRxMode ;1 Finished setb IrdaRxAvail ;1 clrb ledRX ;1 Turn off RX LED (indication LED not actual IR emitter) jmp IrdaRet ;3 Isr Time = +19 cycles from IrdaRxIsr IrdaRxStartIsr ; Time = 10 cycles setb ledRX ;1 Turn on RX LED (indication LED not actual IR emitter) clc ;1 mov w, >>IrdaSpeed ;1 W = IrdaSpeed / 2 mov IrdaDivide, w ;1 IrdaDivide = IrdaSpeed * 0.5 mov IrdaBitCount, #9 ;2 Bit count = 9 (1/2 start, 8 data, ignore stop) setb IrdaRxMode ;1 Enter rx mode jmp IrdaRet ;3 Isr Time = +10 cycles from IrdaRxStartIsr UartTxDataIsr ; Time = 4/11/17 cycles decsz UartTxDivide ;1/2 jmp UartTxRet ;3 Isr Time = +n cycles from UartTxIsr decsz UartTxBitCount ;1/2 Sent all bits? jmp :Bit ;3 No => output next bit :End snb UartTxStart ;1/2 Yes => complete, Another byte to transmit? jmp UartTxStartIsr ;3 Yes => UartTxStartIsr clrb UartTxMode ;1 No => Complete setb UartTxEmpty ;1 Flag to indicate that the transmission is complete jmp UartTxRet ;3 Complete :Bit movb UartTxPin, UartTxBits.0 ;4 Output next bit stc ;1 Stop bit (idle = 1) rr UartTxBits ;1 mov UartTxDivide, #UartSpeed ;2 Apply UartSpeed jmp UartTxRet ;3 Isr Time = +n cycles from UartTxIsr UartTxStartIsr clrb UartTxPin ;1 Output start bit mov UartTxBits, UartTxData ;2 Load data for transmission mov UartTxDivide, #UartSpeed ;2 Apply UartSpeed mov UartTxBitCount, #10 ;2 Bit count = 8 data + 1 stop + 1 for stop bit to complete clrb UartTxStart ;1 Clear start mode setb UartTxMode ;1 Enter Tx mode jmp UartTxRet ;3 Isr Time = +n cycles UartRxDataIsr decsz UartRxDivide ;1/2 jmp UartRxRet ;3 Isr Time = +n cycles decsz UartRxBitCount ;1/2 jmp :Read ;3 :Stop mov UartRxData, UartRxBits ;2 Copy bits into UartData clrb UartRxMode ;1 Finished setb UartRxAvail ;1 jmp UartRxRet ;3 Isr Time = +n cycles :Read clc ;1 Determine bit snb UartRxPin ;1/2 Determine bit stc ;1 Determine bit rr UartRxBits ;1 Record bit mov UartRxDivide, #UartSpeed ;2 Apply baud rate jmp UartRxRet ;3 Isr Time = +n cycles UartRxStartIsr mov UartRxDivide, #UartSpeed / 2 ;2 UartDivide = UartSpeed * 0.5 mov UartRxBitCount, #10 ;2 Bit count = 10 (1/2 start, 8 data, 1 stop) setb UartRxMode ;1 Enter rx mode jmp UartRxRet ;3 Isr Time = +n cycles IsrInit clr IsrStatus bank IsrBank clr IrdaUartStatus mov IrdaSpeed, #Irda9600 mov !option, #%10011111 ;enable rtcc interrupt retp ;******************************************************************************** ENDM FrameInfoSeg MACRO ;******************************************************************************** ; FRAMING LAYER ;******************************************************************************** ; ; Receive : Processes incomming characters and passes payload to payload layer ; Transmit : Frames and applies transparency to payload data ; ;******************************************************************************** ; ; Normal Frame Format: Allowable: Send: ; n * FF n >= 0 n = 10 ; n * BOF n >= 1 n = 1 ; n * Payload data ; 2 * FCS ; 1 * EOF ; ; FCS - Frame Check Sequence ; 16 bit CCITT CRC sent low byte first ; Transmit : send the complement of the calculated FCS ; Receive : include FCS bytes in calculation of the FCS, FCS will equal $f0b8 if valid ; Note : FCS covers the payload data only. ; It is calculated prior to adding any transparency bytes (ie FCS bytes must also be transparent). ; ; Transparency: ; CE(=$7D) indicates transparency issue ; CE EOF incicates sender has terminated packet ; CE BOF indicates sender has restarted payload ; CE * anything else: XOR with $20 to recover origional data ; ;******************************************************************************** ; ;Asynchronous Events ; ; a2flRxAvail() ;Signal to indicate that a byte has been received ; a2flTxEmpty() ;Signal to indicate that the last byte has finished transmitting ; ;Interface ; ; fl2plRxData(w=Data) ;Data byte from frame ; fl2plRxValid() ;Payload data is complete and valid ; fl2plRxError() ;Payload data contains errors ; pl2flRxIgnore() call ;Return to idle state thus terminating any frame being received ; ; pl2flTxStart() ;Request from payload layer to send a frame - Does not test for media busy ; fl2plTxData(ret w=Data ret z=Last) call ;Request data from payload layer - Z flag is set if its the last byte ; fl2plTxComplete() ;Inform payload layer that the transmission is complete ; ;Notes ; - The Rx code does not time out but is reset by calling RxIgnore, by receiving a new frame, or by transmitting a frame ; - If a frame is transmitted (TxStart) while a frame is being recieved the RxCode will reset to the idle state ; without indicating an error (RxError). ; ;******************************************************************************** ENDM FrameDataSeg MACRO ;******************************************************************************** ; FRAMING LAYER ;******************************************************************************** org $38 flBank = $38 ;8 bytes used - Note bank shared with Uart flState ds 1 ;flBank - current state flData ds 1 ;flBank - storage for a byte received flPosition ds 1 ;flBank - Counter used to count the FF codes at start of frame and to keep track of buffer flBuffer ds 2 ;flBank - 2 byte buffer to delay the passing of payload data to allow the removal of the FCS flFFCount ds 1 ;flBank - number of FFs to send at the start of each packet flFCSl ds 1 ;flBank - 16-bit FCS value (low byte) flFCSh ds 1 ;flBank - 16-bit FCS value (high byte) flRxState = %00000000 flTxState = %10000000 flRxBeginState = 1 + flRxState ;waiting for start of payload flRxPayloadState = 2 + flRxState ;receiving payload data flRxCtrlState = 3 + flRxState ;waiting for byte after CE code flTxBeginState = 1 + flTxState ;sending initial FF bytes flTxCtrlState = 2 + flTxState ;waiting to send an encoded payload data byte flTxPayloadState = 3 + flTxState ;waiting to send another payload byte flTxFCSlState = 4 + flTxState ;waiting to send FCSl flTxFCShState = 5 + flTxState ;waiting to send FCSh flTxSendEndState = 6 + flTxState ;waiting to send EOF to close frame flTxWaitEndState = 7 + flTxState ;waiting for EOF to finish begin sent BOF = $C0 ; = %11000000 ;Beginning of Frame code (refer IrLAP specification) EOF = $C1 ; = %11000001 ;End of Frame code (refer IrLAP specification) CE = $7D ; = %01111101 ;Control Escape code (refer IrLAP specification) ValidFCSh = $F0 ValidFCSl = $B8 ;******************************************************************************** ENDM FrameCodeSeg MACRO ;******************************************************************************** ; FRAMING LAYER ;******************************************************************************** ;********** a2flReset ********** a2flReset bank IsrBank mov IrdaSpeed, #Irda9600 ;IrDA UART speed = 9600 bank flBank clr flState ;Reset to idle state mov flFFCount, #10 ;Default to 10 FFs @ 9600 = 10.42ms retp ;********** a2flRxAvail ********** a2flRxAvail ;The IrdaRxAvail flag was set bank IsrBank mov w, IrdaData ;Get received byte clrb IrdaRxAvail ;Clear flag bank flBank snb flState.7 ;Current state = receiving or idle ? retp ;No => ignore (do not need to inform lap layer of media busy as in transmit mode) mov flData, w ;Store byte that was received debug PhysicalDataRx ;Debug: pass data received call @fl2lapMediaBusy ;Inform lap layer of media busy bank flBank mov w, flState ;Jump based on state jmp PC+w jmp flRxIdle ; 0 = Idle jmp flRxBegin ; 1 = flRxBeginState jmp flRxPayload ; 2 = flRxPayloadState jmp flRxCtrl ; 3 = flRxCtrlState ;********** a2flTxEmpty ********** a2flTxEmpty ;From physical layer: Last byte has finished transmitting bank IsrBank clrb IrdaTxEmpty ;Clear flag bank flBank sb flState.7 ;Check that it is a TxState retp ;Rx state or idle => return mov w, flState ;Jump based on state and w, #%01111111 ;Remove Tx state flag jmp PC+w retp ; 0 = Invalid state jmp flTxBegin ; 1 = flTxBeginState jmp flTxCtrl ; 2 = flTxCtrlState jmp flTxPayload ; 3 = flTxPayloadState jmp flTxFCSl ; 4 = flTxFCSlState jmp flTxFCSh ; 5 = flTxFCShState jmp flTxSendEnd ; 6 = flTxSendEndState jmp flTxWaitEnd ; 7 = flTxWaitEndState ;********** pl2flRxIgnore ********** pl2flRxIgnore bank flBank clr flState ;Reset to idle state retp ;******************************************************************************** ; FRAMING LAYER - FCS Subroutines ;******************************************************************************** ;********** FCS Subroutines ********** flFCSa = Temp ;Global - Tempory varable used in the FCS calculation flFCSInit mov w, #$ff ;Init FCS to $FFFF mov flFCSh, w ;Init FCS to $FFFF mov flFCSl, w ;Init FCS to $FFFF retp flFCSData ;Add data to FCS (w = Data) (must be in flBank) xor flFCSl, w ;FCSl[=X] = FCSl xor w mov w,<>flFCSl ;w = FCSl[32107654] and w,#%11110000 ;w = FCSl[3210oooo] xor flFCSl, w ;FCSl = FCSl xor (FCSl shl 4) ;Calculate A = FCSh mov w, <>flFCSl ;w = FCSl[32107654] mov flFCSa, w ;A = FCSl[32107654] mov w, >>flFCSa ;w = FCSl[x3210765] and w, #%00000111 ;w = FCSl[ooooo765] xor w, flFCSl ;w = FCSl xor (FCSl shr 5) mov flFCSa, w ;store w into A = new FCSh value ;Calculate new FCSl value rl flFCSl ; rl flFCSl ; mov w, <<flFCSl ;w = FCSl[43210xxx] and w, #%11111000 ;w = FCSl[43210ooo] xor w, flFCSh ;w = (FCSl shl 3) xor FCSh mov flFCSl, w ;Store w into FCSl mov w, <>flFCSa ;w = A[32107654] and w, #%00001111 ;w = A[oooo7654] xor flFCSl, w ;FCSl = (FCSl shl 3) xor FCSh xor (A shr 4) ;Store new FCSh value mov w, flFCSa ;A holds FCSh value mov flFCSh, w ;Store A in FCSh retp ;******************************************************************************** ; FRAMING LAYER - Receive ;******************************************************************************** flRxPassData ;Adds data (flRxData) to FCS and passes data to payload layer mov w, flData ;Last byte that was received call flFCSData ;Add Data to FCS value mov Temp, flBuffer+1 ;Shift data out of buffer mov flBuffer+1, flBuffer+0 ;Shift data in buffer mov flBuffer+0, flData ;Shift new data into buffer incsz flPosition ;Inc position, Zero ? retp ;No => buffer is not full, return dec flPosition ;Set position to FF to indicate buffer is still full mov w, Temp ;Data to pass jmp @fl2plRxData ;pass data to payload layer (payload layer issues retp instruction) ;********** a2flRxAvail - Idle State ********** flRxIdle ;Waiting for a BOF to indicate start of frame csne flData, #BOF ;Was byte a BOF ? inc flState ;Yes => BOF received indicating start of frame => change to flRxBeginState retp ;********** a2flRxAvail - Begin State ********** flRxBegin ;Waiting for non BOF to indicate start of data csne flData, #BOF ;Was byte a BOF ? retp ;Yes => ignore csne flData, #EOF ;Was byte a EOF indicating sender has terminated frame ? jmp :Idle ;Yes => return to idle state csne flData, #CE ;Was byte a CE indicating a transparency issue ? jmp :Ctrl ;Yes => change to Ctrl state mov flState, #flRxPayloadState ;Must be data => Payload state call flFCSInit ;Init FCS mov flPosition, #-3 ;Init buffer position jmp flRxPassData ;pass data to payload layer (payload layer issues ret instruction) :Idle clr flState ;EOF indicating sender has terminated frame => return to idle state retp :Ctrl mov flState, #flRxCtrlState ;CE indicating transparency issue => change to Ctrl state retp ;********** a2flRxAvail - Payload State ********** flRxPayload ;Currently receiving payload csne flData, #BOF ;Was byte a BOF indicating sender has terminated the payload and started again ? jmp :Begin ;Yes => terminate payload and goto Begin state csne flData, #EOF ;Was byte an EOF indicating the frame/payload is complete ? jmp :Idle ;Yes => signal complete payload and retpurn to idle state csne flData, #CE ;Was byte a CE indicating a transparency issue ? jmp :Ctrl ;Yes => change to Ctrl state jmp flRxPassData ;pass data to payload layer (payload layer issues retp instruction) :Begin mov flState, #flRxBeginState ;premature BOF => indicate payload reset to payload layer and retpurn to RxBegin State jmp @fl2plRxError ;indicate error to payload layer (payload layer issues retp instruction) :Idle clr flState ;EOF => end of frame reached => inform payload layer and retpurn to idle state cse flFCSh, #ValidFCSh ;valid FCS (high) ? jmp @fl2plRxError ;No => indicate reset to payload layer (payload layer issues retp instruction) cse flFCSl, #ValidFCSl ;valid FCS (low) ? jmp @fl2plRxError ;No => indicate reset to payload layer (payload layer issues retp instruction) jmp @fl2plRxValid ;FCS valid => indicate complete to payload layer (payload layer issues retp instruction) :Ctrl mov flState, #flRxCtrlState retp ;********** a2flRxAvail - Ctrl State ********** flRxCtrl ;CE has been encountered, need to check next character csne flData, #BOF ;Was byte BOF indicating sender has terminated payload and started again ? jmp :Begin ;Yes => restart at Begin state (Note payload layer has been passed data => must inform payload layer of reset) csne flData, #EOF ;Was byte EOF indicating sender has terminated frame ? jmp :Idle ;Yes => retpurn to idle (Note: payload layer has been passed any data => must inform payload layer of reset) mov flState, #flRxPayloadState ;Must be data => pass data to payload layer and retpurn to payload state xor flData, #$20 ;Recover data jmp flRxPassData ;pass data to payload layer (payload layer issues retp instruction) :Begin mov flState, #flRxBeginState ;BOF => sender has terminated payload and started again => retpurn to begin state jmp @fl2plRxError ;indicate error to payload layer (payload layer issues retp instruction) :Idle clr flState ;EOF => sender has terminated frame => retpurn to idle state jmp @fl2plRxError ;indicate error to payload layer (payload layer issues retp instruction) ;******************************************************************************** ; FRAMING LAYER - Transmit ;******************************************************************************** flTxSendData ;Send byte (w) now (doesn't check for busy) bank IsrBank mov IrdaData, w ;Byte to send setb IrdaTxStart ;Send byte debug PhysicalDataTx ;Debug: pass data being transmitted retp ;WARNING - not in flBank ;********** pl2flTxFrame ********** pl2flTxFrame ;Request to start a new frame bank flBank mov flState, #flTxBeginState ;Next state = begin mov flPosition, flFFCount ;Counter = FFCount mov w, #$FF jmp flTxSendData ;Send FF (flTxSendData issues ret instruction) ;********** a2flTxEmpty - Begin State ********** flTxBegin ;Sending prefex FF bytes dec flPosition ;Decrement counter snz ;Zero ? jmp :BOF ;Yes => send BOF and set next state to send payload data mov w, #$FF ;No => Send another FF jmp flTxSendData ;(TxSendData issues ret instruction) :BOF mov flState, #flTxPayloadState ;Will enter flTxPayload state after BOF has been sent call flFCSInit ;Init FCS mov w, #BOF ;Send BOF jmp flTxSendData ;********** a2flTxEmpty - Send States ********** flTxPayload call @fl2plTxData ;Get data from payload layer bank flBank snz ;Is this the last byte ? (Z set) inc flState ;Yes => Next State = FCSl mov flData, w ;Store data debug PayloadDataTx ;Debug: pass payload data being transmitted call flFCSData ;w = flData - Add data to FCS jmp flTxSend ;Check for control code and send flTxFCSl mov w, /flFCSl ;Next data to send = FCSl mov flData, w ;Store in TxData inc flState ;Next State = FCSh jmp flTxSend ;Check for control code and send flTxFCSh mov w, /flFCSh ;Next data to send = FCSh mov flData, w ;Store in TxData inc flState ;Next State = End jmp flTxSend ;Check for control code and send flTxSend ;Send payload byte csne flData, #BOF ;Is byte a control code ? jmp :Ctrl ;Yes => transparency issue csne flData, #EOF ;Is byte a control code ? jmp :Ctrl ;Yes => transparency issue csne flData, #CE ;Is byte a control code ? jmp :Ctrl ;Yes => transparency issue mov w, flData ;Yes => transmit data jmp flTxSendData ;Send byte :Ctrl mov flPosition, flState ;Store current state in position variable mov flState, #flTxCtrlState ;Next state = TxCtrlState mov w, #CE jmp flTxSendData ;Send CE code (TxSendData issues ret instruction) flTxCtrl mov flState, flPosition ;Recover old state from position variable mov w, flData xor w, #$20 ;Encode data jmp flTxSendData ;********** a2flTxEmpty - SendEnd State ********** flTxSendEnd ;FCS finished => send EOF to close frame inc flState ;Next state = flTxWaitEnd state mov w, #EOF jmp flTxSendData ;Send EOF (TxSendData issues ret instruction) ;********** a2flTxEmpty - WaitEnd State ********** flTxWaitEnd ;Frame finished and now last byte has finished sending clr flState ;Return to idle state jmp @fl2plTxComplete ;Inform payload layer that the transmission is complete (payload layer issues retp instruction) ;******************************************************************************** ENDM PayloadInfoSeg MACRO ;******************************************************************************** ; PAYLOAD LAYER ;******************************************************************************** ; ;Framing Layer Events ; ; fl2plRxData(w=Data) ;Data byte from frame ; fl2plRxValid() ;Payload data is complete and valid ; fl2plRxError() ;Payload data contains errors ; pl2flRxIgnore() call ;Tell framing layer to ignore the current frame ; ; pl2flTxStart() ;Request framing layer to start a frame ; fl2plTxData(var w=Data var z=Last) call ;Request for data from framing layer - Z flag is set if its the last byte ; fl2plTxComplete() ;Transmission is complete ; ;LAP Layer Events ; ; pl2lapRxFrame(w=Type) ;Incomming frame of given type ; pl2lapRxValid() ;Frame was valid ; pl2lapRxError() ;Frame was invalid ; pl2lapRxXIDData(w=Data) ;Pass XID data to lap layer ; pl2lapRxIData(w=Data) ;Pass I data to lap layer ; pl2lapRxUIData(w=Data) ;Pass I data to lap layer ; lap2plRxIgnore() ;LAP layer has requested that the frame should be ignored ; ; lap2plSNRMAccept() ;Accept connection and send reply ; lap2plTxXIDCmd(w=Slot) ;Send a XID command frame ; lap2plTxXIDRsp() ;Send a XID response frame ; lap2plTxSimpleRsp(w=Command) ;Send simple response frame ; lap2plTxIRsp(w=Command) ;Send an I frame ; pl2lapTxIData(ret w=Data ret z=Last) call ;Request for data ; pl2lapTxComplete() ;Complete indication ; ; lap2plGenerateNewAddr ;Request that a new 32-bit address be generated ; ;******************************************************************************** ENDM PayloadDataSeg MACRO ;******************************************************************************** ; PAYLOAD LAYER ;******************************************************************************** org $50 plBank = $50 ;16 bytes used - Bank not shared plState ds 1 ;Current state plData ds 1 ;Incomming byte of payload data plFrameType ds 1 ;The frame type for shared code / passed to lap layer plCommand ds 1 plPosition ds 1 ;Current position for multibyte states plConnAddr ds 1 ;Connection address (must be FF if not connected) plSelfAddr ds 4 ;Own 4 byte address plDestAddr ds 4 ;Dest 4 byte address plInfo ds 2 ;Frame specific information plTxAddressByte = plData ;Address to be transmitted plTxPostCommand = plPosition plIDataDLSAP = plInfo+0 ;DLSAP byte from/for a I Data frame plIDataSLSAP = plInfo+1 ;SLSAP byte from/for a I Data frame plXIDSlot = plInfo+0 ;Slot number from/for a XID frame plXIDFlags = plInfo+1 ;Discovery Flags from/for a XID frame plSNRMConnAddr = plInfo+0 ;Connection Address of SNRM frame plSNRMBaudRate = plInfo+1 ;Baudrate parameter from SNRM frame iFrame = 1 sRRFrame = 2 sRNRFrame = 3 sREJFrame = 4 sSREJFrame = 5 uUIFrame = 6 ;UICmd or UIRsp (same command) uDISCFrame = 7 ;DISCCmd or RDRsp (same command) uUARspFrame = 8 ;UARsp uNRMFrame = 9 ;SNRMCmd or RNRMRsp (same command) uTESTFrame = 10 ;TESTCmd or TESTRsp (same command) uFRMRRspFrame = 11 ;FRMRRsp uDMRspFrame = 12 ;DMRsp uXIDCmdFrame = 13 ;XIDCmd uXIDRspFrame = 14 ;XIDRsp sRR = %00010001 ;%xxx10001 sRNR = %00010101 ;%xxx10101 sREJ = %00011001 ;%xxx11001 sSREJ = %00011101 ;%xxx11101 uSNRMCmd = %10010011 uDISCCmd = %01010011 uUICmd = %00010011 uXIDCmd = %00111111 uTESTCmd = %11110011 uRNRMRsp = %10010011 uUARsp = %01110011 uFRMRRsp = %10010111 uDMRsp = %00011111 uRDRsp = %01010011 uUIRsp = %00010011 uXIDRsp = %10111111 uTESTRsp = %11110011 plRxState = %00000000 plTxState = %10000000 plRxCommandState = 1 + plRxState ; plRxDataIgnoreState = 2 + plRxState plRxIDataState = 3 + plRxState ;RxI plRxUIDataState = 4 + plRxState ;RxUI plRxXIDFormatState = 5 + plRxState ;RxXID plRxXIDSourceState = 6 + plRxState ;RxXID plRxXIDDestState = 7 + plRxState ;RxXID plRxXIDFlagsState = 8 + plRxState ;RxXID plRxXIDSlotState = 9 + plRxState ;RxXID plRxXIDVersionState = 10 + plRxState ;RxXID plRxXIDInfoState = 11 + plRxState ;RxXID plRxSNRMSourceState = 12 + plRxState ;RxSNRM plRxSNRMDestState = 13 + plRxState ;RxSNRM plRxSNRMAddrState = 14 + plRxState ;RxSNRM plRxSNRMParamTypeState = 15 + plRxState ;RxSNRM plRxSNRMParamSizeState = 16 + plRxState ;RxSNRM plRxSNRMParamDataState = 17 + plRxState ;RxSNRM plTxCompleteState = 1 + plTxState ;Waiting for Complete indication from framing Layer plTxAddressState = 2 + plTxState ; plTxCommandState = 3 + plTxState ; plTxIDataDLSAPState = 4 + plTxState ; plTxIDataSLSAPState = 5 + plTxState ; plTxIDataDataState = 6 + plTxState ; plTxUIDataState = 7 + plTxState ; plTxXIDFormatState = 8 + plTxState ; plTxXIDSourceState = 9 + plTxState ; plTxXIDDestState = 10 + plTxState ; plTxXIDFlagsState = 11 + plTxState ; plTxXIDSlotState = 12 + plTxState ; plTxXIDVersionState = 13 + plTxState ; plTxXIDFooterState = 14 + plTxState ; plTxUASourceState = 15 + plTxState ; plTxUADestState = 16 + plTxState ; plTxUABaudRateState = 17 + plTxState ; plTxUAParamState = 18 + plTxState ; ;******************************************************************************** ENDM PayloadCodeSeg MACRO ;******************************************************************************** ; PAYLOAD LAYER ;******************************************************************************** ;********** a2plReset ********** a2plReset bank plBank clr plState ;Reset to idle state mov plConnAddr,#$FF ;Not connected => address must be $FF retp ;********** fl2plRxData ********** fl2plRxData bank plBank snb plState.7 ;Check that it is a RxState retp ;Tx state => return mov plData, w ;Store incomming byte debug PayloadDataRx ;Debug: Pass payload byte received mov w, plState ;Jump based on state jmp PC+w jmp plRxIdle ; 0 = plIdleState jmp plRxCommand ; 1 = plRxCommandState retp ; 2 = plRxDataIgnoreState jmp plRxIData ; 3 = plRxIDataState jmp plRxUIData ; 4 = plRxUIDataState jmp plRxXIDFormat ; 5 = plRxXIDFormatState jmp plRxXIDSource ; 6 = plRxXIDSourceState jmp plRxXIDDest ; 7 = plRxXIDDestState jmp plRxXIDFlags ; 8 = plRxXIDFlagsState jmp plRxXIDSlot ; 9 = plRxXIDSlotState jmp plRxXIDVersion ;10 = plRxXIDVersionState jmp plRxXIDInfo ;11 = plRxXIDInfoState jmp plRxSNRMSource ;12 = plRxSNRMSourceState jmp plRxSNRMDest ;13 = plRxSNRMDestState jmp plRxSNRMAddr ;14 = plRxSNRMAddrState jmp plRxSNRMParamType ;15 = plRxSNRMParamTypeState jmp plRxSNRMParamSize ;16 = plRxSNRMParamSizeState jmp plRxSNRMParamData ;17 = plRxSNRMParamDataState ;********** fl2plTxData ********** fl2plTxData bank plBank sb plState.7 ;Check that it is a TxState retp ;Rx state => return mov w, plState ;Jump based on state and w, #%01111111 ;Remove Tx state flag jmp PC+w retp ; 0 = Invalid state retp ; 1 = plTxCompleteState (Cannot receive TxData in this state) jmp plTxAddress ; 2 = plTxAddressState jmp plTxCommand ; 3 = plTxCommandState jmp plTxIDataDLSAP ; 4 = plTxIDataDLSAPState jmp plTxIDataSLSAP ; 5 = plTxIDataSLSAPState jmp plTxIDataData ; 6 = plTxIDataDataState jmp plTxUIData ; 7 = plTxUIDataState jmp plTxXIDFormat ; 8 = plTxXIDFormatState jmp plTxXIDSource ; 9 = plTxXIDSourceState jmp plTxXIDDest ;10 = plTxXIDDestState jmp plTxXIDFlags ;11 = plTxXIDFlagsState jmp plTxXIDSlot ;12 = plTxXIDSlotState jmp plTxXIDVersion ;13 = plTxXIDVersionState jmp plTxXIDFooter ;14 = plTxXIDFooterState jmp plTxUASource ;15 = plTxUASourceState jmp plTxUADest ;16 = plTxUADestState jmp plTxUABaudRate ;17 = plTxUABaudRateState jmp plTxUAParam ;18 = plTxUAParamState ;********** fl2plTxComplete ********** fl2plTxComplete bank plBank clr plState ;return to idle state debugl PayloadDataTx, '^' ;Debug: Payload data complete indication jmp @pl2lapTxComplete ;Indicate complete to lap layer (pl2lapTxComplete will issue ret instrustion) ;********** lap2plTxUICmd ********** lap2plTxUICmd jmp plTxUICmd ;******************************************************************************** ; PAYLOAD LAYER - Internal Subroutines ;******************************************************************************** plRxDecodeSCmd ;WARNING - does not set pa bits when ret => must be callled form same half page mov Temp, w ;Command: check bits %....nn.. rr Temp ;Shift command right 1 mov w, >>Temp ;Shift command right 1 and into w and w, #%00000011 ;Mask out unwanted bits jmp PC+w ;jump based on w retw sRRFrame ;....00.. = RR retw sRNRFrame ;....01.. = RNR retw sREJFrame ;....10.. = REJ retw sSREJFrame ;....11.. = SREJ plRxDecodeUNextState ;WARNING - does not set pa bits when ret => must be callled form same half page mov Temp, w ;FrameType mov w, #uUIFrame ;lowest FrameType constant for a U frame sub Temp, w ;subtract lowest valid number so uUIFrame is now 0 mov w, Temp jmp PC+w retw plRxUIDataState ;uUIFrame = 6 ;UICmd or UIRsp (same command) retw plRxDataIgnoreState ;uDISCFrame = 7 ;DISCCmd or RDRsp (same command) retw plRxDataIgnoreState ;uUARspFrame = 8 ;UARsp retw plRxSNRMSourceState ;uNRMFrame = 9 ;SNRMCmd or RNRMRsp (same command) retw plRxDataIgnoreState ;uTESTFrame = 10 ;TESTCmd or TESTRsp (same command) retw plRxDataIgnoreState ;uFRMRRspFrame = 11 ;FRMRRsp retw plRxDataIgnoreState ;uDMRspFrame = 12 ;DMRsp retw plRxXIDFormatState ;uXIDCmdFrame = 13 ;XIDCmd retw plRxXIDFormatState ;uXIDRspFrame = 14 ;XIDRsp lap2plGenerateNewAddr ;Note: code is synchronous with the ISR therfore RTCC and Timer registers are not random numbers bank TimerBank mov w, Random ;Random number bank plBank mov plSelfAddr+0, w ;Byte 0 = Random number mov FSR, w mov w, INDF bank plBank mov plSelfAddr+1, w ;Byte 1 = contents of the register pointer to by the Random number mov m, w ;m = byte 1 number (semi random) mov w, plSelfAddr+0 ;w = byte 0 number (fully random) iread ;read ROM and address given by w and m mov plSelfAddr+2, w ;Byte 2 = low contents of ROM pointed to by byte1:byte0 mov w, m ;w = m = high 4 bits of ROM contents mov plSelfAddr+3, w ;Byte 3 = high contents of ROM pointed to by byte1:byte0 retp ;******************************************************************************** ; PAYLOAD LAYER - Receive ;******************************************************************************** ;********** fl2plRxValid ********** fl2plRxValid clrb ledERR ;Turn ERR led off debugl PayloadDataRx, '^' ;Debug: Indicate complete bank plBank clr plState ;Return to idle state jmp @pl2lapRxValid ;Inform lap layer that frame was valid (lap layer will issue ret instruction) ;********** fl2plRxError ********** fl2plRxError setb ledERR ;Turn ERR led on debugl PayloadDataRx, '!' ;Debug: Indicate error bank plBank clr plState ;Return to idle state jmp @pl2lapRxError ;Inform lap layer that frame was invalid (lap layer will issue ret instruction) ;********** lap2plRxIgnore ********** lap2plRxIgnore ;Ignore the current incomming frame bank plBank plRxIgnore clr plState ;Return to idle state jmp @pl2flRxIgnore plRxInvalid clr plState ;Return to idle state call @pl2flRxIgnore jmp @pl2lapRxError ;Inform lap layer of error ;******************************************************************************** ; PAYLOAD LAYER - RxData General ;******************************************************************************** plRxStoreSource mov w, #plDestAddr ;pointer to DestAddress variable add w, plPosition ;add offset mov FSR, w ;Now can indirectly access mov INDF, plData ;Store byte into SourceAddr inc plPosition ;Move offset ready for next byte of SourceAddr cse plPosition, #4 ;Have 4 bytes been received ? retp ;No => remain in this state waiting for next byte inc plState ;Yes => end of Source. Change to next state clr plPosition retp plRxTestDest ;WARNING : will pass FF bytes in specific address (ie bytewise checking, not FFFFFFFF checking) csne plData, #$FF ;Broadcast address ? jmp :Cont ;Yes => Contiue mov w, #plSelfAddr ;pointer to SelfAddress variable add w, plPosition ;add offset mov FSR, w ;Now can indirectly access cse plData, INDF ;Self Address ? jmp plRxInvalid ;No => Ignore frame, Inform lap layer of error, and return to idle :Cont inc plPosition ;Move offset ready for next byte of DestAddr cse plPosition, #4 ;Have 4 bytes been received ? retp ;No => remain in this state waiting for next byte inc plState ;Yes => end of DestAddr. Change to next state clr plPosition retp ;******************************************************************************** ; PAYLOAD LAYER - RxData ;******************************************************************************** ;********** fl2plRxData - Idle State ********** plRxIdle ;First byte = address mov w, plData ;Received Address xor w, plConnAddr ;Compare with interested address sz ;Valid address ? jmp plRxIgnore ;No => ignore mov plState, #plRxCommandState ;Yes => next will receive command byte retp ;********** fl2plRxData - RxCommand State ********** plRxCommand mov plCommand, plData ;Store command sb plCommand.4 ;Is the P/F bit set ? jmp plRxIgnore ;No => Ignore frame (IrDA lite spec p10 and p16) and return to idle state sb plCommand.0 ;Is this an I frame ? (%.......0) jmp plRxICommand ;Yes => process sb plCommand.1 ;No => must be S or U frame. Is this a S frame ? jmp plRxSCommand ;Yes (%......01) => process S frame jmp plRxUCommand ;No (%......11) => process U frame plRxICommand debugl PayloadInfo, 'I' mov plState, #plRxIDataState ;Next should be data mov plFrameType, #iFrame ;store frame type and w will also be passed to lap layer jmp @pl2lapRxFrame ;pass message (lap layer will issue ret instruction) plRxSCommand debugl PayloadInfo, 'S' mov plState, #plRxDataIgnoreState ;Next should be complete indication (ie no data) but need waiting state mov w, plCommand call plRxDecodeSCmd ;pass w = plRxData, returns w for plFrameType mov plFrameType, w ;store frame type and w will also be passed to lap layer jmp @pl2lapRxFrame ;pass message (lap layer will issue ret instruction) plRxUCommand debugl PayloadInfo, 'U' mov plPosition, #_plUCommands ;plPosition = 1st byte of data :Loop mov m, #_plUCommands / 256 ;m = Pointer to string (high) mov w, plPosition ;w = Pointer to string (low) inc plPosition ;Increment offset for next byte iread ;Read data byte from ROM xor w, plCommand ;is the byte the same as the received command ? jz :Found ;Yes => must be valid mov w, m ;No => try again. Move high part of data to w test w ;Is this the last byte ? jz :Loop ;No => try again jmp plRxIgnore ;Yes => Invalid command => ignore and return to idle state :Found mov plFrameType, plPosition ;plFrameType = position mov w, #_plUCommands + 1 ;w = starting offset sub plFrameType, w ;remove offset => FrameType 0 for a uUIFrame mov w, #uUIFrame ;constant of first type of U command (uUIFrame = 6) add plFrameType, w ;FrameType is now correct mov w, plFrameType ;pass FrameType in w call plRxDecodeUNextState ;Returns w = next state mov plState, w ;Store state clr plPosition ;Clear position for following states mov w, plFrameType ;pass frame type to lap layer jmp @pl2lapRxFrame ;pass message (lap layer will issue ret instruction) ;******************************************************************************** ; PAYLOAD LAYER - Receiving I Frame ;******************************************************************************** ;********** fl2plRxData - RxIData State ********** plRxIData mov w, plData ;Data to pass debug IFrameDataRx ;Show debug info jmp @pl2lapRxIData ;Pass data to lmp layer (via lap layer) ;******************************************************************************** ; PAYLOAD LAYER - Receiving UI Frame ;******************************************************************************** ;********** fl2plRxData - RxUIData State ********** plRxUIData mov w, plData ;Data to pass jmp @pl2lapRxUIData ;Pass data to app layer (via lap layer) ;******************************************************************************** ; PAYLOAD LAYER - Receiving XID Frame ;******************************************************************************** ;********** fl2plRxData - RxXIDFormat State ********** plRxXIDFormat cse plData, #1 ;Format must be 1 jmp plRxInvalid ;No => Ignore frame, inform lap layer, and return to idle state inc plState ;Next 4 bytes will be the source address => Enter plRxXIDSourceState clr plPosition ;Byte 0 of the source address retp ;********** fl2plRxData - RxXIDSource State ********** plRxXIDSource = plRxStoreSource ;Store byte in DestAddr ;********** fl2plRxData - RxXIDDest State ********** plRxXIDDest = plRxTestDest ;Compare 4 bytes with SelfAddr (mismatch of not FFFFFFFF will change to ignore state) ;********** fl2plRxData - RxXIDFlags State ********** plRxXIDFlags mov plXIDFlags, plData ;Store the flags for the response inc plState ;Next will receive the slot number (plRxXIDSlotState) retp ;********** fl2plRxData - RxXIDSlot State ********** plRxXIDSlot mov plXIDSlot, plData ;Store the slot number inc plState ;plRxXIDVersionState retp ;********** fl2plRxData - RxXIDVersion State ********** plRxXIDVersion test plData ;Is version = 0 ? jnz plRxInvalid ;No => Ignore frame, inform lap layer, and return to idle state inc plState ;Next bytes will be the Descovery Info if any (plRxXIDInfoState) clr plPosition ;Clear position for next state retp ;********** fl2plRxData - RxXIDInfo State ********** plRxXIDInfo mov w, plData ;Get data byte jmp @pl2lapRxXIDData ;Pass data to lap layer ;******************************************************************************** ; PAYLOAD LAYER - Receiving SNRM Frame ;******************************************************************************** ;********** fl2plRxData - RxSNRMSource State ********** plRxSNRMSource = plRxStoreSource ;********** fl2plRxData - RxSNRMDest State ********** plRxSNRMDest = plRxTestDest ;********** fl2plRxData - RxSNRMAddr State ********** plRxSNRMAddr mov plSNRMConnAddr, plData ;Store ConnAddr (only apply if frame is validated) mov plSNRMBaudRate, #%00000010 ;If no baud rate received then default to 9600 (bit 1 indicates 9600) inc plState ;#plRxSNRMParamTypeState - Next bytes are the negioation parameters retp ;********** fl2plRxData - RxSNRMParam State ********** plRxSNRMParamType inc plState ;#plRxSNRMParamSizeState - Next byte will state how many bytes of data csne plData, #$01 ;Receiving type $01 = baud rate ? setb plSNRMBaudRate.0 ;Yes => Set flag to indicate receiving baud rate (bit 0 is normally used to indicate 2400 which we do not support thus will be removed later) retp ;No => continue plRxSNRMParamSize mov plPosition, plData ;RxData states how many bytes of data inc plState ;#plRxSNRMParamDataState - Next bytes will be the param data retp plRxSNRMParamData decsz plPosition ;Decrement counter; Zero ? jmp :More ;No => wait for more mov plState, #plRxSNRMParamTypeState ;Yes => Next byte will be another parameter :More sb plSNRMBaudRate.0 ;Is this byte the first byte of the baud rate parameter retp ;No => ignore mov w, plData ;Get baud rate parameter and w, #%00111110 ;And with our supported baud rates = 9600(bit 1), 19200(bit 2), 38400(bit 3) 57600(bit 4) 115200(bit 5) mov plSNRMBaudRate, w ;Store in SNRMBaudRate (note bit 0 is now clear => will correctly ignore next byte of parameter if it is a 2 byte parameter) setb plSNRMBaudRate.1 ;Force 9600 to be valid retp ;******************************************************************************** ; PAYLOAD LAYER - Tx ;******************************************************************************** plTxFooter ;w = Addr, m = Addr / 256 add w, plPosition ;Add offset inc plPosition ;Increment offset for next byte iread mov Temp, w ;Store data mov w, m ;Move high part of data to w test w ;Is this the last byte ? jnz :Last ;Yes => Jump mov w, Temp ;Data byte to be transmitted clz ;Indicate more data to follow retp ;Return data to framing layer :Last mov plState, #plTxCompleteState ;Last byte => change to complete state mov w, Temp ;Data byte to be transmitted stz ;Indicate complete retp ;Return data to framing layer plTxSelfAddr mov w, #plSelfAddr ;pointer to SelfAddress variable add w, plPosition ;add offset mov FSR, w ;Now can indirectly access inc plPosition ;Move offset ready for next byte of SourceAddr cse plPosition, #4 ;Sent all 4 bytes ? jmp :Send ;No => Send current byte (stay in this state) inc plState ;Yes => Send current byte (next state) clr plPosition :Send mov w, INDF ;Byte of Source Address clz ;Indicate more data to follow retp ;Return data to framing layer plTxDestAddr mov w, #plDestAddr ;pointer to recorded DestAddress variable add w, plPosition ;add offset mov FSR, w ;Now can indirectly access inc plPosition ;Move offset ready for next byte cse plPosition, #4 ;Sent all 4 bytes ? jmp :Send ;No => Send current byte (stay in this state) inc plState ;Yes => Send current byte (Next will send Discovery flags) clr plPosition :Send mov w, INDF ;Byte of Source Address clz ;Indicate more data to follow retp ;Return data to framing layer ;******************************************************************************** plTxCmdStart mov plState, #plTxAddressState ;First byte = address mov plTxAddressByte, plConnAddr ;Address = ConnAddr setb plTxAddressByte.0 ;Indicate Cmd frame jmp @pl2flTxFrame ;Ask to framing layer to start a new frame plTxRspStart mov plState, #plTxAddressState ;First byte = address mov plTxAddressByte, plConnAddr ;Address = ConnAddr clrb plTxAddressByte.0 ;Indicate Cmd frame jmp @pl2flTxFrame ;Ask to framing layer to start a new frame ;********** fl2plTxData - TxAddress State ********** plTxAddress inc plState ;After address will send command mov w, plTxAddressByte ;Send Address clz ;Indicate more data to follow retp ;Return Data to framing layer ;********** fl2plTxData - TxCommand State ********** plTxCommand mov plState, plTxPostCommand ;After command will change to state given in TxIState clr plPosition ;Clear position just in case needed for following states csne plState, #plTxCompleteState ;Is this the last byte to be sent ? jmp :Last ;Yes mov w, plCommand ;Send Command clz ;Indicate more data to follow retp ;Return Data to framing layer :Last mov w, plCommand ;Send Command stz ;Indicate complete retp ;Return Data to framing layer ;******************************************************************************** ; PAYLOAD LAYER - Send Simple Frame ;******************************************************************************** lap2plTxSimpleCmd ;Transmit a frame of type specified in w bank plBank mov plCommand, w ;Store command in plCommand mov plTxPostCommand, #plTxCompleteState ;After address & command frame will be complete jmp plTxCmdStart ;Set State and Address, and ask framing layer to start frame lap2plTxSimpleRsp ;Transmit a frame of type specified in w bank plBank mov plCommand, w ;Store command in plCommand mov plTxPostCommand, #plTxCompleteState ;After address & command frame will be complete jmp plTxRspStart ;Set State and Address, and ask framing layer to start frame ;******************************************************************************** ; PAYLOAD LAYER - Send I Frame ;******************************************************************************** lap2plTxIRsp bank plBank mov plCommand, w ;Store command in plCommand mov plTxPostCommand, #plTxIDataDLSAPState ;After address & command will send data jmp plTxRspStart ;Set State and Address, and ask framing layer to start frame plTxIDataDLSAP inc plState ;Next state = plTxIDataSLSAP mov w, plIDataDLSAP ;Send DLSAP byte debug IFrameDataTx ;Show debug info clz ;Indicate more data to follow retp plTxIDataSLSAP inc plState ;Next state = plTxIDataData mov w, plIDataSLSAP ;Send SLSAP byte debug IFrameDataTx ;Show debug info clz ;Indicate more data to follow retp plTxIDataData call @pl2lapTxIData ;Get next byte to be transmitted (returns z = false if data) debug IFrameDataTx ;Show debug info snz ;Is the z flag set (Last byte) ? jmp :Last ;Yes => jump retp ;Z is still clear indicating more data to follow :Last mov Temp, w ;Backup data bank plBank mov plState, #plTxCompleteState ;New state = Wait for complete indication mov w, Temp ;Recover data stz ;Indicate no more data to follow retp ;******************************************************************************** ; PAYLOAD LAYER - Send UI Frame ;******************************************************************************** plTxUICmd bank plBank mov plCommand, #uUICmd ;Store command in plCommand mov plTxPostCommand, #plTxUIDataState ;After address & command will send data jmp plTxCmdStart ;Set State and Address, and ask framing layer to start frame plTxUIData call @pl2lapTxUIData ;Get next byte to be transmitted (returns z = false if data) snz ;Is the z flag set (Last byte) ? jmp :Last ;Yes => jump retp ;Z is still clear indicating more data to follow :Last mov Temp, w bank plBank mov plState, #plTxCompleteState ;New state = Wait for complete indication mov w, Temp ;Recover data stz ;Indicate no more data to follow retp ;******************************************************************************** ; PAYLOAD LAYER - Send XID Frame ;******************************************************************************** ;********** lap2plTxXIDCmd ********** lap2plTxXIDCmd bank plBank mov plXIDSlot, w ;Store slot number mov plCommand, #uXIDCmd ;Command = XID command mov w, #$FF mov plDestAddr+0, w ;Dest address = FFFFFFFF mov plDestAddr+1, w ;Dest address = FFFFFFFF mov plDestAddr+2, w ;Dest address = FFFFFFFF mov plDestAddr+3, w ;Dest address = FFFFFFFF mov plXIDFlags, #2 ;Set flags = 2 (=> 8 slots) mov plFrameType, #uXIDCmdFrame ;Rember that this is a XID Command Frame mov plTxPostCommand, #plTxXIDFormatState ;After address & command will send format jmp plTxCmdStart ;Set State and Address, and ask framing layer to start frame ;********** lap2plTxXIDRsp ********** lap2plTxXIDRsp bank plBank mov plCommand, #uXIDRsp ;Command = XID response mov plFrameType, #uXIDRspFrame ;Rember that this is a XID Response Frame mov plTxPostCommand, #plTxXIDFormatState ;After address & command will send format jmp plTxRspStart ;Set State and Address, and ask framing layer to start frame ;********** fl2plTxNext - TxXIDFormat State ********** plTxXIDFormat ;Send XID Format byte inc plState ;Next will send source mov w, #1 ;Format = 1 clz ;Indicate more data to follow retp ;Return data to framing layer ;********** fl2plTxNext - TxXIDSource State ********** plTxXIDSource = plTxSelfAddr ;********** fl2plTxNext - TxXIDDest State ********** plTxXIDDest = plTxDestAddr ;********** fl2plTxNext - TxXIDFlags State ********** plTxXIDFlags inc plState ;After Flags will send slot number (plTxSlotState) mov w, plXIDFlags ;Reply with same flags as received command frame clz ;Indicate more data to follow retp ;Return data to framing layer ;********** fl2plTxNext - TxXIDSlot State ********** plTxXIDSlot csne plFrameType, #uXIDRspFrame ;Is the frame a XID response frame ? jmp :Footer ;Yes => must send footer csne plXIDSlot, #$FF ;Is the slot number FF ? jmp :Footer ;Yes => must send footer mov plState, #plTxXIDVersionState ;No => Send slot followed by version only jmp :Send :Footer mov plState, #plTxXIDFooterState clr plPosition ;Set to 0 ready for footer :Send mov w, plXIDSlot ;Transmit slot number clz ;Indicate more data to follow retp ;Return data to framing layer ;********** fl2plTxNext - TxXIDVersion State ********** plTxXIDVersion mov plState, #plTxCompleteState ;After version will indicate complete mov w, #0 ;Version = 0 stz ;Indicate complete retp ;Return data to framing layer ;********** fl2plTxNext - TxXIDFooter State ********** plTxXIDFooter mov m, #_plXIDFooter / 256 ;Pointer to string (high) mov w, #_plXIDFooter ;Pointer to string jmp plTxFooter ;******************************************************************************** ; PAYLOAD LAYER - Send UA Connection Frame ;******************************************************************************** lap2plSNRMAccept bank plBank mov plCommand, #uUARsp ;Send UA packet to accept connection mov plConnAddr, plSNRMConnAddr ;Apply connection address setb plConnAddr.0 ;Only accept command frames mov plTxPostCommand, #plTxUASourceState ;After address & command will send source jmp plTxRspStart ;Set State and Address, and ask framing layer to start frame plTxUASource = plTxSelfAddr plTxUADest = plTxDestAddr plTxUABaudRate ;Send $01, $01, BaudRate inc plPosition csne plPosition, #3 ;Is position 3 indicating to send BaudRate ? jmp :Baud ;Yes => send BaudRate mov w, #$01 ;Data to send = $01 clz ;Indicate more data to follow retp ;Return data to framing layer :Baud inc plState ;Next state = plTxUAParamState clr plPosition ;Clear position ready for next state mov w, plSNRMBaudRate ;Data to send = BaudRate clz ;Indicate more data to follow retp ;Return data to framing layer plTxUAParam mov m, #_plSNRMParam / 256 ;Pointer to string (high) mov w, #_plSNRMParam ;Pointer to string jmp plTxFooter ;******************************************************************************** ENDM PayloadString1 MACRO ;******************************************************************************** ; PAYLOAD LAYER - String ;WARNING - Strings must not go over a 256 boundry !!! ;******************************************************************************** _plUCommands ;Must be in the same order as the FrameType constants !!! _plUCommand6 dw uUICmd ;UICmd or UIRsp (same command) _plUCommand7 dw uDISCCmd ;DISCCmd or RDRsp (same command) _plUCommand8 dw uUARsp ;UARsp _plUCommand9 dw uSNRMCmd ;SNRMCmd or RNRMRsp (same command) _plUCommand10 dw uTESTCmd ;TESTCmd or TESTRsp (same command) _plUCommand11 dw uFRMRRsp ;FRMRRsp _plUCommand12 dw uDMRsp ;DMRsp _plUCommand13 dw uXIDCmd ;XIDCmd _plUCommand14 dw uXIDRsp + $F00 ;XIDRsp (F00 indicates end of string) ;******************************************************************************** ENDM PayloadString2 MACRO ;******************************************************************************** ; PAYLOAD LAYER - String ;WARNING - Strings must not go over a 256 boundry !!! ;******************************************************************************** ;_plSNRMParam1 dw $01, 1, %00000010 ;Baud Rate = 9600 bps Flexible _plSNRMParam _plSNRMParam2 dw $82, 1, %00000001 ;Turnaround = 500 ms Solid _plSNRMParam3 dw $83, 1, %00000001 ;Data Size = 64 bytes Flexible ? _plSNRMParam4 dw $84, 1, %00000001 ;Window Size = 1 Solid _plSNRMParam5 dw $85, 1, %10000000 ;Additional BOFs = 0 Solid _plSNRMParam6 dw $86, 1, %00000011 ;Min turnaround = 5/10 ms Solid to IrDA Transeiver spec _plSNRMParam7 dw $08, 1, %00000001+$F00 ;Disconnect = 3 s Solid ;******************************************************************************** ENDM PayloadString3 MACRO ;******************************************************************************** ; PAYLOAD LAYER - String ;WARNING - Strings must not go over a 256 boundry !!! ;******************************************************************************** _plXIDFooter _plXIDVersion dw 0 ;Version = 0 (only possible) _plXIDHints dw $80, $04 ;Hints = IrComm _plXIDCharset dw 0 ;Charset = ASCII _plXIDNickname dw 'SX IrComm Device'+$F00 ;Nickname ($F00 indicates end) ;******************************************************************************** ENDM LapInfoSeg MACRO ;******************************************************************************** ; LAP LAYER ;******************************************************************************** ; ;Framing Layer Events ; ; fl2lapMediaBusy() ;A byte has been received => the media is busy ; ;Payload Layer Events ; ; pl2lapRxFrame(w=Type) ;Incomming frame of given type ; pl2lapRxValid() ;Frame was valid ; pl2lapRxError() ;Frame was invalid ; pl2lapRxXIDData() ;XID data ; pl2lapRxIData() ;I data ; pl2lapRxUIData() ;UI data ; lap2plRxIgnore() ;Tell the framing layer to ignore the frame ; ; lap2plSNRMAccept() ;Accept connection and send reply ; lap2plTxXIDCmd(w=Slot) ;Send a XID command frame ; lap2plTxXIDRsp() ;Send a XID response frame ; lap2plTxSimpleRsp() ;Send simple response frame ; lap2plTxIRsp() ;Send an I frame ; pl2lapTxIData(ret w=Data ret z=Last) call ;Request for data ; pl2lapTxComplete() ;Complete indication ; ; lap2plGenerateNewAddr ;Request that a new 32-bit address be generated ; ;LMP Layer Events ; ; lap2lmpConnectIndication() call ; lap2lmpDisconnectIndication() ; lmp2lapDisconnectRequest() ; ; lap2lmpRxData(w=Data) ;Incomming data bytes ; lap2lmpRxValid() call ;Data bytes passed since RxFrame message are valid ; lap2lmpRxError() call ;Data bytes passed since RxFrame message are invalid ; ; lap2lmpTxFrame(ret z=None) call ;Lap layer can transmit a i-frame and will do so if z is returned false ; lap2lmpTxData(ret w=Data ret z=Last) call ;Payload layer can accept a data byte (for an I frame) if there is one available. if there is data available then lmp returns data byte and sets z to false ; lap2lmpTxValid() call ;Lap layer is indicating that all data passed since last TxStart message was acknowledged ; lap2lmpTxError() call ;Lap layer is indicating that all data passed since last TxStart message will need to be sent again ; ;Application Events ; ; app2lapDiscoveryRequest(ret z=Busy) ;Application wishes to initiate the XID discovery process ; app2lapTxUIStart(ret z=Busy) ;Application wishes to send a UI command frame ; ;******************************************************************************** ENDM LapDataSeg MACRO ;******************************************************************************** ; LAP LAYER ;******************************************************************************** org $70 lapBank = $70 ;8 bytes used lapState ds 1 ;Current lap state lapRxFrame ds 1 lapRxData ds 1 lapTxXIDSlot ds 1 lapStatus ds 1 ;Status bits lapRemoteBusy = lapStatus.0 ;Remote busy flag lapXIDDataFlag = lapStatus.1 ;Indication that host has been informed that XID data will follow lapRxUIDataFlag = lapStatus.2 ;Indication that app layer has been informed that UI data will follow lapTxUIDataFlag = lapStatus.3 ;Indication that app layer has been informed that UI data will follow lapLmpRxFlag = lapStatus.4 ;Indication that lmp layer has sent data that has not been acknowledged lapLmpTxFlag = lapStatus.5 ;Indication that lmp layer has sent data that has not been acknowledged lapMediaIdle = lapStatus.6 ;Indication that the media has not been used in the past 500ms (NDM state only) lapRxNs ds 1 ;%.....nnn = expected next I-frame sequence number (Ns) lapRxNrAck ds 1 ;%.....nnn = expected next I-response sequence number if last frame that was transmitted has been acknowledged lapRxNrNotAck ds 1 ;%.....nnn = expected next I-response sequence number if last frame that was transmitted has been not-acknowledged lapNDMState = 0 ;NDM state lapQUERYState = 1 ;QUERY state lapNDM2NRMState = 2 ;internal state to wait for TxComplete so new connection parameters can be applied lapNRMState = 3 ;NRM state lapSCLOSEState = 4 ;SCLOSE state lapSCLOSE2NDMState = 5 ;internal state to wait for TxComplete so default connection parameters can be applied lapMaxFrameSize = 64 ;Max frame size = 64 bytes lapMinTurnaround = 116 ;Number of additional BOFs to send @ 115200bps (116 = 10ms, 58 = 5ms) Timer140ms = -1 ;1 = 1*256*256*108*(1/50MHz) = 141.56ms Timer570ms = -4 ;4 = 4*256*256*108*(1/50MHz) = 566.23ms Timer1000ms = -7 ;7 = 7*256*256*108*(1/50MHz) = 990.90ms Timer3000ms = -21 ;21 = 21*256*256*108*(1/50MHz) = 2972.72ms ;Note - For a different clock frequency the 108 ISR constant changes => these timeout numbers remain the same ;******************************************************************************** ENDM LapCodeSeg MACRO ;******************************************************************************** ; LAP LAYER ;******************************************************************************** ;********** a2lapReset ********** a2lapReset call @lap2plGenerateNewAddr ;Generate new device address bank lapBank mov lapState, #lapNDMState ;Enter NDM state clr lapStatus ;Init status jmp lapMediaBusy ;Reset media idle detection (lapMediaBusy will issue retp instruction) ;********** a2lapTimer ********** a2lapTimer clrb TimerOverflow ;Clear Timer flag bank lapBank mov w, lapState ;jump based on state jmp PC+w jmp lapNDMTimer ; 0 = lapNDMState jmp lapQUERYTimer ; 1 = lapQUERYState retp ; 2 = lapNDM2NRMState jmp lapNRMTimer ; 3 = lapNRMState jmp lapSCLOSETimer ; 4 = lapSCLOSEState retp ; 5 = lapSCLOSE2NDMState ;********** pl2lapRxFrame ********** pl2lapRxFrame bank lapBank mov lapRxFrame, w ;Store frame type mov w, lapState ;Jump based on state jmp PC+w jmp lapNDMRxFrame ; 0 = lapNDMState jmp lapQUERYRxFrame ; 1 = lapQUERYState retp ; 2 = lapNDM2NRMState (RxFrame = impossable in this state) jmp lapNRMRxFrame ; 3 = lapNRMState jmp lapSCLOSERxFrame ; 4 = lapSCLOSEState retp ; 5 = lapSCLOSE2NDMState (RxFrame = impossable in this state) ;********** pl2lapRxValid ********** pl2lapRxValid bank lapBank mov w, lapState ;Jump based on state jmp PC+w jmp lapNDMRxValid ; 0 = lapNDMState jmp lapQUERYRxValid ; 1 = lapQUERYState retp ; 2 = lapNDM2NRMState (RxValid is impossable in this state) jmp lapNRMRxValid ; 3 = lapNRMState jmp lapSCLOSERxValid ; 4 = lapSCLOSEState retp ; 5 = lapSCLOSE2NDMState (RxValid is impossable in this state) ;********** pl2lapRxValid - NRM State ********** lapNRMRxValid mov w, lapRxFrame ;Jump based on frame type jmp PC+w jmp lapNRMXCmdValid ;xFrame = 0 jmp lapNRMIValid ;iFrame = 1 jmp lapNRMRRValid ;sRRFrame = 2 jmp lapNRMRNRValid ;sRNRFrame = 3 jmp lapNRMREJValid ;sREJFrame = 4 jmp lapNRMSREJValid ;sSREJFrame = 5 jmp lapNRMXCmdValid ;uUIFrame = 6 ;UICmd or UIRsp (same command) jmp lapNRMDISCValid ;uDISCFrame = 7 ;DISCCmd or RDRsp (same command) jmp lapNRMXCmdValid ;uUARspFrame = 8 ;UARsp jmp lapNRMNRMValid ;uNRMFrame = 9 ;SNRMCmd or RNRMRsp (same command) jmp lapNRMXCmdValid ;uTESTFrame = 10 ;TESTCmd or TESTRsp (same command) jmp lapNRMXCmdValid ;uFRMRRspFrame = 11 ;FRMRRsp jmp lapNRMXCmdValid ;uDMRspFrame = 12 ;DMRsp jmp lapNRMXCmdValid ;uXIDCmdFrame = 13 ;XIDCmd jmp lapNRMXCmdValid ;uXIDRspFrame = 14 ;XIDRsp ;********** pl2lapTxValid ********** pl2lapTxComplete bank lapBank mov w, lapState ;Jump based on state jmp PC+w jmp lapNDMTxComplete ; 0 = lapNDMState (not interesting in TxComplete) retp ; 1 = lapQUERYState (not interesting in TxComplete) jmp lapNDM2NRMTxComplete ; 2 = lapNDM2NRMState (now can apply connection parameters) retp ; 3 = lapNRMState (not interesting in TxComplete) retp ; 4 = lapSCLOSEState (not interesting in TxComplete) jmp lapSCLOSE2NDMTxComplete ; 5 = lapSCLOSE2NDMState (now can apply defaultconnection parameters) ;********** fl2lapMediaBusy ********** fl2lapMediaBusy bank lapBank cse lapState, #lapNDMState ;NDM state ? retp ;No => ignore clrb lapMediaIdle ;Clear MediaIdle flag test lapRxFrame ;Is a frame being received ? sz retp ;Yes => do not reset timer mov w, #Timer570ms ;No => Reset timer to 500ms jmp lapSetTimer ;Apply timer to wait for media idle ;********** DiscoveryRequest ********** app2lapDiscoveryRequest bank lapBank cse lapState, #lapNDMState ;NDM state ? clrb lapMediaIdle ;No => same as MediaIdle being false stz ;Indicate busy sb lapMediaIdle ;Is the media idle ? retp ;No => return busy indication bank plBank mov plConnAddr, #$FE ;Accept broadcast replys only bank lapBank clr lapTxXIDSlot ;Start at slot # 0 mov lapState, #lapQUERYState ;Enter QUERY state call :Send ;Send first frame clz ;Indicate request was accepted retp :Send jmp lapQUERYTimer ;********** DiscoveryRequest ********** app2lapTxUIStart bank lapBank cse lapState, #lapNDMState ;NDM state ? clrb lapMediaIdle ;No => same as MediaIdle being false stz ;Indicate busy sb lapMediaIdle ;Is the media idle ? retp ;No => return busy indication clrb lapMediaIdle ;Remember that another frame cannot be sent setb lapRxUIDataFlag ;Flag to pass messages to app layer call @lap2plTxUICmd ;Request that the payload layer send a UI command frame clz ;Indicate request was accepted retp ;******************************************************************************** ; LAP LAYER - Internal Subroutines ;******************************************************************************** lapRandomFlags = Temp+0 lapRandomMask = Temp+1 ;Slot bits: %00 => 1 slot => Mask = %0000 = 0 -> 0 ; %01 => 6 slots => Mask = %0011 = 0 -> 3 (ie can't result in 4 or 5) ; %10 => 8 slots => Mask = %0111 = 0 -> 7 ; %11 => 16 slots => Mask = %1111 = 0 -> 15 lapRandomSlot ;returns Slot number to transmit in bank plBank ;Peek at frame info mov w, plXIDFlags ;get discovery flags bank lapBank and w, #%00000011 ;Mask out non Slot bits snz ;Slot bits = 0 ? retp ;Yes => return 0 mov lapRandomFlags, w ;Store into Flags register mov w, #%00000001 ;If bit 1 = 0 then w = 0001 snb lapRandomFlags.1 mov w, #%00000111 ;If bit 1 = 1 then w = 0111 mov lapRandomMask, w ;Mask = 0001 or 0111 stc snb lapRandomFlags.0 ;If bit 0 = 1 then rotate left with carry set rl lapRandomMask ;Rotate mask with carry set bank TimerBank mov w, Random ;random number (non resetable, increments every timer interrupt) bank lapBank ;Note: The code is synchronous with RTCC and so RTCC is not a random number and w, lapRandomMask ;Mask out unwanted bits mov lapTxXIDSlot, w ;Store slot number retp ;********** SetTimer ********** lapSetTimer ;w = negative number to count up from bank TimerBank ;-1 = 141.56ms clr Timer1 clr Timer2 mov Timer3, w clrb TimerOverflow bank lapBank retp ;********** fl2lapMediaBusy ********** lapMediaBusy clr lapRxFrame ;Reset frame type to none mov w, #Timer570ms ;No => Reset timer to 500ms jmp lapSetTimer ;Apply timer to wait for media idle ;******************************************************************************** ; LAP LAYER ;******************************************************************************** ;********** pl2lapRxError ********** pl2lapRxError bank lapBank call lapMediaBusy ;Reset media idle detection snb laplmpRxFlag ;Has the lmp layer been receiving data ? jmp :LMP ;Yes => must inform lmp layer snb lapXIDDataFlag ;Has the host been informed to expect XID data ? jmp :XID ;Yes => inform of error sb lapRxUIDataFlag ;Is the app layer expecting data retp ;No => return :UI clrb lapRxUIDataFlag ;Yes => Inform app layer that UI frame is invalid jmp @lap2appRxUIError :LMP clrb laplmpRxFlag ;Clear flag jmp @lap2lmpRxError ;Inform lmp layer of error (lmp layer will issue ret instruction) :XID clrb lapXIDDataFlag ;Clear flag debugl ShowXIDInfo, '}' ;Inform host of error retp ;********** pl2lapRxXIDData ********** pl2lapRxXIDData bank lapBank sb lapXIDDataFlag ;Is the host expecting XID Data ? retp ;No => ignore data debug ShowXIDInfo ;Yes => pass data retp ;********** pl2lapRxIData ********** pl2lapRxIData bank lapBank sb laplmpRxFlag ;Should we pass data ? retp ;No => ignore data jmp @lap2lmpRxData ;Yes => pass data ;********** pl2lapTxIData ********** pl2lapTxIData jmp @lap2lmpTxData ;Get data from lmp layer ;********** pl2lapRxUIData ********** pl2lapRxUIData bank lapBank sb lapRxUIDataFlag ;Should we pass data ? retp ;No => ignore data jmp @lap2appRxUIData ;Yes => pass data ;********** pl2lapTxUIData ********** pl2lapTxUIData jmp @lap2appTxUIData ;Get data from app layer ;******************************************************************************** ; LAP LAYER - NDM Events ;******************************************************************************** lapEnterNDMState ;Reset connection parameters mov lapState, #lapNDMState ;Enter NDM state call lapMediaBusy ;Reset media idle detection :Tx sb laplmpTxFlag ;Is the lmp data waiting for comformation of data ? jmp :Rx ;No => contiue without message to lmp layer clrb laplmpTxFlag ;Yes => inform lap layer that data was not-acknowledged and contiue call @lap2lmpTxError bank lapBank :Rx sb lapLmpRxFlag ;Is the lmp layer expecting data ? jmp :Cont ;No => contiue without message to lmp layer clrb lapLmpRxFlag ;Yes => must inform lmp layer that data is invalid call @lap2lmpRxError :Cont bank plBank mov plConnAddr, #$FF ;Not connected => set ConnAddr to only accept be $FF bank flBank mov flFFCount, #10 ;Default to 10 FFs @ 9600 = 10.42ms bank IsrBank mov IrdaSpeed, #Irda9600 ;IrDA UART speed = 9600 clrb ledCON ;Turn off Connect LED debugl ShowConnect, ']' jmp @lap2lmpDisconnectIndication ;Inform lmp layer of disconnection ;********** NDM - RxFrame ********** lapNDMRxFrame csne lapRxFrame, #uXIDCmdFrame ;XID Command frame ? jmp :Accept ;Yes => Accept frame (may want to code to inform host of incommming XIDCmd frame ?) csne lapRxFrame, #uNRMFrame ;SNRM Command frame ? jmp :Accept ;Yes => Accept frame csne lapRxFrame, #uUIFrame ;UI frame ? jmp :UI ;Yes => Accept frame clr lapRxFrame ;No => Ignore frame jmp @lap2plRxIgnore ;Request that the payload layer ignores the frame :UI setb lapRxUIDataFlag ;Flag to pass data to app layer :Accept mov w, #Timer570ms ;500ms Timeout jmp lapSetTimer ;(lapSetTimer will issue retp instruction) ;********** NDM - Timer ********** lapNDMTimer test lapRxFrame ;Was a frame being received ? jnz pl2lapRxError ;Yes => treat as error, pl2lapRxError will reset the MediaBusy detection setb lapMediaIdle ;No => media must be idle retp ;********** NDM - RxValid ********** lapNDMRxValid csne lapRxFrame, #uXIDCmdFrame ;XID Command frame ? jmp :XID ;Yes => process csne lapRxFrame, #uNRMFrame ;SNRM Command frame ? jmp :SNRM ;Yes => process ;No => must be UI frame :UI call lapMediaBusy ;Reset media idle detection sb lapRxUIDataFlag ;Is the app layer expecting data retp ;No => ignore clrb lapRxUIDataFlag ;Yes => Inform app layer that UI frame is complete jmp @lap2appRxUIValid :XID call lapMediaBusy ;Reset media idle detection bank plBank ;Peek at frame info snb plXIDFlags.2 ;Is the "Generate new device address" flag set ? call @lap2plGenerateNewAddr ;Yes => ask payload layer to generate a new 32-bit address bank plBank ;Peek at frame info test plXIDSlot ;is the slot number = 0 ? bank lapBank snz call lapRandomSlot ;Yes => generate random slot (slot returned in lapTxXIDSlot) mov w, lapTxXIDSlot ;Get the slot number to transmit in bank plBank mov w, plXIDSlot-w ;Subtract (ie compare) with current slot number sz ;Are they the same ? (ie this slot to transmit in ?) retp ;No => return bank lapBank mov w, lapTxXIDSlot clr lapTxXIDSlot ;Reset slot number to indicate that a reply has been sent jmp @lap2plTxXIDRsp ;Transmit response :SNRM mov lapState, #lapNDM2NRMState ;Next state wil be NDM2NRM state to apply connection parameters after this reply has been sent clrb lapRemoteBusy ;Initilise RemoteBusy flag to false clr lapRxNs ;Initilise RxNs to 0 clr lapRxNrAck ;Initilise RxNrAck to zero clr lapRxNrNotAck ;Initilise RxNrNotAck to zero mov w, #Timer1000ms ;1s timeout IrDA Lite p15) call lapSetTimer setb ledCON ;Turn on Connect LED debugl ShowConnect, '[' call @lap2lmpConnectIndication ;Inform lmp layer of connection jmp @lap2plSNRMAccept ;Send reply ;********** NDM - TxComplete ********** lapNDMTxComplete call lapMediaBusy ;Reset media idle test sb lapRxUIDataFlag ;Is the app layer expecting data retp ;No => ignore clrb lapRxUIDataFlag ;Yes => Inform app layer that UI frame is complete jmp @lap2appTxUIComplete ;******************************************************************************** ; LAP LAYER - QUERY Events ;******************************************************************************** ;********** QUERY - RxFrame ********** lapQUERYRxFrame cse lapRxFrame, #uXIDRspFrame ;XID Response frame ? jmp @lap2plRxIgnore ;No => Ignore frame setb lapXIDDataFlag ;Yes => Accept frame. Remember that currently passing data to host debugl ShowXIDInfo, '{' ;Show XID info start retp ;********** QUERY - RxValid ********** lapQUERYRxValid sb lapXIDDataFlag ;Is the host expecting data retp ;No => ignore clrb lapXIDDataFlag ;Yes => Inform host that XID frame is complete debugl ShowXIDInfo, '}' retp ;********** QUERY - Timer ********** lapQUERYTimer bank TimerBank ;Set global timer clr Timer1 ;80ms timeout after transmission is complete (75-85ms IrDA Lite p21) mov Timer2, #-198 ;80ms timeout + 29.2 ms (28 bytes) to transmit = 109.2ms. 198 : 198*256*108*(1/50MHz) = 109.49ms mov Timer3, #-1 ;negitive number clrb TimerOverflow bank lapBank sb lapXIDDataFlag ;Has the host been informed to expect XID data ? jmp :Good ;Yes => inform of error clrb lapXIDDataFlag ;Clear flag debugl ShowXIDInfo, '}' ;Inform host of error :Good cse lapTxXIDSlot, #08 ;Last slot ? jmp :Send ;No => send mov lapState, #lapNDMState ;Yes => After send will return to NDM state mov w, #$FF ;w = FF mov lapTxXIDSlot, w ;set slot to $FF to indicate complete bank plBank mov plConnAddr, w ;ConnAddr = FF => Accept broadcast commands only bank lapBank :Send mov w, lapTxXIDSlot ;Get current slot # inc lapTxXIDSlot ;Increment for nexty slot # jmp @lap2plTxXIDCmd ;Send XID command frame (payload layer will return) ;******************************************************************************** ; LAP LAYER - NRM Events ;******************************************************************************** ;********** NDM2NRM - TxComplete ********** lapNDM2NRMTxComplete mov lapState, #lapNRMState ;NRM state bank plBank ;Agreed BaudRate is the most significant bit that is set in plSNRMBaudRate mov w, #Irda9600 ;Min = 9600 snb plSNRMBaudRate.2 ;19200 ? mov w, #Irda19200 ;Yes => w = 19200 snb plSNRMBaudRate.3 ;38400 ? mov w, #Irda38400 ;Yes => w = 38400 snb plSNRMBaudRate.4 ;57600 ? mov w, #Irda57600 ;Yes => w = 57600 snb plSNRMBaudRate.5 ;115200 ? mov w, #Irda115200 ;Yes => w = 115200 bank IsrBank mov IrdaSpeed, w ;Apply baud rate bank plBank ;Set FF Count to ensure 10ms. FFCount = BaudRate / 10 * 0.01s mov w, #lapMinTurnaround / 11.6 ;Min = 9600 => 10ms = 10 bytes snb plSNRMBaudRate.2 ;19200 ? mov w, #lapMinTurnaround / 5.8 ;Yes => 10ms = 20 bytes snb plSNRMBaudRate.3 ;38400 ? mov w, #lapMinTurnaround / 2.9 ;Yes => 10ms = 39 bytes snb plSNRMBaudRate.4 ;57600 ? mov w, #lapMinTurnaround / 2 ;Yes => 10ms = 58 bytes snb plSNRMBaudRate.5 ;115200 ? mov w, #lapMinTurnaround ;Yes => 10ms = 116 bytes bank flBank mov flFFCount, w ;Apply FFCount retp ;********** NRM - SendResponse ********** lapSendNRMResponse snb lapRemoteBusy ;Is the remote busy flag set ? jmp lapSendSResponse ;Yes => send S-Response call @lap2lmpTxFrame ;Returns z = false if data to be sent bank lapBank snz ;Is there data to be sent ? jmp lapSendSResponse ;No => send S-Response :Data setb laplmpTxFlag ;Yes => Rember that lmp layer is passing data mov w, <<lapRxNs ;Send Nr = RxNs. w = RxNs %....nnn. and w, #%00001110 ;mask out non Ns bits mov Temp, w ;Store in Temp swap Temp ;Temp = RxNs %nnn..... setb Temp.4 ;Set bit 4 = final flag mov w, <<lapRxNrAck ;Send Ns = RxNrAck. w = RxNrAck %....nnn. and w, #%00001110 ;mask out non Ns bits add w, Temp ;Add Nr bits inc lapRxNrAck ;add 1 to NrAck - the expect acknowledge jmp @lap2plTxIRsp ;Transmit I frame lapSendSResponse mov w, <<lapRxNs ;Send Nr = RxNs. w = RxNs %....nnn. and w, #%00001110 ;mask out non Ns bits mov Temp, w ;Store in Temp swap Temp ;Temp = RxNs %nnn..... mov w, #sRR ;frame will be of type RR add w, Temp ;Set Nr of frame to RxNs = expected next I frame jmp @lap2plTxSimpleRsp ;Send simple response frame ;********** NRM - SendRD ********** lapNRMSendRD mov w, #Timer3000ms call lapSetTimer ;Reset timer for SCLOSE state sb lapLmpRxFlag ;Is the lmp layer expecting data ? (ie error caused by timeout) jmp :Cont ;No => contiue clrb lapLmpRxFlag ;Yes => must inform lmp layer that data is invalid call @lap2lmpRxError ; bank lapBank :Cont mov lapState, #lapSCLOSEState ;change to SCLOSE state mov w, #uRDRsp ;frame will be of type RD jmp @lap2plTxSimpleRsp ;Send simple response frame ;********** NRM - RxFrame ********** lapNRMRxFrame csne lapRxFrame, #iFrame ;I Data frame ? setb lapLmpRxFlag ;Yes => Flag to pass data to lmp layer retp ;Accept all frames ;********** NRM - SValid or IValid ********** lapNRMSIValid mov w, #Timer3000ms call lapSetTimer ;Reset timer on any S-Command bank plBank mov w, >>plCommand ;w = %.nnn.... get the received command byte (shifted) mov Temp, w ;Temp = received Nr bits (%.nnn....) swap Temp ;Temp = received Nr bits (%.....nnn) bank lapBank mov w, lapRxNrAck ;w = expected Nr if Ack xor w, Temp ;compare received Nr with NrAck and w, #%00000111 ;only examine lowest bits snz ;Does Nr = NrAck (ie is this a valid ack) ? jmp :Ack ;Yes => valid Ack mov w, lapRxNrNotAck ;w = expected Nr if Not-Ack xor w, Temp ;compare received Nr with NrNotAck and w, #%00000111 ;only examine lostest bits sz ;Does Nr = NrNotAck (ie is this a valid not-ack) ? jmp lapNRMSendRD ;No => Fatal Error - invalid Nr => must disconnect (Valid/Error message for LMP layer willbe sent prior to the DisconnectIndication) :NotAck dec lapRxNrAck ;return NrAck back to what it was before transmission of the last I-Frame sb laplmpTxFlag ;Is the lmp data waiting for comformation of data ? jmp :Cont ;No => contiue without message to lmp layer clrb laplmpTxFlag ;Yes => inform lap layer that data was not-acknowledged and contiue call @lap2lmpTxError jmp :Cont :Ack mov lapRxNrNotAck, lapRxNrAck ;Set NrNotAck to match NrAck sb laplmpTxFlag ;Is the lmp data waiting for comformation of data ? jmp :Cont ;No => contiue without message to lmp layer clrb laplmpTxFlag ;Yes => inform lap layer that data was acknowledged and contiue call @lap2lmpTxValid :Cont bank lapBank cse lapRxFrame, #iFrame ;Is this an i frame ? jmp lapSendNRMResponse ;No => S frame => Send-NRM-Response bank plBank ;Yes => must test Ns mov w, >>plCommand ;get the received command byte (shifted right 1 bit) bank lapBank xor w, lapRxNs ;Compare with expected Ns and w, #%00000111 ;Only test lowest 3 bits jnz :Ignore ;If Ns <> expected then ignore :Valid inc lapRxNs ;increment RxNs sb lapLmpRxFlag ;Is the lmp layer expecting data ? jmp lapSendNRMResponse ;No => send NRM-response clrb lapLmpRxFlag ;Yes => must inform lmp layer that data is complete call @lap2lmpRxValid ;Indicate data complete and valid bank lapBank jmp lapSendNRMResponse ;send NRM-response :Ignore sb lapLmpRxFlag ;Is the lmp layer expecting data ? jmp lapSendSResponse ;No => send S-response clrb lapLmpRxFlag ;Yes => must inform lmp layer that data is invalid call @lap2lmpRxError ; bank lapBank jmp lapSendSResponse ;send S-response lapNRMIValid = lapNRMSIValid ;A I frame has been received lapNRMRRValid ;A RR frame has been received clrb lapRemoteBusy ;Remember that remote is not busy and send reply jmp lapNRMSIValid lapNRMRNRValid ;A RNR frame has been received setb lapRemoteBusy ;Remember that remote is busy and send reply jmp lapNRMSIValid lapNRMREJValid = lapNRMSIValid ;A REJ frame has been received lapNRMSREJValid = lapNRMSIValid ;A SREJ frame has been received ;********** NRM - SNRMCmdValid ********** lapNRMNRMValid = lapNRMSendRD ;********** NRM - XCmdValid ********** lapNRMXCmdValid = lapSendSResponse ;********** NRM - DISCCmdValid ********** lapNRMDISCValid ;Disconnect command: ack and apply default parameters. mov lapState, #lapSCLOSE2NDMState ;Next state = transition to apply origional connection parameters once this frame has been sent mov w, #uUARsp ;Send UA frame to acknowledge disconnect jmp @lap2plTxSimpleRsp ;Send simple response frame ;********** NRM - Timer ********** lapNRMTimer = lapEnterNDMState ;Timeout => return to NDM state. ;********** lmp2lapDisconnectRequestr ********** lmp2lapDisconnectRequest bank lapBank cse lapState, #lapNRMState ;Currenly in NRM state ? retp ;No => ignore request mov lapState, #lapSCLOSEState ;Yes => change to SCLOSE state retp ;******************************************************************************** ; LAP LAYER - NRM Events ;******************************************************************************** ;********** SCLOSE - RxFrame ********** lapSCLOSERxFrame retp ;Accept all frames ;********** SCLOSE - RxValid ********** lapSCLOSERxValid csne lapRxFrame, #uDISCFrame ;DISC Command frame ? jmp lapNRMDISCValid ;Yes => Send ack, apply default parameters and enter NDM state mov w, #Timer3000ms call lapSetTimer ;No, however still must be a command frame (due to ConnAddr) => send RD frame mov w, #uRDRsp ;Send RD Response frame to request disconnect jmp @lap2plTxSimpleRsp ;Send simple response frame ;********** SCLOSE - Timer ********** lapSCLOSETimer = lapEnterNDMState ;********** SCLOSE2NDM - TxComplete ********** lapSCLOSE2NDMTxComplete = lapEnterNDMState ;******************************************************************************** ENDM LmpInfoSeg MACRO ;******************************************************************************** ; LMP LAYER ;******************************************************************************** ; ; lap2lmpConnectIndication() call ; lap2lmpDisconnectIndication() ; ; lap2lmpRxData(w=Data) ;Incomming data bytes ; lap2lmpRxValid() call ;Data bytes passed since RxFrame message are valid ; lap2lmpRxError() call ;Data bytes passed since RxFrame message are invalid ; ; lap2lmpTxFrame(ret z=None) call ; lap2lmpTxData(ret w=Data ret z=Last) call ;Payload layer can accept a data byte (for an I frame) if there is one available. if there is data available then lmp returns data byte and sets z to false ; lap2lmpTxValid() call ;Lap layer is indicating that all data passed since last TxStart message was acknowledged ; lap2lmpTxError() call ;Lap layer is indicating that all data passed since last TxStart message will need to be sent again ; ;******************************************************************************** ENDM LmpDataSeg MACRO ;******************************************************************************** ; LMP LAYER ;******************************************************************************** org $90 lmpBank = $90 ;16 bytes lmpPosition ds 1 ;Position of multi byte stages lmpData ds 1 ;Temporary Data storage lmpAppLSAP ds 1 ;LSAP number of remote CommApp (or 0 if not connected) lmpAppStatus ds 1 lmpRxState ds 1 ;Current Rx state lmpRxDLSAP ds 1 ;Received DLSAP lmpRxSLSAP ds 1 ;Received SLSAP lmpRxInfo ds 4 lmpRxLMPCmdOpcode = lmpRxInfo + 0 ;LMP Command frames : holds opcode lmpRxIASErrOpcode = lmpRxInfo + 0 ;IAS frame : holds service request lmpRxIASErrRetCode = lmpRxInfo + 1 ;IAS frame : holds return code for service request lmpRxSendStringL = lmpRxInfo + 2 ;SendStringH = _lmpTxStringSegment lmpRxPostTest = lmpRxInfo + 3 lmpTxState ds 1 ;Current Tx state lmpTxDLSAP ds 1 ;Transmit DLSAP = Received SLSAP lmpTxSLSAP ds 1 ;Transmit SLSAP = Received DLSAP lmpTxInfo ds 2 lmpTxIASErrOpcode = lmpTxInfo + 0 ;IAS frame : holds service request lmpTxIASErrRetCode = lmpTxInfo + 1 ;IAS frame : holds return code for service request lmpTxStringH = lmpTxInfo + 0 lmpTxStringL = lmpTxInfo + 1 lmpConnectCmdOpcode = $01 lmpConnectRspOpcode = $81 lmpDisconnectOpcode = $02 lmpAccessCmdOpcode = $03 lmpAccessRspOpcode = $83 lmpLSAPServer = 0 lmpLSAPComm = 5 ;Random number between 1 and 6F lmpAppRxFlag = lmpAppStatus.0 ;Indicates that app layer has been passed unacknoldged data lmpAppTxFlag = lmpAppStatus.1 ;Indicates that app layer is passing data or has passed data that has not yet been acknoldged lmpRxDataMode = %00000000 ;More data is required lmpRxVerifyMode = %10000000 ;Waiting for frame to complete lmpRxSLSAPState = 1 + lmpRxDataMode ;Second byte = Source LSAP lmpRxLMPCmdOpcodeState = 2 + lmpRxDataMode ;LMP Command : Opcode lmpRxIASCmdState = 3 + lmpRxDataMode ;IAS Data : lmpRxIASClassLengthState = 4 + lmpRxDataMode ;IAS Data : lmpRxIASClassTestState = 5 + lmpRxDataMode ;IAS Data : lmpRxIASDeviceAttribState = 6 + lmpRxDataMode ;IAS Data : lmpRxIASCommAttribState = 7 + lmpRxDataMode ;IAS Data : lmpRxIASAttribTestState = 8 + lmpRxDataMode ;IAS Data : lmpRxCommDataState = 9 + lmpRxDataMode ;Comm Data lmpRxBadLSAPState = 1 + lmpRxVerifyMode ;Error state : Invalid Dest LSAP lmpRxLMPCmdVerifyState = 2 + lmpRxVerifyMode ;LMP Command : Verify lmpRxIASAttribVerifyState = 3 + lmpRxVerifyMode ;IAS Data : lmpRxIASErrorState = 4 + lmpRxVerifyMode ;IAS Data : lmpTxStringState = 1 ;Send a string lmpTxIASErrorState = 2 ;Reply stating that the IAS service is an un-supported option or error lmpTxCommDataState = 3 ;Sending Comm Data ;******************************************************************************** ENDM LmpCodeSeg MACRO ;******************************************************************************** ; LMP LAYER ;******************************************************************************** ;********** a2lmpReset ********** a2lmpReset bank lmpBank clr lmpRxState clr lmpTxState clr lmpAppLSAP retp ;********** lap2lmpConnectIndication ********** lap2lmpConnectIndication = a2lmpReset ;********** lap2lmpDisconnectIndication ********** lap2lmpDisconnectIndication = a2lmpReset ;********** lap2lmpRxData ********** lap2lmpRxData bank lmpBank mov lmpData, w ;Store data snb lmpRxState.7 ;Interested in data ? (lmpRxDataMode) retp mov w, lmpRxState ;Jump based on state jmp PC+w jmp lmpRxDLSAPByte ; 0 = lmpIdleState jmp lmpRxSLSAPByte ; 1 = lmpRxSLSAPState jmp lmpRxCmdOpcodeByte ; 2 = lmpRxLMPCmdOpcodeState jmp lmpRxIASCmd ; 3 = lmpRxIASCmdState jmp lmpRxIASClassLength ; 4 = lmpRxIASClassLengthState jmp lmpRxIASStringTest ; 5 = lmpRxIASClassTestState jmp lmpRxIASDeviceAttrib ; 6 = lmpRxIASDeviceAttribState jmp lmpRxIASCommAttrib ; 7 = lmpRxIASCommAttribState jmp lmpRxIASStringTest ; 8 = lmpRxIASAttribTestState jmp lmpRxCommData ; 9 = lmpRxCommDataState ;********** lap2lmpRxValid ********** lap2lmpRxValid debugl IFrameDataRx, '^' bank lmpBank snb lmpAppRxFlag ;CommData ? jmp lmpRxValidCommData ;Yes => process sb lmpRxState.7 ;Interested in valid ? (lmpRxVerifyMode) retp mov w, lmpRxState ;Jump based on state and w, #%01111111 ;Remove Mode bit clr lmpRxState ;Clear RxState back to idle jmp PC+w retp ; 0 = lmpIdleState (invalid) jmp lmpRxBadLSAP ; 1 = lmpRxBadLSAPState jmp lmpRxValidLMPCommand ; 2 = lmpRxLMPCmdVerifyState jmp lmpRxValidIASAttribVerify ; 3 = lmpRxIASAttribVerifyState jmp lmpRxValidIASError ; 4 = lmpRxIASErrorState ;********** lap2lmpRxInvalid ********** lap2lmpRxError debugl IFrameDataRx, '!' setb ledERR ;Turn ERR led on bank lmpBank clr lmpRxState ;Return to idle state sb lmpAppRxFlag ;CommDataMode ? retp ;No => return clrb lmpAppRxFlag ;Clear flag jmp @lmp2appRxCommError ;Yes => Inform app layer of valid (app layer will issue ret instruction) ;********** lap2lmpTxData ********** lap2lmpTxFrame bank lmpBank clr lmpPosition test lmpTxState ;Idle state ? jnz :Send :Idle test lmpAppLSAP ;LMP Connection open to comm layer ? snz ;Zero indicates no connection retp ;No => indicate no data and return call @lmp2appTxCommStart ;Yes => find out if data to send snz ;Data to send retp ;No => indicate no data and return bank lmpBank mov lmpTxState, #lmpTxCommDataState ;Prepare to transmit frame mov lmpTxDLSAP, lmpAppLSAP ;Ensure correct DLSAP mov lmpTxSLSAP, #lmpLSAPComm ;Ensure correct SLSAP mov lmpPosition, #lapMaxFrameSize-2 ;Protect frame size (LAP frame size less DLSAP and SLSAP bytes) :Send mov w, lmpTxDLSAP ;Desired DLSAP bank plBank mov plIDataDLSAP, w ;Store for transmission bank lmpBank mov w, lmpTxSLSAP ;Desired SLSAP bank plBank mov plIDataSLSAP, w ;Store for transmission clz ;Indicate more data to follow retp ;********** lap2lmpTxData ********** lap2lmpTxData ;Lap layer can accept a data byte (for an I frame) if there is one available. if there is data available then lmp returns data byte and sets z to false bank lmpBank mov w, lmpTxState ;Jump based on state jmp PC+w ;Jump based on state retp ; 0 = Idle state (cannot receive TxData in idle state) jmp lmpTxString ; 1 = lmpTxStringState jmp lmpTxIASError ; 2 = lmpTxIASErrorState jmp lmpTxCommData ; 3 = lmpTxCommDataState ;********** lap2lmpTxValid ********** lap2lmpTxValid ;Lap layer is indicating that all data passed since last TxStart message was acknowledged debugl IFrameDataTx, '^' bank lmpBank clr lmpTxState ;Return to idle state sb lmpAppTxFlag ;Transmitting app data ? retp ;No => return clrb lmpAppTxFlag jmp @lmp2appTxCommValid ;Yes => Inform app layer of valid (app layer will issue ret instruction) ;********** lap2lmpTxError ********** lap2lmpTxError ;Lap layer is indicating that all data passed since last TxStart message will need to be sent again debugl IFrameDataTx, '!' setb ledERR ;Turn ERR led on bank lmpBank sb lmpAppTxFlag ;Transmitting app data ? retp ;No => return (stay in this state for retransmission) clrb lmpAppTxFlag jmp @lmp2appTxCommError ;Yes => Inform app layer of error (app layer will issue ret instruction) ;******************************************************************************** ; LMP LAYER - Rx ;******************************************************************************** lmpRx2TxSetup mov lmpTxDLSAP, lmpRxSLSAP ;DLSAP = received SLSAP mov lmpTxSLSAP, lmpRxDLSAP ;SLSAP = received DLSAP retp ;******************************************************************************** ;********** lap2lmpRxData - RxDLSAPState ********** lmpRxDLSAPByte mov lmpRxDLSAP, lmpData ;Store data inc lmpRxState ;Next state = lmpRxSLSAPState retp ;********** lap2lmpRxData - RxSLSAPState ********** lmpRxSLSAPByte mov lmpRxSLSAP, lmpData ;Store data clrb lmpRxSLSAP.7 ;Ensure MSB is clear snb lmpRxDLSAP.7 ;Is this a LMP-Command frame (DLSAP bit 7 set) ? jmp :Cmd ;Yes => process command csne lmpRxDLSAP, #lmpLSAPComm ;DLSAP addressing Comm ? jmp :Comm ;Yes => accept mov w, lmpRxBadLSAPState ;If not server then Bad LSAP test lmpRxDLSAP ;0 = IAS Server snz ;Addressing IAS Server ? mov w, #lmpRxIASCmdState ;Yes => IAS Server state mov lmpRxState, w ;Apply state retp :Cmd mov lmpRxState, #lmpRxLMPCmdOpcodeState ;No => change to RxCmdOpcodeState clrb lmpRxDLSAP.7 ;Ensure MSB is clear retp :Comm mov w, #lmpRxCommDataState ;Comm data test lmpAppLSAP ;Connected ? snz mov w, lmpRxBadLSAPState ;No => error mov lmpRxState, w ;Apply state retp ;********** lap2lmpRxData - RxCmdOpcodeState ********** lmpRxCmdOpcodeByte mov lmpRxLMPCmdOpcode, lmpData ;Store data in opcode variable mov lmpRxState, #lmpRxLMPCmdVerifyState ;Wait for Valid message retp ;********** lap2lmpRxData - RxIASCmdState ********** lmpRxIASCmd mov w, lmpData ;IAS Service request and w, #%10111111 ;Mask out ack bit mov lmpRxIASErrOpcode, w ;Store Service Request in case of error xor w, #$84 ;Is the service request GetValueByClass ? jnz :Err ;No => must reply with service unsupported inc lmpRxState ;Yes => wait for class name length retp :Err mov lmpRxState, #lmpRxIASErrorState ;Will reply with Unsupported mov lmpRxIASErrRetCode, #$FF ;Reply = $FF = unsupported service retp ;********** lap2lmpRxData - RxIASClassLengthState ********** lmpRxIASClassLength ;Data = lnegth of class name inc lmpRxState ;Next state = lmpRxIASClassTestState mov lmpRxIASErrRetCode, #$01 ;If error then Reply = $01 = no such class csne lmpData, #$06 ;Is the class name length 6 indicating that we should test for "Device" ? jmp :Dev ;Yes => test for "Device" csne lmpData, #$0B ;Is the class name length 11 indicating that we should test for "IrDA:IrCOMM" ? jmp :Comm ;Yes => test for "IrDA:IrCOMM" mov lmpRxState, #lmpRxIASErrorState ;No => Will reply with IAS error retp :Dev mov lmpRxPostTest, #lmpRxIASDeviceAttribState ;If class is correct then will cahnge to DeviceAttrib state mov lmpPosition, #_lmpIASDeviceClass ;Pointer to string retp :Comm mov lmpRxPostTest, #lmpRxIASCommAttribState ;If class is correct then will cahnge to CommAttrib state mov lmpPosition, #_lmpIASCommClass ;Pointer to string retp ;********** lap2lmpRxData - RxIASDeviceAttribState ********** lmpRxIASDeviceAttrib mov lmpRxState, #lmpRxIASAttribTestState ;Next will verify attrib string mov lmpRxPostTest, #lmpRxIASAttribVerifyState ;If attrib is correct then will cahnge to AttribVerify state mov lmpRxIASErrRetCode, #$02 ;If error then Reply = $02 = no such attribute csne lmpData, #$0A ;Is the class name length 10 indicating that we should test for "DeviceName" ? jmp :Name ;Yes => test for "Device" csne lmpData, #12 ;Is the class name length 12 indicating that we should test for "IrLMPSupport" ? jmp :Supp ;Yes => test for "IrLMPSupport" mov lmpRxState, #lmpRxIASErrorState ;No => Will reply with IAS error retp :Name mov lmpRxSendStringL, #_lmpIASDeviceName ;Pointer to string to send in reply if attrib verifies mov lmpPosition, #_lmpIASDeviceAttribName ;Pointer to string to test retp :Supp mov lmpRxSendStringL, #_lmpIASDeviceSupport ;Pointer to string to send in reply if attrib verifies mov lmpPosition, #_lmpIASDeviceAttribSupport ;Pointer to string to test retp ;********** lap2lmpRxData - RxIASCommAttribState ********** lmpRxIASCommAttrib mov lmpRxState, #lmpRxIASAttribTestState ;Next will verify attrib string mov lmpRxPostTest, #lmpRxIASAttribVerifyState ;If attrib is correct then will cahnge to AttribVerify state mov lmpRxIASErrRetCode, #$02 ;If error then Reply = $02 = no such attribute csne lmpData, #$0A ;Is the class name length 10 indicating that we should test for "Parameters" ? jmp :Param ;Yes => test for "Parameters" csne lmpData, #$12 ;Is the class name length 18 indicating that we should test for "IrDA:IrLMP:LsapSel" ? jmp :Lsap ;Yes => test for "IrDA:IrLMP:LsapSel" mov lmpRxState, #lmpRxIASErrorState ;No => Will reply with IAS error retp :Param mov lmpRxSendStringL, #_lmpIASCommParam ;Pointer to string to send in reply if attrib verifies mov lmpPosition, #_lmpIASCommAttribParam ;Pointer to string to test retp :Lsap mov lmpRxSendStringL, #_lmpIASCommLsapSel ;Pointer to string to send in reply if attrib verifies mov lmpPosition, #_lmpIASCommAttribLsapSel ;Pointer to string to test retp ;********** lap2lmpRxData - RxIASStringTestState ********** lmpRxIASStringTest mov m, #_lmpRxStringSegment / 256 ;String Segment (high) mov w, lmpPosition ;Pointer to string (low) inc lmpPosition ;Increment offset for next byte iread ;Get data byte (in w) xor w, lmpData ;Is the received data byte correct ? jnz :Err ;No => error mov w, m ;Yes => continue. Move high part of data to w test w ;Is this the last byte ? (m is not 0) snz retp ;No => stay in this state mov lmpRxState, lmpRxPostTest ;Yes => Change to next state retp :Err mov lmpRxState, #lmpRxIASErrorState ;Will reply with Error code retp ;********** lap2lmpRxData - RxCommDataState ********** lmpRxCommData setb lmpAppRxFlag ;remember passing data mov w, lmpData ;Data to pass jmp @lmp2appRxCommData ;Pass data to app layer ;******************************************************************************** ;********** lap2lmpRxValid - RxBadLSAPState ********** lmpRxBadLSAP ;Should disconnect connection !!! jmp @lmp2lapDisconnectRequest ;********** lap2lmpRxValid - RxLMPCmdVerifyState ********** lmpRxValidLMPCommand csne lmpRxLMPCmdOpcode, #lmpConnectCmdOpcode ;Is this a request to open a connection ? jmp :Conn ;Yes => accept csne lmpRxLMPCmdOpcode, #lmpDisconnectOpcode ;Is this a request to clsoe a connection ? jmp :Disc ;Yes => close retp ;No => Unknown or unsupported command => ignore :Conn mov lmpTxStringH, #_lmpLMPConnRsp / 256 ;Pointer to string mov lmpTxStringL, #_lmpLMPConnRsp ;Pointer to string mov lmpTxState, #lmpTxStringState ;Prepare to transmit parameters setb lmpRxSLSAP.7 ;Indicate command (this will be the DLSAP byte when transmitted) cse lmpRxDLSAP, #lmpLSAPComm ;DLSAP addressing Comm ? jmp lmpRx2TxSetup ;No => nothing more to do other than to prepare to send reply mov lmpAppLSAP, lmpRxSLSAP ;Yes => Store Source LSAP in AppLSAP (ie remember the remote Comm App LSAP) clrb lmpAppLSAP.7 ;Set to information frame jmp lmpRx2TxSetup ;prepare to send reply :Disc csne lmpRxDLSAP, #lmpLSAPComm ;DLSAP addressing Comm ? clr lmpAppLSAP ;Yes => clear connection retp ;********** lap2lmpRxValid - RxIASAttribVerifyState ********** lmpRxValidIASAttribVerify mov lmpTxStringH, #_lmpTxStringSegment / 256 ;Pointer to string mov lmpTxStringL, lmpRxSendStringL ;Pointer to string mov lmpTxState, #lmpTxStringState ;Prepare to transmit parameters jmp lmpRx2TxSetup ;Prepare to transmit frame ;********** lap2lmpRxValid - RxIASErrorState ********** lmpRxValidIASError mov lmpTxState, #lmpTxIASErrorState ;Prepare to transmit error return code mov lmpTxIASErrOpcode, lmpRxIASErrOpcode mov lmpTxIASErrRetCode, lmpRxIASErrRetCode jmp lmpRx2TxSetup ;Prepare to transmit frame ;********** lap2lmpRxValid - RxCommDataState ********** lmpRxValidCommData clr lmpRxState ;Clear RxState back to idle clrb lmpAppRxFlag jmp @lmp2appRxCommValid ;******************************************************************************** ; LMP LAYER - Tx ;******************************************************************************** ;********** lap2lmpTxData - TxStringState ********** lmpTxString mov m, lmpTxStringH ;Pointer to string (high) mov w, lmpTxStringL ;Pointer to string (low) add w, lmpPosition ;Add offset inc lmpPosition ;Increment offset for next byte iread mov Temp, w ;Store data mov w, m ;Move high part of data to w test w ;Is this the last byte ? jnz :Last ;Yes mov w, Temp ;Data to pass clz ;Indicate more data to follow Data retp ;Return data to framing layer :Last mov w, Temp ;Data to pass stz ;Indicate last byte retp ;Return data to framing layer ;********** lap2lmpTxData - TxIASErrorState ********** lmpTxIASError test lmpPosition jnz :ErrCod :Opcode mov w, lmpTxIASErrOpcode ;Opcode that was received inc lmpPosition ;Next will send RetCode clz ;Indicate more data to follow retp :ErrCod mov w, lmpTxIASErrRetCode ;RetCode stz ;Indicate last byte retp ;********** lap2lmpTxData - TxCommDataState ********** lmpTxCommData setb lmpAppTxFlag ;remember receiving data call @lmp2appTxCommData ;Get next data byte bank lmpBank snz ;Skip if not last byte retp ;Z = 0 indicating last byte dec lmpPosition ;Byte counter retp ;Returns Z = true if counter = 0 ie when counter reaches 0 last flag will be set ;******************************************************************************** ENDM LmpRxStringSeg MACRO ;******************************************************************************** ; LMP LAYER - Strings ;WARNING - Strings must not go over a 256 boundry !!! ;******************************************************************************** _lmpRxStringSegment ;Rx strings must all be in the same segement !!! _lmpIASDeviceClass dw 'Device'+$F00 ;Classname = "Device" ($F00 indicates end) _lmpIASDeviceAttribName dw 'DeviceName'+$F00 ;Device Attribute: "DeviceName" ($F00 indicates end) _lmpIASDeviceAttribSupport dw 'IrLMPSupport'+$F00 ;Device Attribute: "IrLMPSupporte" ($F00 indicates end) _lmpIASCommClass dw 'IrDA:IrCOMM'+$F00 ;Classname = "IrDA:IrCOMM" ($F00 indicates end) _lmpIASCommAttribParam dw 'Parameters'+$F00 ;IrCOMM Attribute: "Parameters" ($F00 indicates end) _lmpIASCommAttribLsapSel dw 'IrDA:IrLMP:LsapSel'+$F00 ;IrCOMM Attribute: "LsapSel" ($F00 indicates end) ;******************************************************************************** ENDM LmpTxStringSeg MACRO ;******************************************************************************** ; LMP LAYER - String ;WARNING - Strings must not go over a 256 boundry !!! ;******************************************************************************** _lmpTxStringSegment ;Tx strings must all be in the same segement !!! _lmpLMPConnRsp dw lmpConnectRspOpcode, $00+$F00 _lmpIASDeviceName dw $84, $00 ;$84 = Reply to GetValueByClass, $00 = success _lmpIASDeviceName1 dw $00, $01 ;List length = 1 item _lmpIASDeviceName2 dw $00, $00 ;Object identifier = 0 _lmpIASDeviceName3 dw $03, $00 ;Data is of type "User string", ASCII _lmpIASDeviceName4 dw 28 ;length of text = 28 octets _lmpIASDeviceNameText dw 'SX IrDA IrComm Demonstration'+$F00 ;String to be displayed _lmpIASDeviceSupport dw $84, $00 ;$84 = Reply to GetValueByClass, $00 = success _lmpIASDeviceSupport1 dw $00, $01 ;List length = 1 item _lmpIASDeviceSupport2 dw $00, $00 ;Object identifier = 0 _lmpIASDeviceSupport3 dw $02 ;Data is of type "Octet Sequence" _lmpIASDeviceSupport4 dw $00, $03 ;Data is 3 bytes in length _lmpIASDeviceSupport5 dw $01 ;Data : IrLMP Version = 1 (refer LMP p 84) _lmpIASDeviceSupport6 dw $00 ;Data : IAS Support = no additional features (refer LMP p 84) _lmpIASDeviceSupport7 dw $00+$F00 ;Data : MUX Support = no additional features (refer LMP p 85) ($F00 indicates end) _lmpIASCommParam dw $84, $00 ;$84 = Reply to GetValueByClass, $00 = success _lmpIASCommParam1 dw $00, $01 ;List length = 1 item _lmpIASCommParam2 dw $00, $00 ;Object identifier = 0 _lmpIASCommParam3 dw $02 ;Data is of type "Octet Sequence" _lmpIASCommParam4 dw $00, $06 ;Data is 6 bytes in length _lmpIASCommParam5 dw $00, 1, %00000001 ;Data : Service types = 3 wire raw _lmpIASCommParam6 dw $01, 1, %00000011+$F00 ;Data : Port type = serial or parallel ($F00 indicates end) _lmpIASCommLsapSel dw $84, $00 ;$84 = Reply to GetValueByClass, $00 = success _lmpIASCommLsapSel1 dw $00, $01 ;List length = 1 item _lmpIASCommLsapSel2 dw $00, $00 ;Object identifier = 0 _lmpIASCommLsapSel3 dw $01 ;Data is of type "Integer" _lmpIASCommLsapSel4 dw $00, $00, $00, lmpLSAPComm+$F00 ;LsapSel = 5 ($F00 indicates end) ;******************************************************************************** ENDM AppInfoSeg MACRO ;******************************************************************************** ; APP LAYER ;******************************************************************************** ; Updated 6 Decembet 1999 - Nick Kelsey ; * TransApp: Increased UART buffer size from 7 to 16 bytes. ; * TransApp: Added flow control for UART receive. ;******************************************************************************** ; ; lmp2appRxCommData(w = Data) ;Incomming data bytes ; lmp2appRxCommValid() ;Data bytes passed since last Valid/Error message are valid ; lmp2appRxCommError() ;Data bytes passed since last Valid/Error message are invalid and should be discarded ; ; lmp2appTxCommStart(ret z=None) ;Data bytes can now be sent, Return Z=false if data to be sent ; lmp2appTxCommData(ret w=TxData, z=Last) ;Data bytes can now be sent. Set Z if this is the last byte to be sent ; lmp2appTxCommValid() ;All data passed since last Valid/Error message were acknowledged as received by the remote station ; lmp2appTxCommError() ;All data passed since last Valid/Error message were discarded and will need to be sent again ; ; lap2appRxUIData(w = Data) ;Incomming UI data bytes (outside of a connection only) ; lap2appRxUIValid() ;Data bytes passed since last Valid/Error message are valid ; lap2appRxUIError() ;Data bytes passed since last Valid/Error message are invalid and should be discarded ; ; app2lapTxUIFrame(ret z=Busy) ; lap2appTxUIData(ret w=TxData, z=Last) ; lap2appTxUIComplete() ; ; app2lapDiscoveryRequest(ret z=Busy) ; ;******************************************************************************** ENDM AppCommSX2PCCodeSeg MACRO ;******************************************************************************** ; APP LAYER - CommSX2PC ;******************************************************************************** appBank = $F0 appTxState = appBank + 0 ;Current transmission type appTxPosition = appBank + 1 ;Current transmission position appTxBank = appBank + 2 ;Current transmission position appRxData = appBank + 3 ;Current received byte appTxStrState = 1 appTxRegState = 2 appTxPortState = 3 ;********** Return ********** appReturn retp ;********** a2appReset ********** a2appReset bank appBank clr appTxState retp ;********** lmp2appRxCommData ********** lmp2appRxCommData ;Incomming data bytes bank appBank mov appRxData, w ;Store data (if more bytes are received in frame then only last byte is reconised) retp ;********** lmp2appRxCommValid ********** lmp2appRxCommValid ;Data bytes passed since last Valid/Error message are valid bank appBank test appTxState ;Currently not sending anything ? sz retp ;Already sending a frame => ignore command debugf 1, appRxData ;Show command out debug port csne appRxData, #'?' ;Is the command '?' ? jmp :Str ;Yes => prepare to transmit a string csne appRxData, #'r' ;Is the command 'r' ? jmp :Reg ;Yes => prepare to transmit registers csne appRxData, #'c' ;Is the command 'c' ? jmp :Port ;Yes => prepare to transmit port c contents retp :Str mov appTxState, #appTxStrState ;Will send string retp :Reg mov appTxState, #appTxRegState ;Will send registers clr appTxBank ;Clear TxBank ready for transmission retp :Port mov appTxState, #appTxPortState ;Will send port c retp ;********** lmp2appRxCommError ********** lmp2appRxCommError ;Data bytes passed since last Valid/Error message are invalid and should be discarded retp ;********** lmp2appTxCommStart ********** lmp2appTxCommStart ;Data bytes can now be sent. Return Z = flase if data to be sent bank appBank clr appTxPosition ;Clear TxPosition ready for transmission test appTxState ;Return z=false if TxState not 0 to indicate data to be sent retp ;********** lmp2appTxCommData ********** lmp2appTxCommData ;Data bytes can now be sent. If there is data available then return data byte and set Last (z) to false bank appBank mov w, appTxState ;Jump based on state jmp PC+w retp ;0 = Invalid jmp appTxStrData ;1 = appTxStrState jmp appTxRegData ;2 = appTxRegState jmp appTxPortData ;3 = appTxPortState appTxStrData mov m, #_lmpIASDeviceNameText / 256 ;Pointer to string (high) mov w, #_lmpIASDeviceNameText ;Pointer to string (low) add w, appTxPosition ;index into string inc appTxPosition ;Increment offset for next byte iread ;Read data from ROM mov Temp, w ;Store data mov w, m ;Move high part of data to w test w ;Is this the last byte ? jnz :Last ;Yes => indicate last :More mov w, Temp ;No => indicate more. Recover data to pass clz ;Indicate more data to follow Data retp ;Return data :Last mov w, Temp ;Data to pass stz ;Indicate last byte retp ;Return data appTxRegData mov w, #$10 ;w = $10 add w, appTxBank ;w = current bank (starting from $10) add w, appTxPosition ;w = pointer to current register mov FSR, w ;Apply pointer mov Temp, INDF ;Obtain data from register bank appBank csne appTxPosition, #$0F ;Last byte to be transmitted in frame ? jmp :Last ;Yes => indicate last :More inc appTxPosition ;No => indicate more. Increment position fo next data byte mov w, Temp ;Recover data to send clz ;Indicate more data to follow retp :Last mov w, Temp ;Recover data to send stz ;Indicate last byte retp appTxPortData mov w, rc ;Return contents of port c stz ;Indicate no more data to send retp ;Return data ;********** lmp2appTxCommValid ********** lmp2appTxCommValid ;All data passed since last Valid/Error message were acknowledged as received by the remote station bank appBank csne appTxState, #appTxRegState ;Currently transmitting registers ? jmp :Reg ;Yes => send more registers (multi frame) clr appTxState ;No => finished transmitting, return to idle state retp :Reg add appTxBank, #$20 ;Add $20 for next bank sz ;Back to starting bank ? retp ;No => more data to send, stay in this state clr appTxState ;Yes => finished transmitting, return to idle state retp ;********** lmp2appTxCommError ********** lmp2appTxCommError ;All data passed since last Valid/Error message were discarded and will need to be sent again retp ;Stay in current state for retransmission ;********** UI Frames ********** lap2appRxUIData = appReturn lap2appRxUIValid = appReturn lap2appRxUIError = appReturn lap2appTxUIData = appReturn lap2appTxUIComplete = appReturn ;********** Uart ********** a2appRxAvail bank IsrBank clrb UartRxAvail ;Clear flag retp ;******************************************************************************** ENDM AppCommTransCodeSeg MACRO ;******************************************************************************** ; APP LAYER - CommTrans ;******************************************************************************** appBank = $D0 ;Local variables appData = $F0 ;16-byte buffer appHeadPtr = appBank + 0 ;1 byte appTailPtr = appBank + 1 ;1 byte ;********** Return ********** appReturn retp ;********** a2appReset ********** a2appReset bank appBank clr appHeadPtr ;Init buffer head pointer clr appTailPtr ;Init buffer tail pointer clrb UartCtsPin ;Indicate CTS to PC - ready to accept more data retp ;********** lmp2appRxCommData ********** lmp2appRxCommData ;Incomming data bytes debug 1 ;Show data out debug port retp ;********** lmp2appRxCommValid ********** lmp2appRxCommValid ;Data bytes passed since last Valid/Error message are valid retp ;********** lmp2appRxCommError ********** lmp2appRxCommError ;Data bytes passed since last Valid/Error message are invalid and should be discarded retp ;********** lmp2appTxCommStart ********** lmp2appTxCommStart ;Data bytes can now be sent. Return Z = flase if data to be sent bank appBank mov w, appHeadPtr ;Compare head pointer with tail pointer xor w, appTailPtr ;Z is true if they match => indicating no data to send retp ;Z is false if they do not match indicating data to send ;********** lmp2appTxCommData ********** lmp2appTxCommData ;Data bytes can now be sent. If there is data available then return data byte and set Last (z) to false bank appBank mov w, appTailPtr ;Index into buffer and w, #%00001111 ;16 byte buffer xor w, #appData ;Add pointer to first byte of data mov FSR, w ;Apply pointer mov Temp, INDF ;Read byte out of buffer bank appBank inc appTailPtr ;move on tail ptr mov w, appHeadPtr ;Compare head pointer with tail pointer xor w, appTailPtr ;Do they match (indicating no more data) jz :Last ;Yes => no more data :More mov w, Temp ;No => more data. Recover data clz ;Indicate more data to follow retp ;Return data :Last mov w, Temp ;Recover data clrb UartCtsPin ;Indicate CTS to PC - ready to accept more data stz ;Indicate last byte retp ;Return data ;********** lmp2appTxCommValid ********** lmp2appTxCommValid ;All data passed since last Valid/Error message were acknowledged as received by the remote station retp ;********** lmp2appTxCommError ********** lmp2appTxCommError ;All data passed since last Valid/Error message were discarded and will need to be sent again retp ;********** UI Frames ********** lap2appRxUIData = appReturn lap2appRxUIValid = appReturn lap2appRxUIError = appReturn lap2appTxUIData = appReturn lap2appTxUIComplete = appReturn ;********** Uart ********** a2appRxAvail setb UartCtsPin ;Indicate NOT CTS after 1st byte (PC will send 16 bytes after loosing CTS!) bank IsrBank mov Temp, UartRxData ;Store received byte in buffer clrb UartRxAvail ;Clear flag bank appBank mov w, appHeadPtr ;Index into buffer and w, #%00001111 ;16 byte buffer xor w, #appData ;Add pointer to first byte of data mov FSR, w ;Apply pointer mov INDF, Temp ;Store data bank appBank inc appHeadPtr ;Record count retp ;******************************************************************************** ENDM AppSX2SXCodeSeg MACRO ;******************************************************************************** ; APP LAYER - SX 2 SX ;******************************************************************************** appBank = $F0 appTxState = appBank + 0 ;Current transmission type appTxPosition = appBank + 1 ;Current transmission position appTxStrState = 1 appTxPortState = 2 ;********** Return ********** appReturn retp ;********** a2appReset ********** a2appReset bank appBank clr appTxState retp ;********** lmp2appCommData ********** lmp2appRxCommData = appReturn lmp2appRxCommValid = appReturn lmp2appRxCommError = appReturn lmp2appTxCommData = appReturn lmp2appTxCommValid = appReturn lmp2appTxCommError = appReturn lmp2appTxCommStart stz retp ;********** UI Frames - Rx ********** lap2appRxUIData debug 1 ;Show data retp lap2appRxUIValid retp lap2appRxUIError retp ;********** UI Frames - Tx ********** lap2appTxUIData bank appBank mov w, appTxState ;Jump based on state jmp PC+w retp ;0 = Invalid jmp appTxStrData ;1 = appTxStrState jmp appTxPortData ;2 = appTxPortState appTxStrData mov m, #_lmpIASDeviceNameText / 256 ;Pointer to string (high) mov w, #_lmpIASDeviceNameText ;Pointer to string (low) add w, appTxPosition ;index into string inc appTxPosition ;Increment offset for next byte iread ;Read data from ROM mov Temp, w ;Store data mov w, m ;Move high part of data to w test w ;Is this the last byte ? jnz :Last ;Yes => indicate last :More mov w, Temp ;No => indicate more. Recover data to pass clz ;Indicate more data to follow Data retp ;Return data :Last mov w, Temp ;Data to pass stz ;Indicate last byte retp ;Return data appTxPortData mov w, rc ;Return contents of port c stz ;Indicate no more data to send retp ;Return data lap2appTxUIComplete bank appBank retp ;********** Uart ********** a2appRxAvail bank IsrBank mov Temp, UartRxData ;Store received byte in Temp clrb UartRxAvail ;Clear data available flag bank appBank debugf 1, Temp ;Show command csne Temp, #'d' ;Was the byte a 'd' jmp :XID ;Yes => request discovery csne Temp, #'s' ;Was the byte a 's' jmp :STR ;Yes => send the broadcast string csne Temp, #'c' ;Was the byte a 'c' jmp :PORT ;Yes => send contents of port c retp :XID call @app2lapDiscoveryRequest ;Request discovery mov w, #'^' ;Assume accepted (zero false) snz ;Was the request accepted ? mov w, #'!' ;No => refused debug 1 ;Send character out the debug port for the user retp :STR mov appTxState, #appTxStrState ;Will send string clr appTxPosition ;Reset position jmp :Send :PORT mov appTxState, #appTxPortState ;Will send port :Send call @app2lapTxUIStart mov w, #'^' ;Assume accepted (zero false) snz ;Was the request accepted ? mov w, #'!' ;No => refused debug 1 ;Send character out the debug port for the user retp ;******************************************************************************** ENDM ;******************************************************************************** ; debugl MACRO ; Send a Literal out the debug port ; Affects : w ; Cycles : 3 ;******************************************************************************** debugl MACRO 2 IF \1 = 1 mov w, #\2 mov DebugData, w setb DebugSend ENDIF ENDM ;******************************************************************************** ; debugf MACRO ; Send a Register out the debug port ; Affects : w, Z ; Cycles : 3 ;******************************************************************************** debugf MACRO 2 IF \1 = 1 mov w,\2 mov DebugData, w setb DebugSend ENDIF ENDM ;******************************************************************************** ; debug MACRO ; Send w out the debug port ; Affects : None ; Cycles : 2 ;******************************************************************************** debug MACRO 1 IF \1 = 1 mov DebugData, w setb DebugSend ENDIF ENDM ;******************************************************************************** ; IrDA Project ;******************************************************************************** device SX28L, OSCXT4, TURBO, STACKX_OPTIONX ; device PINS28, PAGES4, BANKS8, OSCHS, TURBO, STACKX, OPTIONX id 'IrDA' reset Startup freq 50000000 ;********** Mode Constants ********** TRIS = $0F PLP = $0E LVL = $0D ST = $0C WKEN = $0B WKED = $0A WKPND = $09 COMP = $08 IsrStatus = $0C ;Global ISR status register DebugData = $0D ;Debug data to be sent out the debug port Temp = $0E ;2 bytes of tempory storage PhysicalDataTx = 0 ;Shows all transmitted bytes to IR medium PhysicalDataRx = 0 ;Shows all received bytes from IR medium PayloadDataTx = 0 ;Shows all payload data bytes transmitted followed by ^ when frame is complete PayloadDataRx = 0 ;Shows all payload data bytes received followed by ^ or ! for pass/fail when frame is complete PayloadInfo = 0 ;Filters address and shows I, S, or U based on command type IFrameDataTx = 0 ;Shows all I frame data bytes transmitted followed by ^ or ! for ack/!ack IFrameDataRx = 0 ;Shows all I frame data bytes received followed by ^ or ! for ack/!ack ShowXIDInfo = 1 ShowConnect = 1 IsrDataSeg FrameDataSeg PayloadDataSeg LapDataSeg LmpDataSeg org $0000 IsrCodeSeg MainCodeSeg FrameCodeSeg LmpRxStringSeg org $0200 LapCodeSeg PayloadString3 org $0400 PayloadCodeSeg PayloadString1 PayloadString2 org $0600 ; ==================================================================== ; Application Code ; ; Uncomment the following lines for the three different applications. ; ; SX to PC communications (IrComm): ; AppCommSX2PCCodeSeg ; ; Transparent data transfer. PC to PC. (IrComm): AppCommTransCodeSeg ; ; SX to SX communications: ; AppSX2SXCodeSeg ; ; ==================================================================== LmpCodeSeg LmpTxStringSeg
file: /Techref/SCENIX/lib/io/osi2/ir/da/IRDA.SRC, 124KB, , updated: 1999/12/6 16:53, local time: 2024/8/14 16:46,
3.14.249.184:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://sxlist.com/TECHREF/SCENIX/lib/io/osi2/ir/da/IRDA.SRC"> SCENIX lib io osi2 ir da IRDA</A> |
Did you find what you needed? |
Welcome to sxlist.com!sales, advertizing, & kind contributors just like you! Please don't rip/copy (here's why Copies of the site on CD are available at minimal cost. |
Welcome to sxlist.com! |
.