{"id":17299963,"url":"https://github.com/f4exb/picc1101","last_synced_at":"2025-04-14T11:14:49.512Z","repository":{"id":27977766,"uuid":"31471136","full_name":"f4exb/picc1101","owner":"f4exb","description":"Connect Raspberry-Pi to CC1101 RF module and play with AX.25/KISS to transmit TCP/IP over the air","archived":false,"fork":false,"pushed_at":"2018-08-06T20:57:44.000Z","size":516,"stargazers_count":84,"open_issues_count":4,"forks_count":19,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-04-14T11:14:44.631Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/f4exb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-02-28T18:04:08.000Z","updated_at":"2024-11-11T13:41:53.000Z","dependencies_parsed_at":"2022-08-26T11:20:30.566Z","dependency_job_id":null,"html_url":"https://github.com/f4exb/picc1101","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f4exb%2Fpicc1101","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f4exb%2Fpicc1101/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f4exb%2Fpicc1101/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f4exb%2Fpicc1101/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/f4exb","download_url":"https://codeload.github.com/f4exb/picc1101/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248868766,"owners_count":21174758,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-15T11:24:56.526Z","updated_at":"2025-04-14T11:14:49.493Z","avatar_url":"https://github.com/f4exb.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"picc1101\n========\n\nConnect Raspberry-Pi to CC1101 RF module and play with AX.25/KISS to transmit TCP/IP over the air.\n\n- [picc1101](#picc1101)\n- [Introduction](#introduction)\n- [Disclaimer](#disclaimer)\n- [Installation and basic usage](#installation-and-basic-usage)\n  - [Prerequisites](#prerequisites)\n  - [Obtain the code](#obtain-the-code)\n  - [Compilation](#compilation)\n  - [Run test programs](#run-test-programs)\n  - [Process priority](#process-priority)\n    - [Specify a higher priority at startup](#specify-a-higher-priority-at-startup)\n    - [Engage the \"real time\" priority](#engage-the-real-time-priority)\n  - [Program options](#program-options)\n  - [Detailed options](#detailed-options)\n    - [Verbosity level (-v)](#verbosity-level--v)\n    - [Radio interface speeds (-R)](#radio-interface-speeds--r)\n    - [Modulations (-M)](#modulations--m)\n    - [Test routines (-t)](#test-routines--t)\n- [AX.25/KISS operation](#ax25kiss-operation)\n  - [Set up the AX.25/KISS environment](#set-up-the-ax25kiss-environment)\n    - [Kernel modules](#kernel-modules)\n    - [Install AX.25 and KISS software](#install-ax25-and-kiss-software)\n    - [Create your AX.25 interfaces configuration](#create-your-ax25-interfaces-configuration)\n    - [Create a virtual serial link](#create-a-virtual-serial-link)\n    - [Create the network device using kissattach](#create-the-network-device-using-kissattach)\n    - [Scripts that will run these commands](#scripts-that-will-run-these-commands)\n  - [Run the program](#run-the-program)\n  - [Relay the KST chat](#relay-the-kst-chat)\n- [Details of the design](#details-of-the-design)\n  - [Multiple block handling](#multiple-block-handling)\n  - [Mitigate AX.25/KISS spurious packet retransmissions](#mitigate-ax25kiss-spurious-packet-retransmissions)\n\n# Introduction\nThe aim of this program is to connect a RF module based on the Texas Instruments (Chipcon) chip CC1101 to a Raspberry-Pi host machine. The CC1101 chip is a OOK/2-FSK/4-FSK/MSK/GFSK low power (~10dBm) digital transceiver working in the 315, 433 and 868 MHz ISM bands. The 433 MHz band also happens to cover the 70cm Amateur Radio band and the major drive of this work is to use these modules as a modern better alternative to the legacy [Terminal Node Controllers](http://en.wikipedia.org/wiki/Terminal_node_controller) or TNCs working in 1200 baud FM AFSK or 9600 baud G3RUH true 2-FSK modulation at best. Using the Linux native AX.25 and KISS interface to the TNCs it is then possible to route TCP/IP traffic using these modules offering the possibility to connect to the Amateur Radio private IP network known as [Hamnet](http://hamnetdb.net/).\n\nAnother opportunity is the direct transmission of a Transport Stream to carry low rate live video and this will be studied later.\n\nThese RF modules are available from a variety of sellers on eBay. Search for words `CC1101` and `433 MHz`. The Raspberry-Pi doesn't need to be introduced any further. If you are reading these lines you probably know what it is!\n\nThe CC1101 chip implements preamble, sync word, CRC, data whitening and FEC using convolutive coding natively. It is a very nice little cheap chip for our purpose. It has all the necessary features to cover the OSI layer 1 (physical). Its advertised speed ranges from 600 to 500000 Baud (300000 in 4-FSK) but it can go as low as 50 baud however details on performance at this speed have not been investigated. Yet the program offers this possibility.\n\nThe CC1101 chip is interfaced using a SPI bus that is implemented natively on the Raspberry-PI and can be accessed through the `spidev` library. In addition two GPIOs must be used to support the handling of the CC1101 Rx and Tx FIFOs. For convenience GPIO-24 and GPIO-25 close to the SPI bus on the Raspberry-Pi are chosen to be connected to the GDO0 and GDO2 lines of the CC1101 respectively. The WiringPi library is used to support the GPIO interrupt handling.\n\nThe CC1101 data sheet is available [here](www.ti.com/lit/ds/symlink/cc1101.pdf).\n\n# Disclaimer\nYou are supposed to use the CC1101 modules and this software sensibly. Please check your local radio spectrum regulations. \n\nFor Amateur Radio use you should have a valid Amateur Radio licence with a callsign and transmit in the bands and conditions granted by your local regulations also please try to respect the IARU band plan. In most if not all countries you are not allowed to transmit encrypted data so please do not route SSL traffic like `https` or `ssh`. Use plain `http` or `telnet` instead.\n\n# Installation and basic usage\n## Prerequisites\nThis has been tested successfully on a Raspberry Pi version 1 B with kernel 3.12.36. Raspberry Pi version 2 with a 3.18 kernel does not work.\n\nFor best performance you will need the DMA based SPI driver for BCM2708 found [here](https://github.com/notro/spi-bcm2708.git) After successful compilation you will obtain a kernel module that is to be stored as `/lib/modules/$(uname -r)/kernel/drivers/spi/spi-bcm2708.ko` \n\nYou will have to download and install the WiringPi library found [here](http://wiringpi.com/) \n\nThe process relies heavily on interrupts that must be served in a timely manner. You are advised to reduce the interrupts activity by removing USB connected devices as much as possible.\n\n## Obtain the code\nJust clone this repository in a local folder of your choice on the Raspberry Pi\n\n## Compilation\nYou can compile on the Raspberry Pi v.1 as it doesn't take too much time even on the single core BCM2735. You are advised to activate the -O3 optimization:\n  - `CFLAGS=-O3 make`\n\nThe result is the `picc1101` executable in the same directory\n\n## Run test programs\nOn the sending side:\n  - `sudo ./picc1101 -v1 -B 9600 -P 252 -R7 -M4 -W -l15 -t2 -n5`\n\nOn the receiving side:\n  - `sudo ./picc1101 -v1 -B 9600 -P 252 -R7 -M4 -W -l15 -t4 -n5`\n\nThis will send 5 blocks of 252 bytes at 9600 Baud using GFSK modulation and receive them at the other end. The block will contain the default test phrase `Hello, World!`.\n\nNote that you have to be super user to execute the program.\n\n## Process priority\nYou may experience better behaviour (less timeouts) depending on the speed of the link when raising the prioriry of the process. Interrupts are already served with high priority (-56) with the WiringPi library. The main process may need a little boost as well though\n\n### Specify a higher priority at startup\nYou can use the `nice` utility: `sudo nice -n -20 ./picc1101 options...` \nThis will set the priority to 0 and is the minimum you can obtain with the `nice` commmand. The lower the priority figure the higher the actual priority. \n\n### Engage the \"real time\" priority\nYou can use option -T of the program to get an even lower priority of -2 for a so called \"real time\" scheduling. This is not real time actually but will push the priority figure into the negative numbers. It has been implemented with the WiringPi piHiPri method and -2 is the practical lowest figure possible before entering into bad behaviour that might make a cold reboot necessary. Note that this is the same priority as the watchdog.\n\n## Program options\n \u003cpre\u003e\u003ccode\u003e\n  -B, --tnc-serial-speed=SERIAL_SPEED\n                             TNC Serial speed in Bauds (default : 9600)\n  -d, --spi-device=SPI_DEVICE   SPI device, (default : /dev/spidev0.0)\n  -D, --tnc-serial-device=SERIAL_DEVICE\n                             TNC Serial device, (default : /var/ax25/axp2)\n  -f, --frequency=FREQUENCY_HZ   Frequency in Hz (default: 433600000)\n  -F, --fec                  Activate FEC (default off)\n  -H, --long-help            Print a long help and exit\n  -l, --packet-delay=DELAY_UNITS   Delay between successive radio blocks when\n                             transmitting a larger block. In 2-FSK byte\n                             duration units. (default 30)\n  -m, --modulation-index=MODULATION_INDEX\n                             Modulation index (default 0.5)\n  -M, --modulation=MODULATION_SCHEME\n                             Radio modulation scheme, See long help (-H)\n                             option\n  -n, --repetition=REPETITION   Repetiton factor wherever appropriate, see long\n                             Help (-H) option (default : 1 single)\n  -P, --packet-length=PACKET_LENGTH\n                             Packet length (fixed) or maximum packet length\n                             (variable) (default: 250)\n  -R, --rate=DATA_RATE_INDEX Data rate index, See long help (-H) option\n  -s, --radio-status         Print radio status and exit\n  -t, --test-mode=TEST_SCHEME   Test scheme, See long help (-H) option fpr\n                             details (default : 0 no test)\n      --tnc-keydown-delay=KEYDOWN_DELAY_US\n                             FUTUR USE: TNC keydown delay in microseconds\n                             (default: 0 inactive)\n      --tnc-keyup-delay=KEYUP_DELAY_US\n                             TNC keyup delay in microseconds (default: 4ms).\n                             In KISS mode it can be changed live via\n                             kissparms.\n      --tnc-radio-window=RX_WINDOW_US\n                             TNC time window in microseconds for concatenating\n                             radio frames. 0: no concatenation (default: 0))\n      --tnc-serial-window=TX_WINDOW_US\n                             TNC time window in microseconds for concatenating\n                             serial frames. 0: no concatenation (default:\n                             40ms))\n      --tnc-switchover-delay=SWITCHOVER_DELAY_US\n                             FUTUR USE: TNC switchover delay in microseconds\n                             (default: 0 inactive)\n  -T, --real-time            Engage so called \"real time\" scheduling (defalut\n                             0: no)\n  -v, --verbose=VERBOSITY_LEVEL   Verbosiity level: 0 quiet else verbose level\n                             (default : quiet)\n  -V, --variable-length      Variable packet length. Given packet length\n                             becomes maximum length (default off)\n  -w, --rate-skew=RATE_MULTIPLIER\n                             Data rate skew multiplier. (default 1.0 = no\n                             skew)\n  -W, --whitening            Activate whitening (default off)\n  -y, --test-phrase=TEST_PHRASE   Set a test phrase to be used in test (default\n                             : \"Hello, World!\")\n  -?, --help                 Give this help list\n      --usage                Give a short usage message\n      --version              Print program version\n\u003c/code\u003e\u003c/pre\u003e\n\nNote: variable length blocks are not implemented yet.\n\n## Detailed options\n### Verbosity level (-v)\nIt ranges from 0 to 4:\n  - 0: nothing at all\n  - 1: Errors and some warnings and one line summary for each block sent or received\n  - 2: Adds details on received blocks like RSSI and LQI\n  - 3: Adds details on interrupt calls\n  - 4: Adds full hex dump of sent and received blocks\n\nBe aware that printing out to console takes time and might cause problems when transfer speeds and interactivity increase.\n\n### Radio interface speeds (-R)\n \u003cpre\u003e\u003ccode\u003e\nValue: Rate (Baud):\n 0     50 (experimental)\n 1     110 (experimental)\n 2     300 (experimental)\n 3     600\n 4     1200\n 5     2400\n 6     4800\n 7     9600\n 8     14400\n 9     19200\n10     28800\n11     38400\n12     57600\n13     76800\n14     115200\n15     250000\n16     500000 (300000 for 4-FSK)\n\u003c/code\u003e\u003c/pre\u003e\n\n### Modulations (-M)\n \u003cpre\u003e\u003ccode\u003e\nValue: Scheme:\n0      OOK\n1      2-FSK\n2      4-FSK\n3      MSK\n4      GFSK\n\u003c/code\u003e\u003c/pre\u003e\n\nNote: MSK does not seem to work too well at least with the default radio options.\n\n### Test routines (-t)\n \u003cpre\u003e\u003ccode\u003e\nValue: Scheme:\n0      No test (KISS virtual TNC)\n1      Simple Tx with polling. Packet smaller than 64 bytes\n2      Simple Tx with packet interrupt handling. Packet up to 255 bytes\n3      Simple Rx with polling. Packet smaller than 64 bytes\n4      Simple Rx with packet interrupt handling. Packet up to 255 bytes\n5      Simple echo test starting with Tx\n6      Simple echo test starting with Rx\n\u003c/code\u003e\u003c/pre\u003e\n\n# AX.25/KISS operation\n## Set up the AX.25/KISS environment\n### Kernel modules\nYou will need to activate the proper options in the `make menuconfig` of your kernel compilation in order to get the `ax25` and `mkiss` modules. It comes by default in most pre-compiled kernels.\n\nLoad the modules with `modprobe` command:\n  - `sudo modprobe ax25`\n  - `sudo modprobe mkiss`\n\nAlternatively you can specify these modules to be loaded at boot time by adding their names in the `/etc/modules` file\n\n### Install AX.25 and KISS software\n  - `sudo apt-get install ax25-apps ax25-node ax25-tools libax25`\n\n### Create your AX.25 interfaces configuration\nIn `/etc/ax25/axports` you have to add a line with:\n  - `\u003cinterface name\u003e \u003ccallsign and suffix\u003e \u003cspeed\u003e \u003cpaclen\u003e \u003cwindow size\u003e \u003ccomment\u003e`\n  - *interface name* is any name you will refer this interface to later\n  - *callsign and suffix* is your callsign and a suffix from 0 to 15. Ex: `F4EXB-14` and is the interface hardware address for AX.25 just like the MAC address is the hardware address for Ethrnet.\n  - *speed* is the speed in Baud. This has not been found really effective. The speed will be determined by the settings of the CC1101 itself and the TCP/IP flow will adapt to the actual speed.\n  - *paclen* this is the MTU of the network interface (ax0). Effectively this sets the limit on the size of each individual KISS frame although several frames can be concatenated. The value 224 along with a fixed radio block size (-P parameter) of 252 has been found satisfactory in most conditions.  \n  - *window size* is a number from 1 to 7 and is the maximum number of packets before an acknowledgement is required. This doesn't really work with KISS. KISS determines how many packets can be combined together in concatenated KISS frames that are sent as a single block. On the other end of the transmission the ACK can only be returned after the whole block has been received.\n  - *comment* is any descriptive comment\n\nExample:\n \u003cpre\u003e\u003ccode\u003e\n # /etc/ax25/axports\n #\n # The format of this file is:\n #\n # name callsign speed paclen window description\n #\n radio0  F4EXB-14           9600  224     1       Hamnet CC1101\n radio1  F4EXB-15           9600  224     1       Hamnet CC1101\n #1      OH2BNS-1           1200  255     2       144.675 MHz (1200  bps)\n #2      OH2BNS-9          38400  255     7       TNOS/Linux  (38400 bps)\n\u003c/code\u003e\u003c/pre\u003e\n\n### Create a virtual serial link\n - `socat d -d pty,link=/var/ax25/axp1,raw,echo=0 pty,link=/var/ax25/axp2,raw,echo=0 \u0026`\n\nNote the `\u0026` at the end that allows the command to run in background.\n\nThis creates two serial devices at the end of a virtual serial cable. \nThey are accessible via the symlinks specified in the command:\n  - /var/ax25/axp1\n  - /var/ax25/axp2\n\nAX.25/KISS engine will be attached to the `axp1` end and the program to `axp2`.\n\n### Create the network device using kissattach\n  - `sudo kissattach /var/ax25/axp1 radio0 10.0.1.7`\n  - `sudo ifconfig ax0 netmask 255.255.255.0`\n\nThis will create the `ax0` network device as shown by the `/sbin/ifconfig` command:\n \u003cpre\u003e\u003ccode\u003e\nax0       Link encap:AMPR AX.25  HWaddr F4EXB-15  \n          inet addr:10.0.1.7  Bcast:10.0.1.255  Mask:255.255.255.0\n          UP BROADCAST RUNNING  MTU:224  Metric:1\n          RX packets:3033 errors:24 dropped:0 overruns:0 frame:0\n          TX packets:3427 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:10 \n          RX bytes:483956 (472.6 KiB)  TX bytes:446797 (436.3 KiB)\n\u003c/code\u003e\u003c/pre\u003e\n\n### Scripts that will run these commands\nIn the `scripts` directory you will find:\n  - `kissdown.sh`: kills all processes and removes the `ax0` network interface from the system\n  - `kissup.sh \u003cIP\u003e \u003cNetmask\u003e`: brings up the `ax0` network interface with IP address \u003cIP\u003e and net mask \u003cNetmask\u003e\n\nExamples:\n  - `./kissdown.sh`\n  - `./kissup.sh 10.0.1.3 255.255.255.0`\n\n## Run the program\nThis example will set the CC1101 at 9600 Baud with GFSK modulation. We raise the priority of the process (lower the priority number down to 0) with the `nice` command:\n\n  - `sudo nice -n -20 ./picc1101 -v1 -B 9600 -P 252 -R7 -M4 -W -l15`\n\nOther options are:\n  - verbosity level (-v) of 1 will only display basic execution messages, errors and warnings\n  - radio block size (-P) is fixed at 252 bytes\n  - data whitening is in use (-W)\n  - inter-block pause when sending multiple blocks (see next) is set for a 15 bytes transmission time approximately (-l) \n\nNote that you have to be super user to execute the program.\n\n## Relay the KST chat\nAs a sidenote this is the way you can relay the KST chat (that is port 23000 of a specific server) through this radio link. \n\nOn one end that has a connection to the Internet (say 10.0.1.3) do the port forwarding:\n  - `sudo /sbin/iptables -t nat -A PREROUTING -p tcp -i ax0 --dport 23000 -j DNAT --to-destination 188.165.198.144:23000`\n  - `sudo /sbin/iptables -t nat -A POSTROUTING -p tcp --dport 23000 -j MASQUERADE`\n\nOn the other end (say 10.0.1.7) use a telnet chat client such as the [modified colrdx for KST](https://github.com/f4exb/colrdx) and connect using the one end's IP address and port 23000:\n  - `colrdx -c (callsign) -k 10.0.1.3 23000`\n\n# Details of the design\n## Multiple block handling\nThe CC1101 can transmit blocks up to 255 bytes. There is a so called \"Infinite block\" option but we don't want to use it here. In order to transmit larger blocks which is necessary for concatenated KISS frames or effective MTUs larger than 255 bytes we simply use a block countdown scheme. Each block has a header of two bytes:\n  - Byte 0 is the length of the actual block of data inside the fixed size block \n  - Byte 1 is a block countdown counter that is decremented at each successive block belonging to the same larger block to transmit. Single blocks are simply transmitted with a countdown of 0 and so is the last block of a multiple block group.\n\nWhen transmitting a sequence of blocks the first block is set to the result of the Euclidean division of the greater block size by the radio block size and it is decremented at each successive radio block to send until it reaches zero for the last block.\n\nAt the reception end the radio block countdown is checked and if it is not zero it will expect a next block with a countdown counter decremented by one until it receives a block with a countdown of zero.\n\nThis allows the transmission of greater blocks of up to 2^16 = 64k = 65536 bytes.\n\nIf any block is corrupted (bad CRC) or if its countdown counter is out of sequence then the whole greater block is discarded. This effectively puts a limit on the acceptable fragmentation depending on the quality of the link.\n\n## Mitigate AX.25/KISS spurious packet retransmissions\nIn the latest versions an effort has been made to try to mitigate unnecessary packet retransmissions. These are generally caused by fragmenting packet chains too early. In return the ACK from the other end is received too early and synchronization is broken. Because of its robust handshake mechanism TCP/IP eventually recovers but some time is wasted.\n\nTo mitigate this effect when a packet is received on the serial link if another packet is received before some delay expires it is concatenated to the previous packet(s). The packets are sent over the air after this delay or if a radio packet has been received. This delay is called the TNC serial window.\n\nThe same mechanism exists on the radio side to possibly concatenate radio packets before they are sent on the serial line. The corresponding delay is called the TNC radio window.\n\nThese delays can be entered on the command line with the following long options with arguments in microseconds. The defaults have proved satisfactory on a 9600 Baud 2-FSK with 252 byte packets transmission. You may want to play with them or tweak them for different transmission characteristics:\n  - `--tnc-serial-window`: defaults to 40ms. \n  - `--tnc-radio-window`: defaults to 0 that is no delay. Once the packet is received it will be immediately transfered to the serial link. At 9600 Baud 2-FSK with 250 byte packets the transmission time is already 208ms.\n  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ff4exb%2Fpicc1101","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ff4exb%2Fpicc1101","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ff4exb%2Fpicc1101/lists"}