Major ease-of-use updates, added start of non-SSDV message support.

pull/1/head
Mark Jessop 2016-08-07 17:41:52 +09:30
rodzic c2e41f775c
commit 023c8861d3
9 zmienionych plików z 120 dodań i 15 usunięć

Wyświetl plik

@ -44,7 +44,7 @@ class PacketTX(object):
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.
if debug == True:
self.s = BinaryDebug()
@ -55,13 +55,14 @@ class PacketTX(object):
self.crc16 = crcmod.predefined.mkCrcFun('crc-ccitt-false')
self.fec = fec
self.callsign = callsign
def start_tx(self):
self.transmit_active = True
txthread = Thread(target=self.tx_thread)
txthread.start()
def frame_packet(self,packet):
def frame_packet(self,packet, fec=False):
# Ensure payload size is equal to the desired payload length
if len(packet) > self.payload_length:
packet = packet[:self.payload_length]
@ -71,11 +72,24 @@ class PacketTX(object):
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)
else:
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):
while self.transmit_active:
@ -84,7 +98,8 @@ class PacketTX(object):
self.s.write(packet)
else:
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:
sleep(0.05)
@ -99,7 +114,7 @@ class PacketTX(object):
sleep(0.01)
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:
while not self.txqueue.empty():

Wyświetl plik

@ -249,9 +249,27 @@ class RFM22B(object):
self.write_register(REG.OPERATING_FUNCTION_CONTROL_1,mode)
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.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.set_bulk(CONFIGS.REGISTERS,CONFIGS.DIRECT_120K) # Direct Asynchronous mode, ~120KHz tone spacing.
rfm.set_mode(0x09)

38
picam_wrapper.py 100644
Wyświetl plik

@ -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()

Wyświetl plik

@ -24,6 +24,10 @@ def ssdv_packet_info(packet):
if len(packet) != 256:
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.
try:
packet_info = {
@ -79,16 +83,16 @@ while True:
# Attempt to decode current image, and write out to a file.
temp_f.close()
# 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:
print("ERROR: SSDV Decode failed!")
else:
print("SSDV Decoded OK!")
# 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.
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.
else:

Wyświetl plik

@ -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

Wyświetl plik

@ -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

10
start_tx.sh 100755
Wyświetl plik

@ -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 &

Wyświetl plik

@ -1,16 +1,23 @@
#!/usr/bin/env python
#
# PiCam Transmitter Script
# Capture images from the PiCam, and transmit them,
# Capture images from the PiCam, and transmit them.
#
# Mark Jessop <vk5qi@rfhead.net>
#
import PacketTX, sys, os, datetime
from picam_wrapper import *
# Set to whatever resolution you want to transmit.
tx_resolution = "1024x768"
callsign = "VK5QI"
try:
callsign = sys.argv[1]
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.
@ -45,12 +52,13 @@ try:
# Capture image using PiCam
print("Capturing Image...")
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
print("Processing...")
#os.system("convert temp.jpg -resize %s\! temp.jpg" % tx_resolution)
# 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
print("Transmitting...")
transmit_file("temp.ssdv",tx)