@@ -54,7 +54,7 @@ class VescInterface::Impl
5454 : owned_ctx{new IoContext (2 )},
5555 serial_driver_{new drivers::serial_driver::SerialDriver (*owned_ctx)}
5656 {}
57- void packet_creation_thread ( );
57+ void receive_callback ( const std::vector< uint8_t > & buffer, const size_t & bytes_transferred );
5858 void on_configure ();
5959 void connect (const std::string & port);
6060
@@ -78,69 +78,66 @@ class VescInterface::Impl
7878 std::vector<uint8_t > buffer_;
7979};
8080
81- void VescInterface::Impl::packet_creation_thread ()
81+ void VescInterface::Impl::receive_callback (
82+ const std::vector<uint8_t > & temp_buffer,
83+ const size_t & bytes_transferred
84+ )
8285{
83- static auto temp_buffer = Buffer (2048 , 0 );
84- while (packet_thread_run_) {
85- const auto bytes_read = serial_driver_->port ()->receive (temp_buffer);
86- buffer_.reserve (buffer_.size () + temp_buffer.size ());
87- buffer_.insert (buffer_.end (), temp_buffer.begin (), temp_buffer.begin () + bytes_read);
88- int bytes_needed = VescFrame::VESC_MIN_FRAME_SIZE;
89- if (!buffer_.empty ()) {
90- // search buffer for valid packet(s)
91- auto iter = buffer_.begin ();
92- auto iter_begin = buffer_.begin ();
93- while (iter != buffer_.end ()) {
94- // check if valid start-of-frame character
95- if (VescFrame::VESC_SOF_VAL_SMALL_FRAME == *iter ||
96- VescFrame::VESC_SOF_VAL_LARGE_FRAME == *iter)
97- {
98- // good start, now attempt to create packet
99- std::string error;
100- VescPacketConstPtr packet =
101- VescPacketFactory::createPacket (iter, buffer_.end (), &bytes_needed, &error);
102- if (packet) {
103- // good packet, check if we skipped any data
104- if (std::distance (iter_begin, iter) > 0 ) {
105- std::ostringstream ss;
106- ss << " Out-of-sync with VESC, unknown data leading valid frame. Discarding " <<
107- std::distance (iter_begin, iter) << " bytes." ;
108- error_handler_ (ss.str ());
109- }
110- // call packet handler
111- packet_handler_ (packet);
112- // update state
113- iter = iter + packet->frame ().size ();
114- iter_begin = iter;
115- // continue to look for another frame in buffer
116- continue ;
117- } else if (bytes_needed > 0 ) {
118- // need more data, break out of while loop
119- break ; // for (iter_sof...
120- } else {
121- // else, this was not a packet, move on to next byte
122- error_handler_ (error);
86+ buffer_.reserve (buffer_.size () + bytes_transferred);
87+ buffer_.insert (buffer_.end (), temp_buffer.begin (), temp_buffer.begin () + bytes_transferred);
88+ int bytes_needed = VescFrame::VESC_MIN_FRAME_SIZE;
89+ if (!buffer_.empty ()) {
90+ // search buffer for valid packet(s)
91+ auto iter = buffer_.begin ();
92+ auto iter_begin = buffer_.begin ();
93+ while (iter != buffer_.end ()) {
94+ // check if valid start-of-frame character
95+ if (VescFrame::VESC_SOF_VAL_SMALL_FRAME == *iter ||
96+ VescFrame::VESC_SOF_VAL_LARGE_FRAME == *iter)
97+ {
98+ // good start, now attempt to create packet
99+ std::string error;
100+ VescPacketConstPtr packet =
101+ VescPacketFactory::createPacket (iter, buffer_.end (), &bytes_needed, &error);
102+ if (packet) {
103+ // good packet, check if we skipped any data
104+ if (std::distance (iter_begin, iter) > 0 ) {
105+ std::ostringstream ss;
106+ ss << " Out-of-sync with VESC, unknown data leading valid frame. Discarding " <<
107+ std::distance (iter_begin, iter) << " bytes." ;
108+ error_handler_ (ss.str ());
123109 }
110+ // call packet handler
111+ packet_handler_ (packet);
112+ // update state
113+ iter = iter + packet->frame ().size ();
114+ iter_begin = iter;
115+ // continue to look for another frame in buffer
116+ continue ;
117+ } else if (bytes_needed > 0 ) {
118+ // need more data, break out of while loop
119+ break ; // for (iter_sof...
120+ } else {
121+ // else, this was not a packet, move on to next byte
122+ error_handler_ (error);
124123 }
125-
126- iter++;
127124 }
128125
129- // if iter is at the end of the buffer, more bytes are needed
130- if (iter == buffer_.end ()) {
131- bytes_needed = VescFrame::VESC_MIN_FRAME_SIZE;
132- }
126+ iter++;
127+ }
133128
134- // erase "used" buffer
135- if (std::distance (iter_begin, iter) > 0 ) {
136- std::ostringstream ss;
137- ss << " Out-of-sync with VESC, discarding " << std::distance (iter_begin, iter) << " bytes." ;
138- error_handler_ (ss.str ());
139- }
140- buffer_.erase (buffer_.begin (), iter);
129+ // if iter is at the end of the buffer, more bytes are needed
130+ if (iter == buffer_.end ()) {
131+ bytes_needed = VescFrame::VESC_MIN_FRAME_SIZE;
141132 }
142- // Only attempt to read every 5 ms
143- std::this_thread::sleep_for (std::chrono::milliseconds (5 ));
133+
134+ // erase "used" buffer
135+ if (std::distance (iter_begin, iter) > 0 ) {
136+ std::ostringstream ss;
137+ ss << " Out-of-sync with VESC, discarding " << std::distance (iter_begin, iter) << " bytes." ;
138+ error_handler_ (ss.str ());
139+ }
140+ buffer_.erase (buffer_.begin (), iter);
144141 }
145142}
146143
@@ -155,9 +152,14 @@ void VescInterface::Impl::connect(const std::string & port)
155152 serial_driver_->init_port (port, *device_config_);
156153 if (!serial_driver_->port ()->is_open ()) {
157154 serial_driver_->port ()->open ();
155+ serial_driver_->port ()->async_receive (
156+ std::bind (
157+ &VescInterface::Impl::receive_callback, this , std::placeholders::_1,
158+ std::placeholders::_2));
158159 }
159160}
160161
162+
161163VescInterface::VescInterface (
162164 const std::string & port,
163165 const PacketHandlerFunction & packet_handler,
@@ -205,12 +207,6 @@ void VescInterface::connect(const std::string & port)
205207 ss << " Failed to open the serial port " << port << " to the VESC. " << e.what ();
206208 throw SerialException (ss.str ().c_str ());
207209 }
208-
209- // start up a monitoring thread
210- impl_->packet_thread_run_ = true ;
211- impl_->packet_thread_ = std::unique_ptr<std::thread>(
212- new std::thread (
213- &VescInterface::Impl::packet_creation_thread, impl_.get ()));
214210}
215211
216212void VescInterface::disconnect ()
@@ -219,9 +215,7 @@ void VescInterface::disconnect()
219215
220216 if (isConnected ()) {
221217 // bring down read thread
222- impl_->packet_thread_run_ = false ;
223218 requestFWVersion ();
224- impl_->packet_thread_ ->join ();
225219 impl_->serial_driver_ ->port ()->close ();
226220 }
227221}
0 commit comments