 }
 
 
+// --- Misc utils functions ---
+
+void settle() {
+    delayMicroseconds(150);
+}
+
+
+// Useful resources:
+// - http://www.hp9845.net/9845/tutorials/hpib/
+
+
+// --- GPIB implementation ---
+
+
+void send_byte(byte_t data) {
+    // wait for all devices to be ready for data.
+    while (check_nrfd() == true) { settle(); }
+
+    // place our data onto the bus
+    gpib_set_data_bus(data);
+    settle();
+
+    // inform the listeners that the data is ready.
+    assert_dav();
+    settle();
+
+    // wait for all devices to read the data.
+    while (check_ndac() == true) { settle(); }
+
+    // indicate that we are done transmitting this byte.
+    unassert_dav();
+    settle();
+
+    // release the data bus lines.
+    gpib_release_data_bus();
+    settle();  
+}
+
+// Uni-line (single) commands.
+// Uni-line commands only require that one bus line be asserted, and do not require a handshake.
+// Use the assert_x functions for these commands:
+void IFC() {
+    assert_ifc();
+    settle();
+    unassert_ifc();
+    settle();
+}
+
+
+// Universal multi-line commands
+// Universal multi-line commands work by asserting ATN while putting a data byte on the bus.
+// The data byte determines which command is issued.
+// Universal multi-line commands apply to all devices on the bus.
+#define LAD_BASE  0x20
+#define TAD_BASE  0x40
+#define SAD_BASE  0x60
+
+byte_t self_gpib_address = 30;
+
+// "Device Listen Address": configure the device at the given address to be a listener.
+void LAD(byte_t address) {
+    send_byte(LAD_BASE + address);
+}
+
+// "Device Talk Address": configure the device at the given address to be a talker.
+void TAD(byte_t address) {
+    send_byte(TAD_BASE + address);
+}
+
+// "Secondary Device Address".
+void SAD(byte_t address) {
+    send_byte(SAD_BASE + address);
+}
+
+// "My Listen Address": declare self to be the listener.
+void MLA() {
+    LAD(self_gpib_address);
+}
+
+// "My Talk Address": declare self to be the talker.
+void MTA() {
+    TAD(self_gpib_address);
+}
+
+// "Unlisten": change all listeners back to an idle state.
+void UNL() {
+    LAD(31);
+}
+
+// "Untalk": change all talkers back to an idle state.
+void UNT() {
+    TAD(31);
+}
+
+
+// REN: place the device at the given address into REMOTE (listen) mode.
+void REN(byte_t address) {
+    assert_ren();
+    assert_atn();
+    settle();
+
+    UNL();
+    TAD(self_gpib_address);
+    LAD(address);
+
+    unassert_atn();
+    settle();
+}
+
+
+void test_K196() {
+    REN(17);
+    send_byte('D');
+    send_byte('A');
+    send_byte('T');
+    send_byte('M');
+    send_byte('E');
+    send_byte('G');
+    send_byte('A');
+    send_byte('X');
+}
+
+
+// Addressed commands
+// Addressed commands use multiple bus lines.
+// Addressed commands work by asserting ATN while putting a data byte on the bus.
+// The data byte determines which command is issued.
+// Addressed commands apply to only one device on the bus, so they require some setup.
+// Before you can issue one of these commands, you need to set up a device as a listener (or talker).
+
+
+
+
 // --- Low-level remote control protocol ---
 
 

    return data;
}

void set_gpib_data_bus_mode(arduino_pinmode_t mode) {
    pinMode(DIO1_ARDUINO_PIN, mode);
    pinMode(DIO2_ARDUINO_PIN, mode);

// %  Print an informational message ("atmega-gpib\n")

#define CMD_PING   '%'
#define CMD_PERFORM_TEST_1   '1'


// --- GPIB commands ---
