Advertisement
Guest User

Untitled

a guest
Jul 23rd, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.79 KB | None | 0 0
  1. #ifndef BOOST_SERIAL_H
  2. #define BOOST_SERIAL_H
  3.  
  4. #include <array>
  5. #include <vector>
  6. #include <string>
  7. #include <mutex>
  8. #include <boost/asio.hpp>
  9. #include <boost/thread.hpp>
  10.  
  11. #include "MMaster.h"
  12.  
  13. class BoostSerial : AbstractSerial
  14. {
  15.   private:
  16.     //serial device stuff
  17.     boost::asio::io_service serial_service;
  18.     boost::asio::io_service::work serial_work;
  19.     boost::asio::serial_port serial;
  20.  
  21.     //async stuff
  22.     //boost::thread *asyncReadThread;
  23.     std::unique_ptr<boost::thread> asyncReadThread;
  24.     std::array<uint8_t, 256> buf;
  25.     mutable std::mutex usableBufferMtx;
  26.     std::vector<uint8_t> usableBuffer;
  27.     void asyncReadHandler(const boost::system::error_code &error, std::size_t bytes_transferred);
  28.  
  29.     //serial config stuff
  30.     int baud = 115200;
  31.  
  32.   public:
  33.     BoostSerial();
  34.     ~BoostSerial();
  35.  
  36.     //write one byte
  37.     void write(uint8_t);
  38.     //write vector of bytes
  39.     void write(std::vector<uint8_t>);
  40.     //write string
  41.     void write(std::string);//todo
  42.  
  43.     //read one character/byte
  44.     int16_t read();
  45.     //read everything as a vector of bytes
  46.     void read(std::vector<uint8_t> &);
  47.     //read everything as a string
  48.     void read(std::string &);
  49.     //read to given character (doesn't includes it in the result but removes from buffer) or to end the of buffer if character couldn't be found
  50.     void read(std::string &, char);
  51.  
  52.     //check next character in the buffer without removing it
  53.     int16_t peek();
  54.  
  55.     //open serial port and stard async read thread
  56.     void open(std::string);
  57.     bool isOpen() const;
  58.     void close();
  59.    
  60.     //returns whether there is data awaiting in the buffer
  61.     bool available() const;
  62.  
  63.     //clear buffer
  64.     void flush();
  65.  
  66.     void setBaud(int = 115200);
  67. };
  68.  
  69. void BoostSerial::asyncReadHandler(const boost::system::error_code &error, std::size_t bytes_transferred)
  70. {
  71.     //place the content of buffer array into usableBuffer vector
  72.     //usableBuffer is necessary because using handler buffer directly in read() or available() functions
  73.     //fuck ups entire world for some reason
  74.     //probably due to manipulating buffer in async_read_some
  75.     std::unique_lock<std::mutex> lk(usableBufferMtx);
  76.     for(auto i = 0; i < bytes_transferred; i++)
  77.     {
  78.         usableBuffer.push_back(buf[i]);
  79.     }
  80.     lk.unlock();
  81.  
  82.     //read async again
  83.     serial.async_read_some(
  84.         boost::asio::buffer(buf, buf.size()),
  85.         boost::bind(
  86.             &BoostSerial::asyncReadHandler,
  87.             this, boost::asio::placeholders::error,
  88.             boost::asio::placeholders::bytes_transferred));
  89. }
  90.  
  91. BoostSerial::BoostSerial() : serial_service(), serial(serial_service), serial_work(serial_service), asyncReadThread(nullptr) {}
  92.  
  93. BoostSerial::~BoostSerial()
  94. {
  95.     if (serial.is_open())
  96.         close();
  97. }
  98.  
  99. void BoostSerial::write(uint8_t c)
  100. {
  101.     std::vector<uint8_t> v({c});
  102.     write(v);
  103. }
  104.  
  105. void BoostSerial::write(std::vector<uint8_t> v)
  106. {
  107.     serial.write_some(boost::asio::buffer(v, v.size()));
  108. }
  109.  
  110. void BoostSerial::write(std::string s)
  111. {
  112.     serial.write_some(boost::asio::buffer(s, s.size()));
  113. }
  114.  
  115. int16_t BoostSerial::read()
  116. {
  117.     std::unique_lock<std::mutex> lk(usableBufferMtx);
  118.     //return -1 if there is no data available
  119.     if(!usableBuffer.size())
  120.         return -1;
  121.  
  122.     //return first element and remove it from the buffer
  123.     int res = usableBuffer[0];
  124.     usableBuffer.erase(usableBuffer.begin());
  125.     return res;
  126. }
  127.  
  128. void BoostSerial::read(std::vector<uint8_t> &v)
  129. {
  130.     //move content of buffer to user's variable
  131.     std::unique_lock<std::mutex> lk(usableBufferMtx);
  132.     v = std::move(usableBuffer);
  133.     usableBuffer.clear();
  134. }
  135.  
  136. void BoostSerial::read(std::string & s)
  137. {
  138.     s = "";
  139.     std::unique_lock<std::mutex> lk(usableBufferMtx);
  140.     for(auto i: usableBuffer)
  141.         s+=i;
  142.     usableBuffer.clear();
  143. }
  144.  
  145. void BoostSerial::read(std::string &s, char c)
  146. {  
  147.     s = "";
  148.     char x;
  149.     bool done = false;
  150.     do
  151.     {
  152.         x = read();
  153.         if(x != -1 || x != c)
  154.         {
  155.             s+=x;
  156.         }
  157.         else
  158.             done = true;
  159.     }while(!done);
  160. }
  161.  
  162. int16_t BoostSerial::peek()
  163. {
  164.     std::unique_lock<std::mutex> lk(usableBufferMtx);
  165.     //return -1 if there is no data available
  166.     if(!usableBuffer.size())
  167.         return -1;
  168.  
  169.     return usableBuffer[0];;
  170. }
  171.  
  172. void BoostSerial::open(std::string dname)
  173. {
  174.     serial.open(dname);
  175.     if (!serial.is_open())
  176.         return;
  177.  
  178.     serial.set_option(boost::asio::serial_port_base::baud_rate(baud));
  179.  
  180.     //create thread that will read incoming data asynchronously
  181.     asyncReadThread.reset(new boost::thread(boost::bind(&boost::asio::io_service::run, &serial_service)));
  182.  
  183.     //push the first read request
  184.     serial.async_read_some(
  185.         boost::asio::buffer(buf, buf.size()),
  186.         boost::bind(
  187.             &BoostSerial::asyncReadHandler,
  188.             this, boost::asio::placeholders::error,
  189.             boost::asio::placeholders::bytes_transferred));
  190. }
  191.  
  192. bool BoostSerial::isOpen() const
  193. {
  194.     return serial.is_open();
  195. }
  196.  
  197. void BoostSerial::close()
  198. {
  199.     if(!serial.is_open())
  200.         return;
  201.  
  202.     //cancel pending async processes
  203.     serial.cancel();
  204.  
  205.     //finish async read thread and delete it
  206.     serial_service.stop();
  207.     asyncReadThread->join();
  208.  
  209.     serial.close();
  210. }
  211.  
  212. bool BoostSerial::available() const
  213. {
  214.     //returns true if there are some bytes in the buffer
  215.     std::unique_lock<std::mutex> lk(usableBufferMtx);
  216.     return (bool)usableBuffer.size();
  217. }
  218.  
  219. void BoostSerial::flush()
  220. {
  221.     std::vector<uint8_t> dull;
  222.     if (available())
  223.         read(dull);
  224. }
  225.  
  226. void BoostSerial::setBaud(int baud_)
  227. {
  228.     baud = baud_;
  229.     if(serial.is_open())
  230.         serial.set_option(boost::asio::serial_port_base::baud_rate(baud));
  231. }
  232.  
  233. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement