MSA301 Driver and example tweaks

pull/149/head
ZodiusInfuser 2021-05-13 16:26:08 +01:00 zatwierdzone przez Phil Howard
rodzic f211fe67e6
commit c4b166d4d9
3 zmienionych plików z 147 dodań i 115 usunięć

Wyświetl plik

@ -25,6 +25,85 @@ namespace pimoroni {
set_range_and_resolution(Range::G_2, Resolution::BITS_14);
}
void MSA301::reset() {
i2c_reg_write_uint8(SOFT_RESET, 0b00100100);
sleep_ms(1);
}
uint8_t MSA301::part_id() {
return i2c_reg_read_uint8(PART_ID);
}
float MSA301::get_axis(Axis axis, uint8_t sample_count) {
if(sample_count > 1) {
int32_t total = 0;
for(uint8_t i = 0; i < sample_count; i++) {
total += i2c_reg_read_int16((int)axis);
}
total /= sample_count;
return total / 16384.0f;
}
return i2c_reg_read_int16(axis) / 16384.0f;
}
float MSA301::get_x_axis(uint8_t sample_count) {
return get_axis(MSA301::X, sample_count);
}
float MSA301::get_y_axis(uint8_t sample_count) {
return get_axis(MSA301::Y, sample_count);
}
float MSA301::get_z_axis(uint8_t sample_count) {
return get_axis(MSA301::Z, sample_count);
}
MSA301::Orientation MSA301::get_orientation() {
return (Orientation)((i2c_reg_read_uint8(ORIENTATION_STATUS) >> 4) & 0b11);
}
void MSA301::set_power_mode(MSA301::PowerMode power_mode) {
i2c_reg_write_uint8(POWER_MODE_BANDWIDTH, power_mode);
}
void MSA301::set_range_and_resolution(Range range, MSA301::Resolution resolution) {
i2c_reg_write_uint8(RESOLUTION_RANGE, range | resolution);
}
void MSA301::set_axis_polarity(int polarity) {
i2c_reg_write_uint8(SET_AXIS_POLARITY, polarity);
}
void MSA301::disable_all_interrupts() {
enable_interrupts(MSA301::Interrupt::NONE);
}
void MSA301::enable_interrupts(int interrupts) {
i2c_reg_write_uint8(INTERRUPT_ENABLE_0, interrupts & 0xff);
i2c_reg_write_uint8(INTERRUPT_ENABLE_1, (interrupts & 0xff00) >> 8);
}
void MSA301::set_interrupt_latch(MSA301::InterruptLatchPeriod latch_period, bool reset_latched = false) {
i2c_reg_write_uint8(INTERRUPT_LATCH_PERIOD, latch_period | (reset_latched ? 0b10000000: 0b0));
}
bool MSA301::read_interrupt(Interrupt interrupt) {
if(interrupt == NEW_DATA) {
return i2c_reg_read_uint8(DATA_INTERRUPT) & 0b1;
}
// determine which bit indicates the status of this interrupt
uint8_t bit = 0;
if(interrupt == FREEFALL) bit = 0;
if(interrupt == ACTIVE) bit = 2;
if(interrupt == DOUBLE_TAP) bit = 4;
if(interrupt == SINGLE_TAP) bit = 5;
if(interrupt == ORIENTATION) bit = 6;
return i2c_reg_read_uint8(MOTION_INTERRUPT) & (1U << bit);
}
void MSA301::i2c_reg_write_uint8(uint8_t reg, uint8_t value) {
uint8_t buffer[2] = {reg, value};
i2c_write_blocking(i2c, address, buffer, 2, false);
@ -44,71 +123,4 @@ namespace pimoroni {
return value;
}
void MSA301::reset() {
i2c_reg_write_uint8(SOFT_RESET, 0b00100100);
sleep_ms(1);
}
uint8_t MSA301::part_id() {
return i2c_reg_read_uint8(PART_ID);
}
float MSA301::get_axis(Axis axis, uint8_t sample_count) {
if(sample_count > 1) {
int32_t total = 0;
for(uint8_t i = 0; i < sample_count; i++) {
total += i2c_reg_read_int16(int(axis));
}
total /= sample_count;
return total / 16384.0f;
}
return i2c_reg_read_int16(axis) / 16384.0f;
}
MSA301::Orientation MSA301::get_orientation() {
return (Orientation)((i2c_reg_read_uint8(ORIENTATION_STATUS) >> 4) & 0b11);
}
void MSA301::set_power_mode(MSA301::PowerMode power_mode) {
i2c_reg_write_uint8(POWER_MODE_BANDWIDTH, power_mode);
}
void MSA301::set_range_and_resolution(Range range, MSA301::Resolution resolution) {
i2c_reg_write_uint8(RESOLUTION_RANGE, range | resolution);
}
void MSA301::set_axis_polarity(int polarity) {
i2c_reg_write_uint8(SET_AXIS_POLARITY, polarity);
}
void MSA301::disable_all_interrupts() {
enable_interrupts(MSA301::Interrupt::NONE);
}
void MSA301::enable_interrupts(int interrupts) {
i2c_reg_write_uint8(INTERRUPT_ENABLE_0, interrupts & 0xff);
i2c_reg_write_uint8(INTERRUPT_ENABLE_1, (interrupts & 0xff00) >> 8);
}
bool MSA301::read_interrupt(Interrupt interrupt) {
if(interrupt == NEW_DATA) {
return i2c_reg_read_uint8(DATA_INTERRUPT) & 0b1;
}
// determine which bit indicates the status of this interrupt
uint8_t bit = 0;
if(interrupt == FREEFALL) bit = 0;
if(interrupt == ACTIVE) bit = 2;
if(interrupt == DOUBLE_TAP) bit = 4;
if(interrupt == SINGLE_TAP) bit = 5;
if(interrupt == ORIENTATION) bit = 6;
return i2c_reg_read_uint8(MOTION_INTERRUPT) & (1U << bit);
}
void MSA301::set_interrupt_latch(MSA301::InterruptLatchPeriod latch_period, bool reset_latched = false) {
i2c_reg_write_uint8(INTERRUPT_LATCH_PERIOD, latch_period | (reset_latched ? 0b10000000: 0b0));
}
}

Wyświetl plik

@ -22,35 +22,18 @@ namespace pimoroni {
static const uint8_t DATA_INTERRUPT = 0x0a;
static const uint8_t ORIENTATION_STATUS = 0x0c;
static const uint8_t RESOLUTION_RANGE = 0x0f;
static const uint8_t POWER_MODE_BANDWIDTH = 0x11;
static const uint8_t POWER_MODE_BANDWIDTH = 0x11;
static const uint8_t SET_AXIS_POLARITY = 0x12;
static const uint8_t INTERRUPT_ENABLE_0 = 0x16;
static const uint8_t INTERRUPT_ENABLE_1 = 0x17;
static const uint8_t INTERRUPT_LATCH_PERIOD = 0x21;
static const uint8_t FREEFALL_DURATION = 0x22;
private:
i2c_inst_t *i2c = i2c0;
// interface pins with our standard defaults where appropriate
int8_t address = DEFAULT_I2C_ADDRESS;
int8_t sda = DEFAULT_SDA_PIN;
int8_t scl = DEFAULT_SCL_PIN;
int8_t interrupt = DEFAULT_INT_PIN;
//--------------------------------------------------
// Enums
//--------------------------------------------------
public:
MSA301() {}
MSA301(i2c_inst_t *i2c, uint8_t sda, uint8_t scl, uint8_t interrupt) :
i2c(i2c), sda(sda), scl(scl), interrupt(interrupt) {}
void init();
void reset();
void i2c_reg_write_uint8(uint8_t reg, uint8_t value);
uint8_t i2c_reg_read_uint8(uint8_t reg);
int16_t i2c_reg_read_int16(uint8_t reg);
enum Axis {
X = 0x02,
Y = 0x04,
@ -58,54 +41,54 @@ namespace pimoroni {
};
enum Orientation {
PORTRAIT = 0b00,
PORTRAIT_INVERTED = 0b01,
LANDSCAPE = 0b10,
PORTRAIT = 0b00,
PORTRAIT_INVERTED = 0b01,
LANDSCAPE = 0b10,
LANDSCAPE_INVERTED = 0b11
};
enum PowerMode {
NORMAL = 0b00,
LOW = 0b01,
NORMAL = 0b00,
LOW = 0b01,
SUSPEND = 0b10
};
enum Range {
G_2 = 0b00,
G_4 = 0b01,
G_8 = 0b10,
G_2 = 0b00,
G_4 = 0b01,
G_8 = 0b10,
G_16 = 0b11
};
enum Resolution {
BITS_14 = 0b0000,
BITS_12 = 0b0100,
BITS_10 = 0b1000,
BITS_14 = 0b0000,
BITS_12 = 0b0100,
BITS_10 = 0b1000,
BITS_8 = 0b1100
};
enum AxisPolarity {
INVERT_X = 0b1000,
INVERT_Y = 0b0100,
INVERT_Z = 0b0010,
INVERT_X = 0b1000,
INVERT_Y = 0b0100,
INVERT_Z = 0b0010,
XY_SWAP = 0b0001
};
enum Interrupt {
NONE = 0,
NONE = 0,
ACTIVE = 0b0000111,
NEW_DATA = 0b1000000000000,
NEW_DATA = 0b1000000000000,
FREEFALL = 0b0100000000000,
ORIENTATION = 0b1000000,
ORIENTATION = 0b1000000,
SINGLE_TAP = 0b0100000,
DOUBLE_TAP = 0b0010000,
Z_ACTIVE = 0b0000100,
Y_ACTIVE = 0b0000010,
Z_ACTIVE = 0b0000100,
Y_ACTIVE = 0b0000010,
X_ACTIVE = 0b0000001
};
enum InterruptLatchPeriod {
LATCH_1MS = 0b1001,
LATCH_1MS = 0b1001,
LATCH_2MS = 0b1011,
LATCH_25MS = 0b1100,
LATCH_50MS = 0b1101,
@ -118,20 +101,57 @@ namespace pimoroni {
LATCH_8S = 0b0110
};
//--------------------------------------------------
// Variables
//--------------------------------------------------
private:
i2c_inst_t *i2c = i2c0;
// interface pins with our standard defaults where appropriate
int8_t address = DEFAULT_I2C_ADDRESS;
int8_t sda = DEFAULT_SDA_PIN;
int8_t scl = DEFAULT_SCL_PIN;
int8_t interrupt = DEFAULT_INT_PIN;
//--------------------------------------------------
// Constructors/Destructor
//--------------------------------------------------
public:
MSA301() {}
MSA301(i2c_inst_t *i2c, uint8_t sda, uint8_t scl, uint8_t interrupt) :
i2c(i2c), sda(sda), scl(scl), interrupt(interrupt) {}
//--------------------------------------------------
// Methods
//--------------------------------------------------
public:
void init();
void reset();
uint8_t part_id();
float get_axis(Axis axis, uint8_t sample_count = 1);
float get_x_axis(uint8_t sample_count = 1) { return this->get_axis(MSA301::X, sample_count); }
float get_y_axis(uint8_t sample_count = 1) { return this->get_axis(MSA301::Y, sample_count); }
float get_z_axis(uint8_t sample_count = 1) { return this->get_axis(MSA301::Z, sample_count); }
float get_x_axis(uint8_t sample_count = 1);
float get_y_axis(uint8_t sample_count = 1);
float get_z_axis(uint8_t sample_count = 1);
Orientation get_orientation();
void set_power_mode(MSA301::PowerMode power_mode);
void set_range_and_resolution(Range range, MSA301::Resolution resolution);
void set_axis_polarity(int polarity);
void disable_all_interrupts();
void enable_interrupts(int interrupts);
void set_interrupt_latch(InterruptLatchPeriod latch_period, bool reset_latched);
bool read_interrupt(Interrupt interrupt);
bool read_interrupt(Interrupt interrupt);
private:
void i2c_reg_write_uint8(uint8_t reg, uint8_t value);
uint8_t i2c_reg_read_uint8(uint8_t reg);
int16_t i2c_reg_read_int16(uint8_t reg);
};
}

Wyświetl plik

@ -18,9 +18,9 @@ int main() {
msa301.enable_interrupts(MSA301::FREEFALL | MSA301::ORIENTATION);
while(true){
printf("%d\n", msa301.read_interrupt(MSA301::FREEFALL));
printf("X: %f, Y: %f, Z: %f\n", msa301.get_x_axis(), msa301.get_y_axis(), msa301.get_z_axis());
printf("%d\n", msa301.get_orientation());
printf("X: %f, Y: %f, Z: %f", msa301.get_x_axis(), msa301.get_y_axis(), msa301.get_z_axis());
printf(", Freefall? %d", msa301.read_interrupt(MSA301::FREEFALL));
printf(", Orientation: %d\n", msa301.get_orientation());
sleep_ms(100);
};
return 0;