summaryrefslogtreecommitdiffstats
path: root/4094sniffer/host/hc4094sniffer.py
blob: 89ef67b2e4d299510ccefb9048df87c6b09abd67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env python3
"""
 *   74HC4094 data sniffer
 *
 *   Copyright (C) 2010-2022 Michael Buesch <m@bues.ch>
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   version 2 as published by the Free Software Foundation.
 *
 *   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.
"""

import getopt
import sys
import time
try:
	from serial import *
except ImportError:
	print("ERROR: pyserial module not available.", file=sys.stderr)
	print("On Debian Linux please do:  apt-get install python3-serial", file=sys.stderr)
	sys.exit(1)


# Serial port config
SERIAL_BAUDRATE		= 115200
SERIAL_BYTESIZE		= 8
SERIAL_PARITY		= PARITY_NONE
SERIAL_STOPBITS		= 1


class SnifferException(Exception):
	pass

class Sniffer:
	def __init__(self, tty, numShiftregs):
		try:
			self.serial = Serial(tty, SERIAL_BAUDRATE,
					     SERIAL_BYTESIZE, SERIAL_PARITY,
					     SERIAL_STOPBITS)
			self.size = numShiftregs
			self.serial.read(self.serial.inWaiting())
			self.__doRead(self.size)
		except (SerialException, OSError, IOError) as e:
			raise SnifferException(str(e))

	def clear(self):
		self.__doRead(self.size ^ 0xFF)
		self.__doRead(self.size)

	def __doRead(self, size):
		self.serial.write(b"%c" % size)
		time.sleep(0.1)
		return self.serial.read(self.serial.inWaiting())

	def read(self):
		try:
			data = self.__doRead(self.size)
			if len(data) != self.size:
				raise SnifferException(
					"Unexpected data length. Is %d, expected %d" %\
					(len(data), self.size))
			return data
		except (SerialException, OSError, IOError) as e:
			raise SnifferException(str(e))

def toAscii(char):
	assert(isinstance(char, int))
	if char >= 32 and char <= 126:
		return chr(char)
	return "."

def dumpMem(mem):
	assert(isinstance(mem, (bytes, bytearray)))
	ascii = ""
	for i in range(len(mem)):
		if i % 16 == 0 and i != 0:
			print("  " + ascii + "\n", end='')
			ascii = ""
		if i % 16 == 0:
			print("0x%04X:  " % i, end='')
		c = mem[i]
		print("%02X" % c, end='')
		if (i % 2 != 0):
			print(" ", end='')
		ascii += toAscii(c)
	print("  " + ascii + "\n")

def usage():
	print("Usage: %s TTY NUM_SHIFTREGS" % sys.argv[0], file=sys.stderr)

def main(argv):
	try:
		tty = argv[1]
		numShiftregs = int(argv[2])
	except (IndexError, ValueError) as e:
		usage()
		return 1
	try:
		s = Sniffer(tty, numShiftregs)
		data = s.read()
		dumpMem(data)
	except SnifferException as e:
		print(str(e), file=sys.stderr)
	return 0

if __name__ == "__main__":
	sys.exit(main(sys.argv))
bues.ch cgit interface