Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
Language: Cpp
BasedOnStyle: google
IndentWidth: 2
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
BreakBeforeBraces: Custom
ColumnLimit: 120
AlignTrailingComments: true
PointerAlignment: Right
UseTab: Never
AllowShortIfStatementsOnASingleLine: false
AccessModifierOffset: -2
IndentCaseLabels: false
AlignAfterOpenBracket: Align
BinPackArguments: true
BinPackParameters: false
ExperimentalAutoDetectBinPacking: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortFunctionsOnASingleLine: Inline
24 changes: 12 additions & 12 deletions examples/serial_loopback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,24 @@
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

/**
* @file serial_loopback.cpp
* @author Daniel Koch <danielpkoch@gmail.com>
*
* This example is designed for use with a USB-to-UART adapter with the RX and TX pins connected together (loopback).
* Sends a series of bytes out and prints them to the console as they are received back.
* This example is designed for use with a USB-to-UART adapter with the RX and
* TX pins connected together (loopback). Sends a series of bytes out and prints
* them to the console as they are received back.
*/

#include <async_comm/serial.h>
Expand All @@ -48,7 +50,6 @@

#define NUM_BYTES 64


/**
* @brief Callback function for the async_comm library
*
Expand All @@ -65,7 +66,6 @@ void callback(const uint8_t* buf, size_t len)
}
}


int main(int argc, char** argv)
{
// initialize
Expand Down
105 changes: 53 additions & 52 deletions examples/serial_protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,38 @@
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

/**
* @file serial_protocol.cpp
* @author Daniel Koch <danielpkoch@gmail.com>
*
* This example implements a simple serial protocol, and tests the async_comm library using that protocol on a serial
* loopback (USB-to-UART converter with the RX and TX pins connected together).
* This example implements a simple serial protocol, and tests the async_comm
* library using that protocol on a serial loopback (USB-to-UART converter with
* the RX and TX pins connected together).
*
* The message defined by the serial protocol has the following format:
*
* | Field | Type | Size (bytes) | Description |
* | Field | Type | Size (bytes) | Description |
* |------------|----------|--------------|------------------------------------------------------|
* | Start Byte | | 1 | Identifies the beginning of a message, value is 0xA5 |
* | `id` | uint32_t | 4 | Sequential message ID |
* | `v1` | uint32_t | 4 | The first data field |
* | `v2` | uint32_t | 4 | The second data field |
* | CRC | uint8_t | 1 | Cyclic redundancy check (CRC) byte |
* | Start Byte | | 1 | Identifies the beginning of a
* message, value is 0xA5 | | `id` | uint32_t | 4 | Sequential
* message ID | | `v1` | uint32_t | 4 | The
* first data field | | `v2` | uint32_t |
* 4 | The second data field | | CRC
* | uint8_t | 1 | Cyclic redundancy check (CRC) byte |
*
* The "payload" of the message is the part that contains the actual data, and consists of the `id`, `v1`, and `v2`
* fields.
* The "payload" of the message is the part that contains the actual data, and
* consists of the `id`, `v1`, and `v2` fields.
*
* The parser is implemented as a finite state machine.
*/
Expand Down Expand Up @@ -78,28 +81,29 @@
#define NUM_START_BITS 1
#define NUM_STOP_BITS 1


/**
* @brief Recursively update the cyclic redundancy check (CRC)
*
* This uses the CRC-8-CCITT polynomial.
*
* Source: http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html#gab27eaaef6d7fd096bd7d57bf3f9ba083
* Source:
* http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html#gab27eaaef6d7fd096bd7d57bf3f9ba083
*
* @param inCrc The current CRC value. This should be initialized to 0 before processing first byte.
* @param inCrc The current CRC value. This should be initialized to 0 before
* processing first byte.
* @param inData The byte being processed
* @return The new CRC value
*/
uint8_t update_crc(uint8_t inCrc, uint8_t inData)
{
uint8_t i;
uint8_t data;
uint8_t i;
uint8_t data;

data = inCrc ^ inData;

for ( i = 0; i < 8; i++ )
for (i = 0; i < 8; i++)
{
if (( data & 0x80 ) != 0 )
if ((data & 0x80) != 0)
{
data <<= 1;
data ^= 0x07;
Expand All @@ -112,32 +116,31 @@ uint8_t update_crc(uint8_t inCrc, uint8_t inData)
return data;
}


/**
* @brief Pack message contents into a buffer
* @param[out] dst Buffer in which to store the message
* @param[in] id ID field of the message
* @param[in] v1 First data field of the message
* @param[in] v2 Second data field of the message
*
* @post The specified buffer contains the complete message packet, including start byte and CRC byte
* @post The specified buffer contains the complete message packet, including
* start byte and CRC byte
*/
void pack_message(uint8_t* dst, uint32_t id, uint32_t v1, uint32_t v2)
{
dst[0] = START_BYTE;
memcpy(dst+1, &id, 4);
memcpy(dst+5, &v1, 4);
memcpy(dst+9, &v2, 4);
memcpy(dst + 1, &id, 4);
memcpy(dst + 5, &v1, 4);
memcpy(dst + 9, &v2, 4);

uint8_t crc = 0;
for (size_t i = 0; i < PACKET_LEN-1; i++)
for (size_t i = 0; i < PACKET_LEN - 1; i++)
{
crc = update_crc(crc, dst[i]);
}
dst[PACKET_LEN-1] = crc;
dst[PACKET_LEN - 1] = crc;
}


/**
* @brief Unpack the contents of a message payload buffer
* @param[in] src The buffer to unpack
Expand All @@ -148,14 +151,13 @@ void pack_message(uint8_t* dst, uint32_t id, uint32_t v1, uint32_t v2)
* @pre Buffer contains a valid message payload
* @post Payload contents have been placed into the specified variables
*/
void unpack_payload(uint8_t* src, uint32_t *id, uint32_t *v1, uint32_t *v2)
void unpack_payload(uint8_t* src, uint32_t* id, uint32_t* v1, uint32_t* v2)
{
memcpy(id, src, 4);
memcpy(v1, src+4, 4);
memcpy(v2, src+8, 4);
memcpy(v1, src + 4, 4);
memcpy(v2, src + 8, 4);
}


/**
* @brief States for the parser state machine
*/
Expand All @@ -166,16 +168,17 @@ enum ParseState
PARSE_STATE_GOT_PAYLOAD
};

ParseState parse_state = PARSE_STATE_IDLE; //!< Current state of the parser state machine
uint8_t receive_buffer[PAYLOAD_LEN]; //!< Buffer for accumulating received payload
ParseState parse_state = PARSE_STATE_IDLE; //!< Current state of the parser state machine
uint8_t receive_buffer[PAYLOAD_LEN]; //!< Buffer for accumulating received payload

volatile int receive_count = 0; //!< Keeps track of how many valid messages have been received
bool received[NUM_MSGS]; //!< Keeps track of which messages we've received back

std::mutex mutex; //!< mutex for synchronization between the main thread and callback thread
std::condition_variable condition_variable; //!< condition variable used to suspend main thread until all messages have been received back
volatile bool all_messages_received = false; //!< flag for whether all messages have been received back
volatile int receive_count = 0; //!< Keeps track of how many valid messages have been received
bool received[NUM_MSGS]; //!< Keeps track of which messages we've received back

std::mutex mutex; //!< mutex for synchronization between the main thread and
//!< callback thread
std::condition_variable condition_variable; //!< condition variable used to suspend main thread
//!< until all messages have been received back
volatile bool all_messages_received = false; //!< flag for whether all messages have been received back

/**
* @brief Passes a received byte through the parser state machine
Expand Down Expand Up @@ -223,13 +226,12 @@ void parse_byte(uint8_t byte)
}
condition_variable.notify_one();
}
} // otherwise ignore it
} // otherwise ignore it
parse_state = PARSE_STATE_IDLE;
break;
}
}


/**
* @brief Callback function for the async_comm library
*
Expand All @@ -246,7 +248,6 @@ void callback(const uint8_t* buf, size_t len)
}
}


int main(int argc, char** argv)
{
// initialize
Expand Down Expand Up @@ -281,15 +282,15 @@ int main(int argc, char** argv)
uint8_t buffer[PACKET_LEN];
for (uint32_t i = 0; i < NUM_MSGS; i++)
{
pack_message(buffer, i, i*2, i*4);
pack_message(buffer, i, i * 2, i * 4);
serial.send_bytes(buffer, PACKET_LEN);
}
auto finish_write = std::chrono::high_resolution_clock::now();

// wait to receive all messages
{
std::unique_lock<std::mutex> lock(mutex);
condition_variable.wait(lock, []{ return all_messages_received; });
condition_variable.wait(lock, [] { return all_messages_received; });
}

auto finish_read = std::chrono::high_resolution_clock::now();
Expand Down Expand Up @@ -320,8 +321,8 @@ int main(int argc, char** argv)
std::printf("Elapsed read time: %fms\n", read_time.count());

int num_bytes = NUM_MSGS * PACKET_LEN;
double expected_time = num_bytes * (8 + NUM_START_BITS + NUM_STOP_BITS) / (double) BAUD_RATE;
std::printf("Expected read time: %fms\n", expected_time*1e3);
double expected_time = num_bytes * (8 + NUM_START_BITS + NUM_STOP_BITS) / (double)BAUD_RATE;
std::printf("Expected read time: %fms\n", expected_time * 1e3);
std::printf("Total: %d bytes\n", num_bytes);

return 0;
Expand Down
21 changes: 10 additions & 11 deletions examples/tcp_client_hello_world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

/**
Expand All @@ -47,7 +48,6 @@
#include <thread>
#include <vector>


/**
* @brief Callback function for the async_comm library
*
Expand All @@ -64,7 +64,6 @@ void callback(const uint8_t* buf, size_t len)
}
}


int main()
{
// open TCP connection
Expand All @@ -81,7 +80,7 @@ int main()
for (size_t i = 0; i < 10; ++i)
{
std::string msg = "hello world " + std::to_string(i) + "!";
tcp_client.send_bytes((uint8_t*) msg.data(), msg.size());
tcp_client.send_bytes((uint8_t*)msg.data(), msg.size());
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}

Expand Down
Loading