kopia lustrzana https://github.com/projecthorus/wenet
Major ease-of-use updates, added start of non-SSDV message support.
rodzic
c2e41f775c
commit
023c8861d3
25
PacketTX.py
25
PacketTX.py
|
@ -44,7 +44,7 @@ class PacketTX(object):
|
||||||
idle_sequence = "\x55"*256
|
idle_sequence = "\x55"*256
|
||||||
|
|
||||||
|
|
||||||
def __init__(self,serial_port="/dev/ttyAMA0", serial_baud=115200, payload_length=256, fec=False, debug = 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.
|
||||||
if debug == True:
|
if debug == True:
|
||||||
self.s = BinaryDebug()
|
self.s = BinaryDebug()
|
||||||
|
@ -55,13 +55,14 @@ class PacketTX(object):
|
||||||
|
|
||||||
self.crc16 = crcmod.predefined.mkCrcFun('crc-ccitt-false')
|
self.crc16 = crcmod.predefined.mkCrcFun('crc-ccitt-false')
|
||||||
self.fec = fec
|
self.fec = fec
|
||||||
|
self.callsign = callsign
|
||||||
|
|
||||||
def start_tx(self):
|
def start_tx(self):
|
||||||
self.transmit_active = True
|
self.transmit_active = True
|
||||||
txthread = Thread(target=self.tx_thread)
|
txthread = Thread(target=self.tx_thread)
|
||||||
txthread.start()
|
txthread.start()
|
||||||
|
|
||||||
def frame_packet(self,packet):
|
def frame_packet(self,packet, fec=False):
|
||||||
# Ensure payload size is equal to the desired payload length
|
# Ensure payload size is equal to the desired payload length
|
||||||
if len(packet) > self.payload_length:
|
if len(packet) > self.payload_length:
|
||||||
packet = packet[:self.payload_length]
|
packet = packet[:self.payload_length]
|
||||||
|
@ -71,11 +72,24 @@ class PacketTX(object):
|
||||||
|
|
||||||
crc = struct.pack("<H",self.crc16(packet))
|
crc = struct.pack("<H",self.crc16(packet))
|
||||||
|
|
||||||
if self.fec:
|
if fec:
|
||||||
return self.preamble + self.unique_word + packet + crc + ldpc_encode_string(packet+crc)
|
return self.preamble + self.unique_word + packet + crc + ldpc_encode_string(packet+crc)
|
||||||
else:
|
else:
|
||||||
return self.preamble + self.unique_word + packet + crc
|
return self.preamble + self.unique_word + packet + crc
|
||||||
|
|
||||||
|
# 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):
|
||||||
|
# Try and read in a message from a file.
|
||||||
|
try:
|
||||||
|
f = open("tx_idle_message.txt")
|
||||||
|
idle_data = f.read()
|
||||||
|
f.close()
|
||||||
|
except:
|
||||||
|
idle_data = "DE %s Wenet High-Speed FSK Transmitter" % self.callsign
|
||||||
|
# Append a \x00 control code before the data
|
||||||
|
return "\x00" + idle_data
|
||||||
|
|
||||||
|
|
||||||
def tx_thread(self):
|
def tx_thread(self):
|
||||||
while self.transmit_active:
|
while self.transmit_active:
|
||||||
|
@ -84,7 +98,8 @@ class PacketTX(object):
|
||||||
self.s.write(packet)
|
self.s.write(packet)
|
||||||
else:
|
else:
|
||||||
if not self.debug:
|
if not self.debug:
|
||||||
self.s.write(self.idle_sequence)
|
#self.s.write(self.idle_sequence)
|
||||||
|
self.s.write(self.frame_packet(self.generate_idle_message()))
|
||||||
else:
|
else:
|
||||||
sleep(0.05)
|
sleep(0.05)
|
||||||
|
|
||||||
|
@ -99,7 +114,7 @@ class PacketTX(object):
|
||||||
sleep(0.01)
|
sleep(0.01)
|
||||||
|
|
||||||
def tx_packet(self,packet,blocking = False):
|
def tx_packet(self,packet,blocking = False):
|
||||||
self.txqueue.put(self.frame_packet(packet))
|
self.txqueue.put(self.frame_packet(packet, self.fec))
|
||||||
|
|
||||||
if blocking:
|
if blocking:
|
||||||
while not self.txqueue.empty():
|
while not self.txqueue.empty():
|
||||||
|
|
|
@ -249,9 +249,27 @@ class RFM22B(object):
|
||||||
self.write_register(REG.OPERATING_FUNCTION_CONTROL_1,mode)
|
self.write_register(REG.OPERATING_FUNCTION_CONTROL_1,mode)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
# Attempt to extract a frequency from the first argument:
|
||||||
|
if len(sys.argv)<2:
|
||||||
|
print("Usage: \tpython init_rfm22b.py <TX Frequency in MHz>")
|
||||||
|
print("Example: \tpython init_rfm22b.py 441.200")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
tx_freq = float(sys.argv[1])
|
||||||
|
except:
|
||||||
|
print("Unable to parse input.")
|
||||||
|
|
||||||
|
if tx_freq>450.0 or tx_freq<430.00:
|
||||||
|
print("Frequency out of 70cm band, using default.")
|
||||||
|
tx_freq = 441.200*1e6
|
||||||
|
else:
|
||||||
|
tx_freq = tx_freq*1e6
|
||||||
|
|
||||||
rfm = RFM22B()
|
rfm = RFM22B()
|
||||||
rfm.set_tx_power(TXPOW.TXPOW_14DBM | 0x08)
|
rfm.set_tx_power(TXPOW.TXPOW_14DBM | 0x08)
|
||||||
rfm.set_frequency(441.2E6) # 441.2MHz.
|
rfm.set_frequency(tx_freq)
|
||||||
rfm.write_register(REG.GPIO2_CONFIGURATION,0x30) # TX Data In
|
rfm.write_register(REG.GPIO2_CONFIGURATION,0x30) # TX Data In
|
||||||
rfm.set_bulk(CONFIGS.REGISTERS,CONFIGS.DIRECT_120K) # Direct Asynchronous mode, ~120KHz tone spacing.
|
rfm.set_bulk(CONFIGS.REGISTERS,CONFIGS.DIRECT_120K) # Direct Asynchronous mode, ~120KHz tone spacing.
|
||||||
rfm.set_mode(0x09)
|
rfm.set_mode(0x09)
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# PiCam Wrapper Functions
|
||||||
|
#
|
||||||
|
|
||||||
|
import os,glob
|
||||||
|
|
||||||
|
picam_str = "raspistill -t 100 -ex auto -o %s -vf -hf -w 1600 -h 1200"
|
||||||
|
temp_file_prefix = "./temp_pic"
|
||||||
|
|
||||||
|
|
||||||
|
def capture_single(filename="temp.jpg"):
|
||||||
|
os.system(picam_str % filename)
|
||||||
|
|
||||||
|
def capture_multiple(filename="output.jpg", n=10, temp_prefix=temp_file_prefix):
|
||||||
|
# Remove any existing temporary images
|
||||||
|
os.system("rm %s*.jpg"%temp_prefix)
|
||||||
|
|
||||||
|
# Capture n images
|
||||||
|
for pic_num in range(n):
|
||||||
|
capture_single("%s_%d.jpg"%(temp_prefix,pic_num))
|
||||||
|
|
||||||
|
# Super high-tech image quality recognition filter
|
||||||
|
# (pick the largest image... thanks daveake!)
|
||||||
|
pic_list = glob.glob("%s*.jpg"%temp_prefix)
|
||||||
|
pic_sizes = []
|
||||||
|
for pic in pic_list:
|
||||||
|
pic_sizes.append(os.path.getsize(pic))
|
||||||
|
largest_pic = pic_list[pic_sizes.index(max(pic_sizes))]
|
||||||
|
|
||||||
|
# Copy best image to resultant filename.
|
||||||
|
os.system("cp %s %s" % (largest_pic, filename))
|
||||||
|
|
||||||
|
# Remove temporary images
|
||||||
|
os.system("rm %s*.jpg"%temp_prefix)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
capture_multiple()
|
10
rx_ssdv.py
10
rx_ssdv.py
|
@ -24,6 +24,10 @@ def ssdv_packet_info(packet):
|
||||||
if len(packet) != 256:
|
if len(packet) != 256:
|
||||||
return {'error': "ERROR: Invalid Packet Length"}
|
return {'error': "ERROR: Invalid Packet Length"}
|
||||||
|
|
||||||
|
if (packet[1] != 0x66) and (packet[1] != 0x67):
|
||||||
|
print("Not a SSDV Packet! Contents: %s" % str(data))
|
||||||
|
return {'error': "ERROR: Not a SSDV Packet."}
|
||||||
|
|
||||||
# We got this far, may as well try and extract the packet info.
|
# We got this far, may as well try and extract the packet info.
|
||||||
try:
|
try:
|
||||||
packet_info = {
|
packet_info = {
|
||||||
|
@ -79,16 +83,16 @@ while True:
|
||||||
# Attempt to decode current image, and write out to a file.
|
# Attempt to decode current image, and write out to a file.
|
||||||
temp_f.close()
|
temp_f.close()
|
||||||
# Run SSDV
|
# Run SSDV
|
||||||
returncode = os.system("ssdv -d rxtemp.bin %s_%d.jpg" % (current_packet_time,current_image))
|
returncode = os.system("ssdv -d rxtemp.bin ./rx_images/%s_%d.jpg" % (current_packet_time,current_image))
|
||||||
if returncode == 1:
|
if returncode == 1:
|
||||||
print("ERROR: SSDV Decode failed!")
|
print("ERROR: SSDV Decode failed!")
|
||||||
else:
|
else:
|
||||||
print("SSDV Decoded OK!")
|
print("SSDV Decoded OK!")
|
||||||
# Make a copy of the raw binary data.
|
# Make a copy of the raw binary data.
|
||||||
os.system("mv rxtemp.bin %s_%d.bin" % (current_packet_time,current_image))
|
os.system("mv rxtemp.bin ./rx_images/%s_%d.bin" % (current_packet_time,current_image))
|
||||||
|
|
||||||
# Update live displays here.
|
# Update live displays here.
|
||||||
trigger_gui_update("%s_%d.jpg" % (current_packet_time,current_image))
|
trigger_gui_update("./rx_images/%s_%d.jpg" % (current_packet_time,current_image))
|
||||||
|
|
||||||
# Trigger upload to habhub here.
|
# Trigger upload to habhub here.
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Start RX using an Airspy.
|
||||||
|
#
|
||||||
|
python rx_gui.py &
|
||||||
|
airspy_rx -f441.0 -r /dev/stdout -a 1 -h 21 | csdr convert_s16_f | csdr bandpass_fir_fft_cc 0.025 0.175 0.025 | csdr fractional_decimator_ff 2.708277 | csdr realpart_cf | csdr convert_f_s16 | ./fsk_demod 2X 8 923096 115387 - - S 2> >(python fskdemodgui.py) | ./drs232 - - | python rx_ssdv.py --partialupdate 16
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Start RX using a rtlsdr.
|
||||||
|
#
|
||||||
|
python rx_gui.py &
|
||||||
|
rtl_sdr -s 1000000 -f 441000000 -g 35 - | csdr convert_u8_f | csdr bandpass_fir_fft_cc 0.1 0.4 0.05 | csdr fractional_decimator_ff 1.08331 | csdr realpart_cf | csdr convert_f_s16 | ./fsk_demod 2X 8 923096 115387 - - S 2> >(python fskdemodgui.py --wide) | ./drs232 - - | python rx_ssdv.py --partialupdate 16
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Wenet TX-side Initialisation Script
|
||||||
|
# 2016-08-07 Mark Jessop <vk5qi@rfhead.net>
|
||||||
|
#
|
||||||
|
# Run this to set up an attached RFM22B and start transmitting!
|
||||||
|
# Replace the transmit frequency and callsign with your own.
|
||||||
|
#
|
||||||
|
python init_rfm22b.py 441.200
|
||||||
|
python tx_picam.py VK5QI &
|
20
tx_picam.py
20
tx_picam.py
|
@ -1,16 +1,23 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
#
|
#
|
||||||
# PiCam Transmitter Script
|
# PiCam Transmitter Script
|
||||||
# Capture images from the PiCam, and transmit them,
|
# Capture images from the PiCam, and transmit them.
|
||||||
#
|
#
|
||||||
# Mark Jessop <vk5qi@rfhead.net>
|
# Mark Jessop <vk5qi@rfhead.net>
|
||||||
#
|
#
|
||||||
|
|
||||||
import PacketTX, sys, os, datetime
|
import PacketTX, sys, os, datetime
|
||||||
|
from picam_wrapper import *
|
||||||
|
|
||||||
# Set to whatever resolution you want to transmit.
|
try:
|
||||||
tx_resolution = "1024x768"
|
callsign = sys.argv[1]
|
||||||
callsign = "VK5QI"
|
if len(callsign)>6:
|
||||||
|
callsign = callsign[:6]
|
||||||
|
except:
|
||||||
|
print("Usage: python tx_picam.py CALLSIGN")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("Using callsign: %s" % callsign)
|
||||||
|
|
||||||
|
|
||||||
debug_output = False # If True, packet bits are saved to debug.bin as one char per bit.
|
debug_output = False # If True, packet bits are saved to debug.bin as one char per bit.
|
||||||
|
@ -45,12 +52,13 @@ try:
|
||||||
# Capture image using PiCam
|
# Capture image using PiCam
|
||||||
print("Capturing Image...")
|
print("Capturing Image...")
|
||||||
capture_time = datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%SZ")
|
capture_time = datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%SZ")
|
||||||
os.system("raspistill -t 100 -o ./tx_images/%s.jpg -vf -hf -w 1024 -h 768" % capture_time)
|
capture_multiple(filename="./tx_images/%s.jpg"%capture_time)
|
||||||
|
#os.system("raspistill -t 100 -o ./tx_images/%s.jpg -vf -hf -w 1024 -h 768" % capture_time)
|
||||||
# Resize using convert
|
# Resize using convert
|
||||||
print("Processing...")
|
print("Processing...")
|
||||||
#os.system("convert temp.jpg -resize %s\! temp.jpg" % tx_resolution)
|
#os.system("convert temp.jpg -resize %s\! temp.jpg" % tx_resolution)
|
||||||
# SSDV'ify the image.
|
# SSDV'ify the image.
|
||||||
os.system("ssdv -e -c %s -i %d ./tx_images/%s.jpg temp.ssdv" % (callsign,image_id,capture_time))
|
os.system("ssdv -e -n -c %s -i %d ./tx_images/%s.jpg temp.ssdv" % (callsign,image_id,capture_time))
|
||||||
# Transmit image
|
# Transmit image
|
||||||
print("Transmitting...")
|
print("Transmitting...")
|
||||||
transmit_file("temp.ssdv",tx)
|
transmit_file("temp.ssdv",tx)
|
||||||
|
|
Ładowanie…
Reference in New Issue