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