Forked MMA7660 , extend implementation by using i2c asynch API, to sleep while waiting for transfer -> blocking asynch :-D
Fork of MMA7660 by
MMA7660.cpp
- Committer:
- Kojto
- Date:
- 2015-05-05
- Revision:
- 5:556829f081f6
- Parent:
- 4:36a163511e34
File content as of revision 5:556829f081f6:
#include "MMA7660.h" MMA7660::MMA7660(PinName sda, PinName scl, bool active, bool asynch) : _i2c(sda, scl), callback_done(false), asynch(asynch) { event.attach(this, &MMA7660::callback); setActive(active); samplerate = 64; } void MMA7660::callback(int event) { if (event == I2C_EVENT_TRANSFER_COMPLETE) { callback_done = true; } else { // handling errors } } //Since the MMA lacks a WHO_AM_I register, we can only check if there is a device that answers to the I2C address bool MMA7660::testConnection( void ) { if (!asynch) { if (_i2c.write(MMA7660_ADDRESS, NULL, 0) == 0 ) return true; else return false; } else { callback_done = false; char received = 0; _i2c.transfer(MMA7660_ADDRESS, NULL, 0, &received, 1, event, I2C_EVENT_ALL, false); while (!callback_done) { sleep(); } return received == 0 ? true : false; } } void MMA7660::setActive(bool state) { active = state; char modereg = read(MMA7660_MODE_R); modereg &= ~(1<<0); //If it somehow was in testmode, disable that if (modereg && (1<<2)) { modereg &= ~(1<<2); write(MMA7660_MODE_R, modereg); } modereg += state; write(MMA7660_MODE_R, modereg); } void MMA7660::readData(int *data) { bool active_old = active; if (!active) { setActive(true); wait(0.012 + 1/samplerate); //Wait until new sample is ready, my experience is that 1/samplerate isnt needed, but datasheet says so } char temp[3]; bool alert; do { alert = false; read(MMA7660_XOUT_R, temp, 3); for (int i = 0; i<3; i++) { if (temp[i] > 63) alert = true; if (temp[i] > 31) temp[i] += 128+64; data[i] = (signed char)temp[i]; } } while (alert); if (!active_old) setActive(false); } void MMA7660::readData(float *data) { int intdata[3]; readData(intdata); for (int i = 0; i<3; i++) data[i] = intdata[i]/MMA7660_SENSITIVITY; } float MMA7660::x( void ) { return getSingle(0); } float MMA7660::y( void ) { return getSingle(1); } float MMA7660::z( void ) { return getSingle(2); } void MMA7660::setSampleRate(int samplerate) { bool active_old = active; setActive(false); //Not allowed to be active to change anything int rates[] = {120, 64, 32, 16, 8, 4, 2, 1}; //Alowed samplerates (and their number in array is also number required for MMA) int sampleLoc = 0, sampleError = 10000, temp; for (int i = 0; i<8; i++) { temp = abs( rates[i] - samplerate ); if (temp<sampleError) { sampleLoc = i; sampleError=temp; } } //Update the samplerate reg temp = read(MMA7660_SR_R); temp &= ~0x07; //Awake sample rate are lowest 3 bit temp |= sampleLoc; write(MMA7660_SR_R, temp); this->samplerate = rates[sampleLoc]; setActive(active_old); //Restore previous active state } MMA7660::Orientation MMA7660::getSide( void ) { char tiltreg = read(MMA7660_TILT_R); //We care about 2 LSBs tiltreg &= 0x03; if (tiltreg == 0x01) return MMA7660::Front; if (tiltreg == 0x02) return MMA7660::Back; return MMA7660::Unknown; } MMA7660::Orientation MMA7660::getOrientation( void ) { char tiltreg = read(MMA7660_TILT_R); //We care about bit 2, 3 and 4 (counting from zero) tiltreg &= 0x07<<2; tiltreg >>= 2; if (tiltreg == 0x01) return MMA7660::Left; if (tiltreg == 0x02) return MMA7660::Right; if (tiltreg == 0x05) return MMA7660::Down; if (tiltreg == 0x06) return MMA7660::Up; return MMA7660::Unknown; } ////////////////////////////////////////////// ///////////////PRIVATE//////////////////////// ////////////////////////////////////////////// void MMA7660::write(char address, char data) { char temp[2]; temp[0]=address; temp[1]=data; if (!asynch) { _i2c.write(MMA7660_ADDRESS, temp, 2); } else { callback_done = false; _i2c.transfer(MMA7660_ADDRESS, &temp[0], 2, NULL, 0, event, I2C_EVENT_ALL); while (!callback_done) { sleep(); } } } char MMA7660::read(char address) { if (!asynch) { char retval; _i2c.write(MMA7660_ADDRESS, &address, 1, true); _i2c.read(MMA7660_ADDRESS, &retval, 1); return retval; } else { callback_done = false; char received = 0; char addr = address; _i2c.transfer(MMA7660_ADDRESS, &addr, 1, &received, 1, event, I2C_EVENT_ALL); while (!callback_done) { sleep(); } return received; } } void MMA7660::read(char address, char *data, int length) { if (!asynch) { _i2c.write(MMA7660_ADDRESS, &address, 1, true); _i2c.read(MMA7660_ADDRESS, data, length); } else { callback_done = false; _i2c.transfer(MMA7660_ADDRESS, &address, 1, data, length, event, I2C_EVENT_ALL); while (!callback_done) { sleep(); } } } float MMA7660::getSingle( int number ) { bool active_old = active; if (!active) { setActive(true); wait(0.012 + 1/samplerate); //Wait until new sample is ready } signed char temp; bool alert; do { alert = false; temp = read(MMA7660_XOUT_R + number); if (temp > 63) alert = true; if (temp > 31) temp += 128+64; } while (alert); if (!active_old) setActive(false); return temp / MMA7660_SENSITIVITY; }