Package brailleDisplayDrivers :: Module hedoProfiLine
[hide private]
[frames] | no frames]

Source Code for Module brailleDisplayDrivers.hedoProfiLine

  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  )) 
49 50 -class BrailleDisplayDriver(braille.BrailleDisplayDriver):
51 name = "hedoProfiLine" 52 description = "hedo ProfiLine USB" 53 54 numCells = HEDO_CELL_COUNT 55 56 @classmethod
57 - def check(cls):
58 return True
59
60 - def __init__(self):
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
106 - def terminate(self):
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
116 - def display(self, cells):
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
126 - def handleResponses(self, wait=False):
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
135 - def handleData(self, data):
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
183 -class InputGestureKeys(braille.BrailleDisplayGesture):
184 185 source = BrailleDisplayDriver.name 186
187 - def __init__(self, keys):
188 super(InputGestureKeys, self).__init__() 189 190 self.id = keys
191
192 -class InputGestureRouting(braille.BrailleDisplayGesture):
193 194 source = BrailleDisplayDriver.name 195
196 - def __init__(self, index):
197 super(InputGestureRouting, self).__init__() 198 199 self.id = "routing" 200 self.routingIndex = index
201