diff --git a/quad/sw/modular_quad_pid/src/controllers.c b/quad/sw/modular_quad_pid/src/controllers.c
index 31f70c3673c15e9e4ca56a03fb5c7ce6804a7b99..7be7616e1a527ebb327c73609a8d93b84bf36508 100644
--- a/quad/sw/modular_quad_pid/src/controllers.c
+++ b/quad/sw/modular_quad_pid/src/controllers.c
@@ -9,7 +9,7 @@
  * Lots of useful information in controllers.h, look in there first
  */
 #include "controllers.h"
-#include "iic_mpu9150_utils.h"
+#include "iic_utils.h"
 #include "quadposition.h"
 #include "util.h"
 #include "uart.h"
diff --git a/quad/sw/modular_quad_pid/src/iic_mpu9150_utils.c b/quad/sw/modular_quad_pid/src/iic_mpu9150_utils.c
deleted file mode 100644
index 75a63cc90ea57d28a08b9e5ca057c833ec88c4e4..0000000000000000000000000000000000000000
--- a/quad/sw/modular_quad_pid/src/iic_mpu9150_utils.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/**
- * IIC_MPU9150_UTILS.c
- *
- * Utility functions for using I2C on a Diligent Zybo board and
- * focused on the SparkFun MPU9150
- *
- * For function descriptions please see iic_mpu9150_utils.h
- *
- * Author: 	ucart
- * Created: 01/20/2015
- */
-
-#include <stdio.h>
-#include <sleep.h>
-#include <math.h>
-
-#include "xparameters.h"
-#include "iic_mpu9150_utils.h"
-#include "xbasic_types.h"
-#include "xiicps.h"
-
-XIicPs_Config* i2c_config;
-XIicPs I2C0;
-double magX_correction = -1, magY_correction, magZ_correction;
-
-int initI2C0(){
-
-	//Make sure CPU_1x clk is enabled for I2C controller
-	Xuint16* aper_ctrl = (Xuint16*) IO_CLK_CONTROL_REG_ADDR;
-
-	if(*aper_ctrl & 0x00040000){
-		xil_printf("CPU_1x is set to I2C0\r\n");
-	}
-
-	else{
-		xil_printf("CPU_1x is not set to I2C0..Setting now\r\n");
-		*aper_ctrl |= 0x00040000;
-	}
-
-
-	// Look up
-	i2c_config = XIicPs_LookupConfig(XPAR_PS7_I2C_0_DEVICE_ID);
-
-	XStatus status = XIicPs_CfgInitialize(&I2C0, i2c_config, i2c_config->BaseAddress);
-
-	// Check if initialization was successful
-	if(status != XST_SUCCESS){
-		return -1;
-	}
-
-	// Reset the controller and set the clock to 400kHz
-	XIicPs_Reset(&I2C0);
-	XIicPs_SetSClk(&I2C0, 400000);
-
-
-	return 0;
-}
-
-int startMPU9150(){
-
-	// Device Reset & Wake up
-	iic0Write(0x6B, 0x80);
-	usleep(5000);
-
-	// Set clock reference to Z Gyro
-	iic0Write(0x6B, 0x03);
-	// Configure Digital Low/High Pass filter
-	iic0Write(0x1A,0x06); // Level 6 low pass on gyroscope
-
-	// Configure Gyro to 2000dps, Accel. to +/-8G
-	iic0Write(0x1B, 0x18);
-	iic0Write(0x1C, 0x10);
-
-	// Enable I2C bypass for AUX I2C (Magnetometer)
-	iic0Write(0x37, 0x02);
-
-	// Setup Mag
-	iic0Write(0x37, 0x02);             //INT_PIN_CFG   -- INT_LEVEL=0 ; INT_OPEN=0 ; LATCH_INT_EN=0 ; INT_RD_CLEAR=0 ; FSYNC_INT_LEVEL=0 ; FSYNC_INT_EN=0 ; I2C_BYPASS_EN=0 ; CLKOUT_EN=0
-
-	usleep(100000);
-
-	int i;
-	gam_t temp_gam;
-
-	// Do about 20 reads to warm up the device
-	for(i=0; i < 20; ++i){
-		if(get_gam_reading(&temp_gam) == -1){
-			return -1;
-		}
-		usleep(1000);
-	}
-
-	return 0;
-}
-
-void stopMPU9150(){
-
-	//Put MPU to sleep
-	iic0Write(0x6B, 0b01000000);
-}
-
-void iic0Write(u8 register_addr, u8 data){
-
-	u16 device_addr = MPU9150_DEVICE_ADDR;
-	u8 buf[] = {register_addr, data};
-
-	// Check if within register range
-	if(register_addr < 0 || register_addr > 0x75){
-		return;
-	}
-
-	if(register_addr <= 0x12){
-		device_addr = MPU9150_COMPASS_ADDR;
-	}
-
-	XIicPs_MasterSendPolled(&I2C0, buf, 2, device_addr);
-
-}
-
-void iic0Read(u8* recv_buffer, u8 register_addr, int size){
-
-	u16 device_addr = MPU9150_DEVICE_ADDR;
-	u8 buf[] = {register_addr};
-
-	// Check if within register range
-	if(register_addr < 0 || register_addr > 0x75){
-	}
-
-	// Set device address to the if 0x00 <= register address <= 0x12
-	if(register_addr <= 0x12){
-		device_addr = MPU9150_COMPASS_ADDR;
-	}
-
-
-	XIicPs_MasterSendPolled(&I2C0, buf, 1, device_addr);
-	XIicPs_MasterRecvPolled(&I2C0, recv_buffer,size,device_addr);
-}
-
-void CalcMagSensitivity(){
-
-	u8 buf[3];
-	u8 ASAX, ASAY, ASAZ;
-
-	// Quickly read from the factory ROM to get correction coefficents
-	iic0Write(0x0A, 0x0F);
-	usleep(10000);
-
-	// Read raw adjustment values
-	iic0Read(buf, 0x10,3);
-	ASAX = buf[0];
-	ASAY = buf[1];
-	ASAZ = buf[2];
-
-	// Set the correction coefficients
-	magX_correction = (ASAX-128)*0.5/128 + 1;
-	magY_correction = (ASAY-128)*0.5/128 + 1;
-	magZ_correction = (ASAZ-128)*0.5/128 + 1;
-}
-
-
-void ReadMag(gam_t* gam){
-
-	u8 mag_data[6];
-	Xint16 raw_magX, raw_magY, raw_magZ;
-
-	// Grab calibrations if not done already
-	if(magX_correction == -1){
-		CalcMagSensitivity();
-	}
-
-	// Set Mag to single read mode
-	iic0Write(0x0A, 0x01);
-	usleep(10000);
-	mag_data[0] = 0;
-
-	// Keep checking if data is ready before reading new mag data
-	while(mag_data[0] == 0x00){
-		iic0Read(mag_data, 0x02, 1);
-	}
-
-	// Get mag data
-	iic0Read(mag_data, 0x03, 6);
-
-	raw_magX = (mag_data[1] << 8) | mag_data[0];
-	raw_magY = (mag_data[3] << 8) | mag_data[2];
-	raw_magZ = (mag_data[5] << 8) | mag_data[4];
-
-	// Set magnetometer data to output
-	gam->mag_x = raw_magX * magX_correction;
-	gam->mag_y = raw_magY * magY_correction;
-	gam->mag_z = raw_magZ * magZ_correction;
-
-}
-
-/**
- * Get Gyro Accel Mag (GAM) information
- */
-int get_gam_reading(gam_t* gam) {
-
-	Xint16 raw_accel_x, raw_accel_y, raw_accel_z;
-	Xint16 gyro_x, gyro_y, gyro_z;
-
-	Xuint8 sensor_data[ACCEL_GYRO_READ_SIZE] = {};
-
-	// We should only get mag_data ~10Hz
-	//Xint8 mag_data[6] = {};
-
-	//readHandler = iic0_read_bytes(sensor_data, ACCEL_GYRO_BASE_ADDR, ACCEL_GYRO_READ_SIZE);
-	iic0Read(sensor_data, ACCEL_GYRO_BASE_ADDR, ACCEL_GYRO_READ_SIZE);
-
-	//Calculate accelerometer data
-	raw_accel_x = sensor_data[ACC_X_H] << 8 | sensor_data[ACC_X_L];
-	raw_accel_y = sensor_data[ACC_Y_H] << 8 | sensor_data[ACC_Y_L];
-	raw_accel_z = sensor_data[ACC_Z_H] << 8 | sensor_data[ACC_Z_L];
-
-	// put in G's
-	gam->accel_x = (raw_accel_x / 4096.0) + ACCEL_X_BIAS; // 4,096 is the gain per LSB of the measurement reading based on a configuration range of +-8g
-	gam->accel_y = (raw_accel_y / 4096.0) + ACCEL_Y_BIAS;
-	gam->accel_z = (raw_accel_z / 4096.0) + ACCEL_Z_BIAS;
-
-	//Get X and Y angles
-	// javey: this assigns accel_(pitch/roll) in units of radians
-	gam->accel_pitch = atan(gam->accel_x / sqrt(gam->accel_y*gam->accel_y + gam->accel_z*gam->accel_z));
-	gam->accel_roll = -atan(gam->accel_y / sqrt(gam->accel_x*gam->accel_x + gam->accel_z*gam->accel_z)); // negative because sensor board is upside down
-
-	//Convert gyro data to rate (we're only using the most 12 significant bits)
-	gyro_x = (sensor_data[GYR_X_H] << 8) | (sensor_data[GYR_X_L]); //* G_GAIN;
-	gyro_y = (sensor_data[GYR_Y_H] << 8 | sensor_data[GYR_Y_L]);// * G_GAIN;
-	gyro_z = (sensor_data[GYR_Z_H] << 8 | sensor_data[GYR_Z_L]);// * G_GAIN;
-
-	//Get the number of degrees
-	//javey: converted to radians to following SI units
-	gam->gyro_xVel_p = ((gyro_x / GYRO_SENS) * DEG_TO_RAD) + GYRO_X_BIAS;
-	gam->gyro_yVel_q = ((gyro_y / GYRO_SENS) * DEG_TO_RAD) + GYRO_Y_BIAS;
-	gam->gyro_zVel_r = ((gyro_z / GYRO_SENS) * DEG_TO_RAD) + GYRO_Z_BIAS;
-
-	return 0;
-
-}
diff --git a/quad/sw/modular_quad_pid/src/iic_utils.c b/quad/sw/modular_quad_pid/src/iic_utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..290d5f9b60e5861d10d1e2770870fbc98e020b30
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/iic_utils.c
@@ -0,0 +1,458 @@
+/**
+ * IIC_UTILS.c
+ *
+ * Utility functions for using I2C on a Diligent Zybo board.
+ * Supports the SparkFun MPU9150 and the LiDAR lite v2 sensor
+ */
+
+#include <stdio.h>
+#include <sleep.h>
+#include <math.h>
+
+#include "xparameters.h"
+#include "iic_utils.h"
+#include "xbasic_types.h"
+#include "xiicps.h"
+
+XIicPs_Config* i2c_config;
+XIicPs I2C0;
+double magX_correction = -1, magY_correction, magZ_correction;
+int XIicPs_MasterSendPolled_ours(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, u16 SlaveAddr);
+int XIicPs_SetupMaster(XIicPs *InstancePtr, int Role);
+s32 TransmitFifoFill(XIicPs *InstancePtr);
+
+int iic0_init(){
+
+	//Make sure CPU_1x clk is enabled for I2C controller
+	Xuint16* aper_ctrl = (Xuint16*) IO_CLK_CONTROL_REG_ADDR;
+
+	if(*aper_ctrl & 0x00040000){
+		xil_printf("CPU_1x is set to I2C0\r\n");
+	}
+
+	else{
+		xil_printf("CPU_1x is not set to I2C0..Setting now\r\n");
+		*aper_ctrl |= 0x00040000;
+	}
+
+
+	// Look up
+	i2c_config = XIicPs_LookupConfig(XPAR_PS7_I2C_0_DEVICE_ID);
+
+	XStatus status = XIicPs_CfgInitialize(&I2C0, i2c_config, i2c_config->BaseAddress);
+
+	// Check if initialization was successful
+	if(status != XST_SUCCESS){
+		return -1;
+	}
+
+	// Reset the controller and set the clock to 400kHz
+	XIicPs_Reset(&I2C0);
+	XIicPs_SetSClk(&I2C0, 400000);
+
+
+	return 0;
+}
+
+int iic0_mpu9150_start(){
+
+	// Device Reset & Wake up
+	iic0_mpu9150_write(0x6B, 0x80);
+	usleep(5000);
+
+	// Set clock reference to Z Gyro
+	iic0_mpu9150_write(0x6B, 0x03);
+	// Configure Digital Low/High Pass filter
+	iic0_mpu9150_write(0x1A,0x06); // Level 6 low pass on gyroscope
+
+	// Configure Gyro to 2000dps, Accel. to +/-8G
+	iic0_mpu9150_write(0x1B, 0x18);
+	iic0_mpu9150_write(0x1C, 0x10);
+
+	// Enable I2C bypass for AUX I2C (Magnetometer)
+	iic0_mpu9150_write(0x37, 0x02);
+
+	// Setup Mag
+	iic0_mpu9150_write(0x37, 0x02);             //INT_PIN_CFG   -- INT_LEVEL=0 ; INT_OPEN=0 ; LATCH_INT_EN=0 ; INT_RD_CLEAR=0 ; FSYNC_INT_LEVEL=0 ; FSYNC_INT_EN=0 ; I2C_BYPASS_EN=0 ; CLKOUT_EN=0
+
+	usleep(100000);
+
+	int i;
+	gam_t temp_gam;
+
+	// Do about 20 reads to warm up the device
+	for(i=0; i < 20; ++i){
+		if(iic0_mpu9150_read_gam(&temp_gam) == -1){
+			return -1;
+		}
+		usleep(1000);
+	}
+
+	return 0;
+}
+
+void iic0_mpu9150_stop(){
+
+	//Put MPU to sleep
+	iic0_mpu9150_write(0x6B, 0b01000000);
+}
+
+void iic0_mpu9150_write(u8 register_addr, u8 data){
+
+	u16 device_addr = MPU9150_DEVICE_ADDR;
+	u8 buf[] = {register_addr, data};
+
+	// Check if within register range
+	if(register_addr < 0 || register_addr > 0x75){
+		return;
+	}
+
+	if(register_addr <= 0x12){
+		device_addr = MPU9150_COMPASS_ADDR;
+	}
+
+	XIicPs_MasterSendPolled_ours(&I2C0, buf, 2, device_addr);
+
+}
+
+void iic0_mpu9150_read(u8* recv_buffer, u8 register_addr, int size){
+
+	u16 device_addr = MPU9150_DEVICE_ADDR;
+	u8 buf[] = {register_addr};
+
+	// Check if within register range
+	if(register_addr < 0 || register_addr > 0x75){
+	}
+
+	// Set device address to the if 0x00 <= register address <= 0x12
+	if(register_addr <= 0x12){
+		device_addr = MPU9150_COMPASS_ADDR;
+	}
+
+
+	XIicPs_MasterSendPolled_ours(&I2C0, buf, 1, device_addr);
+	XIicPs_MasterRecvPolled(&I2C0, recv_buffer,size,device_addr);
+}
+
+void iic0_mpu9150_calc_mag_sensitivity(){
+
+	u8 buf[3];
+	u8 ASAX, ASAY, ASAZ;
+
+	// Quickly read from the factory ROM to get correction coefficents
+	iic0_mpu9150_write(0x0A, 0x0F);
+	usleep(10000);
+
+	// Read raw adjustment values
+	iic0_mpu9150_read(buf, 0x10,3);
+	ASAX = buf[0];
+	ASAY = buf[1];
+	ASAZ = buf[2];
+
+	// Set the correction coefficients
+	magX_correction = (ASAX-128)*0.5/128 + 1;
+	magY_correction = (ASAY-128)*0.5/128 + 1;
+	magZ_correction = (ASAZ-128)*0.5/128 + 1;
+}
+
+
+void iic0_mpu9150_read_mag(gam_t* gam){
+
+	u8 mag_data[6];
+	Xint16 raw_magX, raw_magY, raw_magZ;
+
+	// Grab calibrations if not done already
+	if(magX_correction == -1){
+		iic0_mpu9150_calc_mag_sensitivity();
+	}
+
+	// Set Mag to single read mode
+	iic0_mpu9150_write(0x0A, 0x01);
+	usleep(10000);
+	mag_data[0] = 0;
+
+	// Keep checking if data is ready before reading new mag data
+	while(mag_data[0] == 0x00){
+		iic0_mpu9150_read(mag_data, 0x02, 1);
+	}
+
+	// Get mag data
+	iic0_mpu9150_read(mag_data, 0x03, 6);
+
+	raw_magX = (mag_data[1] << 8) | mag_data[0];
+	raw_magY = (mag_data[3] << 8) | mag_data[2];
+	raw_magZ = (mag_data[5] << 8) | mag_data[4];
+
+	// Set magnetometer data to output
+	gam->mag_x = raw_magX * magX_correction;
+	gam->mag_y = raw_magY * magY_correction;
+	gam->mag_z = raw_magZ * magZ_correction;
+
+}
+
+/**
+ * Get Gyro Accel Mag (GAM) information
+ */
+int iic0_mpu9150_read_gam(gam_t* gam) {
+
+	Xint16 raw_accel_x, raw_accel_y, raw_accel_z;
+	Xint16 gyro_x, gyro_y, gyro_z;
+
+	Xuint8 sensor_data[ACCEL_GYRO_READ_SIZE] = {};
+
+	// We should only get mag_data ~10Hz
+	//Xint8 mag_data[6] = {};
+
+	//readHandler = iic0_read_bytes(sensor_data, ACCEL_GYRO_BASE_ADDR, ACCEL_GYRO_READ_SIZE);
+	iic0_mpu9150_read(sensor_data, ACCEL_GYRO_BASE_ADDR, ACCEL_GYRO_READ_SIZE);
+
+	//Calculate accelerometer data
+	raw_accel_x = sensor_data[ACC_X_H] << 8 | sensor_data[ACC_X_L];
+	raw_accel_y = sensor_data[ACC_Y_H] << 8 | sensor_data[ACC_Y_L];
+	raw_accel_z = sensor_data[ACC_Z_H] << 8 | sensor_data[ACC_Z_L];
+
+	// put in G's
+	gam->accel_x = (raw_accel_x / 4096.0) + ACCEL_X_BIAS; // 4,096 is the gain per LSB of the measurement reading based on a configuration range of +-8g
+	gam->accel_y = (raw_accel_y / 4096.0) + ACCEL_Y_BIAS;
+	gam->accel_z = (raw_accel_z / 4096.0) + ACCEL_Z_BIAS;
+
+	//Get X and Y angles
+	// javey: this assigns accel_(pitch/roll) in units of radians
+	gam->accel_pitch = atan(gam->accel_x / sqrt(gam->accel_y*gam->accel_y + gam->accel_z*gam->accel_z));
+	gam->accel_roll = -atan(gam->accel_y / sqrt(gam->accel_x*gam->accel_x + gam->accel_z*gam->accel_z)); // negative because sensor board is upside down
+
+	//Convert gyro data to rate (we're only using the most 12 significant bits)
+	gyro_x = (sensor_data[GYR_X_H] << 8) | (sensor_data[GYR_X_L]); //* G_GAIN;
+	gyro_y = (sensor_data[GYR_Y_H] << 8 | sensor_data[GYR_Y_L]);// * G_GAIN;
+	gyro_z = (sensor_data[GYR_Z_H] << 8 | sensor_data[GYR_Z_L]);// * G_GAIN;
+
+	//Get the number of degrees
+	//javey: converted to radians to following SI units
+	gam->gyro_xVel_p = ((gyro_x / GYRO_SENS) * DEG_TO_RAD) + GYRO_X_BIAS;
+	gam->gyro_yVel_q = ((gyro_y / GYRO_SENS) * DEG_TO_RAD) + GYRO_Y_BIAS;
+	gam->gyro_zVel_r = ((gyro_z / GYRO_SENS) * DEG_TO_RAD) + GYRO_Z_BIAS;
+
+	return 0;
+}
+
+//////////////////////////////////////////////////
+// LIDAR
+//////////////////////////////////////////////////
+
+int iic0_lidarlite_write(u8 register_addr, u8 data) {
+	u8 buf[] = {register_addr, data};
+
+	return XIicPs_MasterSendPolled_ours(&I2C0, buf, 2, LIDARLITE_DEVICE_ADDR);
+}
+
+int iic0_lidarlite_read(u8* recv_buffer, u8 register_addr, int size) {
+	u8 buf[] = {register_addr};
+	int status = 0;
+
+	status = XIicPs_MasterSendPolled_ours(&I2C0, buf, 1, LIDARLITE_DEVICE_ADDR);
+	status |= XIicPs_MasterRecvPolled(&I2C0, recv_buffer,size, LIDARLITE_DEVICE_ADDR);
+	return status;
+}
+
+int iic0_lidarlite_init() {
+	int status = 0;
+
+	// Device Reset & Wake up with default settings
+	status = iic0_lidarlite_write(0x00, 0x00);
+	usleep(15000);
+
+	// Enable Free Running Mode and distance measurements with correction
+	status |= iic0_lidarlite_write(0x11, 0xff);
+	status |= iic0_lidarlite_write(0x00, 0x04);
+
+	return status;
+}
+
+int iic0_lidarlite_sleep() {
+	return iic0_lidarlite_write(0x65, 0x84);
+}
+
+int iic0_lidarlite_read_distance(lidar_t *lidar) {
+	u8 buf[2];
+	int status = 0;
+
+	// Read the sensor value
+	status = iic0_lidarlite_read(buf, 0x8f, 2);
+	lidar->distance_cm = buf[0] << 8 | buf[1];
+
+	return status;
+}
+
+/*****************************************************************************/
+/**
+* NOTE to MicroCART: This function is originally from the Xilinx library,
+* but we noticed that the original function didn't check for a NACK, which
+* would cause the original polling function to enter an infinite loop in the
+* event of a NACK. Notice that we have added that NACK check at the final
+* while loop of this function.
+*
+*
+* This function initiates a polled mode send in master mode.
+*
+* It sends data to the FIFO and waits for the slave to pick them up.
+* If slave fails to remove data from FIFO, the send fails with
+* time out.
+*
+* @param	InstancePtr is a pointer to the XIicPs instance.
+* @param	MsgPtr is the pointer to the send buffer.
+* @param	ByteCount is the number of bytes to be sent.
+* @param	SlaveAddr is the address of the slave we are sending to.
+*
+* @return
+*		- XST_SUCCESS if everything went well.
+*		- XST_FAILURE if timed out.
+*
+* @note		This send routine is for polled mode transfer only.
+*
+****************************************************************************/
+int XIicPs_MasterSendPolled_ours(XIicPs *InstancePtr, u8 *MsgPtr,
+		 int ByteCount, u16 SlaveAddr)
+{
+	u32 IntrStatusReg;
+	u32 StatusReg;
+	u32 BaseAddr;
+	u32 Intrs;
+
+	/*
+	 * Assert validates the input arguments.
+	 */
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(MsgPtr != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+	Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr);
+
+	BaseAddr = InstancePtr->Config.BaseAddress;
+	InstancePtr->SendBufferPtr = MsgPtr;
+	InstancePtr->SendByteCount = ByteCount;
+
+	XIicPs_SetupMaster(InstancePtr, SENDING_ROLE);
+
+	XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);
+
+	/*
+	 * Intrs keeps all the error-related interrupts.
+	 */
+	Intrs = XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_TX_OVR_MASK |
+			XIICPS_IXR_TO_MASK | XIICPS_IXR_NACK_MASK;
+
+	/*
+	 * Clear the interrupt status register before use it to monitor.
+	 */
+	IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
+	XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
+
+	/*
+	 * Transmit first FIFO full of data.
+	 */
+	TransmitFifoFill(InstancePtr);
+
+	IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
+
+	/*
+	 * Continue sending as long as there is more data and
+	 * there are no errors.
+	 */
+	while ((InstancePtr->SendByteCount > 0) &&
+		((IntrStatusReg & Intrs) == 0)) {
+		StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
+
+		/*
+		 * Wait until transmit FIFO is empty.
+		 */
+		if ((StatusReg & XIICPS_SR_TXDV_MASK) != 0) {
+			IntrStatusReg = XIicPs_ReadReg(BaseAddr,
+					XIICPS_ISR_OFFSET);
+			continue;
+		}
+
+		/*
+		 * Send more data out through transmit FIFO.
+		 */
+		TransmitFifoFill(InstancePtr);
+	}
+
+	/*
+	 * Check for completion of transfer.
+	 */
+	// NOTE for MicroCART: Corrected function. Original left for reference.
+//	while ((XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET) &
+//		XIICPS_IXR_COMP_MASK) != XIICPS_IXR_COMP_MASK);
+	while (!(IntrStatusReg & (Intrs | XIICPS_IXR_COMP_MASK))) {
+		IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
+	}
+
+	/*
+	 * If there is an error, tell the caller.
+	 */
+	if (IntrStatusReg & Intrs) {
+		return XST_FAILURE;
+	}
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/*
+* NOTE to MicroCART: This function is required by the send polling method above,
+* but it was originally static, so we had to copy it word-for-word here.
+*
+* This function prepares a device to transfers as a master.
+*
+* @param	InstancePtr is a pointer to the XIicPs instance.
+*
+* @param	Role specifies whether the device is sending or receiving.
+*
+* @return
+*		- XST_SUCCESS if everything went well.
+*		- XST_FAILURE if bus is busy.
+*
+* @note		Interrupts are always disabled, device which needs to use
+*		interrupts needs to setup interrupts after this call.
+*
+****************************************************************************/
+int XIicPs_SetupMaster(XIicPs *InstancePtr, int Role)
+{
+	u32 ControlReg;
+	u32 BaseAddr;
+	u32 EnabledIntr = 0x0;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+
+	BaseAddr = InstancePtr->Config.BaseAddress;
+	ControlReg = XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET);
+
+
+	/*
+	 * Only check if bus is busy when repeated start option is not set.
+	 */
+	if ((ControlReg & XIICPS_CR_HOLD_MASK) == 0) {
+		if (XIicPs_BusIsBusy(InstancePtr)) {
+			return XST_FAILURE;
+		}
+	}
+
+	/*
+	 * Set up master, AckEn, nea and also clear fifo.
+	 */
+	ControlReg |= XIICPS_CR_ACKEN_MASK | XIICPS_CR_CLR_FIFO_MASK |
+		 	XIICPS_CR_NEA_MASK | XIICPS_CR_MS_MASK;
+
+	if (Role == RECVING_ROLE) {
+		ControlReg |= XIICPS_CR_RD_WR_MASK;
+		EnabledIntr = XIICPS_IXR_DATA_MASK |XIICPS_IXR_RX_OVR_MASK;
+	}else {
+		ControlReg &= ~XIICPS_CR_RD_WR_MASK;
+	}
+	EnabledIntr |= XIICPS_IXR_COMP_MASK | XIICPS_IXR_ARB_LOST_MASK;
+
+	XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, ControlReg);
+
+	XIicPs_DisableAllInterrupts(BaseAddr);
+
+	return XST_SUCCESS;
+}
diff --git a/quad/sw/modular_quad_pid/src/iic_mpu9150_utils.h b/quad/sw/modular_quad_pid/src/iic_utils.h
similarity index 64%
rename from quad/sw/modular_quad_pid/src/iic_mpu9150_utils.h
rename to quad/sw/modular_quad_pid/src/iic_utils.h
index f93b7686b8f62d843b26e5ecaed667ed6b5b08f6..b4185b19da3a9fbf49ee46ea3e592948570a1ed7 100644
--- a/quad/sw/modular_quad_pid/src/iic_mpu9150_utils.h
+++ b/quad/sw/modular_quad_pid/src/iic_utils.h
@@ -11,8 +11,8 @@
  */
 
 
-#ifndef IIC_MPU9150_UTILS_H
-#define IIC_MPU9150_UTILS_H
+#ifndef IIC_UTILS_H
+#define IIC_UTILS_H
 
 
 #include "xbasic_types.h"
@@ -34,11 +34,30 @@
 #define IIC0_INTR_EN			    (0xE0004024)
 #define IIC0_TIMEOUT_REG_ADDR 		(0xE000401C)
 
+//Interrupt Status Register Masks
+#define ARB_LOST       (0x200)
+#define RX_UNF          (0x80)
+#define TX_OVF          (0x40)
+#define RX_OVF          (0x20)
+#define SLV_RDY         (0x10)
+#define TIME_OUT        (0x08)
+#define NACK      		(0x04)
+#define MORE_DAT 	    (0x02)
+#define TRANS_COMPLETE 	(0x01)
+
+#define WRITE_INTR_MASK (ARB_LOST | TIME_OUT | RX_OVF | TX_OVF | NACK)
+#define READ_INTR_MASK (ARB_LOST | TIME_OUT | RX_OVF | RX_UNF | NACK)
+
+// Initialize hardware; Call this FIRST before calling any other functions
+int iic0_init();
+
+///////////////////////////////////////////////////////////////////////////////
 // MPU9150 Sensor Defines (Address is defined on the Sparkfun MPU9150 Datasheet)
+///////////////////////////////////////////////////////////////////////////////
+
 #define MPU9150_DEVICE_ADDR 		0b01101000
 #define MPU9150_COMPASS_ADDR 		0x0C
 
-
 #define ACCEL_GYRO_READ_SIZE 		14		//Bytes
 #define ACCEL_GYRO_BASE_ADDR		0x3B	//Starting register address
 
@@ -70,21 +89,6 @@
 #define MAG_Z_L 4
 #define MAG_Z_H 5
 
-//Interrupt Status Register Masks
-#define ARB_LOST       (0x200)
-#define RX_UNF          (0x80)
-#define TX_OVF          (0x40)
-#define RX_OVF          (0x20)
-#define SLV_RDY         (0x10)
-#define TIME_OUT        (0x08)
-#define NACK      		(0x04)
-#define MORE_DAT 	    (0x02)
-#define TRANS_COMPLETE 	(0x01)
-
-#define WRITE_INTR_MASK (ARB_LOST | TIME_OUT | RX_OVF | TX_OVF | NACK)
-#define READ_INTR_MASK (ARB_LOST | TIME_OUT | RX_OVF | RX_UNF | NACK)
-
-
 // Gyro is configured for +/-2000dps
 // Sensitivity gain is based off MPU9150 datasheet (pg. 11)
 #define GYRO_SENS 16.4
@@ -97,70 +101,34 @@
 #define ACCEL_Y_BIAS	-0.0045f
 #define ACCEL_Z_BIAS	-0.008f
 
-// Initialize hardware; Call this FIRST before calling any other functions
-int initI2C0();
-
-void iic0Write(u8 register_addr, u8 data);
-void iic0Read(u8* recv_buffer, u8 register_addr, int size);
-
+void iic0_mpu9150_write(u8 register_addr, u8 data);
+void iic0_mpu9150_read(u8* recv_buffer, u8 register_addr, int size);
 
 // Wake up the MPU for data collection
 // Configure Gyro/Accel/Mag
-int startMPU9150();
-
-// Put MPU back to sleep
-void stopMPU9150();
-
-void CalcMagSensitivity();
-void ReadMag(gam_t* gam);
-void ReadGyroAccel(gam_t* gam);
-
-int get_gam_reading(gam_t* gam);
-
-
-/////////////
-// Deprecated functions below
-/////////////
-
-
-// Initialize hardware; Call this FIRST before calling any other functions
-void init_iic0();
-
-// Wake up the MPU for data collection
-void start_mpu9150();
+int iic0_mpu9150_start();
 
 // Put MPU back to sleep
-void stop_mpu9150();
-
-
-// Write a byte of data at the given register address on the MPU
-void iic0_write(Xuint16 reg_addr, Xuint8 data);
-
-// Read a single byte at a given register address on the MPU
-Xuint8 iic0_read(Xuint16 reg_addr);
-
-// Read multiple bytes consecutively at a starting register address
-// places the resulting bytes in rv
-int iic0_read_bytes(Xuint8* rv, Xuint16 reg_addr, int bytes);
-
-// Helper function to initialize I2C0 controller on the Zybo board
-// Called by init_iic0
-void iic0_hw_init();
-
+void iic0_mpu9150_stop();
 
-// Clears the interrupt status register
-// Called by configuration functions
-void iic0_clear_intr_status();
+void iic0_mpu9150_calc_mag_sensitivity();
+void iic0_mpu9150_read_mag(gam_t* gam);
+void iic0_mpu9150_read_gyro_accel(gam_t* gam);
 
+int iic0_mpu9150_read_gam(gam_t* gam);
 
+////////////////////////////////////////////////////////////////////////////////////////////
+// LIDAR lite sensor defines (Addressing and registers specified on LIDAR lite v2 datasheet)
+////////////////////////////////////////////////////////////////////////////////////////////
 
-// Configure I2C0 controller on Zybo to receive data
-void iic0_config_ctrl_to_receive();
+#define LIDARLITE_DEVICE_ADDR		0x62
 
-// Configure I2C0 controller to transmit data
-void iic0_config_ctrl_to_transmit();
+int iic0_lidarlite_write(u8 register_addr, u8 data);
+int iic0_lidarlite_read(u8* recv_buffer, u8 register_addr, int size);
 
+int iic0_lidarlite_read_distance(lidar_t *lidar);
 
-void wake_mag();
+int iic0_lidarlite_init();
+int iic0_lidarlite_sleep();
 
-#endif /*IIC_MPU9150_UTILS_H*/
+#endif /*IIC_UTILS_H*/
diff --git a/quad/sw/modular_quad_pid/src/initialize_components.c b/quad/sw/modular_quad_pid/src/initialize_components.c
index 9c79db823252d961b57acd621fb7a09d662f1d2d..91af69ad0b10063fb397bbbe3cd3dd010eaf6391 100644
--- a/quad/sw/modular_quad_pid/src/initialize_components.c
+++ b/quad/sw/modular_quad_pid/src/initialize_components.c
@@ -64,7 +64,7 @@ int initializeAllComponents(user_input_t * user_input_struct, log_t * log_struct
 	}
 
 	// Initialize I2C controller and start the sensor board
-	if (initI2C0() == -1) {
+	if (iic0_init() == -1) {
 		return -1;
 	}
 
diff --git a/quad/sw/modular_quad_pid/src/initialize_components.h b/quad/sw/modular_quad_pid/src/initialize_components.h
index 8a1c66e7545871ba3f35101030d245b0039604f8..151f68296bd554a5d7f47b93691801090c6106ea 100644
--- a/quad/sw/modular_quad_pid/src/initialize_components.h
+++ b/quad/sw/modular_quad_pid/src/initialize_components.h
@@ -12,7 +12,7 @@
 #include "control_algorithm.h"
 #include "platform.h"
 #include "uart.h"
-#include "iic_mpu9150_utils.h"
+#include "iic_utils.h"
 #include "util.h"
 #include "controllers.h"
 
diff --git a/quad/sw/modular_quad_pid/src/sensor.c b/quad/sw/modular_quad_pid/src/sensor.c
index 9f24a3b76f52eef86538396a75cac32f72d8e733..2f1b3e68061f7a35da2406e73172eb73529f35bb 100644
--- a/quad/sw/modular_quad_pid/src/sensor.c
+++ b/quad/sw/modular_quad_pid/src/sensor.c
@@ -11,11 +11,11 @@
 
 int sensor_init(raw_sensor_t * raw_sensor_struct, sensor_t * sensor_struct)
 {
-	if(startMPU9150() == -1)
+	if(iic0_mpu9150_start() == -1)
 		return -1;
 
 	// read sensor board and fill in gryo/accelerometer/magnetometer struct
-	get_gam_reading(&(raw_sensor_struct->gam));
+	iic0_mpu9150_read_gam(&(raw_sensor_struct->gam));
 
 	// Sets the first iteration to be at the accelerometer value since gyro initializes to {0,0,0} regardless of orientation
 	sensor_struct->pitch_angle_filtered = raw_sensor_struct->gam.accel_roll;
@@ -63,7 +63,7 @@ int get_sensors(log_t* log_struct, user_input_t* user_input_struct, raw_sensor_t
 
 
 	// the the sensor board and fill in the readings into the GAM struct
-	get_gam_reading(&(raw_sensor_struct->gam));
+	iic0_mpu9150_read_gam(&(raw_sensor_struct->gam));
 
 	log_struct->gam = raw_sensor_struct->gam;
 
diff --git a/quad/sw/modular_quad_pid/src/sensor.h b/quad/sw/modular_quad_pid/src/sensor.h
index 6561402a1e766dfdd7c11e0f4dcab21f25513fa7..d9592b0ea5f5e1514307541590277ea4a1f8b07b 100644
--- a/quad/sw/modular_quad_pid/src/sensor.h
+++ b/quad/sw/modular_quad_pid/src/sensor.h
@@ -12,7 +12,7 @@
 
 #include "log_data.h"
 #include "user_input.h"
-#include "iic_mpu9150_utils.h"
+#include "iic_utils.h"
 #include "packet_processing.h"
 #include "uart.h"
 
diff --git a/quad/sw/modular_quad_pid/src/type_def.h b/quad/sw/modular_quad_pid/src/type_def.h
index 2157f3b0319920c779c31c40e6c9db4bea68341e..40c0db97f613724b0fa92fef886bc359b0c9bd7f 100644
--- a/quad/sw/modular_quad_pid/src/type_def.h
+++ b/quad/sw/modular_quad_pid/src/type_def.h
@@ -108,6 +108,10 @@ typedef struct {
 
 }gam_t;
 
+typedef struct {
+	unsigned short distance_cm;
+} lidar_t;
+
 typedef struct PID_t {
 	float current_point;	// Current value of the system
 	float setpoint;		// Desired value of the system