#! /usr/bin/python3

import os
import sys
import time
import threading
import binascii
import xusb
import xtalk

def env_debug_mask(module, env_name, default_value):
	debug_mask = os.getenv(env_name, default_value)
	module.set_debug_mask(int(debug_mask, 0));

def env_verbose(module, env_name, default_value):
	verbose = os.getenv(env_name, default_value)
	module.set_verbose(int(verbose, 0));

env_debug_mask(xusb, "XTALK_DEBUG", "0x0")
env_debug_mask(xtalk, "XTALK_DEBUG", "0x0")
env_verbose(xusb, "XTALK_VERBOSE", "0")
env_verbose(xtalk, "XTALK_VERBOSE", "0")

usbdev_by_devpath = dict()
xpp_by_devpath = dict()
mpp_by_devpath = dict()
threads = []

# List of specs to search
specs = (
	xusb.Spec(0xe4e4, 0x1162, "Astribanks-XPP"),
	xusb.Spec(0xe4e4, 0x1162, "Astribanks-MPP"),
	)

class USBTest (threading.Thread):
	def __init__(self, devpath, xusb_device, interface_num):
		threading.Thread.__init__(self)
		self.devpath = devpath
		self.name = self.devpath + "/" + self.__class__.__name__
		self.xusb_device = xusb_device
		self.xusb_iface = xusb_device.claim(interface_num)
		self.log("%s\t%s" % (self.xusb_iface.name(), self.xusb_device.serial()))

	def log(self, s):
		print("%s:" % (self.name), s)

class XPP (USBTest):
	def __init__(self, devpath, xusb_device):
		USBTest.__init__(self, devpath, xusb_device, 0)
		self.xtalk = xtalk.Xtalkraw(self.xusb_iface)

	def ab_sync(self, yes):
		if yes:
			b = "01"
			self.log("AB-sync ON")
		else:
			b = "00"
			self.log("AB-sync OFF")
		buf = binascii.unhexlify("06001900" + b + "00")
		self.xtalk.buffer_send(buf);

	def run(self):
		self.log("Starting")
		self.ab_sync(1)
		count = 0
		for i in range(1, 25000):
			#print("DEBUG: ", sys.getrefcount(None))
			count += 1
			r = self.xtalk.buffer_recv()
			if r == None:
				self.log("timeout")
				self.ab_sync(1)
				continue
			if (count % 1000) == 0:
				self.log("count={}" % count)
			if (count % 3000) == 0:
				self.ab_sync(0)

		self.log("Exiting")

class MPP (USBTest):
	def __init__(self, devpath, xusb_device):
		USBTest.__init__(self, devpath, xusb_device, 1)
		self.xtalk = xtalk.Xtalksync(self.xusb_iface)

	def run(self):
		self.log("Starting")
		self.xusb_device.showinfo()
		self.log("PROTOCOL NAME:" + self.xtalk.name())
		self.xtalk.set_timeout(5000)
		for i in range(1, 4):
			pver = self.xtalk.proto_query()
			self.log("PROTOCOL VERSION: {}" % pver)
			time.sleep(5)
		self.log("Exiting")


# Find all devices
print("Searching for Astribanks:")

for s in specs:
	spec_name = s.name()
	devs = s.find_all()
	print("\t-> %d %s" % (len(devs), spec_name))
	if not devs:
		continue
	for d in devs:
		devpath = d.devpath()
		if usbdev_by_devpath.has_key(devpath):
			usbdev_by_devpath[devpath][spec_name] = d
		else:
			usbdev_by_devpath[devpath] = { spec_name: d }

for devpath in usbdev_by_devpath.keys():
	for sp_name in usbdev_by_devpath[devpath]:
		d = usbdev_by_devpath[devpath][sp_name]
		if sp_name == "Astribanks-XPP":
			print("XPP:", devpath)
			xpp_by_devpath[devpath] = XPP(devpath, d)
			xpp_by_devpath[devpath].start()
			threads.append(xpp_by_devpath[devpath])
		elif sp_name == "Astribanks-MPP":
			print("MPP:", devpath)
			mpp_by_devpath[devpath] = MPP(devpath, d)
			mpp_by_devpath[devpath].start()
			threads.append(mpp_by_devpath[devpath])
		else:
			print("ERROR:", devpath)

# Wait for all threads to complete
for t in threads:
	t.join()
print("Exiting Main Thread")

