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 15:53, local time: 2024/11/14 18:32,
|
| ©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://linistepper.com/techref/scenix/lib/io/osi2/ir/da/IRDA.SRC"> scenix lib io osi2 ir da IRDA</A> |
Did you find what you needed?
|