'''
Python NMEA Radio Functions module for Icom IC-M710 Marine HF SSB Transceiver
Copyright (C) 2015 John Pumford-Green
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
'''
# serial port for Icom IC-M710 Rig Control
import serial
import threading
import time
version = "v0.1"
sport = '/dev/ttyUSB0'
sbaud = 4800
#ser = serial.Serial(sport, 4800, timeout=1)
lock = threading.Lock()
# NMEA Codes
preamble = "$PICOA,"
controller = "90"
radio = "01"
cr = "\x0d"
lf = "\x0a"
# Commands are sent as NMEA private sentences:
#
# $PICOA,controller_id,radio_id,command,,*HH
#
# where HH is the 2 digit ECC value below:
#
# The protocol document states that for messages FROM the controller TO the radio
# the ECC bytes are optional, and may be omitted. This appears to be false information, and
# the ECC bytes seem to be necessary.
#
# The ECC checksum, is a two-digit hex value found by XORing the hex values of the characters
# between "$" and "*" (but not including the $ or *)
#
# The first part of the message is always:
# "PICOA,90,01," and this has an XOR value of (decimal) 112
# we then XOR this with each character's decimal ASCII value, in the required command
# and convert the result to a 2-digit hex value
#
class m710(object):
def __init__(self, model):
self.ser = serial.Serial(sport, sbaud, timeout=0.1)
self.model = model
print "model", model
def get_ecc(self,command):
ecc = 112
for c in command:
ecc = ord(c) ^ ecc
hecc = '{0:02x}'.format(int(ecc))
return hecc
# we must force the radio into "Remote" mode before sending any other commands.
def remote_on(self):
command = "REMOTE,ON"
ecc = self.get_ecc(command)
sendStr = preamble+controller+","+radio+","+command+"*"+ecc+cr+lf
result = self.tx_rx(sendStr)
if result:
return
else:
return self.remote_on()
# we can leave the radio in "Remote" mode for as long as we want to control it remotely
# but we must close the "Remote" mode when finished. The previous radio settings (channel/power etc) are
# restored after Remote mode is closed.
def remote_off(self):
command = "REMOTE,OFF"
ecc = self.get_ecc(command)
sendStr = preamble+controller+","+radio+","+command+"*"+ecc+cr+lf
result = self.tx_rx(sendStr)
if result:
#ser.close()
return
else:
return self.remote_off()
def ptt_on():
command = "TRX,TX"
ecc = get_ecc(command)
sendStr = preamble+controller+","+radio+","+command+"*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return
else:
return ptt_on()
def ptt_off():
command = "TRX,RX"
ecc = get_ecc(command)
sendStr = preamble+controller+","+radio+","+command+"*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return
else:
return ptt_off()
def get_freq(self):
fkhz = self.get_rxfreq()
#fkhz = "%.3f" % (float(f) * 1000)
return fkhz
def set_freq(self,freq):
self.set_rxfreq(freq)
self.set_txfreq(freq)
return "Set freq success"
def get_rxfreq(self):
command = "RXF"
ecc = self.get_ecc(command)
sendStr = preamble+controller+","+radio+","+command+"*"+ecc+cr+lf
result = self.tx_rx(sendStr)
if result:
list = result.split(",")
f = list[4].split("*")[0]
fkhz = "%.3f" % (float(f) * 1000)
return fkhz
else:
return self.get_rxfreq()
def get_txfreq(self):
command = "TXF"
ecc = get_ecc(command)
sendStr = preamble+controller+","+radio+","+command+"*"+ecc+cr+lf
result = self.tx_rx(sendStr)
if result:
list = result.split(",")
f = list[4].split("*")[0]
fkhz = "%.3f" % (float(f) * 1000)
return fkhz
else:
return self.get_txfreq()
def get_mode(self):
command = "MODE"
ecc = self.get_ecc(command)
sendStr = preamble+controller+","+radio+","+command+"*"+ecc+cr+lf
result = self.tx_rx(sendStr)
if result:
list = result.split(",")
mode = list[4].split("*")[0]
return mode
else:
return self.get_mode()
def set_mode(self,mode):
mode = mode.upper()
command = "MODE,"+mode
ecc = self.get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
print "in set_mode with ", sendStr
result = self.tx_rx(sendStr)
if result:
return result
else:
return self.set_mode(mode)
def set_rxfreq(self,freq):
fmhz = float(freq) / 1000
f = str(fmhz)
command = "RXF,"+f
ecc = self.get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = self.tx_rx(sendStr)
if result:
return result
else:
return self.set_rxfreq(freq)
def set_txfreq(self,freq):
fmhz = float(freq) / 1000
f = str(fmhz)
command = "TXF,"+f
ecc = self.get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = self.tx_rx(sendStr)
if result:
return result
else:
return self.set_txfreq(freq)
def get_txpower():
command = "TXP"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
list = result.split(",")
power = list[4].split("*")[0]
return power
else:
return get_txpower()
def set_txpower(p):
command = "TXP,"+p
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return set_txpower(p)
def get_smeter(self):
command = "SIGM"
ecc = self.get_ecc(command)
sendStr = preamble+controller+","+radio+","+command+"*"+ecc+cr+lf
result = self.tx_rx(sendStr)
if result:
list = result.split(",")
smeter = list[4].split("*")[0]
return smeter
else:
return self.get_smeter()
def speaker_on():
command = "SP,ON"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return speaker_on()
def speaker_off():
command = "SP,OFF"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return speaker_off()
def sql_on():
command = "SQLC,ON"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return sql_on()
def sql_off():
command = "SQLC,OFF"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return sql_off()
def nb_on():
command = "NB,ON"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return nb_on()
def nb_off():
command = "NB,OFF"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return nb_off()
def dim_on():
command = "DIM,ON"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return dim_on()
def dim_off():
command = "DIM,OFF"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return dim_off()
def agc_on():
command = "AGC,ON"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return agc_on()
def agc_off():
command = "AGC,OFF"
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return agc_off()
def get_vol():
command = "AFG"
ecc = get_ecc(command)
sendStr = preamble+controller+","+radio+","+command+"*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
list = result.split(",")
vol = list[4].split("*")[0]
return vol
else:
return get_vol()
def set_vol(v):
command = "AFG,"+v
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return set_vol(v)
def get_rfg():
command = "RFG"
ecc = get_ecc(command)
sendStr = preamble+controller+","+radio+","+command+"*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
list = result.split(",")
rf = list[4].split("*")[0]
return rf
else:
return get_rfg()
def get_att(self):
return
def get_pre(self):
return
def set_rfg(v):
command = "RFG,"+v
ecc = get_ecc(command)
sendStr = preamble +controller+","+radio+"," + command + "*"+ecc+cr+lf
result = tx_rx(sendStr)
if result:
return result
else:
return set_rfg(v)
# The message FROM the radio may be corrupted so we do a check on the received ECC versus our calculated cECC
# from the received characters - which are everything AFTER the "$" and BEFORE the "*"
#
# starting the ECC calculation at message[1] ignores the "$" and we iterate through the message XORing each
# character's ASCII (decimal) value until we have the final cECC which is converted by formatting it
# into a two-digit hex value. This is then compared to the received (rECC) value from the radio's message.
# If they match the message is acceptable and check_ecc() returns True to tx_rx(),
# otherwise check_ecc() function returns "False" to tx_rx()
# the True/False value is tested in tx_rx().
# If True then tx_rx() returns the incoming string to the calling function
# otherwise it returns "False".
# The calling function then checkS the boolean state of the returned value.
# If True (ie it has the radio's message and the ECC was good) the message
# is sent back to the client.
# If False the function calls itself again, and attempts to get an error-free reply from the radio, via tx_rx()
def check_ecc(self,message, recc):
i = 1
cecc = 0
while i < len(message):
cecc = ord(message[i]) ^ cecc
i += 1
cecc = '{0:02x}'.format(int(cecc))
if cecc == recc:
return True
else:
return False
def tx_rx(self,sendStr):
print "in tx_rx, sendStr = " , sendStr
lock.acquire()
self.ser.write(sendStr)
time.sleep(0.1)
result = self.ser.readline()
print result
reply = result.split("*")
ecc = reply[1][0:2].lower()
message = reply[0]
lock.release()
if self.check_ecc(message, ecc):
return result
else:
return False
#