Skip to content

Commit

Permalink
fix support for ADNS-5050 optical sensor
Browse files Browse the repository at this point in the history
  • Loading branch information
wertarbyte committed May 10, 2012
1 parent cba5bf4 commit 6431d29
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 25 deletions.
2 changes: 1 addition & 1 deletion README
Expand Up @@ -66,7 +66,7 @@ Wiring:
.--v--.
-| |- VCC
GPS <--| T |--> I²C SCL
-| i |-
-| i |--> Optical CSEL
Optical DIO <--| n |--> I²C SDA
Optical CLK <--| y |-
Sonar Trigger <--| 4 |-
Expand Down
4 changes: 2 additions & 2 deletions config.h
Expand Up @@ -12,8 +12,8 @@
#define USE_SONAR 1
/* query optical flow sensor?
*
* The optical flow sensor (A5050) must be connected to PA0 (SCK) and PA1
* (SDIO) pins.
* The optical flow sensor (A5050) must be connected to PA0 (SCK), PA1 (SDIO)
* and PB6 (CSEL/NCS) pins.
*/
#define USE_OPTICAL 1

Expand Down
68 changes: 49 additions & 19 deletions optical.c
Expand Up @@ -8,80 +8,110 @@
#include <util/delay.h>
#include "optical.h"

#if __AVR__
#include <util/atomic.h>
#define ATOMIC(t) ATOMIC_BLOCK(t)
#else
#define ATOMIC(t)
#endif

#define OPTICAL_SCLK_PORT PORTA
#define OPTICAL_SDIO_PORT PORTA
#define OPTICAL_CSEL_PORT PORTB
#define OPTICAL_SCLK_DDR DDRA
#define OPTICAL_SDIO_DDR DDRA
#define OPTICAL_CSEL_DDR DDRB
#define OPTICAL_SCLK_PIN PINA
#define OPTICAL_SDIO_PIN PINA
#define OPTICAL_CSEL_PIN PINB
#define OPTICAL_SCLK_BIT PA0
#define OPTICAL_SDIO_BIT PA1
#define OPTICAL_CSEL_BIT PB6

#define IO_DELAY 4

/* values for ADNS 5050 */
#define ID_REG 0x00
#define MOTION_REG 0x02
#define DX_REG 0x03
#define DY_REG 0x04
#define QUAL_REG 0x05
#define RESET_REG 0x3a
#define RESET_VAL 0x5a
#define CTRL1_REG 0x0d
#define CTRL2_REG 0x19

static void _spi_write(uint8_t d) {
OPTICAL_SDIO_DDR |= 1<<OPTICAL_SDIO_BIT;
for (uint8_t i=0; i<8; i++) {
OPTICAL_SCLK_PORT &= ~(1<<OPTICAL_SDIO_BIT);
for (int8_t i=7; i>=0; i--) {
OPTICAL_SCLK_PORT &= ~(1<<OPTICAL_SCLK_BIT);
_delay_us(1);
if (d & 1<<i) {
OPTICAL_SDIO_PORT |= 1<<OPTICAL_SDIO_BIT;
} else {
OPTICAL_SDIO_PORT &= ~(1<<OPTICAL_SDIO_BIT);
}
_delay_us(1);
OPTICAL_SCLK_PORT |= 1<<OPTICAL_SDIO_BIT;
OPTICAL_SCLK_PORT |= 1<<OPTICAL_SCLK_BIT;
_delay_us(1);
}
}

static uint8_t optical_read(uint8_t addr) {
OPTICAL_CSEL_PORT &= ~(1<<OPTICAL_CSEL_BIT);
_spi_write(addr);
_delay_us(IO_DELAY);
OPTICAL_SDIO_DDR &= ~(1<<OPTICAL_SDIO_BIT);
_delay_us(IO_DELAY);
uint8_t res = 0;
for (uint8_t i=0; i<8; i++) {
OPTICAL_SCLK_PORT &= ~(1<<OPTICAL_SDIO_BIT);
for (int8_t i=7; i>=0; i--) {
OPTICAL_SCLK_PORT &= ~(1<<OPTICAL_SCLK_BIT);
_delay_us(1);
OPTICAL_SCLK_PORT |= 1<<OPTICAL_SCLK_BIT;
_delay_us(1);
OPTICAL_SCLK_PORT |= 1<<OPTICAL_SDIO_BIT;
if (OPTICAL_SDIO_PIN & 1<<OPTICAL_SDIO_BIT) {
res |= 1<<i;
}
}
OPTICAL_CSEL_PORT |= (1<<OPTICAL_CSEL_BIT);
return res;
}

static void optical_write(uint8_t addr, uint8_t data) {
_spi_write(addr);
OPTICAL_CSEL_PORT &= ~(1<<OPTICAL_CSEL_BIT);
_delay_us(IO_DELAY);
_spi_write(addr | 1<<7);
_delay_us(IO_DELAY);
_spi_write(data);
_delay_us(IO_DELAY);
OPTICAL_CSEL_PORT |= 1<<OPTICAL_CSEL_BIT;
}

void optical_init(void) {
OPTICAL_SCLK_DDR |= 1<<OPTICAL_SCLK_BIT;
OPTICAL_SDIO_DDR |= 1<<OPTICAL_SDIO_BIT;
OPTICAL_SDIO_DDR &= ~(1<<OPTICAL_SDIO_BIT);
OPTICAL_CSEL_DDR |= 1<<OPTICAL_CSEL_BIT;

optical_write(RESET_REG, 0x5a);
_delay_us(50);
// toggle chip select to reset sensor
OPTICAL_CSEL_PORT |= 1<<OPTICAL_CSEL_BIT;
_delay_us(100);
OPTICAL_CSEL_PORT &= ~(1<<OPTICAL_CSEL_BIT);

// raise CLK
OPTICAL_SCLK_PORT |= 1<<OPTICAL_SDIO_BIT;
_delay_us(100);

// start motion detection and reset buffers
optical_write(MOTION_REG, 1);
optical_write(RESET_REG, RESET_VAL);
_delay_us(50);
}

void optical_query(struct optical_data_t *output) {
int8_t dx;
int8_t dy;
if (optical_read(MOTION_REG)) {
dx = optical_read(DX_REG);
dy = optical_read(DY_REG);
output->dx += dx;
output->dy += dy;
int8_t dy = optical_read(DY_REG);
int8_t dx = optical_read(DX_REG);
ATOMIC(ATOMIC_FORCEON) {
output->dx += dx;
output->dy += dy;
}
}
}
#endif
4 changes: 2 additions & 2 deletions optical_structs.h
@@ -1,4 +1,4 @@
struct optical_data_t {
int16_t dx;
int16_t dy;
int8_t dx;
int8_t dy;
};
5 changes: 4 additions & 1 deletion tiny-gps.c
Expand Up @@ -27,7 +27,7 @@ struct nav_data_t nav_data = {{0}};
#if USE_OPTICAL
static void window_trap(void) {
/* did we read the last byte of the data? then reset the counters! */
memset(&nav_data.optical, 0, sizeof(&nav_data.optical));
memset(&nav_data.optical, 0, sizeof(nav_data.optical));
}
#define TRAP_ADDR &window_trap
#else
Expand All @@ -50,6 +50,9 @@ int main(void) {
#if USE_SONAR
sonar_init();
#endif
#if USE_OPTICAL
optical_init();
#endif

usiTwiSlaveInit(TWIADDRESS);
usiTwiSetTransmitWindow( &nav_data, sizeof(nav_data) );
Expand Down

0 comments on commit 6431d29

Please sign in to comment.