static void eload(Space *s, uint8_t old_type, int32_t &addr) { uint8_t num = read_8(addr); if (!s->setup_nums(num, num)) { debug("Failed to set up extruder axes"); uint8_t n = min(s->num_axes, s->num_motors); if (!s->setup_nums(n, n)) { debug("Trouble! Failed to abort. Cancelling."); s->cancel_update(); } } for (int a = EDATA(s).num_axes; a < s->num_axes; ++a) { s->axis[a]->type_data = new ExtruderAxisData; for (int i = 0; i < 3; ++i) EADATA(s, a).offset[i] = 0; } EDATA(s).num_axes = s->num_axes; bool move = false; if (motors_busy && !computing_move && settings.queue_start == settings.queue_end && !settings.queue_full) { move = true; queue[settings.queue_end].probe = false; queue[settings.queue_end].cb = false; queue[settings.queue_end].f[0] = INFINITY; queue[settings.queue_end].f[1] = INFINITY; for (int i = 0; i < spaces[0].num_axes; ++i) { queue[settings.queue_end].data[i] = spaces[0].axis[i]->settings.current; for (int ss = 0; ss < 2; ++ss) queue[settings.queue_end].data[i] = space_types[spaces[ss].type].unchange0(&spaces[ss], i, queue[settings.queue_end].data[i]); if (i == 2) queue[settings.queue_end].data[i] -= zoffset; } for (int i = spaces[0].num_axes; i < QUEUE_LENGTH; ++i) { queue[settings.queue_end].data[i] = NAN; } cpdebug(0, 0, "eload end"); settings.queue_end = (settings.queue_end + 1) % QUEUE_LENGTH; // This shouldn't happen and causes communication problems, but if you have a 1-item buffer it is correct. if (settings.queue_end == settings.queue_start) settings.queue_full = true; } for (int a = 0; a < s->num_axes; ++a) { for (int o = 0; o < 3; ++o) EADATA(s, a).offset[o] = read_float(addr); } if (move) { next_move(); buffer_refill(); } }
void move_to_current() { // {{{ if (computing_move || !motors_busy) { if (moving_to_current == 0) moving_to_current = 1; return; } moving_to_current = 0; debug("move to current"); settings.f0 = 0; settings.fmain = 1; settings.fp = 0; settings.fq = 0; settings.t0 = 0; settings.tp = 0; cbs_after_current_move = 0; current_fragment_pos = 0; first_fragment = current_fragment; computing_move = true; settings.cbs = 0; settings.hwtime = 0; settings.start_time = 0; settings.last_time = 0; settings.last_current_time = 0; for (uint8_t s = 0; s < 2; ++s) { Space &sp = spaces[s]; sp.settings.dist[0] = 0; sp.settings.dist[1] = 0; for (uint8_t a = 0; a < sp.num_axes; ++a) { cpdebug(s, a, "using current %f", sp.axis[a]->settings.current); sp.axis[a]->settings.source = sp.axis[a]->settings.current; sp.axis[a]->settings.target = sp.axis[a]->settings.current; sp.axis[a]->settings.dist[0] = 0; sp.axis[a]->settings.dist[1] = 0; sp.axis[a]->settings.main_dist = 0; } for (uint8_t m = 0; m < sp.num_motors; ++m) sp.motor[m]->settings.last_v = 0; } #ifdef DEBUG_PATH fprintf(stderr, "\n"); #endif buffer_refill(); } // }}}
void move_to_current() { // {{{ if (computing_move || !motors_busy) { if (moving_to_current == 0) moving_to_current = 1; return; } moving_to_current = 0; //debug("move to current"); settings.f0 = 0; settings.fmain = 1; settings.fp = 0; settings.fq = 0; settings.t0 = 0; settings.tp = 0; //debug("clearing %d cbs after current move for move to current", cbs_after_current_move); cbs_after_current_move = 0; current_fragment_pos = 0; first_fragment = current_fragment; computing_move = true; settings.cbs = 0; settings.hwtime = 0; settings.start_time = 0; settings.last_time = 0; settings.last_current_time = 0; for (int s = 0; s < NUM_SPACES; ++s) { Space &sp = spaces[s]; sp.settings.dist[0] = 0; sp.settings.dist[1] = 0; for (int a = 0; a < sp.num_axes; ++a) { cpdebug(s, a, "using current %f", sp.axis[a]->settings.current); sp.axis[a]->settings.source = sp.axis[a]->settings.current; sp.axis[a]->settings.target = sp.axis[a]->settings.current; sp.axis[a]->settings.dist[0] = 0; sp.axis[a]->settings.dist[1] = 0; sp.axis[a]->settings.main_dist = 0; } for (int m = 0; m < sp.num_motors; ++m) sp.motor[m]->settings.last_v = 0; } buffer_refill(); } // }}}
void run_file_fill_queue() { static bool lock = false; if (lock) return; lock = true; rundebug("run queue, wait = %d tempwait = %d q = %d %d %d finish = %d", run_file_wait, run_file_wait_temp, settings.queue_end, settings.queue_start, settings.queue_full, run_file_finishing); if (run_file_audio >= 0) { while (true) { if (!run_file_map || run_file_wait || run_file_finishing) break; if (settings.run_file_current >= run_file_num_records) { run_file_finishing = true; //debug("done running audio"); break; } int16_t next = (current_fragment + 1) % FRAGMENTS_PER_BUFFER; if (next == running_fragment) break; settings.run_file_current = arch_send_audio(&reinterpret_cast <uint8_t *>(run_file_map)[sizeof(double)], settings.run_file_current, run_file_num_records, run_file_audio); current_fragment = next; store_settings(); if ((current_fragment - running_fragment + FRAGMENTS_PER_BUFFER) % FRAGMENTS_PER_BUFFER >= MIN_BUFFER_FILL && !stopping) arch_start_move(0); } lock = false; return; } while (run_file_map // There is a file to run. && (settings.queue_end - settings.queue_start + QUEUE_LENGTH) % QUEUE_LENGTH < 4 // There is space in the queue. && !settings.queue_full // Really, there is space in the queue. && settings.run_file_current < run_file_num_records // There are records to send. && !run_file_wait_temp // We are not waiting for a temp alarm. && !run_file_wait // We are not waiting for something else (pause or confirm). && !run_file_finishing) { // We are not waiting for underflow (should be impossible anyway, if there are commands in the queue). int t = run_file_map[settings.run_file_current].type; if (t != RUN_LINE && t != RUN_PRE_LINE && t != RUN_PRE_ARC && t != RUN_ARC && (arch_running() || settings.queue_end != settings.queue_start || computing_move)) break; Run_Record &r = run_file_map[settings.run_file_current]; rundebug("running %d: %d %d", settings.run_file_current, r.type, r.tool); switch (r.type) { case RUN_SYSTEM: { char const *cmd = strndupa(&reinterpret_cast<char const *>(run_file_map)[run_file_first_string + strings[r.tool].start], strings[r.tool].len); debug("Running system command: %ld %d %s", strings[r.tool].start, strings[r.tool].len, cmd); int ret = system(cmd); debug("Done running system command, return = %d", ret); break; } case RUN_PRE_ARC: { double x = r.X * run_file_cosa - r.Y * run_file_sina + run_file_refx; double y = r.Y * run_file_cosa + r.X * run_file_sina + run_file_refy; double z = r.Z; //debug("line %f %f %f", x, y, z); queue[settings.queue_end].center[0] = x; queue[settings.queue_end].center[1] = y; queue[settings.queue_end].center[2] = handle_probe(x, y, z); queue[settings.queue_end].normal[0] = r.E; queue[settings.queue_end].normal[1] = r.f; queue[settings.queue_end].normal[2] = r.F; break; } case RUN_PRE_LINE: { run_preline.X = r.X; run_preline.Y = r.Y; run_preline.Z = r.Z; run_preline.E = r.E; run_preline.tool = r.tool; break; } case RUN_LINE: case RUN_ARC: { queue[settings.queue_end].single = false; queue[settings.queue_end].probe = false; queue[settings.queue_end].arc = r.type == RUN_ARC; queue[settings.queue_end].f[0] = r.f; queue[settings.queue_end].f[1] = r.F; double x = r.X * run_file_cosa - r.Y * run_file_sina + run_file_refx; double y = r.Y * run_file_cosa + r.X * run_file_sina + run_file_refy; double z = r.Z; //debug("line/arc %f %f %f", x, y, z); int num0 = spaces[0].num_axes; if (num0 > 0) { queue[settings.queue_end].data[0] = x; if (num0 > 1) { queue[settings.queue_end].data[1] = y; if (num0 > 2) { queue[settings.queue_end].data[2] = handle_probe(x, y, z); if (num0 > 3) { queue[settings.queue_end].data[3] = run_preline.X; if (num0 > 4) { queue[settings.queue_end].data[4] = run_preline.Y; if (num0 > 5) { queue[settings.queue_end].data[5] = run_preline.Z; } } run_preline.X = NAN; run_preline.Y = NAN; run_preline.Z = NAN; } } } } for (int i = 6; i < num0; ++i) queue[settings.queue_end].data[i] = NAN; for (int i = 0; i < spaces[1].num_axes; ++i) { queue[settings.queue_end].data[num0 + i] = (i == r.tool ? r.E : i == run_preline.tool ? run_preline.E : NAN); //debug("queue %d + %d = %f", num0, i, queue[settings.queue_end].data[num0 + i]); } run_preline.E = NAN; num0 += spaces[1].num_axes; for (int s = 2; s < NUM_SPACES; ++s) { for (int i = 0; i < spaces[s].num_axes; ++i) queue[settings.queue_end].data[num0 + i] = NAN; num0 += spaces[s].num_axes; } queue[settings.queue_end].time = r.time; queue[settings.queue_end].dist = r.dist; queue[settings.queue_end].cb = false; settings.queue_end = (settings.queue_end + 1) % QUEUE_LENGTH; if (!computing_move) next_move(); else rundebug("no"); buffer_refill(); break; } case RUN_GPIO: { int tool = r.tool; if (tool == -2) tool = fan_id; else if (tool == -3) tool = spindle_id; if (tool < 0 || tool >= num_gpios) { if (tool != -1) debug("cannot set invalid gpio %d", tool); break; } if (r.X) { gpios[tool].state = 1; SET(gpios[tool].pin); } else { gpios[tool].state = 0; RESET(gpios[tool].pin); } send_host(CMD_UPDATE_PIN, tool, gpios[tool].state); break; } case RUN_SETTEMP: { int tool = r.tool; if (tool == -1) tool = bed_id; rundebug("settemp %d %f", tool, r.X); settemp(tool, r.X); send_host(CMD_UPDATE_TEMP, tool, 0, r.X); break; } case RUN_WAITTEMP: { int tool = r.tool; if (tool == -2) tool = bed_id; if (tool == -3) { for (int i = 0; i < num_temps; ++i) { if (temps[i].min_alarm >= 0 || temps[i].max_alarm < MAXINT) { run_file_wait_temp += 1; waittemp(i, temps[i].min_alarm, temps[i].max_alarm); } } break; } if (tool < 0 || tool >= num_temps) { if (tool != -1) debug("cannot wait for invalid temp %d", tool); break; } else rundebug("waittemp %d", tool); if (temps[tool].adctarget[0] >= 0 && temps[tool].adctarget[0] < MAXINT) { rundebug("waiting"); run_file_wait_temp += 1; waittemp(tool, temps[tool].target[0], temps[tool].max_alarm); } else rundebug("not waiting"); break; } case RUN_SETPOS: if (r.tool >= spaces[1].num_axes) { debug("Not setting position of invalid extruder %d", r.tool); break; } setpos(1, r.tool, r.X); break; case RUN_WAIT: if (r.X > 0) { run_file_timer.it_value.tv_sec = r.X; run_file_timer.it_value.tv_nsec = (r.X - run_file_timer.it_value.tv_sec) * 1e9; run_file_wait += 1; timerfd_settime(pollfds[0].fd, 0, &run_file_timer, NULL); } break; case RUN_CONFIRM: { int len = min(strings[r.tool].len, 250); memcpy(datastore, &reinterpret_cast<char const *>(run_file_map)[run_file_first_string + strings[r.tool].start], len); run_file_wait += 1; send_host(CMD_CONFIRM, r.X ? 1 : 0, 0, 0, 0, len); break; } case RUN_PARK: run_file_wait += 1; send_host(CMD_PARKWAIT); break; default: debug("Invalid record type %d in %s", r.type, run_file_name); break; } settings.run_file_current += 1; } rundebug("run queue done"); if (run_file_map && settings.run_file_current >= run_file_num_records && !run_file_wait_temp && !run_file_wait && !run_file_finishing) { // Done. //debug("done running file"); if (!computing_move && !sending_fragment && !arch_running()) { send_host(CMD_FILE_DONE); abort_run_file(); } else run_file_finishing = true; } lock = false; return; }
bool globals_load(int32_t &addr) { bool change_hw = false; uint8_t nt = read_8(addr); uint8_t ng = read_8(addr); // Free the old memory and initialize the new memory. if (nt != num_temps) { ldebug("new temp"); for (uint8_t t = nt; t < num_temps; ++t) temps[t].free(); Temp *new_temps = new Temp[nt]; for (uint8_t t = 0; t < min(nt, num_temps); ++t) temps[t].copy(new_temps[t]); for (uint8_t t = num_temps; t < nt; ++t) new_temps[t].init(); delete[] temps; temps = new_temps; num_temps = nt; } if (ng != num_gpios) { for (uint8_t g = ng; g < num_gpios; ++g) gpios[g].free(); Gpio *new_gpios = new Gpio[ng]; for (uint8_t g = 0; g < min(ng, num_gpios); ++g) gpios[g].copy(new_gpios[g]); for (uint8_t g = num_gpios; g < ng; ++g) new_gpios[g].init(); delete[] gpios; gpios = new_gpios; num_gpios = ng; } ldebug("new done"); int p = led_pin.write(); led_pin.read(read_16(addr)); if (p != led_pin.write()) change_hw = true; p = stop_pin.write(); stop_pin.read(read_16(addr)); if (p != stop_pin.write()) change_hw = true; p = probe_pin.write(); probe_pin.read(read_16(addr)); if (p != probe_pin.write()) change_hw = true; p = spiss_pin.write(); spiss_pin.read(read_16(addr)); if (p != spiss_pin.write()) change_hw = true; int t = timeout; timeout = read_16(addr); if (t != timeout) change_hw = true; bed_id = read_16(addr); fan_id = read_16(addr); spindle_id = read_16(addr); feedrate = read_float(addr); if (isnan(feedrate) || isinf(feedrate) || feedrate <= 0) feedrate = 1; max_deviation = read_float(addr); max_v = read_float(addr); int ce = read_8(addr); targetx = read_float(addr); targety = read_float(addr); double zo = read_float(addr); if (motors_busy && (current_extruder != ce || zoffset != zo) && settings.queue_start == settings.queue_end && !settings.queue_full && !computing_move) { queue[settings.queue_end].probe = false; queue[settings.queue_end].cb = false; queue[settings.queue_end].f[0] = INFINITY; queue[settings.queue_end].f[1] = INFINITY; for (int i = 0; i < spaces[0].num_axes; ++i) { queue[settings.queue_end].data[i] = spaces[0].axis[i]->settings.current - (i == 2 ? zoffset : 0); for (int s = 0; s < NUM_SPACES; ++s) queue[settings.queue_end].data[i] = space_types[spaces[s].type].unchange0(&spaces[s], i, queue[settings.queue_end].data[i]); } for (int i = spaces[0].num_axes; i < QUEUE_LENGTH; ++i) { queue[settings.queue_end].data[i] = NAN; } settings.queue_end = (settings.queue_end + 1) % QUEUE_LENGTH; // This shouldn't happen and causes communication problems, but if you have a 1-item buffer it is correct. if (settings.queue_end == settings.queue_start) settings.queue_full = true; current_extruder = ce; zoffset = zo; next_move(); buffer_refill(); } else { current_extruder = ce; zoffset = zo; } bool store = read_8(addr); if (store && !store_adc) { store_adc = fopen("/tmp/franklin-adc-dump", "a"); } else if (!store && store_adc) { fclose(store_adc); store_adc = NULL; } ldebug("all done"); if (change_hw) arch_motors_change(); return true; }