ジャパンオープン用のメインプログラム

Dependencies:   mbed AQM1602 HMC6352 PID

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers adns_9800.cpp Source File

adns_9800.cpp

Go to the documentation of this file.
00001 /**
00002  * @author Alexander Entinger, MSc / LXRobotics
00003  * @brief this class acts as interface for accessing the adns-9800 sensor - based on https://github.com/mrjohnk/ADNS-9800
00004  * @file adns_9800.cpp
00005  */
00006  
00007 #include "adns_9800.h"
00008 #include "adns_9800_regs.h"
00009 #include "adns_9800_srom_a4.h"
00010  
00011 /**
00012  * @brief Constructor
00013  */
00014 adns_9800::adns_9800(PinName mosi, PinName miso, PinName sclk, PinName ncs) : m_spi(mosi, miso, sclk), m_ncs_pin(ncs)
00015 {
00016     m_spi.format(8, 3); // 8 bits with mode 3 =>Polarity = 1, Phase = 1
00017     m_spi.frequency(1000000); // 1 MHz
00018     
00019     startup();
00020 }
00021     
00022 /**
00023  * @brief Destructor
00024  */
00025 adns_9800::~adns_9800()
00026 {
00027     
00028 }
00029 
00030 /**
00031  * @brief returns true if a motion has occured since the last readout
00032  */
00033 bool adns_9800::new_motion_data_available()
00034 {
00035     uint8_t const motion_reg = read_reg(REG_Motion);
00036     bool const new_data_available = (motion_reg & 0x80) > 0;
00037     return new_data_available;
00038 }
00039     
00040 /**
00041  * @brief retrieves the latest delta values
00042  */
00043 void adns_9800::get_delta_x_y(int16_t &delta_x, int16_t &delta_y)
00044 {
00045     uint16_t delta_x_l = (uint16_t)(read_reg(REG_Delta_X_L));
00046     uint16_t delta_x_h = (uint16_t)(read_reg(REG_Delta_X_H)) << 8;
00047     delta_x = (int16_t)(delta_x_h | delta_x_l);
00048     
00049     uint16_t delta_y_l = (uint16_t)(read_reg(REG_Delta_Y_L));
00050     uint16_t delta_y_h = (uint16_t)(read_reg(REG_Delta_Y_H)) << 8;
00051     delta_y = (int16_t)(delta_y_h | delta_y_l);
00052 }
00053 
00054 /**
00055  * @brief start and stop communication with the sensor by clearing/setting the ncs pin
00056  */
00057 void adns_9800::com_begin()
00058 {
00059     m_ncs_pin = 0;
00060 }
00061 void adns_9800::com_end()
00062 {
00063     m_ncs_pin = 1;
00064 }
00065 
00066 /**
00067  * @brief provide read/write access to a adns register
00068  */
00069 uint8_t adns_9800::read_reg(uint8_t const address)
00070 {
00071   com_begin();
00072   
00073   // send adress of the register, with MSBit = 0 to indicate it's a read
00074   m_spi.write(address & 0x7f );
00075   wait_us(100); // tSRAD
00076   // read data
00077   uint8_t data = m_spi.write(0);
00078   
00079   wait_us(1); // tSCLK-NCS for read operation is 120ns
00080   com_end();
00081   wait_us(19); //  tSRW/tSRR (=20us) minus tSCLK-NCS
00082 
00083   return data; 
00084 }
00085 void adns_9800::write_reg(uint8_t const address, uint8_t const data)
00086 {
00087   com_begin();
00088   
00089   //send adress of the register, with MSBit = 1 to indicate it's a write
00090   m_spi.write(address | 0x80 );
00091   //sent data
00092   m_spi.write(data);
00093   
00094   wait_us(20); // tSCLK-NCS for write operation
00095   com_end();
00096   wait_us(100); // tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound 
00097 }
00098 
00099 /**
00100  * @brief upload the firmware
00101  */
00102 void adns_9800::upload_firmware()
00103 {
00104   // set the configuration_IV register in 3k firmware mode
00105   write_reg(REG_Configuration_IV, 0x02); // bit 1 = 1 for 3k mode, other bits are reserved 
00106   
00107   // write 0x1d in SROM_enable reg for initializing
00108   write_reg(REG_SROM_Enable, 0x1d); 
00109   
00110   // wait for more than one frame period
00111   wait_ms(10); // assume that the frame rate is as low as 100fps... even if it should never be that low
00112   
00113   // write 0x18 to SROM_enable to start SROM download
00114   write_reg(REG_SROM_Enable, 0x18); 
00115   
00116   // write the SROM file (=firmware data) 
00117   com_begin();
00118   m_spi.write(REG_SROM_Load_Burst | 0x80); // write burst destination adress
00119   wait_us(15);
00120   
00121   // send all bytes of the firmware
00122   for(int i = 0; i < firmware_length; i++)
00123   { 
00124     m_spi.write(firmware_data[i]);
00125     wait_us(15);
00126   }
00127   
00128   com_end(); 
00129 }
00130 
00131 /**
00132  * @brief starts the sensor up
00133  */
00134 void adns_9800::startup()
00135 {
00136   com_end(); // ensure that the serial port is reset
00137   com_begin(); // ensure that the serial port is reset
00138   com_end(); // ensure that the serial port is reset
00139   write_reg(REG_Power_Up_Reset, 0x5a); // force reset
00140   wait_ms(50); // wait for it to reboot
00141   // read registers 0x02 to 0x06 (and discard the data)
00142   read_reg(REG_Motion);
00143   read_reg(REG_Delta_X_L);
00144   read_reg(REG_Delta_X_H);
00145   read_reg(REG_Delta_Y_L);
00146   read_reg(REG_Delta_Y_H);
00147   // upload the firmware
00148   upload_firmware();
00149   wait_ms(10);
00150   //enable laser(bit 0 = 0b), in normal mode (bits 3,2,1 = 000b)
00151   // reading the actual value of the register is important because the real
00152   // default value is different from what is said in the datasheet, and if you
00153   // change the reserved bytes (like by writing 0x00...) it would not work.
00154   uint8_t laser_ctrl0 = read_reg(REG_LASER_CTRL0);
00155   write_reg(REG_LASER_CTRL0, laser_ctrl0 & 0xf0 );
00156   
00157   wait_ms(1);
00158 }