kopia lustrzana https://github.com/projecthorus/wenet
hacky
rodzic
3a84f687f9
commit
15097c958d
|
@ -85,11 +85,25 @@ class PacketTX(object):
|
|||
fec=True,
|
||||
udp_listener = None,
|
||||
log_file = None):
|
||||
|
||||
self.min_radio_rotation_time_seconds = 60 # only when queues empty
|
||||
self.last_rotate = time.monotonic()
|
||||
|
||||
self.radio = radio
|
||||
if type(radio) == list: # handle multiple radios
|
||||
self.radios = radio
|
||||
self.radio = radio.pop(0)
|
||||
self.radios.append(self.radio) # rotate since we've used the first one
|
||||
else:
|
||||
self.radios = None
|
||||
self.radio = radio
|
||||
|
||||
self.payload_length = payload_length
|
||||
self.callsign = callsign.encode('ascii')
|
||||
if type(callsign) == list:
|
||||
self.callsigns = [x.encode('ascii') for x in callsign]
|
||||
self.callsign = self.callsigns.pop(0)
|
||||
self.callsigns.append(self.callsign)
|
||||
else:
|
||||
self.callsign = callsign.encode('ascii')
|
||||
self.fec = fec
|
||||
|
||||
self.crc16 = crcmod.predefined.mkCrcFun('crc-ccitt-false')
|
||||
|
@ -157,10 +171,23 @@ class PacketTX(object):
|
|||
packet = self.telemetry_queue.get_nowait()
|
||||
self.radio.transmit_packet(packet)
|
||||
elif self.ssdv_queue.qsize()>0:
|
||||
packet = self.ssdv_queue.get_nowait()
|
||||
self.radio.transmit_packet(packet)
|
||||
(packet, callsign) = self.ssdv_queue.get_nowait()
|
||||
if callsign == self.callsign:
|
||||
self.radio.transmit_packet(packet)
|
||||
else:
|
||||
logging.info("packet not intended for this callsign - dropping")
|
||||
else:
|
||||
self.radio.transmit_packet(self.idle_message)
|
||||
if self.radios:
|
||||
if time.monotonic() > self.min_radio_rotation_time_seconds + self.last_rotate:
|
||||
logging.info("Rotating radio")
|
||||
logging.info(self.radios)
|
||||
self.last_rotate = time.monotonic()
|
||||
self.callsign = self.callsigns.pop(0)
|
||||
self.callsigns.append(self.callsign)
|
||||
self.radio = self.radios.pop(0)
|
||||
self.radios.append(self.radio)
|
||||
self.radio.start()
|
||||
# time.sleep(0.1)
|
||||
# commented this out as we should probably always be sending something
|
||||
# this can cause gaps in i2s, which while won't hurt the performance can be annoying
|
||||
|
@ -192,11 +219,11 @@ class PacketTX(object):
|
|||
|
||||
# New packet queueing and queue querying functions (say that 3 times fast)
|
||||
|
||||
def queue_image_packet(self,packet):
|
||||
self.ssdv_queue.put(self.frame_packet(packet, self.fec))
|
||||
def queue_image_packet(self,packet,callsign):
|
||||
self.ssdv_queue.put([self.frame_packet(packet, self.fec),callsign])
|
||||
|
||||
|
||||
def queue_image_file(self, filename):
|
||||
def queue_image_file(self, filename, callsign):
|
||||
""" Read in <filename> and transmit it, 256 bytes at a time.
|
||||
Intended for transmitting SSDV images.
|
||||
"""
|
||||
|
@ -205,7 +232,7 @@ class PacketTX(object):
|
|||
f = open(filename,'rb')
|
||||
for x in range(file_size//256):
|
||||
data = f.read(256)
|
||||
self.queue_image_packet(data)
|
||||
self.queue_image_packet(data,callsign)
|
||||
f.close()
|
||||
return True
|
||||
except:
|
||||
|
|
|
@ -389,7 +389,7 @@ class WenetPiCamera2(object):
|
|||
|
||||
return True
|
||||
|
||||
def ssdvify(self, filename="output.jpg", image_id=0, quality=6):
|
||||
def ssdvify(self, filename="output.jpg", image_id=0, quality=6, tx=None):
|
||||
""" Convert a supplied JPEG image to SSDV.
|
||||
Returns the filename of the converted SSDV image.
|
||||
|
||||
|
@ -417,6 +417,8 @@ class WenetPiCamera2(object):
|
|||
file_basename = filename[:-4]
|
||||
|
||||
# Construct SSDV command-line.
|
||||
if tx:
|
||||
self.callsign = tx.callsign.decode()
|
||||
ssdv_command = "ssdv -e -n -q %d -c %s -i %d picam_temp.jpg picam_temp.ssdv" % (quality, self.callsign, image_id)
|
||||
print(ssdv_command)
|
||||
# Update debug message.
|
||||
|
@ -503,7 +505,13 @@ class WenetPiCamera2(object):
|
|||
self.debug_message("Image Post-Processing Failed: %s" % error_str)
|
||||
|
||||
# SSDV'ify the image.
|
||||
ssdv_filename = self.ssdvify(capture_filename, image_id=image_id)
|
||||
# Wait until the transmit queue is empty before pushing in packets.
|
||||
self.debug_message("Waiting for SSDV TX queue to empty.")
|
||||
while tx.image_queue_empty() == False:
|
||||
sleep(1) # Sleep for a short amount of time to allow switching of radio
|
||||
if self.auto_capture_running == False:
|
||||
return
|
||||
ssdv_filename = self.ssdvify(capture_filename, image_id=image_id, tx=tx)
|
||||
|
||||
# Check the SSDV Conversion has completed properly. If not, continue
|
||||
if ssdv_filename == "FAIL":
|
||||
|
@ -514,18 +522,11 @@ class WenetPiCamera2(object):
|
|||
# Otherwise, read in the file and push into the TX buffer.
|
||||
file_size = os.path.getsize(ssdv_filename)
|
||||
|
||||
# Wait until the transmit queue is empty before pushing in packets.
|
||||
self.debug_message("Waiting for SSDV TX queue to empty.")
|
||||
while tx.image_queue_empty() == False:
|
||||
sleep(0.05) # Sleep for a short amount of time.
|
||||
if self.auto_capture_running == False:
|
||||
return
|
||||
|
||||
# Inform ground station we are about to send an image.
|
||||
self.debug_message("Transmitting %d PiCam SSDV Packets." % (file_size//256))
|
||||
|
||||
# Push SSDV file into transmit queue.
|
||||
tx.queue_image_file(ssdv_filename)
|
||||
tx.queue_image_file(ssdv_filename, self.callsign.encode('ascii'))
|
||||
|
||||
# Increment image ID.
|
||||
image_id = (image_id + 1) % 256
|
||||
|
|
|
@ -228,7 +228,7 @@ class RFM98W_Serial(RFM98W):
|
|||
|
||||
self.serial_port = serial_port
|
||||
|
||||
super().__init__(spidevice,frequency,baudrate,tx_power_dbm,reinit_count)
|
||||
super().__init__(spidevice,frequency,baudrate,tx_power_dbm,reinit_count,led=5)
|
||||
self.start()
|
||||
|
||||
|
||||
|
@ -242,6 +242,7 @@ class RFM98W_Serial(RFM98W):
|
|||
if self.serial_port:
|
||||
try:
|
||||
self.serial = serial.Serial(self.serial_port, self.baudrate)
|
||||
self.serial.break_condition=True # Set UART to low when we aren't using it. Used for dual tx mode
|
||||
logging.info(f"RFM98W - Opened Serial port {self.serial_port} for modulation.")
|
||||
except Exception as e:
|
||||
logging.critical(f"Could not open serial port! Error: {str(e)}")
|
||||
|
@ -274,8 +275,10 @@ class RFM98W_Serial(RFM98W):
|
|||
"""
|
||||
Modulate serial data, using a UART.
|
||||
"""
|
||||
self.serial.break_condition=False
|
||||
if self.serial:
|
||||
self.serial.write(packet)
|
||||
self.serial.break_condition=True
|
||||
|
||||
super().transmit_packet(packet) # used to reinit the radio occasionally
|
||||
|
||||
|
|
|
@ -20,15 +20,15 @@ from radio_wrappers import *
|
|||
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("callsign", default="N0CALL", help="Payload Callsign")
|
||||
parser.add_argument("callsign", nargs="+", action="extend", help="Payload Callsign")
|
||||
parser.add_argument("--gps", default="none", help="uBlox GPS Serial port. Defaults to /dev/ttyACM0")
|
||||
parser.add_argument("--gpsbaud", default=115200, type=int, help="uBlox GPS Baud rate. (Default: 115200)")
|
||||
parser.add_argument("--logo", default="none", help="Optional logo to overlay on image.")
|
||||
parser.add_argument("--rfm98w", default=None, type=int, help="If set, configure a RFM98W on this SPI device number.")
|
||||
parser.add_argument("--rfm98w-i2s", default=None, type=int, help="If set, configure a RFM98W on this SPI device number. Using I2S")
|
||||
parser.add_argument("--audio-device", default="hw:CARD=i2smaster,DEV=0", type=str, help="Alsa device string. Sets the audio device for rfm98w-i2s mode. (Default: hw:CARD=i2smaster,DEV=0)")
|
||||
parser.add_argument("--frequency", default=443.500, type=float, help="Transmit Frequency (MHz). (Default: 443.500 MHz)")
|
||||
parser.add_argument("--baudrate", default=None, type=int, help="Wenet TX baud rate. (Default: 115200 for uart and 96000 for I2S). Known working I2S baudrates: 8000, 24000, 48000, 96000.")
|
||||
parser.add_argument("--frequency", nargs="+", type=float, help="Transmit Frequency (MHz). (Default: 443.500 MHz)",action="extend")
|
||||
parser.add_argument("--baudrate", nargs="+", type=int,action="extend", help="Wenet TX baud rate. (Default: 115200 for uart and 96000 for I2S). Known working I2S baudrates: 8000, 24000, 48000, 96000.")
|
||||
parser.add_argument("--serial_port", default="/dev/ttyAMA0", type=str, help="Serial Port for modulation.")
|
||||
parser.add_argument("--tx_power", default=17, type=int, help="Transmit power in dBm (Default: 17 dBm, 50mW. Allowed values: 2-17)")
|
||||
parser.add_argument("--vflip", action='store_true', default=False, help="Flip captured image vertically.")
|
||||
|
@ -45,12 +45,6 @@ parser.add_argument("--image_delay", type=float, default=1.0, help="Delay time b
|
|||
parser.add_argument("-v", "--verbose", action='store_true', default=False, help="Show additional debug info.")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.baudrate == None:
|
||||
if args.rfm98w:
|
||||
args.baudrate = 115200
|
||||
elif args.rfm98w_i2s:
|
||||
args.baudrate = 96000
|
||||
|
||||
if args.verbose:
|
||||
logging_level = logging.DEBUG
|
||||
else:
|
||||
|
@ -62,36 +56,35 @@ logging.basicConfig(format="%(asctime)s %(levelname)s: %(message)s", level=loggi
|
|||
|
||||
callsign = args.callsign
|
||||
# Truncate callsign if it's too long.
|
||||
if len(callsign) > 6:
|
||||
callsign = callsign[:6]
|
||||
callsign = [x[:6] for x in args.callsign]
|
||||
|
||||
print("Using Callsign: %s" % callsign)
|
||||
|
||||
radios = []
|
||||
if args.rfm98w is not None:
|
||||
radio = RFM98W_Serial(
|
||||
radios.append(RFM98W_Serial(
|
||||
spidevice = args.rfm98w,
|
||||
frequency = args.frequency,
|
||||
baudrate = args.baudrate,
|
||||
frequency = args.frequency.pop(0),
|
||||
baudrate = args.baudrate.pop(0),
|
||||
serial_port = args.serial_port,
|
||||
tx_power_dbm = args.tx_power
|
||||
)
|
||||
elif args.rfm98w_i2s is not None:
|
||||
radio = RFM98W_I2S(
|
||||
))
|
||||
if args.rfm98w_i2s is not None:
|
||||
radios.append(RFM98W_I2S(
|
||||
spidevice = args.rfm98w_i2s,
|
||||
baudrate = args.baudrate,
|
||||
frequency = args.frequency,
|
||||
baudrate = args.baudrate.pop(0),
|
||||
frequency = args.frequency.pop(0),
|
||||
audio_device= args.audio_device,
|
||||
tx_power_dbm = args.tx_power
|
||||
)
|
||||
))
|
||||
# Other radio options would go here.
|
||||
else:
|
||||
if not radios:
|
||||
logging.critical("No radio type specified! Exiting")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Start up Wenet TX.
|
||||
picam = None
|
||||
tx = PacketTX.PacketTX(radio=radio, callsign=callsign, log_file="debug.log", udp_listener=55674)
|
||||
tx = PacketTX.PacketTX(radio=radios, callsign=callsign, log_file="debug.log", udp_listener=55674)
|
||||
tx.start_tx()
|
||||
|
||||
# Sleep for a second to let the transmitter fire up.
|
||||
|
|
Ładowanie…
Reference in New Issue