Note: All photographs appearing on this page are freely usable for any purpose. Links to high-resolution versions of the pictures appear below each picture.

EtherPort Data Acquisition & Control System

EtherPort DOUT

48-Channel digital output board


High-resolution image

 

The EtherPort DOUT board is a 48-channel digital input board. The EtherPort DOUT offers the following features:

  • Open Source/Open Hardware design (Creative Commons 4.0 license)
  • Single 5V power supply
  • LED indicates when power is applied
  • 48 independent output bits (TTL 5v outputs)
  • 48 output pins divided up into 4 banks of 12 bits each
  • Optional DIN rail brackets allow installation on 35mm DIN rails
  • DIN rail brackets are available in .STL format for 3D-printing
  • Full documentation including System Requirements Specifications (SyRS), Hardware Requirements Specifications (HRS), Hardware Inspection list (HI), Hardware Test Cases (HTC), Hardware Test Procedures (HTP), Hardware Design Description (HDD), and (reverse) Traceability Matrix (RTM) are available for the EtherPort system, including this board.
Table of Contents
Bill of Materials (BOM)
PCB Availabilty and Files
DIN Rail Mounts
Revision History
Board Layout
Connections
DIP Switches
Test Pins
Software Support
Build an EtherPort DOUT Board
Testing the EtherPort DOUT Board
Hardware Design Description
Software Design

 

Bill Of Materials

Bill of Materials (BOM) for the EtherPort DOUT board:

  • (1) 5mm LED
  • (1) 470 Ω 1/4-watt 1% resistor
  • (2) 10 kΩ 1/4-watt 1% resistor
  • (7) 0.1 µF decoupling capacitors
  • (1) 1000 µF electrolytic capacitor
  • (1) 2-pin screw terminal (5mm/0.2" centers) or (1) 5.5mm Barrel Jack for power
  • (4) 24-pin (2x12) male headers (ribbon cable connectors)
  • (1) 74HC125 4-ch tri-state buffer (SOIC-14)
  • (6) 74HC595 serial-in parallel-out shift registers (DIP)
  • (1) 8-position DIP switch
  • (1) 1x12 female header with long pins (Feather bus)
  • (1) 1x16 female header with long pins (Feather bus)
  • (1) Teensy 3.2 with (full) headers
  • (1) EtherPort PCB
  • (1) Adafruit Ethernet Featherwing -or- Robotdyn W5500 Ethernet module (if Ethernet connection is desired)
  • (1) 2x6 female header with long pins (if using Robotdyn W5500 Ethernet module)
  • Optional: (10) test pins
  • Optional: (1) set of female headers for use as a Teensy socket
  • Optional: one set of horizontal 35mm DIN rail mounts for EtherPort/DAQ boards
  • Optional: one EtherPort DOUT vertical 35mm DIN rail mount
  • Optional: 1 set of 3D-printed Featherwing shrouds for the Featherwing headers (STL files here and here)

PCB Availability and Files

Note: If you only want a few EtherPort DOUT PCBs, contact Plantation Productions (randy@plantation-productions.com) to see if there are any in stock. Bare boards are $20 each plus shipping; fully assembled and tested boards are $499 each. If you need more than a couple PCBs and you're not in a huge hurry, it costs about $50 (plus about 4-6 weeks) plus shipping to have a set of 10 manufactured and shipped to you from China. I use Seeed Studio Fusion PCD service (https://www.seeedstudio.com/fusion.html). The EtherPort DOUT PCBs are two-layer boards.

Description Link
Gerber files for PCB (provide these files to Seeed Studio or your personal PCB manufacturer) EtherPort DOUT Gerber Files for PCB
Eagle schematic capture and PCB layout files. Use these if you want to modify or enhance the EtherPort DOUT design, or re-layout the PCB using Eagle EtherPort DOUT Eagle files (Schematic and board layout)
On-line schematic (PDF format)

EtherPort DOUT Schematic (PDF)

PP Standard DIN rails (STL format for 3D printer) PP Standard DIN Rail Brackets 3D printer files
Adjustable DIN rail bracket (STL format for 3D printer) Adjustable DIN Rail Bracket 3D printer file
Vertical DIN rail bracket (STL format for 3D printer) EtherPort DOUT Vertical DIN Rail Bracket

 

DIN Rail Mounts

The DIN rail mounts were created using AutoDesk's Fusion 360 (to produce STL files) and I personally print the results on a Lulzbot Taz6 3D printer using ABS filament (ABS is recommended for this job, PLA and PETG are a bit brittle).

There are three sets of DIN rail mounts:

  1. The "standard" Plantation Productions' DIN rail mounts. These work on most Plantation Productions' DAQ and EtherPort boards (3.5" x 5.9" / 90x150mm). There are two different mounts–one for the left side of the board and one for the right side of the board (the difference is how they tuck away the bulk of the mount underneath the PCB). These mounts have a fixed pair of arms that attach to the DIN rail. They are most easily slid onto the DIN rail from the end of the rail (if you're strong enough to bend the plastic, you can force them on or off in the middle of the rail). The EtherPort DOUT PCB attaches to the standard DIN rail mounts using a set of four 3/8" #3 wood screws (two for each mount).
  2. The "adjustable" DIN rail mounts. These have an adjustable arm that latches onto the DIN rail. You tighten the arm down on a DIN rail using a 3/8" #3 wood screw. There is only a single version of this rail mount as it as two sets of holes to allow placement on either side of the PCB (the drawback is that certain boards may have through-hole pins that run into the plastic on the DIN rail as the interface area to the PCB is wider than the standard rail mounts). The EtherPort DOUT PCB attaches to a pair of adjustable DIN rail mounts using a set of four 3/8" #3 wood screws (two for each mount).
  3. The EtherPort DOUT vertical mount allows mounting the board vertically (rather than flat) on the DIN rail. This takes up less (horizontal) space than the standard and adjustable DIN rail mounts at the expense of not holding the board as rigidly. Also (obviously), the vertical mount requires more space above the DIN rail. One other disadvantage is that the vertical mount is specially designed for the EtherPort DOUT PCB and likely won't work with many other EtherPort or DAQ boards. The EtherPort vertical DIN rail mount also has an adjustable arm. The EtherPort DOUT PCB attaches to the vertical DIN rail mount using a pair of M3x20mm bolts and nuts (washers are also recommented).

The adjustable DIN rail (for 35mm DIN rails) as one arm that swings away for easily attaching to a 35mm DIN rail. You can tighten this arm down with 3/8" #3 wood screw. Note that it has a pair of holes on both sides so it can mount on the left or right side of an EtherPort DOUT board.

Adjustable DIN Rail Mount

Standard DIN Rail Mounts (Left and Right)

 

Vertical EtherPort DOUT mount

Revision History:

Rev 2:

Connected 3V3 (pin 26) to Feather 3.3V.
Added 74lvc125 buffer to protect MISO line.
Redesigned serial shift register logic to use 74HC595 ICs.
Changed LED resistor to 470Ω.

Rev 3:

Connected Feather RST line to Teensy PROG.
Switched QH to Serin line to QH' to Serin.


 

 

EtherPort DOUT Board Layout

 

Connecting Digital Inputs to the EtherPort DOUT Board

The 48 output lines on the EtherPort DOUT are broken up into 4 banks of 12 bits/bank. The connectors have the following pinouts:

 

Note, however, that the bit numbers are offset according to the bank number:

Bank # Starting bit #
0
D0
1
D12
2
D24
3
D36

So, for example, pins 19 and 20 for Bank 3 would actually be D36 and D37, respectively (and pins 1 and 2 would be D47 and D46, respectively).

Because the digital outputs from the EtherPort DOUT aren't usually high-frequency signals (host system generally writes these inputs at around 10-20 Hz), their cabling requirements aren't very critical.

The 74HC595 ICs used on the EtherPort DOUT run off a 5V power supply. Output pins provide a 5V/TTL-logic level. If you intend to connect these outputs to a system expecting 3.3v logic (and cannot tolerate 5v), you will need to use a level shifter.

 

DIP Switches on the EtherPort DOUT

The EtherPort DOUT board contains eight DIP switches, six of which connect to various input pins on the Teensy 3.2. This provides a convenient set of switches for setting default values and other options within your software. The standard software (and silkscreen markings) use these switches to set the Ethernet IP address and enable USB and an OLED display.

Test Pins on the EtherPort DOUT

The EtherPort DOUT board contains 10 test locations that make varous signals available to DVMs, Oscilloscopes, logic analyzers, and other devices:

  • MISO (Master In, Slave Out SPI data signal)
  • MOSI (Master Out, Slave In SPI data signal)
  • SPICLK (SPI clock signal)
  • CS (chip select for the Feather bus (bit 10)
  • Serin (74HC595 serial input signal)
  • CLR (74HC595 clear registers signal)
  • RCK (74HC595 register clock)
  • SCK (74HC595 shift clock)
  • Gnd
  • Vcc (+5V)

You may optionally install test pins in each of these holes. A test pin allows you to clamp a test lead to the pin allowing hands-free circuit connection (otherwise you will need to press the test probe against the test signal's PCB pad).

 

Software Support for the EtherPort DOUT

The standard firmware can be found here:

EPDout.ino

The standard software can be configured to work with a Robotdyn W5500 Ethernet module or an Adafruit Ethernet Featherwing (this requires changing a single define in the source code). With a little bit of hackery, you could actually use both Ethernet modules, if you really had the need.

The standard firmware supports an Adafruit OLED Featherwing module (enabled by putting DIP switch 6 in the on position during power up). It also supports USB communication (in addition to Ethernet communication) by putting DIP switch 5 in the on position during power up.

The standard firmware is an Ethernet server application that waits for an Ethernet client to connect. It supports up to eight concurrent Ethernet clients (though usually there will be only one, maybe two during software testing). Once connected, the Ethernet client can send digital output values to the server or set different operating modes by sending lines of text (with commands) to the EtherPort DOUT and waiting for a response from the EtherPort DOUT.

The EtherPort DOUT server software accepts the following commands from the client (all commands are ASCII text terminated by a newline/linefeed character):

  • dout xxx yyy zzz ttt

where xxx, yyy, zzz, and ttt are three-digit hexadecimal numbers representing the bit pattern outputs for bank 0, 1, 2, and 3 (respectively). Bit 0 of xxx represents bit 0 on Bank 0 output pins; bit 11 of xxx represents bit 11 of xxx on Bank 0 output pins. Bit 0 of yyy represents bit 0 on Bank 1 output pins; bit 11 of yyy represents bit 11 of yy on Bank 1 output pins. Etc.

The dout command echos the input command as its response:

din xxx yyy zzz ttt

If DIP switch 5 is in the on position on power up, then the EtherPort DOUT server firmware will also accept these commands from the USB port (which looks like a serial port on a typical host PC connected to the USB port).

 

Building a EtherPort DOUT Board

Here's the bare EtherPort DOUT PCB (printed circuit board):


High resolution image

(Note: these build instructions show a Rev 2 board. Rev 3 construction is exactly the same.

  1. The usual build process is to build a board from "the bottom up." This means to first install those items closest to the PCB and work you way up to larger objects on the PCB. So, the first thing to start with in the single SMT (surface mount technology) part on the board: the 74HC125 IC. Fortunately, this is an SOIC-14 package and it's possible (with care) to solder it onto the board with a standard (though fine-tipped) soldering iron. Begin by tacking one pin (pin 8 is a good anchor) down on the circuit board:


    High resolution image

  2. Ensure that all the 74HC125 pins are aligned with the pads on the PCB. Solder down the remaining pins (I usually start with pin 14 – the pin diagonally across from pin 8– and then solder the other pins in order). Note how I also cleaned up the tacked pin (8) while doing this:

    High resolution image

  3. Next, solder on the seven 0.1µF bypass capacistors, the two 10kΩ resistors, and the 470Ω resistor:


    High resolution image

  4. The next step is optional: install the 10 test pins on the PCB. Generally, test pins are useful for testing initial runs of PCBs and while developing software for the board. However, for a production run, that than possibly connecting the ground test pin, you really don't need to install test pins. Though test pins could prove useful for field maintenance, it's easy enough to put a scope, logic analyzer, or DVM probe directly on the test pin pads.


    High resolution image


  5. The next step is also optional: install sockets for the ICs on the board. Sockets are optional. They make field repairs easy, but using sockets actually makes the board less reliable than soldering the ICs directly on the board (after several years, the contact between the IC pins and the socket gets corroded and the contact becomes intermittent; removing and reseating the IC usually solves this issue, but it’s a problem you don’t normally have when ICs are soldered directly to the board). If you do choose to use sockets, be sure to use high-quality ones (yes, high-quality sockets often cost more than the ICs going into them). Low-quality sockets create more problems than they solve. When installing sockets, be sure to insert them into the board with the notch on the socket matching the notch in the IC outline on the silkscreen.


    High resolution image

    Note: if you choose not to install sockets, you can solder the ICs onto the PCB at this point. Again, be sure to note the orientation of the chips based on the silkscreen images for the ICs.

    When inserting ICs, you will notice that the pins on the ICs are actually slanted outward and will not directly fit in the holes on the board (or in holes on the sockets, for that matter).  If you have an IC inserter tool, it will automatically bend the pins to the appropriate position prior to insertion. If you don’t have such a tool available, just hold an IC with your fingertips with one row of pins against your workbench or desk and manually bend the pins until they are perpendicular to the body of the IC. Repeat for the pins on the other side of the IC.
    IC Insertion Tool:

    High resolution image

    Board with ICs soldered directly to the PCB:

    High resolution image



  6. For the next step, solder the LED, DIP Switch, and power connector onto the PCB. Note that the DIP switch should always be soldered directly onto the PCB; most DIP switches have pins that are too weak and shaped improperly to go into sockets. Besides, there’s not much to fail in a switch, so the likelihood you will need to ever replace it is low.

    The EtherPort DOUT PCB provides two options for the power connector: you can either install a two-pin screw terminal (I prefer the higher-quality ones that have a removable screw terminal component—see the photograph), or you can install a 5.1mm barrel jack (center pin is +5v). Note that you should install only one or the other.


    High resolution image

    Example showing a detachable two-pin screw terminal (actually on an EtherPort DIN board, but terminal is the same)

    High resolution image

    5.5mm Barrel Jack (also on an EtherPort DIN board, but looks the same on EtherPort DOUT):

    High resolution image

  7. The next step is to solder on all the dual row headers. There are four 24-pin (2x12):


    High resolution image

  8. Now, it's time to install the Teensy 3.2. The first step is to solder all the pins on the Teensy 3.2 (assuming you don't already have one prepared). The instructions for soldering all the pins on a Teensy 3.2 appear here. That web page also describes how to manufacture a socket for the Teensy 3.2 (a good thing to build, it's nearly impossible to remove a Teensy 3.2 from the EtherPort DOUT PCB if you soldered it directly onto the PCB; using a heat gun usually damages the Teensy).




    High resolution image

  9. Now, it's time to install the Feather Bus headers. These are a pair of 1x12 and 1x16 female headers with long leads. You can get them from Adafruit or chop up a set (if you don't find the exact length you need) from longer ones purchased on Amazon (or elsewhere). The Feather bus headers need to raise the Featherwing above the Teensy 3.2. The Adafruit headers (which I'm pretty sure are a standard height) just barely clear the Teensy installed in a socket, leaving just enough pin length in the hole to solder them onto the PCB. The real problem is getting them soldered on in a level manner (especially the same level on both sides of the Teensy). To make this task easier, I've created a pair of shrouds that I've 3D printed into which I insert the pins of the headers. Find the 12-pin shroud here. Find the 16-pin shroud here.

    High-resolution image


    High-resolution image

  10. Insert the 1x12 and 1x15 Feather bus headers into the shrouds and insert them into the appropriate holes on either side of the Teensy 3.2. I generally insert some Featherwing into the headers to hold them at the right position while I solder the headers to the PCB:

    High-resolution image


  11. After tacking down opposite corners of the Feather bus headers, turn the board back over and verify that the headers are evenly pressed into their holes, then finish the soldering of the remaining pins.

    High-resolution image

  12. Next you have to decide whether (1) You will use Ethernet communications on the board (despite the name, Ethernet is optional; you could just use USB), and (2) if using Ethernet, which interface will you use. There are two "standard" Ethernet interfaces you can use with the EtherPort DOUT: An Adafruit Etherwing board (that plugs into the Feather bus headers) or a Robotdyn W5500 Ethernet module. The Adafruit unit is a lot more reliable in my experience, the Robotdyn unit is 1/3 the cost. In reality, you can hook up any 5v W5500 Ethernet module to the EtherPort DOUT board. The SPI bus lines come out to the 2x6 connectors on the board and there are even four mounting holes into which you can screw a 3D printed bracket for your own module (you could even run a 3.3v unit by running a wire from the Feather/Teensy 3.3v output to your module). However, this assembly tutorial will assume you're attaching a Robotdyn or Adafruit Etherwing module.

    Robotdyn W5500 Ethernet module:

    High-resolution image

    Note: The STL file for the 3D printed bracket for the Robotdyn W5500 Ethernet module can be found here. You attach the bracket using four #3 3/8" wood screw (two for the Robotdyn board, two for the EtherPort DOUT PCB).

  13. If connecting a Robotdyn W5500 Ethernet module, you have two choices: you can mount the module on the top of the board or the bottom of the board. Here it is mounted on the bottom:

    High-resolution image

    Here it's mounted on the top (the typical mount point):

    High-resolution image



    You can also install an Adafruit Etherwing on the Feather bus connector rather than the Robotdyn module.

  14. Finally, install the 1000 µF capacitor:

    High-resolution image



  15. At this point, soldering is largely complete (assuming you’ve made no mistakes that will require some rework).  Turn the board over and slowly, careful, visually inspect every solder joint. Well over 50% of the failures I’ve had were due to missing a solder connection. It’s worthwhile to visually inspect all the pins (yeah, I know, there are a lot of them) to verify you haven’t missed any.

    High-resolution image

  16. Now for the actual “smoke” test. With the ICs inserted, apply power and make sure the LED still lights up (no flickering!) and nothing gets overly hot (or worse, smokes and catches on fire! Yes, this has happened to me in the past).

Testing the EtherPort DOUT Board

  1. Assuming your board passes the “smoke” test, now it’s time to do a real test on the board. This will require running software on the EtherPort DOUT board.   I have written a piece of test software that runs on the EtherPort DOUT board: EPDoutTest.ino. The test software assumes that there is an Adafruit OLED Featherwing plugged into the EtherPort DOUT, though it is easy enough to remove this requirement by modifying the source code.
  2. The test software ignores the DIP switches other than to print their positions (as part of the test).
  3. The EPDoutTest.ino program reads an integer in the range 0 through 47 from the Arduino Serial window and sets the bit specified by this integer to '1'. It sets all the other output bits to '0'. You can enter a value from the Arduino IDE's serial window input line and then check the specified output bit to ensure it is set to '1' (it wouldn't hurt to check surrounding bits and ensure they contain '0').
  4. Note that the EPDoutTest.ino program simply checks the functionality of each of the output pins, it does not verify the operation of the Ethernet port. It *somewhat* checks the function of the USB port as the test program writes the output to the Arduino/Teensyduino serial output display.
  5. After testing all the output pins, you should also flip each of the DIP switches and verify that they work properly. Note that the test program displays a '1' bit if the switch is in the *off* position, a '0' bit if the switch is in the *on* position. Also note that only switches 3-8 are wired to the Teensy 3.2.
  6. The next step is to install the standard EtherPort DOUT firmware. If you flip the USB switch (sw 4) to the "on" position, you can enter DOUT commands from the Arduino input line and view the output on the Arduino serial output.
  7. To test the Ethernet port, use an Ethernet terminal program. I've always used the Hercules terminal program. Running it, I can type all the EtherPort DOUT commands ("dout", "reset", and "refresh") and check their operation.

Hardware Design Description

The hardware design for the EtherPort DOUT board is relatively straight-forward. Six 74HC595 parallel-to-serial shift registers are wired in series and connected to the Teensy 3.2. Pin 29 from the Teensy drives the SCK (shift register clock) inputs on the 74HC595s. The 74HC595 CLR (clear) pin is driven by pin 30 on the Teensy. The RCK (register transfer clock) input is driven by pin 32 on the Teensy. Pin 2 on the Teensy connects to the serial input pin on the first 74HC595 in the shift register series. The QH' line on the first through fifth 74HC595 ICs (the unlatched serial output signal) connects to the serial input of the next 74HC595 in the series.

 

The Robotdyn W5500 Ethernet Module will actually work off 5v or 3.3v. However, to avoid problems the EtherPort DOUT board only runs 5v to the connector for this device. The MOSI, chip select (pin 29), and clock pins are all 3.3v going to the Ethernet module (which is fine, that's still TTL compatible). The MOSI signal coming back from the Robotdyn board has to be level shifted from 5v down to 3.3v (also using one of the channels on the 74LVC125 IC). You can wire up a different W5500-based Ethernet board to the EtherPort DOUT; the +5v, Gnd, MOSI, MISO, SCK (SPI-CLK), and CS lines are clearly labelled next to the holes on the EtherPort PCB. You could even run a 3.3v version by running a jumper wire from the 3.3v output on the Teensy 3.2 to the power supply on your device (running the 3.3v output through the 74LVC125 won't matter). Two sets of W5500 connectors were placed on the board to allow mounting the Ethernet module on the top or bottom of the board.

As a general rule, Plantation Productions' DAQ and EtherPort boards attempt to use through-hole ICs and parts. SMT devices are usually put on breakout boards so they can be (more) easily removed from a PCB, if necessary. The 74LVC125, sadly, is only available in an SMT package (SOIC-14 for the variety used on the EtherPort DOUT board). Because the IC is so cheap (well under a dollar), and it's still easy enough to hand solder, the 74LVC125 was put directly on the EtherPort DOUT PCB. If you need to remove it, a localized hot-air gun, or better yet a Chip Qwik SMD removal kit, will take it off.

The Feather bus on the EtherPort DOUT is primarily intended for the Adafruit Ethernet Featherwing board (assuming a Robotdyn W5500 Ethernet module is not used). Two "canned" solutions for Ethernet were designed into the EtherPort DOUT board because Robotdyn modules, being rather inexpensive, haven't always worked. The Adafruit Ethernet Featherwing, on the other hand, has never not worked. The Feather bus also supports the Adafruit OLED Featherwing display module. The design includes four extra mounting holes for a Featherwing doubler, in case the need arised to install both an OLED display and an Ethernet Featherwing. Other possible Featherwing modules, such as the data logger or real-time clock, are generally stackable; therefore, no attempt was made to allow the installation of anything bigger than a doubler.

On most EtherPort boards (including the DOUT), every attempt is made to leave the general-purpose analog and digital I/O pins unused. Except for the SPI and I2C bus pins (SDA, SCL, MOSI, MISO, and SCK) the Feather bus pins are left alone for Featherwings (wherever possible). For digital I/O lines, the EtherPort DOUT uses the non-Feather I/O pins found on the Teensy 3.2.

Note: on power up, the output values on the 74HC595 (output) pins are undefined. The standard firmware immediately clears the output registers on bootup. If you write your own firmware for the EtherPort DOUT, you should also clear all the output bits on power up.

 

Software Design Notes

The standard firmware running on the has a couple of important defines and variables that must be set when compiling the code:

  • #define EthCS (xx): This should be set to either "(cs)" (for an Adafruit Ethernet Featherwing) or to "(W5500pin)" (for a Robotdyn W5500 Ethernet module). If you wire up a different module, you should also use the "(W5500pin)" define and use the chip select (pin 31) set aside for the W5500.
  • #define baseIP2ndB 2: The EtherPort DOUT responds to IP address 192.168.x.y. The x byte is specified by the baseIP2ndB define (default is 2). If you want to change this to some other value, change the define for baseIP2ndB. Note: most Plantation Productions' software expects the second byte to be 2. Think carefully before changing this value as you might make the EtherPort DOUT firmware incompatible with other Plantation Productions' devices and firmware.
  • #define baseIPadrsLOB 30: The low-order byte of the IP base address defaults to this value (30 is the standard default). Note that the firmware reads DIP switches 1 through 4 and adds this 4-bit value to the LO byte. This allows multiple EtherPort DOUT boards in the system (without modifying the firmware). Because it's possible to enter 15 on the DIP switches, the default LO base byte value must be 240 or less.
  • #define usbDebug 0: This define should be 0 for standard firmware builds. If it is non-zero, then the firmware writes debug information to the Arduino Serial device (i.e., the USB port) during operation. For testing purposes, this output is useful. However, if you've enabled the USB port for host communication purposes, this debug information may interfere with the operation of the host software.
  • Note that when shifting data out to the shift register, the system must shift the most significant bit (bit 47) first and the least significant bit (bit 0) last. The EtherPort DOUT hardware implements a software shifting scheme using I/O pins on the Teensy, it does not use the SPI pins for this purpose. The following is the code for shifting out a bit, byte, and 48 bits to the EtherPort DOUT output pins (as well as a function that clears all the output bits):
// shiftBit-
//
//  Shifts a bit to the output shift register.

void shiftBit( int bit )
{
    digitalWrite( Ser, bit );   // Set output bit.
    digitalWrite( SerClk, 0 );  // Pulse the serial 
    digitalWrite( SerClk, 1 );  // shift register clock.
    digitalWrite( SerClk, 0 );
}

// Shift12-
//
//  Shifts 12 bits into the output shift register.

void shift12( uint16_t word )
{
    shiftBit( !!(word & 0x800) ); // Shift out the HO bits first!
    shiftBit( !!(word & 0x400) );
    shiftBit( !!(word & 0x200) );
    shiftBit( !!(word & 0x100) );
    shiftBit( !!(word & 0x80) );
    shiftBit( !!(word & 0x40) );
    shiftBit( !!(word & 0x20) );
    shiftBit( !!(word & 0x10) );
    shiftBit( !!(word & 0x08) );
    shiftBit( !!(word & 0x04) );
    shiftBit( !!(word & 0x02) );
    shiftBit( word & 0x01 );
}

// shift48-
//
//  Ships a full 48 bits into the shift register, and then
// copies the shift register data to the output register.

void shift48( uint16_t word3, uint16_t word2, uint16_t word1, uint16_t word0 )
{
    shift12( word3 );       // Shift out the HO bits first!
    shift12( word2 );
    shift12( word1 );
    shift12( word0 );
    digitalWrite( RCK, 0 ); // Pulse the register clock line to
    digitalWrite( RCK, 1 ); // transfer the data from the shift
    digitalWrite( RCK, 0 ); // registers to the output latches.
    banks[0] = word0;       // Save output values to display
    banks[1] = word1;       //  on the OLED.
    banks[2] = word2;
    banks[3] = word3;
}

// clear48-
//
//  Quickly clears all 48 bits in the shift/output registers

void clear48( void )
{
    digitalWrite( Clr, 1 );  // Pulse the CLR line (active low).
    digitalWrite( Clr, 0 );
    digitalWrite( Clr, 1 );
    digitalWrite( RCK, 0 );  // Pulse the register clock to copy
    digitalWrite( RCK, 1 );  // the zeroed shift registers to 
    digitalWrite( RCK, 0 );  // the output latches
    banks[0] = 0;            // Clear the output values to display
    banks[1] = 0;            // on the OLED.
    banks[2] = 0;
    banks[3] = 0;
}