diff --git a/wifi_bridge/SerialEchoConsole/.gitignore b/wifi_bridge/SerialEchoConsole/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..79db921b2212a94427cd0dfa379c4732539019e6
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/.gitignore
@@ -0,0 +1,275 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+*.vcxproj.filters
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+**/Properties/launchSettings.json
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole.sln b/wifi_bridge/SerialEchoConsole/SerialEchoConsole.sln
new file mode 100644
index 0000000000000000000000000000000000000000..dbf812ac273e8d8cc639c1714cdaef2a10bc3b44
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SerialEchoConsole", "SerialEchoConsole\SerialEchoConsole.vcxproj", "{C2ACDB47-A077-43EB-AA59-DD7E33DEAEE2}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{C2ACDB47-A077-43EB-AA59-DD7E33DEAEE2}.Debug|x64.ActiveCfg = Debug|x64
+		{C2ACDB47-A077-43EB-AA59-DD7E33DEAEE2}.Debug|x64.Build.0 = Debug|x64
+		{C2ACDB47-A077-43EB-AA59-DD7E33DEAEE2}.Debug|x86.ActiveCfg = Debug|Win32
+		{C2ACDB47-A077-43EB-AA59-DD7E33DEAEE2}.Debug|x86.Build.0 = Debug|Win32
+		{C2ACDB47-A077-43EB-AA59-DD7E33DEAEE2}.Release|x64.ActiveCfg = Release|x64
+		{C2ACDB47-A077-43EB-AA59-DD7E33DEAEE2}.Release|x64.Build.0 = Release|x64
+		{C2ACDB47-A077-43EB-AA59-DD7E33DEAEE2}.Release|x86.ActiveCfg = Release|Win32
+		{C2ACDB47-A077-43EB-AA59-DD7E33DEAEE2}.Release|x86.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole/Packet.cpp b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/Packet.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5b16a1c01534c79ac6cbd67b8f334d9708dda1cb
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/Packet.cpp
@@ -0,0 +1,191 @@
+#include "stdafx.h"
+#include "Packet.hpp"
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+#include <chrono>
+
+using namespace std;
+
+Packet::Packet() {
+	isValid = false;
+}
+
+Packet::Packet(uint8_t _type, uint8_t _subtype, uint16_t _id,
+	const vector<unsigned char>& _payload)
+	: type{ _type }
+	, subtype{ _subtype }
+	, id{ _id }
+	, payload{ _payload }
+	, isValid{ true } {
+
+	checksum = 0xBE;
+	
+	checksum ^= type;
+	checksum ^= subtype;
+	checksum ^= (id >> 8);
+	checksum ^= (id & 0xFF);
+	checksum ^= (payload.size() >> 8) & 0xFF;
+	checksum ^= (payload.size() & 0xFF);
+	
+	for (auto& byte : payload) {
+		checksum ^= byte;
+	}
+}
+
+Packet::operator bool() const {
+	return isValid;
+}
+
+
+string Packet::toString() const {
+	stringstream ss;
+	ss << "[ID]\t" + to_string(id) +
+		"\n[Type]\t" + to_string(type) +
+		"\n[Subtype]\t" + to_string(subtype) +
+		"\n[Length]\t" + to_string(payload.size()) +
+		"\n[Payload]\t{ ";
+
+
+	for (auto& byte : payload) {
+		ss << std::hex << (int)byte << " ";
+	}
+
+	ss << "}";
+
+	return ss.str();
+}
+
+vector<unsigned char> Packet::toVector() const {
+	vector<unsigned char> buf({ 0xBE, type, subtype, static_cast<uint8_t>(id & 0xFF), static_cast<uint8_t>(id >> 8) });
+
+	buf.insert(buf.end(), payload.begin(), payload.end());
+	buf.push_back(checksum);
+
+	return buf;
+}
+
+vector<Packet> parsePacket(const vector<unsigned char>& bytes) {
+	static vector<unsigned char> savedBytes;
+	static uint16_t id = 0;
+	static bool first = true;
+	static chrono::high_resolution_clock::time_point lastTime;
+
+	if (bytes.size() == 0)
+		return vector<Packet>();
+
+	/*
+	auto now = chrono::high_resolution_clock::now();
+
+	if (first) {
+		first = false;
+	}
+	else {
+		auto durationMs = chrono::duration_cast<chrono::microseconds>(now - lastTime);
+		double us = chrono::duration<double, micro>(durationMs).count();
+
+		double baudrate = 10000000. * bytes.size() / us;
+
+		if (baudrate > (640. / 0.005)) {
+			cout << us << endl;
+			cout << "[Warning] High baud rate: " << baudrate << endl;
+		}
+	}
+
+	lastTime = now;
+	*/
+
+	if (bytes.size() > 64)
+		cout << '|';
+	
+	vector<Packet> foundPackets;
+	
+	savedBytes.insert(savedBytes.end(), bytes.begin(), bytes.end());
+
+	Packet p;
+	while ((p = findPacket(savedBytes))) {
+		foundPackets.push_back(p);
+
+		if (p.id != id) {
+			cout << "[Warning] Unexpected packet ID (received " << p.id << ", expected " << id << "):\n" << p.toString() << endl;
+		}
+
+		id = p.id + 1;
+	}
+
+	return foundPackets;
+}
+
+Packet findPacket(vector<unsigned char>& bytes) {
+	static bool largePacket = false;
+	Packet found;
+	static chrono::high_resolution_clock::time_point lastTime = chrono::high_resolution_clock::now();
+	static double timeFilter = 50.;
+
+	if (bytes.size() == 0)
+		return found;
+
+	//Find start byte
+	unsigned int i;
+	for (i = 0; i < bytes.size() && bytes[i] != 0xBE; ++i);
+
+	if (i == bytes.size()) {
+		//No start byte
+		cout << "Removing junk data (" << i << " bytes)" << endl;
+
+		bytes.clear();
+		return found;
+	}
+
+	//Remove junk data
+	if (i != 0) {
+		std::cout << "Removing junk data (" << i << " bytes)" << std::endl;
+		bytes.erase(bytes.begin(), bytes.begin() + i);
+	}
+
+	if (bytes.size() >= 7) {
+		uint16_t length = bytes[5] | (bytes[6] << 8);
+
+		if (length > 100 && !largePacket) {
+			largePacket = true;
+
+			cout << "[Warning] Receiving large packet (size " << length << ")" << endl;
+		}
+
+		if (bytes.size() >= (8 + length)) {
+			//We have a full packet!
+			vector<unsigned char> payload(bytes.begin() + 7, bytes.begin() + 7 + length);
+
+			found = Packet(bytes[1], bytes[2], bytes[3] | (bytes[4] << 8), payload);
+
+			if (found.checksum != bytes[7 + length]) {
+				cout << "[Error] Invalid checksum:\n" << found.toString();
+				found.isValid = false;
+			}
+
+			//Remove the packet data
+			bytes.erase(bytes.begin(), bytes.begin() + 8 + length);
+
+			//Clear the large packet flag
+			largePacket = false;
+
+			auto now = chrono::high_resolution_clock::now();
+
+			auto ms = chrono::duration_cast<chrono::milliseconds>(now - lastTime);
+			double duration = chrono::duration<double, milli>(ms).count();
+
+			double baud = 10000. * (8 + length) / duration;
+
+			if (duration > (2 * timeFilter)) {
+				cout << "[Warning] Jitter: Average duration " << (int)timeFilter << "ms, this one " << (int)duration << "ms" << endl;
+			}
+
+			timeFilter = timeFilter*0.5 + duration*0.5;
+
+			lastTime = now;
+		}
+	}
+
+	return found;
+}
\ No newline at end of file
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole/Packet.hpp b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/Packet.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e20be54435447db332fd15348aa34fcd43e52ddc
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/Packet.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <vector>
+#include <string>
+#include <stdint.h>
+
+struct Packet
+{
+	Packet();
+	Packet(uint8_t type, uint8_t subtype, uint16_t id,
+		const std::vector<unsigned char>& payload);
+
+	operator bool() const;
+
+	std::string toString() const;
+
+	std::vector<unsigned char> toVector() const;
+
+	uint8_t type, subtype;
+	uint16_t id;
+	//uint16_t length;
+	std::vector<unsigned char> payload;
+	uint8_t checksum;
+	bool isValid;
+};
+
+std::vector<Packet> parsePacket(const std::vector<unsigned char>&);
+
+Packet findPacket(std::vector<unsigned char>&);
\ No newline at end of file
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole/ReadMe.txt b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/ReadMe.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2a242cc3739a53f906a5f6d33c56f4a54e5cc51c
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/ReadMe.txt
@@ -0,0 +1,40 @@
+========================================================================
+    CONSOLE APPLICATION : SerialEchoConsole Project Overview
+========================================================================
+
+AppWizard has created this SerialEchoConsole application for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your SerialEchoConsole application.
+
+
+SerialEchoConsole.vcxproj
+    This is the main project file for VC++ projects generated using an Application Wizard.
+    It contains information about the version of Visual C++ that generated the file, and
+    information about the platforms, configurations, and project features selected with the
+    Application Wizard.
+
+SerialEchoConsole.vcxproj.filters
+    This is the filters file for VC++ projects generated using an Application Wizard. 
+    It contains information about the association between the files in your project 
+    and the filters. This association is used in the IDE to show grouping of files with
+    similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+    "Source Files" filter).
+
+SerialEchoConsole.cpp
+    This is the main application source file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+    These files are used to build a precompiled header (PCH) file
+    named SerialEchoConsole.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialEchoConsole.cpp b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialEchoConsole.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b67d3d3286cb76ec46beb8abfb6fd264ac6666e2
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialEchoConsole.cpp
@@ -0,0 +1,130 @@
+#include "stdafx.h"
+#include "SerialPort.h"
+#include "Packet.hpp"
+#include <conio.h>
+#include <thread>
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <chrono>
+
+#define SEND_SIZE 512
+#define DELAY 10
+
+
+void printHex(std::vector<unsigned char> data) {
+	for (int i = 0; i < SEND_SIZE; i++) {
+		std::cout << std::setw(2) << std::hex << (int)data[i] << ":";
+	}
+}
+
+
+int n_matches = 0;
+
+int main(int argc, char* argv[]) {
+	if (argc != 3) {
+		std::cout << "[Error] Usage: " << argv[0]
+			<< " [Comm Port] [baud]" << std::endl;
+		return -1;
+	}
+
+	/*
+	std::vector<unsigned char> testData({ 0x00, 0xBE, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF });
+
+	while (true) {
+		for (auto& byte : testData) {
+			auto packets = parsePacket({ byte });
+			for (auto& packet : packets) {
+				//std::cout << "[Info] Found packet with type " << (int)packet.type
+					//<< " and length " << (int)packet.payload.size() << std::endl;
+				std::cout << "Found packet:\n" << packet.toString() << "\n" << std::endl;
+			}
+		}
+		std::this_thread::sleep_for(std::chrono::milliseconds(500));
+	}
+	*/
+
+	int port = std::stoi(std::string(argv[1])),
+		baud = std::stoi(std::string(argv[2]));
+
+	//Create SerialPort object
+	SerialPort serial(port, baud);
+
+	//Connect to serial device
+	try {
+		serial.Connect();
+	}
+	catch (const std::exception& e) {
+		std::cout << "[Error] trying to connect: " << e.what() << std::endl;
+
+		return -1;
+	}
+
+	while (serial.IsConnected()) {
+		auto packets = parsePacket(serial.Read());
+
+		for (auto& packet : packets) {
+			std::cout << '.';
+			//std::cout << "Found packet:\n" << packet.toString() << "\n" << std::endl;
+		}
+	}
+
+
+	/*
+	std::vector<unsigned char> send_data;
+	for (int i = 0; i < SEND_SIZE; i++) {
+		send_data.push_back(i % 256);
+	}
+
+	std::vector<unsigned char> recvd_data;
+
+	std::chrono::milliseconds last_sent = std::chrono::milliseconds(0);
+	while (serial.IsConnected()) {
+		std::chrono::milliseconds now_time = std::chrono::duration_cast< std::chrono::milliseconds >(
+					std::chrono::system_clock::now().time_since_epoch());
+		if ((now_time - last_sent) > std::chrono::milliseconds(DELAY)) {
+			serial.Send(send_data);
+			last_sent = now_time;
+		}
+
+		auto read = serial.Read();
+		recvd_data.insert(recvd_data.end(), read.begin(), read.end());
+
+		if (recvd_data.size() >= SEND_SIZE) {
+			bool matches = true;
+			for (int i = 0; i < SEND_SIZE; i++) {
+				if (recvd_data[i] != send_data[i]) {
+					matches = false;
+				}
+			}
+			if (!matches) {
+				std::cout << "Mismatch on receive" << std::endl;
+				std::cout << "Successfully matched " << n_matches << std::endl;
+
+				std::cout << "Expected ";
+				printHex(send_data);
+				std::cout << std::endl;
+				std::cout << "Received ";
+				printHex(recvd_data);
+				std::cout << std::endl;
+			}
+			else {
+				std::cout << "Matches" << std::endl;
+				n_matches++;
+			}
+			recvd_data = { recvd_data.begin() + SEND_SIZE, recvd_data.end() };
+		}
+
+		if (kbhit()) {
+			exit(0);
+			//unsigned char c = (unsigned char)getch();
+			//serial.Send({ c });
+			//std::cout << "Sent " << c << std::endl;
+		}
+	}
+
+	*/
+	return 0;
+}
+
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialEchoConsole.vcxproj b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialEchoConsole.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..bf0e089fcb2f834689fd4e0cdf95b2ba76dd871b
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialEchoConsole.vcxproj
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{C2ACDB47-A077-43EB-AA59-DD7E33DEAEE2}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>SerialEchoConsole</RootNamespace>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>NotSet</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>NotSet</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Packet.hpp" />
+    <ClInclude Include="SerialPort.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Packet.cpp" />
+    <ClCompile Include="SerialEchoConsole.cpp" />
+    <ClCompile Include="SerialPort.cpp" />
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialPort.cpp b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialPort.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7d074b393468488da3084add486dc5a8bdea925d
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialPort.cpp
@@ -0,0 +1,119 @@
+#include "stdafx.h"
+#include "SerialPort.h"
+
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+SerialPort::SerialPort(unsigned char id, unsigned int baud) {
+	comHandle = INVALID_HANDLE_VALUE;
+	connected = false;
+
+	this->port = id;
+	this->baud = baud;
+
+	//Connect();
+}
+
+void SerialPort::Connect() {
+	DCB dcb;
+	COMMTIMEOUTS timeouts;
+
+	std::string portName = "\\\\.\\COM" + std::to_string(port);
+
+	if (connected || (comHandle != INVALID_HANDLE_VALUE))
+		throw Exception("SerialPort already connected.");
+
+	comHandle = CreateFile(portName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
+
+	if (comHandle == INVALID_HANDLE_VALUE)
+		throw Exception("Unable to open COM port.");
+
+	GetCommState(comHandle, &dcb);
+
+	dcb.BaudRate = baud;
+	dcb.fBinary = 1;
+	dcb.Parity = NOPARITY;
+	dcb.StopBits = TWOSTOPBITS;
+	dcb.ByteSize = 8;
+
+	if (!SetCommState(comHandle, &dcb)) {
+		Disconnect();
+		
+		throw Exception("Unable to set COM port parameters.");
+	}
+
+	timeouts.ReadIntervalTimeout = MAXDWORD;
+	timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+	timeouts.ReadTotalTimeoutConstant = 1;
+	timeouts.WriteTotalTimeoutConstant = 1;
+	timeouts.WriteTotalTimeoutMultiplier = 1;
+
+	if (!SetCommTimeouts(comHandle, &timeouts)) {
+		Disconnect();
+		
+		throw Exception("Unable to set COM port timeouts.");
+	}
+
+	connected = true;
+}
+
+void SerialPort::Disconnect() {
+	if (!connected)
+		return;
+
+	CloseHandle(comHandle);
+	
+	comHandle = INVALID_HANDLE_VALUE;
+	connected = false;
+}
+
+bool SerialPort::IsConnected() {
+	return connected;
+}
+
+void SerialPort::Send(std::vector<unsigned char> data) {
+	DWORD nWritten;
+	unsigned int totalSent = 0, attempts = 0;
+
+	if (!IsConnected())
+		throw Exception("SerialPort not connected.");
+
+	while (totalSent < data.size()) {
+		bool failed = false;
+		if (!WriteFile(comHandle, (LPCVOID)(data.data() + totalSent), data.size() - totalSent, &nWritten, NULL))
+			failed = true;
+
+		if (attempts++ > 10)
+			failed = true;
+
+		if (failed) {
+			Disconnect();
+			throw Exception("Unable to send data.");
+		}
+		totalSent += nWritten;
+	}
+}
+
+std::vector<unsigned char> SerialPort::Read() {
+	if (!IsConnected())
+		throw Exception("SerialPort not connected.");
+
+	DWORD nRead;
+	unsigned char buffer[32];
+
+	if (!ReadFile(comHandle, (LPVOID)buffer, 32, &nRead, NULL)) {
+		Disconnect();
+		throw Exception("Unable to receive data.");
+	}
+
+	std::vector<unsigned char> data;
+	data.assign(buffer, buffer + nRead);
+
+	return data;
+}
+
+SerialPort::~SerialPort() {
+	if (IsConnected())
+		Disconnect();
+}
\ No newline at end of file
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialPort.h b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialPort.h
new file mode 100644
index 0000000000000000000000000000000000000000..a37be9ec935c52c1983e588494180df327bea858
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/SerialPort.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <vector>
+#include <string>
+#include <Windows.h>
+#include <exception>
+
+class SerialPort {
+public:
+	static const int ERROR_SETTING_COMM_SETTINGS = -1;
+	static const int ERROR_SETTING_COMM_TIMEOUTS = -2;
+	static const int ERROR_OPENING_COMM_PORT = -3;
+	static const int ERROR_SENDING_COMM = -4;
+	static const int ERROR_PORT_NOT_READY = -5;
+	static const int ERROR_GENERIC_WRITE_FAIL = -6;
+	static const int ERROR_GENERIC_READ_FAIL = -7;
+	static const int ERROR_GIVEN_NULL_POINTER = -8;
+
+	class Exception : std::exception {
+	public:
+		Exception(std::string message) { _msg = std::string("SerialPort Exception: " + message); }
+
+		virtual const char *what() { return _msg.c_str(); }
+	private:
+		std::string _msg;
+	};
+
+	SerialPort(unsigned char id, unsigned int baud);
+
+	void Connect();
+	void Disconnect();
+
+	bool IsConnected();
+
+	void Send(std::vector<unsigned char> data);
+	std::vector<unsigned char> Read();
+
+	~SerialPort();
+private:
+	HANDLE comHandle;
+	unsigned int baud, port;
+	bool connected;
+};
\ No newline at end of file
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole/stdafx.cpp b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/stdafx.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f4e074442d8dec619646b8ddfb40217891de4aec
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// SerialEchoConsole.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole/stdafx.h b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/stdafx.h
new file mode 100644
index 0000000000000000000000000000000000000000..47a0d0252b148bbb77eca0042cbf79e4e65f4fc8
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/wifi_bridge/SerialEchoConsole/SerialEchoConsole/targetver.h b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/targetver.h
new file mode 100644
index 0000000000000000000000000000000000000000..90e767bfce745c059344fcd374185b064f09dcf7
--- /dev/null
+++ b/wifi_bridge/SerialEchoConsole/SerialEchoConsole/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/WiFiTelnetToSerial_test/WiFiTelnetToSerial_test.ino b/wifi_bridge/simple_bridge/simple_bridge.ino
similarity index 100%
rename from WiFiTelnetToSerial_test/WiFiTelnetToSerial_test.ino
rename to wifi_bridge/simple_bridge/simple_bridge.ino
diff --git a/WiFiTelnetToSerial_test/tcp_corrup_test.py b/wifi_bridge/simple_bridge/tcp_corrup_test.py
similarity index 100%
rename from WiFiTelnetToSerial_test/tcp_corrup_test.py
rename to wifi_bridge/simple_bridge/tcp_corrup_test.py
diff --git a/wifi_dropin/circ_buffer.c b/wifi_bridge/wifi_dropin_old/circ_buffer.c
similarity index 100%
rename from wifi_dropin/circ_buffer.c
rename to wifi_bridge/wifi_dropin_old/circ_buffer.c
diff --git a/wifi_dropin/circ_buffer.h b/wifi_bridge/wifi_dropin_old/circ_buffer.h
similarity index 100%
rename from wifi_dropin/circ_buffer.h
rename to wifi_bridge/wifi_dropin_old/circ_buffer.h
diff --git a/wifi_bridge/wifi_dropin_old/wifi_dropin_before_debug_changes.ino b/wifi_bridge/wifi_dropin_old/wifi_dropin_before_debug_changes.ino
new file mode 100644
index 0000000000000000000000000000000000000000..dfc4493dd30198cf0763e75dbe3f7301fa9c2cc9
--- /dev/null
+++ b/wifi_bridge/wifi_dropin_old/wifi_dropin_before_debug_changes.ino
@@ -0,0 +1,178 @@
+extern "C" {
+#include "user_interface.h"
+#include "circ_buffer.h"
+}
+#include <ESP8266WiFi.h>
+#include <algorithm>
+
+char ssid[] = "uCart_AP";  // Network name of hosted network
+char pass[] = "password"; 
+IPAddress client_ip;
+
+unsigned int tcp_port = 8080;
+// Server object for listening for requests
+WiFiServer server(tcp_port);
+// Reusable client object to communicate with the connected client
+WiFiClient client;
+
+
+// Maximum number of bytes to read at a time
+const int BUF_SIZE = 1024;
+byte* tcp_in_buffer = new byte[BUF_SIZE];
+//byte tcp_in_buffer[BUF_SIZE];
+//byte serial_in_buf[BUF_SIZE];
+byte* serial_in_buf = new byte[BUF_SIZE];
+//byte dummy_data[400];
+byte* dummy_data = new byte[BUF_SIZE];
+const int SEND_BUF_SIZE = 1024;
+
+void setup() {
+  // Set baud rate for UART
+  Serial.begin(115200);
+  Serial.setTimeout(2000);
+  Serial.setRxBufferSize(1024);
+  //Serial.print("Serial TX buffer size: ");
+  Serial.println(Serial.availableForWrite());
+
+  pinMode(0, OUTPUT);
+  pinMode(2, OUTPUT);
+  digitalWrite(2, LOW);
+
+/*
+  WiFiEventHandler client_disconnected_handler = WiFi.onSoftAPModeStationDisconnected(
+    [](const WiFiEventSoftAPModeStationDisconnected& event) {
+      //Serial.println("disconnected");
+  });
+*/
+  
+  // Configure chip to be access point
+  WiFi.mode(WIFI_AP);
+
+  // Wait for Access point to be created
+  while (!WiFi.softAP(ssid)) {
+    delay(500); // Wait half a second before re-trying
+  }
+
+  waitForStation();
+  
+  // Begin TCP on a particular port
+  server.begin();
+  server.setNoDelay(true);
+
+}
+
+void waitForStation() {
+  // Wait for a client to connect
+  struct station_info* connected_stns = NULL;
+  while (connected_stns = wifi_softap_get_station_info(), !connected_stns) {
+    delay(500);
+  }
+  client_ip = IPAddress(IP2STR(&connected_stns->ip));
+  wifi_softap_free_station_info();
+}
+
+int led_on = 0;
+int loop_count = 0;
+void loop() {
+  if (!(loop_count % 5000)) {
+    digitalWrite(0, led_on ? HIGH : LOW);
+    led_on = !led_on;
+  }
+  loop_count++;
+  // Assume only one client will connect at a time. If a new request has arrived,
+  // that means the old client has expired, and the new one should be used
+  WiFiClient new_client = server.available();
+  
+  if (new_client) {
+    // Read and forward any unread data
+    tcpToSerial();
+    // Close existing client
+    client.stop();
+    // Make new client the active one
+    client = new_client;
+    // Disable Nagle algorithm to decrease latency
+    //client.setNoDelay(true);
+  }
+  
+  if (client.connected() && client.available()) {
+    // Send any unsent data
+    //sendTCPBacklog();
+    tcpToSerial();
+  }
+
+  // Try reading Serial data
+  int to_read = std::min(Serial.available(), BUF_SIZE);
+  to_read = 0;
+  if (to_read) {
+    Serial.readBytes(serial_in_buf, to_read);
+    sendTCP(serial_in_buf, to_read);
+    to_read = std::min(Serial.available(), BUF_SIZE);
+  }
+
+}
+
+void tcpToSerial() {
+  if (client.available()) {
+    // Don't read more than Serial can write at once, to prevent blocking
+    ssize_t n_to_read = std::min(client.available(), BUF_SIZE);//, Serial.availableForWrite());
+    if (n_to_read > 0) {
+      client.read(tcp_in_buffer, n_to_read);
+      sendTCP(tcp_in_buffer, n_to_read);
+    }
+    //sendSerial(tcp_in_buffer, n_to_read);
+  }
+}
+
+int write_cnt = 0;
+int write_led_on = 0;
+void sendTCP(byte data[], size_t n_bytes) {
+  size_t to_write = n_bytes;
+  //to_write = 400;
+  size_t total_written = 0;
+  while (client.connected() && to_write) {
+    //if (!(write_cnt % 2)) {
+    //  digitalWrite(2, write_led_on ? HIGH : LOW);
+    //  write_led_on = !led_on;
+    //}
+    //write_cnt++;
+    
+    //sendTCPBacklog();
+    size_t written = client.write((const uint8_t*) data + total_written, to_write);
+    //size_t written = client.write((const uint8_t*) dummy_data + total_written, to_write);
+    delay(1);
+    if (written != to_write) {
+      Serial.println(written);
+    }
+    if (written == 0) {
+      digitalWrite(2, HIGH);
+    }
+    total_written += written;
+    to_write = to_write - written;
+    to_write = 0;
+  }
+  digitalWrite(2, LOW);
+}
+
+void sendTCPBacklog() {
+  struct data_chunk needs_sent = getChunk();
+  if (needs_sent.length) {
+    size_t written = client.write((const uint8_t*) needs_sent.data, needs_sent.length);
+    markConsumed(written);
+  }
+}
+
+//void sendUDP(byte data[], int n_bytes) {
+//  udp.beginPacket(address, localPort);
+//  udp.write(data, n_bytes);
+//  udp.endPacket();
+//}
+
+void sendSerial(byte data[], int n_bytes) {
+  int to_write = n_bytes;
+  while (to_write) {
+    int written = Serial.write(data, to_write);
+    to_write -= written;
+  }
+}
+
+
diff --git a/wifi_dropin/wifi_dropin.ino b/wifi_bridge/wifi_dropin_old/wifi_dropin_old.ino
similarity index 100%
rename from wifi_dropin/wifi_dropin.ino
rename to wifi_bridge/wifi_dropin_old/wifi_dropin_old.ino