Skip to content

Commit

Permalink
Merge pull request #36 from stevenewald/echavemann/aidan-i2c
Browse files Browse the repository at this point in the history
I2C Wrapper + Controller
  • Loading branch information
echavemann authored Dec 4, 2024
2 parents 39003e3 + 8edac30 commit 2b28efe
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ typedef struct
*/
#define NRF_DRV_TWI_DEFAULT_CONFIG \
{ \
.frequency = (nrf_drv_twi_frequency_t)TWI_DEFAULT_CONFIG_FREQUENCY, \
.scl = 31, \
.sda = 31, \
.frequency = (nrf_drv_twi_frequency_t)TWI_DEFAULT_CONFIG_FREQUENCY, \
.interrupt_priority = TWI_DEFAULT_CONFIG_IRQ_PRIORITY, \
.clear_bus_init = TWI_DEFAULT_CONFIG_CLR_BUS_INIT, \
.hold_bus_uninit = TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT, \
Expand Down
15 changes: 15 additions & 0 deletions include/hal/i2c_controller.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

namespace edge::aidan
{

class I2CController
{
public:
~I2CController() = default;
static I2CController& get();
private:
I2CController();
};

} // namespace edge::aidan
90 changes: 90 additions & 0 deletions include/hal/i2c_wrapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#pragma once

#include <stdint.h>
#include "nrf_twi_mngr.h"
#include "nrf_delay.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;

uint8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr);

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
31 changes: 31 additions & 0 deletions src/hal/i2c_controller.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "hal/i2c_controller.hpp"
#include "hal/i2c_wrapper.hpp"
#include "nrf_drv_twi.h"
#include "microbit_v2.h"
#include "nrf_twi.h"
#include "nrf_twi_mngr.h"

namespace edge::aidan
{
static constexpr int QUEUE_SIZE = 1;

NRF_TWI_MNGR_DEF(twi_mngr, QUEUE_SIZE, 0);

I2CController& I2CController::get()
{
static I2CController controller;
return controller;
}

I2CController::I2CController()
{
nrf_drv_twi_config_t i2c_config = NRF_DRV_TWI_DEFAULT_CONFIG;
i2c_config.scl = I2C_INTERNAL_SCL;
i2c_config.sda = I2C_INTERNAL_SDA;
i2c_config.frequency = NRF_DRV_TWI_FREQ_100K;
i2c_config.interrupt_priority = 0;
nrf_twi_mngr_init(&twi_mngr, &i2c_config);
lsm303agr_init(&twi_mngr);
}

} // namespace edge::aidan
71 changes: 71 additions & 0 deletions src/hal/i2c_wrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "hal/i2c_wrapper.hpp"
#include "nrf_error.h"
#include "nrf_twi_mngr.h"
#include "sdk_errors.h"

namespace edge::aidan {


NRF_TWI_MNGR_DEF(twi_mngr, 1, 0);
static const nrf_twi_mngr_t* i2c_manager = &twi_mngr;

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, &reg_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()
{
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);

// ---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);

i2c_reg_write(LSM303AGR_ACC_ADDRESS, TEMP_CFG_REG_A, 0xC0);
}


} // namespace edge::aidan

0 comments on commit 2b28efe

Please sign in to comment.