# HG changeset patch
# User Jens Jensen <kd4tjx@yahoo.com>
# Date 1384997819 21600
#      Wed Nov 20 19:36:59 2013 -0600
# Node ID 43c39ddaf078f332298c07d80698fc1cfcc9f98a
# Parent  fc6b4cd40403f4bb3f2b9bc3578366fdf20a85c6
developer tool bitdiff.py for comparing radio images, #1259

diff -r fc6b4cd40403 -r 43c39ddaf078 chirp/uv5r.py
--- a/chirp/uv5r.py	Sun Nov 17 11:15:47 2013 -0800
+++ b/chirp/uv5r.py	Wed Nov 20 19:36:59 2013 -0600
@@ -1374,7 +1374,7 @@
     
     def get_features(self):
         rf = super(BaojieBJUV55Radio, self).get_features()
-        rf.has_settings = False
+        #rf.has_settings = False
         rf.valid_name_length = 6
         return rf
     
diff -r fc6b4cd40403 -r 43c39ddaf078 tools/bitdiff.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/bitdiff.py	Wed Nov 20 19:36:59 2013 -0600
@@ -0,0 +1,111 @@
+#!/usr/bin/python
+#
+## Copyright 2013 Jens Jensen AF5MI <kd4tjx@yahoo.com>
+
+import sys, os, argparse, time
+
+def printDiff(pos, byte1, byte2, args):
+	
+	bits1 = '{0:08b}'.format(byte1)
+	bits2 = '{0:08b}'.format(byte2)
+	print "@%04Xh" % pos
+	print "1:%02Xh, %sb" % (byte1, bits1)
+	print "2:%02Xh, %sb" % (byte2, bits2)
+	if args.csv:
+	    writeDiffCSV(pos, byte1, byte2, args)
+
+def writeDiffCSV(pos, byte1, byte2, args):
+    bits1 = '{0:08b}'.format(byte1)
+    bits2 = '{0:08b}'.format(byte2)
+    csvline = '%s, %s, %04X, %02X, %s, %02X, %s, %s, %s' % \
+        (args.file1, args.file2, pos, byte1, bits1, byte2, bits2, args.setting, args.value)
+    if not os.path.isfile(args.csv):
+        fh = open(args.csv, "w")
+        header = "filename1, filename2, byte_offset, byte1, bits1, byte2, bits2, item_msg, value_msg"
+        fh.write(header + os.linesep)
+    else:
+        fh = open(args.csv, "a")
+    fh.write(csvline + os.linesep)
+    fh.close()
+    
+
+def compareFiles(args):
+	f1 = open(args.file1, "rb")
+	f1.seek(args.offset)
+	f2 = open(args.file2, "rb")
+	f2.seek(args.offset)
+	
+	while True:
+		c1 = f1.read(1)
+		c2 = f2.read(1)
+		if not (c1 and c2):
+			break
+		b1 = ord(c1)
+		b2 = ord(c2)
+		if b1 != b2:
+			pos = f1.tell() - args.offset
+			printDiff(pos, b1, b2, args)
+	
+	pos = f1.tell() - args.offset
+	print "bytes read: %02d" % pos
+	f1.close()
+	f2.close()
+
+def compareFilesDat(args):
+	f1 = open(args.file1, "r")
+	f1contents = f1.read()
+	f1.close()
+	f2 = open(args.file2, "r")
+	f2contents = f2.read()
+	f2.close()
+	
+	f1strlist = f1contents.split()
+	f1intlist = map(int, f1strlist)
+	f2strlist = f2contents.split()
+	f2intlist = map(int, f2strlist)
+	f1bytes = bytearray(f1intlist)
+	f2bytes = bytearray(f2intlist)
+	
+	length = len(f1intlist)
+	for i in range(length):
+		b1 = f1bytes[i]
+		b2 = f2bytes[i]
+		pos = i
+		if b1 != b2:
+			printDiff(pos, b1, b2, args)
+	
+	pos = length
+	print "bytes read: %02d" % pos
+
+#
+## main
+
+ap = argparse.ArgumentParser(description="byte-/bit- comparison of two files")
+ap.add_argument("file1", help="first (reference) file to parse")
+ap.add_argument("file2", help="second file to parse")
+mutexgrp1 = ap.add_mutually_exclusive_group()
+mutexgrp1.add_argument("-o", "--offset", help="offset (hex) to start comparison", default=0)
+mutexgrp1.add_argument("-d", "--dat", help="process input files from .DAT format (from 'jujumao' oem programming software for chinese radios)", action="store_true")
+ap.add_argument("-w", "--watch", help="'watch' changes. runs in a loop", action="store_true")
+csvgrp = ap.add_argument_group("csv output")
+csvgrp.add_argument("-c", "--csv", help="file to append csv results. format: \
+            filename1, filename2, byte_offset, byte1, bits1, byte2, bits2, item_msg, value_msg")
+csvgrp.add_argument("-s", "--setting", help="user-meaningful field indicating setting/item modified, e.g. 'beep' or 'txtone'")
+csvgrp.add_argument("-v", "--value", help="user-meaningful field indicating values changed, e.g. 'true->false' or '110.9->100.0'")
+args = ap.parse_args()
+if args.offset:
+    args.offset = int(args.offset, 16)
+
+print "f1:", args.file1, " f2:", args.file2
+if args.setting or args.value:
+    print "setting:", args.setting, "- value:", args.value
+
+while True:
+	if (args.dat):
+		compareFilesDat(args)
+	else:
+		compareFiles(args)
+	if not args.watch:
+		break
+	print "------"
+	time.sleep(delay)
