kopia lustrzana https://github.com/projecthorus/wenet
Initial re-structure of repository.
rodzic
0625dfc5d1
commit
5002745874
|
|
@ -62,6 +62,7 @@ If not already done above, you will also need to clone the wenet repository:
|
|||
> git clone https://github.com/projecthorus/wenet.git
|
||||
|
||||
We need some binaries from the codec2-dev repository:
|
||||
(Note that we are using a specific revision number to ensure developmental changes don't break things.)
|
||||
|
||||
> svn checkout -r 2914 http://svn.code.sf.net/p/freetel/code/codec2-dev/
|
||||
> cd codec2-dev
|
||||
|
|
@ -69,11 +70,11 @@ We need some binaries from the codec2-dev repository:
|
|||
> cd build
|
||||
> cmake ../
|
||||
> make
|
||||
> cp src/fsk_demod ~/wenet/
|
||||
> cp src/drs232_ldpc ~/wenet/
|
||||
> cp src/fsk_demod ~/wenet/rx/
|
||||
> cp src/drs232_ldpc ~/wenet/rx/
|
||||
|
||||
We also need to copy out the FSK Demod GUI Utility from this repository
|
||||
> cp ~/codec2-dev/octave/fskdemodgui.py ~/wenet/
|
||||
> cp ~/codec2-dev/octave/fskdemodgui.py ~/wenet/rx/
|
||||
|
||||
|
||||
CALLSIGN AND SHORTCUTS SETUP
|
||||
|
|
@ -91,7 +92,7 @@ If you are using a RTLSDR V3 and need the bias-tee enabled, uncomment the marked
|
|||
|
||||
Next, copy the two .desktop files to your desktop by running:
|
||||
|
||||
> cp *.desktop ~/Desktop/
|
||||
> cp rx/*.desktop ~/Desktop/
|
||||
|
||||
If your username is somethign other than 'wenet', you will need to edit the Start_SSDV.desktop file,
|
||||
so that the 'Exec='' line contains the correct path to start_rx.sh
|
||||
|
|
@ -115,6 +116,7 @@ You can kill all the RX processed by running the 'Kill RX' shortcut on the deskt
|
|||
If you have a recorded sample, you can replay it by doing:
|
||||
|
||||
Opening the SSDV Viewer GUI by running:
|
||||
> cd rx
|
||||
> python rx_gui.py &
|
||||
|
||||
Then 'playback' the sample file using:
|
||||
|
|
|
|||
|
|
@ -3,13 +3,16 @@
|
|||
# Receiver Test Script.
|
||||
# Feeds a list of test images into the receiver code, via stdout/stdin.
|
||||
#
|
||||
# Run using:
|
||||
# python rx_tester.py | python rx_ssdv.py
|
||||
#
|
||||
# Mark Jessop <vk5qi@rfhead.net>
|
||||
#
|
||||
|
||||
import time, sys, os
|
||||
|
||||
# Set to whatever resolution you want to test.
|
||||
file_path = "./test_images/%d_raw.ssdv" # _raw, _800x608, _640x480, _320x240
|
||||
file_path = "../test_images/%d_raw.ssdv" # _raw, _800x608, _640x480, _320x240
|
||||
image_numbers = xrange(1,14)
|
||||
|
||||
print_as_hex = False
|
||||
24
start_rx.sh
24
start_rx.sh
|
|
@ -1,14 +1,32 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Start RX using a rtlsdr.
|
||||
# Wenet RX-side Initialisation Script
|
||||
# 2016-12-05 Mark Jessop <vk5qi@rfhead.net>
|
||||
#
|
||||
# This assumes an RTLSDR will be used for RX.
|
||||
#
|
||||
|
||||
# Set CHANGEME to your callsign.
|
||||
MYCALL=CHANGEME
|
||||
|
||||
cd ~/wenet/
|
||||
# Change the following path as appropriate.
|
||||
# If running this from a .desktop file, you may need to set an absolute path here
|
||||
# i.e. /home/username/wenet/rx/
|
||||
cd ~/wenet/rx/
|
||||
|
||||
# Start up the SSDV Uploader script and push it into the background.
|
||||
python ssdv_upload.py $MYCALL &
|
||||
|
||||
# Start the SSDV RX GUI.
|
||||
python rx_gui.py &
|
||||
|
||||
# Uncomment the following line if using a V3 RTLSDR and need the Bias-Tee enabled.
|
||||
# rtl_biast -b 1
|
||||
rtl_sdr -s 923096 -f 440980000 -g 35 - | csdr convert_u8_f | csdr bandpass_fir_fft_cc 0.05 0.45 0.05 | csdr realpart_cf | csdr gain_ff 0.5 | csdr convert_f_s16 | ./fsk_demod 2XS 8 923096 115387 - - S 2> >(python fskdemodgui.py --wide) | ./drs232_ldpc - - -vv| python rx_ssdv.py --partialupdate 16
|
||||
|
||||
# Start up the receive chain.
|
||||
rtl_sdr -s 923096 -f 440980000 -g 35 - | csdr convert_u8_f | \
|
||||
csdr bandpass_fir_fft_cc 0.05 0.45 0.05 | csdr realpart_cf | \
|
||||
csdr gain_ff 0.5 | csdr convert_f_s16 | \
|
||||
./fsk_demod 2XS 8 923096 115387 - - S 2> >(python fskdemodgui.py --wide) | \
|
||||
./drs232_ldpc - - -vv | \
|
||||
python rx_ssdv.py --partialupdate 16
|
||||
|
|
|
|||
21
start_tx.sh
21
start_tx.sh
|
|
@ -1,10 +1,23 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Wenet TX-side Initialisation Script
|
||||
# 2016-08-07 Mark Jessop <vk5qi@rfhead.net>
|
||||
# 2016-12-05 Mark Jessop <vk5qi@rfhead.net>
|
||||
#
|
||||
# Run this to set up an attached RFM22B and start transmitting!
|
||||
# Run this to set up an attached RFM22B/RFM98W and start transmitting!
|
||||
# Replace the transmit frequency and callsign with your own.
|
||||
#
|
||||
python init_rfm22b.py 441.200
|
||||
python tx_picam.py VK5QI &
|
||||
|
||||
MYCALL=N0CALL
|
||||
TXFREQ=441.200
|
||||
|
||||
# CHANGE THE FOLLOWING LINE TO REFLECT THE ACTUAL PATH TO THE TX FOLDER.
|
||||
# i.e. it may be /home/username/dev/wenet/tx/
|
||||
cd ~/wenet/tx/
|
||||
|
||||
#Uncomment to initialise a RFM22B
|
||||
python init_rfm22b.py $TXFREQ
|
||||
# Uncomment for use with a RFM98W
|
||||
#python init_rfm98w.py $TXFREQ
|
||||
|
||||
# Start the main TX Script.
|
||||
python tx_picam.py $MYCALL &
|
||||
|
|
|
|||
|
|
@ -31,4 +31,4 @@ new_sizes.append("raw")
|
|||
|
||||
for x in image_numbers:
|
||||
for size in new_sizes:
|
||||
os.system("ssdv -e -c %s -i %d %d_%s.jpg %d_%s.ssdv" % (callsign,x,x,size,x,size))
|
||||
os.system("ssdv -e -n -q 6 -c %s -i %d %d_%s.jpg %d_%s.ssdv" % (callsign,x,x,size,x,size))
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2.7
|
||||
#
|
||||
# Serial Packet Transmitter Class
|
||||
# Wenet Packet Transmitter Class
|
||||
#
|
||||
# Frames packets (preamble, unique word, checksum)
|
||||
# and transmits them out of a serial port.
|
||||
#
|
||||
# RPI UART Calibration
|
||||
# 9600 -> 9600.1536
|
||||
# RPI UART Calibration. Measured on a Rpi A+.
|
||||
# YMMV with other RPi models.
|
||||
#
|
||||
# 9600 -> 9600.1536
|
||||
# 19200 -> 19200.307
|
||||
# 38400 -> 38339.148
|
||||
# 57600 -> 57693.417
|
||||
|
|
@ -16,60 +18,73 @@
|
|||
#
|
||||
|
||||
|
||||
import serial,Queue,sys,crcmod,struct
|
||||
import serial
|
||||
import Queue
|
||||
import sys
|
||||
import crcmod
|
||||
import struct
|
||||
from time import sleep
|
||||
from threading import Thread
|
||||
import numpy as np
|
||||
from ldpc_encoder import *
|
||||
|
||||
# Alternate output module, which writes transmitted data as one-bit-per-char (i.e. 0 = 0x00, 1 = 0x01)
|
||||
# to a file. Very useful for debugging.
|
||||
class BinaryDebug(object):
|
||||
def __init__(self):
|
||||
self.f = open("debug.bin",'wb')
|
||||
|
||||
def write(self,data):
|
||||
# TODO: Add in RS232 framing
|
||||
raw_data = np.array([],dtype=np.uint8)
|
||||
for d in data:
|
||||
d_array = np.unpackbits(np.fromstring(d,dtype=np.uint8))
|
||||
raw_data = np.concatenate((raw_data,[0],d_array[::-1],[1]))
|
||||
|
||||
self.f.write(raw_data.astype(np.uint8).tostring())
|
||||
|
||||
def close(self):
|
||||
self.f.close()
|
||||
|
||||
def write_debug_message(message, debug_file = "tx_idle_message.txt"):
|
||||
#f = open(debug_file,'w')
|
||||
#f.write(message)
|
||||
#f.close()
|
||||
print("DEBUG MSG: %s" % message)
|
||||
|
||||
class PacketTX(object):
|
||||
txqueue = Queue.Queue(4096) # Up to 1MB of 256 byte packets
|
||||
transmit_active = False
|
||||
debug = False
|
||||
""" Packet Transmitter Class
|
||||
|
||||
The core of the Wenet transmitter stack.
|
||||
This class handles framing, FEC, and transmission of packets via a
|
||||
serial port.
|
||||
|
||||
Intended to be used with the David Rowe's fsk_demod software, with receiver
|
||||
glue code available in the 'rx' directory of this repository.
|
||||
|
||||
Packet framing is as follows:
|
||||
Preamble: 16 repeats of 0x55. May not be required, but helps with timing estimation on the demod.
|
||||
Unique Word: 0xABCDEF01 Used for packet detection in the demod chain.
|
||||
Packet: 256 bytes of arbitrary binary data.
|
||||
Checksum: CRC16 checksum.
|
||||
Parity bits: 516 bits (zero-padded to 65 bytes) of LDPC parity bits, using a r=0.8 Repeat-accumulate code, developed by
|
||||
Bill Cowley, VK5DSP. See ldpc_enc.c for more details.
|
||||
|
||||
Packets are transmitted from two queues, named 'telemetry' and 'ssdv'.
|
||||
The 'telemetry' queue is intended for immediate transmission of low-latency telemetry packets,
|
||||
for example, GPS or IMU data. Care must be taken to not over-use this queue, at the detriment of image transmission.
|
||||
The 'ssdv' queue is used for transmission of large amounts of image (SSDV) data, and up to 4096 packets can be queued for transmit.
|
||||
|
||||
"""
|
||||
|
||||
# Transmit Queues.
|
||||
ssdv_queue = Queue.Queue(4096) # Up to 1MB of 256 byte packets
|
||||
telemetry_queue = Queue.Queue(16) # Keep this queue small. It's up to the user not to over-use this queue.
|
||||
|
||||
# Framing parameters
|
||||
unique_word = "\xab\xcd\xef\x01"
|
||||
preamble = "\x55"*16
|
||||
|
||||
# Idle sequence, transmitted if there is nothing in the transmit queues.
|
||||
idle_sequence = "\x55"*256
|
||||
|
||||
# Transmit thread active flag.
|
||||
transmit_active = False
|
||||
|
||||
def __init__(self,serial_port="/dev/ttyAMA0", serial_baud=115200, payload_length=256, fec=False, debug = False, callsign="N0CALL"):
|
||||
# WARNING: 115200 baud is ACTUALLY 115386.834 baud, as measured using a freq counter.
|
||||
# WARNING: 115200 baud is ACTUALLY 115386.834 baud, as measured using a freq counter.
|
||||
def __init__(self,serial_port="/dev/ttyAMA0", serial_baud=115200, payload_length=256, fec=True, debug = False, callsign="N0CALL"):
|
||||
|
||||
# Instantiate our low-level transmit interface, be it a serial port, or the BinaryDebug class.
|
||||
if debug == True:
|
||||
self.s = BinaryDebug()
|
||||
self.debug = True
|
||||
else:
|
||||
self.s = serial.Serial(serial_port,serial_baud)
|
||||
self.payload_length = payload_length
|
||||
|
||||
self.crc16 = crcmod.predefined.mkCrcFun('crc-ccitt-false')
|
||||
|
||||
self.payload_length = payload_length
|
||||
self.callsign = callsign
|
||||
self.idle_message = "DE %s" % callsign
|
||||
self.fec = fec
|
||||
|
||||
self.crc16 = crcmod.predefined.mkCrcFun('crc-ccitt-false')
|
||||
|
||||
def start_tx(self):
|
||||
self.transmit_active = True
|
||||
txthread = Thread(target=self.tx_thread)
|
||||
|
|
@ -96,23 +111,29 @@ class PacketTX(object):
|
|||
self.idle_message = self.frame_packet(temp_msg,fec=self.fec)
|
||||
|
||||
|
||||
# Either generate an idle message, or read one in from a file (tx_idle_message.txt) if it exists.
|
||||
# This might be a useful way of getting error messages down from the payload.
|
||||
def generate_idle_message(self):
|
||||
# Append a \x00 control code before the data
|
||||
return "\x00" + "DE %s: \t%s" % (self.callsign,self.idle_message)
|
||||
|
||||
|
||||
def tx_thread(self):
|
||||
""" Main Transmit Thread.
|
||||
|
||||
Checks telemetry and image queues in order, and transmits a packet.
|
||||
"""
|
||||
while self.transmit_active:
|
||||
if self.txqueue.qsize()>0:
|
||||
packet = self.txqueue.get_nowait()
|
||||
if self.telemetry_queue.qsize()>0:
|
||||
packet = self.telemetry_queue.get_nowait()
|
||||
self.s.write(packet)
|
||||
elif self.image_queue.qsize()>0:
|
||||
packet = self.image_queue.get_nowait()
|
||||
self.s.write(packet)
|
||||
else:
|
||||
if not self.debug:
|
||||
#self.s.write(self.idle_sequence)
|
||||
self.s.write(self.idle_message)
|
||||
else:
|
||||
# TODO: Tune this value. Ideally we should be doing a non-blocking
|
||||
sleep(0.05)
|
||||
|
||||
print("Closing Thread")
|
||||
|
|
@ -134,3 +155,23 @@ class PacketTX(object):
|
|||
|
||||
|
||||
|
||||
class BinaryDebug(object):
|
||||
""" Debug binary 'transmitter' Class
|
||||
Used to write packet data to a file in one-bit-per-char (i.e. 0 = 0x00, 1 = 0x01)
|
||||
format for use with codec2-dev's fsk modulator.
|
||||
Useful for debugging, that's about it.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.f = open("debug.bin",'wb')
|
||||
|
||||
def write(self,data):
|
||||
# TODO: Add in RS232 framing
|
||||
raw_data = np.array([],dtype=np.uint8)
|
||||
for d in data:
|
||||
d_array = np.unpackbits(np.fromstring(d,dtype=np.uint8))
|
||||
raw_data = np.concatenate((raw_data,[0],d_array[::-1],[1]))
|
||||
|
||||
self.f.write(raw_data.astype(np.uint8).tostring())
|
||||
|
||||
def close(self):
|
||||
self.f.close()
|
||||
|
|
@ -61,7 +61,7 @@ try:
|
|||
tx.set_idle_message("Converting Image to SSDV...")
|
||||
#os.system("convert temp.jpg -resize %s\! temp.jpg" % tx_resolution)
|
||||
# SSDV'ify the image.
|
||||
os.system("ssdv -e -n -c %s -i %d ./tx_images/%s.jpg temp.ssdv" % (callsign,image_id,capture_time))
|
||||
os.system("ssdv -e -n -q 6 -c %s -i %d ./tx_images/%s.jpg temp.ssdv" % (callsign,image_id,capture_time))
|
||||
# Transmit image
|
||||
print("Transmitting...")
|
||||
transmit_file("temp.ssdv",tx)
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
import PacketTX, sys, os
|
||||
|
||||
# Set to whatever resolution you want to test.
|
||||
file_path = "./test_images/%d_raw.ssdv" # _raw, _800x608, _640x480, _320x240
|
||||
file_path = "../test_images/%d_raw.ssdv" # _raw, _800x608, _640x480, _320x240
|
||||
image_numbers = xrange(1,14)
|
||||
|
||||
debug_output = True # If True, packet bits are saved to debug.bin as one char per bit.
|
||||
Ładowanie…
Reference in New Issue