diff --git a/Firmware/config.h b/Firmware/config.h index 06d17f700..956d178a4 100644 --- a/Firmware/config.h +++ b/Firmware/config.h @@ -43,7 +43,12 @@ //#define PAT9125_I2C_ADDR 0x73 //ID=NC #define PAT9125_XRES 0 #define PAT9125_YRES 240 // maximum resolution (5*X cpi) -#define PAT9124_YRES_MM (5*PAT9125_YRES/25.4) // counts per mm +#define PAT9125_YRES_MM (5*PAT9125_YRES/25.4) // counts per mm +#define PAT9125_INVERT_X 0 //1 means flipped +#define PAT9125_INVERT_Y 1 //1 means flipped +#define PAT9125_SWAP_XY 0 //X is Y and Y is X +#define PAT9125_12B_RES 1 //8bit or 12bit signed motion data +#define PAT9125_NEW_INIT 1 //set to 1 to use the magic sequence provided by pixart. //SM4 configuration #define SM4_DEFDELAY 500 //default step delay [us] diff --git a/Firmware/pat9125.cpp b/Firmware/pat9125.cpp index 0cfce5684..2c062d521 100644 --- a/Firmware/pat9125.cpp +++ b/Firmware/pat9125.cpp @@ -46,27 +46,26 @@ uint8_t pat9125_s = 0; // Init sequence, address & value. -const PROGMEM uint8_t pat9125_init_seq1[] = { +const PROGMEM uint8_t pat9125_init_bank0[] = { // Disable write protect. PAT9125_WP, 0x5a, // Set the X resolution to zero to let the sensor know that it could safely ignore movement in the X axis. - PAT9125_RES_X, PAT9125_XRES, - // Set the Y resolution to a maximum (or nearly a maximum). - PAT9125_RES_Y, PAT9125_YRES, - // Set 12-bit X/Y data format. - PAT9125_ORIENTATION, 0x04, -// PAT9125_ORIENTATION, 0x04 | (xinv?0x08:0) | (yinv?0x10:0), //!? direction switching does not work - // Now continues the magic sequence from the PAT912EL Application Note: Firmware Guides for Tracking Optimization. - 0x5e, 0x08, - 0x20, 0x64, - 0x2b, 0x6d, - 0x32, 0x2f, - // stopper - 0x0ff + PAT9125_RES_X, PAT9125_XRES, + // Set the Y resolution to a maximum (or nearly a maximum). + PAT9125_RES_Y, PAT9125_YRES, + // Set data format and sensor orientation. + PAT9125_ORIENTATION, ((PAT9125_12B_RES?0x04:0) | (PAT9125_INVERT_X?0x08:0) | (PAT9125_INVERT_Y?0x10:0) | (PAT9125_SWAP_XY?0x20:0)), + + // Now continues the magic sequence from the PAT912EL Application Note: Firmware Guides for Tracking Optimization. + 0x5e, 0x08, + 0x20, 0x64, + 0x2b, 0x6d, + 0x32, 0x2f, + 0xff //end of sequence }; // Init sequence, address & value. -const PROGMEM uint8_t pat9125_init_seq2[] = { +const PROGMEM uint8_t pat9125_init_bank1[] = { // Magic sequence to enforce full frame rate of the sensor. 0x06, 0x028, 0x33, 0x0d0, @@ -93,14 +92,14 @@ const PROGMEM uint8_t pat9125_init_seq2[] = { 0x6e, 0x022, 0x71, 0x007, 0x72, 0x008, - // stopper - 0x0ff + 0xff //end of sequence }; -uint8_t pat9125_rd_reg(uint8_t addr); -void pat9125_wr_reg(uint8_t addr, uint8_t data); -uint8_t pat9125_wr_reg_verify(uint8_t addr, uint8_t data); +static uint8_t pat9125_rd_reg(uint8_t addr); +static void pat9125_wr_reg(uint8_t addr, uint8_t data); +static uint8_t pat9125_wr_reg_verify(uint8_t addr, uint8_t data); +static uint8_t pat9125_wr_seq(const uint8_t* seq); extern FILE _uartout; #define uartout (&_uartout) @@ -128,11 +127,14 @@ uint8_t pat9125_probe() uint8_t pat9125_init(void) { - if (!pat9125_probe()) - return 0; + if (!pat9125_probe()) + return 0; - // Verify that the sensor responds with its correct product ID. - pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1); +// Switch to bank0, not allowed to perform pat9125_wr_reg_verify on this register. + pat9125_wr_reg(PAT9125_BANK_SELECTION, 0); + + // Verify that the sensor responds with its correct product ID. + pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1); pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2); if ((pat9125_PID1 != 0x31) || (pat9125_PID2 != 0x91)) { @@ -142,54 +144,41 @@ uint8_t pat9125_init(void) return 0; } -#ifdef PAT9125_NEW_INIT - // Switch to bank0, not allowed to perform OTS_RegWriteRead. - pat9125_wr_reg(PAT9125_BANK_SELECTION, 0); +#if PAT9125_NEW_INIT // Software reset (i.e. set bit7 to 1). It will reset to 0 automatically. - // After the reset, OTS_RegWriteRead is not allowed. + // pat9125_wr_reg_verify is not allowed because the register contents will change as soon as they are written. No point in verifying those. pat9125_wr_reg(PAT9125_CONFIG, 0x97); // Wait until the sensor reboots. - // Delay 1ms. - _delay_us(1000); - { - const uint8_t *ptr = pat9125_init_seq1; - for (;;) { - const uint8_t addr = pgm_read_byte_near(ptr ++); - if (addr == 0x0ff) - break; - if (! pat9125_wr_reg_verify(addr, pgm_read_byte_near(ptr ++))) - // Verification of the register write failed. - return 0; - } - } - // Delay 10ms. - _delay_ms(10); - // Switch to bank1, not allowed to perform OTS_RegWrite. + _delay_ms(1); + + //Write init sequence in bank0. MUST ALREADY BE IN bank0. + if (!pat9125_wr_seq(pat9125_init_bank0)) + return 0; + + _delay_ms(10); // not sure why this is here. But I'll allow it. + + // Switch to bank1, not allowed to perform pat9125_wr_reg_verify on this register. pat9125_wr_reg(PAT9125_BANK_SELECTION, 0x01); - { - const uint8_t *ptr = pat9125_init_seq2; - for (;;) { - const uint8_t addr = pgm_read_byte_near(ptr ++); - if (addr == 0x0ff) - break; - if (! pat9125_wr_reg_verify(addr, pgm_read_byte_near(ptr ++))) - // Verification of the register write failed. - return 0; - } - } - // Switch to bank0, not allowed to perform OTS_RegWriteRead. + //Write init sequence in bank1. MUST ALREADY BE IN bank1. + if (!pat9125_wr_seq(pat9125_init_bank1)) + return 0; + + // Switch to bank0, not allowed to perform pat9125_wr_reg_verify on this register. pat9125_wr_reg(PAT9125_BANK_SELECTION, 0x00); + // Enable write protect. - pat9125_wr_reg(PAT9125_WP, 0x00); + pat9125_wr_reg(PAT9125_WP, 0x00); //prevents writing to registers over 0x09 pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1); pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2); -#endif //PAT9125_NEW_INIT +#else //PAT9125_NEW_INIT pat9125_wr_reg(PAT9125_RES_X, PAT9125_XRES); pat9125_wr_reg(PAT9125_RES_Y, PAT9125_YRES); - fprintf_P(uartout, PSTR("PAT9125_RES_X=%u\n"), pat9125_rd_reg(PAT9125_RES_X)); - fprintf_P(uartout, PSTR("PAT9125_RES_Y=%u\n"), pat9125_rd_reg(PAT9125_RES_Y)); + printf_P(PSTR("PAT9125_RES_X=%u\n"), pat9125_rd_reg(PAT9125_RES_X)); + printf_P(PSTR("PAT9125_RES_Y=%u\n"), pat9125_rd_reg(PAT9125_RES_Y)); +#endif //PAT9125_NEW_INIT + return 1; } @@ -251,7 +240,7 @@ uint8_t pat9125_update_bs(void) return 0; } -uint8_t pat9125_rd_reg(uint8_t addr) +static uint8_t pat9125_rd_reg(uint8_t addr) { uint8_t data = 0; #if defined(PAT9125_SWSPI) @@ -274,7 +263,7 @@ uint8_t pat9125_rd_reg(uint8_t addr) return 0; } -void pat9125_wr_reg(uint8_t addr, uint8_t data) +static void pat9125_wr_reg(uint8_t addr, uint8_t data) { #if defined(PAT9125_SWSPI) swspi_start(); @@ -296,8 +285,21 @@ void pat9125_wr_reg(uint8_t addr, uint8_t data) return; } -uint8_t pat9125_wr_reg_verify(uint8_t addr, uint8_t data) +static uint8_t pat9125_wr_reg_verify(uint8_t addr, uint8_t data) { pat9125_wr_reg(addr, data); return pat9125_rd_reg(addr) == data; } + +static uint8_t pat9125_wr_seq(const uint8_t* seq) +{ + for (;;) { + const uint8_t addr = pgm_read_byte(seq++); + if (addr == 0xff) + break; + if (!pat9125_wr_reg_verify(addr, pgm_read_byte(seq++))) + // Verification of the register write failed. + return 0; + } + return 1; +}