/*
  SparkFun Inventor's Kit
  Example sketch 14
  SHIFT REGISTER
  Use a shift register to turn three pins into eight (or more!)
  outputs
  An integrated circuit ("IC"), or "chip", is a self-contained
  circuit built into a small plastic package. (If you look closely
  at your Arduino board you'll see a number of ICs.) There are
  thousands of different types of ICs available that you can use
  to perform many useful functions.
  The 74HC595 shift register in your kit is an IC that has eight
  digital outputs. To use these outputs, we'll use a new interface
  called SPI (Serial Peripheral Interface). It's like the TX and
  RX you're used to, but has an additional "clock" line that
  controls the speed of the data transfer. Many parts use SPI
  for communications, so the Arduino offers simple commands called
  shiftIn() and shiftOut() to access these parts.
  This IC lets you use three digital pins on your Arduino to
  control eight digital outputs on the chip. And if you need
  even more outputs, you can daisy-chain multiple shift registers
  together, allowing an almost unlimited number of outputs from
  the same three Arduino pins! See the shift register datasheet
  for details:

  http://www.sparkfun.com/datasheets/IC/SN74HC595.pdf

  This sketch was written by SparkFun Electronics,
  with lots of help from the Arduino community.
  This code is completely free for any use.
  Visit http://learn.sparkfun.com/products/2 for SIK information.
  Visit http://www.arduino.cc to learn about the Arduino.
  Version 2.0 6/2012 MDG
*/

/*
Modified to illustrate simultaneous input and output capability
of SPI by adding a 74HC165 PISO shift register and hardware inverter.
*/

#include <SPI.h>

// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;
const int slaveSelectPin2=9;

SPISettings HC595(14000000, MSBFIRST, SPI_MODE0);

// We'll also declare a global variable for the data we're
// sending to the shift register:

byte data = 0;
uint8_t buffer;

void setup()
{
  // set the slaveSelectPin as an output:
  pinMode(slaveSelectPin, OUTPUT);
  // initialize SPI:
  SPI.begin();
}

void loop()
{

  // To try the different functions below, uncomment the one
  // you want to run, and comment out the remaining ones to
  // disable them from running.

  oneAfterAnother();      // All on, all off
  // oneOnAtATime();       // Scroll down the line
  // pingPong();           // Like above, but back and forth
  // randomLED();          // Blink random LEDs
  // marquee();
  // binaryCount();        // Bit patterns from 0 to
}

void oneAfterAnother()
{
  /* This function will set all the LEDs ON or OFF
     based on the eight input switches on the 74HC165
     PISO shift register.

     A separate switch selects inverted/non-inverted
     data out of the switch register.
  */
  static uint8_t index;
  //index = 0xaa;

  // SPI Transaction: sends the contents of buffer, and overwrites it with the
  // received data. digitalWrite(slaveSelectPin, HIGH);
  SPI.beginTransaction(HC595);

  digitalWrite(slaveSelectPin, LOW);
  buffer = SPI.transfer( buffer);
  digitalWrite(slaveSelectPin, HIGH); // strobe SR data to outputs
  SPI.endTransaction();
  index = buffer;

  //delay(200);
}

void shiftWrite(int desiredPin, boolean desiredState) {

  // This function lets you make the shift register outputs
  // HIGH or LOW in exactly the same way that you use digitalWrite().

  // bitWrite(data, desiredPin, desiredState); //Change desired bit to 0 or 1 in "data"

  // // Now we'll actually send that data to the shift register.
  // // The shiftOut() function does all the hard work of
  // // manipulating the data and clock pins to move the data
  // // into the shift register:

  // shiftOut(datapin, clockpin, MSBFIRST, data); //Send "data" to the shift register

  // //Toggle the latchPin to make "data" appear at the outputs
  // digitalWrite(latchpin, HIGH);
  // digitalWrite(latchpin, LOW);
}




void oneOnAtATime()
{
  // // This function will turn the LEDs on and off, one-by-one.
  // int index;
  // int delayTime = 100; // Time (milliseconds) to pause between LEDs
  // // Make this smaller for faster switching

  // // step through the LEDs, from 0 to 7

  // for (index = 0; index <= 7; index++)
  // {
  //   shiftWrite(index, HIGH);    // turn LED on
  //   delay(delayTime);       // pause to slow down the sequence
  //   shiftWrite(index, LOW); // turn LED off
  // }
}

void pingPong()
{
  // // This function turns on the LEDs, one at a time, in both directions.
  // int index;
  // int delayTime = 100; // time (milliseconds) to pause between LEDs
  // // make this smaller for faster switching

  // // step through the LEDs, from 0 to 7

  // for (index = 0; index <= 7; index++)
  // {
  //   shiftWrite(index, HIGH);    // turn LED on
  //   delay(delayTime);       // pause to slow down the sequence
  //   shiftWrite(index, LOW); // turn LED off
  // }

  // // step through the LEDs, from 7 to 0

  // for (index = 7; index >= 0; index--)
  // {
  //   shiftWrite(index, HIGH);    // turn LED on
  //   delay(delayTime);       // pause to slow down the sequence
  //   shiftWrite(index, LOW); // turn LED off
  // }
}

void randomLED()
{
  // // This function will randomly turn on and off LEDs.
  // int index;
  // int delayTime = 100; // time (milliseconds) to pause between LEDs
  // // make this smaller for faster switching

  // index = random(8);    // pick a random number between 0 and 7

  // shiftWrite(index, HIGH);  // turn LED on
  // delay(delayTime);     // pause to slow down the sequence
  // shiftWrite(index, LOW);   // turn LED off
}

void marquee()
{
  // This function will mimic "chase lights" like those around signs.
  // int index;
  // int delayTime = 200; // Time (milliseconds) to pause between LEDs
  // // Make this smaller for faster switching

  // // Step through the first four LEDs
  // // (We'll light up one in the lower 4 and one in the upper 4)

  // for (index = 0; index <= 3; index++)
  // {
  //   shiftWrite(index, HIGH);    // Turn a LED on
  //   shiftWrite(index + 4, HIGH); // Skip four, and turn that LED on
  //   delay(delayTime);       // Pause to slow down the sequence
  //   shiftWrite(index, LOW); // Turn both LEDs off
  //   shiftWrite(index + 4, LOW);
  // }
}


void binaryCount()
{
  // This function creates a visual representation of the on/off pattern
  // of bits in a byte.

  // int delayTime = 1000; // time (milliseconds) to pause between LEDs
  // // make this smaller for faster switching

  // // Send the data byte to the shift register:

  // shiftOut(datapin, clockpin, MSBFIRST, data);

  // // Toggle the latch pin to make the data appear at the outputs:

  // digitalWrite(latchpin, HIGH);
  // digitalWrite(latchpin, LOW);

  // // Add one to data, and repeat!
  // // (Because a byte type can only store numbers from 0 to 255,
  // // if we add more than that, it will "roll around" back to 0
  // // and start over).

  // data++;

  // // Delay so you can see what's going on:

  // delay(delayTime);
}
74HC595
74HC165