Skip to content

Commit abb1d08

Browse files
Merge 3b78aaa into dff28c7
2 parents dff28c7 + 3b78aaa commit abb1d08

1 file changed

Lines changed: 54 additions & 5 deletions

File tree

source/brailleDisplayDrivers/handyTech.py

Lines changed: 54 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,7 @@ class Modular80(Modular):
531542
numCells = 80
532543

533544

534-
class Activator(TimeSyncFirmnessMixin, AtcMixin, JoystickMixin, TripleActionKeysMixin, Model):
545+
class Activator(ActiveSplitMixin, TimeSyncFirmnessMixin, AtcMixin, JoystickMixin, TripleActionKeysMixin, Model):
535546
deviceId = MODEL_ACTIVATOR
536547
numCells = 40
537548
genericName = name = 'Activator'
@@ -545,6 +556,34 @@ def _get_keys(self) -> Dict[int, str]:
545556
return keys
546557

547558

559+
class ActivatorPro64(ActiveSplitMixin, TimeSyncFirmnessMixin, AtcMixin, TripleActionKeysMixin, Model):
560+
deviceId = MODEL_ACTIVATOR_PRO_64
561+
numCells = 64
562+
genericName = name = 'Activator Pro 64'
563+
564+
def _get_keys(self) -> Dict[int, str]:
565+
keys = super().keys
566+
keys.update({
567+
0x7A: "escape",
568+
0x7B: "return",
569+
})
570+
return keys
571+
572+
573+
class ActivatorPro80(ActiveSplitMixin, TimeSyncFirmnessMixin, AtcMixin, TripleActionKeysMixin, Model):
574+
deviceId = MODEL_ACTIVATOR_PRO_80
575+
numCells = 80
576+
genericName = name = 'Activator Pro 80'
577+
578+
def _get_keys(self) -> Dict[int, str]:
579+
keys = super().keys
580+
keys.update({
581+
0x7A: "escape",
582+
0x7B: "return",
583+
})
584+
return keys
585+
586+
548587
def _allSubclasses(cls):
549588
"""List all direct and indirect subclasses of cls
550589
@@ -569,6 +608,7 @@ def _allSubclasses(cls):
569608
HT_PKT_NAK = b"\x7D"
570609
HT_PKT_ACK = b"\x7E"
571610
HT_PKT_OK = b"\xFE"
611+
HT_PKT_OK_WITH_LENGTH = b"\xFD"
572612
HT_PKT_RESET = b"\xFF"
573613
HT_EXTPKT_BRAILLE = HT_PKT_BRAILLE
574614
HT_EXTPKT_KEY = b"\x04"
@@ -589,6 +629,7 @@ def _allSubclasses(cls):
589629
HT_EXTPKT_GET_FIRMNESS = b"\x61"
590630
HT_EXTPKT_GET_PROTOCOL_PROPERTIES = b"\xC1"
591631
HT_EXTPKT_GET_FIRMWARE_VERSION = b"\xC2"
632+
HT_EXTPKT_NO_RECONNECT = b"\xAE"
592633

593634
# HID specific constants
594635
HT_HID_RPT_OutData = b"\x01" # receive data from device
@@ -637,6 +678,8 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar):
637678
"VID_1FE4&PID_0093", # Basic Braille Plus 32
638679
"VID_1FE4&PID_0094", # Basic Braille Plus 40
639680
"VID_1FE4&PID_00A4", # Activator
681+
"VID_1FE4&PID_00A6", # Activator Pro 64
682+
"VID_1FE4&PID_00A8", # Activator Pro 80
640683
})
641684

642685
# Some older HT displays use a HID converter and an internal serial interface
@@ -656,7 +699,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar):
656699
"Braillino BL",
657700
"Braille Wave BW",
658701
"Easy Braille EBR",
659-
"Activator AC",
702+
"Activator",
660703
)))
661704

662705
@classmethod
@@ -712,6 +755,9 @@ def __init__(self, port="auto"):
712755

713756
if self.numCells:
714757
# A display responded.
758+
if not isinstance(self._model, OldProtocolMixin):
759+
self.sendExtendedPacket(HT_EXTPKT_GET_PROTOCOL_PROPERTIES)
760+
self._dev.waitForRead(self.timeout)
715761
self._model.postInit()
716762
log.info("Found {device} connected via {type} ({port})".format(
717763
device=self._model.name, type=portType, port=port))
@@ -923,15 +969,18 @@ def _serialOnReceive(self, data: bytes):
923969
self._handleInputStream(data, self._dev)
924970

925971
def _handleInputStream(self, htPacketType: bytes, stream):
926-
if htPacketType in (HT_PKT_OK, HT_PKT_EXTENDED):
972+
if htPacketType in (HT_PKT_OK, HT_PKT_EXTENDED, HT_PKT_OK_WITH_LENGTH):
927973
modelId: bytes = stream.read(1)
928974
if not self._model:
929975
if modelId not in MODELS:
930976
log.debugWarning("Unknown model: %r" % modelId)
931977
raise RuntimeError(
932978
"The model with ID %r is not supported by this driver" % modelId)
933979
self._model = MODELS.get(modelId)(self)
934-
self.numCells = self._model.numCells
980+
if htPacketType == HT_PKT_OK_WITH_LENGTH:
981+
self.numCells = ord(stream.read(1))
982+
else:
983+
self.numCells = self._model.numCells
935984
elif self._model.deviceId != modelId:
936985
# Somehow the model ID of this display changed, probably another display
937986
# plugged in the same (already open) serial port.
@@ -962,7 +1011,7 @@ def _handleInputStream(self, htPacketType: bytes, stream):
9621011
# Ignore ATC packets for now
9631012
pass
9641013
elif extPacketType == HT_EXTPKT_GET_PROTOCOL_PROPERTIES:
965-
pass
1014+
self.numCells = packet[3]
9661015
elif isinstance(self._model, TimeSyncFirmnessMixin):
9671016
if extPacketType == HT_EXTPKT_GET_RTC:
9681017
self._model.handleTime(packet[1:])

0 commit comments

Comments
 (0)