Here's the code. The 3 wire SPI seems to be (unless I misunderstood) the CS pulled low, and then a clock and IO pin. I've set these on 2 and 3. The CS pin, I just set on 4.
#define SCLK 3
#define SDIO 2
#define PRODUCT_ID 0x00
#define DELTA_Y_REG 0x03
#define DELTA_X_REG 0x04
#define SQUAL_REG 0x05
#define MAXIMUM_PIXEL_REG 0x08
#define MINIMUM_PIXEL_REG 0x0a
#define PIXEL_SUM_REG 0x09
#define PIXEL_DATA_REG 0x0b
#define SHUTTER_UPPER_REG 0x06
#define SHUTTER_LOWER_REG 0x07
#define RESET 0x3a
#define CPI500v 0x00
#define CPI1000v 0x01
const int NCS = 4;
void setup()
{
Serial.begin(57600);
pinMode(NCS, OUTPUT);
digitalWrite(NCS, LOW);
pinMode(SDIO, OUTPUT);
pinMode(SCLK, OUTPUT);
delay(50); //from PD inactive (when NRESET pin is asserted high or write 0x5a to register 0x3a) to valid motion
sync(); //
//call reset
writeReg(RESET, 0x5a);
delay(50); // From NRESET pull high to valid mo tion, assuming VDD and motion is present.
}
void loop()
{
delay(100);
Serial.print(readReg(PRODUCT_ID), DEC); // this should return 0x12 :/
}
//Essentially resets communication to the ADNS5050
void sync()
{
digitalWrite(SCLK, HIGH);
delay(1);
digitalWrite(SCLK, LOW);
delay(1);
digitalWrite(SCLK, HIGH);
delay(100);
}
//Reads a register from the ADNS5050 sensor. Returns the result to the calling function.
char readReg(char address)
{
char value=0;
pinMode(SDIO, OUTPUT); //Make sure the SDIO pin is set as an output.
digitalWrite(SCLK, HIGH); //Make sure the clock is high.
address &= 0x7F; //Make sure the highest bit of the address byte is '0' to indicate a read.
//Send the Address to the ADNS5050
for(int address_bit=7; address_bit >=0; address_bit--){
digitalWrite(SCLK, LOW); //Lower the clock
pinMode(SDIO, OUTPUT); //Make sure the SDIO pin is set as an output.
//If the current bit is a 1, set the SDIO pin. If not, clear the SDIO pin
if(address & (1<<address_bit)){
digitalWrite(SDIO, HIGH);
}
else{
digitalWrite(SDIO, LOW);
}
delayMicroseconds(10);
digitalWrite(SCLK, HIGH);
delayMicroseconds(10);
}
delayMicroseconds(120); //Allow extra time for ADNS5050 to transition the SDIO pin (per datasheet)
//Make SDIO an input on the microcontroller
pinMode(SDIO, INPUT); //Make sure the SDIO pin is set as an input.
digitalWrite(SDIO, HIGH); //Enable the internal pull-up
//Send value byte
for(int value_bit=7; value_bit >= 0; value_bit--){
digitalWrite(SCLK, LOW); //Lower the clock
delayMicroseconds(10); //Allow the ADNS5050 to configure the SDIO pin
digitalWrite(SCLK, HIGH); //Raise the clock
delayMicroseconds(10);
//If the SDIO pin is high, set the current bit in the 'value' variable. If low, leave the value bit default (0).
//if((ADNS_PIN & (1<<ADNSSDIO)) == (1<<ADNSSDIO))value|=(1<<value_bit);
if(digitalRead(SDIO))value |= (1<<value_bit);
}
return value;
}
//Writes a value to a register on the ADNS5050.
void writeReg(char address, char value)
{
pinMode(SDIO, OUTPUT); //Make sure the SDIO pin is set as an output.
digitalWrite(SCLK, HIGH); //Make sure the clock is high.
address |= 0x80; //the highest bit is '1' to indicate a write.
//Send Address
for(int address_bit=7; address_bit >=0; address_bit--){
digitalWrite(SCLK, LOW); //Lower the clock
delayMicroseconds(10); //small delay
//If the current bit is a 1, set the SDIO pin. If not, clear the SDIO pin
if(address & (1<<address_bit))digitalWrite(SDIO, HIGH);
else digitalWrite(SDIO, LOW);
delayMicroseconds(10);
digitalWrite(SCLK, HIGH);
delayMicroseconds(10);
}
//Send the Value byte to the ADNS5050
for(int value_bit=7; value_bit >= 0; value_bit--){
digitalWrite(SCLK, LOW); //Lower the clock
//If the current bit is a 1, set the SDIO pin. If not, clear the SDIO pin
if(value & (1<<value_bit))digitalWrite(SDIO, HIGH);
else digitalWrite(SDIO, LOW);
delayMicroseconds(10);
digitalWrite(SCLK, HIGH);
delayMicroseconds(10);
}
}