Forked MMA7660 , extend implementation by using i2c asynch API, to sleep while waiting for transfer -> blocking asynch :-D
Fork of MMA7660 by
MMA7660.cpp
00001 #include "MMA7660.h" 00002 00003 MMA7660::MMA7660(PinName sda, PinName scl, bool active, bool asynch) : _i2c(sda, scl), callback_done(false), asynch(asynch) 00004 { 00005 event.attach(this, &MMA7660::callback); 00006 setActive(active); 00007 samplerate = 64; 00008 } 00009 00010 void MMA7660::callback(int event) 00011 { 00012 if (event == I2C_EVENT_TRANSFER_COMPLETE) { 00013 callback_done = true; 00014 } else { 00015 // handling errors 00016 } 00017 } 00018 00019 //Since the MMA lacks a WHO_AM_I register, we can only check if there is a device that answers to the I2C address 00020 bool MMA7660::testConnection( void ) 00021 { 00022 if (!asynch) { 00023 if (_i2c.write(MMA7660_ADDRESS, NULL, 0) == 0 ) 00024 return true; 00025 else 00026 return false; 00027 } else { 00028 callback_done = false; 00029 char received = 0; 00030 _i2c.transfer(MMA7660_ADDRESS, NULL, 0, &received, 1, event, I2C_EVENT_ALL, false); 00031 while (!callback_done) { 00032 sleep(); 00033 } 00034 return received == 0 ? true : false; 00035 } 00036 } 00037 00038 void MMA7660::setActive(bool state) 00039 { 00040 active = state; 00041 char modereg = read(MMA7660_MODE_R); 00042 modereg &= ~(1<<0); 00043 00044 //If it somehow was in testmode, disable that 00045 if (modereg && (1<<2)) { 00046 modereg &= ~(1<<2); 00047 write(MMA7660_MODE_R, modereg); 00048 } 00049 00050 modereg += state; 00051 write(MMA7660_MODE_R, modereg); 00052 } 00053 00054 void MMA7660::readData(int *data) 00055 { 00056 bool active_old = active; 00057 if (!active) { 00058 setActive(true); 00059 wait(0.012 + 1/samplerate); //Wait until new sample is ready, my experience is that 1/samplerate isnt needed, but datasheet says so 00060 } 00061 00062 char temp[3]; 00063 bool alert; 00064 00065 do { 00066 alert = false; 00067 read(MMA7660_XOUT_R, temp, 3); 00068 for (int i = 0; i<3; i++) { 00069 if (temp[i] > 63) 00070 alert = true; 00071 if (temp[i] > 31) 00072 temp[i] += 128+64; 00073 data[i] = (signed char)temp[i]; 00074 } 00075 } while (alert); 00076 00077 if (!active_old) 00078 setActive(false); 00079 } 00080 00081 00082 void MMA7660::readData(float *data) 00083 { 00084 int intdata[3]; 00085 readData(intdata); 00086 for (int i = 0; i<3; i++) 00087 data[i] = intdata[i]/MMA7660_SENSITIVITY; 00088 } 00089 00090 float MMA7660::x( void ) 00091 { 00092 return getSingle(0); 00093 } 00094 00095 float MMA7660::y( void ) 00096 { 00097 return getSingle(1); 00098 } 00099 00100 float MMA7660::z( void ) 00101 { 00102 return getSingle(2); 00103 } 00104 00105 00106 void MMA7660::setSampleRate(int samplerate) 00107 { 00108 bool active_old = active; 00109 setActive(false); //Not allowed to be active to change anything 00110 int rates[] = {120, 64, 32, 16, 8, 4, 2, 1}; //Alowed samplerates (and their number in array is also number required for MMA) 00111 int sampleLoc = 0, sampleError = 10000, temp; 00112 for (int i = 0; i<8; i++) { 00113 temp = abs( rates[i] - samplerate ); 00114 if (temp<sampleError) { 00115 sampleLoc = i; 00116 sampleError=temp; 00117 } 00118 } 00119 00120 //Update the samplerate reg 00121 temp = read(MMA7660_SR_R); 00122 temp &= ~0x07; //Awake sample rate are lowest 3 bit 00123 temp |= sampleLoc; 00124 write(MMA7660_SR_R, temp); 00125 this->samplerate = rates[sampleLoc]; 00126 setActive(active_old); //Restore previous active state 00127 } 00128 00129 00130 MMA7660::Orientation MMA7660::getSide( void ) 00131 { 00132 char tiltreg = read(MMA7660_TILT_R); 00133 //We care about 2 LSBs 00134 tiltreg &= 0x03; 00135 if (tiltreg == 0x01) 00136 return MMA7660::Front; 00137 if (tiltreg == 0x02) 00138 return MMA7660::Back; 00139 return MMA7660::Unknown; 00140 } 00141 00142 MMA7660::Orientation MMA7660::getOrientation( void ) 00143 { 00144 char tiltreg = read(MMA7660_TILT_R); 00145 00146 //We care about bit 2, 3 and 4 (counting from zero) 00147 tiltreg &= 0x07<<2; 00148 tiltreg >>= 2; 00149 if (tiltreg == 0x01) 00150 return MMA7660::Left; 00151 if (tiltreg == 0x02) 00152 return MMA7660::Right; 00153 if (tiltreg == 0x05) 00154 return MMA7660::Down; 00155 if (tiltreg == 0x06) 00156 return MMA7660::Up; 00157 return MMA7660::Unknown; 00158 } 00159 00160 00161 00162 ////////////////////////////////////////////// 00163 ///////////////PRIVATE//////////////////////// 00164 ////////////////////////////////////////////// 00165 00166 00167 void MMA7660::write(char address, char data) 00168 { 00169 char temp[2]; 00170 temp[0]=address; 00171 temp[1]=data; 00172 00173 if (!asynch) { 00174 _i2c.write(MMA7660_ADDRESS, temp, 2); 00175 } else { 00176 callback_done = false; 00177 _i2c.transfer(MMA7660_ADDRESS, &temp[0], 2, NULL, 0, event, I2C_EVENT_ALL); 00178 while (!callback_done) { 00179 sleep(); 00180 } 00181 } 00182 } 00183 00184 char MMA7660::read(char address) 00185 { 00186 if (!asynch) { 00187 char retval; 00188 00189 _i2c.write(MMA7660_ADDRESS, &address, 1, true); 00190 _i2c.read(MMA7660_ADDRESS, &retval, 1); 00191 return retval; 00192 } else { 00193 callback_done = false; 00194 char received = 0; 00195 char addr = address; 00196 _i2c.transfer(MMA7660_ADDRESS, &addr, 1, &received, 1, event, I2C_EVENT_ALL); 00197 while (!callback_done) { 00198 sleep(); 00199 } 00200 return received; 00201 } 00202 } 00203 00204 void MMA7660::read(char address, char *data, int length) 00205 { 00206 if (!asynch) { 00207 _i2c.write(MMA7660_ADDRESS, &address, 1, true); 00208 _i2c.read(MMA7660_ADDRESS, data, length); 00209 } else { 00210 callback_done = false; 00211 _i2c.transfer(MMA7660_ADDRESS, &address, 1, data, length, event, I2C_EVENT_ALL); 00212 while (!callback_done) { 00213 sleep(); 00214 } 00215 } 00216 } 00217 00218 float MMA7660::getSingle( int number ) 00219 { 00220 bool active_old = active; 00221 if (!active) { 00222 setActive(true); 00223 wait(0.012 + 1/samplerate); //Wait until new sample is ready 00224 } 00225 00226 signed char temp; 00227 bool alert; 00228 00229 do { 00230 alert = false; 00231 temp = read(MMA7660_XOUT_R + number); 00232 if (temp > 63) 00233 alert = true; 00234 if (temp > 31) 00235 temp += 128+64; 00236 } while (alert); 00237 00238 if (!active_old) 00239 setActive(false); 00240 00241 return temp / MMA7660_SENSITIVITY; 00242 }
Generated on Wed Jul 13 2022 08:47:22 by
1.7.2
