home *** CD-ROM | disk | FTP | other *** search
- page 132,63,1,1
- opt rc
- title 'KISS protocol handling'
-
- ;***************************************************************
- ;* KISS.ASM -- KISS protocol interface and SCI drivers *
- ;* *
- ;* Provides interrupt based SCI handling, data buffering *
- ;* and KISS protocol handling. *
- ;* *
- ;* KISS protocol handling is based on article *
- ;* Chepponis, M., Karn, P.: *
- ;* "The KISS TNC: A simple Host-to-TNC communications *
- ;* protocol", *
- ;* Proc. of the sixth ARRL computer networking cnf., 1988 *
- ;* *
- ;* This module uses registers as follows: *
- ;* r1 - read queue tail ptr *
- ;* r4 - general purpose *
- ;* r5 - write queue head ptr *
- ;* *
- ;* Copyright (C) 1990, 1991 by Alef Null. All rights reserved. *
- ;* Author(s): Jarkko Vuori, OH2LNS *
- ;* Modification(s): *
- ;* 1991-Jun: corrected FEND TFEND, FEND TFESC bug *
- ;***************************************************************
-
- nolist
- include 'ioequlc'
- list
-
- section Kiss
- xdef baud
- xdef sci_ini,sci_rec,sci_err,sci_xmt
- xdef rdhost,tsthost
- xdef wrhost,endfrm,rejfrm
- xref kickx
- xref m_scr,m_sccr,m_srxl,m_ssr,m_tie,m_stxl
-
- org p:
-
- nolist
- include 'macros'
- list
-
- ; Serial interface parameters
- baud equ 9600
-
- ; KISS special characters
- fend equ $c0
- fesc equ $db
- tfend equ $dc
- tfesc equ $dd
-
- ; Xmitter status flags
- idle equ 0
-
-
- ;****************************
- ;* SCI initialization *
- ;****************************
- sci_ini
- ; initialize SCI
- IF !DEBUG
- movep #$2b02,x:m_scr ; async 8,n,1
- movep #20736000/(2*2*16*baud),x:m_sccr
- ELSE
- movep #$2b02,x:m_scr ; async 8,n,1
- movep #20736000/(10*2*2*16*baud),x:m_sccr
- ENDIF
- ; initialize receiving queue handling
- movi str0,x:<rstate
- movi 0,x:<rfrmcnt
- movi inbuf,x:<rhead
- move #inbuf,r1
- move #inqlen-1,m1
- movi $1,x:<rstatus ; receiver idling
- ; initialize sending queue handling
- movi stx0,x:<xstate
- movi 0,x:<xfrmcnt
- move #outbuf,r5
- move #outqlen-1,m5
- move r5,x:<xohead
- movi outbuf,x:<xtail
- movi $1,x:<xstatus ; xmitter idling
-
- rts
-
-
- ;****************************
- ;* SCI receive interrupt *
- ;****************************
- sci_rec
- ; save registers to be used
- enter scir
- stor scirr,4
- ; read received character
- movep x:m_srxl,x0
- clr a x:<rstate,r4
- clr b #fend,a1
- jmp (r4) ; determine what to do for it
-
- ; --- State 0, waiting for FEND
- str0 cmp x0,a #str1,b1
- jne <scr_end ; we didn't see FEND, keep looking
- move b1,x:<rstate ; FEND found, change state
- jmp <scr_end
-
- ; --- State 1, we have seen FEND, look for the command byte
- str1 cmp x0,a
- jeq <scr_end ; just another FEND, keep looking for cmd
- ; analyze command byte
- clr a
- cmp x0,a #str2,b1
- jeq <str1c ; cmd 0, data will follow
- ; check for command 1,2,3,4,5,6
- str1a move #parcnt,a1
- cmp x0,a #str4,b1
- jlt <str1b
- ; valid cmd, store it and change state
- move b1,x:<rstate
- move x0,x:<cmd
- jmp <scr_end
- ; invalid cmd, look for FEND
- str1b move #str0,b1
- move b1,x:<rstate
- jmp <scr_end
- ; start a new frame
- str1c move b1,x:<rstate
- move x:<rhead,b1 ; backup current rhead
- move b1,x:<rohead
- jmp <scr_end
-
- ; --- State 2, data to follow
- str2 cmp x0,a #fesc,b1 ; check if end of frame
- jeq <strend
- cmp x0,b ; check if escape
- jeq <stresc
- ; store the character to the queue
- store move #inqlen-1,m4
- move x:<rhead,r4
- move r1,b1
- move x0,p:(r4)+
- move r4,x1 ; check buffer full
- cmp x1,b x0,a
- jeq <strful
- ; check if end of frame
- move r4,x:<rhead
- tst a
- jpl <scr_end
- ori #$02,mr
- nop
- nop
- nop
- nop
- move x:<rfrmcnt,r4
- andi #$fe,mr ; do not allow SCI interrupts yet
- clr a (r4)+ ; yeah, increment frame counter
- move r4,x:<rfrmcnt
- ; check if receiver sleeping
- bclr #idle,x:<rstatus
- jcc <scr_st0
- jsr <kickx ; yup, kick receiver
- jmp <scr_st0
- ; queue full, discard the current frame
- strful move x:<rohead,b1 ; restore rhead
- move b1,x:<rhead
- jmp <scr_st0 ; enter FEND hunt
- ; end of frame, store negative value and increment frame counter
- strend
- move #-1,x0
- jmp <store
- ; escape character found
- stresc move #str3,b1 ; enter FESC found state
- move b1,x:<rstate
- jmp <scr_end
-
- ; --- State 3, saw FESC, expecting TFESC or TFEND
- str3 move #tfesc,b1 ; check if TFESC
- cmp x0,b #tfend,a1
- jeq <str3esc
- cmp x0,a #str2,b1 ; check if TFEND
- jeq <str3end
- move b1,x:<rstate ; something wrong has happened,
- jmp <scr_end ; go back to the data receiving mode
- ; we have seen TFESC after an FESC, write an FESC
- str3esc move #str2,b1
- move b1,x:<rstate
- move #>fesc,x0
- jmp <store
- ; we have seen TFEND after an FESC, write an FEND
- str3end move #str2,b1
- move b1,x:<rstate
- move #>fend,x0
- jmp <store
-
- ; --- State 4, get command data
- str4 move x:<cmd,n4 ; enter byte to its place in parameter area
- move #params-1,r4
- ; check if we need special scaling
- clr a x:<cmd,x1
- move #<(txdly-params+1),a1
- cmp x1,a #<(slotime-params+1),a1
- jeq <str4a
- cmp x1,a #<(txtail-params+1),a1
- jeq <str4a
- cmp x1,a #<(gain-params+1),a1
- jeq <str4a
- cmp x1,a #>@cvi(@pow(2,15-1)),x1
- jne <str4b
- ; yes, gain scaling (shift left 15 bits)
- mpy x0,x1,a
- move a0,x:(r4+n4)
- jmp <scr_st0
- ; yes, time scaling
- str4a move #>baud/100,x1
- mpy x0,x1,a
- asr a ; interger multiply correction
- move a0,x:(r4+n4) ; product in low order word
- jmp <scr_st0
- ; no scaling needed, just store the value
- str4b move x0,x:(r4+n4)
-
- ; go back to FEND hunt state
- scr_st0 movi str0,x:<rstate
-
- ; restore registers
- scr_end rclr scirr,4
- leave scir
-
-
- ;****************************
- ;* SCI receive with errors *
- ;* interrupt *
- ;****************************
- sci_err
- ; save registers to be used (b1)
- move b1,y:<scir
- ; clear SCI interrupts
- movep x:m_ssr,b1
- movep x:m_srxl,b1
- ; restore frame
- move x:<rohead,b1 ; restore rhead
- move b1,x:<rohead
- ; restore registers (b1)
- move y:<scir,b1
-
- rti
-
-
- ;****************************
- ;* SCI xmitter interrupt *
- ;****************************
- sci_xmt
- ; save registers to be used
- enter scix
- stor scixr,4
- ; jump to the current state
- move x:<xstate,r4
- nop
- jmp (r4)
-
- ; --- State 0, start sending KISS-packet
- stx0 move x:<xfrmcnt,a
- tst a
- jeq <stx0no
- ; there is data in the queue, begin a new frame
- movi stx1,x:<xstate
- move #>fend,x0
- jmp <xbyte
- ; there are no data left in the queue, stop xmitter
- stx0no bset #idle,x:<xstatus
- bclr #m_tie,x:m_scr
- jmp <scx_end
-
- ; --- State 1, send KISS command byte (always data command)
- stx1 movi stx2,x:<xstate
- move #>0,x0
- jmp <xbyte
-
- ; --- State 2, send KISS data
- stx2
- ; get a new character from the queue
- move x:<xtail,r4
- move #outqlen-1,m4
- nop
- move p:(r4)+,a
- tst a r4,x:<xtail
- jpl <stx2dat
- ; end of frame, decrement frame counter
- ori #$02,mr
- nop
- nop
- nop
- nop
- move x:<xfrmcnt,r4
- andi #$fe,mr ; do not allow SCI interrupts yet
- move (r4)-
- move r4,x:<xfrmcnt
- ; and then send frame end flag
- movi stx0,x:<xstate
- move #>fend,x0
- jmp <xbyte
- ; new data found, check for special characters
- stx2dat move #>fesc,x0
- cmp x0,a #>tfesc,x0 ; check if FESC
- jeq <stx2spe
- move #>fend,x0
- cmp x0,a #>tfend,x0 ; check if FEND
- jeq <stx2spe
- move a,x0
- jmp <xbyte ; normal character out
- ; special character, enter escaped mode
- stx2spe movi stx3,x:<xstate
- move x0,x:<xtmp
- move #>fesc,x0
- jmp <xbyte
-
- ; --- State 3, escaped mode
- stx3 movi stx2,x:<xstate
- move x:<xtmp,x0
- jmp <xbyte
-
- ; send x0 to SCI
- xbyte movep x0,x:m_stxl
-
- ; restore registers
- scx_end rclr scixr,4
- leave scix
-
-
- ;****************************
- ;* Read from host buffer *
- ;****************************
- ; x0 byte read from the queue
- ; returns with N bit set when frame end detected
- ; Note! this routine must not be called when you
- ; are not sure if there are data left
- rdhost move p:(r1)+,a ; get next byte from the queue
- tst a x:<rfrmcnt,r0 ; decrement byte counter
- jpl <rdhend
- ; end of frame, decrement frame counter
- move (r0)-
- move r0,x:<rfrmcnt
-
- rdhend move a,x0
- rts
-
-
- ;****************************
- ;* Test if data in queue *
- ;****************************
- ; returns with Zero if there are no data available
- tsthost move x:<rfrmcnt,a
- tst a
- jne <tstend
- ; no data, receiver idling
- bset #idle,x:<rstatus
- tstend rts
-
-
- ;****************************
- ;* Write to the host buffer *
- ;****************************
- ; x0 byte written to the queue
- wrhost move x0,p:(r5)+
- ; check if buffer full
- move x:<xtail,a
- move r5,x1
- cmp x1,a
- move x0,a ; &&&&&
- jeq <wrfull
- ; no, check if this was an end of frame
- tst a x:<xfrmcnt,r0
- jpl <wrend
- ; yes, store a new frame beginning
- move r5,x:<xohead
- ; increment frame counter
- move (r0)+
- move r0,x:<xfrmcnt
- ; check for idling xmitter
- bclr #idle,x:<xstatus
- jcc <wrend
- ; xmitter was idling, kick it up
- movi stx1,x:<xstate
- movep #fend,x:m_stxl
- bset #m_tie,x:m_scr
- rts
- ; queue full, discard the current frame
- wrfull move x:<xohead,r5
-
- wrend rts
-
-
- ;****************************
- ;* End the current frame *
- ;****************************
- endfrm move #-1,x0
- jmp <wrhost
-
-
- ;****************************
- ;* Reject the current frame *
- ;****************************
- rejfrm jmp <wrfull
-
-
- ;****************************
- ;* DATA - AREA *
- ;****************************
-
- org x:
-
- ; KISS-to-data queue
- rfrmcnt ds 1 ; how many frames in the queue
- rohead ds 1 ; start of the current frame
- rhead ds 1
- rstatus ds 1
-
- ; KISS decoder data
- rstate ds 1 ; KISS decoder state
- cmd ds 1 ; current KISS command
-
- ; data-to-KISS queue
- xfrmcnt ds 1 ; how many frames in the queue
- xohead ds 1 ; start of the current frame
- xtail ds 1
- xstatus ds 1 ; xmitter status
-
- ; KISS coder data
- xstate ds 1 ; KISS coder state
- xtmp ds 1 ; temporary store
-
- endsec
-
- ;****************************
- ;* MODEM PARAMETERS *
- ;****************************
- section ModemPar
- xdef params,parcnt,txdly,P,slotime,txtail,fuldplx,gain
-
- org x:
-
- ; every time delay is in 1/baud s
- params equ *
- IF !DEBUG
- txdly dc baud/100*50 ; 500 mS
- P dc 63
- slotime dc baud/100*1 ; 10 mS
- txtail dc baud/100*1 ; 10 mS
- fuldplx ds 1
- gain dc 0.05
- ELSE
- txdly dc 10
- P dc 63
- slotime dc 10
- txtail dc 10
- fuldplx ds 1
- gain dc 0.1
- ENDIF
- parcnt equ *-params
-
- endsec
-
- ;****************************
- ;* DATA QUEUE BUFFERS *
- ;****************************
- section KissQue
- xdef inqlen,outqlen
- xdef outbuf,inbuf
-
- org p:
-
- inqlen equ 2048
- outqlen equ 1024
-
- outbuf ds outqlen
- inbuf ds inqlen
-
- endsec
-
- end
-