blob: 036028eb973688c7a7ca04242f4760e2d63ae0c1 [file] [log] [blame]
cliechtib1055802004-04-16 01:10:29 +00001class BitaccessMeta(type):
2 """meta class that adds bit access properties to a
3 parallel port implementation"""
cliechti54f69b62009-07-21 19:48:41 +00004
cliechtib1055802004-04-16 01:10:29 +00005 def __new__(self, classname, bases, classdict):
6 klass = type.__new__(self, classname, bases, classdict)
cliechti54f69b62009-07-21 19:48:41 +00007 # status lines
cliechtib1055802004-04-16 01:10:29 +00008 klass.paperOut = property(klass.getInPaperOut, None, "Read the PaperOut signal")
cliechti54f69b62009-07-21 19:48:41 +00009 # control lines
cliechtib1055802004-04-16 01:10:29 +000010 klass.dataStrobe = property(None, klass.setDataStrobe, "Set the DataStrobe signal")
cliechti54f69b62009-07-21 19:48:41 +000011 # XXX ... other bits
12 # data bits
cliechtib1055802004-04-16 01:10:29 +000013 for bit in range(8):
14 mask = (1<<bit)
15 def getter(self, mask=mask):
16 return (self.getData() & mask) != 0
17 def setter(self, b, mask=mask):
18 if b:
19 self.setData(self.getData() | mask)
20 else:
21 self.setData(self.getData() & ~mask)
22 setattr(klass, "D%d" % bit, property(getter, setter, "Access databit %d" % bit))
cliechti54f69b62009-07-21 19:48:41 +000023 # nibbles
cliechtib1055802004-04-16 01:10:29 +000024 for name, shift, width in [('D0_D3', 0, 4), ('D4_D7', 4, 4)]:
25 mask = (1<<width) - 1
26 def getter(self, shift=shift, mask=mask):
27 return (self.getData() >> shift) & mask
28 def setter(self, b, shift=shift, mask=mask):
29 self.setData((self.getData() & ~(mask<<shift)) | ((b&mask) << shift))
30 setattr(klass, name, property(getter, setter, "Access to %s" % name))
31 return klass
32
33class VirtualParallelPort:
34 """provides a virtual parallel port implementation, useful
35 for tests and simulations without real hardware"""
cliechti54f69b62009-07-21 19:48:41 +000036
cliechtib1055802004-04-16 01:10:29 +000037 __metaclass__ = BitaccessMeta
cliechti54f69b62009-07-21 19:48:41 +000038
cliechtib1055802004-04-16 01:10:29 +000039 def __init__(self, port=None):
40 self._data = 0
cliechti54f69b62009-07-21 19:48:41 +000041
cliechtib1055802004-04-16 01:10:29 +000042 def setData(self, value):
43 self._data = value
44
45 def getData(self):
46 return self._data
47
cliechti54f69b62009-07-21 19:48:41 +000048 # inputs return dummy value
cliechtib1055802004-04-16 01:10:29 +000049 def getInPaperOut(self): return self._dummy
cliechti54f69b62009-07-21 19:48:41 +000050 # ...
51 # outputs just store a tuple with (action, value) pair
cliechtib1055802004-04-16 01:10:29 +000052 def setDataStrobe(self, value): self._last = ('setDataStrobe', value)
cliechti54f69b62009-07-21 19:48:41 +000053 # ...
cliechtib1055802004-04-16 01:10:29 +000054
cliechti54f69b62009-07-21 19:48:41 +000055# testing
cliechtib1055802004-04-16 01:10:29 +000056if __name__ == '__main__':
57 import unittest, sys
cliechti54f69b62009-07-21 19:48:41 +000058
cliechtib1055802004-04-16 01:10:29 +000059 class TestBitaccess(unittest.TestCase):
60 """Tests a port with no timeout"""
61 def setUp(self):
62 self.p = VirtualParallelPort()
cliechti54f69b62009-07-21 19:48:41 +000063
cliechtib1055802004-04-16 01:10:29 +000064 def testDatabits(self):
65 """bit by bit D0..D7"""
66 p = self.p
67 p.D0 = p.D2 = p.D4 = p.D6 = 1
68 self.failUnlessEqual(p._data, 0x55)
69 self.failUnlessEqual(
70 [p.D7, p.D6, p.D5, p.D4, p.D3, p.D2, p.D1, p.D0],
71 [0, 1, 0, 1, 0, 1, 0, 1]
72 )
73 p._data <<= 1
74 self.failUnlessEqual(
75 [p.D7, p.D6, p.D5, p.D4, p.D3, p.D2, p.D1, p.D0],
76 [1, 0, 1, 0, 1, 0, 1, 0]
77 )
cliechti54f69b62009-07-21 19:48:41 +000078
cliechtib1055802004-04-16 01:10:29 +000079 def testDatabitsGroups(self):
80 """nibbles D0..D7"""
81 p = self.p
82 p.D0_D3 = 14
83 self.failUnlessEqual(p._data, 0x0e)
84 p.D0_D3 = 0
85 p.D4_D7 = 13
86 self.failUnlessEqual(p._data, 0xd0)
87 p.D0_D3 = p.D4_D7 = 0xa
88 self.failUnlessEqual(p._data, 0xaa)
cliechti54f69b62009-07-21 19:48:41 +000089 # test bit patterns
cliechtib1055802004-04-16 01:10:29 +000090 for x in range(256):
cliechti54f69b62009-07-21 19:48:41 +000091 # test getting
cliechtib1055802004-04-16 01:10:29 +000092 p._data = x
93 self.failUnlessEqual((p.D4_D7, p.D0_D3), (((x>>4) & 0xf), (x & 0xf)))
cliechti54f69b62009-07-21 19:48:41 +000094 # test setting
cliechtib1055802004-04-16 01:10:29 +000095 p._data = 0
96 (p.D4_D7, p.D0_D3) = (((x>>4) & 0xf), (x & 0xf))
97 self.failUnlessEqual(p._data, x)
cliechti54f69b62009-07-21 19:48:41 +000098
cliechtib1055802004-04-16 01:10:29 +000099 def testStatusbits(self):
100 """bit by bit status lines"""
cliechti54f69b62009-07-21 19:48:41 +0000101 # read the property:
cliechtib1055802004-04-16 01:10:29 +0000102 self.p._dummy = 0
103 self.failUnlessEqual(self.p.paperOut, 0)
cliechti54f69b62009-07-21 19:48:41 +0000104
cliechtib1055802004-04-16 01:10:29 +0000105 self.p._dummy = 1
106 self.failUnlessEqual(self.p.paperOut, 1)
cliechti54f69b62009-07-21 19:48:41 +0000107
108 # read only, must not be writable:
cliechtib1055802004-04-16 01:10:29 +0000109 self.failUnlessRaises(AttributeError, setattr, self.p, 'paperOut', 1)
cliechti54f69b62009-07-21 19:48:41 +0000110
cliechtib1055802004-04-16 01:10:29 +0000111 def testControlbits(self):
112 """bit by bit control lines"""
113 self.p.dataStrobe = 0
114 self.failUnlessEqual(self.p._last, ('setDataStrobe', 0))
115 self.p.dataStrobe = 1
116 self.failUnlessEqual(self.p._last, ('setDataStrobe', 1))
cliechti54f69b62009-07-21 19:48:41 +0000117
118 # write only, must not be writable:
cliechtib1055802004-04-16 01:10:29 +0000119 self.failUnlessRaises(AttributeError, getattr, self.p, 'dataStrobe')
cliechti54f69b62009-07-21 19:48:41 +0000120
cliechtib1055802004-04-16 01:10:29 +0000121 sys.argv.append('-v')
122 # When this module is executed from the command-line, it runs all its tests
123 unittest.main()
cliechti54f69b62009-07-21 19:48:41 +0000124