// 8xDIP --> 74HC165 --> ATtiny85 --> 74HC595 --> 8xLED
// ====================================================================================
// Updated 05May2015
// By C. Parkin
// https://hackaday.io/project/5439-one-tiny-bot/log/17466-expanding-the-attiny85s-io-capacity-with-shift-registers
// Pins
int clockPin = 0; // *COMMON* connected to pin 11 (SH_CP, SRCLK) of 595, pin 2 (CLK/CP) of 165
int outLatchPin = 1; //connected to pin 12 (ST_CP, RCLK) of 595
int outDataPin = 2; //connected to pin 14 (DS, SER) of 595
int inLatchPin = 3; //connected to pin 1 (SH/LD, PL)("shift/load") of 165
int inDataPin = 4; //connected to pin 9 (QH, Q7) ("data") of 165
// Other Pin Settings:
// 165:
// Pin 15 (CLK INH or CE) ("clock enable") to GROUND (active low)
// Pin 10 (SER, DS) ("serial data input") to GROUND (when not connected to another 165)
// Pin 11-14 (A-D), 3-6 (E-H) to parallel inputs
// Pin 16 to Vcc
// Pin 8 to GND
// Pin 7 (Q_H or Q_7) ("complementary output from the last stage") left unconnected?(as shown on 2+ sources)
//
// 595:
// Pin 10 (MR, SRCLR) ("Master Reset", "Serial Clear") to Vcc
// Pin 13 (OE) ("output enable input") to GROUND (active LOW)
// Pin 16 to Vcc
// Pin 8 to GND
// Pin 15, 1-7 to parallel outputs
// Pin 9 (Q7") ("Serial out") left unconnected w/only 1 chip?
// Serial storage variables
byte inByte; //for the 8 values loaded FROM the 165 shift register
byte outByte; //for the 8 values loaded TO the 595 shift register
// function to read in from 165
void getter() {
// take the latch pin low to move the parallel inputs into the shift register
digitalWrite(inLatchPin, LOW);
delayMicroseconds(5); //some resources suggest 10 for this; try that if 5 doesn't work.
digitalWrite(inLatchPin, HIGH);
// populate the inByte
for (int bitCount = 0; bitCount < 8; bitCount++) {
// set the current bit to the current value of inDataPin
bitWrite(inByte, bitCount, !digitalRead(inDataPin));
//pulse the clock to shift to the next serial-in bit
digitalWrite(clockPin, HIGH);
delayMicroseconds(5);
digitalWrite(clockPin, LOW);
}
}
// function to write out to 595
void putter() {
// output the outByte
for (int bitCount = 0; bitCount < 8; bitCount++) {
// set outDataPin according to current bit value:
digitalWrite(outDataPin, bitRead(outByte, bitCount));
//pulse the clock
digitalWrite(clockPin, HIGH);
delayMicroseconds(10);
digitalWrite(clockPin, LOW);
}
//take the latch pin high to move the new sequence to the parallel output
digitalWrite(outLatchPin, HIGH);
delayMicroseconds(5);
digitalWrite(outLatchPin, LOW);
}
void setup() {
// Common Clock Pin
pinMode(clockPin, OUTPUT); //sends pulses to the shift registers
// IN specific pins
pinMode(inLatchPin, OUTPUT); //latch/loads the current parallel in values into the shift register for serial output to tiny
pinMode(inDataPin, INPUT); //serial input from shift register to tiny
// OUT specific pins
pinMode(outLatchPin, OUTPUT); //shifts current serial values in register to register outputs
pinMode(outDataPin, OUTPUT); //serial output from tiny to shift register
// Set pins to proper states: (Is this better done in the loop or getter/putter functions?)
digitalWrite(inLatchPin, HIGH); // SH/LD is active low, so we set it high to avoid premature loading
digitalWrite(clockPin, LOW); // clock is low-to-high edge-triggered, so start low
digitalWrite(outLatchPin, LOW); // SH_CP is positive-edge triggered, so start low
// Initialize in/outBytes to zero
inByte = B00000000;
outByte = B00000000;
}
void loop() {
getter();
// Here is where we would, in a more complicated program, figure out what to do with the input data
outByte = inByte; // In this simple case, simply pass it over to the Putter function
putter();
}