SMACK - Protocol Description
Version 1.0, Dated 27.02.92
by Jan Schiefer, DL5UE and Dieter Deyke, DK5SG/N0PRA
1. Introduction
The end of 1990 was the first time that the Stuttgart Packet-Radio-Amateurs 
thought about the factual certainty of Data Security between TNC and 
WAMPES(*)- Node Computer. Already with other Packet-Node Systems Data losses 
had appeared, we considered which sort and in what manner a compatible  
development of the KISS-Protocols with a Checksum could be considered 
possible. From the Result of this consideration came the name SMACK 
(Stuttgart Modified Amateur radio CRC-KISS. This Document should explain 
the difference between SMACK and KISS and make possible the implementation 
of other Systems. 
2. What is KISS?
KISS had been recommended by Phil Khan KA9Q [1]. Because his TCP/IP-Software 
it needed a Protocol, that enabled a simple entry to Packet-Radio below
the AX.25-Protocol level. KISS offers a layer 2a-Entry. Assignments of the 
TNC are basically, only the Access Control of the Frequency (Channel-Busy-
Recognition, P-Persistence-Action) and the conversion of the synchronous 
HDLC-Data on the PR-Channel into the asynchronous Format of the  RS232-Port. 
The KISS-Protocol regulates the demarcation of individual Packets with 
Delimiters, the eventual handling n the Data Stream of the appearing 
Delimiter and defines a simple Command structure for the installation of 
TNC-Parameters. Also, it has met the provision, to be able to operate TNCs 
with more Packet-Channels. 
3. Modification of the KISS-Protocol
The Host Computer communicates with KISS in the Form of Packets. The 
beginning of such a Packet will be recognised through the FEND. Then 
follows the so called Command Byte. It issues, whether it is handling Data- 
or a Command Packet and what Command is meant. With one exception (Reset-
Command = 255) all Commands employ only the lower 4 Bits of this Command 
Byte. This means, that the upper 4 Bits with Multi-Channel-TNCs can issue 
the Channel. So 16 Channels can be given Parameters individually. 
Because we do not know either 16- or 8-Channel-TNCs, we have used a purpose 
other than originally intended, the topmost Bit of this Command Byte. If 
it is set, it handles itself with the doubtful Packet as a Data Packet with 
CRC (only with Data Packets are to found a Checksum calculation instead!). 
With such Packets, the Checksum will be attached at the End of the Frame, 
and the lower value Byte first. Both of the following illustrations show the 
layout of a Data Packet once with and once without Checksum. 
| FEND | 0x00 | DATA | DATA | ... | DATA | FEND |
KISS-Frame without Checksum
| FEND | 0x80 | DATA | DATA | ... | DATA | CRC LOW | CRC HIGH | FEND |
Smack-Frame with Checksum
It should be once again reiterated here, that only Data Packets will be 
CRC-secured. With that it will be prevented, that a Command can be sent to 
the TNC, when themselves Host and TNC with CRC/not CRC are in disagreement.
4. Switching from KISS onto SMACK
A SMACK-TNC works after switching into the KISS-Modus, therefore generates 
no Checksum. As soon as the first Packet is received with CRC, it switches 
its Send Routines likewise to CRC. This Operation condition can be  
abandoned only through a Reset. The Host behaves analogously.  If however a 
KISS-TNC is connected, so CRC-Frames from the Host by reason of their 
unknown Command Byte will be discarded and working continued. 
This Method has the advantage, that both KISS- as also SMACK-TNCs can be 
operated alternately to a Host; without that, a reconfiguration is 
necessary. That should be illustrated by a Display of both cases. 
Case 1: KISS-TNC
Host                                    TNC
- Sends an individual Packet with
  CRC, then switches its Sender
  on Normal-KISS again.
                                        - Receives a frame which for
                                          it is an unknown Command-
                                          byte 0x80 and abandons it.
- Dispatches KISS-Data without
                                        - Dispatches KISS-Data without
Host                                    TNC
- Sends an individual Packet with
  CRC, then switches its Sender
  onto Normal-KISS again.
                                         - Receives a Frame with CRC-
                                          Recognition, switches its 
                                          Sender on CRC.
- Dispatches KISS-Data without
                                        - TNC sends the first Frame
                                          with CRC.
- Receives a Frame with CRC-
  Recognition, switches its
  Sender on CRC.
- Dispatches SMACK-Data with
                                        - Dispatches SMACK-Data with
Dependent upon Send condition (CRC/not CRC) the received Frames will always 
be handled as follows:
        Receiver Frame                 | Action
        No CRC                         | Frame progressed further
        With CRC, Correct Checksum     | Frame progressed further
        With CRC, False Checksum       | Frame abandoned
This Protocol sets in advance, that a KISS-Implementation abandons its 
unknown Frame. This will be promoted in the KISS-Specification [1].
4. CRC-Calculation and Implementation Tips
This is not the correct place, to explain the Theory of the cyclical 
Redundancy-check CRC. Reference should be made to the work of Michael 
R”hner, DC4OX [2]. This extract depicts only important Details for an 
As Check Polynomial the CRC16-Polynomial will be used. This has the form
         16    15   2
        X   + X  + X  + 1
The CRC-Generator will be pre-set with 0. The calculation of the CRC will be 
of the CRC over all Data Bytes inclusive of the Command Byte 0x80. 
As is well known in the KISS-Protocol the demarcation of the Frame will be 
performed with the FEND-Character (0xc0). In the case where this Character 
occurs in the Data Stream, it will be handled otherwise. This occurrence 
will be named SLIP-Encoding. 
The CRC must be calculated, before the SLIP-Encoding takes place, and will 
be checked, after the SLIP-Decoding has taken place. Instead it gives more 
- The CRC Bytes could contain FESC, TFEND, FEND etc.
- The SLIP En/Decoder will be used in most Host-Implementations (e.g.
  WAMPES) also dependent upon KISS, in order to make the Connection to the
  Unix-Kernel as an example. Additionally, it is admitted that in this case
  CRC-Checking would be desirable, but will not be understood by the other
The CRCs logically belong therefore, to the KISS Layer.
Instead the Calculation is to be found as follows:
- CRC-Generator pre-set with 0.
- All Data Bytes one behind the other added into the Algorithm, including
  both CRC-Bytes.
- At the End a 0 must stand again in the CRC-Generator. If the value is not
  0, so  a Transfer Error has occurred and the Frame must be discarded.
Different Algorithms for the CRC-Generator will be described in [2].
Here is a simple table of a controlled Algorithm issued in the C
Programming-Language, which the CRC of a Buffers (buf) calculates the
Length n
static int  calc_crc(char *buf, int n)
  static int  crc_table[] = {
    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
    0xcc01, 0xcc0,  0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
    0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
    0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
    0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
    0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
    0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
    0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
    0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
    0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
    0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
    0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
    0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
  int  crc;
  crc = 0;
  while (--n >= 0)
    crc = ((crc >> 8) & 0xff) ^ crc_table[(crc ^ *buf++) & 0xff];
  return crc;
Saving of the Table requires 512 Bytes. If the EPROM in the TNC should 
be too full for the saving of this Table, so it can be constructed as 
follows for the Runtime: 
unsigned short Table[256];
const int Rest[8] = { 0xC0C1, 0xC181, 0xC301, 0xC601, 0xCC01, 0xD801,
                      0xF001, 0xA001 };
        int i, j;
        unsigned short value;
        for (i = 0; i < 256; i++) {
                value = 0;
                for (j = 0; j < 8; j++)
                        if (i & (1 << j))
                                value ^= Rest[j];
                Table[i] = value;
If this Algorithm is to be coded in Assembler, so it requires distinctly 
less space than the Saving of the Table itself.
The Theory is to be found again in [2].
5. Implementation
Previously this Protocol has been implemented in the following Systems:
- SMACK, Version 1.3. This Software has been developed further by Jan 
  Schiefer, DL5UE, from TNC2-KISS-Implementation written by K3MC. It will 
  be installed especially in the TNCs of the WAMPES-NODES DB0ID (Digipeater 
  Stuttgart) and DB0SAO (Mailbox Stuttgart) there it contains also, 
  individual WAMPES-specific adaptations. - In the KISS of the NORD><LINK-
  Firmware, from TheFirmware Version 2.4 - For the TCP/IP-Software NOS it 
  gives from Thommy Osterried, DL9SAU, a 'a rundown', of the NOS developed 
  from the SMACK-capabilities. 
7. Outlook
A  desirable Implementation of this Protocol would be especially, a Packet-
Driver from the 'Packet driver specification' [3]. With it would be given an 
uninhibited possibility for all existing NET- and NOS-Versions without 
alteration of the Source Codes. But also every other Packet-Radio-Software, 
that installs the KISS-TNCs could profit from the Error Protection of the 
This Protocol Description has a preliminary Character. The Authors 
(dl5ue@db0sao, dk5sg@db0sao) are thankful for Improvement recommendations, 
Advice on Error or other Comments. 

(*) WAMPES = Wrttemberg Amateurraadio Multi-Protocol-Experimental-Software. 
    A software packet under UNIX, that implements multiple Protocols from  
    AX.25-, TCP/IP and NET/ROM-Protocol Families and, will be installed 
    mainly in the Stuttgart Area, as Net Nodes. Compare [4].
[1] Karn, Phil, KA9Q; Proposed "Raw" TNC Functional Spec, 6.8.1986;
    published in the USENET-News;
[2] R”hner, Michael, DC4OX; Was ist CRC?; distributed in the Packet-Radio
    Mailbox-Net, May 1988
[3] FTP Software, Inc.; PC/TCP Version 1.09 Packet Driver Specification;
    Wakefield, MA 1989
[4] Schiefer, Jan, DL5UE; WAMPES - Weiterentwicklung; Vortrags-Skriptum
    des 5. berregionalen Packet-Radio-Treffens; Frankfurt 1989;
Translation by G0KIU

Ritorna a Software Radioamatoriale by IW3FQG