{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mobilinkd M17 Setup Guide\n",
    "\n",
    "This is a guide on how to properly configure and use the Mobilinkd TNC3\n",
    "for M17 voice and data communication.\n",
    "\n",
    "This guide assumes that you will be using the TNC3 with a suitable\n",
    "9600-baud capable radio, and that you have the proper cable to\n",
    "connect the TNC3 to the radio.  It also assumes that you will be\n",
    "using the [M17-KISS-HT](https://github.com/mobilinkd/m17-kiss-ht)\n",
    "Android app for voice communications.\n",
    "\n",
    "The guide assumes familiarity with GNU Radio for the M17 receive\n",
    "tests.  And it assumes that you can side-load apps to your Android\n",
    "device.\n",
    "\n",
    "This is very much a guide for the experienced experimenter, and not\n",
    "a step-by-step guide designed for beginners.\n",
    "\n",
    "I will gladly accept pull requests for added detail for any of the\n",
    "sections below, or for setup hints for specific radio models.\n",
    "\n",
    "## Required Tools\n",
    "\n",
    " 1. An RTL-SDR (TCXO-based, or well-characterized) with antenna.\n",
    " 1. A Pluto SDR with accurate timebase (or other suitable transmit-capable SDR)\n",
    " 1. A Linux-based computer with working sound system\n",
    " 1. The `rtl-sdr` package installed, which contains `/usr/bin/rtl_fm`.\n",
    " 1. [m17-cxx-demod](https://github.com/mobilinkd/m17-cxx-demod) built for Linux\n",
    " 1. GQRX or other GUI-based software for viewing the spectrum by an RTL-SDR\n",
    " 1. A working GNU Radio installation with gr-iio (or sink for your SDR transmitter)\n",
    " 1. Android device running a recent version of Android (10 or greater)\n",
    " 1. The Mobilinkd Config App installed on the Android device\n",
    " 1. M17-KISS-HT installed on the Android device (must be side-loaded)\n",
    " 1. A USB-OTG adapter for the Android device, and an USB cable to connect to the TNC\n",
    " 1. A dummy load\n",
    " \n",
    "Please note that both SDRs will require accurate reference clocks.\n",
    "4-FSK requires reasonably accurate transmit and receive frequencies to\n",
    "be decoded properly.  If your SDR has a 20ppm clock, you can be off by\n",
    "8kHz on 70cm.  It will be impossible to tune the system properly with\n",
    "such an error.  The maximum error that will work is about 500Hz, and\n",
    "less than 100Hz is preferred. That's a 1ppm error, max, at 70cm.\n",
    "\n",
    "We will be connecting to the TNC via USB-OTG rather than over BLE\n",
    "as it been considerably more reliable.  The BLE connection has been\n",
    "unreliable on certain phones and Android versions.\n",
    "\n",
    "### Recommended Tools\n",
    "\n",
    " 1. RF filters for the transmit SDR\n",
    " 1. RF attenuators 20-40dB\n",
    " 1. Spectrum Analyzer\n",
    " 1. Cables and adapters that allow connecting the SDR to\n",
    "    the radio through an attenuator.\n",
    " \n",
    "## Overview\n",
    "\n",
    "We will be performing the following steps:\n",
    "\n",
    " 1. Configure the TX deviation of the TNC/radio pair\n",
    " 1. Configure the TX polarity of the TNC/radio pair\n",
    " 1. Run a TX BERT (bit error rate test)\n",
    " 1. Set up M17-KISS-HT\n",
    " 1. Configure the RX polarity of the TNC/radio pair\n",
    " 1. Run an RX BERT\n",
    " 1. Transmit and receive voice\n",
    "\n",
    "## Resources\n",
    "\n",
    " * TNC3 Firmware: https://github.com/mobilinkd/tnc3-firmware/releases\n",
    " * Mobilinkd Config App: https://play.google.com/store/apps/details?id=com.mobilinkd.tncconfig\n",
    " * M17 KISS HT Android App: https://github.com/mobilinkd/m17-kiss-ht/releases\n",
    " * M17 C++ Demodulator (m17-cxx-demod): https://github.com/mobilinkd/m17-cxx-demod/\n",
    "\n",
    "## Prep Work\n",
    "\n",
    "All of the detailed setup steps outlined in the sections below assume that\n",
    "this prep work has been completed.\n",
    "\n",
    " * Connect the radio to a suitable dummy load.\n",
    " * Install the M17 firmware (currently version 2.4.1) on the TNC3.\n",
    " * Install the Mobilinkd Config app on the Android device.\n",
    " * Side-load the M17 KISS HT app on the Android device.\n",
    " * Pair the Mobilinkd TNC3 with the Android Device.  Leave the TNC turned on.\n",
    " * Connect the TNC3 to the radio.\n",
    " * Turn on the radio and set it to the desired test frequency.\n",
    " * Connect the RTL-SDR with an antenna to the computer.\n",
    " * Connect the Pluto (with an antenna connected to the TX port) to the computer.\n",
    " * Install GQRX and GNU Radio if not already installed.\n",
    "\n",
    "\n",
    "### Configure the TNC3 for M17\n",
    "\n",
    "Open the Mobilinkd Config app, connect to the TNC, and go to *Modem Settings*.\n",
    "\n",
    "Select *M17 4-FSK* as the modem type.\n",
    "\n",
    "Select *Close*.\n",
    "\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-modem-settings.png\" alt=\"TNC3 modem settings for M17\" style=\"width: 300px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "\n",
    "Select *Save Settings*\n",
    "\n",
    "### Install and Build m17-cxx-demod\n",
    "\n",
    "Install the required libraries for m17-cxx-demod: boost-devel and codec2-devel.\n",
    "These may be named differently on your Linux platform.  `m17-cxx-demod` requires\n",
    "the `codec2` library and the `Boost program-options` library.\n",
    "\n",
    "Clone the m17-cxx-demod repo and build the M17 C++ tools.\n",
    "\n",
    "    git clone https://github.com/mobilinkd/m17-cxx-demod.git\n",
    "    cd m17-cxx-demod\n",
    "    mkdir build\n",
    "    cd build\n",
    "    cmake ..\n",
    "    make\n",
    "    make test\n",
    "\n",
    "## When Transmitting...\n",
    "\n",
    "Choose a test frequency that is unused and unlikely to interfere with\n",
    "other amateur radio users.\n",
    "\n",
    "You may have an obligation to announce your callsign on the frequency that\n",
    "you are transmitting on.  If you are conducting open-air tests using an\n",
    "antenna -- not via a dummy load or via direct coax connection between\n",
    "radios -- you should announce at the start of the test, as frequently\n",
    "as required by law, and when you are finished with the tests.\n",
    "\n",
    "## Mobilinkd Config App\n",
    "\n",
    "The *Audio Output Settings* of the Mobilinkd Config app was designed for\n",
    "configuring 1200 baud AFSK audio levels.  There are tone settings for\n",
    "1200Hz, 2200Hz, and Both.  Those settings are mapped as follows when\n",
    "the TNC is in M17 mode:\n",
    "\n",
    " * 1200Hz -> 2400Hz (M17 Preamble)\n",
    " * 2200Hz -> 1000Hz (M17 Deviation Aid)\n",
    " * BOTH -> M17 BER Mode.\n",
    "\n",
    "BER mode implements the M17 BER testing specification.\n",
    "\n",
    "## Transmit Deviation\n",
    "\n",
    "This section assumes that you have completed the [Prep Work](#Prep-Work) steps above.\n",
    "\n",
    "**NOTE:** The preferred way to do this is with a spectrum analyzer instead of an\n",
    "RTL-SDR and GQRX.  Use an appropriately sized attenuator between the radio and the\n",
    "instrument.  Set the span to 50kHz and the RBW to 300Hz.  Follow the output\n",
    "adjustment procedure below.\n",
    "\n",
    "Start `GQRX` and tune to the desired frequency.  The examples below use\n",
    "144.910MHz for the test frequency.\n",
    "\n",
    "In the *Input Controls* tab, set the appropriate frequency correction factor\n",
    "for your RTL-SDR.  If you are not using an accurate TCXO, it must be set very\n",
    "close to the PPM offset of your RTL-SDR.  You need to be within 1PPM.\n",
    "\n",
    "In the *Receiver Options* tab, select Narrow FM in the *Mode* setting.  Select\n",
    "the \"...\" to the right of the *Mode* selection.  Set the maximum deviation to\n",
    "2.5kHz and the Tau factor to 0.\n",
    "\n",
    "In the *FFT Settings* tab, use the *Freq Zoom* slider to increase the zoom\n",
    "factor to 10-20x.  You may need to adjust this later while testing to get the\n",
    "best view.\n",
    "\n",
    "Start the receiver using *Play* button.\n",
    "\n",
    "Open the Mobilinkd Config app on the Android device, connect to the TNC,\n",
    "then select *Audio Output Settings*.  Select the *2200Hz* for the *Output Tone*.\n",
    "When in M17 mode, this will transmit a 1000Hz tone.  A 1000Hz tone will create\n",
    "the first Bessel null at 2405Hz deviation.  This is very close to the value\n",
    "needed for M17.\n",
    "\n",
    "Press the *Transmit* button.  Observe the received spectrum in *GQRX*.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-audio-output.png\" alt=\"TNC3 audio output for M17\" style=\"width: 300px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "Adjust the output level until you see carrier (the middle peak) dip to its\n",
    "lowest point.  It may require careful adjustment of the slider on the app\n",
    "as it was not really designed for such small adjustments that are required\n",
    "here.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-bessel-null.png\" alt=\"GQRX Bessel null for M17\" style=\"width: 600px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "After the output setting has been adjusted to the desired level, press the\n",
    "*Transmit* button to stop transmitting.  Press *Close* to go back to the\n",
    "main menu, then select *Save Settings*.\n",
    "\n",
    "Press the *Play* button in *GQRX* to stop the receiver.  You can now exit *GQRX*.\n",
    "\n",
    "## Configure TX Polarity\n",
    "\n",
    "This section assumes that you have completed the [Prep Work](#Prep-Work) steps above. \n",
    "\n",
    "We are going to run rtl_fm and m17-cxx-demod to receive and decode M17 from the\n",
    "TNC and radio.  The TNC will sent a BER (bit error-rate) test sequence.\n",
    "\n",
    "Inside the `m17-cxx-demod/build` directory from earlier, run the following command:\n",
    "\n",
    "    rtl_fm -F 9 -f 144.91M -s 18k | sox -t s16 -r 18k -c1 - -t raw - gain 9 rate -v -s 48k | ./apps/m17-demod -d -l > /dev/null\n",
    "\n",
    "You may need to set a `\"-p\"` option value for `rtl_fm` to adjust for the\n",
    "clock error on your RTL-SDR dongle.\n",
    "\n",
    "Using a wide screen is best since it will output a wide diagnostics line.  If the\n",
    "terminal window is too narrow, it will scroll endlessly and be hard to read.  A\n",
    "width of 160 characters is about right.\n",
    "\n",
    " * Open the *Mobilinkd Config App* on the Android device.\n",
    " * Connect to the TNC.\n",
    " * Open *Audio Output Settings*.\n",
    " * Select *Both* for the *Output Tone*.  This will send a BER test sequence.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-tx-ber-test.png\" alt=\"M17 BER test for TX Polarity\" style=\"width: 300px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "Observe the results from the `m17-demod` program in the terminal window.  A\n",
    "good result will look something like this:\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-ber-test-2.png\" alt=\"M17 BER test for TX Polarity (good)\" style=\"width: 600px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "If, instead, you see something like the below result showing a high BER rate\n",
    "(typically 80+), you likely need to change the polarity.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-ber-test-1.png\" alt=\"M17 BER test for TX Polarity (bad)\" style=\"width: 600px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "Stop transmitting, close the *Audio Output Settings* and open *Modem Settings*.\n",
    "Enable the *TX Reverse Polarity* option.  Then repeat the BER test above.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-tx-reverse-polarity.png\" alt=\"M17 setting TX Reverse Polarity\" style=\"width: 300px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "Stop transmitting. If the results look good after changing the polarity, go\n",
    "back to the main menu and press *Save Settings*.\n",
    "\n",
    "If the results are still bad, check the frequency settings used on the radio and\n",
    "on the command-line for `rtl_fm`.  Verify the PPM settings on the RTL-SDR.  Ensure\n",
    "that your radio's VCO is properly calibrated and that it is transmitting and\n",
    "receiving at the proper frequency.\n",
    "\n",
    "You can also reach out to #public-chat on the M17 Discord for help.\n",
    "\n",
    "In the Mobilindk Config app, press the *Disconnect* button to disconnect from\n",
    "the TNC.\n",
    "\n",
    "## M17 KISS HT\n",
    "\n",
    "This section assumes that you have completed the [Prep Work](#Prep-Work) steps\n",
    "above, including side loading of the *M17 KISS HT* app.\n",
    "\n",
    " * Ensure that there is no existing connection to the TNC.\n",
    " * Connect the USB cable to the USB OTG adapter.\n",
    " * Plug the USB OTG adapter into the Android device.\n",
    " * Plug the USB cable into the Mobilinkd TNC.\n",
    "\n",
    "You should be presented with a dialog to open the connection with an app.\n",
    "Choose the *M17 HT* app.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-usb-connection.png\" alt=\"M17 TNC USB Connection\" style=\"width: 300px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "The first thing you need to do in order to use the app is to set your\n",
    "callsign.  This can include a suffix designator.  Here you see that I\n",
    "chose \"WX9O-8\" to distinguish this connection.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-kiss-ht-callsign.png\" alt=\"M17 KISS HT Callsign\" style=\"width: 300px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "### Voice Transmission\n",
    "\n",
    "We are going to run the m17-cxx-demod program again, this time taking the\n",
    "demodulated output and sending it to the computer's sound system.\n",
    "\n",
    "    rtl_fm -F 9 -f 144.91M -s 18k | sox -t s16 -r 18k -c1 - -t raw - gain 9 rate -v -s 48k | ./apps/m17-demod -d -l | play -b 16 -r 8000 -c1 -t s16 -\n",
    "\n",
    "This is the same command used for BER testing and setting up the TX polarity,\n",
    "except we are now piping the output to the computer's audio output.\n",
    "\n",
    "Press the transmit button on the M17 HT app. The Transmit button can act\n",
    "like a toggle button or a push button. A short press locks the transmit\n",
    "button.  Another short press disengages the transmit button.  If instead you\n",
    "hold the button for longer than 1/2 second, it acts as a push button and will\n",
    "stop transmitting as soon as you release the button.\n",
    "\n",
    "Press the transmit button, speak, then release the transmit button.  It is\n",
    "likely that you will hear a long delay before the received audio plays.  This\n",
    "is because the pipeline used in the command above has high latency due to\n",
    "the buffers in each stage of the pipeline.\n",
    "\n",
    "You should hear your voice and see something like this in the terminal window.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-ht-voice-transmit.png\" alt=\"M17 KISS Voice Transmit Test\" style=\"width: 600px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "Notice that the callsign you entered into the M17 HT app was decoded.\n",
    "\n",
    "The long audio delay can be reduced somewhat by using `stdbuf`.  This makes the\n",
    "command-line a bit unwieldy.\n",
    "\n",
    "    stdbuf -o0 rtl_fm -F 9 -f 144.91M -s 18k | stdbuf -i0 -o0 sox --buffer 24 -t s16 -r 18k -c1 - -t raw - gain 9 rate -v -s 48k | stdbuf -i0 -o0 ./apps/m17-demod -d -l -b | stdbuf -i0  play --buffer 24 -q -b 16 -r 8000 -c1 -t s16 -\n",
    "\n",
    "### M17 BER Receive Test\n",
    "\n",
    "For this test you will need the `m17-gnuradio` repo cloned.\n",
    "\n",
    "**NOTE:** If you are using an SDR other than an ADALM Pluto, please\n",
    "verify that the output polarity is correct first by attempting to\n",
    "receive it using the method outline in [Configure TX Polarity](#Configure-TX-Polarity).\n",
    "\n",
    "Set up your ADALM Pluto or other transmit-capable SDR.  Install any required\n",
    "filters and transmit antenna.  If you can, connect the SDR to the radio\n",
    "under test through a 30dB or 40dB attenuator.  *Be very careful if you do\n",
    "connect the SDR to the radio because it is very easy to damage the SDR\n",
    "if the radio transmits.*\n",
    "\n",
    "Open *GNU Radio Companion* (GRC) and within that, open the `m17-bert.grc` file.\n",
    "Adjust the output sink paramters (including the frequency) for the test.  You\n",
    "may need to adjust the pathnam in the *File Source* block so that the `bert.bin` \n",
    "file can be found.  The path is typically relative to your HOME directory.\n",
    "\n",
    "Once done, click the *Play* button on GRC. It should start transmitting a\n",
    "BER test sequence similar to the one transmitted by the Mobilinkd Config app.\n",
    "\n",
    "Connect the TNC to the Android device via the USB-OTG connection used earlier.\n",
    "Once connected, the TNC should start receiving the BER test sequence.  It is\n",
    "likely that you will see some error if you start receiving in the middle of\n",
    "the test sequence.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-rx-ber-test.png\" alt=\"M17 KISS BER Test\" style=\"width: 300px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "If you do not see the app go into BER test mode, you will need to troubleshoot\n",
    "the issue.\n",
    "\n",
    " 1. Verify that the receive indicator on the TNC is green.  If not, check the\n",
    "    transmit frequency and transmit power levels.  Check the radio's receive\n",
    "    frequency is correct and that it is not set for a repeater split.\n",
    " 1. If the receive indicator is green, disconnect the USB OTG cable from\n",
    "    the Android device.  Open the Mobilinkd Config app. Connect to the TNC.\n",
    "    Select *Modem Settings*, then enable `RX Reverse Polarity`. Press *Close*\n",
    "    and then *Save Settings*.  Repeat the experiment.\n",
    " 1. Try reducing the attenuation in the *PlutoSDR Sink* block.\n",
    "\n",
    "### Voice Reception\n",
    "\n",
    "The voice reception test is quite similar to the BER test above.  It is another\n",
    "GNU Radio flowgraph that transmits a long-form English language voice program\n",
    "for amateur radio.\n",
    "\n",
    "This assumes the ADALM Pluto, radio and TNC are configured the same as with\n",
    "the BER Receive Test.  If it is not, follow the setup steps in that section.\n",
    "\n",
    "Open *GNU Radio Companion* (GRC) and within that, open the `m17-arn.grc` file.\n",
    "Adjust the output sink paramters (including the frequency) for the test.  You\n",
    "may need to adjust the pathnam in the *File Source* block so that the `Report2288.bin` \n",
    "file can be found.  The path is typically relative to your HOME directory.\n",
    "\n",
    "Connect the TNC to the Android device via the USB-OTG connection used earlier.\n",
    "This should start the M17 HT app.\n",
    "\n",
    "Click the *Play* button on GRC. It will start transmitting a voice program,\n",
    "which you should hear being received on the Android device.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/m17-rx-voice-test.png\" alt=\"M17 KISS HT Voice Receive Test\" style=\"width: 300px;\"/> </td>\n",
    "  </tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# M17 Radio Configuration Hints\n",
    "\n",
    "Add instructions and hints for configuring various radios for use with M17 below."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Yaesu FT-991\n",
    "\n",
    "This section outlines set up steps and some issues with the Yeasu FT-991.\n",
    "\n",
    "### Radio Setup Steps\n",
    "\n",
    "Press the *Menu* button and adjust the following settings to use the packet data port for M17:\n",
    "\n",
    " * Set `75 FM OUT LEVEL` to `100`\n",
    " * Set `76 FM PKT PTT SELECT` to `DAKY`\n",
    " * Set `77 FM PKT PORT SELECT` to `DATA`\n",
    " * Set `78 FM PKT TX GAIN` to `64`\n",
    " * Set `79 FM PKT MODE` to `9600`\n",
    " \n",
    "Press the *Menu* button again to go back to the main screen.\n",
    "\n",
    "Press the *Mode* button and select `DATA-FM`.  Press *Mode* again to go back to the main screen.\n",
    "\n",
    "### TNC Setup Steps\n",
    "\n",
    "In *Audio Input Settings*, set the `Input Gain` value to 3.\n",
    "\n",
    "In *Modem Settings*, enable the `TX Reverse Polarity` option for this radio.\n",
    "\n",
    "### Known Issues\n",
    "\n",
    "#### Low Output Level\n",
    "\n",
    "The demodulated baseband signal from the *DATA-FM* mode is very low.  It\n",
    "is an order of magnitude lower than in pure *FM* mode.  There is a lot of\n",
    "high-frequency noise in the signal.\n",
    "\n",
    "#### Frequency Stability\n",
    "\n",
    "On my unit, the frequency stability when it first starts transmitting is rather poor.\n",
    "\n",
    "<table>\n",
    "  <tr>\n",
    "    <td> <img src=\"images/wobbly-freq-accuracy.png\" alt=\"FT-991 wobbly frequency\" style=\"width: 600px;\"/> </td>\n",
    "  </tr>\n",
    "</table>\n",
    "\n",
    "Note the wobbly lines at the start of the transmission.  This lasts for a few\n",
    "seconds.  It can cause a burst of bit errors at the start of the transmission."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
