void choose_delay(nrk_time_t *delay, nrk_time_t *max_delay) { /* Make roughly twice as many parts as nodes */ const uint8_t part_denom = 100; /* doesn't matter too much */ const uint8_t part_numerator = part_denom / (2 * MAX_NODES); uint16_t delay_ms; /* Pick a random fraction of the specified delay */ delay_ms = TIME_TO_MS(*max_delay); delay_ms = (delay_ms * part_numerator / part_denom) * (rand() % (part_denom / part_numerator + 1)); MS_TO_TIME(*delay, delay_ms); }
int8_t cmd_cnvtime(uint8_t argc, char **argv) { nrk_time_t time; uint32_t ms; char to_unit; char *sec, *nsec; if (argc != 3) { OUT("usage: cnvtime t|m <value>\r\n"); return NRK_ERROR; } to_unit = argv[1][0]; switch (to_unit) { case 't': ms = atol(argv[2]); MS_TO_TIME(time, ms); OUTP("%lu = ", ms); OUTP("%lu:%lu\r\n", time.secs, time.nano_secs); break; case 'm': sec = argv[2]; nsec = strchr(sec, ':'); if (nsec == NULL) { OUT("invalid time value: expecting s:ns\r\n"); return; } *nsec = '\0'; nsec++; time.secs = atol(sec); time.nano_secs = atol(nsec); ms = TIME_TO_MS(time); OUTP("%lu:%lu = ", time.secs, time.nano_secs); OUTP("%lu ms\r\n", ms); break; default: OUT("unknown unit\r\n"); return NRK_ERROR; } return NRK_OK; }
float sol_step(struct s_vary *vary, const float *g, float dt, int ui, int *m) { float P[3], V[3], v[3], r[3], a[3], d, e, nt, b = 0.0f, tt = dt, t; int c; union cmd cmd; if (ui < vary->uc) { struct v_ball *up = vary->uv + ui; /* If the ball is in contact with a surface, apply friction. */ v_cpy(a, up->v); v_cpy(v, up->v); v_cpy(up->v, g); if (m && sol_test_file(tt, P, V, up, vary) < 0.0005f) { v_cpy(up->v, v); v_sub(r, P, up->p); t = v_len(r) * v_len(g); if (t == 0.f) { t = SMALL; } if ((d = v_dot(r, g) / t) > 0.999f) { if ((e = (v_len(up->v) - dt)) > 0.0f) { /* Scale the linear velocity. */ v_nrm(up->v, up->v); v_scl(up->v, up->v, e); /* Scale the angular velocity. */ v_sub(v, V, up->v); v_crs(up->w, v, r); v_scl(up->w, up->w, -1.0f / (up->r * up->r)); } else { /* Friction has brought the ball to a stop. */ up->v[0] = 0.0f; up->v[1] = 0.0f; up->v[2] = 0.0f; (*m)++; } } else v_mad(up->v, v, g, tt); } else v_mad(up->v, v, g, tt); /* Test for collision. */ for (c = 16; c > 0 && tt > 0; c--) { float st; int mi, ms; /* HACK: avoid stepping across path changes. */ st = tt; for (mi = 0; mi < vary->mc; mi++) { struct v_move *mp = vary->mv + mi; struct v_path *pp = vary->pv + mp->pi; if (!pp->f) continue; if (mp->tm + ms_peek(st) > pp->base->tm) st = MS_TO_TIME(pp->base->tm - mp->tm); } /* Miss collisions if we reach the iteration limit. */ if (c > 1) nt = sol_test_file(st, P, V, up, vary); else nt = tt; cmd.type = CMD_STEP_SIMULATION; cmd.stepsim.dt = nt; sol_cmd_enq(&cmd); ms = ms_step(nt); sol_move_step(vary, nt, ms); sol_swch_step(vary, nt, ms); sol_ball_step(vary, nt); if (nt < st) if (b < (d = sol_bounce(up, P, V, nt))) b = d; tt -= nt; } v_sub(a, up->v, a); sol_pendulum(up, a, g, dt); } return b; }