25 May 2020, 04:44

For a change, I decided that rather than reverse engineering something that would ultimately turn out to be a simple protocol with funny voltages, I would have a go at something well documented but complicated: HP-HIL.

This is a multi-device protocol, so like USB. But in a daisy-chain, so even more like ADB. There are four wires, 12VDC, ground, transmit, and receive, which are known as SO and SI, respectively. Devices capable of being in the middle of the chain have two ports.

The connectors are AMP SDL, keyed two different ways ways, A and E, for the downstream and upstream from the host, respectively. So, a converter taking its place at the head needs some E receptacles. The part numbers given in the technical reference start with 1- and 5- (get it?). Digi-Key stocks some 4-conductor SDL jacks, made by AMP's sucessor's successor, TE Connectivity's, AMP division. And although the part numbers don't match, they come keyed two different ways and the datasheet says they will have a keying letter printed inside. So, 5's will probably work. And, indeed, they have E embossed deep in there. And, more importantly, fit the end of an HP-HIL cable with two dots.

At root, the protocol is just TTL-level serial. Even though the power line is 12V, every device is 5V and does nothing with it other than regulate it down. Maybe the potential of voltage drop over the whole chain was a concern. Or maybe 12V is just what they had coming out of the power supply.

Except that each "frame" is 15-bits long instead of 10: start bit, three-bit address (so, up to seven devices with one broadcast address; ADB allowed up to sixteen devices), a command vs. data bit, eight bits of data, and parity and stop bits. So, there is no question of using even the more advanced MCU UARTs. Each bit is 10µs wide, so bit-banging is probably doable by a ATMega32U4 Teensy.

There are photos, including the insides, of various devices online at Bitsavers, so I won't bother taking any of the particular ones I used to debug.

The result uses QMK and is available here.

The keyboard to which I had access is rubber dome. Not bad as rubber dome goes, I suppose. And the purple and green dye-sub legends do reenforce a later '80s vibe. There are apparently also versions of the 46021A that use Fujitsu leaf-spring switches. But there does not seem to be any way to tell from the outside which is which. Which, together with eBay' sellers', uhm, expansive ideas of what consitututes "clicky," means I am not sure how I would set out to get one. Perhaps the older 46010A is more reliably Fujitsu? There are also 46021B and 46021C, which make all the arrow keys outlines and not just home. I think maybe those are always rubber dome. Anyway, I have something good enough for testing the mapping and typing at speed.

There are two- and three-button mice, and a three-button trackball. They all work more or less the same way with a rolling ball. And so aren't of much interest except as retro-computing. But I was able to get them functioning okay with QMK.

Of potentially more interest even today is a 32-key macropad, err, "48086A 32-button Control Box." These came with thin plastic templates on which one could pencil what the buttons did. It also has a green LED in the upper-right corner, wired to HIL's prompt / acknowledge commands. I made this controlled by QMK's backlight function. So, if one wanted to assign a layer toggle with backlight when activated (a standard QMK trick), that would be 62 macros to program.

48084A ID Modules, that is, node licensing dongles, just return their (unique) serial number when queried. All devices have the optional ability to respond to this "security code report" query, so in some sense an ID module is just a device with nothing other than its serial number. But, as far as I can tell, no other device actually has the serial number programmed in (which would be expensive and for what). They either don't claim support or do and return all zeros in the query response. I didn't come up with anything useful to do with this, though. So I just added a "magic" QMK command to print them out to hidlisten.

The speaker device, 46081A HIL Audio Extension, does not seem to be an active device at all. The photo on Bitsavers of the inside just shows a NAND gate and some passives. No MLC chip to talk the HIL protocol and no timer or anything to make beeps. It has a mini phono plug input. Am I missing something? Or is it just using the 12VDC to power a simple audio amplifier? Like USB-Powered PC Computer Speakers, which aren't really USB audio devices?

I was not able to scare up access to any control dial devices, which evidently used optical rotary encoders. So they won't work like the ones on custom keyboards today. These came in two versions: "46083A HP-HIL Knob," one giant dial in its own box; and "46085A Control Dial Module," a tic-tac-toe matrix, which might possibly not be as silly as it looks in this '80s "office" photo shoot.
320_1985-PromoPhoto-29.jpg (176.15 KiB) Viewed 2130 times
The timing of the code isn't perfect: there are occasional framing and parity errors (reported in debug mode). But the protocol design is quite robust for recovering from these, without even losing events most of the time. Both the sent and received frames look to accord with the spec pretty closely. So I think the problem is not starting the bit scanning loop from the interrupt all the time reliably.
hp-hil-441-so-zoom.png (19.64 KiB) Viewed 2130 times
hp-hil-441-si-zoom.png (18.92 KiB) Viewed 2130 times
When I put a converter in its own case, I usually go with the Hammond ABS project boxes. And the black ones.
hp-hil-converter-open.jpg (647.2 KiB) Viewed 2130 times
But, in this case, I tried as best I could with what I had at hand to recreate the aesthetic of having all these little beige HIL boxes on your desk.
hp-hil-converter-closed.jpg (211.98 KiB) Viewed 2130 times


25 May 2020, 18:01

Okay. Had a closer look at the photos of 46081A Bitsavers to try to confirm for myself what it does.

I had been parsing "HP-HIL / Audio Extension" all wrong. It isn't an Audio Extension. It's an HIL extension with audio thrown in. That is, it is a TTL repeater with an 8 Ohm speaker in the same box, I guess cause there was room.
46081-66501_B.jpg (553.87 KiB) Viewed 2069 times
The digital part just drives SI from E to SO on A and vice versa, with loads of circuit protecting diodes, current limiting and pull-up resistors and transient smoothing capacitors. Only two of the NAND gates are used and they're always open.

The analog part is just a speaker connected to a jack. No amp; no nothing.

I'm not sure under what circumstances the HIL signal would have degraded such that you need this. Normal devices buffer frames, so it should always be clean coming out of the previous one and not degrade over the length of the chain. Maybe you need one if you put a device further away than its ordinary cable?

But apparently this was worth $225 in 1989 money. (The description there mentions 2.4m, so maybe it is for slightly longer distance.)

User avatar

25 May 2020, 20:55

Cool stuff. I enjoyed looking at the HIL spec and seeing what you've done.

User avatar

26 May 2020, 22:20

You gotta find one of those tic-tac-toe matrix boxes and hook it up!

User avatar

28 May 2020, 16:02

Great work!
It works perfectly with my HP 98203C keyboard, it seems to use its device specific 'Keycode Set 2' like below. Interestingly, the keyboard has no ghost-blocking and phantom key can appear with specific three keys.

I had broken its rotary encoder a few years ago and can't test the dial unfortunately.

Code: Select all

/* HP 98203C Keyboard Keycodes
 *   https://i.imgur.com/QKqVuQu.jpg
 *   Device ID: E0
 *   Describe Record: 0A(Extended, 2 axes?), 61(X Max?), 0F(Y Max?)
 *   Extended Describe Record: 40(Read Register), 00(0 register?)
 *   Poll Record Header: 0x60(Keycode Set 2)
 *   Keycode Set 2 is device dependent and user  definable. Use the LSB to indicate
 *   the key transition (0 = Down, 1 = Up). 128 keys maximum. (p.E-3):
 *         ,___.___.___.___.___.   ,___.___.   ,___.___.___.         ,___.___.___.___.
 *         `---'---'---'---'---'   `---'---'   `---'---'---'         `---'---'---'---'
 *         ,___.___.___.___.___.   ,___.___.   ,___.___.___.         ,___.___.___.___.
 *         `---'---'---'---'---'   `---'---'   `---'---'---'         `---'---'---'---'
 * ,-------------------------------------------------------. ,-----. ,---------------.
 * |Ctl|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bsp| |PUASE| | E | ( | ) | ^-|
 * |-------------------------------------------------------| |-----| |---------------|
 * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]| | | RUN | |  7|  8|  9| / |
 * |-----------------------------------------------------' | |-----| |---------------|
 * |CapsL |  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '| Ent| |CONTI| |  4|  5|  6| * |
 * |-------------------------------------------------------| `-----' |---------------|
 * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  .|  /|Shift |         |  1|  2|  3| - |
 * |-------------------------------------------------------' ,-----. |---------------|
 *              |           Space               |            |EXECU| |  0| . | , | + |
 *              `-------------------------------'            `-----' `---------------'
 * Raw Keycodes:
 *       34 36 38 40 42    44 46    50 52 54      60 62 64 66
 *       3A 3C 3E 48 4A    4C 4E    56 58 5A      68 6A 6C 6E
 * 0C A0 A2 A4 A6 A8 AA AC AE B0 B2 B4 B6 5C  70  98 9A 9C 9E
 * 32 D0 D2 D4 D6 D8 DA DC DE C8 CA B8 BA     5E  90 92 94 96
 * 30 E0 E2 E4 E6 E8 EA EC CC CE BC BE 72     74  88 8A 8C 8E
 * 0A F0 F2 F4 F6 F8 FA EE C0 C2 C4 0A            80 82 84 86
 *                C6                          76  78 7A 7C 7E
 * (Raw Keycodes)>>1:
 *       1A 1B 1C 20 21    22 23    28 29 2A      30 31 32 33
 *       1D 1E 1F 24 25    26 27    2B 2C 2D      34 35 36 37
 * 06 50 51 52 53 54 55 56 57 58 59 5A 5B 2E  38  4C 4D 4E 4F
 * 19 68 69 6A 6B 6C 6D 6E 6F 64 65 5C 5D     2F  48 49 4A 4B
 * 18 70 71 72 73 74 75 76 66 67 5E 5F 39     3A  44 45 46 47
 * 05 78 79 7A 7B 7C 7D 77 60 61 62 05            40 41 42 43
 *                63                          3B  3C 3D 3E 3F

As for parity error, it seems that ISR(INT0_vect) is interfered by 'USB SOF' event and fails to track signal. After disable the event I don't see the error.

Code: Select all

diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index 374add20f..64103f98c 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -974,7 +974,9 @@ int main(void) {
+    wait_ms(4000);
     print("Keyboard start.\n");
+    USB_Device_DisableSOFEvents();
     while (1) {
 #if !defined(NO_USB_STARTUP_CHECK)
         while (USB_DeviceState == DEVICE_STATE_Suspended) {
@@ -1008,6 +1010,11 @@ int main(void) {
+        if (console_flush) {
+            Console_Task();
+            console_flush = false;
+        }

User avatar

29 May 2020, 01:49

Always such great photos hasu.


30 May 2020, 04:07

hasu wrote:
28 May 2020, 16:02
As for parity error, it seems that ISR(INT0_vect) is interfered by 'USB SOF' event and fails to track signal. After disable the event I don't see the error.
Thank you very much for this. I have incorporated your patch into my branch, putting it under a conditional for Lufa's existing NO_SOF_EVENTS define.

It's too bad that 48086A and 98203C both send keycode set 2 with a few keys overlapping.To use those together we'll need the mapping to respect the device id as well somehow. I think I have a lead on a 98203C, so I'll see what I can do.


07 Jun 2020, 01:04

I managed to get access to a 98203C, which has both unshifted ( ) for Lisp fans and a k9 key for Tom Baker fans, and fooled around with the macros so that it now works out of the box in the default mapping. In particular, it works to have both it and a 46086A connected at the same time, even though both send key set #2 with some overlapping key codes.

It should even work to define a custom mapping with two of the same keyboard having different key layouts, provided they are always connected in the same order and this is captured in the macros.

The dial (a horizontal-only mouse like Hasu shows) also works now, with mapping customized the same way encoders are normally in QMK. I still don't know what a 46083A sends, because the protocol doesn't have room for nine axes. So I am on the lookout for one.

User avatar

07 Jun 2020, 06:37

I also tried the dial on my 98203C with wiring cheap usual mechanical encoder tentatively (it failed to read optical encoder I got for the keyboard, for some reason), and found that it sends Y-axis data when rotate the dial with pressing Shift key. I can move mouse cursor with the dial now.

I ported to TMK for my 98203C. Thanks.
https://github.com/tmk/tmk_keyboard/tre ... /hphil_usb

I found this note in a HP document, the 46085A uses three different addresses to support nine dials?
You cannot have more than 7 HP-HIL addressable devices connected to
your computer at one time. The HP 46080A, 46081A, 46082A and 46082B
Extension modules and the HP 46089A Four-Button Cursor do not count
as addressable devices, and the HP 46085A Control Dials Module counts
as three addressable devices.
All other devices count as one addressable
device .
p.10-42 of
http://bitsavers.trailing-edge.com/pdf/ ... _Sep89.pdf


28 Feb 2021, 00:41

I finally got ahold of a 46085A, which does indeed take three addresses (bottom, middle, top) of three axes (left, middle, right) each.
HP-HIL-family.jpg (323.1 KiB) Viewed 581 times

User avatar

28 Feb 2021, 01:18

Very clean photo! I love that backdrop.

User avatar

28 Feb 2021, 15:26

Gotta love early attempts at mouse ergonomics.

Post Reply

Return to “Workshop”