Skip to content

Commit 93a1d73

Browse files
authored
Merge fc9ad9c into 81d81dc
2 parents 81d81dc + fc9ad9c commit 93a1d73

2 files changed

Lines changed: 149 additions & 1 deletion

File tree

source/bdDetect.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,12 @@ def driverSupportsAutoDetection(driver):
576576
"SmartBeetle",
577577
)))
578578

579+
# NattiqBraille
580+
addUsbDevices("nattiqbraille", KEY_SERIAL, {
581+
"VID_2341&PID_8036", # Atmel-based USB Serial for Nattiq nBraille
582+
})
583+
579584
# superBrl
580585
addUsbDevices("superBrl", KEY_SERIAL, {
581586
"VID_10C4&PID_EA60", # SuperBraille 3.2
582587
})
583-
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# brailleDisplayDrivers/nattiqbraille.py
2+
# A part of NonVisual Desktop Access (NVDA)
3+
# This file is covered by the GNU General Public License.
4+
# See the file COPYING for more details.
5+
# Copyright (C) 2020 NV Access Limited, Mohammed Noman
6+
7+
8+
9+
import serial
10+
import braille
11+
import inputCore
12+
from logHandler import log
13+
import hwIo
14+
15+
BAUD_RATE = 10000000
16+
INIT_TAG = b"0"
17+
RESET_TAG = b"reset"
18+
# Initialization response id
19+
INIT_RESP = 0
20+
# Keys response id
21+
ROUTE_RESP = 1
22+
UP_KEY_RESP = 2
23+
DOWN_KEY_RESP = 3
24+
RIGHT_KEY_RESP = 4
25+
LEFT_KEY_RESP = 5
26+
# Keys pressed id
27+
UP_KEY_PRESS = 1
28+
DOWN_KEY_PRESS = 2
29+
RIGHT_KEY_PRESS = 3
30+
LEFT_KEY_PRESS = 4
31+
32+
33+
class BrailleDisplayDriver(braille.BrailleDisplayDriver):
34+
name = "nattiqbraille"
35+
# Translators: Names of braille displays
36+
description = _("Nattiq nBraille")
37+
isThreadSafe = True
38+
39+
@classmethod
40+
def getManualPorts(cls):
41+
return braille.getSerialPorts()
42+
43+
def __init__(self, port="auto"):
44+
super(BrailleDisplayDriver, self).__init__()
45+
self._serial = None
46+
for portType, portId, port, portInfo in self._getTryPorts(port):
47+
log.debug("Checking port %s for a Nattiq nBraille", port)
48+
try:
49+
self._serial = hwIo.Serial(
50+
port, baudrate=BAUD_RATE, timeout=self.timeout, writeTimeout=self.timeout,
51+
parity=serial.PARITY_NONE, onReceive=self._onReceive
52+
)
53+
except EnvironmentError:
54+
log.debugWarning("", exc_info=True)
55+
continue
56+
# Check for cell information
57+
if self._describe():
58+
log.debug("Nattiq nBraille found on %s with %d cells", port, self.numCells)
59+
break
60+
else:
61+
self._serial.close()
62+
else:
63+
raise RuntimeError("Can't find a Nattiq nBraille device (port = %s)" % port)
64+
65+
def terminate(self):
66+
try:
67+
super(BrailleDisplayDriver, self).terminate()
68+
finally:
69+
self._serial.write(RESET_TAG)
70+
self._serial.close()
71+
self._serial = None
72+
73+
def _describe(self):
74+
self.numCells = 0
75+
log.debug("Writing reset tag")
76+
self._serial.write(RESET_TAG)
77+
self._serial.waitForRead(self.timeout * 10)
78+
log.debug("Writing init tag")
79+
self._serial.write(INIT_TAG)
80+
self._serial.waitForRead(self.timeout * 10)
81+
# If a valid response was received, _onReceive will have set numCells.
82+
if self.numCells:
83+
return True
84+
log.debug("Not a Nattiq nBraille")
85+
return False
86+
87+
def _onReceive(self, command):
88+
if int(command) == INIT_RESP:
89+
CELLS_NUM = self._serial.read(2)
90+
self.numCells = int(CELLS_NUM)
91+
elif int(command) == ROUTE_RESP:
92+
ROUTE_KEY = self._serial.read(2)
93+
inputCore.manager.executeGesture(RoutingInputGesture(int(ROUTE_KEY)))
94+
elif int(command) == UP_KEY_RESP:
95+
inputCore.manager.executeGesture(InputGestureKeys(UP_KEY_PRESS))
96+
log.debug("Up Key Pressed")
97+
elif int(command) == DOWN_KEY_RESP:
98+
inputCore.manager.executeGesture(InputGestureKeys(DOWN_KEY_PRESS))
99+
log.debug("Down Key Pressed")
100+
elif int(command) == RIGHT_KEY_RESP:
101+
inputCore.manager.executeGesture(InputGestureKeys(RIGHT_KEY_PRESS))
102+
log.debug("Right Key Pressed")
103+
elif int(command) == LEFT_KEY_RESP:
104+
inputCore.manager.executeGesture(InputGestureKeys(LEFT_KEY_PRESS))
105+
log.debug("Left Key Pressed")
106+
107+
def display(self, cells):
108+
cells = "-".join(str(cell) for cell in cells)
109+
log.debug(cells)
110+
self._serial.write(cells.encode())
111+
112+
gestureMap = inputCore.GlobalGestureMap({
113+
"globalCommands.GlobalCommands": {
114+
"braille_scrollBack": ("br(nattiqbraille):tback",),
115+
"braille_routeTo": ("br(nattiqbraille):routing",),
116+
"braille_scrollForward": ("br(nattiqbraille):tadvance",),
117+
"braille_previousLine": ("br(nattiqbraille):tprevious",),
118+
"braille_nextLine": ("br(nattiqbraille):tnext",),
119+
},
120+
})
121+
122+
123+
class InputGestureKeys(braille.BrailleDisplayGesture):
124+
source = BrailleDisplayDriver.name
125+
126+
def __init__(self, keys):
127+
super(InputGestureKeys, self).__init__()
128+
if keys == UP_KEY_PRESS:
129+
self.id = "tback"
130+
elif keys == DOWN_KEY_PRESS:
131+
self.id = "tadvance"
132+
elif keys == RIGHT_KEY_PRESS:
133+
self.id = "tnext"
134+
elif keys == LEFT_KEY_PRESS:
135+
self.id = "tprevious"
136+
137+
138+
class RoutingInputGesture(braille.BrailleDisplayGesture):
139+
source = BrailleDisplayDriver.name
140+
141+
def __init__(self, routingIndex):
142+
super(RoutingInputGesture, self).__init__()
143+
self.routingIndex = routingIndex
144+
self.id = "routing"

0 commit comments

Comments
 (0)