From 8811d36e17f0a721fca93c73d001c4cca7aba487 Mon Sep 17 00:00:00 2001
From: Brendan Bartels <bbartels@iastate.edu>
Date: Mon, 27 Feb 2017 09:45:56 -0600
Subject: [PATCH] wip: Separate Xilinx code into hardware interfaces

---
 quad/.gitignore                               |   3 +
 quad/lib/queue/.gitignore                     |   1 +
 quad/lib/queue/Makefile                       |  13 +
 quad/lib/queue/queue.c                        |  68 +++
 quad/lib/queue/queue.h                        |  25 +
 quad/lib/queue/test_queue.c                   | 143 ++++++
 quad/lib/test/Makefile                        |  14 +-
 quad/sw/.gitignore                            |   2 +-
 quad/sw/imu_logger/src/iic_mpu9150_utils.h    |  11 +-
 quad/sw/modular_quad_pid/src/callbacks.c      |  60 +--
 quad/sw/modular_quad_pid/src/callbacks.h      |   4 +-
 quad/sw/modular_quad_pid/src/communication.c  | 222 +++------
 quad/sw/modular_quad_pid/src/communication.h  |  11 +-
 quad/sw/modular_quad_pid/src/controllers.c    |   1 -
 quad/sw/modular_quad_pid/src/gam.h            |   2 -
 .../modular_quad_pid/src/hardware/hw_iface.h  |  50 ++
 .../src/hardware/hw_impl_zybo.h               |  51 ++
 .../src/hardware/hw_impl_zybo_axi_timer.c     |  23 +
 .../src/hardware/hw_impl_zybo_global_timer.c  |  18 +
 .../src/hardware/hw_impl_zybo_i2c.c           | 231 +++++++++
 .../src/hardware/hw_impl_zybo_mio7_led.c      |  22 +
 .../src/hardware/hw_impl_zybo_pwm_input.c     |  32 ++
 .../src/hardware/hw_impl_zybo_pwm_output.c    |  52 ++
 .../src/hardware/hw_impl_zybo_uart.c          | 290 +++++++++++
 quad/sw/modular_quad_pid/src/hardware/queue.c |   1 +
 quad/sw/modular_quad_pid/src/hardware/queue.h |   1 +
 quad/sw/modular_quad_pid/src/iic_utils.c      | 228 +--------
 quad/sw/modular_quad_pid/src/iic_utils.h      |   6 +-
 .../src/initialize_components.c               | 104 ++--
 .../src/initialize_components.h               |   6 +-
 quad/sw/modular_quad_pid/src/log_data.c       |   7 +-
 quad/sw/modular_quad_pid/src/log_data.h       |   2 +-
 quad/sw/modular_quad_pid/src/main.c           |  21 +-
 quad/sw/modular_quad_pid/src/mio7_led.c       |  54 +-
 quad/sw/modular_quad_pid/src/mio7_led.h       |  15 +-
 quad/sw/modular_quad_pid/src/new_log_data.h   |   1 -
 quad/sw/modular_quad_pid/src/old_log_data.h   |   1 -
 .../modular_quad_pid/src/packet_processing.c  |   1 -
 .../src/send_actuator_commands.c              |  15 +-
 .../src/send_actuator_commands.h              |   2 +-
 quad/sw/modular_quad_pid/src/sensor.h         |   1 -
 quad/sw/modular_quad_pid/src/timer.c          |  76 ++-
 quad/sw/modular_quad_pid/src/timer.h          |  13 +-
 quad/sw/modular_quad_pid/src/type_def.h       |  34 +-
 quad/sw/modular_quad_pid/src/uart.c           | 381 --------------
 quad/sw/modular_quad_pid/src/uart.h           |  82 ---
 quad/sw/modular_quad_pid/src/uart_buff.c      | 417 ----------------
 quad/sw/modular_quad_pid/src/uart_buff.h      |  29 --
 quad/sw/modular_quad_pid/src/user_input.c     |  31 +-
 quad/sw/modular_quad_pid/src/user_input.h     |   2 +-
 quad/sw/modular_quad_pid/src/util.c           | 471 +-----------------
 quad/sw/modular_quad_pid/src/util.h           |  97 +---
 52 files changed, 1383 insertions(+), 2065 deletions(-)
 create mode 100644 quad/lib/queue/.gitignore
 create mode 100644 quad/lib/queue/Makefile
 create mode 100644 quad/lib/queue/queue.c
 create mode 100644 quad/lib/queue/queue.h
 create mode 100644 quad/lib/queue/test_queue.c
 create mode 100644 quad/sw/modular_quad_pid/src/hardware/hw_iface.h
 create mode 100644 quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo.h
 create mode 100644 quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_axi_timer.c
 create mode 100644 quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_global_timer.c
 create mode 100644 quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_i2c.c
 create mode 100644 quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_mio7_led.c
 create mode 100644 quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_pwm_input.c
 create mode 100644 quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_pwm_output.c
 create mode 100644 quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_uart.c
 create mode 120000 quad/sw/modular_quad_pid/src/hardware/queue.c
 create mode 120000 quad/sw/modular_quad_pid/src/hardware/queue.h
 delete mode 100644 quad/sw/modular_quad_pid/src/uart.c
 delete mode 100644 quad/sw/modular_quad_pid/src/uart.h
 delete mode 100644 quad/sw/modular_quad_pid/src/uart_buff.c
 delete mode 100644 quad/sw/modular_quad_pid/src/uart_buff.h

diff --git a/quad/.gitignore b/quad/.gitignore
index 53a35d022..47696c7b6 100644
--- a/quad/.gitignore
+++ b/quad/.gitignore
@@ -1,3 +1,6 @@
 zybo_fsbl_bsp/
 zybo_fsbl/
 test.log
+inc/
+obj/
+TAGS
\ No newline at end of file
diff --git a/quad/lib/queue/.gitignore b/quad/lib/queue/.gitignore
new file mode 100644
index 000000000..30d74d258
--- /dev/null
+++ b/quad/lib/queue/.gitignore
@@ -0,0 +1 @@
+test
\ No newline at end of file
diff --git a/quad/lib/queue/Makefile b/quad/lib/queue/Makefile
new file mode 100644
index 000000000..25a22026d
--- /dev/null
+++ b/quad/lib/queue/Makefile
@@ -0,0 +1,13 @@
+OBJ = ../../obj
+INC = ../../inc
+
+queue: queue.h queue.c
+	[ -d $(OBJ) ] ||  mkdir -p $(OBJ)
+	[ -d $(INC) ] || mkdir -p $(INC)
+	gcc -c -o $(OBJ)/libqueue.a queue.c
+	cp queue.h $(INC)/
+
+.PHONY : test
+test: queue test_queue.c
+	gcc -o test test_queue.c -I$(INC) -L$(OBJ) -lqueue -ltest
+	./test
diff --git a/quad/lib/queue/queue.c b/quad/lib/queue/queue.c
new file mode 100644
index 000000000..3eb19fc2d
--- /dev/null
+++ b/quad/lib/queue/queue.c
@@ -0,0 +1,68 @@
+#include "queue.h"
+
+struct Queue queue_create(unsigned int max_size) {
+  struct Queue q;
+  q.buff = malloc(sizeof(char) * (max_size + 1));
+  q.max_size = max_size + 1;
+  q.start = max_size;
+  q.end = 0;
+  return q;
+}
+
+int queue_init(struct Queue *q, unsigned int max_size) {
+  q->buff = malloc(sizeof(unsigned char) * (max_size + 1));
+  if (q->buff == NULL) return -1;
+  q->max_size = max_size + 1; // required for start/end pointers
+  q->start = max_size;
+  q->end = 0;
+  return 0;
+}
+
+void queue_destroy(struct Queue *q) {
+  free(q->buff);
+}
+
+int queue_add(volatile struct Queue *q, unsigned char c) {
+  if (queue_full(q)) {
+    return -1;
+  }
+  q->buff[q->end] = c;
+  q->end += 1;
+  q->end %= q->max_size;
+  return 0;
+}
+
+int queue_remove(volatile struct Queue *q, unsigned char *c) {
+  if (queue_empty(q)) {
+    return -1;
+  }
+  q->start += 1;
+  q->start %= q->max_size;
+  *c = q->buff[q->start];
+  return 0;
+}
+
+int queue_size(volatile struct Queue *q) {
+  return (q->max_size + q->end - q->start - 1) % q->max_size;
+}
+
+int queue_full(volatile struct Queue *q) {
+  return q->start == q->end;;
+}
+
+int queue_empty(volatile struct Queue *q) {
+  return queue_size(q) == 0;
+}
+
+void queue_print(struct Queue *q) {
+  int i;
+  printf("buffer contents:\n");
+  for (i = 0; i < q->max_size; i += 1) {
+    char c = (char) q->buff[i];
+    if (c == 0) c = '-';
+    printf("%c", c);;
+    if (i == q->start) printf("  <- start");
+    if (i == q->end) printf("  <- end");
+    printf("\n");
+  }
+}
diff --git a/quad/lib/queue/queue.h b/quad/lib/queue/queue.h
new file mode 100644
index 000000000..8e3461844
--- /dev/null
+++ b/quad/lib/queue/queue.h
@@ -0,0 +1,25 @@
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+struct Queue {
+  unsigned char *buff;
+  unsigned int max_size;
+  unsigned int start;
+  unsigned int end;
+};
+
+
+struct Queue queue_create(unsigned int max_size);
+int queue_init(struct Queue *q, unsigned int max_size);
+void queue_destory(struct Queue *q);
+int queue_add(volatile struct Queue *q, unsigned char c);
+int queue_remove(volatile struct Queue *q, unsigned char *c);
+int queue_size(volatile struct Queue *q);
+int queue_full(volatile struct Queue *q);
+int queue_empty(volatile struct Queue *q);
+void queue_print(struct Queue *q);
+
+#endif
diff --git a/quad/lib/queue/test_queue.c b/quad/lib/queue/test_queue.c
new file mode 100644
index 000000000..58b9edc8f
--- /dev/null
+++ b/quad/lib/queue/test_queue.c
@@ -0,0 +1,143 @@
+#include "test.h"
+#include "queue.h"
+
+int test_add() {
+  puts("---");
+  puts("test_add");
+  int failed = 0;
+  struct Queue *q = malloc(sizeof(struct Queue));
+  queue_init(q, 5);
+  puts("initialized");
+  unsigned char c;
+  failed = failed || queue_add(q, 'a');
+  return failed;
+}
+
+int test_size() {
+  puts("---");
+  puts("test_size");
+  int failed = 0;
+  struct Queue *q = malloc(sizeof(struct Queue));
+  queue_init(q, 4);
+  unsigned char c;
+  failed = failed || queue_size(q) != 0;
+  printf("size: %d\n", queue_size(q));
+  queue_print(q);
+
+  queue_add(q, 'a');
+
+  printf("size: %d\n", queue_size(q));
+  queue_print(q);
+  failed = failed || queue_size(q) != 1;
+
+  queue_add(q, 'b');
+
+  printf("size: %d\n", queue_size(q));
+  queue_print(q);
+  failed = failed || queue_size(q) != 2;
+
+  queue_add(q, 'c');
+
+  printf("size: %d\n", queue_size(q));
+  queue_print(q);
+  failed = failed || queue_size(q) != 3;
+
+  queue_add(q, 'd');
+
+  printf("size: %d\n", queue_size(q));
+  queue_print(q);
+  failed = failed || queue_size(q) != 4;
+
+  queue_remove(q, &c);
+  queue_remove(q, &c);
+
+  printf("size: %d\n", queue_size(q));
+  queue_print(q);
+  failed = failed || queue_size(q) != 2;
+
+  queue_add(q, 'e');
+
+  printf("size: %d\n", queue_size(q));
+  queue_print(q);
+  failed = failed || queue_size(q) != 3;
+
+  return failed;
+}
+
+int test_full_when_full() {
+  puts("---");
+  puts("test_full_when_full");
+  int failed = 0;
+  struct Queue *q = malloc(sizeof(struct Queue));
+  queue_init(q, 4);
+  unsigned char c;
+  queue_add(q, 'a');
+  queue_add(q, 'b');
+  queue_add(q, 'c');
+  queue_add(q, 'd');
+  failed = failed || !queue_full(q);
+  return failed;
+}
+
+int test_add_when_full() {
+  puts("---");
+  puts("test_add_when_full");
+  int failed = 0;
+  struct Queue *q = malloc(sizeof(struct Queue));
+  queue_init(q, 4);
+  unsigned char c;
+  queue_add(q, 'a');
+  queue_add(q, 'b');
+  queue_add(q, 'c');
+  queue_add(q, 'd');
+  queue_print(q);
+  failed = failed || !queue_add(q, 'x');
+  queue_remove(q, &c);
+  queue_print(q);
+  failed = failed || !(c == 'a');
+  queue_remove(q, &c);
+  queue_print(q);
+  failed = failed || !(c == 'b');
+  queue_remove(q, &c);
+  queue_print(q);
+  failed = failed || !(c == 'c');
+  queue_remove(q, &c);
+  queue_print(q);
+  failed = failed || !(c == 'd');
+  return failed;
+}
+
+int test_add_over_edge() {
+  int failed = 0;
+  struct Queue *q = malloc(sizeof(struct Queue));
+  queue_init(q, 4);
+  unsigned char c;
+  queue_add(q, 'x');
+  queue_add(q, 'x');
+  queue_remove(q, &c);
+  queue_remove(q, &c);
+  queue_add(q, 'a');
+  queue_add(q, 'b');
+  queue_add(q, 'c');
+  queue_add(q, 'd');
+  queue_print(q);
+  failed = failed || !queue_add(q, 'x');
+  queue_remove(q, &c);
+  failed = failed || !(c == 'a');
+  queue_remove(q, &c);
+  failed = failed || !(c == 'b');
+  queue_remove(q, &c);
+  failed = failed || !(c == 'c');
+  queue_remove(q, &c);
+  failed = failed || !(c == 'd');
+  return failed;
+}
+
+int main() {
+  test(test_add, "test_add");
+  test(test_size, "test_size");
+  test(test_full_when_full, "test_full_when_full");
+  test(test_add_when_full, "test_add_when_full");
+  test(test_add_over_edge, "test_add_over_edge");
+  return test_summary();
+}
diff --git a/quad/lib/test/Makefile b/quad/lib/test/Makefile
index b7b47546a..dc7703f75 100644
--- a/quad/lib/test/Makefile
+++ b/quad/lib/test/Makefile
@@ -1,8 +1,14 @@
-test.o: test.c
-	gcc -c test.c
+OBJ = ../../obj
+INC = ../../inc
 
-example: example.c test.c test.h
-	gcc -g -o example example.c test.c test.h
+test: test.c test.h
+	[ -d $(OBJ) ] || mkdir -p $(OBJ)
+	[ -d $(INC) ] || mkdir -p $(INC)
+	gcc -c -o $(OBJ)/libtest.a test.c
+	cp test.h $(INC)
+
+example: test_lib example.c
+	gcc -g -o example example.c -I$(INC) -L$(OBJ) -ltest
 
 .PHONY: clean
 clean:
diff --git a/quad/sw/.gitignore b/quad/sw/.gitignore
index 97d34666e..250db3108 100644
--- a/quad/sw/.gitignore
+++ b/quad/sw/.gitignore
@@ -2,4 +2,4 @@ SDK.log
 test.log
 .metadata/
 system_bsp/
-
+TAGS
\ No newline at end of file
diff --git a/quad/sw/imu_logger/src/iic_mpu9150_utils.h b/quad/sw/imu_logger/src/iic_mpu9150_utils.h
index 3c9907933..2ccb8cf39 100644
--- a/quad/sw/imu_logger/src/iic_mpu9150_utils.h
+++ b/quad/sw/imu_logger/src/iic_mpu9150_utils.h
@@ -15,9 +15,8 @@
 #define IIC_MPU9150_UTILS_H
 
 
-#include "xbasic_types.h"
-#include "xiicps.h"
 #include "type_def.h"
+#include "hardware/hw_iface.h"
 
 // System configuration registers
 // (Please see Appendix B: System Level Control Registers in the Zybo TRM)
@@ -97,6 +96,8 @@
 #define ACCEL_Y_BIAS	0.009f
 #define ACCEL_Z_BIAS	0.087f
 
+void iic_set_global(struct I2CDriver *given_i2c);
+
 // Initialize hardware; Call this FIRST before calling any other functions
 int initI2C0();
 
@@ -134,14 +135,14 @@ void stop_mpu9150();
 
 
 // Write a byte of data at the given register address on the MPU
-void iic0_write(Xuint16 reg_addr, Xuint8 data);
+void iic0_write(u16 reg_addr, u8 data);
 
 // Read a single byte at a given register address on the MPU
-Xuint8 iic0_read(Xuint16 reg_addr);
+u8 iic0_read(u16 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);
+int iic0_read_bytes(u8* rv, u16 reg_addr, int bytes);
 
 // Helper function to initialize I2C0 controller on the Zybo board
 // Called by init_iic0
diff --git a/quad/sw/modular_quad_pid/src/callbacks.c b/quad/sw/modular_quad_pid/src/callbacks.c
index 36f393434..183ecf854 100644
--- a/quad/sw/modular_quad_pid/src/callbacks.c
+++ b/quad/sw/modular_quad_pid/src/callbacks.c
@@ -1,8 +1,8 @@
 #include "communication.h"
 #include "commands.h"
 #include "type_def.h"
-#include "uart.h"
 #include "computation_graph.h"
+#include "util.h"
 
 /*
  * Static variables used to keep track of packet counts
@@ -16,26 +16,26 @@ static size_t total_payload_received = 0;
 /**
   * Currently does nothing.
   */
-int cb_debug(modular_structs_t *structs)
+int cb_debug(modular_structs_t *structs, metadata_t *meta, u8 *data, u16 length)
 {
 	char buf[255];
 
 	// Get the node ID, parameter ID, parameter value
-	u8 node_id = uart_buff_data_get_u8(0);
+	u8 node_id = data[0];
 	struct computation_graph* graph = structs->parameter_struct.graph;
 	float param_val = graph_get_output(graph, node_id, 0);
 
-	int length = snprintf(buf, sizeof buf, "%f", param_val);
-	send_data(DEBUG_ID, 0, buf, length >= sizeof(buf) ? 255 : length + 1);
+	int len = snprintf(buf, sizeof buf, "%f", param_val);
+	send_data(&structs->hardware_struct.uart, DEBUG_ID, 0, buf, len >= sizeof(buf) ? 255 : length + 1);
 	return 0;
 }
 
 /**
   * counts the number of packet logs.
   */
-int cb_packetlog(modular_structs_t* structs) {
+int cb_packetlog(modular_structs_t* structs, metadata_t *meta, u8 *data, u16 length) {
 	n_msg_received += 1;
-	total_payload_received += uart_buff_data_length();
+	total_payload_received += length;
 	return 0;
 }
 
@@ -43,38 +43,38 @@ int cb_packetlog(modular_structs_t* structs) {
   * Handles a get packet logs request and sends a response
   * with the packet log data.
   */
-int cb_getpacketlogs(modular_structs_t* structs) {
+int cb_getpacketlogs(modular_structs_t* structs, metadata_t *meta, u8 *data, u16 length) {
 	char buf[255];
 
 	// Message logging number of messages received and size of payload received
-	int length = snprintf(buf, sizeof buf, "%d,%d", n_msg_received, total_payload_received);
+	int len = snprintf(buf, sizeof buf, "%d,%d", n_msg_received, total_payload_received);
 
-	send_data(LOG_ID, 0, buf, length >= sizeof(buf) ? 255 : length + 1);
+	send_data(&structs->hardware_struct.uart, LOG_ID, 0, buf, len >= sizeof(buf) ? 255 : len + 1);
 	return 0;
 }
 
 /*
  * Handles receiving new location updates.
  */
-int cb_update(modular_structs_t *structs)
+int cb_update(modular_structs_t *structs, metadata_t *meta, u8 *data, u16 length)
 {
 	//processUpdate(packet, &(structs->raw_sensor_struct.currentQuadPosition));
 
 	quadPosition_t* currentQuadPosition = &(structs->raw_sensor_struct.currentQuadPosition);
 	// Packet must come as [NEARPY], 4 bytes each
-	int packetId = uart_buff_data_get_u32(0);
+	int packetId = build_int(data + 0);
 //	printf("Packet ID: %d\n", packetId);
-	float y_pos = uart_buff_data_get_float(4);
+	float y_pos = build_float(data + 4);
 //	printf("y_pos: %f\n", y_pos);
-	float x_pos = uart_buff_data_get_float(8);
+	float x_pos = build_float(data + 8);
 //	printf("x_pos: %f\n", x_pos);
-	float alt_pos = uart_buff_data_get_float(12);
+	float alt_pos = build_float(data + 12);
 //	printf("alt_pos: %f\n", alt_pos);
-	float roll = uart_buff_data_get_float(16);
+	float roll = build_float(data + 16);
 //	printf("roll: %f\n", roll);
-	float pitch = uart_buff_data_get_float(20);
+	float pitch = build_float(data + 20);
 //	printf("pitch: %f\n", pitch);
-	float yaw = uart_buff_data_get_float(24);
+	float yaw = build_float(data + 24);
 //	printf("yaw: %f\n", yaw);
 
 	currentQuadPosition->packetId = packetId;
@@ -94,7 +94,7 @@ int cb_update(modular_structs_t *structs)
 /**
   * This is called on the ground station to begin sending VRPN to the quad.
   */
-int cb_beginupdate(modular_structs_t *structs) {
+int cb_beginupdate(modular_structs_t *structs, metadata_t *meta, u8 *data, u16 length) {
 	structs->user_input_struct.receivedBeginUpdate = 1;
 	return 0;
 }
@@ -117,10 +117,10 @@ int cb_beginupdate(modular_structs_t *structs) {
   * 
   * Does not send anything in response.
   */
-int cb_setparam(modular_structs_t *structs)
+int cb_setparam(modular_structs_t *structs, metadata_t *meta, u8 *data, u16 length)
 {
 	// Get some of the meta data
-	u16 data_len = uart_buff_data_length();
+	u16 data_len = length;
 	// Check if the data length is correct
 	if (data_len != 6)
 	{
@@ -129,9 +129,9 @@ int cb_setparam(modular_structs_t *structs)
 	struct computation_graph* graph = structs->parameter_struct.graph;
 
 	// Get the node ID, parameter ID, parameter value
-	u8 node_id = uart_buff_data_get_u8(0);
-	u8 param_id = uart_buff_data_get_u8(1);
-	float param_val = uart_buff_data_get_float(2);
+	u8 node_id = data[0];
+	u8 param_id = data[1];
+	float param_val = build_float(data + 2);
 	// Set the value for that parameter on that node
 	graph_set_param_val(graph, node_id, param_id, param_val);
 
@@ -162,11 +162,11 @@ int cb_setparam(modular_structs_t *structs)
   * |       bytes ||      1      |      1      |      4      |
   * |--------------------------------------------------------|
   */
-int cb_getparam(modular_structs_t* structs)
+int cb_getparam(modular_structs_t* structs, metadata_t *meta,  u8 *data, u16 length)
 {
 	// Get some of the meta data
-	u16 data_len = uart_buff_data_length();
-	u16 msg_id = uart_buff_get_u16(3);
+	u16 data_len = length;
+	u16 msg_id = meta->msg_id;
 	// Check if the data length is correct
 	if (data_len != 2)
 	{
@@ -174,8 +174,8 @@ int cb_getparam(modular_structs_t* structs)
 	}
 
 	// Get the controller ID, parameter ID
-	u8 node_id = uart_buff_data_get_u8(0);
-	u8 param_id = uart_buff_data_get_u8(1);
+	u8 node_id = data[0];
+	u8 param_id = data[1];
 	struct computation_graph* graph = structs->parameter_struct.graph;
 	float param_val = graph_get_param_val(graph, node_id, param_id);
 
@@ -190,7 +190,7 @@ int cb_getparam(modular_structs_t* structs)
 	memcpy(&resp_data[2], &param_val, sizeof(param_val));
 
 	// Send the response
-	send_data(RESPPARAM_ID, msg_id, resp_data, sizeof(resp_data));
+	send_data(&structs->hardware_struct.uart, RESPPARAM_ID, msg_id, resp_data, sizeof(resp_data));
 
 	return 0;
 }
diff --git a/quad/sw/modular_quad_pid/src/callbacks.h b/quad/sw/modular_quad_pid/src/callbacks.h
index 7e67ddac5..80d0bbc43 100644
--- a/quad/sw/modular_quad_pid/src/callbacks.h
+++ b/quad/sw/modular_quad_pid/src/callbacks.h
@@ -2,10 +2,10 @@
 #define __callbacks_h
 
 /* Grab some stupid stuff from legacy code */
-
 struct modular_structs;
+struct metadata;
 
 /* Make commands.c happy */
-typedef int (command_cb)(struct modular_structs *structs);
+typedef int (command_cb)(struct modular_structs *, struct metadata *, unsigned char *, unsigned short);
 
 #endif
diff --git a/quad/sw/modular_quad_pid/src/communication.c b/quad/sw/modular_quad_pid/src/communication.c
index bba31571e..54922981a 100644
--- a/quad/sw/modular_quad_pid/src/communication.c
+++ b/quad/sw/modular_quad_pid/src/communication.c
@@ -1,5 +1,5 @@
 #include "communication.h"
-#include "uart_buff.h"
+#include "hardware/hw_iface.h"
 
 #define INTC		XScuGic
 #define COMM_UART_DEVICE_ID		XPAR_PS7_UART_0_DEVICE_ID
@@ -12,6 +12,7 @@
 // plus 128 for a little buffer
 // (bit/s) * (seconds) / (10 bits / byte for UART)
 #define MAX_PACKET_SIZE 256
+#define PACKET_HEADER_SIZE 7
 #define UART_BUF_SIZE (((BAUD_RATE * (DESIRED_USEC_PER_LOOP / 1000) / 1000) / 10) + MAX_PACKET_SIZE + 128)
 
 //#define INTERRUPT_BENCHMARK
@@ -19,154 +20,75 @@
 // Declaration of interrupt handler
 void Handler(void *CallBackRef, u32 Event, unsigned int EventData);
 
-// Pointer to the UART driver instance
-static XUartPs* uartInstPtr;
-
-
-int initUartComms() {
-	uartInstPtr = uart0_init(COMM_UART_DEVICE_ID, BAUD_RATE);
-	// Initialize UART0 (Bluetooth/WiFi)
-	if(!uartInstPtr) {
-		return -1;
-	}
-
-	uart0_clearFIFOs();
-
-	if (uart0_int_init(COMM_UART_INT_IRQ_ID, (Xil_ExceptionHandler) uart_interrupt_handler) != XST_SUCCESS) {
-		return -1;
-	}
-
-
-	/*
-	 * Setup the handlers for the UART that will be called from the
-	 * interrupt context when data has been sent and received, specify
-	 * a pointer to the UART driver instance as the callback reference
-	 * so the handlers are able to access the instance data
-	 */
-	//XUartPs_SetHandler(uartInstPtr, (XUartPs_Handler)Handler, uartInstPtr);
-
-	u32 IntrMask = XUARTPS_IXR_RXFULL | XUARTPS_IXR_RXOVR | XUARTPS_IXR_TOUT;
-
-	XUartPs_SetInterruptMask(uartInstPtr, IntrMask);
-
-
-	/*
-	 * Set the receiver timeout. If it is not set, and the last few bytes
-	 * of data do not trigger the over-water or full interrupt, the bytes
-	 * will not be received. By default it is disabled.
-	 * Timeout duration = RecvTimeout x 4 x Bit Period. 0 disables the
-	 *		timeout function.
-	 *
-	 * The setting of 8 will timeout after 8 x 4 = 32 character times.
-	 * Increase the time out value if baud rate is high, decrease it if
-	 * baud rate is low.
-	 */
-	XUartPs_SetRecvTimeout(uartInstPtr, 8);
-
-	// Second argument is the number of bytes to trigger an interrupt at
-	XUartPs_SetFifoThreshold(uartInstPtr, 48);
-
-	return 0;
+static u8 packet[MAX_PACKET_SIZE];
+static int bytes_recv = 0;
+
+int try_receive_packet(struct UARTDriver *uart) {
+
+  // Find start of packet
+  int attempts = 0;
+  while (bytes_recv == 0) {
+    if (attempts > MAX_PACKET_SIZE) return -1; // keep trying later
+    if (uart->read(uart, &packet[bytes_recv], 1)) return -1; // ran out
+    if (packet[bytes_recv] == 0xBE) bytes_recv += 1;
+    attempts += 1;
+  }
+
+  // Find length bytes in packet
+  while (bytes_recv < PACKET_HEADER_SIZE) {
+    if (uart->read(uart, &packet[bytes_recv++], 1)) return -1; // ran out
+    bytes_recv += 1;
+  }
+
+  // Wait for rest of data plus checksum (+1)
+  int length = (packet[6] << 8 | packet[5]) + PACKET_HEADER_SIZE + 1;
+  while (bytes_recv < length) {
+    if (uart->read(uart, &packet[bytes_recv++], 1)) return -1; // ran out
+    bytes_recv += 1;
+  }
+
+  // Fully recieved a packet
+  return 0;
 }
 
 int process_packet(modular_structs_t *structs) {
-	metadata_t meta_data;
-	// parse metadata
-	meta_data.begin_char = uart_buff_get_u8(0);
-	meta_data.msg_type = uart_buff_get_u16(1);
-	meta_data.msg_id = uart_buff_get_u16(3);
-	meta_data.data_len = uart_buff_get_u16(5);
-	unsigned char packet_checksum = uart_buff_get_u8(7+meta_data.data_len);
-	//unsigned char* packet_data = packet + sizeof(metadata_t);
-
-	// Compute checksum
-	int i;
-	unsigned char calculated_checksum = 0;
-	for(i = 0; i < meta_data.data_len + 7; i++){
-		calculated_checksum ^= uart_buff_get_u8(i);
-	}
-	// Discard if checksum didn't match
-	if(packet_checksum != calculated_checksum) {
-		uart_buff_consume_packet();
-		return -1;
-	}
-
-	// Call appropriate function for packet
-	(* (MessageTypes[meta_data.msg_type].functionPtr))(structs);
-
-	uart_buff_consume_packet();
-
-	return 0;
-
-}
-
-/*
- * Temporarily disables interrupts and returns the interrupt state, for restoring them
- */
-u32 disable_interrupts() {
-	u32 ImrRegister;
-	ImrRegister = XUartPs_ReadReg(uartInstPtr->Config.BaseAddress, XUARTPS_IMR_OFFSET);
-	XUartPs_WriteReg(uartInstPtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, XUARTPS_IXR_MASK);
-	return ImrRegister;
-}
-
-/*
- * Restores the interrupt state, saved from disable_interrupts
- */
-void restore_interrupts(u32 intr_state) {
-	XUartPs_WriteReg(uartInstPtr->Config.BaseAddress, XUARTPS_IER_OFFSET, intr_state);
+  metadata_t meta;
+  // parse metadata
+  meta.begin_char = packet[0];
+  meta.msg_type = packet[2] << 8 | packet[1];
+  meta.msg_id = packet[4] << 8 | packet[3];
+  meta.data_len = packet[6] << 8 | packet[5];
+  unsigned char packet_checksum = packet[7+meta.data_len];
+
+  // Compute checksum
+  int i;
+  unsigned char calculated_checksum = 0;
+  for(i = 0; i < meta.data_len + 7; i++){
+    calculated_checksum ^= packet[i];
+  }
+  // Discard if checksum didn't match
+  if(packet_checksum != calculated_checksum) {
+    return -1;
+  }
+
+  // Call appropriate function for packet
+  (* (MessageTypes[meta.msg_type].functionPtr))(structs,&meta,packet[PACKET_HEADER_SIZE], meta.data_len);
+
+  // Done processing packets, reset
+  bytes_recv = 0;
+
+  return 0;
 }
 
 void process_received(modular_structs_t *structs) {
-	// Parse as many packets as possible
-	while (uart_buff_packet_ready()) {
-		process_packet(structs);
-	}
-}
-
-void uart_interrupt_handler(XUartPs *InstancePtr) {
-	u32 IsrStatus;
-
-	/*
-	 * Read the interrupt ID register to determine which
-	 * interrupt is active
-	 */
-	IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
-				   XUARTPS_IMR_OFFSET);
-
-	IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
-				   XUARTPS_ISR_OFFSET);
-
-	/*
-	* Read the Channel Status Register to determine if there is any data in
-	 * the RX FIFO
-	 */
-
-	u32 CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
-				XUARTPS_SR_OFFSET);
-
-#ifdef INTERRUPT_BENCHMARK
-		u32 start_time = timer_get_count();
-#endif
-
-	while (0 == (CsrRegister & XUARTPS_SR_RXEMPTY) && !uart_buff_full()) {
-		u8 byte = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_FIFO_OFFSET);
-		uart_buff_add_u8(byte);
-		CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_SR_OFFSET);
-	}
-
-#ifdef INTERRUPT_BENCHMARK
-		u32 end_time = timer_get_count();
-		u32 duration = end_time - start_time;
-		send_data(0, 0, 0, (char *) &duration, 8);
-#endif
-
-	// Clear the interrupt status.
-	XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
-			IsrStatus);
+  // Parse as many packets as possible
+  struct UARTDriver *uart = &structs->hardware_struct.uart;
+  while (try_receive_packet(uart)) {
+    process_packet(structs);
+  }
 }
 
-int send_data(u16 type_id, u16 msg_id, char* data, size_t size) {
+int send_data(struct UARTDriver *uart, u16 type_id, u16 msg_id, char* data, size_t size) {
 	//----------------------------------------------------------------------------------------------
 	//	   index||	   0	|	  1	   |	  2		 |	3 & 4 |		 5 & 6		 |	7+	|	end	   |
 	//---------------------------------------------------------------------------------------------|
@@ -175,7 +97,7 @@ int send_data(u16 type_id, u16 msg_id, char* data, size_t size) {
 	//	   bytes||	   1	|	       2             |   2    |        2         | var	|	 1	   |
 	//----------------------------------------------------------------------------------------------
 
-	char formattedHeader[7];
+	unsigned char formattedHeader[PACKET_HEADER_SIZE];
 
 	// Begin Char:
 	formattedHeader[0] = BEGIN_CHAR;
@@ -189,22 +111,20 @@ int send_data(u16 type_id, u16 msg_id, char* data, size_t size) {
 	formattedHeader[5] = size & 0x000000ff;
 	formattedHeader[6] = (size >> 8) & 0x000000ff;
 
-	// Compute checksum while sending
+	// Compute checksum
 	unsigned char packet_checksum = 0;
-
 	int i;
-	for(i = 0; i < 7; i++) {
+	for(i = 0; i < PACKET_HEADER_SIZE; i++) {
 		packet_checksum ^= formattedHeader[i];
-		uart0_sendByte(formattedHeader[i]);
 	}
-	// Send data
 	for (i = 0; i < size; i++) {
 		packet_checksum ^= data[i];
-		uart0_sendByte(data[i]);
 	}
-	//uart0_sendBytes(data, size);
-	// Send checksum
-	uart0_sendByte(packet_checksum);
+
+	// Send header, data, and checksum
+	uart->write(uart, formattedHeader, PACKET_HEADER_SIZE);
+	uart->write(uart, (unsigned char *) data, size);
+	uart->write(uart, &packet_checksum, 1);
 
 	return 0;
 }
diff --git a/quad/sw/modular_quad_pid/src/communication.h b/quad/sw/modular_quad_pid/src/communication.h
index 92c7c86d0..df37a8cda 100644
--- a/quad/sw/modular_quad_pid/src/communication.h
+++ b/quad/sw/modular_quad_pid/src/communication.h
@@ -1,21 +1,14 @@
 #ifndef _COMMUNICATION_H
 #define _COMMUNICATION_H
 
-#include <xuartps.h>
-#include "xparameters.h"
-#include "xscugic.h"
-#include "xil_exception.h"
-
 #include "type_def.h"
-#include "uart.h"
 #include "mio7_led.h"
 #include "timer.h"
 #include "commands.h"
-#include "uart_buff.h"
+#include "hardware/hw_iface.h"
 
 int initUartComms();
 void process_received(modular_structs_t *structs);
-void uart_interrupt_handler(XUartPs *InstancePtr);
-int send_data(u16 type_id, u16 msg_id, char* data, size_t size);
+int send_data(struct UARTDriver *uart, u16 type_id, u16 msg_id, char* data, size_t size);
 
 #endif
diff --git a/quad/sw/modular_quad_pid/src/controllers.c b/quad/sw/modular_quad_pid/src/controllers.c
index 7be7616e1..22f8d5d02 100644
--- a/quad/sw/modular_quad_pid/src/controllers.c
+++ b/quad/sw/modular_quad_pid/src/controllers.c
@@ -12,7 +12,6 @@
 #include "iic_utils.h"
 #include "quadposition.h"
 #include "util.h"
-#include "uart.h"
 #include "sleep.h"
 #include "stdio.h"
 #include <math.h>
diff --git a/quad/sw/modular_quad_pid/src/gam.h b/quad/sw/modular_quad_pid/src/gam.h
index 6c5ed8554..0f4803e8d 100644
--- a/quad/sw/modular_quad_pid/src/gam.h
+++ b/quad/sw/modular_quad_pid/src/gam.h
@@ -1,8 +1,6 @@
 #ifndef _GAM_H
 #define _GAM_H
 
-#include "xbasic_types.h"
-
 //Gyro, accelerometer, and magnetometer data structure
 //Used for reading an instance of the sensor data
 typedef struct {
diff --git a/quad/sw/modular_quad_pid/src/hardware/hw_iface.h b/quad/sw/modular_quad_pid/src/hardware/hw_iface.h
new file mode 100644
index 000000000..a5b7d148e
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/hw_iface.h
@@ -0,0 +1,50 @@
+#ifndef HW_IFACE_H
+#define HW_IFACE_H
+
+struct I2CDriver {
+  void *state;
+  int (*reset)(struct I2CDriver *self);
+  int (*write)(struct I2CDriver *self,
+               unsigned short device_addr,
+               unsigned char *data,
+               unsigned int length);
+  int (*read)(struct I2CDriver *self,
+              unsigned short device_addr,
+              unsigned char *buff,
+              unsigned int length);
+};
+
+struct PWMOutputDriver {
+  void *state;
+  int (*reset)(struct PWMOutputDriver *self);
+  int (*write)(struct PWMOutputDriver *self, unsigned int channel, unsigned long pulse_width_us);
+};
+
+struct PWMInputDriver {
+  void *state;
+  int (*reset)(struct PWMInputDriver *self);
+  int (*read)(struct PWMInputDriver *self, unsigned int channel, unsigned long *pulse_width_us);
+};
+
+struct UARTDriver {
+  void *state;
+  int (*reset)(struct UARTDriver *self);
+  int (*write)(struct UARTDriver *self, unsigned char *data, unsigned int length);
+  int (*read)(struct UARTDriver *self, unsigned char *buff, unsigned int length);
+};
+
+struct TimerDriver {
+  void *state;
+  int (*reset)(struct TimerDriver *self);
+  int (*restart)(struct TimerDriver *self);
+  int (*read)(struct TimerDriver *self, unsigned long *us);
+};
+
+struct LEDDriver {
+  void *state;
+  int (*reset)(struct LEDDriver *self);
+  int (*turn_on)(struct LEDDriver *self);
+  int (*turn_off)(struct LEDDriver *self);
+};
+
+#endif
diff --git a/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo.h b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo.h
new file mode 100644
index 000000000..eb50756d4
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo.h
@@ -0,0 +1,51 @@
+#ifndef HW_IMPL_ZYBO
+#define HW_IMPL_ZYBO
+
+#include "hw_iface.h"
+
+#include <sleep.h>
+#include <stdlib.h>
+#include <xtmrctr.h>
+#include <xgpiops.h>
+#include "xiicps.h"
+#include "xparameters.h"
+#include "xgpiops.h"
+#include "xil_types.h"
+#include "xscugic.h"
+#include "xtime_l.h"
+#include "xuartps.h"
+#include "queue.h"
+
+int zybo_uart_reset(struct UARTDriver *self);
+int zybo_uart_write(struct UARTDriver *self, unsigned char *data, unsigned int length);
+int zybo_uart_read(struct UARTDriver *self, unsigned char *buff, unsigned int length);
+
+int zybo_pwm_output_reset(struct PWMOutputDriver *self);
+int zybo_pwm_output_write(struct PWMOutputDriver *self, unsigned int channel, unsigned long pulse_width_us);
+
+int zybo_pwm_input_reset(struct PWMInputDriver *self);
+int zybo_pwm_input_read(struct PWMInputDriver *self, unsigned int channel, unsigned long *pulse_width_us);
+
+int zybo_i2c_reset(struct I2CDriver *self);
+int zybo_i2c_write(struct I2CDriver *self,
+                   unsigned short device_addr,
+                   unsigned char *data,
+                   unsigned int length);
+int zybo_i2c_read(struct I2CDriver *self,
+                  unsigned short device_addr,
+                  unsigned char *buff,
+                  unsigned int length);
+
+int zybo_global_timer_reset(struct TimerDriver *self);
+int zybo_global_timer_restart(struct TimerDriver *self);
+int zybo_global_timer_read(struct TimerDriver *self, unsigned long *us);
+
+int zybo_axi_timer_reset(struct TimerDriver *self);
+int zybo_axi_timer_restart(struct TimerDriver *self);
+int zybo_axi_timer_read(struct TimerDriver *self, unsigned long *us);
+
+int zybo_led_reset(struct LEDDriver *self);
+int zybo_led_turn_on(struct LEDDriver *self);
+int zybo_led_turn_off(struct LEDDriver *self);
+
+#endif
diff --git a/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_axi_timer.c b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_axi_timer.c
new file mode 100644
index 000000000..399c819fa
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_axi_timer.c
@@ -0,0 +1,23 @@
+#include "hw_impl_zybo.h"
+
+// Apparently, this is number of counts per usec
+#define PL_CLK_CNTS_PER_USEC 100
+
+int zybo_axi_timer_reset(struct TimerDriver *self) {
+  if (self->state == NULL) {
+    self->state = malloc(sizeof(XTmrCtr));
+  }
+  return XTmrCtr_Initialize(self->state, XPAR_AXI_TIMER_0_DEVICE_ID);
+}
+
+int zybo_axi_timer_restart(struct TimerDriver *self) {
+  XTmrCtr_Reset(self->state, 0);
+  XTmrCtr_Start(self->state, 0);
+  return 0;
+}
+
+int zybo_axi_timer_read(struct TimerDriver *self, unsigned long *us) {
+  // Returns the number of useconds
+  *us = XTmrCtr_GetValue(self->state, 0) / PL_CLK_CNTS_PER_USEC;
+  return 0;
+}
diff --git a/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_global_timer.c b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_global_timer.c
new file mode 100644
index 000000000..9f59573df
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_global_timer.c
@@ -0,0 +1,18 @@
+#include "hw_impl_zybo.h"
+
+int zybo_global_timer_reset(struct TimerDriver *self) {
+  // Nothing to initialize
+  return 0;
+}
+
+int zybo_global_timer_restart(struct TimerDriver *self) {
+  XTime_SetTime(0);
+  return 0;
+}
+
+int zybo_global_timer_read(struct TimerDriver *self, unsigned long *us) {
+  XTime time;
+  XTime_GetTime(&time);
+  *us = (time * 1000000) / COUNTS_PER_SECOND; // (ticks)(1000000us/s)(s/ticks)
+  return 0;
+}
diff --git a/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_i2c.c b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_i2c.c
new file mode 100644
index 000000000..c24a2b7a7
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_i2c.c
@@ -0,0 +1,231 @@
+#include "hw_impl_zybo.h"
+
+#define IO_CLK_CONTROL_REG_ADDR	(0xF800012C)
+
+int XIicPs_MasterSendPolled_ours(XIicPs *InstancePtr, u8 *MsgPtr,
+				 int ByteCount, u16 SlaveAddr);
+int XIicPs_SetupMaster(XIicPs *InstancePtr, int Role);
+
+int zybo_i2c_reset(struct I2CDriver *self) {
+  if (self->state == NULL) {
+    self->state = malloc(sizeof(XIicPs));
+  }
+  XIicPs *inst = self->state;
+
+  //Make sure CPU_1x clk is enabled for I2C controller
+  u16 *aper_ctrl = (u16 *) 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
+  XIicPs_Config *i2c_config = XIicPs_LookupConfig(XPAR_PS7_I2C_0_DEVICE_ID);
+  XStatus status = XIicPs_CfgInitialize(inst, 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(inst);
+  XIicPs_SetSClk(inst, 400000);
+
+  return 0;
+}
+
+int zybo_i2c_write(struct I2CDriver *self,
+                   unsigned short device_addr,
+                   unsigned char *data,
+                   unsigned int length) {
+  XIicPs *inst = self->state;
+  return XIicPs_MasterSendPolled_ours(inst, data, length, device_addr);
+}
+
+int zybo_i2c_read(struct I2CDriver *self,
+                  unsigned short device_addr,
+                  unsigned char *buff,
+                  unsigned int length) {
+  XIicPs *inst = self->state;
+  return XIicPs_MasterRecvPolled(inst, buff, length, device_addr);
+}
+
+/*****************************************************************************/
+/**
+* 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/hardware/hw_impl_zybo_mio7_led.c b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_mio7_led.c
new file mode 100644
index 000000000..03a192671
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_mio7_led.c
@@ -0,0 +1,22 @@
+#include "hw_impl_zybo.h"
+
+int zybo_mio7_led_reset(struct LEDDriver *self) {
+  if (self->state == NULL) {
+    self->state = malloc(sizeof(XGpioPs));
+  }
+
+  XGpioPs_Config *ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
+  XGpioPs_CfgInitialize(self->state, ConfigPtr, ConfigPtr->BaseAddr);
+  XGpioPs_SetDirectionPin(self->state, 7, 1);
+  return 0;
+}
+
+int zybo_mio7_led_turn_on(struct LEDDriver *self) {
+  XGpioPs_WritePin(self->state, 7, 0x01);
+  return 0;
+}
+
+int zybo_mio7_led_turn_off(struct LEDDriver *self) {
+  XGpioPs_WritePin(self->state, 7, 0x00);
+  return 0;
+}
diff --git a/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_pwm_input.c b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_pwm_input.c
new file mode 100644
index 000000000..b0c3cd98e
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_pwm_input.c
@@ -0,0 +1,32 @@
+#include "hw_impl_zybo.h"
+
+struct PWMInputDriverState {
+  int *channels[6];
+};
+
+int zybo_pwm_input_reset(struct PWMInputDriver *self) {
+  if (self->state == NULL) {
+    self->state = malloc(sizeof(struct PWMInputDriverState));
+    if (self->state == NULL) {
+      return -1;
+    }
+  }
+
+  // Save the addresses of the input PWM recorders
+  struct PWMInputDriverState *state = self->state;
+  state->channels[0] = (int *) XPAR_PWM_RECORDER_0_BASEADDR;
+  state->channels[1] = (int *) XPAR_PWM_RECORDER_1_BASEADDR;
+  state->channels[2] = (int *) XPAR_PWM_RECORDER_2_BASEADDR;
+  state->channels[3] = (int *) XPAR_PWM_RECORDER_3_BASEADDR;
+  state->channels[4] = (int *) XPAR_PWM_RECORDER_4_BASEADDR;
+  state->channels[5] = (int *) XPAR_PWM_RECORDER_5_BASEADDR;
+  return 0;
+}
+
+int zybo_pwm_input_read(struct PWMInputDriver *self,
+                        unsigned int channel,
+                        unsigned long *pulse_width_us) {
+  struct PWMInputDriverState *state = self->state;
+  *pulse_width_us = (long) *((int *) state->channels[channel]);
+  return 0;
+}
diff --git a/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_pwm_output.c b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_pwm_output.c
new file mode 100644
index 000000000..e4c75bd50
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_pwm_output.c
@@ -0,0 +1,52 @@
+#include "hw_impl_zybo.h"
+
+#define THROTTLE_PULSE_WIDTH_LOW 1000 // us
+#define THROTTLE_PULSE_WIDTH_HIGH 2000 // us
+#define PERIOD_WIDTH 222222 // 100000000 ns / 450
+#define PULSE_WIDTH_ADDR_OFFSET 4
+
+struct PWMOutputDriverState {
+  int *outputs[4];
+};
+
+int zybo_pwm_output_reset(struct PWMOutputDriver *self) {
+  if (self->state == NULL) {
+    self->state = malloc(sizeof(struct PWMOutputDriverState));
+    if (self->state == NULL) {
+      return -1;
+    }
+  }
+  struct PWMOutputDriverState *state = self->state;
+
+  state->outputs[0] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_0_BASEADDR;
+  state->outputs[1] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_1_BASEADDR;
+  state->outputs[2] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_2_BASEADDR;
+  state->outputs[3] = (int *) XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_3_BASEADDR;
+
+  // Set period width of PWM pulse
+  *(state->outputs[0]) = PERIOD_WIDTH;
+  *(state->outputs[1]) = PERIOD_WIDTH;
+  *(state->outputs[2]) = PERIOD_WIDTH;
+  *(state->outputs[3]) = PERIOD_WIDTH;
+
+  // Set a low pulse (1 ms) so that outputs are off
+  *(state->outputs[0] + PULSE_WIDTH_ADDR_OFFSET) = THROTTLE_PULSE_WIDTH_LOW;
+  *(state->outputs[1] + PULSE_WIDTH_ADDR_OFFSET) = THROTTLE_PULSE_WIDTH_LOW;
+  *(state->outputs[2] + PULSE_WIDTH_ADDR_OFFSET) = THROTTLE_PULSE_WIDTH_LOW;
+  *(state->outputs[3] + PULSE_WIDTH_ADDR_OFFSET) = THROTTLE_PULSE_WIDTH_LOW;
+
+  usleep(1000000);
+  return 0;
+}
+
+int zybo_pwm_output_write(struct PWMOutputDriver *self,
+                          unsigned int channel,
+                          unsigned long pulse_width_us) {
+  if (pulse_width_us > THROTTLE_PULSE_WIDTH_HIGH)
+    pulse_width_us = THROTTLE_PULSE_WIDTH_HIGH;
+  if (pulse_width_us < THROTTLE_PULSE_WIDTH_LOW)
+    pulse_width_us = THROTTLE_PULSE_WIDTH_LOW;
+  struct PWMOutputDriverState *state = self->state;
+  *(state->outputs[channel] + PULSE_WIDTH_ADDR_OFFSET) = pulse_width_us;
+  return 0;
+}
diff --git a/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_uart.c b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_uart.c
new file mode 100644
index 000000000..263e4ad9e
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/hw_impl_zybo_uart.c
@@ -0,0 +1,290 @@
+#include "hw_impl_zybo.h"
+
+#define BAUD_RATE 921600
+#define MAX_UART_BUFFER_SIZE 2048
+
+int XUartPs_SetBaudRate_ours(XUartPs *InstancePtr, u32 BaudRate);
+void uart_interrupt_handler(XUartPs *InstancePtr);
+int SetupInterruptSystem(XUartPs *UartInstancePtr, u16 UartIntrId, Xil_ExceptionHandler handler);
+void uart_interrupt_handler(XUartPs *InstancePtr);
+
+// Queue has to be global to be accessible to ISR
+static volatile struct Queue queue;
+static XScuGic xscugic;
+
+int zybo_uart_reset(struct UARTDriver *self) {
+  // Instantiate the Driver state
+  if (self->state == NULL) {
+    self->state = malloc(sizeof(XUartPs));
+    if (self->state == NULL) {
+      return -1;
+    }
+    queue = queue_create(MAX_UART_BUFFER_SIZE);
+  }
+
+  XUartPs *inst = self->state;;
+
+  // Configure XUartPs instance
+  XUartPs_Config* config = XUartPs_LookupConfig(XPAR_PS7_UART_0_DEVICE_ID);
+  if (XUartPs_CfgInitialize(inst, config, config->BaseAddress) != XST_SUCCESS) {
+    return -1;
+  }
+
+  // Set UART Baudrate
+  if(XUartPs_SetBaudRate_ours(inst, BAUD_RATE) != XST_SUCCESS) {
+    return -1;
+  }
+
+  // Clear Tx/Rx FIFOs
+  int* uart_ctrl_reg = (int*) inst->Config.BaseAddress;
+  *uart_ctrl_reg |= 0x00000003; // clear TX & RX
+
+  // Setup Interrupts
+  if (SetupInterruptSystem(inst, XPAR_PS7_UART_0_INTR, (Xil_ExceptionHandler) uart_interrupt_handler) != XST_SUCCESS) {
+    return -1;
+  }
+
+  // Interrupts selected: Rx FIFO threashold reached, RX overflow, timeout
+  u32 IntrMask = XUARTPS_IXR_RXFULL | XUARTPS_IXR_RXOVR | XUARTPS_IXR_TOUT;
+  XUartPs_SetInterruptMask(inst, IntrMask);
+
+  /*
+   * Set the receiver timeout. If it is not set, and the last few bytes
+   * of data do not trigger the over-water or full interrupt, the bytes
+   * will not be received. By default it is disabled.
+   * Timeout duration = RecvTimeout x 4 x Bit Period. 0 disables the
+   * timeout function.
+   *
+   * The setting of 8 will timeout after 8 x 4 = 32 character times.
+   * Increase the time out value if baud rate is high, decrease it if
+   * baud rate is low.
+   */
+  XUartPs_SetRecvTimeout(inst, 8);
+
+  // Second argument is the number of bytes to trigger an interrupt at
+  XUartPs_SetFifoThreshold(inst, 48);
+
+  return 0;
+}
+
+int zybo_uart_write(struct UARTDriver *self, unsigned char *data, unsigned int length) {
+  XUartPs *inst = self->state;
+  int i;
+  for (i = 0; i < length; i += 1) {
+    XUartPs_SendByte(inst->Config.BaseAddress, data[i]);
+  }
+
+  return 0;
+}
+
+int zybo_uart_read(struct UARTDriver *self, unsigned char *buff, unsigned int length) {
+  int i = 0;
+  while (queue_remove(&queue, &buff[i]) == 0 && i < length) i += 1;
+  return i;
+}
+
+//This is copied from xuart driver
+/***************************************************/
+
+#define XUARTPS_MAX_BAUD_ERROR_RATE              3      /* max % error allowed */
+int XUartPs_SetBaudRate_ours(XUartPs *InstancePtr, u32 BaudRate)
+{
+  u8 IterBAUDDIV;               /* Iterator for available baud divisor values */
+  u32 BRGR_Value;               /* Calculated value for baud rate generator */
+  u32 CalcBaudRate;     /* Calculated baud rate */
+  u32 BaudError;                /* Diff between calculated and requested baud rate */
+  u32 Best_BRGR = 0;    /* Best value for baud rate generator */
+  u8 Best_BAUDDIV = 0;  /* Best value for baud divisor */
+  u32 Best_Error = 0xFFFFFFFF;
+  u32 PercentError;
+  u32 ModeReg;
+  u32 InputClk;
+
+  /*
+   * Asserts validate the input arguments
+   */
+  Xil_AssertNonvoid(InstancePtr != NULL);
+  Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+  //Xil_AssertNonvoid(BaudRate <= XUARTPS_MAX_RATE);
+  Xil_AssertNonvoid(BaudRate >= XUARTPS_MIN_RATE);
+
+  /*
+   * Make sure the baud rate is not impossilby large.
+   * Fastest possible baud rate is Input Clock / 2.
+   */
+  if ((BaudRate * 2) > InstancePtr->Config.InputClockHz) {
+    return XST_UART_BAUD_ERROR;
+  }
+  /*
+   * Check whether the input clock is divided by 8
+   */
+  ModeReg = XUartPs_ReadReg( InstancePtr->Config.BaseAddress,
+                             XUARTPS_MR_OFFSET);
+
+  InputClk = InstancePtr->Config.InputClockHz;
+  if(ModeReg & XUARTPS_MR_CLKSEL) {
+    InputClk = InstancePtr->Config.InputClockHz / 8;
+  }
+
+  /*
+   * Determine the Baud divider. It can be 4to 254.
+   * Loop through all possible combinations
+   */
+  for (IterBAUDDIV = 4; IterBAUDDIV < 255; IterBAUDDIV++) {
+
+    /*
+     * Calculate the value for BRGR register
+     */
+    BRGR_Value = InputClk / (BaudRate * (IterBAUDDIV + 1));
+
+    /*
+     * Calculate the baud rate from the BRGR value
+     */
+    CalcBaudRate = InputClk/ (BRGR_Value * (IterBAUDDIV + 1));
+
+    /*
+     * Avoid unsigned integer underflow
+     */
+    if (BaudRate > CalcBaudRate) {
+      BaudError = BaudRate - CalcBaudRate;
+    }
+    else {
+      BaudError = CalcBaudRate - BaudRate;
+    }
+
+    /*
+     * Find the calculated baud rate closest to requested baud rate.
+     */
+    if (Best_Error > BaudError) {
+
+      Best_BRGR = BRGR_Value;
+      Best_BAUDDIV = IterBAUDDIV;
+      Best_Error = BaudError;
+    }
+  }
+
+  /*
+   * Make sure the best error is not too large.
+   */
+  PercentError = (Best_Error * 100) / BaudRate;
+  if (XUARTPS_MAX_BAUD_ERROR_RATE < PercentError) {
+    return XST_UART_BAUD_ERROR;
+  }
+
+  /*
+   * Disable TX and RX to avoid glitches when setting the baud rate.
+   */
+  XUartPs_DisableUart(InstancePtr);
+
+  XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XUARTPS_BAUDGEN_OFFSET, Best_BRGR);
+  XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XUARTPS_BAUDDIV_OFFSET, Best_BAUDDIV);
+
+  /*
+   * Enable device
+   */
+  XUartPs_EnableUart(InstancePtr);
+
+  InstancePtr->BaudRate = BaudRate;
+
+  return XST_SUCCESS;
+
+}
+
+void uart_interrupt_handler(XUartPs *InstancePtr) {
+  u32 IsrStatus;
+
+  /*
+   * Read the interrupt ID register to determine which
+   * interrupt is active
+   */
+  IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
+                              XUARTPS_IMR_OFFSET);
+
+  IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
+                               XUARTPS_ISR_OFFSET);
+
+  /*
+   * Read the Channel Status Register to determine if there is any data in
+   * the RX FIFO
+   */
+
+  u32 CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
+                                    XUARTPS_SR_OFFSET);
+
+  while (0 == (CsrRegister & XUARTPS_SR_RXEMPTY) && !queue_full(&queue)) {
+    u8 byte = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_FIFO_OFFSET);
+    queue_add(&queue, byte);
+    CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_SR_OFFSET);
+  }
+
+  // Clear the interrupt status.
+  XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
+                   IsrStatus);
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets up the interrupt system so interrupts can occur for the
+* Uart. This function is application-specific.
+*
+* @param	IntcInstancePtr is a pointer to the instance of the INTC.
+* @param	UartInstancePtr contains a pointer to the instance of the UART
+*		driver which is going to be connected to the interrupt
+*		controller.
+* @param	UartIntrId is the interrupt Id and is typically
+*		XPAR_<UARTPS_instance>_INTR value from xparameters.h.
+*
+* @return	XST_SUCCESS if successful, otherwise XST_FAILURE.
+*
+* @note		None.
+*
+****************************************************************************/
+int SetupInterruptSystem(XUartPs *UartInstancePtr, u16 UartIntrId, Xil_ExceptionHandler handler)
+{
+	int Status;
+
+	XScuGic_Config *IntcConfig; /* Config for interrupt controller */
+
+	/* Initialize the interrupt controller driver */
+	IntcConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
+	if (NULL == IntcConfig) {
+		return XST_FAILURE;
+	}
+
+	Status = XScuGic_CfgInitialize(&xscugic, IntcConfig,
+					IntcConfig->CpuBaseAddress);
+	if (Status != XST_SUCCESS) {
+		return XST_FAILURE;
+	}
+
+	/*
+	 * Connect the interrupt controller interrupt handler to the
+	 * hardware interrupt handling logic in the processor.
+	 */
+	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
+				(Xil_ExceptionHandler) XScuGic_InterruptHandler,
+				&xscugic);
+
+	/*
+	 * Connect a device driver handler that will be called when an
+	 * interrupt for the device occurs, the device driver handler
+	 * performs the specific interrupt processing for the device
+	 */
+	Status = XScuGic_Connect(&xscugic, UartIntrId,
+				  handler,
+				  (void *) UartInstancePtr);
+	if (Status != XST_SUCCESS) {
+		return XST_FAILURE;
+	}
+
+	/* Enable the interrupt for the device */
+	XScuGic_Enable(&xscugic, UartIntrId);
+
+	/* Enable interrupts */
+	 Xil_ExceptionEnable();
+
+	return XST_SUCCESS;
+}
diff --git a/quad/sw/modular_quad_pid/src/hardware/queue.c b/quad/sw/modular_quad_pid/src/hardware/queue.c
new file mode 120000
index 000000000..6b67b81f5
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/queue.c
@@ -0,0 +1 @@
+../../../../lib/queue/queue.c
\ No newline at end of file
diff --git a/quad/sw/modular_quad_pid/src/hardware/queue.h b/quad/sw/modular_quad_pid/src/hardware/queue.h
new file mode 120000
index 000000000..b9524b354
--- /dev/null
+++ b/quad/sw/modular_quad_pid/src/hardware/queue.h
@@ -0,0 +1 @@
+../../../../lib/queue/queue.h
\ No newline at end of file
diff --git a/quad/sw/modular_quad_pid/src/iic_utils.c b/quad/sw/modular_quad_pid/src/iic_utils.c
index 290d5f9b6..9bbfd82ed 100644
--- a/quad/sw/modular_quad_pid/src/iic_utils.c
+++ b/quad/sw/modular_quad_pid/src/iic_utils.c
@@ -14,44 +14,13 @@
 #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);
+static struct I2CDriver *i2c;
 
+double magX_correction = -1, magY_correction, magZ_correction;
 
-	return 0;
+void iic_set_global(struct I2CDriver *given_i2c) {
+  i2c = given_i2c;
 }
 
 int iic0_mpu9150_start(){
@@ -111,8 +80,7 @@ void iic0_mpu9150_write(u8 register_addr, u8 data){
 		device_addr = MPU9150_COMPASS_ADDR;
 	}
 
-	XIicPs_MasterSendPolled_ours(&I2C0, buf, 2, device_addr);
-
+	i2c->write(i2c, device_addr, buf, 2);
 }
 
 void iic0_mpu9150_read(u8* recv_buffer, u8 register_addr, int size){
@@ -130,8 +98,8 @@ void iic0_mpu9150_read(u8* recv_buffer, u8 register_addr, int size){
 	}
 
 
-	XIicPs_MasterSendPolled_ours(&I2C0, buf, 1, device_addr);
-	XIicPs_MasterRecvPolled(&I2C0, recv_buffer,size,device_addr);
+	i2c->write(i2c, device_addr, buf, 1);
+	i2c->read(i2c, device_addr, recv_buffer, size);
 }
 
 void iic0_mpu9150_calc_mag_sensitivity(){
@@ -241,16 +209,16 @@ int iic0_mpu9150_read_gam(gam_t* gam) {
 
 int iic0_lidarlite_write(u8 register_addr, u8 data) {
 	u8 buf[] = {register_addr, data};
-
-	return XIicPs_MasterSendPolled_ours(&I2C0, buf, 2, LIDARLITE_DEVICE_ADDR);
+	
+	return i2c->write(i2c, LIDARLITE_DEVICE_ADDR, buf, 2);
 }
 
 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);
+	status |= i2c->write(i2c, LIDARLITE_DEVICE_ADDR, buf, 1);
+	status |= i2c->read(i2c, LIDARLITE_DEVICE_ADDR, recv_buffer, size);
 	return status;
 }
 
@@ -282,177 +250,3 @@ int iic0_lidarlite_read_distance(lidar_t *lidar) {
 
 	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_utils.h b/quad/sw/modular_quad_pid/src/iic_utils.h
index 8a8a9a3bb..41673799a 100644
--- a/quad/sw/modular_quad_pid/src/iic_utils.h
+++ b/quad/sw/modular_quad_pid/src/iic_utils.h
@@ -18,6 +18,7 @@
 #include "xbasic_types.h"
 #include "xiicps.h"
 #include "type_def.h"
+#include "hardware/hw_iface.h"
 
 // System configuration registers
 // (Please see Appendix B: System Level Control Registers in the Zybo TRM)
@@ -48,9 +49,6 @@
 #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)
 ///////////////////////////////////////////////////////////////////////////////
@@ -101,6 +99,8 @@ int iic0_init();
 #define ACCEL_Y_BIAS	0.009f
 #define ACCEL_Z_BIAS	0.087f
 
+void iic_set_global(struct I2CDriver *given_i2c);
+
 void iic0_mpu9150_write(u8 register_addr, u8 data);
 void iic0_mpu9150_read(u8* recv_buffer, u8 register_addr, int size);
 
diff --git a/quad/sw/modular_quad_pid/src/initialize_components.c b/quad/sw/modular_quad_pid/src/initialize_components.c
index 91af69ad0..7328e381a 100644
--- a/quad/sw/modular_quad_pid/src/initialize_components.c
+++ b/quad/sw/modular_quad_pid/src/initialize_components.c
@@ -15,19 +15,20 @@ extern int Xil_AssertWait;
 
 int protection_loops(modular_structs_t *structs)
 {
-	int rc_commands[6]; // 6 "receiver_input" elements: Throttle, Pitch, Roll, Yaw, Gear, and Flap
-
-	read_rec_all(rc_commands);
+	u32 rc_commands[6]; // 6 "receiver_input" elements: Throttle, Pitch, Roll, Yaw, Gear, and Flap
+	
+	struct PWMInputDriver *pwm_inputs = &structs->hardware_struct.pwm_inputs;
+	read_rec_all(pwm_inputs, rc_commands);
 
 	// wait for RC receiver to connect to transmitter
 	while(rc_commands[THROTTLE] < 75000)
-		read_rec_all(rc_commands);
+	  read_rec_all(pwm_inputs, rc_commands);
 
 	// wait until throttle is low and the gear switch is engaged (so you don't immediately break out of the main loop below)
 	// also wait for the flight mode to be set to manual
 	while(rc_commands[THROTTLE] > 125000 || read_kill(rc_commands[GEAR]) || !read_flap(rc_commands[FLAP])) {
 		process_received(structs);
-		read_rec_all(rc_commands);
+		read_rec_all(pwm_inputs, rc_commands);
 	}
 
 	// let the pilot/observers know that the quad is now active
@@ -36,49 +37,60 @@ int protection_loops(modular_structs_t *structs)
 	return 0;
 }
 
-int initializeAllComponents(user_input_t * user_input_struct, log_t * log_struct, raw_sensor_t * raw_sensor_struct,
-		sensor_t * sensor_struct, setpoint_t * setpoint_struct, parameter_t * parameter_struct, user_defined_t *user_defined_struct,
-		raw_actuator_t * raw_actuator_struct, actuator_command_t * actuator_command_struct)
-{
-    // Turn off LED 7 to let observers know that the quad is not yet active
-	MIO7_led_off();
-
-	// Initialize the controller
-	control_algorithm_init(parameter_struct);
-
-	// Initialize the logging
-	initialize_logging(log_struct, parameter_struct);
-
-	// Xilinx given initialization
-	init_platform();
-
-
-	// Initialize loop timers
-	if (timer_init()) {
-		return -1;
-	}
-
-	// Initialize UART0 (Bluetooth)
-	if (initUartComms()) {
-		return -1;
-	}
-
-	// Initialize I2C controller and start the sensor board
-	if (iic0_init() == -1) {
-		return -1;
-	}
-
-	// Initialize PWM Recorders and Motor outputs
-	pwm_init();
-
-	//manual flight mode
-	user_defined_struct->flight_mode = MANUAL_FLIGHT_MODE;
+int init_structs(modular_structs_t *structs) {
+  struct LEDDriver *mio7_led = &structs->hardware_struct.mio7_led;
+  if (mio7_led->reset(mio7_led)) return -1;
+  mio7_init_global(mio7_led);
+  // Turn off LED 7 to let observers know that the quad is not yet active
+
+  mio7_led->turn_off(mio7_led);
+
+  // Initialize the controller
+  control_algorithm_init(&structs->parameter_struct);
+
+  // Xilinx given initialization
+  init_platform();
+
+  // Initialize loop timers
+  struct TimerDriver *global_timer = &structs->hardware_struct.global_timer;
+  struct TimerDriver *axi_timer = &structs->hardware_struct.axi_timer;
+  if (global_timer->reset(global_timer)) {
+    return -1;
+  }
+  if (axi_timer->reset(axi_timer)) {
+    return -1;
+  }
+  timer_init_globals(global_timer, axi_timer);
+
+  // Initialize UART0
+  struct UARTDriver *uart = &structs->hardware_struct.uart;
+  if (uart->reset(uart)) {
+    return -1;
+  }
+
+  // Initialize I2C controller and start the sensor board
+  struct I2CDriver *i2c = &structs->hardware_struct.i2c;
+  if (i2c->reset(i2c)) {
+    return -1;
+  }
+  iic_set_global(i2c);
+
+  // Initialize PWM Recorders and Motor outputs
+  struct PWMInputDriver *pwm_inputs = &structs->hardware_struct.pwm_inputs;
+  if (pwm_inputs->reset(pwm_inputs)) return -1;
+  struct PWMOutputDriver *pwm_outputs = &structs->hardware_struct.pwm_outputs;
+  if (pwm_outputs->reset(pwm_outputs)) return -1;
+
+  // Initialize sensors
+
+  //manual flight mode
+  structs->user_defined_struct.flight_mode = MANUAL_FLIGHT_MODE;
 
 #ifndef BENCH_TEST
-	// Get the first loop data from accelerometer for the gyroscope to use
-	if(sensor_init(raw_sensor_struct, sensor_struct) == -1)
-		return -1;
+  // Get the first loop data from accelerometer for the gyroscope to use
+  if(sensor_init(&structs->raw_sensor_struct, &structs->sensor_struct) == -1)
+    return -1;
 #endif
 
-	return 0;
+  return 0;
 }
diff --git a/quad/sw/modular_quad_pid/src/initialize_components.h b/quad/sw/modular_quad_pid/src/initialize_components.h
index 151f68296..aa2c0e962 100644
--- a/quad/sw/modular_quad_pid/src/initialize_components.h
+++ b/quad/sw/modular_quad_pid/src/initialize_components.h
@@ -11,9 +11,9 @@
 #include "timer.h"
 #include "control_algorithm.h"
 #include "platform.h"
-#include "uart.h"
 #include "iic_utils.h"
 #include "util.h"
+#include "type_def.h"
 #include "controllers.h"
 
 /**
@@ -35,9 +35,7 @@ int protection_loops(modular_structs_t *structs);
  *      error message
  *
  */
-int initializeAllComponents(user_input_t * user_input_struct, log_t * log_struct, raw_sensor_t * raw_sensor_struct,
-		sensor_t * sensor_struct, setpoint_t * setpoint_struct, parameter_t * parameter_struct, user_defined_t *user_defined_struct,
-		raw_actuator_t * raw_actuator_struct, actuator_command_t * actuator_command_struct);
+int init_structs(modular_structs_t *structs);
 
 #endif /* INITALIZE_COMPONENTS_H_ */
 
diff --git a/quad/sw/modular_quad_pid/src/log_data.c b/quad/sw/modular_quad_pid/src/log_data.c
index 5af76302b..ee106bef6 100644
--- a/quad/sw/modular_quad_pid/src/log_data.c
+++ b/quad/sw/modular_quad_pid/src/log_data.c
@@ -10,7 +10,6 @@
 #include <string.h>
 #include "PID.h"
 #include "type_def.h"
-#include "uart.h"
 #include "sleep.h"
 #include "log_data.h"
 #include "communication.h"
@@ -123,7 +122,7 @@ int log_data(log_t* log_struct, parameter_t* ps)
  * TODO: This should probably be transmitting in binary instead of ascii
  */
 
-void printLogging(log_t* log_struct, parameter_t* ps){
+void printLogging(hardware_t *hardware_struct, log_t* log_struct, parameter_t* ps){
 	if (arrayIndex == 0) {
 		// Don't send any logs if nothing was logged
 		return;
@@ -162,13 +161,13 @@ void printLogging(log_t* log_struct, parameter_t* ps){
 	strcat(buf,header1);
 	strcat(buf,header2);
 
-	send_data(LOG_ID, 0, buf, strlen(buf));
+	send_data(&hardware_struct->uart, LOG_ID, 0, buf, strlen(buf));
 
 	/*************************/
 	/* print & send log data */
 	for(i = 0; i < arrayIndex; i++){
 		int size = format_log(i, log_struct, buf);
-		send_data(LOG_ID, 0, buf, size);
+		send_data(&hardware_struct->uart, LOG_ID, 0, buf, size);
 	}
 
 	char data[1] = {0}; // 1 byte to make compilers happy
diff --git a/quad/sw/modular_quad_pid/src/log_data.h b/quad/sw/modular_quad_pid/src/log_data.h
index 0db1751ba..baa21990c 100644
--- a/quad/sw/modular_quad_pid/src/log_data.h
+++ b/quad/sw/modular_quad_pid/src/log_data.h
@@ -47,7 +47,7 @@ void addParamToLog(log_t* log_struct, int controller_id, int param_id);
  /**
   * Prints all the log information.
   */
- void printLogging(log_t* log_struct, parameter_t* ps);
+ void printLogging(hardware_t *hardware_struct, log_t* log_struct, parameter_t* ps);
 
  /**
   * Resets and clears logged data
diff --git a/quad/sw/modular_quad_pid/src/main.c b/quad/sw/modular_quad_pid/src/main.c
index 52f8c0a83..f06bab8c9 100644
--- a/quad/sw/modular_quad_pid/src/main.c
+++ b/quad/sw/modular_quad_pid/src/main.c
@@ -15,6 +15,7 @@
 #include "actuator_command_processing.h"
 #include "send_actuator_commands.h"
 #include "update_gui.h"
+#include "communication.h"
 
 //#define BENCH_TEST
 //#define UART_BENCHMARK
@@ -28,9 +29,7 @@ int main()
 	// Initialize all required components and structs:
 	// Uart, PWM receiver/generator, I2C, Sensor Board
 	// Xilinx Platform, Loop Timer, Control Algorithm
-	int init_error = initializeAllComponents(&(structs.user_input_struct), &(structs.log_struct),
-			&(structs.raw_sensor_struct), &(structs.sensor_struct), &(structs.setpoint_struct), &(structs.parameter_struct),
-			&(structs.user_defined_struct), &(structs.raw_actuator_struct), &(structs.actuator_command_struct));
+	int init_error = init_structs(&(structs));
 
 	if (init_error != 0) {
 		return -1;
@@ -72,7 +71,7 @@ int main()
 
 #ifndef BENCH_TEST
 		// Get the user input and put it into user_input_struct
-		get_user_input(&(structs.log_struct), &(structs.user_input_struct));
+		get_user_input(&(structs.hardware_struct), &(structs.log_struct), &(structs.user_input_struct));
 
 		// Get data from the sensors and put it into raw_sensor_struct
 		get_sensors(&(structs.log_struct), &(structs.user_input_struct), &(structs.raw_sensor_struct));
@@ -86,7 +85,7 @@ int main()
 					&(structs.parameter_struct), &(structs.user_defined_struct), &(structs.actuator_command_struct), &structs);
 
 			// send the actuator commands
-			send_actuator_commands(&(structs.log_struct), &(structs.actuator_command_struct));
+			send_actuator_commands(&(structs.hardware_struct.pwm_outputs), &(structs.log_struct), &(structs.actuator_command_struct));
 		}
 		else {
 			pwm_kill();
@@ -125,18 +124,16 @@ int main()
 		}
 
 		if (this_kill_condition == 1 && last_kill_condition == 0) {
-			// Just disabled
-			printLogging(&(structs.log_struct), &(structs.parameter_struct));
-			resetLogging();
-			MIO7_led_off();
+		  // Just disabled
+		  printLogging(&structs.hardware_struct, &(structs.log_struct), &(structs.parameter_struct));
+		  resetLogging();
+		  MIO7_led_off();
 		}
 
 		last_kill_condition = this_kill_condition;
 	}
 
-	pwm_kill();
-
-
+	kill_motors();
 
 	flash_MIO_7_led(10, 100);
 
diff --git a/quad/sw/modular_quad_pid/src/mio7_led.c b/quad/sw/modular_quad_pid/src/mio7_led.c
index 4742add5b..1da5ad79f 100644
--- a/quad/sw/modular_quad_pid/src/mio7_led.c
+++ b/quad/sw/modular_quad_pid/src/mio7_led.c
@@ -5,49 +5,29 @@
  *      Author: Amy Seibert
  */
  
- #include "mio7_led.h"
- 
-void flash_MIO_7_led(int how_many_times, int ms_between_flashes)
-{
-	if(how_many_times <= 0)
-		return;
-
-	while(how_many_times)
-	{
-		MIO7_led_on();
+#include "mio7_led.h"
 
-		usleep(ms_between_flashes * 500);
+static struct LEDDriver *mio7_led;
 
-		MIO7_led_off();
-
-		usleep(ms_between_flashes * 500);
-
-		how_many_times--;
-	}
+void mio7_init_global(struct LEDDriver *given_mio7_led) {
+  mio7_led = given_mio7_led;
 }
 
-void MIO7_led_off()
+void flash_MIO_7_led(int how_many_times, int ms_between_flashes)
 {
-	XGpioPs Gpio;
-
-	XGpioPs_Config * ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
-	XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
-
-	XGpioPs_SetDirectionPin(&Gpio, 7, 1);
-
-	// Disable LED
-	XGpioPs_WritePin(&Gpio, 7, 0x00);
+  int i;
+  for (i = 0; i < how_many_times; i += 1) {
+    mio7_led->turn_on(mio7_led);
+    usleep(ms_between_flashes * 500);
+    mio7_led->turn_off(mio7_led);
+    usleep(ms_between_flashes * 500);
+  }
 }
 
-void MIO7_led_on()
-{
-	XGpioPs Gpio;
 
-	XGpioPs_Config * ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
-	XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
-
-	XGpioPs_SetDirectionPin(&Gpio, 7, 1);
-
-	// Enable LED
-	XGpioPs_WritePin(&Gpio, 7, 0x01);
+void MIO7_led_on() {
+  mio7_led->turn_on(mio7_led);
+}
+void MIO7_led_off() {
+  mio7_led->turn_off(mio7_led);
 }
diff --git a/quad/sw/modular_quad_pid/src/mio7_led.h b/quad/sw/modular_quad_pid/src/mio7_led.h
index 2517f6241..157a04691 100644
--- a/quad/sw/modular_quad_pid/src/mio7_led.h
+++ b/quad/sw/modular_quad_pid/src/mio7_led.h
@@ -9,8 +9,8 @@
 #define MIO7_LED_H_
  
 #include <stdio.h>
-#include <xgpiops.h>
 #include "sleep.h"
+#include "hardware/hw_iface.h"
 
 /**
  * @brief 
@@ -25,18 +25,9 @@
  */
 void flash_MIO_7_led(int how_many_times, int ms_between_flashes);
 
-/**
- * @brief 
- *      Turns off MIO7 LED. 
- *
- */
+void mio7_init_global(struct LEDDriver *given_mio7_led);
+void MIO7_led_on();
 void MIO7_led_off();
 
-/**
- * @brief 
- *      Turns on MIO7 LED. 
- *
- */
-void MIO7_led_on();
 
 #endif /* MIO7_LED_H_ */
diff --git a/quad/sw/modular_quad_pid/src/new_log_data.h b/quad/sw/modular_quad_pid/src/new_log_data.h
index 932eb1a92..13e713a9e 100644
--- a/quad/sw/modular_quad_pid/src/new_log_data.h
+++ b/quad/sw/modular_quad_pid/src/new_log_data.h
@@ -13,7 +13,6 @@
 #include <string.h>
 #include "PID.h"
 #include "type_def.h"
-#include "uart.h"
 #include "sleep.h"
 #include "communication.h"
 
diff --git a/quad/sw/modular_quad_pid/src/old_log_data.h b/quad/sw/modular_quad_pid/src/old_log_data.h
index 932eb1a92..13e713a9e 100644
--- a/quad/sw/modular_quad_pid/src/old_log_data.h
+++ b/quad/sw/modular_quad_pid/src/old_log_data.h
@@ -13,7 +13,6 @@
 #include <string.h>
 #include "PID.h"
 #include "type_def.h"
-#include "uart.h"
 #include "sleep.h"
 #include "communication.h"
 
diff --git a/quad/sw/modular_quad_pid/src/packet_processing.c b/quad/sw/modular_quad_pid/src/packet_processing.c
index c6764a00b..5dc8df320 100644
--- a/quad/sw/modular_quad_pid/src/packet_processing.c
+++ b/quad/sw/modular_quad_pid/src/packet_processing.c
@@ -5,7 +5,6 @@
  *      Author: ucart
  */
 #include "packet_processing.h"
-#include "uart.h"
 #include "type_def.h"
 #include "sleep.h"
 #include "util.h"
diff --git a/quad/sw/modular_quad_pid/src/send_actuator_commands.c b/quad/sw/modular_quad_pid/src/send_actuator_commands.c
index 3ef6f1a87..efc4e44f7 100644
--- a/quad/sw/modular_quad_pid/src/send_actuator_commands.c
+++ b/quad/sw/modular_quad_pid/src/send_actuator_commands.c
@@ -8,13 +8,12 @@
 #include "send_actuator_commands.h"
 #include "util.h"
  
-int send_actuator_commands(log_t* log_struct, actuator_command_t* actuator_command_struct)
-{
-	int i;
-	// write the PWMs to the motors
-	for (i = 0; i < 4; i++)
-		pwm_write_channel(actuator_command_struct->pwms[i], i);
+int send_actuator_commands(struct PWMOutputDriver *pwm_outputs, log_t* log_struct, actuator_command_t* actuator_command_struct) {
+  int i;
+  // write the PWMs to the motors
+  for (i = 0; i < 4; i++) {
+    pwm_outputs->write(pwm_outputs, i, actuator_command_struct->pwms[i]);
+  }
 
-    return 0;
+  return 0;
 }
- 
diff --git a/quad/sw/modular_quad_pid/src/send_actuator_commands.h b/quad/sw/modular_quad_pid/src/send_actuator_commands.h
index ca337ad7b..3f6fb0fc8 100644
--- a/quad/sw/modular_quad_pid/src/send_actuator_commands.h
+++ b/quad/sw/modular_quad_pid/src/send_actuator_commands.h
@@ -27,6 +27,6 @@
  *      error message
  *
  */
-int send_actuator_commands(log_t* log_struct, actuator_command_t* actuator_command_struct);
+int send_actuator_commands(struct PWMOutputDriver *pwm_outputs, log_t* log_struct, actuator_command_t* actuator_command_struct);
 
 #endif /* SEND_ACTUATOR_COMMANDS_H_ */
diff --git a/quad/sw/modular_quad_pid/src/sensor.h b/quad/sw/modular_quad_pid/src/sensor.h
index d9592b0ea..45791a5aa 100644
--- a/quad/sw/modular_quad_pid/src/sensor.h
+++ b/quad/sw/modular_quad_pid/src/sensor.h
@@ -14,7 +14,6 @@
 #include "user_input.h"
 #include "iic_utils.h"
 #include "packet_processing.h"
-#include "uart.h"
 
 /**
  * @brief
diff --git a/quad/sw/modular_quad_pid/src/timer.c b/quad/sw/modular_quad_pid/src/timer.c
index c82b373a5..29b697b5e 100644
--- a/quad/sw/modular_quad_pid/src/timer.c
+++ b/quad/sw/modular_quad_pid/src/timer.c
@@ -11,67 +11,55 @@
 #include "xtime_l.h"
 #include <xtmrctr.h>
 
-static XTime before = 0;
-static XTime after = 0;
-static XTmrCtr axi_timer;
-static float LOOP_TIME;
-static float time_stamp = 0;
+u32 before = 0, after = 0;
+float LOOP_TIME;
+float time_stamp = 0;
 
-int timer_init()
-{
+struct TimerDriver *global_timer;
+struct TimerDriver *axi_timer;
 
-	// using a axi_timer core because we've had problems with the Global Timer
-	return XTmrCtr_Initialize(&axi_timer, XPAR_AXI_TIMER_0_DEVICE_ID);
+void timer_init_globals(struct TimerDriver *given_global_timer, struct TimerDriver *given_axi_timer) {
+  global_timer = given_global_timer;
+  axi_timer = given_axi_timer;
 }
 
 int timer_start_loop()
 {
-	//timing code
-	LOOP_TIME = ((float)(after - before)) / ((float) COUNTS_PER_SECOND);
-	XTime_GetTime(&before);
-	XTmrCtr_Reset(&axi_timer, 0);
-	XTmrCtr_Start(&axi_timer, 0);
-
-	return 0;
+  //timing code
+  LOOP_TIME = ((float)(after - before));
+  global_timer->read(global_timer, &before);
+  axi_timer->restart(axi_timer);
+  return 0;
 }
 
 int timer_end_loop(log_t *log_struct)
 {
-	// get number of useconds its taken to run the loop thus far
-	int usec_loop = XTmrCtr_GetValue(&axi_timer, 0) / (PL_CLK_CNTS_PER_USEC);
-
-	// attempt to make each loop run for the same amount of time
-	while(usec_loop < DESIRED_USEC_PER_LOOP)
-	{
-		usec_loop = XTmrCtr_GetValue(&axi_timer, 0) / (PL_CLK_CNTS_PER_USEC);
-	}
-
-//	static int counter = 0;
-//	counter++;
-//	if(counter % 50 == 0)
-//		printf("usec_loop: %d\n", usec_loop);
-
-	//timing code
-	XTime_GetTime(&after);
-	time_stamp += LOOP_TIME;
-	XTmrCtr_Stop(&axi_timer, 0);
+  // get number of useconds its taken to run the loop thus far
+  u32 usec_loop;
+  axi_timer->read(axi_timer, &usec_loop);
 
-	// for timing debugging, its a separate hardware PL timer not associated with the PS
-	// used this to compare to the PS clock to make sure the timing matched
-//	float axi_timer_val = ((float)XTmrCtr_GetValue(&axi_timer, 0)) / ((float)100000000);
+  // attempt to make each loop run for the same amount of time
+  while(usec_loop < DESIRED_USEC_PER_LOOP) {
+    axi_timer->read(axi_timer, &usec_loop);
+  }
 
+  //timing code
+  global_timer->read(global_timer, &after);
+  time_stamp += LOOP_TIME;
 
-	// Log the timing information
-	log_struct->time_stamp = time_stamp;
-	log_struct->time_slice = LOOP_TIME;
+  // Log the timing information
+  log_struct->time_stamp = time_stamp;
+  log_struct->time_slice = LOOP_TIME;
 
-	return 0;
+  return 0;
 }
 
 float get_last_loop_time() {
-	return LOOP_TIME;
+  return LOOP_TIME;
 }
 
-uint32_t timer_get_count() {
-	return XTmrCtr_GetValue(&axi_timer, 0);
+u32 timer_get_count() {
+  u32 time;
+  return axi_timer->read(axi_timer, &time);
+  return time;
 }
diff --git a/quad/sw/modular_quad_pid/src/timer.h b/quad/sw/modular_quad_pid/src/timer.h
index 5ebc293e8..c12a2f6eb 100644
--- a/quad/sw/modular_quad_pid/src/timer.h
+++ b/quad/sw/modular_quad_pid/src/timer.h
@@ -13,18 +13,6 @@
 // desired loop time is not guaranteed (its possible that the loop may take longer than desired)
 #define DESIRED_USEC_PER_LOOP 5000 // gives 5ms loops
 
-#define PL_CLK_CNTS_PER_USEC 100
-
-/**
- * @brief
- *      Initializes the items necessary for loop timing.
- *
- * @return
- *      error message
- *
- */
-int timer_init();
-
 /**
  * @brief
  *      Does processing of the loop timer at the beginning of the control loop.
@@ -50,4 +38,5 @@ float get_last_loop_time();
 
 uint32_t timer_get_count();
 
+void timer_init_globals(struct TimerDriver *global_timer, struct TimerDriver *axi_timer);
 #endif /* TIMER_H_ */
diff --git a/quad/sw/modular_quad_pid/src/type_def.h b/quad/sw/modular_quad_pid/src/type_def.h
index e67da1705..2a9de7fb6 100644
--- a/quad/sw/modular_quad_pid/src/type_def.h
+++ b/quad/sw/modular_quad_pid/src/type_def.h
@@ -11,6 +11,14 @@
 #include <stdint.h>
 #include "commands.h"
 #include "computation_graph.h"
+#include "hardware/hw_iface.h"
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+typedef signed char i8;
+typedef signed short i16;
+typedef signed long i32;
 
 /**
  * @brief
@@ -140,7 +148,7 @@ typedef struct PID_values{
  *
  */
 typedef struct user_input_t {
-	int rc_commands[6]; 	// Commands from the RC transmitter
+	u32 rc_commands[6]; 	// Commands from the RC transmitter
 
 
 //	float cam_x_pos;	// Current x position from the camera system
@@ -371,6 +379,29 @@ typedef struct actuator_command_t {
 	int pwms[4];
 } actuator_command_t;
 
+enum PWMChannels {
+  MOTOR_0,
+  MOTOR_1,
+  MOTOR_2,
+  MOTOR_3,
+  RC_INPUT_0,
+  RC_INPUT_1,
+  RC_INPUT_2,
+  RC_INPUT_3,
+  RC_INPUT_4,
+  RC_INPUT_5,
+};
+
+typedef struct hardware_t {
+  struct I2CDriver i2c;
+  struct PWMInputDriver pwm_inputs;
+  struct PWMOutputDriver pwm_outputs;
+  struct UARTDriver uart;
+  struct TimerDriver global_timer;
+  struct TimerDriver axi_timer;
+  struct LEDDriver mio7_led;
+} hardware_t;
+
 /**
  * @brief
  * 		Structures to be used throughout
@@ -385,6 +416,7 @@ typedef struct modular_structs {
 	user_defined_t user_defined_struct;
 	raw_actuator_t raw_actuator_struct;
 	actuator_command_t actuator_command_struct;
+	hardware_t hardware_struct;
 } modular_structs_t;
 
 //////// END MAIN MODULAR STRUCTS
diff --git a/quad/sw/modular_quad_pid/src/uart.c b/quad/sw/modular_quad_pid/src/uart.c
deleted file mode 100644
index 8328bed7b..000000000
--- a/quad/sw/modular_quad_pid/src/uart.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * uart.c
- *
- *  Created on: Nov 10, 2014
- *      Author: ucart
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "uart.h"
-#include <xuartps.h>
-#include <xstatus.h>
-
-// Global PS's
-XUartPs* _Uart0PS;
-XUartPs* _Uart1PS;
-static INTC Intc;
-
-//This is copied from xuart driver
-/***************************************************/
-
-#define XUARTPS_MAX_BAUD_ERROR_RATE		 3	/* max % error allowed */
-int XUartPs_SetBaudRate_ours(XUartPs *InstancePtr, u32 BaudRate)
-{
-	u8 IterBAUDDIV;		/* Iterator for available baud divisor values */
-	u32 BRGR_Value;		/* Calculated value for baud rate generator */
-	u32 CalcBaudRate;	/* Calculated baud rate */
-	u32 BaudError;		/* Diff between calculated and requested baud rate */
-	u32 Best_BRGR = 0;	/* Best value for baud rate generator */
-	u8 Best_BAUDDIV = 0;	/* Best value for baud divisor */
-	u32 Best_Error = 0xFFFFFFFF;
-	u32 PercentError;
-	u32 ModeReg;
-	u32 InputClk;
-
-	/*
-	 * Asserts validate the input arguments
-	 */
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-	//Xil_AssertNonvoid(BaudRate <= XUARTPS_MAX_RATE);
-	Xil_AssertNonvoid(BaudRate >= XUARTPS_MIN_RATE);
-
-	/*
-	 * Make sure the baud rate is not impossilby large.
-	 * Fastest possible baud rate is Input Clock / 2.
-	 */
-	if ((BaudRate * 2) > InstancePtr->Config.InputClockHz) {
-		return XST_UART_BAUD_ERROR;
-	}
-	/*
-	 * Check whether the input clock is divided by 8
-	 */
-	ModeReg = XUartPs_ReadReg( InstancePtr->Config.BaseAddress,
-				 XUARTPS_MR_OFFSET);
-
-	InputClk = InstancePtr->Config.InputClockHz;
-	if(ModeReg & XUARTPS_MR_CLKSEL) {
-		InputClk = InstancePtr->Config.InputClockHz / 8;
-	}
-
-	/*
-	 * Determine the Baud divider. It can be 4to 254.
-	 * Loop through all possible combinations
-	 */
-	for (IterBAUDDIV = 4; IterBAUDDIV < 255; IterBAUDDIV++) {
-
-		/*
-		 * Calculate the value for BRGR register
-		 */
-		BRGR_Value = InputClk / (BaudRate * (IterBAUDDIV + 1));
-
-		/*
-		 * Calculate the baud rate from the BRGR value
-		 */
-		CalcBaudRate = InputClk/ (BRGR_Value * (IterBAUDDIV + 1));
-
-		/*
-		 * Avoid unsigned integer underflow
-		 */
-		if (BaudRate > CalcBaudRate) {
-			BaudError = BaudRate - CalcBaudRate;
-		}
-		else {
-			BaudError = CalcBaudRate - BaudRate;
-		}
-
-		/*
-		 * Find the calculated baud rate closest to requested baud rate.
-		 */
-		if (Best_Error > BaudError) {
-
-			Best_BRGR = BRGR_Value;
-			Best_BAUDDIV = IterBAUDDIV;
-			Best_Error = BaudError;
-		}
-	}
-
-	/*
-	 * Make sure the best error is not too large.
-	 */
-	PercentError = (Best_Error * 100) / BaudRate;
-	if (XUARTPS_MAX_BAUD_ERROR_RATE < PercentError) {
-		return XST_UART_BAUD_ERROR;
-	}
-
-	/*
-	 * Disable TX and RX to avoid glitches when setting the baud rate.
-	 */
-	XUartPs_DisableUart(InstancePtr);
-
-	XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
-			   XUARTPS_BAUDGEN_OFFSET, Best_BRGR);
-	XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
-			   XUARTPS_BAUDDIV_OFFSET, Best_BAUDDIV);
-
-	/*
-	 * Enable device
-	 */
-	XUartPs_EnableUart(InstancePtr);
-
-	InstancePtr->BaudRate = BaudRate;
-
-	return XST_SUCCESS;
-
-}
-
-/***************************************************/
-
-/************************************************/
-/************** Main UART Interface *************/
-
-XUartPs* uart_init(XUartPs* uartps_ptr, u16 deviceID, int baudRate) {
-	XUartPs_Config* config = XUartPs_LookupConfig(deviceID);
-
-	//Configure XUartPs instance
-	int Status = XUartPs_CfgInitialize(uartps_ptr, config, config->BaseAddress);
-	if (Status != XST_SUCCESS){
-		return NULL;
-	}
-
-	//Set Baudrate for BT
-	//XUartPs_SetBaudRate(uartps_ptr, baudRate);
-	XUartPs_SetBaudRate_ours(uartps_ptr, baudRate);
-
-	return uartps_ptr;
-}
-
-void uart_clearFIFOs(XUartPs* uartps_ptr) {
-	//Get UART0 Control Register and clear the TX and RX Fifos
-	int* uart_ctrl_reg = (int*) uartps_ptr->Config.BaseAddress;
-	*uart_ctrl_reg |= 0x00000003; // clear TX & RX
-}
-
-void uart_sendByte(XUartPs* uartps_ptr, char data) {
-	XUartPs_SendByte(uartps_ptr->Config.BaseAddress, data);
-}
-
-void uart_sendStr(XUartPs* uartps_ptr, char* str) {
-	uart_sendBytes(uartps_ptr, str, strlen(str));
-}
-
-void uart_sendBytes(XUartPs* uartps_ptr, char* data, int numBytes) {
-	while (uart_isSending(uartps_ptr))
-		;
-
-	int done = 0;
-	while (done < numBytes) {
-		done += XUartPs_Send(uartps_ptr, (unsigned char*) (&data[done]), numBytes - done);
-	}
-}
-
-int uart_isSending(XUartPs* uartps_ptr) {
-	return XUartPs_IsSending(uartps_ptr);
-}
-
-int uart_hasData(XUartPs* uartps_ptr) {
-	return XUartPs_IsReceiveData(uartps_ptr->Config.BaseAddress);
-}
-
-void uart_recvBytes(XUartPs* uartps_ptr, char* buffer, int numBytes) {
-	int received = 0;
-	while (received < numBytes) {
-		received += XUartPs_Recv(uartps_ptr, (unsigned char*) &buffer[received], (numBytes - received));
-	}
-}
-
-char uart_recvByte(XUartPs* uartps_ptr) {
-	return XUartPs_RecvByte(uartps_ptr->Config.BaseAddress);
-	//char buffer[1];
-	//XUartPs_Recv(uartps_ptr, (unsigned char*) &buffer[0], 1);
-
-//	return buffer[0];
-}
-
-
-/*****************************************************************************/
-/**
-*
-* This function sets up the interrupt system so interrupts can occur for the
-* Uart. This function is application-specific.
-*
-* @param	IntcInstancePtr is a pointer to the instance of the INTC.
-* @param	UartInstancePtr contains a pointer to the instance of the UART
-*		driver which is going to be connected to the interrupt
-*		controller.
-* @param	UartIntrId is the interrupt Id and is typically
-*		XPAR_<UARTPS_instance>_INTR value from xparameters.h.
-*
-* @return	XST_SUCCESS if successful, otherwise XST_FAILURE.
-*
-* @note		None.
-*
-****************************************************************************/
-int SetupInterruptSystem(XUartPs *UartInstancePtr, u16 UartIntrId, Xil_ExceptionHandler handler)
-{
-	int Status;
-
-	XScuGic_Config *IntcConfig; /* Config for interrupt controller */
-
-	/* Initialize the interrupt controller driver */
-	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
-	if (NULL == IntcConfig) {
-		return XST_FAILURE;
-	}
-
-	Status = XScuGic_CfgInitialize(&Intc, IntcConfig,
-					IntcConfig->CpuBaseAddress);
-	if (Status != XST_SUCCESS) {
-		return XST_FAILURE;
-	}
-
-	/*
-	 * Connect the interrupt controller interrupt handler to the
-	 * hardware interrupt handling logic in the processor.
-	 */
-	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
-				(Xil_ExceptionHandler) XScuGic_InterruptHandler,
-				&Intc);
-
-	/*
-	 * Connect a device driver handler that will be called when an
-	 * interrupt for the device occurs, the device driver handler
-	 * performs the specific interrupt processing for the device
-	 */
-	Status = XScuGic_Connect(&Intc, UartIntrId,
-				  handler,
-				  (void *) UartInstancePtr);
-	if (Status != XST_SUCCESS) {
-		return XST_FAILURE;
-	}
-
-	/* Enable the interrupt for the device */
-	XScuGic_Enable(&Intc, UartIntrId);
-
-	/* Enable interrupts */
-	 Xil_ExceptionEnable();
-
-	return XST_SUCCESS;
-}
-/************************************************/
-/************************************************/
-
-
-
-
-
-/************************************************/
-/********** UART 0 convenience methods **********/
-
-XUartPs* uart0_init(u16 deviceID, int baudRate){
-	if (_Uart0PS) {
-		free(_Uart0PS);
-	}
-	_Uart0PS = malloc(sizeof(XUartPs));
-	return uart_init(_Uart0PS, deviceID, baudRate);
-}
-
-// Initializes the interrupt system for UART 0
-int uart0_int_init(u16 UartIntrId, Xil_ExceptionHandler handler) {
-	return SetupInterruptSystem(_Uart0PS, UartIntrId, handler);
-}
-
-void uart0_clearFIFOs(){
-	uart_clearFIFOs(_Uart0PS);
-}
-
-void uart0_sendByte(u8 data){
-	uart_sendByte(_Uart0PS, data);
-}
-
-void uart0_sendStr(char* str) {
-	uart_sendStr(_Uart0PS, str);
-}
-
-void uart0_sendMetaData(metadata_t md)
-{
-	uart0_sendByte(md.begin_char);
-	uart0_sendByte(md.msg_type & 0x00ff);
-	uart0_sendByte((md.msg_type >> 8) & 0x00ff);
-	uart0_sendByte(md.msg_id & 0x00ff);
-	uart0_sendByte((md.msg_id >> 8) & 0x00ff);
-	uart0_sendByte(md.data_len & 0x00ff);
-	uart0_sendByte((md.data_len >> 8) & 0x00ff);
-}
-
-void uart0_sendBytes(char* data, int numBytes){
-	uart_sendBytes(_Uart0PS, data, numBytes);
-}
-
-int uart0_isSending(){
-	return uart_isSending(_Uart0PS);
-}
-
-int uart0_hasData(){
-	return uart_hasData(_Uart0PS);
-}
-
-void uart0_recvBytes(char* buffer, int numBytes) {
-	uart_recvBytes(_Uart0PS, buffer, numBytes);
-}
-
-char uart0_recvByte() {
-	return uart_recvByte(_Uart0PS);
-}
-
-/************************************************/
-/************************************************/
-
-
-
-
-
-
-/************************************************/
-/********** UART 1 convenience methods **********/
-
-XUartPs* uart1_init(u16 deviceID, int baudRate){
-	if (_Uart1PS) {
-		free(_Uart1PS);
-	}
-	_Uart1PS = malloc(sizeof(XUartPs));
-	return uart_init(_Uart1PS, deviceID, baudRate);
-}
-
-void uart1_clearFIFOs(){
-	uart_clearFIFOs(_Uart1PS);
-}
-
-void uart1_sendByte(char data){
-	uart_sendByte(_Uart1PS, data);
-}
-
-void uart1_sendStr(char* str) {
-	uart_sendStr(_Uart1PS, str);
-}
-
-void uart1_sendBytes(char* data, int numBytes){
-	uart_sendBytes(_Uart1PS, data, numBytes);
-}
-
-int uart1_isSending(){
-	return uart_isSending(_Uart1PS);
-}
-
-int uart1_hasData(){
-	return uart_hasData(_Uart1PS);
-}
-
-void uart1_recvBytes(char* buffer, int numBytes) {
-	uart_recvBytes(_Uart1PS, buffer, numBytes);
-}
-
-char uart1_recvByte() {
-	return uart_recvByte(_Uart1PS);
-}
-
-/************************************************/
-
diff --git a/quad/sw/modular_quad_pid/src/uart.h b/quad/sw/modular_quad_pid/src/uart.h
deleted file mode 100644
index 6629e21af..000000000
--- a/quad/sw/modular_quad_pid/src/uart.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * uart.h
- *
- *  Created on: Nov 10, 2014
- *      Author: ucart
- */
-
-#ifndef UART_H_
-#define UART_H_
-
-#include "xparameters.h"
-#include "xuartps.h"
-#include "xscugic.h"
-#include "communication.h"
-
-#define PACKET_START_CHAR 2
-#define PACKET_END_CHAR 3
-#define UPDATE_SIZE 28
-
-#define INTC		XScuGic // Interrupt controller type
-#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID
-
-extern XUartPs* _Uart0PS;
-extern XUartPs* _Uart1PS;
-
-
-/************************************************/
-/************** Main UART Interface *************/
-XUartPs* uart_init(XUartPs* uartps_ptr, u16 deviceID, int baudRate);
-void uart_clearFIFOs(XUartPs* uartps_ptr);
-void uart_sendByte(XUartPs* uartps_ptr, char data);
-void uart_sendStr(XUartPs* uartps_ptr, char* str);
-void uart_sendBytes(XUartPs* uartps_ptr, char* data, int numBytes);
-int uart_isSending(XUartPs* uartps_ptr);
-int uart_hasData(XUartPs* uartps_ptr);
-
-//char uart_recvByte(); // block until char received
-
-//int uart_recvBytes(char* buffer, int numBytes, int timeoutMicros); // block until all received
-
-//void uart_recvCallback(void (*func)(char data));
-
-void uart_recvBytes(XUartPs* uartps_ptr, char* buffer, int numBytes);
-
-char uart_recvByte(XUartPs* uartps_ptr);
-/************************************************/
-/************************************************/
-
-
-
-/************************************************/
-/********** UART 0 convenience methods **********/
-XUartPs* uart0_init(u16 deviceID, int baudRate);
-int uart0_int_init(u16 UartIntrId, Xil_ExceptionHandler handler);
-void uart0_clearFIFOs();
-void uart0_sendByte(u8 data);
-void uart0_sendStr(char* data);
-void uart0_sendBytes(char* data, int numBytes);
-int uart0_isSending();
-int uart0_hasData();
-void uart0_recvBytes(char* buffer, int numBytes);
-char uart0_recvByte();
-void uart0_sendMetaData(metadata_t md);
-/************************************************/
-/************************************************/
-
-
-
-/************************************************/
-/********** UART 1 convenience methods **********/
-XUartPs* uart1_init(u16 deviceID, int baudRate);
-void uart1_clearFIFOs();
-void uart1_sendByte(char data);
-void uart1_sendStr(char* data);
-void uart1_sendBytes(char* data, int numBytes);
-int uart1_isSending();
-int uart1_hasData();
-void uart1_recvBytes(char* buffer, int numBytes);
-char uart1_recvByte();
-/************************************************/
-
-#endif /* UART_H_ */
diff --git a/quad/sw/modular_quad_pid/src/uart_buff.c b/quad/sw/modular_quad_pid/src/uart_buff.c
deleted file mode 100644
index 2ee7edbb8..000000000
--- a/quad/sw/modular_quad_pid/src/uart_buff.c
+++ /dev/null
@@ -1,417 +0,0 @@
-#include <stdio.h>
-#include "uart_buff.h"
-#include <stdlib.h>
-
-// function prototype declarations specific to the circular buffer
-void uart_buff_scan_packet();
-void uart_buff_scan_packet_start();
-void uart_buff_scan_packet_size();
-size_t uart_buff_packet_size();
-size_t uart_buff_calc_index(int);
-
-static volatile u8 buff[UART_MAX_BUFF_SIZE];
-u8 packet_buff[UART_MAX_PACKET_SIZE];
-
-static size_t start = 0;
-static volatile size_t end = 0;
-static size_t packet_data_length = 0;
-
-static u8 packet_ready = 0;
-
-// TODO: Delete these debugging variables
-static u32 packets_processed = 0;
-
-/**
- * Put a byte into the buffer.
- */
-void uart_buff_add_u8(u8 c) {
-  if (uart_buff_full()) {
-    return;
-  }
-
-  buff[end] = c;
-  end += 1;
-  if (end >= UART_MAX_BUFF_SIZE) {
-    end -= UART_MAX_BUFF_SIZE;
-  }
-}
-
-/**
- * Scan for a packet, updating any necessary indices and flags.
- */
-void uart_buff_scan_packet() {
-  size_t scan_limit = uart_buff_size();
-  size_t scan_iteration = 0;
-  while (!packet_ready && scan_iteration < scan_limit) {
-    scan_iteration += 1;
-
-    if (buff[start] != 0xBE) {
-      start += 1;
-      if (start >= UART_MAX_BUFF_SIZE) {
-	start -= UART_MAX_BUFF_SIZE;
-      }
-      continue;
-    }
-
-    if (uart_buff_size() < UART_PACKET_HEADER_SIZE) {
-      // Haven't received the "length" bytes yet. Check back later.
-      break;
-    }
-
-    packet_data_length = (uart_buff_get_u8(6) << 8) | uart_buff_get_u8(5);
-    if (uart_buff_packet_size() > UART_MAX_PACKET_SIZE) {
-      // Packet size is too big. Abort this packet.
-      start += 1;
-      if (start >= UART_MAX_BUFF_SIZE) {
-	start -= UART_MAX_BUFF_SIZE;
-      }
-      continue;
-    }
-
-    if (uart_buff_size() < uart_buff_packet_size()) {
-      // Haven't received the whole packet. Check back later.
-      break;
-    }
-
-    packet_ready = 1;
-  }
-}
-
-/**
- * Return 1 if a packet is ready to processed, 0 otherwise.
- */
-int uart_buff_packet_ready() {
-  if (!packet_ready) {
-    uart_buff_scan_packet();
-  }
-  return packet_ready;
-}
-
-/**
- * Retrieve a 8-bit from the buffer according to the given offset with respect
- * to the start index of the current packet.
- */
-u8 uart_buff_get_u8(size_t offset) {
-  size_t index = start + offset;
-
-  if (index >= UART_MAX_BUFF_SIZE) {
-    index -= UART_MAX_BUFF_SIZE;
-  }
-
-  return buff[index];
-}
-
-/**
- * Retrieve a 16-bit unsigned integer from the buffer according to the given
- * offset with respect to the start index of the current packet.
- */
-u16 uart_buff_get_u16(size_t offset) {
-  size_t index_1 = start + offset + 1;
-  size_t index = start + offset;
-
-  // Check common cases first
-  if (index_1 < UART_MAX_BUFF_SIZE) {
-    // in range, no need to correct indices
-  }
-  else if (index >= UART_MAX_BUFF_SIZE) {
-    index_1 -= UART_MAX_BUFF_SIZE;
-    index -= UART_MAX_BUFF_SIZE;
-  }
-  else {
-    index_1 -= UART_MAX_BUFF_SIZE;
-  }
-
-  return buff[index_1] << 8
-    | buff[index];
-}
-
-/**
- * Retrieve a 32-bit from the buffer according to the given offset with respect
- * to the start index of the current packet.
- */
-u32 uart_buff_get_u32(size_t offset) {
-  size_t index_3 = start + offset + 3;
-  size_t index_2 = start + offset + 2;
-  size_t index_1 = start + offset + 1;
-  size_t index = start + offset;
-
-  if (index_3 < UART_MAX_BUFF_SIZE) {
-    // in range, no need to correct indices
-  }
-  else if (index >= UART_MAX_BUFF_SIZE) {
-    index_3 -= UART_MAX_BUFF_SIZE;
-    index_2 -= UART_MAX_BUFF_SIZE;
-    index_1 -= UART_MAX_BUFF_SIZE;
-    index -= UART_MAX_BUFF_SIZE;
-  }
-  else {
-    index_3 = uart_buff_calc_index(index_3);
-    index_2 = uart_buff_calc_index(index_2);
-    index_1 = uart_buff_calc_index(index_1);
-    index = uart_buff_calc_index(index);
-  }
-
-  return buff[index_3] << 24
-    | buff[index_2] << 16
-    | buff[index_1] << 8
-    | buff[index];
-}
-
-/**
- * Retrieve a 8-bit unsigned integer from the buffer according to
- * the given offset with respect to the start of the data portion
- * of the current packet.
- *
- * This has undefined behavior if a packet is not ready.
- */
-u8 uart_buff_data_get_u8(size_t offset) {
-  size_t index = start + UART_PACKET_HEADER_SIZE + offset;
-
-  if (index >= UART_MAX_BUFF_SIZE) {
-    index -= UART_MAX_BUFF_SIZE;
-  }
-
-  return buff[index];
-}
-
-/**
- * Retrieve a 16-bit unsigned integer from the buffer according to
- * the given offset with respect to the start of the data portion
- * of the current packet.
- *
- * This has undefined behavior if a packet is not ready.
- */
-u16 uart_buff_data_get_u16(size_t offset) {
-  size_t index_1 = start + UART_PACKET_HEADER_SIZE + offset + 1;
-  size_t index = start + UART_PACKET_HEADER_SIZE + offset;
-
-  // Check common cases first
-  if (index_1 < UART_MAX_BUFF_SIZE) {
-    // in range, no need to correct indices
-  }
-  else if (index >= UART_MAX_BUFF_SIZE) {
-    index_1 -= UART_MAX_BUFF_SIZE;
-    index -= UART_MAX_BUFF_SIZE;
-  }
-  else {
-    index_1 -= UART_MAX_BUFF_SIZE;
-  }
-
-  return buff[index_1] << 8
-    | buff[index];
-}
-
-/**
- * Retrieve a 32-bit unsigned integer from the buffer according to
- * the given offset with respect to the start of the data portion
- * of the current packet.
- *
- * This has undefined behavior if a packet is not ready.
- */
-u32 uart_buff_data_get_u32(size_t offset) {
-  size_t index_3 = start + UART_PACKET_HEADER_SIZE + offset + 3;
-  size_t index_2 = start + UART_PACKET_HEADER_SIZE + offset + 2;
-  size_t index_1 = start + UART_PACKET_HEADER_SIZE + offset + 1;
-  size_t index = start + UART_PACKET_HEADER_SIZE + offset;
-
-  if (index_3 < UART_MAX_BUFF_SIZE) {
-    // in range, no need to correct indices
-  }
-  else if (index >= UART_MAX_BUFF_SIZE) {
-    index_3 -= UART_MAX_BUFF_SIZE;
-    index_2 -= UART_MAX_BUFF_SIZE;
-    index_1 -= UART_MAX_BUFF_SIZE;
-    index -= UART_MAX_BUFF_SIZE;
-  }
-  else {
-    index_3 = uart_buff_calc_index(index_3);
-    index_2 = uart_buff_calc_index(index_2);
-    index_1 = uart_buff_calc_index(index_1);
-    index = uart_buff_calc_index(index);
-  }
-
-  return buff[index_3] << 24
-    | buff[index_2] << 16
-    | buff[index_1] << 8
-    | buff[index];
-}
-
-/**
- * Retrieve a 32-bit floating point number from the buffer according to the
- * given offset with respect to the start of the data portion of the current
- * packet.
- *
- * This has undefined behavior if a packet is not ready.
- */
-float uart_buff_data_get_float(size_t offset) {
-  size_t index_3 = start + UART_PACKET_HEADER_SIZE + offset + 3;
-  size_t index_2 = start + UART_PACKET_HEADER_SIZE + offset + 2;
-  size_t index_1 = start + UART_PACKET_HEADER_SIZE + offset + 1;
-  size_t index = start + UART_PACKET_HEADER_SIZE + offset;
-
-  if (index_3 < UART_MAX_BUFF_SIZE) {
-    // in range, no need to correct indices
-  }
-  else if (index >= UART_MAX_BUFF_SIZE) {
-    index_3 -= UART_MAX_BUFF_SIZE;
-    index_2 -= UART_MAX_BUFF_SIZE;
-    index_1 -= UART_MAX_BUFF_SIZE;
-    index -= UART_MAX_BUFF_SIZE;
-  }
-  else {
-    index_3 = uart_buff_calc_index(index_3);
-    index_2 = uart_buff_calc_index(index_2);
-    index_1 = uart_buff_calc_index(index_1);
-    index = uart_buff_calc_index(index);
-  }
-
-  union {
-    float f;
-    int i;
-  } x;
-
-  x.i =  buff[index_3] << 24
-    | buff[index_2] << 16
-    | buff[index_1] << 8
-    | buff[index];
-
-  return x.f;
-}
-
-/**
- * Move the start index of the buffer to the end of the current packet.
- * If a packet is not ready, this function does nothing.
- */
-void uart_buff_consume_packet() {
-  if (!packet_ready) {
-    return;
-  }
-
-  start = uart_buff_calc_index(start + uart_buff_packet_size());
-  packet_ready = 0;
-  packets_processed += 1;
-}
-
-/**
- * Return the current number of bytes held in the buffer.
- */
-size_t uart_buff_size() {
-  int size = end - start;
-  if (size < 0) {
-    size += UART_MAX_BUFF_SIZE;
-  }
-  return size;
-}
-
-/**
- * Return the length of the data portion of the current packet.
- */
-size_t uart_buff_data_length() {
-  return packet_data_length;
-}
-
-/**
- * Return the size of the current packet.
- */
-inline
-size_t uart_buff_packet_size() {
-  return UART_PACKET_HEADER_SIZE + packet_data_length + 1;
-}
-
-/**
- * Return 1 if the buffer is empty, 0 otherwise.
- */
-int uart_buff_empty() {
-  return start == end;
-}
-
-/**
- * Return 1 if the buffer is full, 0 otherwise.
- */
-int uart_buff_full() {
-  int effective_end = end + 1;
-  if (effective_end >= UART_MAX_BUFF_SIZE) {
-    effective_end -= UART_MAX_BUFF_SIZE;
-  }
-  return start == effective_end;
-}
-
-/**
- * Calculate the actual index from the given index, wrapping around
- * the edges of the circular buffer if necessary.
- */
-size_t uart_buff_calc_index(int given_index) {
-  int actual_index = given_index;
-  if (actual_index >= UART_MAX_BUFF_SIZE) {
-    actual_index -= UART_MAX_BUFF_SIZE;
-  }
-  return actual_index;
-}
-
-/**
- * Return a pointer to the start of the packet.
- */
-u8 * uart_buff_get_raw(size_t *packet_size) {
-  // Copy packet into temp buffer
-  *packet_size = uart_buff_packet_size();
-  int i;
-  for (i = 0; i < *packet_size; i += 1) {
-    packet_buff[i] = uart_buff_get_u8(i);
-  }
-  return packet_buff;
-}
-
-/**
- * Print the buffer with a pretty ASCII art image.
- */
-void uart_buff_print() {
-  size_t packet_size = uart_buff_packet_size();
-  size_t data_start = uart_buff_calc_index(start + UART_PACKET_HEADER_SIZE);
-  size_t data_end = uart_buff_calc_index(start + packet_size);
-  int i;
-  printf("buffer size = %zu\n", uart_buff_size());
-  puts("Buffer:");
-  puts(".--.");
-  puts("|  |");
-  puts("|  v");
-  for (i = 0; i < UART_MAX_BUFF_SIZE; i += 1) {
-    printf("|  %02X", buff[i]);
-    if (i == start) {
-      printf("<-- start");
-    }
-    if (packet_ready) {
-      if (i == data_start) {
-        printf("<-- data start");
-      }
-      if (i == data_end) {
-        printf("<-- data end");
-      }
-    }
-    if (i == end) {
-      printf("<-- end");
-    }
-    printf("\n");
-  }
-  puts("|  |");
-  puts("'--'");
-}
-
-/**
- * Reset the state of the buffer.
- */
-void uart_buff_reset() {
-  start = 0;
-  end = 0;
-  int i;
-  for (i = 0; i < UART_MAX_BUFF_SIZE; i += 1) {
-    buff[i] = 0;
-  }
-  packet_ready = 0;
-}
-
-/**
- * Return the total number of packets processed.
- */
-u32 uart_buff_packets_processed() {
-  return packets_processed;
-}
diff --git a/quad/sw/modular_quad_pid/src/uart_buff.h b/quad/sw/modular_quad_pid/src/uart_buff.h
deleted file mode 100644
index 4d6ddbe8a..000000000
--- a/quad/sw/modular_quad_pid/src/uart_buff.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef CIRC_BUFF_H
-#define CIRC_BUFF_H
-
-#include "xil_types.h"
-
-#define UART_MAX_BUFF_SIZE 2048
-#define UART_MAX_PACKET_SIZE 256
-#define UART_PACKET_HEADER_SIZE 7
-
-void uart_buff_add_u8(u8);
-int uart_buff_packet_ready();
-u8 uart_buff_get_u8(size_t);
-u16 uart_buff_get_u16(size_t);
-u32 uart_buff_get_u32(size_t);
-u8 uart_buff_data_get_u8(size_t);
-u16 uart_buff_data_get_u16(size_t);
-u32 uart_buff_data_get_u32(size_t);
-float uart_buff_data_get_float(size_t);
-void uart_buff_consume_packet();
-size_t uart_buff_size();
-size_t uart_buff_data_length();
-int uart_buff_empty();
-int uart_buff_full();
-u8 * uart_buff_get_raw(size_t *);
-void uart_buff_print();
-u32 uart_buff_packets_processed();
-void uart_buff_reset();
-
-#endif
diff --git a/quad/sw/modular_quad_pid/src/user_input.c b/quad/sw/modular_quad_pid/src/user_input.c
index b3b4331e2..bcb7478bf 100644
--- a/quad/sw/modular_quad_pid/src/user_input.c
+++ b/quad/sw/modular_quad_pid/src/user_input.c
@@ -6,27 +6,26 @@
  */
  
 #include "user_input.h"
-#include "uart.h"
-#include "controllers.h"
  
-int get_user_input(log_t* log_struct, user_input_t* user_input_struct)
+int get_user_input(hardware_t *hardware_struct, log_t* log_struct, user_input_t* user_input_struct)
 {
-	// Read in values from RC Receiver
-	read_rec_all(user_input_struct->rc_commands);
+  // Read in values from RC Receiver
+  struct PWMInputDriver *pwm_inputs = &hardware_struct->pwm_inputs;
+  read_rec_all(pwm_inputs, user_input_struct->rc_commands);
 
-	//create setpoints for manual flight
-	// currently in units of radians
-	user_input_struct->yaw_manual_setpoint = convert_from_receiver_cmd(user_input_struct->rc_commands[YAW], YAW_MAX, YAW_CENTER, YAW_MIN, YAW_RAD_TARGET, -(YAW_RAD_TARGET));
-	user_input_struct->roll_angle_manual_setpoint = convert_from_receiver_cmd(user_input_struct->rc_commands[ROLL], ROLL_MAX, ROLL_CENTER, ROLL_MIN, ROLL_RAD_TARGET, -(ROLL_RAD_TARGET));
-	user_input_struct->pitch_angle_manual_setpoint = convert_from_receiver_cmd(user_input_struct->rc_commands[PITCH], PITCH_MAX, PITCH_CENTER, PITCH_MIN, PITCH_RAD_TARGET, -(PITCH_RAD_TARGET));
+  //create setpoints for manual flight
+  // currently in units of radians
+  user_input_struct->yaw_manual_setpoint = convert_from_receiver_cmd(user_input_struct->rc_commands[YAW], YAW_MAX, YAW_CENTER, YAW_MIN, YAW_RAD_TARGET, -(YAW_RAD_TARGET));
+  user_input_struct->roll_angle_manual_setpoint = convert_from_receiver_cmd(user_input_struct->rc_commands[ROLL], ROLL_MAX, ROLL_CENTER, ROLL_MIN, ROLL_RAD_TARGET, -(ROLL_RAD_TARGET));
+  user_input_struct->pitch_angle_manual_setpoint = convert_from_receiver_cmd(user_input_struct->rc_commands[PITCH], PITCH_MAX, PITCH_CENTER, PITCH_MIN, PITCH_RAD_TARGET, -(PITCH_RAD_TARGET));
 
-	// Listen on bluetooth and if there's a packet,
-	// then receive the packet and set hasPacket for later processing
-	// "update packet" type processing is done in sensor.c
-	// "command packet" type processing is done in control_algorithm.c
-	//user_input_struct->hasPacket = tryReceivePacket(user_input_struct->sb, 0);
+  // Listen on bluetooth and if there's a packet,
+  // then receive the packet and set hasPacket for later processing
+  // "update packet" type processing is done in sensor.c
+  // "command packet" type processing is done in control_algorithm.c
+  //user_input_struct->hasPacket = tryReceivePacket(user_input_struct->sb, 0);
 
-    return 0;
+  return 0;
 }
 
 int kill_condition(user_input_t* user_input_struct)
diff --git a/quad/sw/modular_quad_pid/src/user_input.h b/quad/sw/modular_quad_pid/src/user_input.h
index c17fe91fe..c289e99c9 100644
--- a/quad/sw/modular_quad_pid/src/user_input.h
+++ b/quad/sw/modular_quad_pid/src/user_input.h
@@ -79,7 +79,7 @@
  *      error message
  *
  */
-int get_user_input(log_t* log_struct,  user_input_t* user_input_struct);
+int get_user_input(hardware_t *hardware_struct, log_t* log_struct,  user_input_t* user_input_struct);
 int kill_condition(user_input_t* user_input_struct);
 float convert_from_receiver_cmd(int receiver_cmd, int max_receiver_cmd, int center_receiver_cmd, int min_receiver_cmd, float max_target, float min_target);
 
diff --git a/quad/sw/modular_quad_pid/src/util.c b/quad/sw/modular_quad_pid/src/util.c
index be07d3818..9262e49f4 100644
--- a/quad/sw/modular_quad_pid/src/util.c
+++ b/quad/sw/modular_quad_pid/src/util.c
@@ -1,10 +1,3 @@
-/*
- * util.c
- *
- *  Created on: Oct 11, 2014
- *      Author: ucart
- */
-
 #include "util.h"
 
 #include <stdlib.h>
@@ -17,110 +10,17 @@
 #include <sleep.h>
 #include "controllers.h"
 #include "xparameters.h"
-#include "uart.h"
 
 extern int motor0_bias, motor1_bias, motor2_bias, motor3_bias;
-//Global variable representing the current pulseW
-int pulseW = pulse_throttle_low;
-
-/**
- * Initializes the PWM output components.
- * Default pulse length  = 1 ms
- * Default period length = 2.33 ms
- */
-void pwm_init() {
-
-	int* pwm_0 = (int*) PWM_0_ADDR + PWM_PERIOD;
-	int* pwm_1 = (int*) PWM_1_ADDR + PWM_PERIOD;
-	int* pwm_2 = (int*) PWM_2_ADDR + PWM_PERIOD;
-	int* pwm_3 = (int*) PWM_3_ADDR + PWM_PERIOD;
-
-	// Initializes all the PWM address to have the correct period width at 450 hz
-	*pwm_0 = period_width;
-	*pwm_1 = period_width;
-	*pwm_2 = period_width;
-	*pwm_3 = period_width;
-	// Initializes the PWM pulse lengths to be 1 ms
-	*(int*) (PWM_0_ADDR + PWM_PULSE) = pulse_throttle_low;
-	*(int*) (PWM_1_ADDR + PWM_PULSE) = pulse_throttle_low;
-	*(int*) (PWM_2_ADDR + PWM_PULSE) = pulse_throttle_low;
-	*(int*) (PWM_3_ADDR + PWM_PULSE) = pulse_throttle_low;
-
-	usleep(1000000);
-}
-
-/**
- * Writes all PWM components to be the same given pulsewidth
- */
-void pwm_write_all(int pulseWidth) {
-	// Check lower and upper bounds
-	if (pulseWidth > pulse_throttle_high)
-		pulseWidth = pulse_throttle_high;
-	if (pulseWidth < pulse_throttle_low)
-		pulseWidth = pulse_throttle_low;
-	// Set all the pulse widths
-	*(int*) (PWM_0_ADDR + PWM_PULSE) = pulseWidth;
-	*(int*) (PWM_1_ADDR + PWM_PULSE) = pulseWidth;
-	*(int*) (PWM_2_ADDR + PWM_PULSE) = pulseWidth;
-	*(int*) (PWM_3_ADDR + PWM_PULSE) = pulseWidth;
-}
-/**
- * Write a given pulseWidth to a channel
- */
-void pwm_write_channel(int pulseWidth, int channel){
-	// Check lower and upper bounds
-		if (pulseWidth > pulse_throttle_high)
-			pulseWidth = pulse_throttle_high;
-		if (pulseWidth < pulse_throttle_low)
-			pulseWidth = pulse_throttle_low;
 
-		switch(channel){
-		case 0:
-			*(int*) (PWM_0_ADDR + PWM_PULSE) = pulseWidth;
-			break;
-		case 1:
-			*(int*) (PWM_1_ADDR + PWM_PULSE) = pulseWidth;
-			break;
-		case 2:
-			*(int*) (PWM_2_ADDR + PWM_PULSE) = pulseWidth;
-			break;
-		case 3:
-			*(int*) (PWM_3_ADDR + PWM_PULSE) = pulseWidth;
-			break;
-		default:
-			break;
-		}
-}
-/**
- * Reads the registers from the PWM_Recorders, and returns the pulse width
- * of the last PWM signal to come in
- */
-int read_rec(int channel) {
-	switch (channel) {
-	case 0:
-		return *((int*) PWM_REC_0_ADDR);
-	case 1:
-		return *((int*) PWM_REC_1_ADDR);
-	case 2:
-		return *((int*) PWM_REC_2_ADDR);
-	case 3:
-		return *((int*) PWM_REC_3_ADDR);
-	case 4:
-		return *((int*) PWM_REC_4_ADDR);
-	case 5:
-		return *((int*) PWM_REC_5_ADDR);
-	default:
-		return 0;
-	}
-}
 /**
- * Reads all 4 receiver channels at once
+ * Reads all 6 receiver channels at once
  */
-void read_rec_all(int* mixer){
-	int i;
-	for(i = 0; i < 6; i++){
-		mixer[i] = read_rec(i);
-	}
+void read_rec_all(struct PWMInputDriver *pwm_input, u32 *mixer){
+  int i;
+  for(i = 0; i < 6; i++){
+    pwm_input->read(pwm_input, i, &mixer[i]);
+  }
 }
 
 int hexStrToInt(char *buf, int startIdx, int endIdx) {
@@ -146,131 +46,6 @@ int hexStrToInt(char *buf, int startIdx, int endIdx) {
 	return result;
 }
 
-void read_bluetooth_all(int* mixer) {
-	char buffer[32];
-
-	int done = 0;
-	int gotS = 0;
-	char c  = 0;
-	while (!done) {
-		int counter = 0;
-		if (!gotS) {
-			c = uart0_recvByte();
-		}
-		if (c == 'S') {
-
-			while (1) {
-				char cc = uart0_recvByte();
-				if (cc == 'S') {
-									counter = 0;
-									gotS = 1;
-									break;
-								}
-				printf("C=%c,\r\n",cc);
-				buffer[counter++] = cc;
-
-
-				if (counter == 12) {
-					buffer[12] = 0;
-					done = 1;
-					gotS = 0;
-				}
-			}
-			//uart0_recvBytes(buffer, 12);
-			//buffer[12] = 0;
-
-
-		}
-	}
-
-//	// data := "XX XX XX XX XX"
-//	uart0_recvBytes(buffer, 12);
-//	buffer[12] = 0;
-//
-//
-	int i;
-	for(i=0; i < 5; i++) {
-		mixer[i] = 0;
-	}
-
-	for (i=0; i < 4; i++) {
-		//mixer[i] = hexStrToInt(buffer, 3*i, 3*i + 1);
-		mixer[i] = (buffer[i*3] << 8) | buffer[i*3 + 1];
-	}
-
-	printf("mixer: \"%s\" -> %d %d %d %d %d\r\n", buffer, mixer[0], mixer[1], mixer[2], mixer[3], mixer[4]);
-
-}
-
-/**
- * Use the buttons to drive the pulse length of the channels
- */
-void b_drive_pulse() {
-	int* btns = (int *) XPAR_BTNS_BASEADDR;
-
-	// Increment the pulse width by 5% throttle
-	if (*btns & 0x1) {
-		pulseW += 1000;
-		if (pulseW > 200000)
-			pulseW = 200000;
-		pwm_write_all(pulseW);
-		while (*btns & 0x1)
-			;
-	} //Decrease the pulse width by 5% throttle
-	else if (*btns & 0x2) {
-		pulseW -= 1000;
-		if (pulseW < 100000) {
-			pulseW = 100000;
-		}
-		pwm_write_all(pulseW);
-		while (*btns & 0x2)
-			;
-	}
-	// Set the pulses back to default
-	else if (*btns & 0x4) {
-		pulseW = MOTOR_0_PERCENT;
-		pwm_write_all(pulseW);
-	}
-	// Read the pulse width of pwm_recorder 0
-	else if (*btns & 0x8) {
-		int i;
-		for(i = 0; i < 4; i++){
-			xil_printf("Channel %d:  %d\n", i, read_rec(i));
-		}
-		//xil_printf("%d\n",pulseW);
-		while (*btns & 0x8)
-			;
-	}
-}
-
-/**
- * Creates a sine wave driving the motors from 0 to 100% throttle
- */
-void sine_example(){
-
-	int* btns = (int *) XPAR_BTNS_BASEADDR;
-	/*        Sine Wave        */
-	static double time = 0;
-
-	time += .0001;
-	pulseW = (int)fabs(sin(time)*(100000)) + 100000;
-	//pulseW = (int) (sin(time) + 1)*50000 + 100000;
-	if (*btns & 0x1){
-		printf("%d", pulseW);
-		printf("   %d\n", *(int*) (PWM_0_ADDR + PWM_PULSE));
-	}
-	pwm_write_all(pulseW);
-	usleep(300);
-}
-
-void print_mixer(int * mixer){
-	int i;
-	for(i = 0; i < 4; i++){
-		xil_printf("%d : %d			", i, mixer[i]);
-	}
-	xil_printf("\n");
-}
-
 /**
  * Argument is the reading from the pwm_recorder4 which is connected to the gear pwm
  * If the message from the receiver is 0 - gear, kill the system by sending a 1
@@ -295,223 +70,29 @@ int read_flap(int flap)
 /**
  * Turns off the motors
  */
-void pwm_kill(){
-	// Initializes the PWM pulse lengths to be 1 ms
-	*(int*) (PWM_0_ADDR + PWM_PULSE) = pulse_throttle_low;
-	*(int*) (PWM_1_ADDR + PWM_PULSE) = pulse_throttle_low;
-	*(int*) (PWM_2_ADDR + PWM_PULSE) = pulse_throttle_low;
-	*(int*) (PWM_3_ADDR + PWM_PULSE) = pulse_throttle_low;
+void kill_motors(struct PWMOutputDriver *pwm_outputs) {
+  pwm_outputs->write(pwm_outputs, 0, 0);
+  pwm_outputs->write(pwm_outputs, 1, 0);
+  pwm_outputs->write(pwm_outputs, 2, 0);
+  pwm_outputs->write(pwm_outputs, 3, 0);
 }
 
-/**
- * Useful stuff in here in regards to PID tuning, and motor tuning
- * TODO : Scanf string stuff
- * TODO : Make adam do it :DDDDDDDD
- */
-void bluetoothTunePID(char instr, gam_t* gam, PID_t* CFpid, PID_t* Gpid){
-	int wasX = 0;
-	int wasPid = 0;
-	int wasSetpoint = 0;
-	int wasLog = 0;
-	char buf[100];
-
-	switch (instr) {
-	case 'P':
-		// Change this if tuning other PIDs
-		CFpid->Kp += .5;
-		wasPid = 1;
-		break;
-	case 'p':
-		CFpid->Kp -= .5;
-		wasPid = 1;
-		break;
-	case 'O':
-		CFpid->Kp += .2;
-		wasPid = 1;
-		break;
-	case 'o':
-		CFpid->Kp -= .2;
-		wasPid = 1;
-		break;
-
-	case 'I':
-		CFpid->Kp += 0.1;
-		wasPid = 1;
-		break;
-	case 'i':
-		CFpid->Kp -= 0.1;
-		wasPid = 1;
-		break;
-	case 'W':
-		Gpid->Kp += 1;
-		wasPid = 1;
-		break;
-	case 'w':
-		Gpid->Kp -= 1;
-		wasPid = 1;
-		break;
-	case 'E':
-		Gpid->Kp += 2;
-		wasPid = 1;
-		break;
-	case 'e':
-		Gpid->Kp -= 2;
-		wasPid = 1;
-		break;
-	case 'R':
-		Gpid->Kp += 5;
-		wasPid = 1;
-		break;
-	case 'r':
-		Gpid->Kp -= 5;
-		wasPid = 1;
-		break;
-	case 'D':
-		CFpid->Kd += .1;
-		wasPid = 1;
-		break;
-	case 'd':
-			CFpid->Kd -= .1;
-			wasPid = 1;
-			break;
-	case 'S':
-			CFpid->setpoint += 1;
-			wasSetpoint = 1;
-			break;
-	case 's':
-			CFpid->setpoint -= 1;
-			wasSetpoint = 1;
-			break;
-	case '0':
-		motor0_bias += 100;
-		wasPid = 0;
-		break;
-	case '1':
-		motor1_bias += 100;
-		wasPid = 0;
-		break;
-	case '2':
-		motor2_bias += 100;
-		wasPid = 0;
-		break;
-	case '3':
-		motor3_bias += 100;
-		wasPid = 0;
-		break;
-	case ')':
-		motor0_bias -= 100;
-		wasPid = 0;
-		break;
-	case '!':
-		motor1_bias -= 100;
-		wasPid = 0;
-		break;
-	case '@':
-		motor2_bias -= 100;
-		wasPid = 0;
-		break;
-	case '#':
-		motor3_bias -= 100;
-		wasPid = 0;
-		break;
-	case 'x':
-		wasX = 1;
-		break;
-	case ' ':
-		wasLog = 1;
-		break;
-/*	case 'm':
-		pid->setpoint = -45.0;
-		// Change set point
-		break;
-	case 'n':
-		pid->setpoint = 45.0;
-	*/	// Change set point
-	default:
-		wasPid = 0;
-		break;
-	}
-
-	if(wasX){
-		return;
-	}
-	else if(wasSetpoint){
-		sprintf(buf, "Setpoint: %4.1f\n\r", CFpid->setpoint);
-		uart0_sendBytes(buf, strlen(buf));
-		usleep(5000);
-	}
-	else if (wasPid) {
-		/*sprintf(buf,
-				"PAngle: %8.3f RAngle: %8.3f PID p: %8.3f  d: %8.3f\r\n",
-				compY, compX, pitchPID.Kp, pitchPID.Kd);*/
-
-		sprintf(buf, "CFP Coeff: %4.1f D %4.1f GP Coeff: %4.1f\n\r", CFpid->Kp, CFpid->Kd, Gpid->Kp);
-		uart0_sendBytes(buf, strlen(buf));
-		usleep(5000);
-	}
-	else if (wasLog){
-		sprintf(buf, "CX %5.2f GP GX: %5.2f\n\r", 0.0, gam->gyro_xVel_p);
-		uart0_sendBytes(buf, strlen(buf));
-		usleep(5000);
-	}
-	else {
-		sprintf(buf, "Motor bias's \t\t0: %d 1: %d 2: %d 3: %d \r\n", motor0_bias,
-				motor1_bias, motor2_bias, motor3_bias);
-		uart0_sendBytes(buf, strlen(buf));
-
-//		sprintf(buf, "P: %3.2f I: %3.2f D: %3.2f\r\n", log_struct.ang_vel_pitch_PID_values.P, log_struct.ang_vel_pitch_PID_values.I, log_struct.ang_vel_pitch_PID_values.D);
-		uart0_sendBytes(buf, strlen(buf));
-		usleep(1e4);
-	}
+int build_int(u8 *buff) {
+  return  buff[3] << 24
+    | buff[2] << 16
+    | buff[1] << 8
+    | buff[0];
 }
-/*
-void flash_MIO_7_led(int how_many_times, int ms_between_flashes)
-{
-	if(how_many_times <= 0)
-		return;
-
-	while(how_many_times)
-	{
-		MIO7_led_on();
-
-		usleep(ms_between_flashes * 500);
 
-		MIO7_led_off();
+float build_float(u8 *buff) {
+  union {
+    float f;
+    int i;
+  } x;
 
-		usleep(ms_between_flashes * 500);
-
-		how_many_times--;
-	}
+  x.i =  buff[3] << 24
+    | buff[2] << 16
+    | buff[1] << 8
+    | buff[0];
+  return x.f;
 }
-
-void MIO7_led_off()
-{
-	XGpioPs Gpio;
-
-	XGpioPs_Config * ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
-	XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
-
-	XGpioPs_SetDirectionPin(&Gpio, 7, 1);
-
-	// Disable LED
-	XGpioPs_WritePin(&Gpio, 7, 0x00);
-}
-
-void MIO7_led_on()
-{
-	XGpioPs Gpio;
-
-	XGpioPs_Config * ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
-	XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
-
-	XGpioPs_SetDirectionPin(&Gpio, 7, 1);
-
-	// Enable LED
-	XGpioPs_WritePin(&Gpio, 7, 0x01);
-}
-*/
-void msleep(int msecs)
-{
-	usleep(msecs * 1000);
-}
-
diff --git a/quad/sw/modular_quad_pid/src/util.h b/quad/sw/modular_quad_pid/src/util.h
index 7c864f4d6..003987759 100644
--- a/quad/sw/modular_quad_pid/src/util.h
+++ b/quad/sw/modular_quad_pid/src/util.h
@@ -1,92 +1,23 @@
-/*
- * util.h
- *
- *  Created on: Oct 11, 2014
- *      Author: ucart
- */
 #ifndef _UTIL_H
 #define _UTIL_H
 
 #include "type_def.h"
-
-
-#define clock_rate          100000000
-#define frequency           450
-#define period_width        clock_rate/frequency
-#define pulse_throttle_low  clock_rate / 1000 // 1ms
-#define pulse_throttle_high clock_rate / 500 // 2ms
-#define MOTOR_0_PERCENT     115000
-
-
-#define XPAR_BTNS_BASEADDR 0x41200000
-
-/**
- * Various Addresses of custom IP components
- */
-#define PWM_0_ADDR     XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_0_BASEADDR
-#define PWM_1_ADDR     XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_1_BASEADDR
-#define PWM_2_ADDR     XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_2_BASEADDR
-#define PWM_3_ADDR     XPAR_PWM_SIGNAL_OUT_WKILLSWITCH_3_BASEADDR
-#define PWM_REC_0_ADDR XPAR_PWM_RECORDER_0_BASEADDR
-#define PWM_REC_1_ADDR XPAR_PWM_RECORDER_1_BASEADDR
-#define PWM_REC_2_ADDR XPAR_PWM_RECORDER_2_BASEADDR
-#define PWM_REC_3_ADDR XPAR_PWM_RECORDER_3_BASEADDR
-#define PWM_REC_4_ADDR XPAR_PWM_RECORDER_4_BASEADDR
-#define PWM_REC_5_ADDR XPAR_PWM_RECORDER_5_BASEADDR
-
-/**
- * Register offsets within the custom IP
- */
-#define PWM_PERIOD     0
-#define PWM_PULSE      4
-
-void pwm_init();
-void pwm_write_all(int pulseWidth);
-void pwm_write_channel(int pulseWidth, int channel);
-
-int read_rec(int channel);
-void read_rec_all(int* mixer);
-
-void read_bluetooth_all(int* mixer);
-
-void b_drive_pulse();
-
-void sine_example();
-
-void print_mixer(int* mixer);
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "PID.h"
+#include "log_data.h"
+#include <sleep.h>
+#include "controllers.h"
+#include "hardware/hw_iface.h"
+
+void read_rec_all(struct PWMInputDriver *pwm_input, u32 *mixer);
 int read_kill(int gear);
 int read_flap(int flap);
-void pwm_kill();
-
-void printLogging();
-void bluetoothTunePID(char instr, gam_t* gam, PID_t* CFpid, PID_t* Gpid);
-void msleep(int msecs);
-
-/**
- * @brief
- *      Flashes the MIO7 LED how_many_times times and with ms_between_flashes between the flashes.
- *
- * @param how_many_times
- *      times the LED should be flashed
- *
- * @param ms_between_flashes
- *      time between flashes in milliseconds
- *
- */
-void flash_MIO_7_led(int how_many_times, int ms_between_flashes);
-
-/**
- * @brief
- *      Turns off MIO7 LED.
- *
- */
-void MIO7_led_off();
+void kill_motors();
 
-/**
- * @brief
- *      Turns on MIO7 LED.
- *
- */
-void MIO7_led_on();
+int build_int(u8 *buff);
+float build_float(u8 *buff);
 
 #endif //_UTIL_H
-- 
GitLab