Skip to content

Commit 3d86cfb

Browse files
Merge a1db542 into dff28c7
2 parents dff28c7 + a1db542 commit 3d86cfb

2 files changed

Lines changed: 69 additions & 5 deletions

File tree

source/brailleDisplayDrivers/handyTech.py

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ def windowProc(self, hwnd: int, msg: int, wParam: int, lParam: int):
110110
MODEL_MODULAR_80 = b"\x88"
111111
MODEL_MODULAR_40 = b"\x89"
112112
MODEL_ACTIVATOR = b"\xA4"
113+
MODEL_ACTIVATOR_PRO_64 = b"\xA6"
114+
MODEL_ACTIVATOR_PRO_80 = b"\xA8"
113115

114116
# Key constants
115117
KEY_B1 = 0x03
@@ -373,6 +375,15 @@ def display(self, cells: List[int]):
373375
super(StatusCellMixin, self).display(cells)
374376

375377

378+
class ActiveSplitMixin(object):
379+
"""Mixin for displays supporting ActiveSplit, i.e. dynamic adjustment of number of cells"""
380+
381+
def postInit(self):
382+
super(ActiveSplitMixin, self).postInit()
383+
log.debug("Prevent disconnect/reconnect activity for dynamic length adjustment")
384+
self._display.sendExtendedPacket(HT_EXTPKT_NO_RECONNECT)
385+
386+
376387
class ModularConnect88(TripleActionKeysMixin, Model):
377388
deviceId = MODEL_MODULAR_CONNECT_88
378389
genericName = "Modular Connect"
@@ -531,7 +542,14 @@ class Modular80(Modular):
531542
numCells = 80
532543

533544

534-
class Activator(TimeSyncFirmnessMixin, AtcMixin, JoystickMixin, TripleActionKeysMixin, Model):
545+
class Activator(
546+
ActiveSplitMixin,
547+
TimeSyncFirmnessMixin,
548+
AtcMixin,
549+
JoystickMixin,
550+
TripleActionKeysMixin,
551+
Model
552+
):
535553
deviceId = MODEL_ACTIVATOR
536554
numCells = 40
537555
genericName = name = 'Activator'
@@ -545,6 +563,40 @@ def _get_keys(self) -> Dict[int, str]:
545563
return keys
546564

547565

566+
class ActivatorPro64(
567+
ActiveSplitMixin,
568+
TimeSyncFirmnessMixin,
569+
AtcMixin,
570+
TripleActionKeysMixin,
571+
Model
572+
):
573+
deviceId = MODEL_ACTIVATOR_PRO_64
574+
numCells = 64
575+
genericName = name = 'Activator Pro 64'
576+
577+
def _get_keys(self) -> Dict[int, str]:
578+
keys = super().keys
579+
keys.update({
580+
0x7A: "escape",
581+
0x7B: "return",
582+
})
583+
return keys
584+
585+
586+
class ActivatorPro80(ActiveSplitMixin, TimeSyncFirmnessMixin, AtcMixin, TripleActionKeysMixin, Model):
587+
deviceId = MODEL_ACTIVATOR_PRO_80
588+
numCells = 80
589+
genericName = name = 'Activator Pro 80'
590+
591+
def _get_keys(self) -> Dict[int, str]:
592+
keys = super().keys
593+
keys.update({
594+
0x7A: "escape",
595+
0x7B: "return",
596+
})
597+
return keys
598+
599+
548600
def _allSubclasses(cls):
549601
"""List all direct and indirect subclasses of cls
550602
@@ -569,6 +621,7 @@ def _allSubclasses(cls):
569621
HT_PKT_NAK = b"\x7D"
570622
HT_PKT_ACK = b"\x7E"
571623
HT_PKT_OK = b"\xFE"
624+
HT_PKT_OK_WITH_LENGTH = b"\xFD"
572625
HT_PKT_RESET = b"\xFF"
573626
HT_EXTPKT_BRAILLE = HT_PKT_BRAILLE
574627
HT_EXTPKT_KEY = b"\x04"
@@ -589,6 +642,7 @@ def _allSubclasses(cls):
589642
HT_EXTPKT_GET_FIRMNESS = b"\x61"
590643
HT_EXTPKT_GET_PROTOCOL_PROPERTIES = b"\xC1"
591644
HT_EXTPKT_GET_FIRMWARE_VERSION = b"\xC2"
645+
HT_EXTPKT_NO_RECONNECT = b"\xAE"
592646

593647
# HID specific constants
594648
HT_HID_RPT_OutData = b"\x01" # receive data from device
@@ -637,6 +691,8 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar):
637691
"VID_1FE4&PID_0093", # Basic Braille Plus 32
638692
"VID_1FE4&PID_0094", # Basic Braille Plus 40
639693
"VID_1FE4&PID_00A4", # Activator
694+
"VID_1FE4&PID_00A6", # Activator Pro 64
695+
"VID_1FE4&PID_00A8", # Activator Pro 80
640696
})
641697

642698
# Some older HT displays use a HID converter and an internal serial interface
@@ -656,7 +712,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar):
656712
"Braillino BL",
657713
"Braille Wave BW",
658714
"Easy Braille EBR",
659-
"Activator AC",
715+
"Activator",
660716
)))
661717

662718
@classmethod
@@ -712,6 +768,9 @@ def __init__(self, port="auto"):
712768

713769
if self.numCells:
714770
# A display responded.
771+
if not isinstance(self._model, OldProtocolMixin):
772+
self.sendExtendedPacket(HT_EXTPKT_GET_PROTOCOL_PROPERTIES)
773+
self._dev.waitForRead(self.timeout)
715774
self._model.postInit()
716775
log.info("Found {device} connected via {type} ({port})".format(
717776
device=self._model.name, type=portType, port=port))
@@ -923,15 +982,18 @@ def _serialOnReceive(self, data: bytes):
923982
self._handleInputStream(data, self._dev)
924983

925984
def _handleInputStream(self, htPacketType: bytes, stream):
926-
if htPacketType in (HT_PKT_OK, HT_PKT_EXTENDED):
985+
if htPacketType in (HT_PKT_OK, HT_PKT_EXTENDED, HT_PKT_OK_WITH_LENGTH):
927986
modelId: bytes = stream.read(1)
928987
if not self._model:
929988
if modelId not in MODELS:
930989
log.debugWarning("Unknown model: %r" % modelId)
931990
raise RuntimeError(
932991
"The model with ID %r is not supported by this driver" % modelId)
933992
self._model = MODELS.get(modelId)(self)
934-
self.numCells = self._model.numCells
993+
if htPacketType == HT_PKT_OK_WITH_LENGTH:
994+
self.numCells = ord(stream.read(1))
995+
else:
996+
self.numCells = self._model.numCells
935997
elif self._model.deviceId != modelId:
936998
# Somehow the model ID of this display changed, probably another display
937999
# plugged in the same (already open) serial port.
@@ -962,7 +1024,7 @@ def _handleInputStream(self, htPacketType: bytes, stream):
9621024
# Ignore ATC packets for now
9631025
pass
9641026
elif extPacketType == HT_EXTPKT_GET_PROTOCOL_PROPERTIES:
965-
pass
1027+
self.numCells = packet[3]
9661028
elif isinstance(self._model, TimeSyncFirmnessMixin):
9671029
if extPacketType == HT_EXTPKT_GET_RTC:
9681030
self._model.handleTime(packet[1:])

user_docs/en/changes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ Unicode CLDR has been updated.
2121
* This can be useful when reading characters that are unknown to a particular speech synthesizer or braille table and which have a compatible alternative, like the bold and italic characters commonly used on social media.
2222
* It also allows reading of equations in the Microsoft Word equation editor. (#4631)
2323
* You can enable this functionality for both speech and braille in their respective settings categories in the NVDA Settings dialog.
24+
* New Braille features:
25+
* Added support for the Help Tech Activator Pro displays.
2426

2527
### Changes
2628

0 commit comments

Comments
 (0)