blob: 1150c5506368fd6464c65a64691858f459745d19 [file] [log] [blame]
Daniel Petti059be422013-12-14 19:47:42 -08001#include <cmath>
2#include <cstring>
3#include <fcntl.h>
4#include <termios.h>
5#include <unistd.h>
6
7#include "aos/common/logging/logging_impl.h"
8#include "bbb_cape/src/cape/cows.h"
9#include "crc.h"
10#include "uart_receiver.h"
11
12// This is the code for receiving data from the cape via UART.
13// NOTE: In order for this to work, you MUST HAVE "capemgr.enable_partno=BB_UART1"
14// in your BBB's /media/BEAGLEBONE/uEnv.txt file!
15
16namespace bbb {
17
18UartReceiver::UartReceiver(speed_t baud_rate, size_t packet_size) :
19 baud_rate_(baud_rate), packet_size_(packet_size) {
20 //packet_size_ should be a multiple of four.
21 int toadd = packet_size_ % 4;
22 LOG(DEBUG, "Increasing packet size by %d bytes.\n", toadd);
23 packet_size_ += toadd;
24
25 // See cows.h for where this comes from.
26 stuffed_size_ = ((packet_size_ - 1) / (pow(2, 32) - 1) + 1) * 4 + packet_size_;
27
28 buf_ = static_cast<char *>(malloc(stuffed_size_));
29}
30
31UartReceiver::~UartReceiver() {
32 free(buf_);
33}
34
35int UartReceiver::SetUp() {
36 termios cape;
37
38 if ((fd_ = open("/dev/ttyO1", O_RDWR | O_NOCTTY)) < 0) {
39 LOG(FATAL, "Open() failed with error %d.\
40 (Did you read my note in uart_receiver.cc?)\n", fd_);
41 }
42 if (int ret = tcgetattr(fd_, &cape)) {
43 LOG(ERROR, "Tcgetattr() failed with error %d.\n", ret);
44 return -1;
45 }
46 if (int ret = cfsetispeed(&cape, baud_rate_) < 0) {
47 LOG(ERROR, "Cfsetispeed() failed with error %d.\n", ret);
48 return -1;
49 }
50
51 cape.c_iflag = 0;
52 cape.c_oflag = 0;
53 cape.c_lflag = 0;
54 cape.c_cc[VMIN] = 0;
55 cape.c_cc[VTIME] = 0;
56
57 tcsetattr(fd_, TCSANOW, &cape);
58
59 return 0;
60}
61
62int UartReceiver::GetPacket(DataStruct *packet) {
63 int pstarti = 0, bread, cons_zeros = 0;
64 uint32_t readi = 0;
65 bool done = false, has_packet = false;
66 uint32_t ptemp [(stuffed_size_ - 1) / 4 + 1];
67
68 while (!done && buf_used_ < stuffed_size_) {
69 if ((bread = read(fd_, buf_ + buf_used_, stuffed_size_ - buf_used_)) < 0) {
70 LOG(WARNING, "Read() failed with error %d.\n", bread);
71 return -1;
72 }
73 buf_used_ += bread;
74
75 // Find the beginning of the packet.
76 // Look for four bytes of zeros.
77 while (readi < buf_used_) {
78 if (buf_[readi] == 0) {
79 if (cons_zeros == 4) {
80 if (has_packet) {
81 // We got to the end of a packet.
82 done = true;
83 break;
84 } else {
85 // We got to the start of a packet.
86 has_packet = true;
87 pstarti = readi - 3;
88 }
89 } else {
90 ++cons_zeros;
91 }
92 } else {
93 cons_zeros = 0;
94 }
95 }
96 ++readi;
97 }
98
99 // Copy packet data to output.
100 int filled = 0;
101 readi -= 3;
102 for (uint32_t i = pstarti; i < readi - 3; ++i) {
103 ptemp[i] = buf_[i];
104 ++filled;
105 }
106 // Move everything we didn't use to the beginning of the buffer for next time.
107 uint32_t puti = 0;
108 for (uint32_t i = readi; i < stuffed_size_; ++i) {
109 buf_[puti++] = buf_[i];
110 }
111 buf_used_ = stuffed_size_ - readi;
112
113 // Cows algorithm always outputs something 4-byte aligned.
114 if (filled % 4) {
115 LOG(WARNING, "Rejecting packet due to it not being possible\
116 for cows to have created it.\n");
117 return -1;
118 }
119
120 // Unstuff our packet.
121 uint32_t ptemp_unstuffed [packet_size_];
122 uint32_t bunstuffed;
123 if ((bunstuffed = cows_unstuff(ptemp, sizeof(ptemp), ptemp_unstuffed)) == 0) {
124 LOG(WARNING, "Rejecting packet due to failure to unstuff it.\n");
125 return -1;
126 }
127 if (bunstuffed != packet_size_) {
128 LOG(WARNING, "Rejecting packet of wrong size.\
129 Expected packet of size %d, got packet of size %d.\n",
130 packet_size_, bunstuffed);
131 return -1;
132 }
133
134 // Make sure the checksum checks out.
135 uint32_t checksum = static_cast<uint32_t>(ptemp_unstuffed[packet_size_ - 4]);
136 memcpy(packet, ptemp_unstuffed, sizeof(DataStruct));
137 if (cape::CalculateChecksum((uint8_t *)packet, sizeof(DataStruct)) != checksum) {
138 LOG(WARNING, "Rejecting packet due to checksum failure.\n");
139 return -1;
140 }
141
142 return 0;
143}
144
145} //bbb
146