Forked MMA7660 , extend implementation by using i2c asynch API, to sleep while waiting for transfer -> blocking asynch :-D

Fork of MMA7660 by Erik -

Committer:
Kojto
Date:
Tue May 05 07:23:40 2015 +0000
Revision:
5:556829f081f6
Parent:
4:36a163511e34
Support I2C Asynch API

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 0:7bc29a9ea016 1 #include "MMA7660.h"
Sissors 0:7bc29a9ea016 2
Kojto 5:556829f081f6 3 MMA7660::MMA7660(PinName sda, PinName scl, bool active, bool asynch) : _i2c(sda, scl), callback_done(false), asynch(asynch)
Sissors 0:7bc29a9ea016 4 {
Kojto 5:556829f081f6 5 event.attach(this, &MMA7660::callback);
Sissors 2:a8e20db7901e 6 setActive(active);
Sissors 1:8997a1b348dd 7 samplerate = 64;
Sissors 0:7bc29a9ea016 8 }
Sissors 0:7bc29a9ea016 9
Kojto 5:556829f081f6 10 void MMA7660::callback(int event)
Kojto 5:556829f081f6 11 {
Kojto 5:556829f081f6 12 if (event == I2C_EVENT_TRANSFER_COMPLETE) {
Kojto 5:556829f081f6 13 callback_done = true;
Kojto 5:556829f081f6 14 } else {
Kojto 5:556829f081f6 15 // handling errors
Kojto 5:556829f081f6 16 }
Kojto 5:556829f081f6 17 }
Kojto 5:556829f081f6 18
Sissors 0:7bc29a9ea016 19 //Since the MMA lacks a WHO_AM_I register, we can only check if there is a device that answers to the I2C address
Sissors 0:7bc29a9ea016 20 bool MMA7660::testConnection( void )
Sissors 0:7bc29a9ea016 21 {
Kojto 5:556829f081f6 22 if (!asynch) {
Kojto 5:556829f081f6 23 if (_i2c.write(MMA7660_ADDRESS, NULL, 0) == 0 )
Kojto 5:556829f081f6 24 return true;
Kojto 5:556829f081f6 25 else
Kojto 5:556829f081f6 26 return false;
Kojto 5:556829f081f6 27 } else {
Kojto 5:556829f081f6 28 callback_done = false;
Kojto 5:556829f081f6 29 char received = 0;
Kojto 5:556829f081f6 30 _i2c.transfer(MMA7660_ADDRESS, NULL, 0, &received, 1, event, I2C_EVENT_ALL, false);
Kojto 5:556829f081f6 31 while (!callback_done) {
Kojto 5:556829f081f6 32 sleep();
Kojto 5:556829f081f6 33 }
Kojto 5:556829f081f6 34 return received == 0 ? true : false;
Kojto 5:556829f081f6 35 }
Sissors 0:7bc29a9ea016 36 }
Sissors 0:7bc29a9ea016 37
Sissors 0:7bc29a9ea016 38 void MMA7660::setActive(bool state)
Sissors 0:7bc29a9ea016 39 {
Sissors 3:89cb08cc663b 40 active = state;
Sissors 0:7bc29a9ea016 41 char modereg = read(MMA7660_MODE_R);
Sissors 0:7bc29a9ea016 42 modereg &= ~(1<<0);
Sissors 0:7bc29a9ea016 43
Sissors 0:7bc29a9ea016 44 //If it somehow was in testmode, disable that
Sissors 0:7bc29a9ea016 45 if (modereg && (1<<2)) {
Sissors 0:7bc29a9ea016 46 modereg &= ~(1<<2);
Sissors 0:7bc29a9ea016 47 write(MMA7660_MODE_R, modereg);
Sissors 0:7bc29a9ea016 48 }
Sissors 0:7bc29a9ea016 49
Sissors 0:7bc29a9ea016 50 modereg += state;
Sissors 0:7bc29a9ea016 51 write(MMA7660_MODE_R, modereg);
Sissors 0:7bc29a9ea016 52 }
Sissors 0:7bc29a9ea016 53
Sissors 0:7bc29a9ea016 54 void MMA7660::readData(int *data)
Sissors 0:7bc29a9ea016 55 {
Sissors 3:89cb08cc663b 56 bool active_old = active;
Sissors 0:7bc29a9ea016 57 if (!active) {
Sissors 0:7bc29a9ea016 58 setActive(true);
Sissors 1:8997a1b348dd 59 wait(0.012 + 1/samplerate); //Wait until new sample is ready, my experience is that 1/samplerate isnt needed, but datasheet says so
Sissors 0:7bc29a9ea016 60 }
Sissors 0:7bc29a9ea016 61
Sissors 0:7bc29a9ea016 62 char temp[3];
Sissors 0:7bc29a9ea016 63 bool alert;
Sissors 0:7bc29a9ea016 64
Sissors 0:7bc29a9ea016 65 do {
Sissors 0:7bc29a9ea016 66 alert = false;
Sissors 0:7bc29a9ea016 67 read(MMA7660_XOUT_R, temp, 3);
Sissors 0:7bc29a9ea016 68 for (int i = 0; i<3; i++) {
Sissors 0:7bc29a9ea016 69 if (temp[i] > 63)
Sissors 0:7bc29a9ea016 70 alert = true;
Sissors 0:7bc29a9ea016 71 if (temp[i] > 31)
Sissors 0:7bc29a9ea016 72 temp[i] += 128+64;
Sissors 0:7bc29a9ea016 73 data[i] = (signed char)temp[i];
Sissors 0:7bc29a9ea016 74 }
Sissors 0:7bc29a9ea016 75 } while (alert);
Sissors 2:a8e20db7901e 76
Sissors 3:89cb08cc663b 77 if (!active_old)
Sissors 2:a8e20db7901e 78 setActive(false);
Sissors 0:7bc29a9ea016 79 }
Sissors 0:7bc29a9ea016 80
Sissors 1:8997a1b348dd 81
Sissors 0:7bc29a9ea016 82 void MMA7660::readData(float *data)
Sissors 0:7bc29a9ea016 83 {
Sissors 0:7bc29a9ea016 84 int intdata[3];
Sissors 0:7bc29a9ea016 85 readData(intdata);
Sissors 0:7bc29a9ea016 86 for (int i = 0; i<3; i++)
Sissors 0:7bc29a9ea016 87 data[i] = intdata[i]/MMA7660_SENSITIVITY;
Sissors 0:7bc29a9ea016 88 }
Sissors 0:7bc29a9ea016 89
Sissors 2:a8e20db7901e 90 float MMA7660::x( void )
Sissors 1:8997a1b348dd 91 {
Sissors 0:7bc29a9ea016 92 return getSingle(0);
Sissors 1:8997a1b348dd 93 }
Sissors 1:8997a1b348dd 94
Sissors 2:a8e20db7901e 95 float MMA7660::y( void )
Sissors 1:8997a1b348dd 96 {
Sissors 1:8997a1b348dd 97 return getSingle(1);
Sissors 1:8997a1b348dd 98 }
Sissors 1:8997a1b348dd 99
Sissors 2:a8e20db7901e 100 float MMA7660::z( void )
Sissors 1:8997a1b348dd 101 {
Sissors 1:8997a1b348dd 102 return getSingle(2);
Sissors 1:8997a1b348dd 103 }
Sissors 1:8997a1b348dd 104
Sissors 1:8997a1b348dd 105
Sissors 1:8997a1b348dd 106 void MMA7660::setSampleRate(int samplerate)
Sissors 1:8997a1b348dd 107 {
Sissors 3:89cb08cc663b 108 bool active_old = active;
Sissors 1:8997a1b348dd 109 setActive(false); //Not allowed to be active to change anything
Sissors 1:8997a1b348dd 110 int rates[] = {120, 64, 32, 16, 8, 4, 2, 1}; //Alowed samplerates (and their number in array is also number required for MMA)
Sissors 1:8997a1b348dd 111 int sampleLoc = 0, sampleError = 10000, temp;
Sissors 1:8997a1b348dd 112 for (int i = 0; i<8; i++) {
Sissors 1:8997a1b348dd 113 temp = abs( rates[i] - samplerate );
Sissors 1:8997a1b348dd 114 if (temp<sampleError) {
Sissors 1:8997a1b348dd 115 sampleLoc = i;
Sissors 1:8997a1b348dd 116 sampleError=temp;
Sissors 1:8997a1b348dd 117 }
Sissors 0:7bc29a9ea016 118 }
Sissors 0:7bc29a9ea016 119
Sissors 1:8997a1b348dd 120 //Update the samplerate reg
Sissors 1:8997a1b348dd 121 temp = read(MMA7660_SR_R);
Sissors 2:a8e20db7901e 122 temp &= ~0x07; //Awake sample rate are lowest 3 bit
Sissors 1:8997a1b348dd 123 temp |= sampleLoc;
Sissors 1:8997a1b348dd 124 write(MMA7660_SR_R, temp);
Sissors 1:8997a1b348dd 125 this->samplerate = rates[sampleLoc];
Sissors 3:89cb08cc663b 126 setActive(active_old); //Restore previous active state
Sissors 1:8997a1b348dd 127 }
Sissors 1:8997a1b348dd 128
Sissors 1:8997a1b348dd 129
Sissors 1:8997a1b348dd 130 MMA7660::Orientation MMA7660::getSide( void )
Sissors 1:8997a1b348dd 131 {
Sissors 1:8997a1b348dd 132 char tiltreg = read(MMA7660_TILT_R);
Sissors 1:8997a1b348dd 133 //We care about 2 LSBs
Sissors 1:8997a1b348dd 134 tiltreg &= 0x03;
Sissors 1:8997a1b348dd 135 if (tiltreg == 0x01)
Sissors 1:8997a1b348dd 136 return MMA7660::Front;
Sissors 1:8997a1b348dd 137 if (tiltreg == 0x02)
Sissors 1:8997a1b348dd 138 return MMA7660::Back;
Sissors 1:8997a1b348dd 139 return MMA7660::Unknown;
Sissors 1:8997a1b348dd 140 }
Sissors 1:8997a1b348dd 141
Sissors 1:8997a1b348dd 142 MMA7660::Orientation MMA7660::getOrientation( void )
Sissors 1:8997a1b348dd 143 {
Sissors 1:8997a1b348dd 144 char tiltreg = read(MMA7660_TILT_R);
Sissors 1:8997a1b348dd 145
Sissors 1:8997a1b348dd 146 //We care about bit 2, 3 and 4 (counting from zero)
Sissors 1:8997a1b348dd 147 tiltreg &= 0x07<<2;
Sissors 1:8997a1b348dd 148 tiltreg >>= 2;
Sissors 1:8997a1b348dd 149 if (tiltreg == 0x01)
Sissors 1:8997a1b348dd 150 return MMA7660::Left;
Sissors 1:8997a1b348dd 151 if (tiltreg == 0x02)
Sissors 1:8997a1b348dd 152 return MMA7660::Right;
Sissors 1:8997a1b348dd 153 if (tiltreg == 0x05)
Sissors 1:8997a1b348dd 154 return MMA7660::Down;
Sissors 1:8997a1b348dd 155 if (tiltreg == 0x06)
Sissors 1:8997a1b348dd 156 return MMA7660::Up;
Sissors 1:8997a1b348dd 157 return MMA7660::Unknown;
Sissors 1:8997a1b348dd 158 }
Sissors 1:8997a1b348dd 159
Sissors 2:a8e20db7901e 160
Sissors 1:8997a1b348dd 161
Sissors 1:8997a1b348dd 162 //////////////////////////////////////////////
Sissors 1:8997a1b348dd 163 ///////////////PRIVATE////////////////////////
Sissors 1:8997a1b348dd 164 //////////////////////////////////////////////
Sissors 1:8997a1b348dd 165
Sissors 0:7bc29a9ea016 166
Sissors 0:7bc29a9ea016 167 void MMA7660::write(char address, char data)
Sissors 0:7bc29a9ea016 168 {
Sissors 0:7bc29a9ea016 169 char temp[2];
Sissors 0:7bc29a9ea016 170 temp[0]=address;
Sissors 0:7bc29a9ea016 171 temp[1]=data;
Sissors 0:7bc29a9ea016 172
Kojto 5:556829f081f6 173 if (!asynch) {
Kojto 5:556829f081f6 174 _i2c.write(MMA7660_ADDRESS, temp, 2);
Kojto 5:556829f081f6 175 } else {
Kojto 5:556829f081f6 176 callback_done = false;
Kojto 5:556829f081f6 177 _i2c.transfer(MMA7660_ADDRESS, &temp[0], 2, NULL, 0, event, I2C_EVENT_ALL);
Kojto 5:556829f081f6 178 while (!callback_done) {
Kojto 5:556829f081f6 179 sleep();
Kojto 5:556829f081f6 180 }
Kojto 5:556829f081f6 181 }
Sissors 0:7bc29a9ea016 182 }
Sissors 0:7bc29a9ea016 183
Sissors 0:7bc29a9ea016 184 char MMA7660::read(char address)
Sissors 0:7bc29a9ea016 185 {
Kojto 5:556829f081f6 186 if (!asynch) {
Kojto 5:556829f081f6 187 char retval;
Kojto 5:556829f081f6 188
Kojto 5:556829f081f6 189 _i2c.write(MMA7660_ADDRESS, &address, 1, true);
Kojto 5:556829f081f6 190 _i2c.read(MMA7660_ADDRESS, &retval, 1);
Kojto 5:556829f081f6 191 return retval;
Kojto 5:556829f081f6 192 } else {
Kojto 5:556829f081f6 193 callback_done = false;
Kojto 5:556829f081f6 194 char received = 0;
Kojto 5:556829f081f6 195 char addr = address;
Kojto 5:556829f081f6 196 _i2c.transfer(MMA7660_ADDRESS, &addr, 1, &received, 1, event, I2C_EVENT_ALL);
Kojto 5:556829f081f6 197 while (!callback_done) {
Kojto 5:556829f081f6 198 sleep();
Kojto 5:556829f081f6 199 }
Kojto 5:556829f081f6 200 return received;
Kojto 5:556829f081f6 201 }
Sissors 0:7bc29a9ea016 202 }
Sissors 0:7bc29a9ea016 203
Sissors 0:7bc29a9ea016 204 void MMA7660::read(char address, char *data, int length)
Sissors 0:7bc29a9ea016 205 {
Kojto 5:556829f081f6 206 if (!asynch) {
Kojto 5:556829f081f6 207 _i2c.write(MMA7660_ADDRESS, &address, 1, true);
Kojto 5:556829f081f6 208 _i2c.read(MMA7660_ADDRESS, data, length);
Kojto 5:556829f081f6 209 } else {
Kojto 5:556829f081f6 210 callback_done = false;
Kojto 5:556829f081f6 211 _i2c.transfer(MMA7660_ADDRESS, &address, 1, data, length, event, I2C_EVENT_ALL);
Kojto 5:556829f081f6 212 while (!callback_done) {
Kojto 5:556829f081f6 213 sleep();
Kojto 5:556829f081f6 214 }
Kojto 5:556829f081f6 215 }
Sissors 0:7bc29a9ea016 216 }
Sissors 0:7bc29a9ea016 217
Sissors 0:7bc29a9ea016 218 float MMA7660::getSingle( int number )
Sissors 0:7bc29a9ea016 219 {
Sissors 3:89cb08cc663b 220 bool active_old = active;
Sissors 0:7bc29a9ea016 221 if (!active) {
Sissors 0:7bc29a9ea016 222 setActive(true);
Sissors 1:8997a1b348dd 223 wait(0.012 + 1/samplerate); //Wait until new sample is ready
Sissors 0:7bc29a9ea016 224 }
Sissors 0:7bc29a9ea016 225
Sissors 0:7bc29a9ea016 226 signed char temp;
Sissors 0:7bc29a9ea016 227 bool alert;
Sissors 0:7bc29a9ea016 228
Sissors 0:7bc29a9ea016 229 do {
Sissors 0:7bc29a9ea016 230 alert = false;
Sissors 0:7bc29a9ea016 231 temp = read(MMA7660_XOUT_R + number);
Sissors 0:7bc29a9ea016 232 if (temp > 63)
Sissors 0:7bc29a9ea016 233 alert = true;
Sissors 0:7bc29a9ea016 234 if (temp > 31)
Sissors 0:7bc29a9ea016 235 temp += 128+64;
Sissors 2:a8e20db7901e 236 } while (alert);
Sissors 0:7bc29a9ea016 237
Sissors 3:89cb08cc663b 238 if (!active_old)
Sissors 2:a8e20db7901e 239 setActive(false);
Sissors 0:7bc29a9ea016 240
Sissors 0:7bc29a9ea016 241 return temp / MMA7660_SENSITIVITY;
Kojto 5:556829f081f6 242 }