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: 2009/1/7 22:47,
|