The transmit side is designed to run on a Raspberry Pi, and the UART (/dev/ttyAMA0) is used to modulate a RFM98W (yes, a LoRa module) in direct-asynchronous mode. I expect other transmitters could probably be used (i.e. NTX2's or similar) at lower bandwidths.
*`rx/rx_ssdv.py` - Reads in received packets (256 byte SSDV frames) via stdin, and decodes them to JPEGs. Also informs other processes (via UDP broadcast) of new ssdv and telemetry data.
*`rx/rx_gui.py` - Displays last received image, as commanded by rx_ssdv.py via UDP.
*`tx/init_rfm22b.py` - Set RFM22B (attached via SPI to the RPi) into Direct-Asynchronous mode.
*`tx/init_rfm98w.py` - Set RFM98W (attached via SPI to the RPi) into Direct-Asynchronous mode.
*`tx_picam_gps.py` - Captures pictures using the PiCam, overlays GPS data and transmits them.
* Run either `python WenetPiCam.py (might need sudo to access camera & SPI) or `python tx_test_images.py` on the transmitter Raspberry Pi. There's also a start_tx.sh bash script which also sets up a RFM22B or RFM98W. I run this bash script from /etc/rc.local so it starts on boot.
* While the transit code requests an output baud rate of 115200 baud from the RPi's UART, the acheived baud rate (due to clock divisors) on a RPi A+ is actually 115386.843 baud (measured using a frequency counter). All of the resampling within the receive chain had to be adjusted accordingly, which means CPU-intensive fractional decimators.
* Baud rates on other RPi models may be different - best to measure and check!
* Apparently the newer Raspberry Pi's (or possibly just a newer version of Raspbian) use the alternate UART hardware by default, which has a smaller transmit buffer. This may result in gaps between bytes, which will likely throw the rx timing estimation off.
* A few example gnuradio-companion flow-graphs are in the `grc` directory, for different SDRs. These receive samples from the SDR, demodulate a 500KHz section of spectrum as USB, resamples them to fsbaud*8 (which fsk_demod requires), then presents these samples via a TCP sink, which is acting as a TCP server. You will probably need to modify these to set the appropriate receive frequency.
* To receive the FSK data and display the images 'live', run:
* In another terminal: `python rx_gui.py`, which will listen via UDP for new images to display.
This mess of a command line (bash piping, yay!) receives samples from the rtlsdr, filters out the upper 'sideband' of the received bandwidth, then throws away the imaginary part and convert to 16-bit shorts. The signal is then fed into fsk_demod (the FSK modem). Debug output (on stderr) from the modem is piped into a python GUI), while the received soft-decision 'bits' are piped into drs232_ldpc, which does de-framing and LDPC error correction. Packets which pass checksum are then passed onto the rx_ssdv.py python utility for assembly into images.
On my flights the centre frequency of the transmitter is around 441.2 MHz, so I tune the RTLSDR to just below 441 MHz to sit the signal roughly in the middle of the passband.
* It is highly recommended to use a preamplifier in front of your RTLSDR to lower the overall noise figure of the system. With a NooElec RTLSDR (R820T2 Tuner) and a [HabAmp](https://store.uputronics.com/index.php?route=product/product&product_id=53), we were able to achieve a Minimum-Detectable-Signal (MDS - which we defined as the point where we get no packet errors) of around -112 dBm.
* If needed, the transmit bitrate can be slowed down by editing the defaults in tx_picam.py. You will then have to determine the appropriate parameters for fsk_demod and the preceding filtering/resampling chain.