| Trees | Indices | Help |
|---|
|
|
1 #A part of NonVisual Desktop Access (NVDA)
2 #This file is covered by the GNU General Public License.
3 #See the file COPYING for more details.
4 #Copyright (C) 2011 Sebastian Kruber <sebastian.kruber@hedo.de>
5
6 # Parts of this code are inherited from the baum braille driver
7 # written by James Teh <jamie@jantrid.net>
8
9 # This file represents the braille display driver for
10 # hedo ProfiLine USB, a product from hedo Reha-Technik GmbH
11 # see www.hedo.de for more details
12
13 import time
14 import wx
15 import serial
16 import braille
17 import inputCore
18 import hwPortUtils
19 from logHandler import log
20
21 HEDO_TIMEOUT = 0.2
22 HEDO_BAUDRATE = 19200
23 HEDO_READ_INTERVAL = 50
24 HEDO_ACK = 0x7E
25 HEDO_INIT = 0x01
26 HEDO_CR_BEGIN = 0x20
27 HEDO_CR_END = 0x6F
28 HEDO_RELEASE_OFFSET = 0x80
29 HEDO_CELL_COUNT = 80
30 HEDO_STATUS_CELL_COUNT = 4
31
32 HEDO_KEYMAP = {
33 0x04: "K1",
34 0x03: "K2", # K2 or B1
35 0x08: "K3",
36 0x07: "B2",
37 0x0B: "B3",
38 0x0F: "B4",
39 0x13: "B5",
40 0x17: "B6",
41 0x1B: "B7",
42 0x1F: "B8",
43 }
44
45 HEDO_USB_IDS = frozenset((
46 "VID_0403&PID_DE59", # Hedo ProfiLine
47 "VID_0403&PID_DE58", # Hedo MobiLine
48 ))
51 name = "hedoProfiLine"
52 description = "hedo ProfiLine USB"
53
54 numCells = HEDO_CELL_COUNT
55
56 @classmethod
59
61 super(BrailleDisplayDriver, self).__init__()
62
63 for portInfo in hwPortUtils.listComPorts(onlyAvailable=True):
64 port = portInfo["port"]
65 hwID = portInfo["hardwareID"]
66 #log.info("Found port {port} with hardwareID {hwID}".format(port=port, hwID=hwID))
67 if not hwID.startswith(r"FTDIBUS\COMPORT"):
68 continue
69 try:
70 usbID = hwID.split("&", 1)[1]
71 except IndexError:
72 continue
73 if usbID not in HEDO_USB_IDS:
74 continue
75 # At this point, a port bound to this display has been found.
76 # Try talking to the display.
77 try:
78 self._ser = serial.Serial(port, baudrate=HEDO_BAUDRATE, timeout=HEDO_TIMEOUT, writeTimeout=HEDO_TIMEOUT, parity=serial.PARITY_ODD, bytesize=serial.EIGHTBITS, stopbits=serial.STOPBITS_ONE)
79 except serial.SerialException:
80 continue
81
82 # Prepare a blank line
83 cells = chr(HEDO_INIT) + chr(0) * (HEDO_CELL_COUNT + HEDO_STATUS_CELL_COUNT)
84
85 # Send the blank line twice
86 self._ser.write(cells)
87 self._ser.flush()
88 self._ser.write(cells)
89 self._ser.flush()
90
91 # Read out the input buffer
92 ackS = self._ser.read(2)
93 if chr(HEDO_ACK) in ackS:
94 log.info("Found hedo ProfiLine connected via {port}".format(port=port))
95 break
96
97 else:
98 raise RuntimeError("No hedo display found")
99
100 self._readTimer = wx.PyTimer(self.handleResponses)
101 self._readTimer.Start(HEDO_READ_INTERVAL)
102
103 self._keysDown = set()
104 self._ignoreKeyReleases = False
105
107 try:
108 super(BrailleDisplayDriver, self).terminate()
109 self._readTimer.Stop()
110 self._readTimer = None
111 finally:
112 # We absolutely must close the Serial object, as it does not have a destructor.
113 # If we don't, we won't be able to re-open it later.
114 self._ser.close()
115
117 # every transmitted line consists of the preamble HEDO_INIT, the statusCells and the Cells
118 line = chr(HEDO_INIT) + chr(0) * HEDO_STATUS_CELL_COUNT + "".join(chr(cell) for cell in cells)
119
120 # cells will be padded up to 1 + numStatusCells + numCells.
121 expectedLength = 1 + HEDO_STATUS_CELL_COUNT + HEDO_CELL_COUNT
122 line += chr(0) * (expectedLength - len(line))
123
124 self._ser.write(line)
125
127 while wait or self._ser.inWaiting():
128 data = self._ser.read(1)
129 if data:
130 # do not handle acknowledge bytes
131 if data != chr(HEDO_ACK):
132 self.handleData(ord(data))
133 wait = False
134
136
137 if data >= HEDO_CR_BEGIN and data <= HEDO_CR_END:
138 # Routing key is pressed
139 try:
140 inputCore.manager.executeGesture(InputGestureRouting(data - HEDO_CR_BEGIN))
141 except inputCore.NoInputGestureAction:
142 log.debug("No Action for routing command")
143 pass
144
145 elif data >= (HEDO_CR_BEGIN + HEDO_RELEASE_OFFSET) and data <= (HEDO_CR_END + HEDO_RELEASE_OFFSET):
146 # Routing key is released
147 return
148
149 elif data in HEDO_KEYMAP:
150 # A key is pressed
151 # log.debug("Key " + HEDO_KEYMAP[data] + " pressed")
152 self._keysDown.add(HEDO_KEYMAP[data])
153 self._ignoreKeyReleases = False
154
155 elif data > HEDO_RELEASE_OFFSET and (data - HEDO_RELEASE_OFFSET) in HEDO_KEYMAP:
156 # A key is released
157 # log.debug("Key " + str(self._keysDown) + " released")
158 if self._ignoreKeyReleases == False:
159 keys = "+".join(self._keysDown)
160 self._ignoreKeyReleases = True
161 self._keysDown = set()
162 try:
163 inputCore.manager.executeGesture(InputGestureKeys(keys))
164 except inputCore.NoInputGestureAction:
165 log.debug("No Action for keys {keys}".format(keys=keys))
166 pass
167
168 # else:
169 # log.debug("Key " + hex(data) + " not identified")
170
171 gestureMap = inputCore.GlobalGestureMap({
172 "globalCommands.GlobalCommands": {
173 "braille_scrollBack": ("br(hedoProfiLine):K1",),
174 "braille_toggleTether": ("br(hedoProfiLine):K2",),
175 "braille_scrollForward": ("br(hedoProfiLine):K3",),
176 "braille_previousLine": ("br(hedoProfiLine):B2",),
177 "braille_nextLine": ("br(hedoProfiLine):B5",),
178 "sayAll": ("br(hedoProfiLine):B6",),
179 "braille_routeTo": ("br(hedoProfiLine):routing",),
180 },
181 })
182
191
193
194 source = BrailleDisplayDriver.name
195
197 super(InputGestureRouting, self).__init__()
198
199 self.id = "routing"
200 self.routingIndex = index
201
| Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Fri Nov 18 17:46:09 2011 | http://epydoc.sourceforge.net |