|
|
|
@ -29,6 +29,8 @@
@@ -29,6 +29,8 @@
|
|
|
|
|
#include "AP_OpticalFlow_Pixart_SROM.h" |
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
|
#define debug(fmt, args ...) do {printf(fmt, ## args); } while(0) |
|
|
|
|
|
|
|
|
|
extern const AP_HAL::HAL& hal; |
|
|
|
|
|
|
|
|
|
#define PIXART_REG_PRODUCT_ID 0x00 |
|
|
|
@ -62,7 +64,9 @@ extern const AP_HAL::HAL& hal;
@@ -62,7 +64,9 @@ extern const AP_HAL::HAL& hal;
|
|
|
|
|
#define PIXART_REG_POWER_RST 0x3A |
|
|
|
|
#define PIXART_REG_SHUTDOWN 0x3B |
|
|
|
|
#define PIXART_REG_INV_PROD_ID 0x3F |
|
|
|
|
#define PIXART_REG_INV_PROD_ID2 0x5F // for 3901
|
|
|
|
|
#define PIXART_REG_MOT_BURST 0x50 |
|
|
|
|
#define PIXART_REG_MOT_BURST2 0x16 |
|
|
|
|
#define PIXART_REG_SROM_BURST 0x62 |
|
|
|
|
#define PIXART_REG_RAW_BURST 0x64 |
|
|
|
|
|
|
|
|
@ -70,7 +74,7 @@ extern const AP_HAL::HAL& hal;
@@ -70,7 +74,7 @@ extern const AP_HAL::HAL& hal;
|
|
|
|
|
#define PIXART_WRITE_FLAG 0x80 |
|
|
|
|
|
|
|
|
|
// timings in microseconds
|
|
|
|
|
#define PIXART_Tsrad 150 |
|
|
|
|
#define PIXART_Tsrad 300 |
|
|
|
|
|
|
|
|
|
// correct result for SROM CRC
|
|
|
|
|
#define PIXART_SROM_CRC_RESULT 0xBEEF |
|
|
|
@ -112,16 +116,29 @@ bool AP_OpticalFlow_Pixart::setup_sensor(void)
@@ -112,16 +116,29 @@ bool AP_OpticalFlow_Pixart::setup_sensor(void)
|
|
|
|
|
hal.scheduler->delay(50); |
|
|
|
|
|
|
|
|
|
// check product ID
|
|
|
|
|
if (reg_read(PIXART_REG_PRODUCT_ID) != 0x3F || |
|
|
|
|
reg_read(PIXART_REG_INV_PROD_ID) != 0xC0) { |
|
|
|
|
uint8_t id1 = reg_read(PIXART_REG_PRODUCT_ID); |
|
|
|
|
uint8_t id2; |
|
|
|
|
if (id1 == 0x3f) { |
|
|
|
|
id2 = reg_read(PIXART_REG_INV_PROD_ID); |
|
|
|
|
} else { |
|
|
|
|
id2 = reg_read(PIXART_REG_INV_PROD_ID2); |
|
|
|
|
} |
|
|
|
|
debug("id1=0x%02x id2=0x%02x ~id1=0x%02x\n", id1, id2, uint8_t(~id1)); |
|
|
|
|
if (id1 == 0x3F && id2 == uint8_t(~id1)) { |
|
|
|
|
model = PIXART_3900; |
|
|
|
|
} else if (id1 == 0x49 && id2 == uint8_t(~id1)) { |
|
|
|
|
model = PIXART_3901; |
|
|
|
|
} else { |
|
|
|
|
debug("Not a recognised device\n"); |
|
|
|
|
goto failed; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (model == PIXART_3900) { |
|
|
|
|
srom_download(); |
|
|
|
|
|
|
|
|
|
id = reg_read(PIXART_REG_SROM_ID); |
|
|
|
|
if (id != srom_id) { |
|
|
|
|
printf("Pixart: bad SROM ID: 0x%02x\n", id); |
|
|
|
|
debug("Pixart: bad SROM ID: 0x%02x\n", id); |
|
|
|
|
goto failed; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -130,21 +147,22 @@ bool AP_OpticalFlow_Pixart::setup_sensor(void)
@@ -130,21 +147,22 @@ bool AP_OpticalFlow_Pixart::setup_sensor(void)
|
|
|
|
|
|
|
|
|
|
crc = reg_read16u(PIXART_REG_DOUT_L); |
|
|
|
|
if (crc != 0xBEEF) { |
|
|
|
|
printf("Pixart: bad SROM CRC: 0x%04x\n", crc); |
|
|
|
|
debug("Pixart: bad SROM CRC: 0x%04x\n", crc); |
|
|
|
|
goto failed; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
load_configuration(); |
|
|
|
|
if (model == PIXART_3900) { |
|
|
|
|
load_configuration(init_data_3900, ARRAY_SIZE(init_data_3900)); |
|
|
|
|
} else { |
|
|
|
|
load_configuration(init_data_3901_1, ARRAY_SIZE(init_data_3901_1)); |
|
|
|
|
hal.scheduler->delay(100); |
|
|
|
|
load_configuration(init_data_3901_2, ARRAY_SIZE(init_data_3901_2)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
hal.scheduler->delay(50); |
|
|
|
|
|
|
|
|
|
printf("Pixart ready: prod:0x%02x rev:0x%02x iprod:0x%02x shi:0x%02x cfg1:0x%02x cfg2:0x%02x\n", |
|
|
|
|
(unsigned)reg_read(PIXART_REG_PRODUCT_ID), |
|
|
|
|
(unsigned)reg_read(PIXART_REG_REVISION_ID), |
|
|
|
|
(unsigned)reg_read(PIXART_REG_INV_PROD_ID), |
|
|
|
|
(unsigned)reg_read(PIXART_REG_SHUTTER_HI), |
|
|
|
|
(unsigned)reg_read(PIXART_REG_CONFIG1), |
|
|
|
|
(unsigned)reg_read(PIXART_REG_CONFIG2)); |
|
|
|
|
debug("Pixart %s ready\n", model==PIXART_3900?"3900":"3901"); |
|
|
|
|
|
|
|
|
|
_dev->get_semaphore()->give(); |
|
|
|
|
|
|
|
|
@ -177,10 +195,10 @@ uint8_t AP_OpticalFlow_Pixart::reg_read(uint8_t reg)
@@ -177,10 +195,10 @@ uint8_t AP_OpticalFlow_Pixart::reg_read(uint8_t reg)
|
|
|
|
|
uint8_t v = 0; |
|
|
|
|
_dev->set_chip_select(true); |
|
|
|
|
_dev->transfer(®, 1, nullptr, 0); |
|
|
|
|
hal.scheduler->delay_microseconds(PIXART_Tsrad); |
|
|
|
|
hal.scheduler->delay_microseconds(35); |
|
|
|
|
_dev->transfer(nullptr, 0, &v, 1); |
|
|
|
|
_dev->set_chip_select(false); |
|
|
|
|
hal.scheduler->delay_microseconds(120); |
|
|
|
|
hal.scheduler->delay_microseconds(200); |
|
|
|
|
return v; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -208,7 +226,7 @@ void AP_OpticalFlow_Pixart::srom_download(void)
@@ -208,7 +226,7 @@ void AP_OpticalFlow_Pixart::srom_download(void)
|
|
|
|
|
reg_write(PIXART_REG_SROM_EN, 0x18); |
|
|
|
|
|
|
|
|
|
if (!_dev->set_chip_select(true)) { |
|
|
|
|
printf("Failed to force CS\n"); |
|
|
|
|
debug("Failed to force CS\n"); |
|
|
|
|
} |
|
|
|
|
hal.scheduler->delay_microseconds(1); |
|
|
|
|
uint8_t reg = PIXART_REG_SROM_BURST | PIXART_WRITE_FLAG; |
|
|
|
@ -221,14 +239,14 @@ void AP_OpticalFlow_Pixart::srom_download(void)
@@ -221,14 +239,14 @@ void AP_OpticalFlow_Pixart::srom_download(void)
|
|
|
|
|
|
|
|
|
|
hal.scheduler->delay_microseconds(125); |
|
|
|
|
if (!_dev->set_chip_select(false)) { |
|
|
|
|
printf("Failed to force CS off\n"); |
|
|
|
|
debug("Failed to force CS off\n"); |
|
|
|
|
} |
|
|
|
|
hal.scheduler->delay_microseconds(160); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AP_OpticalFlow_Pixart::load_configuration(void) |
|
|
|
|
void AP_OpticalFlow_Pixart::load_configuration(const RegData *init_data, uint16_t n) |
|
|
|
|
{ |
|
|
|
|
for (uint16_t i = 0; i < ARRAY_SIZE(init_data); i++) { |
|
|
|
|
for (uint16_t i = 0; i < n; i++) { |
|
|
|
|
// writing a config register can fail - retry up to 5 times
|
|
|
|
|
for (uint8_t tries=0; tries<5; tries++) { |
|
|
|
|
reg_write(init_data[i].reg, init_data[i].value); |
|
|
|
@ -236,7 +254,7 @@ void AP_OpticalFlow_Pixart::load_configuration(void)
@@ -236,7 +254,7 @@ void AP_OpticalFlow_Pixart::load_configuration(void)
|
|
|
|
|
if (v == init_data[i].value) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
//printf("reg[%u:%02x] 0x%02x 0x%02x\n", (unsigned)i, (unsigned)init_data[i].reg, (unsigned)init_data[i].value, (unsigned)v);
|
|
|
|
|
//debug("reg[%u:%02x] 0x%02x 0x%02x\n", (unsigned)i, (unsigned)init_data[i].reg, (unsigned)init_data[i].value, (unsigned)v);
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -250,7 +268,7 @@ void AP_OpticalFlow_Pixart::motion_burst(void)
@@ -250,7 +268,7 @@ void AP_OpticalFlow_Pixart::motion_burst(void)
|
|
|
|
|
burst.delta_y = 0; |
|
|
|
|
|
|
|
|
|
_dev->set_chip_select(true); |
|
|
|
|
uint8_t reg = PIXART_REG_MOT_BURST; |
|
|
|
|
uint8_t reg = model==PIXART_3900?PIXART_REG_MOT_BURST:PIXART_REG_MOT_BURST2; |
|
|
|
|
|
|
|
|
|
_dev->transfer(®, 1, nullptr, 0); |
|
|
|
|
hal.scheduler->delay_microseconds(150); |
|
|
|
@ -288,6 +306,10 @@ void AP_OpticalFlow_Pixart::timer(void)
@@ -288,6 +306,10 @@ void AP_OpticalFlow_Pixart::timer(void)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
static int fd = -1; |
|
|
|
|
if (fd == -1) { |
|
|
|
|
fd = open("/dev/ttyACM0", O_WRONLY); |
|
|
|
|
} |
|
|
|
|
// used for debugging
|
|
|
|
|
sum_x += burst.delta_x; |
|
|
|
|
sum_y += burst.delta_y; |
|
|
|
@ -295,7 +317,7 @@ void AP_OpticalFlow_Pixart::timer(void)
@@ -295,7 +317,7 @@ void AP_OpticalFlow_Pixart::timer(void)
|
|
|
|
|
uint32_t now = AP_HAL::millis(); |
|
|
|
|
if (now - last_print_ms >= 100 && (sum_x != 0 || sum_y != 0)) { |
|
|
|
|
last_print_ms = now; |
|
|
|
|
printf("Motion: %d %d obs:0x%02x squal:%u rds:%u maxr:%u minr:%u sup:%u slow:%u\n", |
|
|
|
|
dprintf(fd, "Motion: %d %d obs:0x%02x squal:%u rds:%u maxr:%u minr:%u sup:%u slow:%u\n", |
|
|
|
|
(int)sum_x, (int)sum_y, (unsigned)burst.squal, (unsigned)burst.rawdata_sum, (unsigned)burst.max_raw, |
|
|
|
|
(unsigned)burst.max_raw, (unsigned)burst.min_raw, (unsigned)burst.shutter_upper, (unsigned)burst.shutter_lower); |
|
|
|
|
sum_x = sum_y = 0; |
|
|
|
|