From 03632dfc10df0bf85625cc7b34d3d994f9bfb3fc Mon Sep 17 00:00:00 2001 From: klaute Date: Mon, 29 Aug 2016 17:48:24 +0200 Subject: [PATCH] Multiplexer control script added. --- tools/muxctrl.py | 334 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100755 tools/muxctrl.py diff --git a/tools/muxctrl.py b/tools/muxctrl.py new file mode 100755 index 0000000..4f7784f --- /dev/null +++ b/tools/muxctrl.py @@ -0,0 +1,334 @@ + +############################################################################### + +import argparse +import threading +import time +import serial +import copy + +############################################################################### + +parser = argparse.ArgumentParser(description='USB2SerialMux control helper tool.') +parser.add_argument("-g", "--getbaudrate", default=False, help="", action='store_true') +parser.add_argument("-s", "--setbaudrate", type=int, help="Something like 9600 or 115200.") +parser.add_argument("-m", "--getmuxline", default=False, help="", action='store_true') +parser.add_argument("-l", "--setmuxline", type=int, help="Something like 0 to 7.") +parser.add_argument("-r", "--resettobtldr", default=False, help="Reset the device to the LUFA bootloader.", action='store_true') + +############################################################################### + +MSG_SOD1 = 0x3c +MSG_SOD2 = 0x3e +MSG_EOD1 = 0x0d +MSG_EOD2 = 0x0a + +MSG_TYPE_ANSWER_OK = 0x01 +MSG_TYPE_ANSWER_NOK = 0x02 +MSG_TYPE_BAUDRATE = 0x03 +MSG_TYPE_MUXLINE = 0x04 + +CC_CMD_SET_BAUDRATE = 0x0A +CC_CMD_GET_BAUDRATE = 0x14 +CC_CMD_SET_MUX_LINE = 0x1E +CC_CMD_GET_MUX_LINE = 0x28 +CC_CMD_START_BTLDR = 0x32 + +CC_CMD_GET_BAUDRATE_DATA_TO_RECV 4 +CC_CMD_SET_BAUDRATE_DATA_TO_RECV 0 +CC_CMD_GET_MUX_LINE_DATA_TO_RECV 1 +CC_CMD_SET_MUX_LINE_DATA_TO_RECV 0 +CC_CMD_START_BTLDR_DATA_TO_RECV 0 + +############################################################################### + +TIMEOUT_CNT_MAX = 1000 +MAIN_LOOP_DELAY_S = 0.05 +THREAD_LOOP_DELAY_S = 0.01 + +############################################################################### + +baudrate = 0xffffffff +muxLine = 0xff + +############################################################################### + +CC_STATE_WAIT_SOD1 = 0x01 +CC_STATE_WAIT_SOD2 = 0x02 +CC_STATE_READ_DATA = 0x03 +CC_STATE_WAIT_EOD1 = 0x04 +CC_STATE_WAIT_EOD2 = 0x05 + +cc_state = CC_STATE_WAIT_SOD1 + +cc_cmd_list = [ CC_CMD_SET_BAUDRATE, + CC_CMD_GET_BAUDRATE, + CC_CMD_SET_MUX_LINE, + CC_CMD_GET_MUX_LINE, + CC_CMD_START_BTLDR, ] + +cc_state_fn = { CC_STATE_WAIT_SOD1 : cc_state_fn_wait_for_sod1, + CC_STATE_WAIT_SOD2 : cc_state_fn_wait_for_sod2, + CC_STATE_WAIT_EOD1 : cc_state_fn_wait_for_eod1, + CC_STATE_WAIT_EOD2 : cc_state_fn_wait_for_eod2, + CC_STATE_GET_TYPE : cc_state_fn_get_type, + CC_STATE_READ_DATA : cc_state_fn_read_data, } + +cc_cmd_data_to_read = { CC_CMD_SET_BAUDRATE : CC_CMD_SET_BAUDRATE_DATA_TO_RECV, + CC_CMD_GET_BAUDRATE : CC_CMD_GET_BAUDRATE_DATA_TO_RECV, + CC_CMD_SET_MUX_LINE : CC_CMD_SET_MUX_LINE_DATA_TO_RECV, + CC_CMD_GET_MUX_LINE : CC_CMD_GET_MUX_LINE_DATA_TO_RECV, + CC_CMD_START_BTLDR : CC_CMD_START_BTLDR_DATA_TO_RECV, } + +cc_data_read = 0 +cc_type = 0 +cc_data_buffer = [] + +# yes a separate counter to manage the order of the received messages +cc_message_cnt = 0 +cc_received_messages = [] + +############################################################################### + +thread_obj = None +thread_lock = None + +############################################################################### + +########## function to call by the thread +def processReceivedData(): + + incoming = [] + + thread_started = True + + for thread_stop == False: + + # 1. read byte from serial port into incoming + # 2. process the received data + for c in incoming: + cc_state_fn[cc_state](c) + + time.sleep(THREAD_LOOP_DELAY_S) + + thread_started = False + +########## +def startReceiverThread(): + if thread_started == False: + thread_lock = threading.Lock() + thread_obj = threading.Thread(target=processReceivedData) + thread_obj.start() + thread_stop = False + +########## +def stopReceiverThread(): + thread_stop = True + thread_obj.join() # wait for the thread to finish + +##### CC_STATE_WAIT_SOD1 +def cc_state_fn_wait_for_sod1(c): + cc_data_read = 0 + cc_type = 0 + cc_data_buffer = [] + + if c == MSG_SOD1: + cc_state = CC_STATE_WAIT_SOD2 + else + cc_state = CC_STATE_WAIT_SOD1 + +##### CC_STATE_WAIT_SOD2 +def cc_state_fn_wait_for_sod2(c): + if c == MSG_SOD2: + cc_state = CC_STATE_GET_TYPE + else + cc_state = CC_STATE_WAIT_SOD1 + +##### CC_STATE_GET_TYPE +def cc_state_fn_get_type(c): + if c in cc_cmd_list: + cc_type = c + if cc_cmd_data_to_read[cc_type] > 0: + cc_state = CC_STATE_READ_DATA + else: + cc_state = CC_STATE_WAIT_EOD1 + else + cc_state = CC_STATE_WAIT_SOD1 + +##### CC_STATE_READ_DATA +def cc_state_fn_read_data(c): + if cc_data_read <= cc_state_data_to_read[cc_state] - 1: + cc_data_buffer[cc_data_read] = c + cc_data_read = cc_data_read + 1 + + if cc_data_read == cc_state_data_to_read[cc_state]: + cc_state = CC_STATE_WAIT_EOD1 + +##### CC_STATE_WAIT_EOD1 +def cc_state_fn_wait_for_eod1(c): + if c == MSG_EOD1: + cc_state = CC_STATE_WAIT_EOD2 + else + cc_state = CC_STATE_WAIT_SOD1 + +##### CC_STATE_WAIT_EOD2 +def cc_state_fn_wait_for_eod2(c): + if c == MSG_EOD2: + # TODO process or save the data + is_message_read = False + thread_lock.acquire() + cc_received_messages.append([ cc_message_cnt, cc_type, is_message_read, copy.deepcopy(cc_data_buffer) ]) + thread_lock.release() + cc_message_cnt = cc_message_cnt + 1 + + cc_state = CC_STATE_WAIT_SOD1 + +############################################################################### + +def getBaudrate(): + print "send: get baudrate " % CC_CMD_GET_BAUDRATE + sendSerialData([CC_CMD_GET_BAUDRATE]) + +def setBaudrate(b): + print "send: set baudrate " % CC_CMD_SET_BAUDRATE + sendSerialData([CC_CMD_SET_BAUDRATE, + (baudrate & 0xff000000) >> 24, + (baudrate & 0xff0000) >> 16, + (baudrate & 0xff00) >> 8, + (baudrate & 0xff)]) + +############################################################################### + +def getMuxLine(): + print "send: get mux line " % CC_CMD_GET_MUX_LINE + sendSerialData([CC_CMD_GET_MUX_LINE]) + +def setMuxLine(l): + print "send: set mux line " % CC_CMD_SET_MUX_LINE + sendSerialData([CC_CMD_SET_MUX_LINE, muxLine]) + +############################################################################### + +def getStatus(): + + getBaudrate() + getMuxLine() + +############################################################################### + +def resetToBtldr(): + print "send: reset to bootloader message " % CC_CMD_START_BTLDR + sendSerialData([CC_CMD_START_BTLDR]) + +############################################################################### + +##### +def openSerialDevice(d): + pass + +##### +def closeSerialDevice(): + pass + +##### +def sendSerialData(data): + for c in data: + + pass + +############################################################################### + +if __name__ == "__main__": + + # parse the commandline arguments + args = parser.parse_args() + + dataSend = 0 + timeout = 0 + + # 1. open serial device or abort + openSerialDevice("/dev/ttyACM0") + + # 2. start thread to poll processReceivedData() + startReceiverThread() + + # 3. get status + getStatus() + + # 4. get and process the commandline arguments/parameter + if args.resettobtldr == True: + resetToBtldr() + + else: + + if args.getbaudrate == True: + getBaudrate() + dataSend = dataSend + 1 + + if args.getmuxline == True: + getMuxLine() + dataSend = dataSend + 1 + + if args.setbaudrate != None: + baudrate = map(int, args.setbaudrate) + setBaudrate(baudrate) + dataSend = dataSend + 1 + + if args.setmuxline != None: + muxLine = map(int, args.setmuxline) + if muxLine < 0: + muxLine = 0 + if muxLine > 7: + muxLine = 7 + setMuxLine(muxLine) + dataSend = dataSend + 1 + + # 5. start main loop + for dataSend > 0 and timeout < TIMEOUT_CNT_MAX: + + thread_lock.acquire() + tmp_messages = copy.deepcopy(cc_received_messages) + thread_lock.release() + + # 5.1 wait for the response(s) + for e in tmp_messages: + if e[2] == False: # test for unread message + + # process it and set the data to read + if e[1] == MSG_TYPE_ANSWER_OK: + print "recv: OK" + elif e[1] == MSG_TYPE_ANSWER_NOK: + print "recv: NOT OK" + elif e[1] == MSG_TYPE_BAUDRATE: + baudrate = e[3][0] << 24 + baudrate = baudrate + e[3][1] << 16 + baudrate = baudrate + e[3][2] << 8 + baudrate = baudrate + e[3][3] + print "recv: baudrate = " % baudrate + elif e[1] == MSG_TYPE_MUXLINE: + muxLine = e[3][0] + print "recv: muxLine = " % muxLine + else: + print "err: unknown type " % e[1] + break + + thread_lock.acquire() + cc_received_messages[e[0]][2] = True + thread_lock.release() + + timeout = 0 # reset the timeout + + # reduce the number of messages to receive + dataSend = dataSend - 1 + + # manage the timeout behaviour + time.sleep(MAIN_LOOP_DELAY_S) + timeout = timeout + 1 + + # 6. stop data processing thread + stopReceiverThread() + + # 7. close serial device + closeSerialDevice() + + exit(0)