Port to Windows
This commit is contained in:
parent
403788d559
commit
aba65b07bf
5 changed files with 218 additions and 49 deletions
36
Makefile
36
Makefile
|
|
@ -1,16 +1,42 @@
|
|||
OS = LINUX
|
||||
#OS = MACOSX
|
||||
#OS = WINDOWS
|
||||
|
||||
ifeq ($(OS), LINUX)
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -Wall
|
||||
CPPFLAGS = `$(WXCONFIG) --cppflags`
|
||||
CXX = g++
|
||||
CFLAGS = -O2 -Wall -D$(OS)
|
||||
CXXFLAGS = $(CFLAGS) `$(WXCONFIG) --cppflags`
|
||||
LDFLAGS =
|
||||
WXCONFIG = ~/wxwidgets/3.0.2.gtk2-opengl/bin/wx-config
|
||||
CLILIBS = -lglut -lGLU -lGL
|
||||
|
||||
else ifeq ($(OS), MACOSX)
|
||||
#TODO: Macintosh build...
|
||||
|
||||
else ifeq ($(OS), WINDOWS)
|
||||
CC = i686-w64-mingw32-gcc
|
||||
CXX = i686-w64-mingw32-g++
|
||||
CFLAGS = -O2 -Wall -D$(OS)
|
||||
CXXFLAGS = $(CFLAGS) `$(WXCONFIG) --cppflags`
|
||||
LDFLAGS = -static -static-libgcc
|
||||
WXCONFIG = ~/wxwidgets/3.0.2.mingw-opengl/bin/wx-config
|
||||
CLILIBS = -lglut32 -lglu32 -lopengl32
|
||||
|
||||
endif
|
||||
|
||||
|
||||
all: gui imuread
|
||||
|
||||
gui: gui.o visualize.o serialdata.o
|
||||
g++ $(CFLAGS) -o $@ $^ `$(WXCONFIG) --libs all,opengl`
|
||||
$(CXX) -s $(CFLAGS) $(LDFLAGS) -o $@ $^ `$(WXCONFIG) --libs all,opengl`
|
||||
ifeq ($(OS), WINDOWS)
|
||||
cp gui gui.exe
|
||||
endif
|
||||
|
||||
|
||||
imuread: imuread.o visualize.o serialdata.o
|
||||
$(CC) $(CFLAGS) -o $@ $^ -lglut -lGLU -lGL
|
||||
$(CC) -s $(CFLAGS) $(LDFLAGS) -o $@ $^ $(CLILIBS)
|
||||
|
||||
clean:
|
||||
rm -f gui imuread *.o
|
||||
rm -f gui imuread *.o *.exe
|
||||
|
|
|
|||
4
gui.cpp
4
gui.cpp
|
|
@ -69,7 +69,7 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title,
|
|||
{
|
||||
wxMenuBar *menuBar;
|
||||
wxMenu *menu;
|
||||
wxMenuItem *item;
|
||||
//wxMenuItem *item;
|
||||
|
||||
menuBar = new wxMenuBar;
|
||||
menu = new wxMenu;
|
||||
|
|
@ -87,7 +87,7 @@ MyFrame::MyFrame(wxWindow *parent, wxWindowID id, const wxString &title,
|
|||
{ WX_GL_RGBA, WX_GL_MIN_RED, 1, WX_GL_MIN_GREEN, 1,
|
||||
WX_GL_MIN_BLUE, 1, WX_GL_DEPTH_SIZE, 1,
|
||||
WX_GL_DOUBLEBUFFER,
|
||||
None};
|
||||
0};
|
||||
|
||||
|
||||
m_canvas = new MyCanvas(this, wxID_ANY, gl_attrib);
|
||||
|
|
|
|||
26
imuread.c
26
imuread.c
|
|
@ -1,10 +1,17 @@
|
|||
#if defined(LINUX) || defined(MACOSX)
|
||||
|
||||
#include "imuread.h"
|
||||
#include <GL/glut.h> // sudo apt-get install xorg-dev libglu1-mesa-dev freeglut3-dev
|
||||
|
||||
void die(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
static void timer_callback(int val)
|
||||
{
|
||||
int r;
|
||||
|
||||
glutTimerFunc(TIMEOUT_MSEC, timer_callback, 0);
|
||||
read_serial_data();
|
||||
r = read_serial_data();
|
||||
if (r < 0) die("Error reading %s\n", PORT);
|
||||
glutPostRedisplay(); // TODO: only redisplay if data changes
|
||||
}
|
||||
|
||||
|
|
@ -27,11 +34,26 @@ int main(int argc, char *argv[])
|
|||
glutDisplayFunc(glut_display_callback);
|
||||
glutTimerFunc(TIMEOUT_MSEC, timer_callback, 0);
|
||||
|
||||
open_port(PORT);
|
||||
if (!open_port(PORT)) die("Unable to open %s\n", PORT);
|
||||
glutMainLoop();
|
||||
close_port();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void die(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
close_port();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
22
imuread.h
22
imuread.h
|
|
@ -6,17 +6,27 @@
|
|||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/select.h>
|
||||
#if defined(LINUX)
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#elif defined(WINDOWS)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
|
||||
#define PORT "/dev/ttyACM0"
|
||||
#if defined(LINUX)
|
||||
#define PORT "/dev/ttyACM0"
|
||||
#elif defined(WINDOWS)
|
||||
#define PORT "COM3"
|
||||
#elif defined(MACOSX)
|
||||
#define PORT "/dev/cu.usbmodem123"
|
||||
#endif
|
||||
|
||||
#define TIMEOUT_MSEC 40
|
||||
|
||||
#define MAGBUFFSIZEX 14
|
||||
|
|
@ -44,10 +54,8 @@ typedef struct {
|
|||
} quat_t;
|
||||
extern quat_t current_orientation;
|
||||
|
||||
extern void die(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
extern void *malloc_or_die(size_t size);
|
||||
extern int open_port(const char *name);
|
||||
extern void read_serial_data(void);
|
||||
extern int read_serial_data(void);
|
||||
extern void close_port(void);
|
||||
void visualize_init(void);
|
||||
void display_callback(void);
|
||||
|
|
|
|||
179
serialdata.c
179
serialdata.c
|
|
@ -1,6 +1,5 @@
|
|||
#include "imuread.h"
|
||||
|
||||
static int portfd=-1;
|
||||
|
||||
void print_data(const char *name, const unsigned char *data, int len)
|
||||
{
|
||||
|
|
@ -13,7 +12,7 @@ void print_data(const char *name, const unsigned char *data, int len)
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
void packet_primary_data(const unsigned char *data)
|
||||
static void packet_primary_data(const unsigned char *data)
|
||||
{
|
||||
current_position.x = (float)((int16_t)((data[13] << 8) | data[12])) / 10.0f;
|
||||
current_position.y = (float)((int16_t)((data[15] << 8) | data[14])) / 10.0f;
|
||||
|
|
@ -39,7 +38,7 @@ void packet_primary_data(const unsigned char *data)
|
|||
#endif
|
||||
}
|
||||
|
||||
void packet_magnetic_cal(const unsigned char *data)
|
||||
static void packet_magnetic_cal(const unsigned char *data)
|
||||
{
|
||||
int16_t id, x, y, z;
|
||||
magdata_t *cal;
|
||||
|
|
@ -71,7 +70,7 @@ void packet_magnetic_cal(const unsigned char *data)
|
|||
}
|
||||
}
|
||||
|
||||
void packet(const unsigned char *data, int len)
|
||||
static void packet(const unsigned char *data, int len)
|
||||
{
|
||||
if (len <= 0) return;
|
||||
//print_data("packet", data, len);
|
||||
|
|
@ -84,7 +83,7 @@ void packet(const unsigned char *data, int len)
|
|||
// TODO: actually do something with the arriving data...
|
||||
}
|
||||
|
||||
void packet_encoded(const unsigned char *data, int len)
|
||||
static void packet_encoded(const unsigned char *data, int len)
|
||||
{
|
||||
const unsigned char *p;
|
||||
unsigned char buf[256];
|
||||
|
|
@ -124,7 +123,7 @@ void packet_encoded(const unsigned char *data, int len)
|
|||
}
|
||||
}
|
||||
|
||||
void newdata(const unsigned char *data, int len)
|
||||
static void newdata(const unsigned char *data, int len)
|
||||
{
|
||||
static unsigned char packetbuf[256];
|
||||
static unsigned int packetlen=0;
|
||||
|
|
@ -158,51 +157,61 @@ void newdata(const unsigned char *data, int len)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(LINUX)
|
||||
|
||||
static int portfd=-1;
|
||||
|
||||
int open_port(const char *name)
|
||||
{
|
||||
struct termios termsettings;
|
||||
int r;
|
||||
|
||||
portfd = open(name, O_RDWR | O_NONBLOCK);
|
||||
if (portfd < 0) die("Unable to open %s\n", name);
|
||||
|
||||
if (portfd < 0) return 0;
|
||||
r = tcgetattr(portfd, &termsettings);
|
||||
if (r < 0) die("Unable to read terminal settings from %s\n", name);
|
||||
if (r < 0) {
|
||||
close_port();
|
||||
return 0;
|
||||
}
|
||||
cfmakeraw(&termsettings);
|
||||
cfsetspeed(&termsettings, B115200);
|
||||
r = tcsetattr(portfd, TCSANOW, &termsettings);
|
||||
if (r < 0) die("Unable to program terminal settings on %s\n", name);
|
||||
return 0;
|
||||
if (r < 0) {
|
||||
close_port();
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void read_serial_data(void)
|
||||
int read_serial_data(void)
|
||||
{
|
||||
unsigned char buf[256];
|
||||
static int nodata_count=0;
|
||||
int n;
|
||||
|
||||
while (portfd >= 0) {
|
||||
if (portfd < 0) return -1;
|
||||
while (1) {
|
||||
n = read(portfd, buf, sizeof(buf));
|
||||
if (n > 0 && n <= sizeof(buf)) {
|
||||
//printf("read %d bytes\n", r);
|
||||
newdata(buf, n);
|
||||
nodata_count = 0;
|
||||
//return n;
|
||||
} else if (n == 0) {
|
||||
printf("read no data\n");
|
||||
if (++nodata_count > 6) {
|
||||
close_port();
|
||||
die("No data from %s\n", PORT);
|
||||
nodata_count = 0;
|
||||
close_port();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
return 0;
|
||||
} else {
|
||||
n = errno;
|
||||
if (n == EAGAIN) {
|
||||
break;
|
||||
} else if (n == EAGAIN) {
|
||||
return 0;
|
||||
} else if (n == EINTR) {
|
||||
} else {
|
||||
printf("read error, n=%d\n", n);
|
||||
break;
|
||||
close_port();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -216,25 +225,129 @@ void close_port(void)
|
|||
}
|
||||
}
|
||||
|
||||
#elif defined(WINDOWS)
|
||||
|
||||
void die(const char *format, ...)
|
||||
static HANDLE port_handle;
|
||||
|
||||
int open_port(const char *name)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
exit(1);
|
||||
COMMCONFIG port_cfg;
|
||||
COMMTIMEOUTS timeouts;
|
||||
DWORD len;
|
||||
char buf[64];
|
||||
int n;
|
||||
|
||||
if (strncmp(name, "COM", 3) == 0 && sscanf(name + 3, "%d", &n) == 1) {
|
||||
snprintf(buf, sizeof(buf), "\\\\.\\COM%d", n);
|
||||
name = buf;
|
||||
}
|
||||
port_handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE,
|
||||
0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||
if (port_handle == INVALID_HANDLE_VALUE) {
|
||||
return 0;
|
||||
}
|
||||
len = sizeof(COMMCONFIG);
|
||||
if (!GetCommConfig(port_handle, &port_cfg, &len)) {
|
||||
CloseHandle(port_handle);
|
||||
return 0;
|
||||
}
|
||||
port_cfg.dcb.BaudRate = 115200;
|
||||
port_cfg.dcb.fBinary = TRUE;
|
||||
port_cfg.dcb.fParity = FALSE;
|
||||
port_cfg.dcb.fOutxCtsFlow = FALSE;
|
||||
port_cfg.dcb.fOutxDsrFlow = FALSE;
|
||||
port_cfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
port_cfg.dcb.fDsrSensitivity = FALSE;
|
||||
port_cfg.dcb.fTXContinueOnXoff = TRUE; // ???
|
||||
port_cfg.dcb.fOutX = FALSE;
|
||||
port_cfg.dcb.fInX = FALSE;
|
||||
port_cfg.dcb.fErrorChar = FALSE;
|
||||
port_cfg.dcb.fNull = FALSE;
|
||||
port_cfg.dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
port_cfg.dcb.fAbortOnError = FALSE;
|
||||
port_cfg.dcb.ByteSize = 8;
|
||||
port_cfg.dcb.Parity = NOPARITY;
|
||||
port_cfg.dcb.StopBits = ONESTOPBIT;
|
||||
if (!SetCommConfig(port_handle, &port_cfg, sizeof(COMMCONFIG))) {
|
||||
CloseHandle(port_handle);
|
||||
return 0;
|
||||
}
|
||||
if (!EscapeCommFunction(port_handle, CLRDTR | CLRRTS)) {
|
||||
CloseHandle(port_handle);
|
||||
return 0;
|
||||
}
|
||||
timeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
timeouts.ReadTotalTimeoutConstant = 0;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
timeouts.WriteTotalTimeoutConstant = 0;
|
||||
if (!SetCommTimeouts(port_handle, &timeouts)) {
|
||||
CloseHandle(port_handle);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *malloc_or_die(size_t size)
|
||||
int read_serial_data(void)
|
||||
{
|
||||
void *p;
|
||||
COMSTAT st;
|
||||
DWORD errmask=0, num_read, num_request;
|
||||
OVERLAPPED ov;
|
||||
unsigned char buf[256];
|
||||
int r;
|
||||
|
||||
p = malloc(size);
|
||||
if (!p) die("unable to allocate memory, %d bytes\n", (int)size);
|
||||
return p;
|
||||
while (1) {
|
||||
if (!ClearCommError(port_handle, &errmask, &st)) return -1;
|
||||
//printf("Read, %d requested, %lu buffered\n", count, st.cbInQue);
|
||||
if (st.cbInQue <= 0) return 0;
|
||||
// now do a ReadFile, now that we know how much we can read
|
||||
// a blocking (non-overlapped) read would be simple, but win32
|
||||
// is all-or-nothing on async I/O and we must have it enabled
|
||||
// because it's the only way to get a timeout for WaitCommEvent
|
||||
if (st.cbInQue < (DWORD)sizeof(buf)) {
|
||||
num_request = st.cbInQue;
|
||||
} else {
|
||||
num_request = (DWORD)sizeof(buf);
|
||||
}
|
||||
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (ov.hEvent == NULL) {
|
||||
close_port();
|
||||
return -1;
|
||||
}
|
||||
ov.Internal = ov.InternalHigh = 0;
|
||||
ov.Offset = ov.OffsetHigh = 0;
|
||||
if (ReadFile(port_handle, buf, num_request, &num_read, &ov)) {
|
||||
// this should usually be the result, since we asked for
|
||||
// data we knew was already buffered
|
||||
//printf("Read, immediate complete, num_read=%lu\n", num_read);
|
||||
r = num_read;
|
||||
} else {
|
||||
if (GetLastError() == ERROR_IO_PENDING) {
|
||||
if (GetOverlappedResult(port_handle, &ov, &num_read, TRUE)) {
|
||||
//printf("Read, delayed, num_read=%lu\n", num_read);
|
||||
r = num_read;
|
||||
} else {
|
||||
//printf("Read, delayed error\n");
|
||||
r = -1;
|
||||
}
|
||||
} else {
|
||||
//printf("Read, error\n");
|
||||
r = -1;
|
||||
}
|
||||
}
|
||||
CloseHandle(ov.hEvent);
|
||||
if (r <= 0) break;
|
||||
newdata(buf, r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void close_port(void)
|
||||
{
|
||||
CloseHandle(port_handle);
|
||||
port_handle = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue