Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for new braille display from Nattiq #10778

Merged
merged 20 commits into from
Mar 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion source/bdDetect.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,12 @@ def driverSupportsAutoDetection(driver):
"SmartBeetle",
)))

# NattiqBraille
m-noman marked this conversation as resolved.
Show resolved Hide resolved
addUsbDevices("nattiqbraille", KEY_SERIAL, {
"VID_2341&PID_8036", # Atmel-based USB Serial for Nattiq nBraille
})

# superBrl
addUsbDevices("superBrl", KEY_SERIAL, {
"VID_10C4&PID_EA60", # SuperBraille 3.2
})

143 changes: 143 additions & 0 deletions source/brailleDisplayDrivers/nattiqbraille.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# brailleDisplayDrivers/nattiqbraille.py
# A part of NonVisual Desktop Access (NVDA)
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.
# Copyright (C) 2020 NV Access Limited, Mohammed Noman - Nattiq Technologies


import serial
import braille
import inputCore
from logHandler import log
import hwIo

BAUD_RATE = 10000000
INIT_TAG = b"0"
RESET_TAG = b"reset"
# Initialization response id
INIT_RESP = 0
# Keys response id
ROUTE_RESP = 1
UP_KEY_RESP = 2
DOWN_KEY_RESP = 3
RIGHT_KEY_RESP = 4
LEFT_KEY_RESP = 5
# Keys pressed id
UP_KEY_PRESS = 1
DOWN_KEY_PRESS = 2
RIGHT_KEY_PRESS = 3
LEFT_KEY_PRESS = 4


class BrailleDisplayDriver(braille.BrailleDisplayDriver):
name = "nattiqbraille"
# Translators: Names of braille displays
description = _("Nattiq nBraille")
isThreadSafe = True

@classmethod
def getManualPorts(cls):
return braille.getSerialPorts()

def __init__(self, port="auto"):
super(BrailleDisplayDriver, self).__init__()
self._serial = None
for portType, portId, port, portInfo in self._getTryPorts(port):
log.debug("Checking port %s for a Nattiq nBraille", port)
try:
self._serial = hwIo.Serial(
port, baudrate=BAUD_RATE, timeout=self.timeout, writeTimeout=self.timeout,
parity=serial.PARITY_NONE, onReceive=self._onReceive
)
except EnvironmentError:
log.debugWarning("", exc_info=True)
continue
# Check for cell information
if self._describe():
log.debug("Nattiq nBraille found on %s with %d cells", port, self.numCells)
break
else:
self._serial.close()
else:
raise RuntimeError("Can't find a Nattiq nBraille device (port = %s)" % port)

def terminate(self):
try:
super(BrailleDisplayDriver, self).terminate()
finally:
self._serial.write(RESET_TAG)
self._serial.close()
self._serial = None

def _describe(self):
self.numCells = 0
log.debug("Writing reset tag")
self._serial.write(RESET_TAG)
self._serial.waitForRead(self.timeout * 10)
log.debug("Writing init tag")
self._serial.write(INIT_TAG)
self._serial.waitForRead(self.timeout * 10)
# If a valid response was received, _onReceive will have set numCells.
if self.numCells:
return True
log.debug("Not a Nattiq nBraille")
return False

def _onReceive(self, command):
if int(command) == INIT_RESP:
CELLS_NUM = self._serial.read(2)
self.numCells = int(CELLS_NUM)
elif int(command) == ROUTE_RESP:
ROUTE_KEY = self._serial.read(2)
inputCore.manager.executeGesture(RoutingInputGesture(int(ROUTE_KEY)))
elif int(command) == UP_KEY_RESP:
inputCore.manager.executeGesture(InputGestureKeys(UP_KEY_PRESS))
log.debug("Up Key Pressed")
elif int(command) == DOWN_KEY_RESP:
inputCore.manager.executeGesture(InputGestureKeys(DOWN_KEY_PRESS))
log.debug("Down Key Pressed")
elif int(command) == RIGHT_KEY_RESP:
inputCore.manager.executeGesture(InputGestureKeys(RIGHT_KEY_PRESS))
log.debug("Right Key Pressed")
elif int(command) == LEFT_KEY_RESP:
inputCore.manager.executeGesture(InputGestureKeys(LEFT_KEY_PRESS))
log.debug("Left Key Pressed")

def display(self, cells):
cells = "-".join(str(cell) for cell in cells)
m-noman marked this conversation as resolved.
Show resolved Hide resolved
log.debug(cells)
self._serial.write(cells.encode())
m-noman marked this conversation as resolved.
Show resolved Hide resolved

gestureMap = inputCore.GlobalGestureMap({
"globalCommands.GlobalCommands": {
"braille_scrollBack": ("br(nattiqbraille):tback",),
"braille_routeTo": ("br(nattiqbraille):routing",),
"braille_scrollForward": ("br(nattiqbraille):tadvance",),
"braille_previousLine": ("br(nattiqbraille):tprevious",),
"braille_nextLine": ("br(nattiqbraille):tnext",),
},
})


class InputGestureKeys(braille.BrailleDisplayGesture):
source = BrailleDisplayDriver.name

def __init__(self, keys):
super(InputGestureKeys, self).__init__()
if keys == UP_KEY_PRESS:
self.id = "tback"
elif keys == DOWN_KEY_PRESS:
self.id = "tadvance"
elif keys == RIGHT_KEY_PRESS:
self.id = "tnext"
elif keys == LEFT_KEY_PRESS:
self.id = "tprevious"


class RoutingInputGesture(braille.BrailleDisplayGesture):
source = BrailleDisplayDriver.name

def __init__(self, routingIndex):
super(RoutingInputGesture, self).__init__()
self.routingIndex = routingIndex
self.id = "routing"
17 changes: 17 additions & 0 deletions user_docs/en/userGuide.t2t
Original file line number Diff line number Diff line change
Expand Up @@ -2175,6 +2175,7 @@ The following displays support this automatic detection functionality.
- Optelec ALVA 6 series
- HIMS Braille Sense/Braille EDGE/Smart Beetle/Sync Braille Series
- Eurobraille Esys/Esytime/Iris displays
- Nattiq nBraille displays
-

++ Freedom Scientific Focus/PAC Mate Series ++[FreedomScientificFocus]
Expand Down Expand Up @@ -2956,6 +2957,22 @@ Please see the display's documentation for descriptions of where these keys can
| ToggleHID keyboard input simulation | esytime):l1+joystick1Down, esytime):l8+joystick1Down |
%kc:endInclude

++ Nattiq nBraille Displays ++[NattiqTechnologies]
NVDA supports displays from [Nattiq Technologies https://www.nattiq.com/] when connected via USB.
Windows 10 detects the Braille Displays once connected, you may need to install USB drivers if using older versions of Windows (below Win10).
You can get them from the manufacturer's website.

Following are the key assignments for Nattiq Technologies displays with NVDA.
Please see the display's documentation for descriptions of where these keys can be found.
%kc:beginInclude
|| Name | Key |
| Scroll braille display back | up |
| Scroll braille display forward | down |
m-noman marked this conversation as resolved.
Show resolved Hide resolved
| Move braille display to previous line | left |
| Move braille display to next line | right |
| Route to braille cell | routing |
%kc:endInclude

++ BRLTTY ++[BRLTTY]
[BRLTTY https://www.brltty.com/] is a separate program which can be used to support many more braille displays.
In order to use this, you need to install [BRLTTY for Windows https://www.brltty.com/download.html].
Expand Down