When I started experimenting with LoRa, I wasn’t sure it would thrill me (it did!), so I was looking for a minimal cost setup, without investing too much in hardware.
In studying the possible solutions, I stumbled upon the Austrian LoRa OM site and found that there were schematics available for a very compact tracker that could also act as a Gateway.
However, the funniest idea was to integrate the Lora with the 144.800VHF network already present on my digi / I-gate of which I am sysop, to create a cross-band and cross-protocol digipeater between VHF FSK1200baud and UHF LoRa.
Still on the Austrians’ website, I discovered that there is a Software Modem that was created to interface with aprx, the software I have been using on my digipeater for over 10 years and which still remains one of the most versatile in the APRS field.
This configuration requires that the software that implements the TNC (in this case RPi-LoRA-KISS-TNC) and the software that takes charge of the packets to and from the TNC and then manages them according to the APRS protocol (in this case aprx) are connected to each other through the KISS protocol encapsulated in TCP-IP.
Using a tcp-ip link, the possible scenarios are the following:
- Aprx (or equivalent) and RPi-LoRa-KISS-TNC installaed on the same host and linked by loopback 127.0.0.1:

Aprx (or equivalent) and RPi-LoRa-KISS-TNC installed on different hosts and maybe even distant from each other (interesting configuration):

My case is the first, that is software that run on the same raspberry, so a port of this type must be declared in the aprx.conf file:

The port must obviously be the same as the one declared in config.py of the RPi-LoRa-KISS-TNC.
I therefore decide to take this path and order an RFW96 module from aliexpress, to connect it to the raapberry SPI as indicated on the software installation how-to. After about 3 weeks, a couple of LoRa modules arrive from China. Unfortunately the Lora module has a very narrow pitch pinout, incompatible with the 2.54mm standard, so the ideal would be to use an adapter PCB. I ask the “IOT4PI” group for the PCB that was created for this purpose, but they tell me that they no longer have it available, so I decide to connect it to the raspy in a flying way. I proceed with some simple pieces of prototype jumpers (female square pins) and I can wire the LoRa module towards the raspberry following the Austrian scheme. I manage to solder a thin Teflon cable on the pads of the antenna output, and at the other end of the coax cable I fix a flying SMA. In the photo below the final result.





Both the software and the hardware worked immediately and I started conducting the first tests that immediately showed me the potential of this protocol. During the first period of experimentation I also had the opportunity to find and solve some small bugs on the software and to start communicating constructively with TOM, the author of the Software.
After this first phase, I came into contact with the Italian group SARIMESH, very active in the Lora experimentation, which has as its reference the very kind OM Michele I8FUC.
I learned that Sarimesh set their software to be compatible with both that of the Austrian group (baptizing it “OE_style”) and with the standard ax25. The idea is more than acceptable, because we should always avoid proprietary protocols and stick to the standard ones. However it must always be considered that the speed of the Lora is low and the ax25 produces a slight data overhead, so this trade-off is always in question.
From the need to maintain the ax25, the idea of expanding the RPi-LoRa-KISS-TNC was born.
During the first stages of debugging, I had already had the opportunity to understand the structure of the code written entirely in python and luckily Tom had also added some comments that made my work easier. Editing was easy enough and only took me a few hours of time.
The discrimination of the received packet is based on a packet header which was chosen by the Austrian OMs as their standard identifier, and consists of the 3 bytes “0x3C 0xFF 0x01”. Once I have received the packet, I check for the presence of this header. If present, then it is an “OE_Style” package to be processed with the functions already present in the code, otherwise it is a standard AX25 package.
To learn more about the structure of a standard AX25 frame, in addition to reading the protocol, I also recommend reading this excellent article, which also has a simulator that builds the frame in real time starting from editable fields.
Here below, a typical structure of a kiss frame is reported:

In case of ax25 package, the job is very simple: you take the package and encapsulate it in KISS.
KISS is a very simple protocol. In our case, what I do is simply:
- Add at the beginning and at the end a byte “0xC0” of Frame start and Frame End;
- After the first Start byte, I add a “0x00” byte. This packet is divided into two nibbles: the most significant is the port number (in the case of a single TNC it is “0”), while the least significant is the command. Again from the protocol, we see that the command “0” is the one that must always precede a data frame when it is passed from the tnc to the user. So basically this byte is always “0x00”.
- Vice versa, the packet to be transmitted in Lora is received by the software, de-encapsulated by the kiss (thus eliminating the delimiters and the “0x00” byte described above) and transmitted as it is via LoRa RF.
While making these changes, I have also implemented these improvements:
- Brought all the Lora configuration parameters (sync word, bandwidth, spread factor, preamble lenght, power, etc ..) into the config.py configuration file. Before, the parameters were hidden inside the code and it was a bit difficult to find them without a minimum of programming skills.
- Added a printout of all these parameters at the start of the software, which is always useful to remind the user in what conditions the tnc was started.
- Added printouts of the source call and the destination call of the standard ax25 packages, using the functions already present in the code.
- Added log files to log both RF packets and system messages.
The configuration file is commented as much as possible to avoid user errors. A note on the “TX_OE_Style” parameter: it is a Boolean (therefore it can only assume a True / False status) which determines the transmission format. While in reception the TNC accepts both OE / ax25 formats, obviously in transmission we must necessarily choose one of the two, and this is done with this parameter.
Another obvious consideration: the parameters of the LoRa protocol (sync word, spread factor, etc.) will be the same in the case of OE_Style or ax25 packets, and it is not possible to differentiate them because the LoRa module only accepts a set of parameters to be initialized.
Here below, an example of cofig file:

You must also be careful to declare a valid path for the log files, and with the right write permissions, otherwise the software will fail on startup.
Below you will find some example screens in the various operating phases.
The following is the start-up screen with all the initialization parameters. Note the string announcing the successful connection between RPi-KISS-TNC and the client software, in this case APRX.

The following, is an ax25 packet receiver via KISS-TCP and transmitted by LoRa interface:

Here below, a OE_style packet riceived by LoRa channel and passed to aprx via KISS-TCP:

The previous packet (OE_style) received by aprx via KISS-TCP:

Packet received via LoRa in ax25 fromat and passed to aprx via KISS-TCP:

Here below, you can see as the austrian tracker is correctly receiving a beacon originated by aprx , passet to RPi-LoRa-KISS-TNC by KISS-TCP and transmitted o LoRa channel:

So far the software is behaving stably and has never crashed. Obviously anyone who wants to try it, test it and possibly contribute to the development with code modification or suggestions, is welcome!
The source is available on my github. The installation is described in the INSTALL.md file and is fairly straightforward. It plans to download, using the “git clone” command, the content from github to a local folder of the raspberry, and to download the python libraries of the LoRa module in a subfolder.
ATTENTION !: install.md says to go and modify the content of the pySX127x / SX127x / board_config.py file and change the mapping of one of the GP / IO pins of the raspberry dedicated to interfacing with the LoRa module :

This modification is in line with the connections provided in the wiring diagram, but there is nothing to prevent the original mapping from being changed, always consistently with the diagram, as long as the GP/IO lines are free and not used by other processes.
Take care also of the log files, which can become big. Configure logrotate for a correct storing strategy.
The log files are very useful because they store also corrupted packets which are not passed to and from aprx, but sometimes contain useful information.
I want to thank the original author, Tom OE9TKH who was the first creatorof the Software I expanded.
Have fun with LoRa.
73’s
Alfredo IZ7BOJ