Commit a85f83fb845f08a7f57294ae753e0169868210b6

Authored by Enrique Díaz Roque
2 parents 63342a41 5db0f6db
Exists in master and in 1 other branch dev

Merge branch 'dev' of bizet.dis.ulpgc.es:ediaz/heisenwave into dev

app/CMakeLists.txt
... ... @@ -14,7 +14,17 @@ add_executable(
14 14 lib/tinycthread/tinycthread.c
15 15 )
16 16  
17   -add_definitions(-std=c99)
  17 +if(APPLE)
  18 + set(SYSTEM_TYPE "OS_APPLE")
  19 +elseif(UNIX)
  20 + set(SYSTEM_TYPE "OS_LINUX")
  21 +elseif(WIN32)
  22 + set(SYSTEM_TYPE "OS_WINDOWS")
  23 +else(APPLE)
  24 + set(SYSTEM_TYPE "OS_NONE")
  25 +endif(APPLE)
  26 +
  27 +add_definitions(-std=c99 -D${SYSTEM_TYPE})
18 28  
19 29 add_subdirectory(lib/glfw)
20 30 include_directories(lib/glew/include)
... ...
app/src/gl_util.c 0 → 100644
... ... @@ -0,0 +1,117 @@
  1 +#include "gl_util.h"
  2 +
  3 +#include <stdlib.h>
  4 +#include <errno.h>
  5 +#include <string.h>
  6 +
  7 +#include "lodepng.h"
  8 +
  9 +static int load_file(char **buffer, int *length, const char *path)
  10 +{
  11 + FILE *file = fopen(path, "rb");
  12 + if( file == NULL ) {
  13 + log_warn("Unable to open %s",path);
  14 + return 1;
  15 + }
  16 + fseek(file, 0, SEEK_END);
  17 + *length = ftell(file);
  18 + rewind(file);
  19 + *buffer = malloc(*length);
  20 + fread(*buffer, 1, *length, file);
  21 + fclose(file);
  22 + return 0;
  23 +}
  24 +
  25 +GLuint load_shader(GLenum type, const char *path)
  26 +{
  27 + int length;
  28 + char *buffer;
  29 + load_file(&buffer, &length, path);
  30 + GLuint shader = glCreateShader(type);
  31 + glShaderSource(shader, 1, (const GLchar *const*)&buffer, (const GLint *)&length);
  32 + glCompileShader(shader);
  33 + GLint status;
  34 + glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
  35 + if( status == GL_FALSE ) {
  36 + GLint length;
  37 + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
  38 + GLchar *info = malloc(length * sizeof(GLchar));
  39 + glGetShaderInfoLog(shader, length, NULL, info);
  40 + log_err("Compiling Shader %s\n%s", path, info);
  41 + free(info);
  42 + }
  43 + return shader;
  44 +}
  45 +
  46 +GLuint load_program(const char *vpath, const char *fpath)
  47 +{
  48 + GLuint vs = load_shader(GL_VERTEX_SHADER, vpath);
  49 + GLuint fs = load_shader(GL_FRAGMENT_SHADER, fpath);
  50 + GLuint program = glCreateProgram();
  51 + glAttachShader(program, vs);
  52 + glAttachShader(program, fs);
  53 + glLinkProgram(program);
  54 + GLint status;
  55 + glGetProgramiv(program, GL_LINK_STATUS, &status);
  56 + if( status == GL_FALSE) {
  57 + GLint length;
  58 + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
  59 + GLchar *info = malloc(length * sizeof(GLchar));
  60 + glGetProgramInfoLog(program, length, NULL, info);
  61 + log_err("Linking Program\n%s", info);
  62 + free(info);
  63 + }
  64 + glDetachShader(program, vs);
  65 + glDetachShader(program, fs);
  66 + glDeleteShader(vs);
  67 + glDeleteShader(fs);
  68 + return program;
  69 +}
  70 +
  71 +GLuint gen_buffer(GLsizei size, GLfloat *data)
  72 +{
  73 + GLuint buffer;
  74 + glGenBuffers(1, &buffer);
  75 + glBindBuffer(GL_ARRAY_BUFFER, buffer);
  76 + glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
  77 + glBindBuffer(GL_ARRAY_BUFFER, 0);
  78 + return buffer;
  79 +}
  80 +
  81 +static void flip_image_vertical(
  82 + unsigned char *data, unsigned int width, unsigned int height)
  83 +{
  84 + unsigned int size = width * height * 4;
  85 + unsigned int stride = sizeof(char) * width * 4;
  86 + unsigned char *new_data = malloc(sizeof(unsigned char) * size);
  87 + for( unsigned int i = 0; i < height; ++i ) {
  88 + unsigned int j = height - i - 1;
  89 + memcpy(new_data + j * stride, data + i * stride, stride);
  90 + }
  91 + memcpy(data, new_data, size);
  92 + free(new_data);
  93 +}
  94 +
  95 +GLuint gen_texture(const char *path)
  96 +{
  97 + unsigned int error;
  98 + unsigned char *data;
  99 + unsigned int width, height;
  100 + error = lodepng_decode32_file(&data, &width, &height, path);
  101 + if( error ) {
  102 + log_err("Loading %s: %s",path,lodepng_error_text(error));
  103 + }
  104 + flip_image_vertical(data, width, height);
  105 + GLuint texture;
  106 + glGenTextures(1, &texture);
  107 + glBindTexture(GL_TEXTURE_2D, texture);
  108 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  109 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  110 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  111 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  112 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
  113 + GL_UNSIGNED_BYTE, data);
  114 + free(data);
  115 + glGenerateMipmap(GL_TEXTURE_2D);
  116 + return texture;
  117 +}
... ...
app/src/gl_util.h 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +#ifndef GL_UTIL_H
  2 +#define GL_UTIL_H
  3 +
  4 +#include <GL/glew.h>
  5 +#include <GLFW/glfw3.h>
  6 +
  7 +#include "config.h"
  8 +#include "util.h"
  9 +
  10 +#define PI 3.14159265359
  11 +#define DEGREES(rad) ((rad) * 180 / PI)
  12 +#define RADIANS(deg) ((deg) * PI / 180)
  13 +#define ABS(X) ((x) < 0 ? (-(x)) : (x))
  14 +#define MIN(A, B) ((a) < (b) ? (a) : (b))
  15 +#define MAX(A, B) ((a) > (b) ? (a) : (b))
  16 +#define SIGN(X) (((x)) > 0 - ((x) < 0))
  17 +
  18 +GLuint make_shader(GLenum type, const char *source);
  19 +GLuint load_shader(GLenum type, const char *path);
  20 +GLuint make_program(GLuint vs, GLuint fs);
  21 +GLuint load_program(const char *vpath, const char *fpath);
  22 +
  23 +GLuint gen_buffer(GLsizei size, GLfloat *data);
  24 +GLuint gen_texture(const char *path);
  25 +
  26 +#endif
... ...
app/src/graphics.c 0 → 100644
... ... @@ -0,0 +1,197 @@
  1 +#include "graphics.h"
  2 +
  3 +#include <GL/glew.h>
  4 +#include <GLFW/glfw3.h>
  5 +
  6 +#include "config.h"
  7 +#include "util.h"
  8 +#include "serial.h"
  9 +#include "timer.h"
  10 +#include "gl_util.h"
  11 +
  12 +// GL Stuff
  13 +static const GLfloat logo_data[] = {
  14 + // Position
  15 + -0.5f, -1.0f,
  16 + -0.5f, 1.0f,
  17 + 0.5f, -1.0f,
  18 + 0.5f, 1.0f,
  19 + // UV Map
  20 + 0.0f, 0.0f,
  21 + 0.0f, 1.0f,
  22 + 1.0f, 0.0f,
  23 + 1.0f, 1.0f,
  24 +
  25 +};
  26 +
  27 +static const GLfloat sine_data[] = {
  28 + // Position
  29 + -1.0f, -1.0f,
  30 + -1.0f, 1.0f,
  31 + 1.0f, -1.0f,
  32 + 1.0f, 1.0f,
  33 + // UV Map
  34 + 0.0f, 0.0f,
  35 + 0.0f, 1.0f,
  36 + 1.0f, 0.0f,
  37 + 1.0f, 1.0f,
  38 +
  39 +};
  40 +
  41 +struct image {
  42 + GLuint program;
  43 + GLuint position;
  44 + GLuint uv;
  45 + GLuint sampler;
  46 + GLuint buffer;
  47 + GLuint texture;
  48 +} logo;
  49 +
  50 +struct wave {
  51 + GLuint program;
  52 + GLuint position;
  53 + GLuint uv;
  54 + GLuint time_ms;
  55 + GLuint buffer;
  56 +} sine;
  57 +
  58 +GLFWwindow *window;
  59 +float global_time;
  60 +
  61 +void error_callback(int error, const char *description)
  62 +{
  63 + log_err("GLFW: %s", description);
  64 +}
  65 +
  66 +void draw_image(struct image *image)
  67 +{
  68 + glEnable(GL_BLEND);
  69 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  70 +
  71 + glUseProgram(image->program);
  72 + glBindBuffer(GL_ARRAY_BUFFER, image->buffer);
  73 +
  74 + glEnableVertexAttribArray(image->position);
  75 + glEnableVertexAttribArray(image->uv);
  76 +
  77 + glVertexAttribPointer(image->position, 2, GL_FLOAT, GL_FALSE, 0, 0);
  78 + glVertexAttribPointer(image->uv, 2, GL_FLOAT, GL_FALSE, 0,
  79 + (GLvoid *)(sizeof(GLfloat) * 8));
  80 +
  81 + glActiveTexture(GL_TEXTURE0);
  82 + glBindTexture(GL_TEXTURE_2D, image->texture);
  83 + glUniform1i(image->texture, 0);
  84 +
  85 + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  86 +
  87 + glDisableVertexAttribArray(image->position);
  88 + glDisableVertexAttribArray(image->uv);
  89 + glBindBuffer(GL_ARRAY_BUFFER, 0);
  90 +}
  91 +
  92 +void draw_wave(struct wave *wave)
  93 +{
  94 + glUseProgram(wave->program);
  95 + glBindBuffer(GL_ARRAY_BUFFER, wave->buffer);
  96 +
  97 + glEnableVertexAttribArray(wave->position);
  98 + glEnableVertexAttribArray(wave->uv);
  99 +
  100 + glVertexAttribPointer(wave->position, 2, GL_FLOAT, GL_FALSE, 0, 0);
  101 + glVertexAttribPointer(wave->uv, 2, GL_FLOAT, GL_FALSE, 0,
  102 + (GLvoid *)(sizeof(GLfloat) * 8));
  103 +
  104 + glUniform1f(wave->time_ms,global_time);
  105 +
  106 + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  107 +
  108 + glDisableVertexAttribArray(wave->position);
  109 + glDisableVertexAttribArray(wave->uv);
  110 + glBindBuffer(GL_ARRAY_BUFFER, 0);
  111 +}
  112 +
  113 +int graphics_init()
  114 +{
  115 + global_time = 0.0f;
  116 +
  117 + glfwSetErrorCallback(error_callback);
  118 +
  119 + glfwInit();
  120 + glfwWindowHint(GLFW_SAMPLES, 4);
  121 + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
  122 + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
  123 + glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
  124 + //glfwWindowHint(GLFW_DECORATED, GL_FALSE);
  125 +
  126 + window = glfwCreateWindow(512, 256, "Heisenwave", NULL, NULL);
  127 + if( window == NULL ) {
  128 + glfwTerminate();
  129 + exit(EXIT_FAILURE);
  130 + }
  131 +
  132 + glfwMakeContextCurrent(window);
  133 +
  134 + GLenum rc = glewInit();
  135 +
  136 + if( rc != GLEW_OK ) {
  137 + log_err("Unable to initialize GLEW: %s",glewGetErrorString(rc));
  138 + glfwTerminate();
  139 + exit(EXIT_FAILURE);
  140 + }
  141 +
  142 + glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
  143 + glClearColor(0.4f, 0.5f, 0.6f, 0.0f);
  144 +
  145 + GLuint program;
  146 +
  147 + program = load_program(
  148 + "res/shaders/image_vert.glsl", "res/shaders/image_frag.glsl");
  149 + logo.position = glGetAttribLocation(program, "position");
  150 + logo.uv = glGetAttribLocation(program, "uv");
  151 + logo.sampler = glGetUniformLocation(program, "sampler");
  152 + logo.program = program;
  153 + logo.buffer = gen_buffer(sizeof(logo_data),(GLfloat*)logo_data);
  154 + logo.texture = gen_texture("res/images/heisenwave.png");
  155 +
  156 + program = load_program(
  157 + "res/shaders/sine_vert.glsl", "res/shaders/sine_frag.glsl");
  158 + sine.position = glGetAttribLocation(program, "position");
  159 + sine.uv = glGetAttribLocation(program, "uv");
  160 + sine.time_ms = glGetUniformLocation(program, "time_ms");
  161 + sine.program = program;
  162 + sine.buffer = gen_buffer(sizeof(sine_data),(GLfloat*)sine_data);
  163 +
  164 + return 0;
  165 +}
  166 +
  167 +int graphics_update(double dt, void *running)
  168 +{
  169 + global_time += dt / 3000;
  170 + glClear(GL_COLOR_BUFFER_BIT);
  171 +
  172 + draw_wave(&sine);
  173 + draw_image(&logo);
  174 +
  175 + glfwSwapBuffers(window);
  176 + glfwPollEvents();
  177 + if( glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS
  178 + || glfwWindowShouldClose(window) ) {
  179 + *(int *)running = 0;
  180 + }
  181 + return 1;
  182 +}
  183 +
  184 +int graphics_free()
  185 +{
  186 +
  187 + glDeleteBuffers(1, &(logo.buffer));
  188 + glDeleteProgram(logo.program);
  189 + glDeleteTextures(1, &(logo.texture));
  190 +
  191 + glDeleteBuffers(1, &(sine.buffer));
  192 + glDeleteProgram(sine.program);
  193 +
  194 + glfwTerminate();
  195 +
  196 + return 0;
  197 +}
... ...
app/src/graphics.h 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +#ifndef GRAPHICS_H
  2 +#define GRAPHICS_H
  3 +
  4 +int graphics_init();
  5 +int graphics_free();
  6 +
  7 +int graphics_update(double time, void *args);
  8 +
  9 +#endif
... ...
app/src/main.c
1 1 #include <stdio.h>
2 2 #include <stdlib.h>
  3 +#include <unistd.h>
3 4  
4 5 #include <GL/glew.h>
5 6 #include <GLFW/glfw3.h>
6 7  
7 8 #include "config.h"
8 9 #include "util.h"
  10 +#include "serial.h"
  11 +#include "timer.h"
  12 +#include "graphics.h"
9 13  
10   -static const GLfloat logo_data[] = {
11   - // Position
12   - -0.5f, -1.0f,
13   - -0.5f, 1.0f,
14   - 0.5f, -1.0f,
15   - 0.5f, 1.0f,
16   - // UV Map
17   - 0.0f, 0.0f,
18   - 0.0f, 1.0f,
19   - 1.0f, 0.0f,
20   - 1.0f, 1.0f,
  14 +char *bye = "Bye";
  15 +char *hello = "Hello";
  16 +int printer;
21 17  
22   -};
23   -
24   -static const GLfloat sine_data[] = {
25   - // Position
26   - -1.0f, -1.0f,
27   - -1.0f, 1.0f,
28   - 1.0f, -1.0f,
29   - 1.0f, 1.0f,
30   - // UV Map
31   - 0.0f, 0.0f,
32   - 0.0f, 1.0f,
33   - 1.0f, 0.0f,
34   - 1.0f, 1.0f,
35   -
36   -};
37   -
38   -struct image {
39   - GLuint program;
40   - GLuint position;
41   - GLuint uv;
42   - GLuint sampler;
43   - GLuint buffer;
44   - GLuint texture;
45   -};
46   -
47   -struct wave {
48   - GLuint program;
49   - GLuint position;
50   - GLuint uv;
51   - GLuint time_ms;
52   - GLuint buffer;
53   -};
54   -
55   -float global_time = 0;
56   -
57   -void error_callback(int error, const char *description)
  18 +int print_sth(double dt, void *args)
58 19 {
59   - log_err("GLFW: %s", description);
60   -}
61   -
62   -void draw_image(struct image *image)
63   -{
64   - glEnable(GL_BLEND);
65   - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
66   -
67   - glUseProgram(image->program);
68   - glBindBuffer(GL_ARRAY_BUFFER, image->buffer);
69   -
70   - glEnableVertexAttribArray(image->position);
71   - glEnableVertexAttribArray(image->uv);
72   -
73   - glVertexAttribPointer(image->position, 2, GL_FLOAT, GL_FALSE, 0, 0);
74   - glVertexAttribPointer(image->uv, 2, GL_FLOAT, GL_FALSE, 0,
75   - (GLvoid *)(sizeof(GLfloat) * 8));
76   -
77   - glActiveTexture(GL_TEXTURE0);
78   - glBindTexture(GL_TEXTURE_2D, image->texture);
79   - glUniform1i(image->texture, 0);
80   -
81   - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
82   -
83   - glDisableVertexAttribArray(image->position);
84   - glDisableVertexAttribArray(image->uv);
85   - glBindBuffer(GL_ARRAY_BUFFER, 0);
  20 + printf("%s\n",args);
  21 + return 1;
86 22 }
87 23  
88   -void draw_wave(struct wave *wave)
  24 +int count_down(double dt, void *args)
89 25 {
90   - glUseProgram(wave->program);
91   - glBindBuffer(GL_ARRAY_BUFFER, wave->buffer);
92   -
93   - glEnableVertexAttribArray(wave->position);
94   - glEnableVertexAttribArray(wave->uv);
95   -
96   - glVertexAttribPointer(wave->position, 2, GL_FLOAT, GL_FALSE, 0, 0);
97   - glVertexAttribPointer(wave->uv, 2, GL_FLOAT, GL_FALSE, 0,
98   - (GLvoid *)(sizeof(GLfloat) * 8));
99   -
100   - glUniform1f(wave->time_ms,global_time);
101   -
102   - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
103   -
104   - glDisableVertexAttribArray(wave->position);
105   - glDisableVertexAttribArray(wave->uv);
106   - glBindBuffer(GL_ARRAY_BUFFER, 0);
  26 + int i = *(int *)args - 1;
  27 + if( i == 0 ) {
  28 + timer_submit(1000,print_sth,bye);
  29 + timer_cancel(printer);
  30 + }
  31 + *(int *)args = i;
  32 + return i;
107 33 }
108 34  
109 35 int main(int argc, const char *argv[])
110 36 {
111   - GLFWwindow *window;
  37 + int i;
112 38  
113   - glfwSetErrorCallback(error_callback);
  39 + timer_init();
  40 + graphics_init();
114 41  
115   - glfwInit();
116   - glfwWindowHint(GLFW_SAMPLES, 4);
117   - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
118   - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
119   - glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
120   - glfwWindowHint(GLFW_DECORATED, GL_FALSE);
121   -
122   - window = glfwCreateWindow(512, 256, "Heisenwave", NULL, NULL);
123   - if( window == NULL ) {
124   - glfwTerminate();
125   - exit(EXIT_FAILURE);
  42 + struct ino inos[4];
  43 + int disc = serial_discover(4,inos);
  44 + log_info("%d Arduino discovered", disc);
  45 + for( i = 0; i < disc; ++i ) {
  46 + log_info("Arduino @ %s",inos[i].port);
126 47 }
127 48  
128   - glfwMakeContextCurrent(window);
  49 + int running = 1;
129 50  
130   - GLenum rc = glewInit();
  51 + int count = 5;
  52 + timer_submit(16,graphics_update,&running);
  53 + printer = timer_submit(1000,print_sth,hello);
  54 + timer_submit(1000,count_down,&count);
131 55  
132   - if( rc != GLEW_OK ) {
133   - log_err("Unable to initialize GLEW: %s",glewGetErrorString(rc));
134   - glfwTerminate();
135   - exit(EXIT_FAILURE);
  56 + while( running ) {
  57 + usleep(1);
  58 + timer_update();
136 59 }
137 60  
138   - glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
139   - glClearColor(0.4f, 0.5f, 0.6f, 0.0f);
140   -
141   - struct image logo;
142   - struct wave sine;
143   - GLuint program;
144   -
145   - program = load_program(
146   - "res/shaders/image_vert.glsl", "res/shaders/image_frag.glsl");
147   - logo.position = glGetAttribLocation(program, "position");
148   - logo.uv = glGetAttribLocation(program, "uv");
149   - logo.sampler = glGetUniformLocation(program, "sampler");
150   - logo.program = program;
151   - logo.buffer = gen_buffer(sizeof(logo_data),(GLfloat*)logo_data);
152   - logo.texture = gen_texture("res/images/heisenwave.png");
153   -
154   - program = load_program(
155   - "res/shaders/sine_vert.glsl", "res/shaders/sine_frag.glsl");
156   - sine.position = glGetAttribLocation(program, "position");
157   - sine.uv = glGetAttribLocation(program, "uv");
158   - sine.time_ms = glGetUniformLocation(program, "time_ms");
159   - sine.program = program;
160   - sine.buffer = gen_buffer(sizeof(sine_data),(GLfloat*)sine_data);
161   -
162   - do {
163   - glClear(GL_COLOR_BUFFER_BIT);
164   -
165   - draw_wave(&sine);
166   - draw_image(&logo);
167   -
168   - glfwSwapBuffers(window);
169   - glfwPollEvents();
170   - global_time += 0.01;
171   - } while( glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS
172   - && glfwWindowShouldClose(window) == 0);
173   -
174   - glDeleteBuffers(1, &(logo.buffer));
175   - glDeleteProgram(logo.program);
176   - glDeleteTextures(1, &(logo.texture));
177   -
178   - glDeleteBuffers(1, &(sine.buffer));
179   - glDeleteProgram(sine.program);
  61 + for( i = 0; i < disc; ++i ) {
  62 + serial_free(&inos[i]);
  63 + }
180 64  
181   - glfwTerminate();
182   -
183   - exit(EXIT_SUCCESS);
  65 + timer_free();
  66 + graphics_free();
184 67 }
... ...
app/src/serial.c 0 → 100644
... ... @@ -0,0 +1,206 @@
  1 +#include "serial.h"
  2 +
  3 +#define SERIAL_DIR "/dev"
  4 +
  5 +#ifdef OS_LINUX
  6 +#define PATTERN_COUNT 2
  7 +static const char *serial_patterns[] = {
  8 + "ttyACM", "ttyUSB"
  9 +};
  10 +#endif
  11 +
  12 +#ifdef OS_APPLE
  13 +#define PATTERN_COUNT 2
  14 +static const char *serial_patterns[] = {
  15 + "tty.usbmodem", "tty.usbserial"
  16 +};
  17 +#endif
  18 +
  19 +#include <stdio.h>
  20 +#include <unistd.h>
  21 +#include <fcntl.h>
  22 +#include <termios.h>
  23 +#include <string.h>
  24 +#include <sys/ioctl.h>
  25 +#include <dirent.h>
  26 +
  27 +#include "util.h"
  28 +
  29 +static int matches_pattern(char *port, const char *pattern)
  30 +{
  31 + int len = strlen(pattern);
  32 + int i;
  33 + for( i = 0; i < len; ++i ) {
  34 + if( port[i] == 0 ) return 0;
  35 + if( port[i] != pattern[i] ) return 0;
  36 + }
  37 + return 1;
  38 +}
  39 +
  40 +static int matches_any_pattern(char *port)
  41 +{
  42 + int i;
  43 + for( i = 0; i < PATTERN_COUNT; ++i ) {
  44 + if(matches_pattern(port, serial_patterns[i])) {
  45 + return 1;
  46 + }
  47 + }
  48 + return 0;
  49 +}
  50 +
  51 +int serial_discover(int max, struct ino *inos)
  52 +{
  53 + DIR *dir = opendir(SERIAL_DIR);
  54 + int i = 0;
  55 + while(1) {
  56 + struct dirent *entry;
  57 + entry = readdir(dir);
  58 + if( entry == NULL ) {
  59 + break;
  60 + }
  61 + char *port = entry->d_name;
  62 + if( matches_any_pattern(port) ) {
  63 + serial_init(&inos[i++], port);
  64 + }
  65 + }
  66 + closedir(dir);
  67 + return i;
  68 +}
  69 +
  70 +int serial_init(struct ino *ino, char *port)
  71 +{
  72 + ino->port = strdup(port);
  73 + ino->status = 0;
  74 + ino->fd = -1;
  75 + ino->read = 0;
  76 + return 0;
  77 +}
  78 +
  79 +int serial_free(struct ino *ino)
  80 +{
  81 + free(ino->port);
  82 + if( ino->status & INO_OPEN ) {
  83 + serial_disconnect(ino);
  84 + }
  85 + return 0;
  86 +}
  87 +
  88 +int serial_connect(struct ino *ino)
  89 +{
  90 + check(ino->port,"No port for Arduino");
  91 + check(!(ino->status & INO_OPEN),"Arduino already connected");
  92 +
  93 + struct termios toptions;
  94 + int fd;
  95 +
  96 + fd = open(ino->port, O_RDWR | O_NONBLOCK);
  97 +
  98 + if( fd == -1 ) {
  99 + return -1;
  100 + }
  101 +
  102 + tcgetattr(fd, &toptions);
  103 +
  104 + speed_t brate;
  105 + switch(BAUD_RATE) {
  106 + case 4800: brate = B4800; break;
  107 + case 9600: brate = B9600; break;
  108 + case 14400: brate = B14400; break;
  109 + case 19200: brate = B19200; break;
  110 + case 28800: brate = B28800; break;
  111 + case 38400: brate = B38400; break;
  112 + case 57600: brate = B57600; break;
  113 + case 115200: brate = B115200; break;
  114 + default: check(0,"Invalid Baud Rate %d",BAUD_RATE);
  115 + }
  116 + cfsetispeed(&toptions, brate);
  117 + cfsetospeed(&toptions, brate);
  118 +
  119 + // No parity bit
  120 + // No stop bit
  121 + // 8 bit mode
  122 + toptions.c_cflag &= ~PARENB;
  123 + toptions.c_cflag &= ~CSTOPB;
  124 + toptions.c_cflag &= ~CSIZE;
  125 + toptions.c_cflag |= CS8;
  126 + // No Flow Control
  127 + toptions.c_cflag &= ~CRTSCTS;
  128 +
  129 + //toptions.c_cflag &= ~HUPCL;
  130 +
  131 + // Turn on read
  132 + // Ignore control
  133 + toptions.c_cflag |= CREAD | CLOCAL;
  134 + toptions.c_iflag &= ~(IXON | IXOFF | IXANY);
  135 +
  136 + // Raw data
  137 + toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  138 + toptions.c_oflag &= ~OPOST;
  139 +
  140 + // TODO Run Serial Port on own Thread
  141 + // See: http://unixwiz.net/techtips/termios-vmin-vtime.html
  142 + // Active Polling :S
  143 + toptions.c_cc[VMIN] = 0;
  144 + toptions.c_cc[VTIME] = 0;
  145 +
  146 + tcsetattr(fd, TCSANOW, &toptions);
  147 + tcsetattr(fd, TCSAFLUSH, &toptions);
  148 +
  149 + ino->fd = fd;
  150 + ino->status |= INO_OPEN;
  151 + ino->read = 0;
  152 + return 0;
  153 +}
  154 +
  155 +int serial_disconnect(struct ino *ino)
  156 +{
  157 + check(ino->status & INO_OPEN, "Arduino already disconnected");
  158 + ino->status &= ~INO_OPEN;
  159 + return close(ino->fd);
  160 +}
  161 +
  162 +
  163 +int serial_write(struct ino *ino, int argc, char *argv)
  164 +{
  165 + check(ino->status & INO_OPEN,"Arduino not connected");
  166 + int n = write(ino->fd,argv,argc);
  167 + if( n != argc ) {
  168 + return -1;
  169 + }
  170 + return 0;
  171 +}
  172 +
  173 +int serial_available(struct ino *ino)
  174 +{
  175 + check(ino->status & INO_OPEN,"Arduino not connected");
  176 +
  177 + if( ino->read == INO_SIZE ) return INO_SIZE;
  178 + char *buf = &(ino->buffer[ino->read]);
  179 + int todo = INO_SIZE - ino->read;
  180 + int n = read(ino->fd, buf, todo);
  181 + if( n == -1 ) {
  182 + return -1;
  183 + }
  184 + ino->read += n;
  185 + return ino->read;
  186 +}
  187 +
  188 +int serial_read(struct ino *ino, int argc, char *argv)
  189 +{
  190 + check(ino->status & INO_OPEN, "Arduino not connected");
  191 + check(argc <= INO_SIZE, "Arduino Buffer too small");
  192 +
  193 + if( ino->read < argc ) return -1;
  194 +
  195 + memcpy(argv,ino->buffer,argc);
  196 + ino->read -= argc;
  197 + if(ino->read) memmove(ino->buffer,&(ino->buffer[ino->read]),ino->read);
  198 + return 0;
  199 +}
  200 +
  201 +int serial_flush(struct ino *ino)
  202 +{
  203 + check(ino->status & INO_OPEN, "Arduino not connected");
  204 + //sleep(2); //required to make flush work, for some reason
  205 + return tcflush(ino->fd, TCIOFLUSH);
  206 +}
... ...
app/src/serial.h 0 → 100644
... ... @@ -0,0 +1,34 @@
  1 +#ifndef SERIAL_H
  2 +#define SERIAL_H
  3 +
  4 +#ifdef OS_WINDOWS
  5 +#error Currently no Serial Support for Windows Systems
  6 +#endif
  7 +
  8 +#include <stdint.h>
  9 +
  10 +#define BAUD_RATE 9600
  11 +
  12 +#define INO_SIZE 256
  13 +
  14 +struct ino{
  15 + char *port;
  16 + int fd;
  17 + int status;
  18 + char buffer[INO_SIZE];
  19 + int read;
  20 +};
  21 +
  22 +#define INO_OPEN 1
  23 +
  24 +int serial_discover(int max, struct ino *inos);
  25 +int serial_init(struct ino *ino, char *port);
  26 +int serial_free(struct ino *ino);
  27 +int serial_connect(struct ino *ino);
  28 +int serial_disconnect(struct ino *ino);
  29 +int serial_write(struct ino *ino, int argc, char *argv);
  30 +int serial_available(struct ino *ino);
  31 +int serial_read(struct ino *ino, int argc, char *argv);
  32 +int serial_flush(struct ino *ino);
  33 +
  34 +#endif
... ...
app/src/timer.c 0 → 100644
... ... @@ -0,0 +1,107 @@
  1 +#include "timer.h"
  2 +
  3 +#include <sys/time.h>
  4 +#include <strings.h>
  5 +
  6 +#include "util.h"
  7 +
  8 +struct timer_event {
  9 + double delta;
  10 + double last;
  11 + timer_cb callback;
  12 + void *args;
  13 +};
  14 +
  15 +#ifndef TIMER_INIT_SIZE
  16 +#define TIMER_INIT_SIZE 256
  17 +#endif
  18 +
  19 +static struct timer_event *events;
  20 +static int capacity;
  21 +static int head;
  22 +static int count;
  23 +
  24 +double time_ms()
  25 +{
  26 + struct timeval tv;
  27 + gettimeofday(&tv, NULL);
  28 + return (double)tv.tv_sec*1000 + (double)tv.tv_usec/1000;
  29 +}
  30 +
  31 +int timer_init()
  32 +{
  33 + head = 0;
  34 + capacity = TIMER_INIT_SIZE;
  35 + events = calloc(capacity,sizeof(struct timer_event));
  36 + count = 0;
  37 + if( events == NULL ) return -1;
  38 + return 0;
  39 +}
  40 +
  41 +int timer_free()
  42 +{
  43 + if( events == NULL ) return -1;
  44 + free(events);
  45 + return 0;
  46 +}
  47 +
  48 +int timer_submit(double ms, timer_cb cb, void *args)
  49 +{
  50 + int i;
  51 + for( i = 0; i < capacity; ++i ) {
  52 + }
  53 + i = head;
  54 + while(1) {
  55 + if(events[i].callback == NULL) {
  56 + events[i].delta = ms;
  57 + events[i].last = time_ms();
  58 + events[i].args = args;
  59 + events[i].callback = cb;
  60 + head = (i+1) % capacity;
  61 + count += 1;
  62 + return i;
  63 + }
  64 + i = (i+1) % capacity;
  65 + if( i == head ) {
  66 + // The following causes bugs with GLFW
  67 + // events = realloc(events, capacity * 2);
  68 + // memset(&events[capacity],0,sizeof(struct timer_event)*capacity);
  69 + // i = capacity;
  70 + // capacity *= 2;
  71 + return -1;
  72 + }
  73 + }
  74 +}
  75 +
  76 +int timer_cancel(int evt)
  77 +{
  78 + if(events[evt].callback == NULL) return -1;
  79 + count -= 1;
  80 + memset(&events[evt],0,sizeof(struct timer_event));
  81 + return 0;
  82 +}
  83 +
  84 +int timer_update()
  85 +{
  86 + if( events == NULL ) return -1;
  87 + int i;
  88 + i = head;
  89 + double now = time_ms();
  90 + int t = 0;
  91 + do {
  92 + i = (i + capacity - 1) % capacity;
  93 + if( events[i].callback != NULL ) {
  94 + t += 1;
  95 + double delta = now - events[i].last;
  96 + if( events[i].delta <= delta ) {
  97 + int rv = events[i].callback(delta,events[i].args);
  98 + if( rv == 0 ) {
  99 + timer_cancel(i);
  100 + } else {
  101 + events[i].last = now;
  102 + }
  103 + }
  104 + }
  105 + } while( i != head && t < count );
  106 + return 0;
  107 +}
... ...
app/src/timer.h 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +#ifndef TIMER_H
  2 +#define TIMER_H
  3 +
  4 +#include <sys/time.h>
  5 +
  6 +typedef int (*timer_cb)(double dt, void *args);
  7 +
  8 +double time_ms();
  9 +
  10 +int timer_submit(double dt, timer_cb cb, void *args);
  11 +int timer_cancel(int evt);
  12 +
  13 +int timer_init();
  14 +int timer_free();
  15 +int timer_update();
  16 +
  17 +#endif
... ...
app/src/util.c
... ... @@ -1,118 +0,0 @@
1   -#include "util.h"
2   -
3   -#include <assert.h>
4   -#include <stdlib.h>
5   -#include <errno.h>
6   -#include <string.h>
7   -
8   -#include "lodepng.h"
9   -
10   -static int load_file(char **buffer, int *length, const char *path)
11   -{
12   - FILE *file = fopen(path, "rb");
13   - if( file == NULL ) {
14   - log_warn("Unable to open %s",path);
15   - return 1;
16   - }
17   - fseek(file, 0, SEEK_END);
18   - *length = ftell(file);
19   - rewind(file);
20   - *buffer = malloc(*length);
21   - fread(*buffer, 1, *length, file);
22   - fclose(file);
23   - return 0;
24   -}
25   -
26   -GLuint load_shader(GLenum type, const char *path)
27   -{
28   - int length;
29   - char *buffer;
30   - load_file(&buffer, &length, path);
31   - GLuint shader = glCreateShader(type);
32   - glShaderSource(shader, 1, (const GLchar *const*)&buffer, (const GLint *)&length);
33   - glCompileShader(shader);
34   - GLint status;
35   - glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
36   - if( status == GL_FALSE ) {
37   - GLint length;
38   - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
39   - GLchar *info = malloc(length * sizeof(GLchar));
40   - glGetShaderInfoLog(shader, length, NULL, info);
41   - log_err("Compiling Shader %s\n%s", path, info);
42   - free(info);
43   - }
44   - return shader;
45   -}
46   -
47   -GLuint load_program(const char *vpath, const char *fpath)
48   -{
49   - GLuint vs = load_shader(GL_VERTEX_SHADER, vpath);
50   - GLuint fs = load_shader(GL_FRAGMENT_SHADER, fpath);
51   - GLuint program = glCreateProgram();
52   - glAttachShader(program, vs);
53   - glAttachShader(program, fs);
54   - glLinkProgram(program);
55   - GLint status;
56   - glGetProgramiv(program, GL_LINK_STATUS, &status);
57   - if( status == GL_FALSE) {
58   - GLint length;
59   - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
60   - GLchar *info = malloc(length * sizeof(GLchar));
61   - glGetProgramInfoLog(program, length, NULL, info);
62   - log_err("Linking Program\n%s", info);
63   - free(info);