/*---------------------------------------------------------------------------*/ static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *len = NULL; char message[40]; memset(message, 0, 40); print_temperature(&message[0]); int length = strlen(&message[0]); /* The query string can be retrieved by rest_get_query(), * or parsed for its key-value pairs. */ if(REST.get_query_variable(request, "len", &len)) { length = atoi(len); if(length < 0) { length = 0; } if(length > REST_MAX_CHUNK_SIZE) { length = REST_MAX_CHUNK_SIZE; } memcpy(buffer, message, length); } else { memcpy(buffer, message, length); } REST.set_header_content_type(response, REST.type.TEXT_PLAIN); REST.set_header_etag(response, (uint8_t *)&length, 1); REST.set_response_payload(response, buffer, length); }
int main(void) { Display* display = 0; struct temperature* temperature = 0; int ret = EXIT_FAILURE; signal(SIGINT, &signal_handler); signal(SIGTERM, &signal_handler); setlocale(LC_ALL, u8""); display = XOpenDisplay(0); if (!display) { fprintf(stderr, u8"Could not open X11 display.\n"); goto cleanup; } temperature = temperature_init(); if (!temperature) { fprintf(stderr, u8"Could not initialize temperature.\n"); goto cleanup; } while (running) { char buffer[1024]; char* cur = buffer; size_t size = sizeof buffer; size_t check = 0; check = print_temperature(cur, size, temperature); size -= check; cur += check; check = print_time(cur, size); size -= check; cur += check; XStoreName(display, DefaultRootWindow(display), buffer); XSync(display, False); sleep(1); } ret = EXIT_SUCCESS; cleanup: temperature_cleanup(temperature); if (display) XCloseDisplay(display); return ret; }
static void track_disp_wpt_cb(const waypoint *wpt) { waypoint *prev = cur_info->prev_wpt; time_t delta; double dist, depth; gbfprintf(fout, "Trackpoint\t"); print_position(wpt); print_date_and_time(wpt->creation_time, 0); if IS_VALID_ALT(wpt->altitude) print_distance(wpt->altitude, 1, 0, 0); gbfprintf(fout, "\t"); depth = WAYPT_GET(wpt, depth, unknown_alt); if (depth != unknown_alt) print_distance(depth, 1, 0, 1); if (prev != NULL) { float temp; gbfprintf(fout, "\t"); delta = wpt->creation_time - prev->creation_time; temp = WAYPT_GET(wpt, temperature, -999); if (temp != -999) print_temperature(temp); gbfprintf(fout, "\t"); dist = waypt_distance_ex(prev, wpt); print_distance(dist, 0, 1, 0); print_date_and_time(delta, 1); print_speed(&dist, &delta); print_course(prev, wpt); } gbfprintf(fout, "\r\n"); cur_info->prev_wpt = (waypoint *)wpt; }
/** * Generate textual weather forecast for the specified radio tower. */ std::string weather_forecast( point const &abs_sm_pos ) { std::ostringstream weather_report; // Local conditions const auto cref = overmap_buffer.closest_city( tripoint( abs_sm_pos, 0 ) ); const std::string city_name = cref ? cref.city->name : std::string( _( "middle of nowhere" ) ); // Current time weather_report << string_format( _("The current time is %s Eastern Standard Time. At %s in %s, it was %s. The temperature was %s. "), calendar::turn.print_time().c_str(), calendar::turn.print_time(true).c_str(), city_name.c_str(), weather_data(g->weather).name.c_str(), print_temperature(g->temperature).c_str() ); //weather_report << ", the dewpoint ???, and the relative humidity ???. "; //weather_report << "The wind was <direction> at ? mi/km an hour. "; //weather_report << "The pressure was ??? in/mm and steady/rising/falling."; // Regional conditions (simulated by choosing a random range containing the current conditions). // Adjusted for weather volatility based on how many weather changes are coming up. //weather_report << "Across <region>, skies ranged from <cloudiest> to <clearest>. "; // TODO: Add fake reports for nearby cities // TODO: weather forecast // forecasting periods are divided into 12-hour periods, day (6-18) and night (19-5) // Accumulate percentages for each period of various weather statistics, and report that // (with fuzz) as the weather chances. // int weather_proportions[NUM_WEATHER_TYPES] = {0}; double high = -100.0; double low = 100.0; point const abs_ms_pos = overmapbuffer::sm_to_ms_copy( abs_sm_pos ); // TODO wind direction and speed int last_hour = calendar::turn - ( calendar::turn % HOURS(1) ); for(int d = 0; d < 6; d++) { weather_type forecast = WEATHER_NULL; for(calendar i(last_hour + 7200 * d); i < last_hour + 7200 * (d + 1); i += 600) { w_point w = g->weather_gen->get_weather( abs_ms_pos, i ); forecast = std::max(forecast, g->weather_gen->get_weather_conditions(w)); high = std::max(high, w.temperature); low = std::min(low, w.temperature); } std::string day; bool started_at_night; calendar c(last_hour + 7200 * d); if(d == 0 && c.is_night()) { day = _("Tonight"); started_at_night = true; } else { day = _("Today"); started_at_night = false; } if(d > 0 && ((started_at_night && !(d % 2)) || (!started_at_night && d % 2))) { day = rmp_format(_("<Mon Night>%s Night"), c.day_of_week().c_str()); } else { day = c.day_of_week(); } weather_report << string_format( _("%s... %s. Highs of %s. Lows of %s. "), day.c_str(), weather_data(forecast).name.c_str(), print_temperature(high).c_str(), print_temperature(low).c_str() ); } return weather_report.str(); }
std::string weather_forecast(game *g, radio_tower tower) { std::stringstream weather_report; // Current time weather_report << "The current time is " << g->turn.print_time() << " Eastern Standard Time. "; // Local conditions weather_report << "At " << g->turn.print_time(true); city *closest_city = &g->cur_om->cities[g->cur_om->closest_city(point(tower.x, tower.y))]; if (closest_city) { weather_report << " in " << closest_city->name; } weather_report << ", it was " << weather_data[g->weather].name << ". "; weather_report << "The temperature was " << print_temperature(g->temperature); //weather_report << ", the dewpoint ???, and the relative humidity ???. "; //weather_report << "The wind was <direction> at ? mi/km an hour. "; //weather_report << "The pressure was ??? in/mm and steady/rising/falling."; // Regional conditions (simulated by chosing a random range containing the current conditions). // Adjusted for weather volatility based on how many weather changes are coming up. //weather_report << "Across <region>, skies ranged from <cloudiest> to <clearest>. "; // TODO: Add fake reports for nearby cities // TODO: weather forecast // forecasting periods are divided into 12-hour periods, day (6-18) and night (19-5) // Accumulate percentages for each period of various weather statistics, and report that // (with fuzz) as the weather chances. int weather_proportions[NUM_WEATHER_TYPES] = {0}; signed char high = 0; signed char low = 0; calendar start_time = g->turn; int period_start = g->turn.hours(); // TODO wind direction and speed for( std::list<weather_segment>::iterator period = g->future_weather.begin(); period != g->future_weather.end(); period++ ) { int period_deadline = period->deadline.hours(); signed char period_temperature = period->temperature; weather_type period_weather = period->weather; bool start_day = period_start >= 6 && period_start <= 18; bool end_day = period_deadline >= 6 && period_deadline <= 18; high = std::max(high, period_temperature); low = std::min(low, period_temperature); if(start_day != end_day) // Assume a period doesn't last over 12 hrs? { weather_proportions[period_weather] += end_day ? 6 : 18 - period_start; int weather_duration = 0; int predominant_weather; std::string day; if( g->turn.days() == period->deadline.days() ) { if( start_day ) { day = "Today"; } else { day = "Tonight"; } } else { day = start_time.day_of_week(); if( !start_day ) { day += " Night"; } } for( int i = WEATHER_CLEAR; i < NUM_WEATHER_TYPES; i++) { if( weather_proportions[i] > weather_duration) { weather_duration = weather_proportions[i]; predominant_weather = i; } } // Print forecast weather_report << day << "..." << weather_data[predominant_weather].name << ". "; weather_report << "Highs of " << print_temperature(high) << ". Lows of " << print_temperature(low) << ". "; low = period_temperature; high = period_temperature; weather_proportions[period_weather] += end_day ? 6 : 18 - period_start; } else { weather_proportions[period_weather] += period_deadline - period_start; } start_time = period->deadline; period_start = period_deadline; } return weather_report.str(); }
std::string weather_forecast(radio_tower tower) { std::stringstream weather_report; // Local conditions city *closest_city = &g->cur_om->cities[g->cur_om->closest_city(point(tower.x, tower.y))]; // Current time weather_report << string_format( _("The current time is %s Eastern Standard Time. At %s in %s, it was %s. The temperature was %s"), g->turn.print_time().c_str(), g->turn.print_time(true).c_str(), closest_city->name.c_str(), weather_data[g->weather].name.c_str(), print_temperature(g->temperature).c_str() ); //weather_report << ", the dewpoint ???, and the relative humidity ???. "; //weather_report << "The wind was <direction> at ? mi/km an hour. "; //weather_report << "The pressure was ??? in/mm and steady/rising/falling."; // Regional conditions (simulated by chosing a random range containing the current conditions). // Adjusted for weather volatility based on how many weather changes are coming up. //weather_report << "Across <region>, skies ranged from <cloudiest> to <clearest>. "; // TODO: Add fake reports for nearby cities // TODO: weather forecast // forecasting periods are divided into 12-hour periods, day (6-18) and night (19-5) // Accumulate percentages for each period of various weather statistics, and report that // (with fuzz) as the weather chances. int weather_proportions[NUM_WEATHER_TYPES] = {0}; signed char high = 0; signed char low = 0; calendar start_time = g->turn; int period_start = g->turn.hours(); // TODO wind direction and speed for(std::map<int, weather_segment>::iterator it = g->weather_log.lower_bound( int(g->turn) ); it != g->weather_log.end(); ++it ) { weather_segment * period = &(it->second); int period_deadline = period->deadline.hours(); signed char period_temperature = period->temperature; weather_type period_weather = period->weather; bool start_day = period_start >= 6 && period_start <= 18; bool end_day = period_deadline >= 6 && period_deadline <= 18; high = std::max(high, period_temperature); low = std::min(low, period_temperature); if(start_day != end_day) // Assume a period doesn't last over 12 hrs? { weather_proportions[period_weather] += end_day ? 6 : 18 - period_start; int weather_duration = 0; int predominant_weather = 0; std::string day; if( g->turn.days() == period->deadline.days() ) { if( start_day ) { day = _("Today"); } else { day = _("Tonight"); } } else { std::string dayofweak = start_time.day_of_week(); if( !start_day ) { day = rmp_format(_("<Mon Night>%s Night"), dayofweak.c_str()); } else { day = dayofweak; } } for( int i = WEATHER_CLEAR; i < NUM_WEATHER_TYPES; i++) { if( weather_proportions[i] > weather_duration) { weather_duration = weather_proportions[i]; predominant_weather = i; } } // Print forecast weather_report << string_format( _("%s...%s. Highs of %s. Lows of %s. "), day.c_str(), weather_data[predominant_weather].name.c_str(), print_temperature(high).c_str(), print_temperature(low).c_str() ); low = period_temperature; high = period_temperature; weather_proportions[period_weather] += end_day ? 6 : 18 - period_start; } else { weather_proportions[period_weather] += period_deadline - period_start; } start_time = period->deadline; period_start = period_deadline; } return weather_report.str(); }
static void write_waypt(const waypoint *wpt) { unsigned char wpt_class; garmin_fs_p gmsd; char *wpt_type; char *dspl_mode; const char *country; double x; int i, icon, dynamic; char *icon_descr; gmsd = GMSD_FIND(wpt); i = GMSD_GET(display, 0); if (i > GT_DISPLAY_MODE_MAX) i = 0; dspl_mode = gt_display_mode_names[i]; wpt_class = GMSD_GET(wpt_class, 0); if (wpt_class <= gt_waypt_class_map_line) wpt_type = gt_waypt_class_names[wpt_class]; else wpt_type = gt_waypt_class_names[0]; gbfprintf(fout, "Waypoint\t%s\t", (wpt->shortname) ? wpt->shortname : ""); if (wpt_class <= gt_waypt_class_airport_ndb) { char *temp = wpt->notes; if (temp == NULL) { if (wpt->description && (strcmp(wpt->description, wpt->shortname) != 0)) temp = wpt->description; else temp = ""; } print_string("%s\t", temp); } else gbfprintf(fout, "\t"); gbfprintf(fout, "%s\t", wpt_type); print_position(wpt); if IS_VALID_ALT(wpt->altitude) print_distance(wpt->altitude, 1, 0, 0); gbfprintf(fout, "\t"); x = WAYPT_GET(wpt, depth, unknown_alt); if (x != unknown_alt) print_distance(x, 1, 0, 1); gbfprintf(fout, "\t"); x = WAYPT_GET(wpt, proximity, unknown_alt); if (x != unknown_alt) print_distance(x, 0, 0, 0); gbfprintf(fout, "\t"); x = WAYPT_GET(wpt, temperature, -999); if (x != -999) print_temperature(x); gbfprintf(fout, "\t%s\t", dspl_mode); gbfprintf(fout, "Unknown\t"); /* Color is fixed: Unknown */ icon = GMSD_GET(icon, -1); if (icon == -1) { icon = gt_find_icon_number_from_desc(wpt->icon_descr, GDB); } icon_descr = gt_find_desc_from_icon_number(icon, GDB, &dynamic); print_string("%s\t", icon_descr); if (dynamic) xfree(icon_descr); print_string("%s\t", GMSD_GET(facility, "")); print_string("%s\t", GMSD_GET(city, "")); print_string("%s\t", GMSD_GET(state, "")); country = gt_get_icao_country(GMSD_GET(cc, "")); print_string("%s\t", (country != NULL) ? country : ""); print_date_and_time(wpt->creation_time, 0); print_string("%s\t", wpt->url ? wpt->url : ""); print_categories(GMSD_GET(category, 0)); gbfprintf(fout, "\r\n"); }
int main(int argc, char* argv[]) { int nbytes; int status; unsigned int previous, ch; unsigned int temp_extruder = 0, temp_bed = 0; // rename TODO unsigned int key_mask=0; unsigned int jog_distance = DEFAULT_JOG_DISTANCE; unsigned int jog_speed = DEFAULT_JOG_SPEED; unsigned int temp_target = DEFAULT_TEMP_TARGET; unsigned int feedrate = DEFAULT_FEEDRATE; // Explain? float delta_e = 0.001666669999999968 * (float)feedrate;; // TODO heater on/off keys // TODO consider a struct to hold state, then we can declare it once // and pass a single pointer around to various functions!!! // TODO float? need to? int posX=0, posY=0, posZ=0; float posE=0.0; int extruding=0; time_t last_temp = time(NULL); time_t last_extrude = time(NULL); int pipe_gcode = 0, pipe_feedback = 0; //stream_gcode = fdopen(pipe_gcode[1], "w"); FILE *stream_gcode = NULL, *stream_feedback = NULL; // User options char *serial_port = NULL; char *cmd = NULL; // Command string to execute austerus-core //size_t line_feedback_len = PIPE_LINE_BUFFER_LEN; //char *line_feedback = NULL; char line_feedback[LINE_FEEDBACK_LEN]; // Allocate inital size of input line buffer //pipe_buffer = (char *) malloc (pipe_buffer_len + 1); // Read command line options int option_index = 0, opt=0; static struct option loptions[] = { {"help", no_argument, 0, 'h'}, {"port", required_argument, 0, 'p'}, {"baud", required_argument, 0, 'b'}, {"verbose", no_argument, 0, 'v'} }; // Generate the command line for austerus-core asprintf(&cmd, "/usr/bin/env AG_ACKCOUNT=1 PATH=$PWD:$PATH"); while(opt >= 0) { opt = getopt_long(argc, argv, "hp:b:v", loptions, &option_index); switch (opt) { case 'h': usage(); return EXIT_SUCCESS; case 'p': serial_port = optarg; asprintf(&cmd, "%s AG_SERIALPORT=%s", cmd, optarg); break; case 'b': asprintf(&cmd, "%s AG_BAUDRATE=%ld", cmd, strtol(optarg, NULL, 10)); break; case 'v': asprintf(&cmd, "%s AG_VERBOSE=1", cmd); break; } } if (!serial_port & !getenv("AG_SERIALPORT")) { fprintf(stderr, "A serial port must be specified\n"); return EXIT_FAILURE; } asprintf(&cmd, "%s austerus-core", cmd); // Open the gcode output stream to austerus-core popen2(cmd, &pipe_gcode, &pipe_feedback); free(cmd); // Make feedback pipe non-blocking fcntl(pipe_feedback, F_SETFL, O_NONBLOCK); stream_gcode = fdopen(pipe_gcode, "w"); stream_feedback = fdopen(pipe_feedback, "r"); if (!stream_gcode) { fprintf(stderr, "unable to open output stream\n"); return EXIT_FAILURE; } if (!stream_feedback) { fprintf(stderr, "unable to open feedback stream\n"); return EXIT_FAILURE; } // Start curses mode initscr(); // Line buffering disabled raw(); // We get F1, F2 etc keypad(stdscr, TRUE); // Don't echo() while we do getch noecho(); // Hide cursor curs_set(0); // Timeout so we can run extruder and check for feedback timeout(CURSES_TIMEOUT); // draw initial screen mvprintw(0, 0, "austerusG %s", VERSION); mvprintw(0, 30, "- +"); print_fkeys(PANEL_POS_NUMBERS_X, PANEL_POS_NUMBERS_Y); print_extruder_keys(key_mask); print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); print_temperature(temp_extruder, temp_target); print_feedrate(feedrate); print_jog_distance(jog_distance); print_jog_speed(jog_speed); print_fan(0); mvprintw(LINES - 1, 0, "Status: Idle"); refresh(); // start of print reset fprintf(stream_gcode, "M110\n"); // set absolute positioning fprintf(stream_gcode, "G90\n"); // set to mm fprintf(stream_gcode, "G21\n"); // reset coordinates to zero fprintf(stream_gcode, "G92 X0 Y0 Z0 E0\n"); fflush(stream_gcode); while (1) { // Wait for user input ch = getch(); // Handle any two key sequences switch (previous) { case KEY_HOME: if (home_axis(stream_gcode, ch)) { key_mask = key_mask & !BIT_H; print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); } break; case KEY_END: if (end_axis(stream_gcode, ch)) { key_mask = key_mask & !BIT_END; print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); } break; } // Handle single key press switch (ch) { case '1': // Decrease target temperature if (temp_target > 0) { temp_target = temp_target - 1; fprintf(stream_gcode, "M104 S%d\n", temp_target); fflush(stream_gcode); print_temperature(temp_extruder, temp_target); } break; case '2': // Increase target temperature temp_target = temp_target + 1; fprintf(stream_gcode, "M104 S%d\n", temp_target); fflush(stream_gcode); print_temperature(temp_extruder, temp_target); break; case '3': // Decrease feedrate if (feedrate >= 1) { feedrate -= 1; delta_e = 0.001666669999999968 * (float)feedrate; print_feedrate(feedrate); } break; case '4': // Increase feedrate feedrate += 1; delta_e = 0.001666669999999968 * (float)feedrate; print_feedrate(feedrate); break; case '5': // Decrease jog distance if (jog_distance > 10) { fprintf(stream_gcode, "M104 %d\n", temp_target); fflush(stream_gcode); jog_distance = jog_distance - 10; print_jog_distance(jog_distance); } break; case '6': // Increase jog distance jog_distance = jog_distance + 10; print_jog_distance(jog_distance); break; case '7': // Decrease jog speed if (jog_speed > 10) { jog_speed = jog_speed - 100; print_jog_speed(jog_speed); } break; case '8': // Increase jog speed jog_speed = jog_speed + 100; print_jog_speed(jog_speed); break; case 'e': extruding = 1; key_mask = (key_mask | BIT_E) & ~(BIT_D | BIT_R); print_extruder_keys(key_mask); break; case 'd': extruding = 0; key_mask = (key_mask | BIT_D) & ~(BIT_E | BIT_R); print_extruder_keys(key_mask); break; case 'r': extruding = -1; key_mask = (key_mask | BIT_R) & ~(BIT_D | BIT_E); print_extruder_keys(key_mask); break; case KEY_LEFT: // Jog X axis minus // TODO merits of G0 or G1 moves? posX -= jog_distance; fprintf( stream_gcode, "G1 X%d Y%d Z%d F%d\n", posX, posY, posZ, jog_speed ); fflush(stream_gcode); key_mask = key_mask | BIT_MX; print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); break; case KEY_RIGHT: // Jog X axis plus posX += jog_distance; fprintf( stream_gcode, "G1 X%d Y%d Z%d F%d\n", posX, posY, posZ, jog_speed ); fflush(stream_gcode); key_mask = key_mask | BIT_PX; print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); break; case KEY_UP: // Jog Y axis plus posY += jog_distance; fprintf( stream_gcode, "G1 X%d Y%d Z%d F%d\n", posX, posY, posZ, jog_speed ); fflush(stream_gcode); key_mask = key_mask | BIT_PY; print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); break; case KEY_DOWN: // Jog Y axis minus posY -= jog_distance; fprintf( stream_gcode, "G1 X%d Y%d Z%d F%d\n", posX, posY, posZ, jog_speed ); fflush(stream_gcode); key_mask = key_mask | BIT_MY; print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); break; case KEY_PPAGE: // Jog Z axis up posZ += jog_distance; fprintf( stream_gcode, "G1 X%d Y%d Z%d F%d\n", posX, posY, posZ, jog_speed ); fflush(stream_gcode); key_mask = key_mask | BIT_PZ; print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); break; case KEY_NPAGE: // Jog Z axis down posZ -= jog_distance; fprintf( stream_gcode, "G1 X%d Y%d Z%d F%d\n", posX, posY, posZ, jog_speed ); fflush(stream_gcode); key_mask = key_mask | BIT_MZ; print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); break; case KEY_HOME: // Start of two key move to home command key_mask = key_mask | BIT_H; print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); previous = ch; break; case KEY_END: // Start of two key move to end command key_mask = key_mask | BIT_END; print_keys(PANEL_POS_KEYS_X, PANEL_POS_KEYS_Y, key_mask); previous = ch; break; case 'f': case 'F': // Fan on fprintf(stream_gcode, "M106\n"); fflush(stream_gcode); print_fan(1); break; case 'g': case 'G': // Fan off fprintf(stream_gcode, "M107\n"); fflush(stream_gcode); print_fan(0); break; case 'q': case KEY_ESC: // Shutdown printer fprintf(stream_gcode, "M112\n"); // Exit core fprintf(stream_gcode, "#ag:exit\n\n"); fflush(stream_gcode); endwin(); pclose(stream_gcode); pclose(stream_feedback); close(pipe_gcode); close(pipe_feedback); //if (line_feedback) // free(line_feedback); wait(&status); printf("core exit = %d\n", status); return EXIT_SUCCESS; } // TODO check core alive? if (time(NULL) - last_temp > TEMP_PERIOD) { do { nbytes = nonblock_getline(line_feedback, stream_feedback); //nbytes = getline(&line_feedback, &line_feedback_len, stream_feedback); //fprintf(stream_gcode, "NB %d %s\n", nbytes); //fflush(stream_gcode); if (nbytes > 0) { mvprintw(LINES - 3, 0, "nb %d", nbytes); sscanf(line_feedback, "ok T:%d B:%d", &temp_extruder, &temp_bed); // if (nbytes > 66) { line_feedback[63] = '.'; line_feedback[64] = '.'; line_feedback[65] = '.'; line_feedback[66] = '\0'; } mvprintw(LINES - 2, 0, "Response: %s", line_feedback); print_temperature(temp_extruder, temp_target); } } while (nbytes != -1); last_temp = time(NULL); fprintf(stream_gcode, "M105\n"); fflush(stream_gcode); // tODO this needs it's own clock too! // tODO arrow keys etc if (key_mask | BIT_D) { key_mask = key_mask & ~BIT_D; print_extruder_keys(key_mask); } // We can make one mask #def? from all keys we want cleared // and use it for check andf clear! } if (time(NULL) - last_extrude > EXTRUDE_PERIOD) { last_extrude = time(NULL); // This needs to be on an indepentent time check so it can be controlled!! TODO if (extruding > 0) { posE += delta_e; fprintf(stream_gcode, "G1 E%.2f F%d\n", posE, feedrate); fflush(stream_gcode); } else if (extruding < 0) { posE -= delta_e; fprintf(stream_gcode, "G1 E%.2f F%d\n", posE, feedrate); fflush(stream_gcode); } // tODO arrow keys etc if (key_mask | BIT_D) { key_mask = key_mask & ~BIT_D; print_extruder_keys(key_mask); } // We can make one mask #def? from all keys we want cleared // and use it for check andf clear! } refresh(); // TODO check core is still alive } }