#include #include #include #include #include #include #include #include #include #include #include #include #include #include "display.h" #include "config.h" #include "engine.h" /*** Global config and status values ***/ /* Window width and height */ // const int g_width = 1024, g_height = 768; const int g_width = 800, g_height = 600; StringConfig g_string_conf[MAX_LINECOUNT]; int g_string_count; int g_harfe_connected = 0; int g_harfe_fd = -1; static char * find_harfe() { // Device name should be a cu.device // followed by the letter HAR somewhere // e.g. /dev /cu.usbmodemHAR1 DIR * dev = opendir("/dev/"); struct dirent *dp; char *harfe = 0; if (!dev) return 0; while ((dp = readdir(dev)) != NULL) { size_t len = dp->d_namlen; char *name = dp->d_name, *H, *A, *R; int i; if (len < 6 || name[0] != 'c' || name[1] != 'u' || name[2] != '.') continue; for (i = 0; i < len - 3; ++i) if (name[i] == 'H' && name[i + 1] == 'A' && name[i + 2] == 'R') { if ((harfe = calloc(1, 5 + len + 1))) { sprintf(harfe, "/dev/"); memcpy(harfe + 5, name, len); } break; } } closedir(dev); return harfe; } int set_interface_attribs(int fd, int speed, int parity) { struct termios tty; memset(&tty, 0, sizeof tty); if (tcgetattr(fd, &tty) != 0) return -1; cfsetospeed(&tty, speed); cfsetispeed(&tty, speed); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; tty.c_iflag &= ~IGNBRK; tty.c_lflag = 0; tty.c_oflag = 0; tty.c_cc[VMIN] = 0; tty.c_cc[VTIME] = 5; tty.c_iflag &= ~(IXON | IXOFF | IXANY); tty.c_cflag |= (CLOCAL | CREAD); tty.c_cflag &= ~(PARENB | PARODD); tty.c_cflag |= parity; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CRTSCTS; if (tcsetattr(fd, TCSANOW, &tty) != 0) return -1; return 0; } void set_blocking(int fd, int should_block) { struct termios tty; memset(&tty, 0, sizeof tty); if (tcgetattr(fd, &tty) != 0) return; tty.c_cc[VMIN] = should_block ? 1 : 0; tty.c_cc[VTIME] = 5; if (tcsetattr(fd, TCSANOW, &tty) != 0) return; } uint32_t now() { struct timeval now; gettimeofday(&now, (struct timezone *)NULL); return now.tv_sec * 1000 + now.tv_usec / 1000; /* in ms */ } static uint32_t g_last_avg; static uint32_t g_starttime, g_last_mouse_event, g_lastredraw; static int g_events; static void harfe_worker(void) { LPoint p[4]; char text[256], *lineend; int fd, i, text_fill = 0, consumed, running = 1; uint32_t ptime; char *portname = find_harfe(); if (!portname) { printf("Can't find harfe serial device.\n"); return; } g_harfe_fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); if (g_harfe_fd < 0) { free(portname); printf("Can't connect to harfe..."); return; } set_interface_attribs(g_harfe_fd, B115200, 0); set_blocking(g_harfe_fd, 0); printf("Connection to harfe established at %s.\n", portname); free(portname); g_harfe_connected = 1; while (running) { while (text_fill < sizeof(text) && !memchr(text, '\n', text_fill)) { ssize_t b = read(g_harfe_fd, text + text_fill, sizeof(text) - text_fill); if ((b < 0) && (errno != EAGAIN)) { printf("Connection to harfe lost..."); running = 0; close(g_harfe_fd); g_harfe_fd = -1; break; } text_fill += b; } //Overlong line, drop it and try to resync if (text_fill == sizeof(text)) { text_fill = 0; continue; } // find and remove newline and cf if (!(lineend = memchr(text, '\n', text_fill))) continue; *lineend = 0; if (text_fill && lineend[-1] == '\r') lineend[-1] = 0; int num_points = sscanf(text, "%04d:%04d %04d:%04d %04d:%04d %04d:%04d", &p[0].x, &p[0].y, &p[1].x, &p[1].y, &p[2].x, &p[2].y, &p[3].x, &p[3].y); ptime = now(); for (i = 0; i < num_points / 2; ++i) { // printf("%04d:%04d\n", p[i].x, p[i].y); engine_handle_point(p + i, ptime); } if (num_points > 1 || *text == '-') ++g_events; consumed = lineend - text + 1; memmove(text, lineend + 1, text_fill - consumed); text_fill -= consumed; } return; } static void * worker(void *args) { while (1) { harfe_worker(); g_harfe_connected = 0; printf("retrying in 5 seconds.\n"); sleep(5); } } int main(int argc, char **argv) { SDL_Event ev; int i, counter = 0; pthread_t thread_id; uint32_t runtime; static int last_click_x, last_click_y, last_mouse_event; display_init(g_width, g_height); engine_init(); config_parse("config_midi"); pthread_create(&thread_id, NULL, worker, NULL); /* Spin and let call back do all the work */ while (1) { SDL_WaitEventTimeout(&ev, 10); switch (ev.type) { case SDL_QUIT: exit(0); case SDL_KEYDOWN: /* if( ev.key.keysym.sym >= SDLK_1 && ev.key.keysym.sym <= SDLK_9 ) engine_select_string( ev.key.keysym.sym - SDLK_1 ); if( ev.key.keysym.sym == SDLK_BACKSPACE || ev.key.keysym.sym == SDLK_DELETE ) engine_delete_selected_string( ); if( ev.key.keysym.sym == SDLK_d ) { g_stringsdescending = 1 - g_stringsdescending; printf( "String order (left to right) is now %sscending.\n", g_stringsdescending ? "de" : "a" ); } */ break; case SDL_MOUSEBUTTONDOWN: /* if( ( g_last_mouse_event / 1000 ) != ( engine_now( ) / 1000 ) || ev.button.x != last_click_x || ev.button.y != last_click_y ) engine_process_mouse( ev.button.x, ev.button.y ); last_click_x = ev.button.x; last_click_y = ev.button.y; last_mouse_event = engine_now( ); */ break; } engine_checksilence(now()); runtime = now(); if (runtime - g_lastredraw > 30) { g_lastredraw = runtime; engine_redraw(); } if (runtime / 1000 - g_last_avg > 10) { printf("avg: %i\n", g_events / 10); g_events = 0; g_last_avg = runtime / 1000; } } return 0; }