Skip to content

Instantly share code, notes, and snippets.

@mlt
Created October 11, 2015 17:40
Show Gist options
  • Save mlt/d2e41c9855c2c993ab89 to your computer and use it in GitHub Desktop.
Save mlt/d2e41c9855c2c993ab89 to your computer and use it in GitHub Desktop.
Sainsonic RST599 extraction
#!/usr/bin/env python
from __future__ import print_function
from datetime import timedelta
import argparse, os, sys
import logging
from serial import Serial, SerialException
from binascii import hexlify
import struct
import re
from chirp.bitwise import bcd_to_int
from chirp.chirp_common import Memory
_log = logging.getLogger(__name__)
CONNECT = bytearray.fromhex("06 59 41 53 48 45 ff ff")
ACK = bytearray.fromhex("02")
STUFF = bytearray.fromhex("00 91 52 16 b7 59 fa 9c 3d de 80 21 c2 64 05 86")
#00 3d 7f c3 64 05 a7 48 e9 8b 54 cd 6f 10 b1 9c
def get_parser():
parser = argparse.ArgumentParser(description='Download stuff from RST599', \
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--port',
default='COM3',
help='Virtual COM port')
return parser
class RST599:
def _read(self, where, amount):
cmd = struct.pack(">B", 0x52)
what = struct.pack(">HB", where, amount)
self.port.write(cmd + what)
res = self.port.read(1)
if res != "\x57":
raise Exception("WTF")
res = self.port.read(3)
if res != what:
raise Exception("zzz")
res = self.port.read(amount)
self.dump(res)
return res
def __init__(self, args):
self._log = logging.getLogger(__name__)
self._log.debug("Opening port")
self.port = Serial(args.port, 9600, timeout=1, writeTimeout=1)
self._log.debug("Sending connect")
self.port.write(CONNECT)
res = self.port.read(8) # TDXSD01\xff
self.dump(res)
self._log.debug("Checking")
self.port.write(ACK)
self.check_ok()
self._log.debug("Writing stuff")
self.port.write(STUFF) # TODO needs documentation badly. Changes often
self.check_ok()
self._log.debug("Getting channel bitmask")
mask = self._read(0x4000, 32)
chan = 0
for x in mask[:31]:
x = struct.unpack("B", x)[0]
for bit in xrange(0, 8):
present = x & 1 > 0
x >>= 1
if present:
# mem = Memory()
res = self._read(chan * 0x16, 0x16)
name = res[16:22]
rx, tx = struct.unpack("<II", res[:8])
rx = unpack_bcd(rx) / 1.e5
tx = unpack_bcd(tx) / 1.e5
self._log.debug("Got channel %d (%s), rx=%.5f MHz, tx=%.5f MHz", chan, name.strip("\x00"), rx, tx)
chan += 1
# self._log.debug("Getting blocks 0x5214e010-0x5219e010")
# le = int("5214e010", 16)
# ue = int("5219e011", 16)
# for e in xrange(le, ue, 4096):
# cmd = struct.pack(">I", e)
# self.port.write(cmd)
# res = self.port.read(20)
# self.dump(res)
# self._log.debug("Getting blocks 0x52410010-0x52451010")
# le = int("52410010", 16)
# ue = int("52451011", 16)
# for e in xrange(le, ue, 4096):
# cmd = struct.pack(">I", e)
# self.port.write(cmd)
# res = self.port.read(20)
# self.dump(res)
self.port.write("\x45")
res = self.port.read(1)
a = hexlify(res)
self._log.debug(a)
def dump(self, val):
a = hexlify(val)
ascii = re.sub(r'[^a-zA-Z0-9]', '.', val)
self._log.debug("%s%s%s", a, " ", ascii)
def check_ok(self, expect="\x06"):
res = self.port.read(1)
if res != expect:
raise Exception("Failed check, expected 6 but got %s" % res)
def unpack_bcd(x0):
x00 = x0
x = 0
m = 0
while x0:
digit = x0 & 0x000f
if digit>9:
raise Exception("Non-BCD argument {:X} in {:X}".format(digit, x00))
x = x + digit * 10**m
m = m + 1
x0 = x0 >> 4
return x
def main():
args = get_parser().parse_args()
try:
radio = RST599(args)
except SerialException as e:
_log.fatal("Port %s can't be opened :(", args.port)
sys.exit(-1)
print("Done")
if __name__ == '__main__':
# FORMAT = FORMAT = '%(asctime)-15s %(message)s'
# logging.basicConfig(level=logging.DEBUG, format=FORMAT)
logging.basicConfig(level=logging.DEBUG)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment