Finished initial uart code, it compiles.
The next task is writting unit tests for it.
Also fixed some minor issues in Brian's code.
Finally, fixed a minor problem in download_externals.sh
that was causing things not to build properly.
diff --git a/bbb_cape/src/bbb/bbb.gyp b/bbb_cape/src/bbb/bbb.gyp
index a2d62ea..9040140 100644
--- a/bbb_cape/src/bbb/bbb.gyp
+++ b/bbb_cape/src/bbb/bbb.gyp
@@ -10,5 +10,17 @@
'crc.cc',
],
},
+ {
+ 'target_name': 'uart_receiver',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'crc',
+ '<(DEPTH)/bbb_cape/src/cape/cape.gyp:cows',
+ '<(AOS)/build/aos.gyp:logging',
+ ],
+ 'sources': [
+ 'uart_receiver.cc',
+ ],
+ },
],
}
diff --git a/bbb_cape/src/bbb/crc.cc b/bbb_cape/src/bbb/crc.cc
index b770f37..60e665a 100644
--- a/bbb_cape/src/bbb/crc.cc
+++ b/bbb_cape/src/bbb/crc.cc
@@ -1,4 +1,4 @@
-#include "bbb/crc.h"
+#include "crc.h"
#include "aos/common/once.h"
@@ -27,7 +27,7 @@
} // namespace
uint32_t CalculateChecksum(uint8_t *data, size_t length) {
- static ::aos::once<const uint32_t> table_once(GenerateTable);
+ static ::aos::Once<const uint32_t> table_once(GenerateTable);
const uint32_t *const table = table_once.Get();
uint32_t r = 0xFFFFFFFF;
diff --git a/bbb_cape/src/bbb/crc.h b/bbb_cape/src/bbb/crc.h
index b353efc..cb0bf63 100644
--- a/bbb_cape/src/bbb/crc.h
+++ b/bbb_cape/src/bbb/crc.h
@@ -1,6 +1,7 @@
#ifndef BBB_CRC_H_
#define BBB_CRC_H_
+#include <cstring>
#include <stdint.h>
namespace cape {
diff --git a/bbb_cape/src/bbb/uart_receiver.cc b/bbb_cape/src/bbb/uart_receiver.cc
new file mode 100644
index 0000000..1150c55
--- /dev/null
+++ b/bbb_cape/src/bbb/uart_receiver.cc
@@ -0,0 +1,146 @@
+#include <cmath>
+#include <cstring>
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "aos/common/logging/logging_impl.h"
+#include "bbb_cape/src/cape/cows.h"
+#include "crc.h"
+#include "uart_receiver.h"
+
+// This is the code for receiving data from the cape via UART.
+// NOTE: In order for this to work, you MUST HAVE "capemgr.enable_partno=BB_UART1"
+// in your BBB's /media/BEAGLEBONE/uEnv.txt file!
+
+namespace bbb {
+
+UartReceiver::UartReceiver(speed_t baud_rate, size_t packet_size) :
+ baud_rate_(baud_rate), packet_size_(packet_size) {
+ //packet_size_ should be a multiple of four.
+ int toadd = packet_size_ % 4;
+ LOG(DEBUG, "Increasing packet size by %d bytes.\n", toadd);
+ packet_size_ += toadd;
+
+ // See cows.h for where this comes from.
+ stuffed_size_ = ((packet_size_ - 1) / (pow(2, 32) - 1) + 1) * 4 + packet_size_;
+
+ buf_ = static_cast<char *>(malloc(stuffed_size_));
+}
+
+UartReceiver::~UartReceiver() {
+ free(buf_);
+}
+
+int UartReceiver::SetUp() {
+ termios cape;
+
+ if ((fd_ = open("/dev/ttyO1", O_RDWR | O_NOCTTY)) < 0) {
+ LOG(FATAL, "Open() failed with error %d.\
+ (Did you read my note in uart_receiver.cc?)\n", fd_);
+ }
+ if (int ret = tcgetattr(fd_, &cape)) {
+ LOG(ERROR, "Tcgetattr() failed with error %d.\n", ret);
+ return -1;
+ }
+ if (int ret = cfsetispeed(&cape, baud_rate_) < 0) {
+ LOG(ERROR, "Cfsetispeed() failed with error %d.\n", ret);
+ return -1;
+ }
+
+ cape.c_iflag = 0;
+ cape.c_oflag = 0;
+ cape.c_lflag = 0;
+ cape.c_cc[VMIN] = 0;
+ cape.c_cc[VTIME] = 0;
+
+ tcsetattr(fd_, TCSANOW, &cape);
+
+ return 0;
+}
+
+int UartReceiver::GetPacket(DataStruct *packet) {
+ int pstarti = 0, bread, cons_zeros = 0;
+ uint32_t readi = 0;
+ bool done = false, has_packet = false;
+ uint32_t ptemp [(stuffed_size_ - 1) / 4 + 1];
+
+ while (!done && buf_used_ < stuffed_size_) {
+ if ((bread = read(fd_, buf_ + buf_used_, stuffed_size_ - buf_used_)) < 0) {
+ LOG(WARNING, "Read() failed with error %d.\n", bread);
+ return -1;
+ }
+ buf_used_ += bread;
+
+ // Find the beginning of the packet.
+ // Look for four bytes of zeros.
+ while (readi < buf_used_) {
+ if (buf_[readi] == 0) {
+ if (cons_zeros == 4) {
+ if (has_packet) {
+ // We got to the end of a packet.
+ done = true;
+ break;
+ } else {
+ // We got to the start of a packet.
+ has_packet = true;
+ pstarti = readi - 3;
+ }
+ } else {
+ ++cons_zeros;
+ }
+ } else {
+ cons_zeros = 0;
+ }
+ }
+ ++readi;
+ }
+
+ // Copy packet data to output.
+ int filled = 0;
+ readi -= 3;
+ for (uint32_t i = pstarti; i < readi - 3; ++i) {
+ ptemp[i] = buf_[i];
+ ++filled;
+ }
+ // Move everything we didn't use to the beginning of the buffer for next time.
+ uint32_t puti = 0;
+ for (uint32_t i = readi; i < stuffed_size_; ++i) {
+ buf_[puti++] = buf_[i];
+ }
+ buf_used_ = stuffed_size_ - readi;
+
+ // Cows algorithm always outputs something 4-byte aligned.
+ if (filled % 4) {
+ LOG(WARNING, "Rejecting packet due to it not being possible\
+ for cows to have created it.\n");
+ return -1;
+ }
+
+ // Unstuff our packet.
+ uint32_t ptemp_unstuffed [packet_size_];
+ uint32_t bunstuffed;
+ if ((bunstuffed = cows_unstuff(ptemp, sizeof(ptemp), ptemp_unstuffed)) == 0) {
+ LOG(WARNING, "Rejecting packet due to failure to unstuff it.\n");
+ return -1;
+ }
+ if (bunstuffed != packet_size_) {
+ LOG(WARNING, "Rejecting packet of wrong size.\
+ Expected packet of size %d, got packet of size %d.\n",
+ packet_size_, bunstuffed);
+ return -1;
+ }
+
+ // Make sure the checksum checks out.
+ uint32_t checksum = static_cast<uint32_t>(ptemp_unstuffed[packet_size_ - 4]);
+ memcpy(packet, ptemp_unstuffed, sizeof(DataStruct));
+ if (cape::CalculateChecksum((uint8_t *)packet, sizeof(DataStruct)) != checksum) {
+ LOG(WARNING, "Rejecting packet due to checksum failure.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+} //bbb
+
diff --git a/bbb_cape/src/bbb/uart_receiver.h b/bbb_cape/src/bbb/uart_receiver.h
new file mode 100644
index 0000000..1a29dab
--- /dev/null
+++ b/bbb_cape/src/bbb/uart_receiver.h
@@ -0,0 +1,31 @@
+#ifndef FCR971_INPUT_UART_RECEIVER_H_
+#define FRC971_INPUT_UART_RECEIVER_H_
+
+#include <cstdint>
+#include <termios.h>
+
+#define DATA_STRUCT_NAME DataStruct
+#include <bbb_cape/src/cape/data_struct.h>
+#undef DATA_STRUCT_NAME
+
+namespace bbb {
+
+ class UartReceiver {
+ speed_t baud_rate_;
+ size_t packet_size_, stuffed_size_;
+ int fd_;
+ uint32_t buf_used_;
+ char *buf_;
+
+ public:
+ UartReceiver(speed_t baud_rate, size_t packet_size);
+ ~UartReceiver();
+ // Opens file descriptor, etc.
+ int SetUp();
+ int GetPacket(DataStruct *packet);
+
+ };
+
+} //bbb
+
+#endif
diff --git a/bbb_cape/src/cape/cape.gyp b/bbb_cape/src/cape/cape.gyp
new file mode 100644
index 0000000..e9d34ef
--- /dev/null
+++ b/bbb_cape/src/cape/cape.gyp
@@ -0,0 +1,11 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'cows',
+ 'type': 'static_library',
+ 'sources': [
+ 'cows.c',
+ ],
+ },
+ ],
+}
diff --git a/bbb_cape/src/cape/cows.c b/bbb_cape/src/cape/cows.c
index b0d168e..22bd056 100644
--- a/bbb_cape/src/cape/cows.c
+++ b/bbb_cape/src/cape/cows.c
@@ -1,4 +1,4 @@
-#include "cape/cows.h"
+#include "cows.h"
#include <limits.h>
diff --git a/bbb_cape/src/cape/cows.h b/bbb_cape/src/cape/cows.h
index a589fca..27cb556 100644
--- a/bbb_cape/src/cape/cows.h
+++ b/bbb_cape/src/cape/cows.h
@@ -18,8 +18,8 @@
// source and destination both have to be 4-byte aligned.
// Returns the total number of words written (not necessarily the maximum given
// in the above description of destination).
-uint32_t cows_stuff(const void *restrict source, size_t source_length,
- void *restrict destination);
+uint32_t cows_stuff(const void *__restrict__ source, size_t source_length,
+ void *__restrict__ destination);
// source_length will be rounded up a multiple of 4. That many bytes of source
// will be read.
@@ -27,7 +27,7 @@
// cows_stuff for the exact size it might be).
// source and destination both have to be 4-byte aligned.
// Returns the total number of words written to destination or 0 for error.
-uint32_t cows_unstuff(const uint32_t *restrict source, size_t source_length,
- uint32_t *restrict destination);
+uint32_t cows_unstuff(const uint32_t *__restrict__ source, size_t source_length,
+ uint32_t *__restrict__ destination);
#endif // CAPE_COWS_H_