ICS Electronics 4883 Instrument Coupler
This device is from early 1980ies. Its purpose is to control devices like physical or chemical instruments, not compliant with GPIB, via GPIB bus.
Control happens via digital input and output lines. 4883 has 40 input pins and 40 output pins. Today it can be used as a general digital IO with 40+40 channels, controllable via GPIB.
There is not much information on this device on the internet.
It looks another company reselled this thing as “PI-952 Pulse Instruments Bidirectional Instrument Coupler”: https://www.artisantg.com/TestMeasurement/61926-1/Pulse-Instruments-PI-952-Bidirectional-Instrument-Coupler
And also it was sold as “Fairchild 4880 Instrument Coupler”.
A hint to manual copy service from ICS from 2017:
“Fairchild Model 4880 Instrument Coupler Instruction Manual”, Rev. 5, 1981, Fairchild Instruments, Los Angeles, CA. (Available for $25 from ICS Electronics, 1620 Banker Rd., Sandose, CA. 95112, Part No. 120002.) Google Scholar”
Details


PSU:

Dirt here and there:

Main board:

Input/Output board:

8080 CPU (National Semiconductor INS8080AN P8080A) and 2708 EPROM 1Kx8. There is also some RAM 2x 2112 (256x4, i.e. 1KBit) on board. We have two, so 256x8 Bit, = 256 Bytes RAM. The CPU can run with 2 MHz. Quarz visible has 14.74 MHz.

The two boards are connected via 2 16-pin PDIP connectors named “W1” and “W2”. W1 is related to input section (4883 as a Talker) and W2 to output section (4883 as a Listener). But division W1=Talker and W2=Listener is not 100%.
ROM content
ROM was dumped with Batronix Barlino II, EPROM set to “AM2716B (read only)”, and a special adapter was created on the fly to map the 2708 pins to the AM2716B pins. 2708 needs -5 volts, + 5 volts and +12 volts, and I had to provide -5 volts and +12 volts from an external power supply.
Image shows Batronix Barlino, and on top of it a breadboard with the 2708. All required wires go to a 24 pin IC socket, which is mounted to Eprommers test socket. The two required additional voltages (-5 and +12 volts) are provided from an external power supply.

Current state of analysis (to be improved):
; 0000 - 03FF : 1024 Bytes ROM (code and tables)
; 0400 - 04FF : 256 Bytes RAM and STACK
; 0500 - 05FF : Input and Output registers (needs more detailing)
; 0600 - 06FF : Input and Output registers (needs more detailing)
; 0700 - 07FF : GPIB connector control
; 0800 and above - unused
Improved ROM dump: rom-with-labels.txt
Disassembled ROM
I tried to dissassemble the ROM content.
- README - https://github.com/DennisD2/ics4883/blob/main/README.md
- Result: ics4883.asm - https://github.com/DennisD2/ics4883/blob/main/ics4883.asm
The result file can be assembled using an 8080 assembler. The result 100% identical with ROM content.
Use
I give several code examples below. You can find all that code on github: https://github.com/DennisD2/linuxgpib/tree/main/cmd.
All code uses the GPIB for Linux API. There is a Go API for this at https://github.com/msiegen/linuxgpib, and I have forked this and added some test applications for ICS 4883.
Check inside https://github.com/DennisD2/linuxgpib/tree/main/cmd for ics4883* directories.
General programming information
Data transfer is done with characters. They are handled in a special way, and different depending on direction.
In general, up to 12 bytes are send or received from coupler.
These 12 bytes are always organized in the following way:
D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 \n \r
where Di means “Digit number i”. So ten digits, followed by a CR and a LF. nothing is between these digits and CR and LF (no other chars like space or so).
I think I’ve read that it is possible to send fewer digits, like “D1D2D3\n\r”, have not tested this so far.
Inside of a byte, only the lower nibble is used and processed. The numbering of the bits inside the nibble is:
B4 B3 B2 B1
where Bi means “Bit number i”.
Data conversation direction “Coupler -> Instrument”
The upper 4 bits of each character D are ignored. Only lower 4 bits are used for sending to J3 connector pins.
- Each character D can be of [0-9,:;<=>?].
- ASCII values for ‘0’-‘9’ are converted to BCD code (4 bits 0000-1001).
- Byte values 1010..1111 are replaced with special characters
In summary, the chars are converted like this:
| D | Hex Code | BCD |
|---|---|---|
| 0 | 0000 | |
| 1 | 0001 | |
| 2 | 0010 | |
| 3 | 0011 | |
| 4 | 0100 | |
| 5 | 0101 | |
| 6 | 0110 | |
| 7 | 0111 | |
| 8 | 1000 | |
| 9 | 1001 | |
| : | 0x3a | 1010 |
| ; | 0x3b | 1011 |
| < | 0x3c | 1100 |
| = | 0x3d | 1101 |
| > | 0x3e | 1110 |
| ? | 0x3f | 1111 |
Data conversation direction “Instrument -> Coupler”
Instrument data comes in 4 bit groups, nibbles.
- Incoming code can be any of 0000-1111
- BCD code (4 bits 0000-1001) are converted to ‘0’-‘9’ ASCII values
- Byte values 1010..1111 are replaced with special characters
Here we can see the nature/origin of the coupler, which expects these nibbles are digits of measurement instruments, looking like “-1.945E06”
| D | ASCII Hex code | ASCII character |
|---|---|---|
| 0000 | 0x30 | 0 |
| 0001 | 0x31 | 1 |
| 0010 | 0x32 | 2 |
| 0011 | 0x33 | 3 |
| 0100 | 0x34 | 4 |
| 0101 | 0x35 | 5 |
| 0110 | 0x36 | 6 |
| 0111 | 0x37 | 7 |
| 1000 | 0x38 | 8 |
| 1001 | 0x39 | 9 |
| 1010 | 0x2b | + |
| 1011 | 0x2d | - |
| 1100 | 0x2e | . (dot) |
| 1101 | 0x2c | , (comma) |
| 1110 | 0x45 | E |
| 1111 | 0x20 | SPACE |
Digit most left:
- Pin 7 = Nibble pin 1, i.e. the x in “000x”.
- Pin 8 = Nibble pin 2, i.e. the x in “00x0”.
- Pin 9 = Nibble pin 3, i.e. the x in “0x00”.
- Pin 10 = Nibble pin 4, i.e. the x in “x000”.
Next digit:
- Pin 11 = Nibble pin 1, i.e. the x in “000x”.
- Pin 12 = Nibble pin 2, i.e. the x in “00x0”.
And so on. I will provide full connector pin drawing later.
A quick try out: writing to 4883 (4883 as listener)
Writing to 4883 means that bits are set/cleared at 50 pin output connector J3 named “Com’D”, according to control data sent via GPIB.
Two pins have +5 volts and GND. From spec, 4883 has 40 output lines. I could see that all 50 pins are connected to the PCB. This means that 50-40-2=8 pins are of yet unknown functionality.
When addressed as listener, we can send a string of content “DDDDDDDDDD\n\r”, i.e. 10 characters and CR,LF.
For 10 character, we can control 10*4=40 output pins.
A write lasts less than 9ms, which is fast for GPIB.
ibtest
Do you wish to open a (d)evice or an interface (b)oard?
(you probably want to open a device): 16
Do you wish to open a (d)evice or an interface (b)oard?
(you probably want to open a device): d
enter primary gpib address for device you wish to open [0-30]: 16
trying to open pad = 16 on /dev/gpib0 ...
You can:
w(a)it for an event
...
send group e(x)ecute trigger (device only)
: w
enter a string to send to your device: >>>>>>>>>>
sending string: >>>>>>>>>>
gpib status is:
ibsta = 0x2100 < END CMPL >
iberr= 0
ibcntl = 11
You can:
w(a)it for an event
...
send group e(x)ecute trigger (device only)
: w
enter a string to send to your device: 0000000000
sending string: 0000000000
gpib status is:
ibsta = 0x2100 < END CMPL >
iberr= 0
ibcntl = 11
You can:
w(a)it for an event
...
send group e(x)ecute trigger (device only)
A quick try out: Reading from 4883 (4883 as talker)
Reading from 4883 means that bits at 50 pin input connector J2 named “Input”, according to input data, are read via GPIB.
The quick try for reading failed.
Status after initial try out: I can output data. But there is some handshake for output board. Due to missing manuals and such I do not know the exact pin meanings and how to control the handshake.
Furthermore, input is not working at all. Also because I do not know what to do for “input” data.
So I looked deeper at the device.
Deeper analysis of IO board
Because there is nothing printed on board, I’ve numbered the chips myself.
Output section, ICS4883 as a Listener, connector J3
Output handling is done in area of chips U11-U34. (U41-U84 are for input section). U43 is also part of output handling.
In total, 13 chips are used for output processing:
- 11 x 74LS75 (4 bit latches)
- 74LS138 1:8 demultiplexer
- 74LS04
Control lines from/to main board are routed through 16 pin PDIP connector W2.

And here is a part of the real schematics, derived from the board.
I’ve only looked at lines from output connector to chips on board.
The part from those chips to the controlling connectors was left out.

For each output digit, a 4 bit latch is used. We have 10 digits. The chip used is the 74LS75. One additional latch is there, 11 in total, and the 11th is not related to digits! So we have it, one latch with 4 handshake output lines. These are at J3 connector Pin 22-25. Furthermore, there are three input lines, at pins 48-50, also used for handshake.
The input pins just mentioned are enabled by logical HI level at pin 21. If pin21==0, their values will be read by internal logic always as 1, independent of input. if pin21==1, their inverted value will be forwarded to internal logic. Maybe the meaning of this pin is “enable handshake mode” (to be checked).
Finally, we have a ground pin (pin 1) and a Vcc pin with +5 volts (pin 5).
With that information, I can try to find out how handshake is intended to work.
Don’t forget that the aim of communication here is to send a command to an external instrument, and to verify somehow that the command was executed with no issues.
Pins 48-50: I suppose there is a “Device is ready for commands” input, also a “Device command completed”, so at least 2 input lines. Maybe there is an “error condition during command execution”, which would be 3rd input line.
Pin 21: needs to be set to HI in any case, to enable input lines/handshake.
Pin 22 and 23 : These output lines are “DATA READY” at pin 22. The pin goes HI after signals at data pins are stable. Pin 23 is same signal, but inverted. I found that signal is a strobe, with a duration of 25 µs. After a signal change on a data pin, it needs about 200 µs to occur.
Below is pin 22, DATA READY signal in yellow. some data pin signal in blue.
We can see the duration of DATA READY signal (25 µs)…

And we can see the time it needs after the data signal is already at its
data pin. This time is required that all signals at all pins are stable.
It is about 200 µs.

Pin 24 and 25:
When I measured signals there, pin 24 is usually HI and pin 25 usually LO.
No changes were ever seen. Maybe among them is a “Device reset” pin, which
forwards a GPIB “Universal/Selected Device Clear”.
Table with “special” pins:
| J3 Pin | I/O | Meaning | Comment | Verified |
|---|---|---|---|---|
| 1 | O | GND | YES | |
| 5 | O | +5V | YES | |
| 21 | I | “Enable Handshaking” ? | to be checked | 50% |
| 22 | O | DATA READY | YES | |
| 23 | O | /DATA READY | YES | |
| 24 | O | ? | ||
| 25 | O | ? | ||
| 48 | I | ? | ||
| 49 | I | ? | ||
| 50 | I | ? |
Some months later I had a second look on the output section. There were some new findings:
-
Connector from main board to IO board. There is one connector related to output topics, and one to input topics.
-
The output connector has eight data bits, pins 1-8. These 8 bits are organized as two 4-bit buses. Pins 1-4 is DATA_A and 4-8 is DATA_B. These two buses are routed to these chips, to their data input pins:
- DATA_A: U11, U12, U13, U31, U32, U14
- DATA_B: U21, U22, U23, U43, U33
-
Pins 9,10,11 of the output connector controls the three inputs of a 1:8 selector 74LS138. From the 8 output signals of that selector the following (mostly pairs of) enable pins are driven together (forming a latch group):
- U11 and U21 (digits 9 and 10)
- U12 and U22 (digits 1 and 2)
- U13 and U23 (digits 7 and 8)
- U31 and U43 (digits 5 and 6)
- U32 and U33 (digits 3 and 4)
- U14 (control out)
The left chips are all on DATA_A, the right are all on DATA_B. In that way, the CPU can write 8 bits in total in a single step (4 to DATA_A and 4 to DATA_B). So we have 8 bits per latch group and 5 groups, resulting in 40 data bits. U14 is a single 4 bit latch, and transfers not data but handshake signals, as already was found out before.
-
74LS138 has 8 outputs, but only 6 are used by the chips we have looked at. Y7 (output number 8th) is not used at all, it is not connected to anything on PCB. Y5 goes to the input part of the board, and I have just ignored it so far.
Chips used:
74LS75:



With that new information, I have some usable result for the output connector pin functionality.
Final table for output connector J3 pins. Tested and verified:
| Pin | Meaning | Comment |
|---|---|---|
| 1 | GND | |
| 2 | digit=3, bit=1 | |
| 3 | digit=3, bit=2 | |
| 4 | digit=3, bit=3 | |
| 5 | VCC | |
| 6 | digit=3, bit=4 | |
| 7 | digit=4, bit=4 | strange location |
| 8 | digit=2, bit=4 | |
| 9 | digit=2, bit=3 | |
| 10 | digit=2, bit=2 | |
| 11 | digit=2, bit=1 | |
| 12 | digit=8, bit=1 | strange location |
| 13 | digit=1, bit=1 | |
| 14 | digit=1, bit=2 | |
| 15 | digit=1, bit=3 | |
| 16 | digit=1, bit=4 | |
| 17 | digit=7, bit=4 | |
| 18 | digit=7, bit=3 | |
| 19 | digit=7, bit=2 | |
| 20 | digit=7, bit=1 | |
| 21 | HANDSHAKE_ENABLE | |
| 22 | DATA READY | |
| 23 | /DATA READY | |
| 24 | CONTROL OUT 3 | |
| 25 | CONTROL OUT 4 | |
| 26 | digit=5, bit=2 | |
| 27 | digit=5, bit=3 | |
| 28 | digit=5, bit=4 | |
| 29 | digit=5, bit=1 | |
| 30 | digit=10, bit=4 | |
| 31 | digit=10, bit=2 | |
| 32 | digit=10, bit=3 | |
| 33 | digit=10, bit=1 | |
| 34 | digit=9, bit=1 | |
| 35 | digit=9, bit=2 | |
| 36 | digit=9, bit=4 | |
| 37 | digit=9, bit=3 | |
| 38 | digit=4, bit=1 | |
| 39 | digit=4, bit=2 | |
| 40 | digit=4, bit=3 | |
| 41 | digit=8, bit=4 | |
| 42 | digit=8, bit=3 | |
| 43 | digit=8, bit=2 | |
| 44 | digit=6, bit=4 | |
| 45 | digit=6, bit=3 | |
| 46 | digit=6, bit=2 | |
| 47 | digit=6, bit=1 | |
| 48 | CONTROL IN 1 | |
| 49 | CONTROL IN 2 | |
| 50 | CONTROL IN 3 |
Below are the pin assignments shown together with Centronics 50 socket:
- CO = Control Out: output pins, used for handshake (4 pins)
- HS EN: Handshake enable, input pin
- CI = Control In: input pins, used for handshake (3 pins)

Strange pin assignments…
While some digits are assigned to pins like one would expect, others have strange arrangements.
Simple 1-2-3-4 bit order for pin assignments of bits:
- D1, D3
reverse assignments 4-3-2-1:
- D2, D7, D6
somewhat arbitrary assignments:
- D5 is 2-3-4-1
- D9 is 1-2-4-3
- D10 is 4-2-3-1
arrangements with pins at totally different places:
- D4: bit 1 of D4 is at centronics pin 7. Between D3 and D2 pins. remaining D4 pins are then at 40-38.
- D8: bit 1 of D8 is at centronics pin 12. Between D2 abd D1 pins. Remaining D8 pins are then at 43-41.
I do not understand why these strange arrangements were done. To have an understandable behavior at the Centronics socket, the software would need rearrange bits in cumbersome way. But it does not do this.
Input section, ICS4883 as a Talker, connector J2
Input handling is done in area of chips U41-U84.
In total, 18 chips are used for output processing:
- 12 x 74LS03 (4 NAND gates)
- 74LS138 1:8 demultiplexer
- 2 x 74LS00
- 74LS04
- 74LS74
- JM38510 (should be compatible with 74LS05, see below)
Control lines from/to main board are routed through 16 pin PDIP connector W1.

One strange chip…
There is one strange chip. Someone has written “7406” with a pencil on it. What is printed on its surface is:
JM38510/
00801 BCB
CGG M 7825A
The M above is Motorola logo. There are numerous ICs with names like “JM38510/…”, it seems these are “Motorola - Military High-Reliability Integrated Circuits”. It also looks like this chip has been replaced as a repair job.
From datasheet examination, this is a 7405 (not a 7406 as written on surface). 7405 has open collector outputs, where 7406 has standard TTL output. The resistors R1-R4 support that this is a 7405 or 74LS05.

But back to input section analysis.
Partial schematics:

Pin 1 ist GND, pin 5 is Vcc.
Handshake path
Some output control signal comes from internal logic in through inverter U83E.
Its OC output is pulled up via 10K to Vcc. This signal goes to connector pin 4.
The signal goes also to a second inverter U83B, also pulled up at its output,
and this inverted signal goes to connector pin 3.
This is probably the “start of read cycle” signal.
Via pin 2 (inverted 2 times U83A and U83F) and pin 6 (inverted 1 time U83F) some input handshake signal comes in. Pin 6 input connector is pulled up to Vcc. I suppose this is kind of “data at connector pins is valid” signal. I call it “DATA READY”.
Pins 49+50 are also outputs, and are connected to U64, which is a 74LS74, D-Flip-Flops triggered by positive edges, having preset and clear.
Pins 47+48, connected to U74, are input pins. Because with pins 7..46, we have already covered to 40 required input pins for input data, I suppose that pins 47+48 are also pins related to handshake.
Data path
With ten 74LS03, the 40=10*4 input bits are fetched. These are at pins 7..46. One 4 bit part is shown in schematics (connector pins 6-10).
74LS03 pins:

74LS04 pins:

74LS138 pins:


Addressing
Regarding addressing to individual input pins, the following scheme shows more details.

Each of the ten 7403 chip related to input pins from J1 has NAND gate inputs 1,4,13 and 10 connected together. The second gate input serves in that way as an enable input. By wiring 4 gate pins together, all 4 gates can be enabled with one wire.
Moreover, always two 7403 chips have connected these two wires. By doing this, eight gates can be anabled at once.
These 5 enable wires are driven by the 74LS138 3-to-8 demultiplexer. Between gate pins and demultiplexer pins, an inverter (U53 7404) is connected. The table below shows the pairs of 7403 and their address line used by 74LS138:
| 7404 pairs | 74LS138 output pin |
|---|---|
| U81, U71 | Y4 (pin 11) |
| U82, U72 | Y1 (pin 14) |
| U61, U51 | Y3 (pin 12) |
| U52, U62 | Y0 (pin 15) |
| U42, U41 | Y2 (pin 13) |
The 3 input address pins (A,B,C) from 74LS138 are routed to W2, pin 13, 12, 11. One of the enable pins of 74LS138 also is routed there at pin 9.
Note: two more 7403, U44 and U74 are used otherwise and do not participating in address topics for input pins (to be checked further):
- U74 is used for handshake signals (see handshake section)
- U44 is used for ???
For U74, I looked further and added following schematics. It shows that Y5 of U63 goes to gate inputs 3,10,13 of U74. The other input pins of these three gates go directly to input connector J2. The 4th gate of U74 is handled differently.
Interesting is that output pins of gates, pins 3 and 11, are wired together and are connected to output pin Y6 of U63. This is possible because we have Open Collector outputs. So the signal at these pins ca be set to LKO by either gates of U74 or by pin Y6 of U63. Output of all these gates have not checked further.
I found also that enabling of U63 is like this: /G2B goes to ground. So enabling is true if /G2A=0 and G1=1. /G2A goes to W2, pin 9. G1 goes to W2, pin 10.
The second 74LS138 on that board, that controls input section, is connected in a similar way. /G2B ist grounded. G1 pin is connected also to W2, pin 10. /G2A is connected to W2, pin 14.
Both 74LS138 get same input signals at A,B,C. And I assume these are the adress CPU address bits 0,1,2.

Connector J2, handshake pins, how does handshake works?
Table with “special” pins (for a complete table see further below):
| J1 Pin | I/O | Meaning | Comment | Verified |
|---|---|---|---|---|
| 1 | O | GND | YES | |
| 5 | O | +5V | YES | |
| 2 | I | /DATA READY | Inverter to pin 6 | YES |
| 3 | O | ? | ||
| 4 | O | ? | Inverter to pin 3 | |
| 6 | I | DATA READY | YES | |
| 47 | I | ? | pin of an NAND gate | |
| 48 | I | ? | pin of another NAND gate | |
| 49 | O | ? | Q output of 1st FF in 74LS74 | |
| 50 | O | ? | Q output of 2nd FF in 74LS74 |
When playing with these lines I’ve got following results:
- All input pins, are in HI state when not connected. Single exception is Pin 6, details on that pin see next point below. HI is around 4.3 volts, LO around 0.3 volts
- Pins 2 and 6 are input and
can beare the “Instrument Data Ready” pins. Pin 2 triggers the read in of data pins on raising edge. Pin 6 just adds an inverter with its output connected to pins 2. So Pin 6 triggers the read in on falling edge. Issue: changing state of pins 2 and 6 rarely create a SRQ. SRQ is only created in a special condition. Why? - Pins 3 and 4 are output and are not the “Start Instrument Data Read” pins. Pin 3 just adds an inverter, with input pin connected to pin 4.
- Pin 50 is the “Start Instrument Data Read”. It gives an LO pulse to start the
data read. Pulse width is ~26µs.
- The pulse is created when sending a device trigger command.
- Pin 49 is like signal at Pin 50, but inverted. It gives an HI pulse to start
the data read.
- The pulse is created when sending a device trigger command.
- Pin 49 and Pin 50 go to the A outputs of two different D-Flip-Flops in an 74LS74. I suppose they can be operated independent by firmware. In my test, they were coupled, so that 49 is like 50, but inverted signal.
For handshake in general, we can conclude:
- Having 4 input lines and 4 output lines for handshake, different handshakes can be implemented and are possible.
- 2 and 6 are coupled together in HW, also 3 and 4 (coupled each by an inverter).
- So in reality, these are 3 input lines and 3 output lines.
Because we have Open Collector inverters, it could be also possible that pin 4 is used as an input pin.
Signal at pins 50 (blue) and 49 (yellow):

Fixed table:
| J2 Pin | I/O | Meaning | Comment | Functionality verified |
|---|---|---|---|---|
| 1 | O | GND | YES | |
| 5 | O | +5V | YES | |
| 2 | I | /DATA READY | Default value = HI. Falling edge triggers 4883 read function. Inverter to pin 6 | 50% |
| 6 | I | DATA READY | Default value = LO. Rising edge triggers 4883 read function | 50% |
| 3 | O | /Coupler read data done | Default = HI. Is LO as long as coupler needs stable data at input pins. | 10% |
| 4 | O | Coupler read data done | Default = LO. Inverter to pin 3 | 10% |
| 47 | I | ? | pin of an NAND gate | 0% |
| 48 | I | ? | pin of another NAND gate | 0% |
| 49 | O | Start Instrument Data Read | Default = LO. HI pulse triggers Instrument data read. Q output of 1st FF in 74LS74 | YES |
| 50 | O | /Start Instrument Data Read | Default = HI. LO pulse triggers Instrument data read. Q output of 2nd FF in 74LS74 | YES |
Behavior for SRQ topic (unresolved issue):
- If I simply connect pin 2 to ground, there is never any SRQ.
- If I first press “RESET” key on front plate and then connect pin 2 to ground, an SRQ is generated!
Deeper analysis of handshake
The overall dump below shows U74, signals A,B,C and its gate signals G1 and /G2A. /G2B is grounded. First line is signal at Pin 3 of J2.
The first big gap between 1120 ms and 1480 ms is me pressing the RESET button.
Around 1820 ms, I am pressing the switch that created a falling edge at J2, Pin 2. This creates a raising signal at Pin 3. The read process starts, and after about 20 ms, it finishes and Pin3 goes LO again.
(Some time later, maybe by a follwing read, Pin 3 goes HI, but this is after the read process we want o examine).

The following trace shows the area where the read is processed in more detail. This trace uses a custom “74138 address decoder” that I’ve written on the fly. It calculates the Y output pin addressed by A,B,C, and is using the gate inputs the check if 74138 is enabled.
The custom decoder can be configured to filter only Yn outputs that we are interested in. From hardware analysis I already know that Y0,Y1,Y2,Y3,Y4 outputs are used to drive the 7403 Quad NAND chips to read in from 40=5*8 input pins.
So I have filtered only to show Y0,Y1,Y2,Y3,Y4 becoming LO. And the nice thing is, the sheer mass of thousand Yn events come down to five events during read period.

These events are coming in, in the order Y4,Y3,Y2,Y1,Y0. 1832,66 ms till 1834,4 ms. Next trace shows this area of interest.

After being sure that I am looking at the correct location, we can move our focus to the handshaking issue. We already know from hardware analysis, that Y5 is controlling the input pins at location 47 and 48.
Because all input pins of 74LS03 float at HI state, I suppose a HI-LO edge is required after the Pin 3 BUSY signal gets LO after read process has finished.
By examination, the following pins are not used: Y6, Y7. But many Y5 events occur. See next trace:
All new events after the read part are Y5 activations. Note that even three Y5 events occur now inside read section. The new order there is Y4 - Y3 - Y5 - Y2 - Y5 - Y1 - Y5 - Y0.

So we can conclude that Y5 is an enabling signal for handshake input signal of a type “I acknowledge to have received the end of your BUSY state”. But simply putting the 47 or 48 pin to LO did not fix the handshake issue so far.
Final table for input connector J2 pins.
Pin assignments for input connector are simple and do not contain oddities like the assignments at output connector. All bytes are in correct order, and bits inside all bytes are always 1-2-3-4 well-ordered. All 40 data bits are located between pin numbers 7 and 46.
Tested and verified:
| Pin | Meaning | Comment |
|---|---|---|
| 1 | GND | |
| 2 | CI1 /DATA_READY | Default value = HI. Falling edge triggers 4883 read function. |
| 3 | CO1 | |
| 4 | CO2 | |
| 5 | VCC | |
| 6 | CI2 DATA_READY | Default value = LO. Rising edge triggers 4883 read function. |
| 7 | digit=1, bit=1 | |
| 8 | digit=1, bit=2 | |
| 9 | digit=1, bit=3 | |
| 10 | digit=1, bit=4 | |
| 11 | digit=2, bit=1 | |
| 12 | digit=2, bit=2 | |
| 13 | digit=2, bit=3 | |
| 14 | digit=2, bit=4 | |
| 15 | digit=3, bit=1 | |
| 16 | digit=3, bit=2 | |
| 17 | digit=3, bit=3 | |
| 18 | digit=3, bit=4 | |
| 19 | digit=4, bit=1 | |
| 20 | digit=4, bit=2 | |
| 21 | digit=4, bit=3 | |
| 22 | digit=4, bit=4 | |
| 23 | digit=5, bit=1 | |
| 24 | digit=5, bit=2 | |
| 25 | digit=5, bit=3 | |
| 26 | digit=5, bit=4 | |
| 27 | digit=6, bit=1 | |
| 28 | digit=6, bit=2 | |
| 29 | digit=6, bit=3 | |
| 30 | digit=6, bit=4 | |
| 31 | digit=7, bit=1 | |
| 32 | digit=7, bit=2 | |
| 33 | digit=7, bit=3 | |
| 34 | digit=7, bit=4 | |
| 35 | digit=8, bit=1 | |
| 36 | digit=8, bit=2 | |
| 37 | digit=8, bit=3 | |
| 38 | digit=8, bit=4 | |
| 39 | digit=9, bit=1 | |
| 40 | digit=9, bit=2 | |
| 41 | digit=9, bit=3 | |
| 42 | digit=9, bit=4 | |
| 43 | digit=10, bit=1 | |
| 44 | digit=10, bit=2 | |
| 45 | digit=10, bit=3 | |
| 46 | digit=10, bit=4 | |
| 47 | CONTROL IN 3 | |
| 48 | CONTROL IN 4 | |
| 49 | CO3 Start Instrument Data Read | Default = LO. HI pulse triggers Instrument data read. |
| 50 | CO4 /Start Instrument Data Read | Default = HI. LO pulse triggers Instrument data read. |
Below are the pin assignments shown together with Centronics 50 socket:
- CO = Control Out: output pins, used for handshake (4 pins)
- CI = Control In: input pins, used for handshake (4 pins)

Main board analysis
Main board with pin ids and chip types:

GPIB Connector J1
TBD
Addressing
Address bus: only A0..A10 pins are used for direct address decoding.
Addresses A8/A9/A10 are routed to a 3-to-8 demultiplexer U4 (74LS138). The output pins Yi are used as enable-signals for various memory-mapped sections:
- Values 000-011 (0-3 dec) are addresses inside ROM (No direct connection to ROM Chip Enable pin 20 was found)
- Value 100 (4 dec) is routed to CS-pin 13 of RAM chips U7 and U8
- Value 101 (5 dec) is routed to connector W2 pin 14
- Value 110 (6 dec) is routed to connector W2 pin 9
- Value 111 (7 dec) is routed to another 74LS138 (U17), pin 4. This chip is located in the area that seems to control the GPIB connector.
The following handmade picture shows the use of A8/A9/A10 and related chips:

Front panel LED control on Main board
- Power - controlled by PSU
- Ready
- Talking
- Listening
The LEDs are connected to a driver/inverter U21. Their states are being hold in a Flip-Flop U29. Incoming signals for this Flip-Flop come from GPIB section. No further analysis for now.

DIP switch panel
At device backside there is a IO switch to control:
- bit 0..4 - GPIB address (5 bits)
- bit 5 - Talker mode
- bit 6 - Listener mode
- bit 7 - “Only” mode (used together with Talker/Listener)
Front panel switches
- Power - controls PSU
- Reset - switch has 6 pins, assumed 2x3. One of those 1x3 switches goes to U40 on main board, around pin 8-10. I did not follow the path further for now.
- SRQ inhibit
All switches are grounded at one side.
Example code in Go
Open device:
import (
...
"github.com/msiegen/linuxgpib"
"github.com/msiegen/linuxgpib/internal"
)
var opts []linuxgpib.Option
if *verbose {
opts = append(opts, linuxgpib.Log(log.Default()))
opts = append(opts, linuxgpib.Timeout(1000*time.Millisecond))
}
d, err := linuxgpib.NewDevice(*board, *address, opts...)
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to open device:", err)
os.Exit(1)
}
defer d.Close()
Output data to device
The following code accesses sets one bit, for some pin number. For complete code, look here:
https://github.com/DennisD2/linuxgpib/blob/main/cmd/ics4883-write/readme.md
Function createDataString() is used to generate a string from pin number.
dString = createDataString(*pin)
fmt.Printf("Data string for pin %v: %v\n", *pin, dString)
if _, err := fmt.Fprintln(d, dString); err != nil {
fmt.Fprintln(os.Stderr, "Failed to write to device:", err)
os.Exit(1)
}
Function createDataString(), which creates a character string, that
defines some bit number num to be high, all others low, is below.
Note that an array is used, named outputConn, containing the mapping
from a pin number [1..50] to digit number and bit number inside digit.
The content of outputConn is complex and not listed here. See real code
(link is above) for details.
func createDataString(num int) string {
// String looks like "0080000000"
// num is in [1..50]
cpos := outputConn[num].digit
bpos := outputConn[num].bit
if cpos == 0 && bpos == 0 {
fmt.Printf("invalid pin position, no data pin: %v\n", num)
os.Exit(1)
}
queryStr := ""
var i int
for i = 1; i < cpos; i++ {
queryStr += "0"
}
queryStr += bitPosToNibble(bpos - 1)
for j := i + 1; j <= 10; j++ {
queryStr += "0"
}
return queryStr
}
func bitPosToNibble(bpos int) string {
ret := ""
switch bpos {
case 0:
ret = "1"
break
case 1:
ret = "2"
break
case 2:
ret = "4"
break
case 3:
ret = "8"
break
}
return ret
}
Reading from device
We can just try to read data, or use a SRQ for data reading. The first case is working, the SRQ case is still unknown how to do it.
Simple Read
The following code reads from input pins, all pins at once. For complete code, look here:
https://github.com/DennisD2/linuxgpib/blob/main/cmd/ics4883-read/readme.md
import (
...
"github.com/msiegen/linuxgpib"
)
Some main loop for the reading:
var p []byte = make([]byte, 12)
loops := 1
for true {
var n int
n, err = d.Read(p)
if err != nil {
e := fmt.Sprintf("%s", err)
if e != "timed out" {
// expected "error" is timeout. This is not really an error, but means
// that just no new data arrived (i.e. no LO->HO transition at pin 2)
// All other errors are real, unexpected errors
fmt.Fprintln(os.Stderr, "Failed to read from device:", err)
os.Exit(1)
}
time.Sleep(time.Second * 1)
}
if n == 0 {
continue
}
pins := prettyPrintPins(p)
fmt.Printf("%v\tRead %d bytes: %v\n", loops, n, pins)
loops++
time.Sleep(100 * time.Millisecond)
}
Helper functions:
// prettyPrintPins print bit values
func prettyPrintPins(p []byte) string {
result := ""
i := 0
for i < len(p)-2 {
bitValue := bitvalue(p[i])
commaStr := ""
if i < len(p)-3 {
commaStr = ","
}
result += fmt.Sprintf("%v%v", bitValue, commaStr)
i++
}
return result
}
// bitvalue format bit value according to 4883 coupler output data
func bitvalue(b byte) string {
bvalue := fmt.Sprintf("%x", b)
switch b {
case 0x30: bvalue = "0000"
case 0x31: bvalue = "0001"
case 0x32: bvalue = "0010"
case 0x33: bvalue = "0011"
case 0x34: bvalue = "0100"
case 0x35: bvalue = "0101"
case 0x36: bvalue = "0110"
case 0x37: bvalue = "0111"
case 0x38: bvalue = "1000"
case 0x39: bvalue = "1001"
case 0x26: bvalue = "1010"
case 0x2d: bvalue = "1011"
case 0x2e: bvalue = "1100"
case 0x2c: bvalue = "1101"
case 0x45: bvalue = "1110"
case 0x20: bvalue = "1111"
}
return bvalue
}
Output from program. I have grounded one pin. All others are unused, thus HI level and occur as “1” digits in output.
“time out” lines occur as long as there is no raising edge on pin 2 (no data).
./ics4883-read -address=16 -verbose=true
2026/10/22 15:43:55 linuxgpib.go:132 Opened board 0 with version 4.3.7
2026/10/22 15:43:55 linuxgpib.go:210 Opened address 16 (16/0) on board 0 as device 16
2026/10/22 15:43:56 linuxgpib.go:331 Failed to read from address 16 device 16: timed out
2026/10/22 15:43:58 linuxgpib.go:331 Failed to read from address 16 device 16: timed out
2026/10/22 15:43:59 linuxgpib.go:333 Read " E \r\n" in 8ms from address 16
Read 12 bytes
1: Read: 1111,1111,1110,1111,1111,1111,1111,1111,1111,1111,
2026/10/22 15:44:00 linuxgpib.go:331 Failed to read from address 16 device 16: timed out
2026/10/22 15:44:01 linuxgpib.go:333 Read " E \r\n" in 9ms from address 16
Read 12 bytes
2: Read: 1111,1111,1110,1111,1111,1111,1111,1111,1111,1111,
2026/10/22 15:44:02 linuxgpib.go:333 Read " E \r\n" in 690ms from address 16
Read 12 bytes
3: Read: 1111,1111,1110,1111,1111,1111,1111,1111,1111,1111,
2026/10/22 15:44:02 linuxgpib.go:333 Read " E \r\n" in 9ms from address 16
...
2026/10/22 15:53:39 linuxgpib.go:331 Failed to read from address 16 device 16: timed out
2026/10/22 15:53:41 linuxgpib.go:331 Failed to read from address 16 device 16: timed out
2026/10/22 15:53:56 linuxgpib.go:331 Failed to read from address 16 device 16: timed out
2026/10/22 15:53:58 linuxgpib.go:331 Failed to read from address 16 device 16: timed out
...
Read via SRQ
When executing the read() via GPIB call, the coupler generates a pulse on
pin 3/4 of J2, meaning “Start Instrument Data Read”.
Text lines found in the book PET and the IEEE488 Bus. These lines are directly for ICS 488x devices:
The response to the universal command, DT (device trigger), is to output a pulse which initiates a reading. The 4880 will asynchronously generate a service request for the controller when the data is ready.
I found: When Device Trigger command is send by controller, the coupler generates a pulse on pin 50 of J2, meaning “Start Instrument Data Read”. Nothing happens at pin 3 and 4 (which are also output pins, with unknown meaning so far).
A simple read() does not create a pulse on pin 50 of J2 (verified).
After a short while, the external instrument should provide data at the input bits and signal the availability of new data on pin 2 or 6, meaning “Instrument Data Ready”. This should generate a SRQ. (There is a switch at front of coupler “SRQ inhibit”, which will suppress SRQ generation)
From SRQ handling, a read() will then return state of all input bits.
As I wrote above, the behavior is different so far:
Behavior for SRQ topic:
- If I simply connect pin 2 to ground, there is no SRQ.
- If I first press “RESET” key on front plate and then connect pin 2 to ground,
- an SRQ is generated!
Maybe there is more handshake required than I have understood so far. It could be that the GPIB trigger topic includes more “state”, e.g. some intermediate ARM state, which must be handled via the yet unknown pins. To be found out…
SRQ handling for input data
Check for SRQ and read data:
var p = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
for true {
state, glines := internal.Iblines(*board)
if err := internal.Err(state); err != nil {
// some error handling
}
// 0x2000 means SRQ occured
if glines & 0x2000 {
// Read status byte from device
sbyte := internal.ReadStatusByte(*board, *address)
fmt.Printf("Status byte: %x\n", sbyte)
// 0x41: data available, 0x0 = no data
if sbyte == 0x41 {
fmt.Printf("Data available!\n")
_, _ = d.Read(p)
fmt.Printf("Read: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x, %x\n",
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11])
}
}
}
Details if an SRQ occurs, shortly after a “RESET” key press:
51: 16ff (16ff eoi atn srq REN ifc NRFD NDAC dav) SRQ line is LOW
52: 16ff (16ff eoi atn srq REN ifc NRFD NDAC dav) SRQ line is LOW
53: 16ff (16ff eoi atn srq REN ifc NRFD NDAC dav) SRQ line is LOW
54: 16ff (16ff eoi atn srq REN ifc NRFD NDAC dav) SRQ line is LOW
55: 16ff (16ff eoi atn srq REN ifc NRFD NDAC dav) SRQ line is LOW
56: 36ff (36ff eoi atn SRQ REN ifc NRFD NDAC dav) SRQ line is HI <-- SRQ line asserted
Read: 1111,1111,1111,1111,1111,1111,1111,0111,1111,1111,
Status byte: 0
57: 52ff (52ff eoi ATN srq REN ifc nrfd NDAC dav) SRQ line is LOW <-- ATN, srq, nrfd changed!?!
58: 16ff (16ff eoi atn srq REN ifc NRFD NDAC dav) SRQ line is LOW
59: 16ff (16ff eoi atn srq REN ifc NRFD NDAC dav) SRQ line is LOW
60: 16ff (16ff eoi atn srq REN ifc NRFD NDAC dav) SRQ line is LOW
By reading the data available, the SRQ flag is cleared, also NRFD. Now the ATN is set, I suppose the controller is doing that during finishing the SRQ handling.
GPIB connector J1
TBD
References
- GPIB Concepts - very good and short intro to GPIB by Tektronix, 1980 - Tek_gpib_concepts.pdf
- Book “PET and the IEE E488 Bus”, with section for ICS Electronics 4883 Instrument Coupler
- Excerpt from book, 4883 pages only
- Fairchild Model 4880 Instrument Coupler Instruction Manual Rev. 5 (1981), Part No. 120002
Used chips:
IO Board:
- 74LS03 Quad 2-input NAND with open collector outputs
- 74LS04 Hex Inverters
- 74LS05 Hex Inverters with open collector outputs and jm38510-00801bcb
- 74LS06 Hex Inverters with open collector outputs high voltage outputs
- 74LS74 Dual D-type FF with preset and clear
- 74LS75 Quad Latch
- 74LS138 3-to-8 Demultiplexer
Main board:
- 2708 1K EPROM
- 2112 256 bytes SRAM
- 8T87 Hex tristate bus buffer
- 8080 CPU
- 8080asm.pdf
- Instruction short table - http://dunfield.classiccmp.org/r/8080.txt
- Instruction set - https://popolony2k.com.br/xtras/programming/asm/nemesis-lonestar/8080-z80-instruction-set.html
- SN74LS00 Quad 2-Input NAND Gate
- 7410 Triple 3-Input NAND Gates
- SN7413 Dual 4-Input Positive NAND Schmitt Triggers
- DM7438 Quad 2-Input NAND Buffers with Open-Collector Outputs
- SN74107 DUAL J-K FLIP-FLOPS WITH CLEAR
- SN74LS197 30 Mhz Presettable decade or binary counters/latches
Some research papers, using 4883:
Mail to ICS
Hello,
I am searching the instruction manual for a very old device that
ICS electronics distributed many years ago. It is the
"ICS Electronics Instrument Coupler 4883", also sold as
"Fairchild Instrument Coupler 4883". There were also versions with
model numbers 4881/4882/4880.
I read somewhere else that it was possible in the past (around 2017)
to get a copy of these manuals for some amount of money + shipping.
Do you offer still this service? I would be very glad.
And one day later a response:
Hello Denni,
Thank you for the inquiry. I was able to find a copy of an old manual
for the 4880 Instrument Coupler. We can make a photocopy of it for you.
Price will be $350 which will include Postal Service.
If you are interested, please send me a mailing address and form of
payment will need to be by credit card. Delivery can take up to 2
to 3 weeks.
Best regards,
(name removed)
Um, no, I am not interested.