Permalink
Browse files

Single port version of a c++ UDP listener.

  • Loading branch information...
cibomahto committed May 25, 2012
1 parent 5b4dcb4 commit dd88510720ba8b13f736660f1235a28fedf361a0
Showing with 257 additions and 118 deletions.
  1. +93 −0 c++_host/LedStrip.cpp
  2. +57 −0 c++_host/LedStrip.h
  3. +50 −0 c++_host/SocketListener.cpp
  4. +30 −0 c++_host/SocketListener.h
  5. +27 −118 c++_host/host.cpp
View
@@ -0,0 +1,93 @@
+#include <iostream>
+#include <fcntl.h> /* File control definitions */
+#include <errno.h> /* Error number definitions */
+#include <termios.h> /* POSIX terminal control definitions */
+
+#include "LedStrip.h"
+
+void LedStrip::Connect(std::string portname)
+{
+ m_fd = open(portname.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
+ if (m_fd == -1)
+ {
+ perror("open_port: Unable to open port:");
+ perror(portname.c_str());
+ exit(1); // TODO: Should we actually exit here?
+ }
+
+// Don't need to set a baud rate, the teensy ignores it
+// struct termios options;
+// tcgetattr(m_fd, &options);
+// cfsetispeed(&options, B115200);
+// cfsetospeed(&options, B115200);
+// tcsetattr(m_fd, TCSANOW, &options);
+}
+
+void LedStrip::SendBytes64(char* data) {
+ int return_code;
+ int count = 0;
+
+ do {
+ return_code = write(m_fd, data, 64);
+ // If a write error occurs, it is probably because the buffer is full.
+ // Force it to drain, then try again.
+ if (return_code < 0) {
+ tcdrain(m_fd);
+ count++;
+ }
+ }
+ while (return_code < 0);
+
+ if (count > 0) {
+ std::cerr << "count=" << count << std::endl;
+ }
+}
+
+void LedStrip::ConvertColor24(char* data) {
+ char newData[24];
+
+ memset(newData,0,24);
+
+ newData[0] = 0xFF;
+ newData[8] = 0xFF;
+ newData[16] = 0xFF;
+
+
+ for (int bit_index = 7; bit_index > 0; bit_index--) {
+ for (int pixel_index = 0; pixel_index < 8; pixel_index++) {
+ newData[1 +7-bit_index] |= ((data[1 + 3*pixel_index] >> bit_index) & 1) << pixel_index;
+ newData[9 +7-bit_index] |= ((data[ 3*pixel_index] >> bit_index) & 1) << pixel_index;
+ newData[17+7-bit_index] |= ((data[2 + 3*pixel_index] >> bit_index) & 1) << pixel_index;
+ }
+ }
+
+// for (int i = 0; i < 7; i++) {
+// newData[i+1] = 0x00;
+// newData[i+9] = 0x00;
+// newData[i+17] = 0x00;
+// }
+
+ memcpy(data, newData, 24);
+}
+
+void LedStrip::LoadData(char* data) {
+ // Convert the data to the appropriate space
+ for (int index = 1; index < m_image_height*8*3; index+=24) {
+ ConvertColor24(data+index);
+ }
+
+ // Write out the appropriate amount of data
+ for (int index = 1; index < m_image_height*8*3; index+=64) {
+ SendBytes64(data+index);
+ }
+}
+
+void LedStrip::Flip() {
+ char test[64];
+ for (int index = 0; index < 64; index++) {
+ test[index] = 0x00;
+ }
+
+ // Write out the appropriate amount of data
+ SendBytes64(test);
+}
View
@@ -0,0 +1,57 @@
+#ifndef LEDSTRIP_H
+#define LEDSTRIP_H
+
+#include <string>
+
+class LedStrip {
+ public:
+ /**
+ * Create a new LedStrip
+ * @param image_width Width of the source impage
+ * @param image_height Height of the source image
+ * @param offst Row offset to write to this strip
+ */
+ LedStrip(int image_width, int image_height, int offset) :
+ m_image_width(image_width),
+ m_image_height(image_height),
+ m_offset(offset) {
+ }
+
+ /**
+ * Open a serial device for writing
+ * @param portname Name of the serial port to open (example: /dev/ttyACM0)
+ */
+ void Connect(std::string portname);
+
+ /**
+ * Write a buffer of data out to the serial port
+ * @param data Frame of color data to load, image_height*image_width*3 bytes
+ */
+ void LoadData(char* data);
+
+ /**
+ * Cause the strips to update their displays by clocking out 0's
+ */
+ void Flip();
+
+ private:
+ /**
+ * Send 64 bytes of data to the machine. Automatically handles flushing the
+ * data, and retrying if necessicary.
+ * @param data 64 bytes of data to send.
+ **/
+ void SendBytes64(char* data);
+
+ /**
+ * Convert a block of colors from split RGB format to parallal format
+ */
+ void ConvertColor24(char* data);
+
+ int m_image_width;
+ int m_image_height;
+ int m_offset;
+
+ int m_fd; // File descriptor
+};
+
+#endif
@@ -0,0 +1,50 @@
+#include <iostream>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "SocketListener.h"
+
+void SocketListener::Connect(std::string ip_address, unsigned int port) {
+ struct sockaddr_in address;
+
+ m_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (m_fd < 0)
+ {
+ perror("open_socket: Unable to open socket");
+ exit(1); // TODO: Should we actually exit here?
+ }
+
+
+ address.sin_family = AF_INET;
+ address.sin_port = htons(port);
+ inet_aton(ip_address.c_str(), &address.sin_addr);
+
+ int return_code;
+ return_code = bind(m_fd, (struct sockaddr*) &address, sizeof(struct sockaddr_in));
+ if (return_code < 0)
+ {
+ perror("open_socket: Unable to bind to port");
+ exit(1); // TODO: Should we actually exit here?
+ }
+}
+
+int SocketListener::GetFrame(char* frame, int length) {
+ int received_length = read(m_fd, frame, length);
+
+ // TODO: How to return erros here?
+ if (length != received_length) {
+ std::cerr << "Bad data frame, expected_length=" << length
+ << " received_length=" << received_length << std::endl;
+ return -1;
+ }
+
+ if (frame[0] != 0x01) {
+ std::cerr << "Bad header, expected=1"
+ << " got=" << static_cast<int>(frame[0]) << std::endl;
+ return -2;
+ }
+
+ return 0;
+}
View
@@ -0,0 +1,30 @@
+#ifndef SOCKETLISTENER_H
+#define SOCKETLISTENER_H
+
+#include <string>
+
+class SocketListener {
+ public:
+ /**
+ * Start a UDP server at the given address
+ * @param ip_address IP address to listen on (0.0.0.0 binds to all)
+ * @param port Port to listen on (58082 is popular)
+ */
+ void Connect(std::string ip_address, unsigned int port);
+
+ /**
+ * Get a frame of data from the socket and check that it is valid.
+ * @param frame Buffer to store the frame in.
+ * @param length Expected length of the frame.
+ * @return 0 if successful, < 0 if a failure occurred.
+ */
+ int GetFrame(char* frame, int length);
+
+ private:
+ std::string m_address;
+ unsigned int m_port;
+
+ int m_fd;
+};
+
+#endif
Oops, something went wrong.

0 comments on commit dd88510

Please sign in to comment.