kopia lustrzana https://github.com/pimoroni/pimoroni-pico
MSA301 Driver and example tweaks
rodzic
f211fe67e6
commit
c4b166d4d9
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Ładowanie…
Reference in New Issue