せとうちオープン用のメインプログラム
Dependencies: mbed AQM1602 HMC6352 PID
lib/adns_9800/adns_9800.cpp
- Committer:
- lilac0112_1
- Date:
- 2016-05-01
- Revision:
- 0:b910276f9da2
File content as of revision 0:b910276f9da2:
/** * @author Alexander Entinger, MSc / LXRobotics * @brief this class acts as interface for accessing the adns-9800 sensor - based on https://github.com/mrjohnk/ADNS-9800 * @file adns_9800.cpp */ #include "adns_9800.h" #include "adns_9800_regs.h" #include "adns_9800_srom_a4.h" /** * @brief Constructor */ adns_9800::adns_9800(PinName mosi, PinName miso, PinName sclk, PinName ncs) : m_spi(mosi, miso, sclk), m_ncs_pin(ncs) { m_spi.format(8, 3); // 8 bits with mode 3 =>Polarity = 1, Phase = 1 m_spi.frequency(1000000); // 1 MHz startup(); } /** * @brief Destructor */ adns_9800::~adns_9800() { } /** * @brief returns true if a motion has occured since the last readout */ bool adns_9800::new_motion_data_available() { uint8_t const motion_reg = read_reg(REG_Motion); bool const new_data_available = (motion_reg & 0x80) > 0; return new_data_available; } /** * @brief retrieves the latest delta values */ void adns_9800::get_delta_x_y(int16_t &delta_x, int16_t &delta_y) { uint16_t delta_x_l = (uint16_t)(read_reg(REG_Delta_X_L)); uint16_t delta_x_h = (uint16_t)(read_reg(REG_Delta_X_H)) << 8; delta_x = (int16_t)(delta_x_h | delta_x_l); uint16_t delta_y_l = (uint16_t)(read_reg(REG_Delta_Y_L)); uint16_t delta_y_h = (uint16_t)(read_reg(REG_Delta_Y_H)) << 8; delta_y = (int16_t)(delta_y_h | delta_y_l); } /** * @brief start and stop communication with the sensor by clearing/setting the ncs pin */ void adns_9800::com_begin() { m_ncs_pin = 0; } void adns_9800::com_end() { m_ncs_pin = 1; } /** * @brief provide read/write access to a adns register */ uint8_t adns_9800::read_reg(uint8_t const address) { com_begin(); // send adress of the register, with MSBit = 0 to indicate it's a read m_spi.write(address & 0x7f ); wait_us(100); // tSRAD // read data uint8_t data = m_spi.write(0); wait_us(1); // tSCLK-NCS for read operation is 120ns com_end(); wait_us(19); // tSRW/tSRR (=20us) minus tSCLK-NCS return data; } void adns_9800::write_reg(uint8_t const address, uint8_t const data) { com_begin(); //send adress of the register, with MSBit = 1 to indicate it's a write m_spi.write(address | 0x80 ); //sent data m_spi.write(data); wait_us(20); // tSCLK-NCS for write operation com_end(); wait_us(100); // tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound } /** * @brief upload the firmware */ void adns_9800::upload_firmware() { // set the configuration_IV register in 3k firmware mode write_reg(REG_Configuration_IV, 0x02); // bit 1 = 1 for 3k mode, other bits are reserved // write 0x1d in SROM_enable reg for initializing write_reg(REG_SROM_Enable, 0x1d); // wait for more than one frame period wait_ms(10); // assume that the frame rate is as low as 100fps... even if it should never be that low // write 0x18 to SROM_enable to start SROM download write_reg(REG_SROM_Enable, 0x18); // write the SROM file (=firmware data) com_begin(); m_spi.write(REG_SROM_Load_Burst | 0x80); // write burst destination adress wait_us(15); // send all bytes of the firmware for(int i = 0; i < firmware_length; i++) { m_spi.write(firmware_data[i]); wait_us(15); } com_end(); } /** * @brief starts the sensor up */ void adns_9800::startup() { com_end(); // ensure that the serial port is reset com_begin(); // ensure that the serial port is reset com_end(); // ensure that the serial port is reset write_reg(REG_Power_Up_Reset, 0x5a); // force reset wait_ms(50); // wait for it to reboot // read registers 0x02 to 0x06 (and discard the data) read_reg(REG_Motion); read_reg(REG_Delta_X_L); read_reg(REG_Delta_X_H); read_reg(REG_Delta_Y_L); read_reg(REG_Delta_Y_H); // upload the firmware upload_firmware(); wait_ms(10); //enable laser(bit 0 = 0b), in normal mode (bits 3,2,1 = 000b) // reading the actual value of the register is important because the real // default value is different from what is said in the datasheet, and if you // change the reserved bytes (like by writing 0x00...) it would not work. uint8_t laser_ctrl0 = read_reg(REG_LASER_CTRL0); write_reg(REG_LASER_CTRL0, laser_ctrl0 & 0xf0 ); wait_ms(1); }