Trying to understand bitbanging, shiftIn(), reading EEPROM Alright, so I have an Atmel 93C66, http://www.atmel.com/Images/doc0172Z.pdf Datasheet and I'm wanting to read whatever is in it.

I copied the following code from this thread http://forum.arduino.cc/index.php?topic=96411.0 and made some changes to it, mainly I deleted the part where it writes:

//difining pins for eeprom   
int CLOCK =4;          
int DATA_OUT =3;
int DATA_IN = 2;
int CHIP_SEL =5;

int low =0;     //low address 

byte READ  = 0b1100;                //read instruction 

void setup(){

  pinMode(CLOCK ,OUTPUT);
  pinMode(DATA_OUT ,OUTPUT);
  pinMode(DATA_IN ,INPUT);
  pinMode(CHIP_SEL ,OUTPUT);
  digitalWrite(CHIP_SEL ,LOW);
  digitalWrite(CLOCK, LOW);
  Serial.begin(9600); 
}

void loop()
{

  for (int i=0;i&lt;=511;i++)
  { 
    digitalWrite(CHIP_SEL ,HIGH);
    shiftOut(DATA_OUT,CLOCK,MSBFIRST,READ); //sending READ instruction 
    shiftOut(DATA_OUT,CLOCK,MSBFIRST,low);   //sending low address
    byte incoming = shiftIn(DATA_IN,CLOCK,MSBFIRST); //receiving data
    digitalWrite(CHIP_SEL ,LOW);

    Serial.print(low);
    Serial.print("/t");
    Serial.print(incoming, BIN);
    Serial.print("/t");
    Serial.print(incoming, HEX);
    Serial.println():

    low++;       //incrementing low address

  } 
  while(1);
}


What I'm trying to understand is:

In the 93C66 datasheet page 5, table 6, it says that to read the contents of memory I need to send SB 1, OPCODE 10, and memory address, which I don't know exactly how to do, but I guess the chip wants a 110 (or a HIGH, HIGH, LOW signal) plus memory address (variable “low”=0). The SB and OP CODE are similar to the BYTE variable READ in the code above, but this variable has an extra 0 (1100). I tested the code with 110 and I get different incoming data. I also thought if BYTE is 8 bits then why not make the BYTE variable READ 11000000, but it changes the incoming data. So now I don't really know how exactly to send SB 1 and OP CODE 10. Need help with that.

Also, as you can see I'm printing the variable "low" and the variable "incoming" (in Binary and Hex) on one line, I thought it would be printing 1 bit per line, but it prints varying amounts of bits. Sometimes it would print 4 bits, 6 bits, or 8 bits, as in 1110, 11111111, 111100. I thought the line byte incoming = shiftIn(DATA_IN,CLOCK,MSBFIRST);
would get filled with 8 bits all the time, so when I Serial.print() it would have 8 bits, but it's not happening, why? 

Also I thought the shifting in of the bits into the variable "incoming" occurs once in the for loop, or is there an inner loop in shiftIn()? I ask because I first made the for loop go for i=&lt;4095, since there are 4096 bits in this EEPROM, but the increment of I doesn’t match the amount of bits I’m getting on each Serial.print() line. 
i.e. I would get something like this:

1   10111111    BF 


I thought it would be getting something like this. (I’m thinking the shiftIn() of the 1st bit at address 0 happens when i=0, then 2nd bits gets shiftIn() when i=1, and so forth)

1   1   
2   1   
3   0
4   1
Etc, etc


How is shiftIn() shiftinf in the bits into the BYTE variable?

Thanks and sorry if it’s so many questions.
OK I know this is a little late, but for other readers having the same problem, here's a sketch I wrote to read a 93c46 when I had to dump the EEPROM from a car radio. I've deliberately not included the EWEN instruction anywhere as the last thing I wanted to do was accidentally write to the EEPROM.

The key is the modified shiftOut routine which adds a parameter specifying how many bits you want to shift out.

To adapt sketch for other 93c packages, change the number of 16bit words at start of loop{} and number of address bits in 2nd call to myshiftOut.

If your package has an ORG pin, tie it to Vcc.

Hope this helps someone...

/*
Arduino Uno sketch to dump a 93c46 EEPROM in 16 bit mode.  Metalbanana 12/9/16, with thanks to raint.
Easily modified for other 93c series parts. Note many 93c46 from autos are 'rotated' pinout,
i.e. those with a T following part no. e.g. 'TEM8':

1=NC    8=ORG
2=Vcc   7=GND
3=CS    6=DO
4=SK    5=DI

so check pcb for Vcc and GND locations with a meter first! An Arduino ProtoShield is ideal to mount IC
as it has a SOIC pad (Note: you can't use the mini breadboard at same time as it covers one set of headers).
Standard shiftOut is not suitable as it sends 8 bits, our addresses are 6 bits,
instructions are 3 bits so sketch uses a modified shiftOut called myshiftOut.
*/



// define pins for eeprom
const int CHIP_SEL = 8;  // to CS
const int CLOCK = 9;     // to SK
const int DATA_IN = 10;  // to DO
const int DATA_OUT = 11; // to DI

const byte READ  = B110;                //read instruction

bool debug = 0;


void myshiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val, uint8_t bits)
{
  for (int i = 0; i &lt; bits; i++)  {
    if (bitOrder == LSBFIRST) {
      digitalWrite(dataPin, !!(val &amp; (1 &lt;&lt; i)));
      if (debug)Serial.print(!!(val &amp; (1 &lt;&lt; i)));
    }
    else
    {
      digitalWrite(dataPin, !!(val &amp; (1 &lt;&lt; (bits - 1 - i))));
      if (debug)Serial.print(!!(val &amp; (1 &lt;&lt; (bits - 1 - i))));
    }
    digitalWrite(clockPin, HIGH);
    digitalWrite(clockPin, LOW);
  }
}


void setup() {
  pinMode(CHIP_SEL, OUTPUT);
  pinMode(CLOCK, OUTPUT);
  pinMode(DATA_OUT, OUTPUT);
  pinMode(DATA_IN, INPUT_PULLUP);

  Serial.begin(9600);
  Serial.println("\n\n");
}



void loop()
{
  for (int addr = 0; addr &lt; 64; addr++) // 64 words for 93c46
  {
    // print address at start of each line
    if (addr % 8 == 0) {
      Serial.println();
      if (addr &lt; 8) Serial.print("0");
      Serial.print(addr * 2, HEX);
      Serial.print(": ");
    }

    digitalWrite(CHIP_SEL, HIGH);
    myshiftOut(DATA_OUT, CLOCK, MSBFIRST, READ, 3); //send READ instruction
    myshiftOut(DATA_OUT, CLOCK, MSBFIRST, addr, 6); //send address, 6 bits for 93c46


    digitalWrite(CLOCK, LOW); // recommended in language reference
    byte incomingH = shiftIn(DATA_IN, CLOCK, MSBFIRST); //receive high byte
    byte incomingL = shiftIn(DATA_IN, CLOCK, MSBFIRST); //receive low byte

    // reverse byte order &amp; print
    if (incomingL &lt; 16) Serial.print("0");
    Serial.print(incomingL, HEX);
    Serial.print(" ");
    if (incomingH &lt; 16) Serial.print("0");
    Serial.print(incomingH, HEX);
    Serial.print(" ");

    digitalWrite(CHIP_SEL, LOW);
  }

  while (1);
}