From f61105587a89b7b8375f430f2a74659a49fb4d9a Mon Sep 17 00:00:00 2001
From: Brendan Bartels <bbartels@iastate.edu>
Date: Mon, 27 Mar 2017 22:01:46 -0500
Subject: [PATCH] quad: implement PWM input and outputs for the virtual quad

---
 quad/executable.mk                           |  4 +-
 quad/src/virt_quad/Makefile                  |  4 +-
 quad/src/virt_quad/README.md                 | 17 ++++
 quad/src/virt_quad/hw_impl_unix_pwm_input.c  | 85 +++++++++++---------
 quad/src/virt_quad/hw_impl_unix_pwm_output.c | 27 ++++++-
 5 files changed, 97 insertions(+), 40 deletions(-)
 create mode 100644 quad/src/virt_quad/README.md

diff --git a/quad/executable.mk b/quad/executable.mk
index d17244a83..0f5f64352 100644
--- a/quad/executable.mk
+++ b/quad/executable.mk
@@ -12,6 +12,8 @@ OBJECTS = $(patsubst %.c, $(OBJDIR)/%.o, $(SOURCES))
 
 TARGET = $(EXEDIR)/$(NAME)
 
+CLEANUP = $(TARGET) $(OBJDIR)
+
 .PHONY: default run clean
 
 ################
@@ -24,7 +26,7 @@ run: $(TARGET)
 	$(EXEDIR)/$(NAME)
 
 clean:
-	rm -rf $(TARGET) $(OBJDIR)
+	rm -rf $(CLEANUP)
 
 ####################
 ## Internal Targets
diff --git a/quad/src/virt_quad/Makefile b/quad/src/virt_quad/Makefile
index 3626790b0..76e2b857d 100644
--- a/quad/src/virt_quad/Makefile
+++ b/quad/src/virt_quad/Makefile
@@ -1,6 +1,8 @@
 TOP=../..
 
-NAME = virt_quad
+NAME = virt-quad
 REQLIBS = -lquad_app -lcomputation_graph -lm -lcommands -lgraph_blocks
 
 include $(TOP)/executable.mk
+
+CLEANUP += virt-quad-fifos
diff --git a/quad/src/virt_quad/README.md b/quad/src/virt_quad/README.md
new file mode 100644
index 000000000..e7789797a
--- /dev/null
+++ b/quad/src/virt_quad/README.md
@@ -0,0 +1,17 @@
+The Virtual Quadcopter
+----
+Look at how modular our quad is ... it can even run in a Unix environment!
+
+But really, this isn't just some token project, this is pretty useful for
+debugging routine things in the quad_app without having to fire up the
+plethoria of things required for flight in Coover 3050. In fact, you don't 
+even have to be in Coover 3050...
+
+# Using the Virtual Quad
+Start it up:
+```
+make run
+```
+
+And you can do things with it. You'll notice it will make a bunch of FIFOs in
+the current directory. Write to / read from these FIFOs as you see fit.
\ No newline at end of file
diff --git a/quad/src/virt_quad/hw_impl_unix_pwm_input.c b/quad/src/virt_quad/hw_impl_unix_pwm_input.c
index 8881f5f38..60c51234f 100644
--- a/quad/src/virt_quad/hw_impl_unix_pwm_input.c
+++ b/quad/src/virt_quad/hw_impl_unix_pwm_input.c
@@ -1,50 +1,61 @@
 #include "hw_impl_unix.h"
+#include "controllers.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+static char *fifo_dir = "virt-quad-fifos";
+static char *pwms[6];
+static int fifos[6];
+static unsigned long cache[6];
 
 int unix_pwm_input_reset(struct PWMInputDriver *self) {
+  pwms[0] = "pwm-input-throttle";
+  pwms[1] = "pwm-input-roll";
+  pwms[2] = "pwm-input-pitch";
+  pwms[3] = "pwm-input-yaw";
+  pwms[4] = "pwm-input-gear";
+  pwms[5] = "pwm-input-flap";
+
+  mkdir(fifo_dir, 0777);
+  int i;
+  for (i = 0; i < 6; i += 1) {
+    unlink(pwms[i]);
+    char fifoname[64];
+    sprintf(fifoname, "%s/%s", fifo_dir, pwms[i]);
+    mkfifo(fifoname, 0666);
+    fifos[i] = open(fifoname, O_RDONLY | O_NONBLOCK);
+  }
+
+  cache[0] = THROTTLE_MIN;
+  cache[1] = ROLL_CENTER;
+  cache[2] = PITCH_CENTER;
+  cache[3] = YAW_CENTER;
+  cache[4] = GEAR_0;
+  cache[5] = FLAP_1;
+
+  for (i = 0; i < 6; i += 1) {
+    printf("%s: %d\n", pwms[i], cache[i]);
+  }
+
   return 0;
 }
 
 int unix_pwm_input_read(struct PWMInputDriver *self,
                         unsigned int channel,
                         unsigned long *pulse_width_us) {
-  static int inc = 0;
-  unsigned long gear;
-
-  switch (channel) {
-  case 0:
-    *pulse_width_us = 100000;
-    break;
-  case 1:
-    *pulse_width_us = 100000;
-    break;
-  case 2:
-    *pulse_width_us = 100000;
-    break;
-  case 3:
-    *pulse_width_us = 100000;
-    break;
-  case 4:
-    if (inc == 0) {
-      inc += 1;
-      puts("GEAR OFF");
-    }
-    if (inc < 20) {
-      inc += 1;
-      gear = 120000;
-    }
-    else if (inc == 20) {
-      puts("GEAR ON");
-      inc += 1;
-    }
-    else {
-      gear = 140000;
+
+  char buff[16];
+  int bytes_read = read(fifos[channel], buff, 15);
+  if (bytes_read >= 6) {
+    buff[bytes_read] = '\0';
+    unsigned long val = strtoll(buff, NULL, 10);
+    if (val < max && val > min) {
+      cache[channel] = val;
+      printf("%s: %d\n", pwms[channel], val);
     }
-    *pulse_width_us = gear;
-    break;
-  case 5:
-    // flap 1
-    *pulse_width_us = 192000;
-    break;
   }
+
+  *pulse_width_us = cache[channel];
   return 0;
 }
diff --git a/quad/src/virt_quad/hw_impl_unix_pwm_output.c b/quad/src/virt_quad/hw_impl_unix_pwm_output.c
index b549cd436..3e094b37f 100644
--- a/quad/src/virt_quad/hw_impl_unix_pwm_output.c
+++ b/quad/src/virt_quad/hw_impl_unix_pwm_output.c
@@ -1,12 +1,37 @@
 #include "hw_impl_unix.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+static char *fifo_dir = "virt-quad-fifos";
+static char *output_pwms[4];
 
 int unix_pwm_output_reset(struct PWMOutputDriver *self) {
+  output_pwms[0] = "virt-quad-fifos/pwm-output-motor1";
+  output_pwms[1] = "virt-quad-fifos/pwm-output-motor2";
+  output_pwms[2] = "virt-quad-fifos/pwm-output-motor3";
+  output_pwms[3] = "virt-quad-fifos/pwm-output-motor4";
+
+  mkdir("virt-quad-fifos", 0777);
+  int i;
+  for (i = 0; i < 4; i += 1) {
+    unlink(output_pwms[i]);
+    mkfifo(output_pwms[i], 0666);
+  }
+
   return 0;
 }
 
 int unix_pwm_output_write(struct PWMOutputDriver *self,
                           unsigned int channel,
                           unsigned long pulse_width_us) {
-  //printf("PWM OUTPUT: %d %d\n", channel, pulse_width_us);
+  char buff[16];
+  int fifo = open(output_pwms[channel], O_WRONLY | O_NONBLOCK);
+  if (fifo >= 0) {
+    sprintf(buff, "%d\0", pulse_width_us);
+    int bytes_read = write(fifo, buff, strlen(buff));
+  }
+  close(fifo);
   return 0;
 }
-- 
GitLab