Skip to content

Commit

Permalink
Transitioning to git
Browse files Browse the repository at this point in the history
  • Loading branch information
Terraneo Federico committed Jul 11, 2011
0 parents commit a0e8102
Show file tree
Hide file tree
Showing 36 changed files with 4,281 additions and 0 deletions.
14 changes: 14 additions & 0 deletions 1_simple/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

cmake_minimum_required(VERSION 2.6)
project(TEST)

## Target
set(TEST_SRCS main.cpp)
add_executable(simple ${TEST_SRCS})

## Link libraries
set(BOOST_LIBS thread date_time system)
find_package(Boost COMPONENTS ${BOOST_LIBS} REQUIRED)
target_link_libraries(simple ${Boost_LIBRARIES})
find_package(Threads REQUIRED)
target_link_libraries(simple ${CMAKE_THREAD_LIBS_INIT})
8 changes: 8 additions & 0 deletions 1_simple/Makefile.windows
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#Using MinGW distro from http://nuwen.net/mingw.html that contains boost precompiled

all:
g++ -O2 -c main.cpp -D_WIN32_WINNT=0x0501
g++ -o simple.exe main.o -s -lwsock32 -lws2_32 -lboost_system

clean:
del simple.exe main.o
73 changes: 73 additions & 0 deletions 1_simple/SimpleSerial.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* File: SimpleSerial.h
* Author: Terraneo Federico
* Distributed under the Boost Software License, Version 1.0.
*
* Created on September 10, 2009, 12:12 PM
*/

#ifndef _SIMPLESERIAL_H
#define _SIMPLESERIAL_H

#include <boost/asio.hpp>

class SimpleSerial
{
public:
/**
* Constructor.
* \param port device name, example "/dev/ttyUSB0" or "COM4"
* \param baud_rate communication speed, example 9600 or 115200
* \throws boost::system::system_error if cannot open the
* serial device
*/
SimpleSerial(std::string port, unsigned int baud_rate)
: io(), serial(io,port)
{
serial.set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
}

/**
* Write a string to the serial device.
* \param s string to write
* \throws boost::system::system_error on failure
*/
void writeString(std::string s)
{
boost::asio::write(serial,boost::asio::buffer(s.c_str(),s.size()));
}

/**
* Blocks until a line is received from the serial device.
* Eventual '\n' or '\r\n' characters at the end of the string are removed.
* \return a string containing the received line
* \throws boost::system::system_error on failure
*/
std::string readLine()
{
//Reading data char by char, code is optimized for simplicity, not speed
using namespace boost;
char c;
std::string result;
for(;;)
{
asio::read(serial,asio::buffer(&c,1));
switch(c)
{
case '\r':
break;
case '\n':
return result;
default:
result+=c;
}
}
}

private:
boost::asio::io_service io;
boost::asio::serial_port serial;
};

#endif /* _SIMPLESERIAL_H */

24 changes: 24 additions & 0 deletions 1_simple/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

#include <iostream>
#include "SimpleSerial.h"

using namespace std;
using namespace boost;

int main(int argc, char* argv[])
{
try {

SimpleSerial serial("/dev/ttyUSB0",115200);

serial.writeString("Hello world\n");

cout<<"Received : "<<serial.readLine()<<" : end"<<endl;

} catch(boost::system::system_error& e)
{
cout<<"Error: "<<e.what()<<endl;
return 1;
}
}

14 changes: 14 additions & 0 deletions 2_with_timeout/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

cmake_minimum_required(VERSION 2.6)
project(TEST)

## Target
set(TEST_SRCS main.cpp TimeoutSerial.cpp)
add_executable(timeout ${TEST_SRCS})

## Link libraries
set(BOOST_LIBS thread date_time system)
find_package(Boost COMPONENTS ${BOOST_LIBS} REQUIRED)
target_link_libraries(timeout ${Boost_LIBRARIES})
find_package(Threads REQUIRED)
target_link_libraries(timeout ${CMAKE_THREAD_LIBS_INIT})
9 changes: 9 additions & 0 deletions 2_with_timeout/Makefile.windows
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#Using MinGW distro from http://nuwen.net/mingw.html that contains boost precompiled

all:
g++ -O2 -c main.cpp -D_WIN32_WINNT=0x0501
g++ -O2 -c TimeoutSerial.cpp -D_WIN32_WINNT=0x0501
g++ -o timeout.exe main.o TimeoutSerial.o -s -lwsock32 -lws2_32 -lboost_system

clean:
del timeout.exe main.o TimeoutSerial.o
234 changes: 234 additions & 0 deletions 2_with_timeout/TimeoutSerial.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/*
* File: TimeoutSerial.cpp
* Author: Terraneo Federico
* Distributed under the Boost Software License, Version 1.0.
* Created on September 12, 2009, 3:47 PM
*
* v1.04: Fixed bug with timeout set to zero
*
* v1.03: Fix for Mac OS X, now fully working on Mac.
*
* v1.02: Code cleanup, speed improvements, bug fixes.
*
* v1.01: Fixed a bug that caused errors while reading after a timeout.
*
* v1.00: First release.
*/

#include "TimeoutSerial.h"
#include <string>
#include <algorithm>
#include <iostream>
#include <boost/bind.hpp>

using namespace std;
using namespace boost;

TimeoutSerial::TimeoutSerial(): io(), port(io), timer(io),
timeout(posix_time::seconds(0)) {}

TimeoutSerial::TimeoutSerial(const std::string& devname, unsigned int baud_rate,
asio::serial_port_base::parity opt_parity,
asio::serial_port_base::character_size opt_csize,
asio::serial_port_base::flow_control opt_flow,
asio::serial_port_base::stop_bits opt_stop)
: io(), port(io), timer(io), timeout(posix_time::seconds(0))
{
open(devname,baud_rate,opt_parity,opt_csize,opt_flow,opt_stop);
}

void TimeoutSerial::open(const std::string& devname, unsigned int baud_rate,
asio::serial_port_base::parity opt_parity,
asio::serial_port_base::character_size opt_csize,
asio::serial_port_base::flow_control opt_flow,
asio::serial_port_base::stop_bits opt_stop)
{
if(isOpen()) close();
port.open(devname);
port.set_option(asio::serial_port_base::baud_rate(baud_rate));
port.set_option(opt_parity);
port.set_option(opt_csize);
port.set_option(opt_flow);
port.set_option(opt_stop);
}

bool TimeoutSerial::isOpen() const
{
return port.is_open();
}

void TimeoutSerial::close()
{
if(isOpen()==false) return;
port.close();
}

void TimeoutSerial::setTimeout(const posix_time::time_duration& t)
{
timeout=t;
}

void TimeoutSerial::write(const char *data, size_t size)
{
asio::write(port,asio::buffer(data,size));
}

void TimeoutSerial::write(const std::vector<char>& data)
{
asio::write(port,asio::buffer(&data[0],data.size()));
}

void TimeoutSerial::writeString(const std::string& s)
{
asio::write(port,asio::buffer(s.c_str(),s.size()));
}

void TimeoutSerial::read(char *data, size_t size)
{
if(readData.size()>0)//If there is some data from a previous read
{
istream is(&readData);
size_t toRead=min(readData.size(),size);//How many bytes to read?
is.read(data,toRead);
data+=toRead;
size-=toRead;
if(size==0) return;//If read data was enough, just return
}

setupParameters=ReadSetupParameters(data,size);
performReadSetup(setupParameters);

//For this code to work, there should always be a timeout, so the
//request for no timeout is translated into a very long timeout
if(timeout!=posix_time::seconds(0)) timer.expires_from_now(timeout);
else timer.expires_from_now(posix_time::hours(100000));

timer.async_wait(boost::bind(&TimeoutSerial::timeoutExpired,this,
asio::placeholders::error));

result=resultInProgress;
bytesTransferred=0;
for(;;)
{
io.run_one();
switch(result)
{
case resultSuccess:
timer.cancel();
return;
case resultTimeoutExpired:
port.cancel();
throw(timeout_exception("Timeout expired"));
case resultError:
timer.cancel();
port.cancel();
throw(boost::system::system_error(boost::system::error_code(),
"Error while reading"));
//if resultInProgress remain in the loop
}
}
}

std::vector<char> TimeoutSerial::read(size_t size)
{
vector<char> result(size,'\0');//Allocate a vector with the desired size
read(&result[0],size);//Fill it with values
return result;
}

std::string TimeoutSerial::readString(size_t size)
{
string result(size,'\0');//Allocate a string with the desired size
read(&result[0],size);//Fill it with values
return result;
}

std::string TimeoutSerial::readStringUntil(const std::string& delim)
{
// Note: if readData contains some previously read data, the call to
// async_read_until (which is done in performReadSetup) correctly handles
// it. If the data is enough it will also immediately call readCompleted()
setupParameters=ReadSetupParameters(delim);
performReadSetup(setupParameters);

//For this code to work, there should always be a timeout, so the
//request for no timeout is translated into a very long timeout
if(timeout!=posix_time::seconds(0)) timer.expires_from_now(timeout);
else timer.expires_from_now(posix_time::hours(100000));

timer.async_wait(boost::bind(&TimeoutSerial::timeoutExpired,this,
asio::placeholders::error));

result=resultInProgress;
bytesTransferred=0;
for(;;)
{
io.run_one();
switch(result)
{
case resultSuccess:
{
timer.cancel();
bytesTransferred-=delim.size();//Don't count delim
istream is(&readData);
string result(bytesTransferred,'\0');//Alloc string
is.read(&result[0],bytesTransferred);//Fill values
is.ignore(delim.size());//Remove delimiter from stream
return result;
}
case resultTimeoutExpired:
port.cancel();
throw(timeout_exception("Timeout expired"));
case resultError:
timer.cancel();
port.cancel();
throw(boost::system::system_error(boost::system::error_code(),
"Error while reading"));
//if resultInProgress remain in the loop
}
}
}

TimeoutSerial::~TimeoutSerial() {}

void TimeoutSerial::performReadSetup(const ReadSetupParameters& param)
{
if(param.fixedSize)
{
asio::async_read(port,asio::buffer(param.data,param.size),boost::bind(
&TimeoutSerial::readCompleted,this,asio::placeholders::error,
asio::placeholders::bytes_transferred));
} else {
asio::async_read_until(port,readData,param.delim,boost::bind(
&TimeoutSerial::readCompleted,this,asio::placeholders::error,
asio::placeholders::bytes_transferred));
}
}

void TimeoutSerial::timeoutExpired(const boost::system::error_code& error)
{
if(!error && result==resultInProgress) result=resultTimeoutExpired;
}

void TimeoutSerial::readCompleted(const boost::system::error_code& error,
const size_t bytesTransferred)
{
if(!error)
{
result=resultSuccess;
this->bytesTransferred=bytesTransferred;
return;
}

#ifdef __APPLE__
if(error.value()==45)
{
//Bug on OS X, it might be necessary to repeat the setup
//http://osdir.com/ml/lib.boost.asio.user/2008-08/msg00004.html
performReadSetup(setupParameters);
return;
}
#endif //__APPLE__

result=resultError;
}
Loading

0 comments on commit a0e8102

Please sign in to comment.