From 5b8235ba33e2e6e2b4a71831d3c4e25e245bf29d Mon Sep 17 00:00:00 2001 From: Ethan Havemann Date: Sun, 1 Dec 2024 13:41:46 -0600 Subject: [PATCH] init --- include/hal/i2c_wrapper.hpp | 87 +++++++++++++++++++++++++++++++++++++ src/hal/i2c_wrapper.cpp | 79 +++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 include/hal/i2c_wrapper.hpp create mode 100644 src/hal/i2c_wrapper.cpp diff --git a/include/hal/i2c_wrapper.hpp b/include/hal/i2c_wrapper.hpp new file mode 100644 index 00000000..9e5054b2 --- /dev/null +++ b/include/hal/i2c_wrapper.hpp @@ -0,0 +1,87 @@ +#include +#include "nrf_twi_mngr.h" + +namespace edge::aidan { + +static const uint8_t LSM303AGR_ACC_ADDRESS = 0x19; +static const uint8_t LSM303AGR_MAG_ADDRESS = 0x1E; + +typedef struct { + float x_axis; + float y_axis; + float z_axis; +} lsm303agr_measurement_t; + +// Accel Enums +typedef enum { + STATUS_REG_AUX_A = 0x07, + OUT_TEMP_L_A = 0x0C, + OUT_TEMP_H_A = 0x0D, + INT_COUNTER_REG_A = 0x0E, + WHO_AM_I_A = 0x0F, + TEMP_CFG_REG_A = 0x1F, + CTRL_REG1_A = 0x20, + CTRL_REG2_A = 0x21, + CTRL_REG3_A = 0x22, + CTRL_REG4_A = 0x23, + CTRL_REG5_A = 0x24, + CTRL_REG6_A = 0x25, + REFERENCE_DATACAPTURE_A = 0x26, + STATUS_REG_A = 0x27, + OUT_X_L_A = 0x28, + OUT_X_H_A = 0x29, + OUT_Y_L_A = 0x2A, + OUT_Y_H_A = 0x2B, + OUT_Z_L_A = 0x2C, + OUT_Z_H_A = 0x2D, + FIFO_CTRL_REG_A = 0x2E, + FIFO_SRC_REG_A = 0x2F, + INT1_CFG_A = 0x30, + INT1_SRC_A = 0x31, + INT1_THS_A = 0x32, + INT1_DURATION_A = 0x33, + INT2_CFG_A = 0x34, + INT2_SRC_A = 0x35, + INT2_THS_A = 0x36, + INT2_DURATION_A = 0x37, + CLICK_CFG_A = 0x38, + CLICK_SRC_A = 0x39, + CLICK_THS_A = 0x3A, + TIME_LIMIT_A = 0x3B, + TIME_LATENCY_A = 0x3C, + TIME_WINDOW_A = 0x3D, + ACT_THS_A = 0x3E, + ACT_DUR_A = 0x3F, +} lsm303agr_acc_reg_t; + +// Magneto Enums +typedef enum { + OFFSET_X_REG_L_M = 0x45, + OFFSET_X_REG_H_M = 0x46, + OFFSET_Y_REG_L_M = 0x47, + OFFSET_Y_REG_H_M = 0x48, + OFFSET_Z_REG_L_M = 0x49, + OFFSET_Z_REG_H_M = 0x4A, + WHO_AM_I_M = 0x4F, + CFG_REG_A_M = 0x60, + CFG_REG_B_M = 0x61, + CFG_REG_C_M = 0x62, + INT_CTRL_REG_M = 0x63, + INT_SOURCE_REG_M = 0x64, + INT_THS_L_REG_M = 0x65, + INT_THS_H_REG_M = 0x66, + STATUS_REG_M = 0x67, + OUTX_L_REG_M = 0x68, + OUTX_H_REG_M = 0x69, + OUTY_L_REG_M = 0x6A, + OUTY_H_REG_M = 0x6B, + OUTZ_L_REG_M = 0x6C, + OUTZ_H_REG_M = 0x6D, +} lsm303agr_mag_reg_t; + +static uint8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr); + +static void i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t data); + +void lsm303agr_init(const nrf_twi_mngr_t* i2c); +} // namespace edge::aidan diff --git a/src/hal/i2c_wrapper.cpp b/src/hal/i2c_wrapper.cpp new file mode 100644 index 00000000..9064315a --- /dev/null +++ b/src/hal/i2c_wrapper.cpp @@ -0,0 +1,79 @@ +#include "hal/i2c_wrapper.hpp" +#include "cmsis_gcc.h" +#include "nrf_error.h" +#include "nrf_twi_mngr.h" +#include "sdk_errors.h" + +namespace edge::aidan { + +static const nrf_twi_mngr_t* i2c_manager = NULL; + +uint8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr) +{ + uint8_t rx_buf = 0; + nrf_twi_mngr_transfer_t const read_transfer[] = { + NRF_TWI_MNGR_WRITE(i2c_addr, ®_addr, 1, NRF_TWI_MNGR_NO_STOP), + NRF_TWI_MNGR_READ(i2c_addr, &rx_buf, 1, NRF_TWI_MNGR_NO_STOP) + }; + ret_code_t result = nrf_twi_mngr_perform(i2c_manager, NULL, read_transfer, 2, NULL); + if (result != NRF_SUCCESS) + { + printf("I2C TRANSACTION FAILED!"); + } + return rx_buf; +}; + +void i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t data) +{ + uint16_t rx_buf = (reg_addr << 8) | data; + rx_buf = (data << 8) | reg_addr; + nrf_twi_mngr_transfer_t const write_transfer[] = { + NRF_TWI_MNGR_WRITE(i2c_addr, &rx_buf, 2, NRF_TWI_MNGR_NO_STOP), + }; + ret_code_t result = nrf_twi_mngr_perform(i2c_manager, NULL, write_transfer, 1, NULL); + if (result != NRF_SUCCESS) + { + printf("I2C transaction failed! Error: %lX\n", result); + } +} + +void lsm303agr_init(const int *i2c) +{ + i2c_manager = i2c; + + i2c_reg_write(LSM303AGR_ACC_ADDRESS, CTRL_REG5_A, 0x80); + nrf_delay_ms(100); // needs delay to wait for reboot + + // Enable Block Data Update + // Only updates sensor data when both halves of the data has been read + i2c_reg_write(LSM303AGR_ACC_ADDRESS, CTRL_REG4_A, 0x80); + + // Configure accelerometer at 100Hz, normal mode (10-bit) + // Enable x, y and z axes + i2c_reg_write(LSM303AGR_ACC_ADDRESS, CTRL_REG1_A, 0x57); + + // Read WHO AM I register + // Always returns the same value if working + uint8_t res1 = i2c_reg_read(LSM303AGR_ACC_ADDRESS, WHO_AM_I_A); + + // ---Initialize Magnetometer--- + + // Reboot magnetometer + i2c_reg_write(LSM303AGR_MAG_ADDRESS, CFG_REG_A_M, 0x40); + nrf_delay_ms(100); // needs delay to wait for reboot + + // Enable Block Data Update + // Only updates sensor data when both halves of the data has been read + i2c_reg_write(LSM303AGR_MAG_ADDRESS, CFG_REG_C_M, 0x10); + + // Configure magnetometer at 100Hz, continuous mode + i2c_reg_write(LSM303AGR_MAG_ADDRESS, CFG_REG_A_M, 0x0C); + + // Read WHO AM I register + uint8_t res2 = i2c_reg_read(LSM303AGR_MAG_ADDRESS, WHO_AM_I_M); + + i2c_reg_write(LSM303AGR_ACC_ADDRESS, TEMP_CFG_REG_A, 0xC0); +} + + +}