char *rx_server_request(struct mg_connection *mc, char *buf, size_t *size) { int i, j, n; const char *s; stream_t *st; char *op = NULL, *oc, *lc; int badp; int rem = NREQ_BUF; for (st=streams; st->uri; st++) { if (strcmp(mc->uri, st->uri) == 0) break; } if (!st->uri) return NULL; if (down && (st->type != STREAM_PWD)) return NULL; buf[0]=0; switch (st->type) { case STREAM_OTHERS: conn_t *c; op = buf; oc = op; for (c=conns; c<&conns[RX_CHANS*2]; c++) { if (c->type == STREAM_SOUND) { if (c->arrived) { n = snprintf(oc, rem, "user(%d,\"%s\",\"%s\",%d);", c->rx_channel, c->user, c->geo, c->freqHz); } else { n = snprintf(oc, rem, "user(%d,\"\",\"\",0);", c->rx_channel); } if (!rem || rem < n) { *oc = 0; break; } else { oc += n; rem -= n; } } } // statistics int stats; stats=0; n = sscanf(mc->query_string, "stats=%d", &stats); //printf("%d %d <%s>\n", n, stats, mc->query_string); lc = oc; // skip entire response if we run out of room for (; stats; ) { // hack so we can use 'break' statements below n = snprintf(oc, rem, "wrx_cpu_stats("); if (!rem || rem < n) { oc = lc; *oc = 0; break; } else { oc += n; rem -= n; } int user, sys, idle; static int last_user, last_sys, last_idle; user = sys = 0; u4_t now = timer_ms(); static u4_t last_now; float secs = (float)(now - last_now) / 1000; last_now = now; float del_user = 0; float del_sys = 0; float del_idle = 0; FILE *pf = popen("cat /proc/stat", "r"); if (pf) { char pfbuf[128]; pfbuf[0]=0; n = fscanf(pf, "cpu %d %*d %d %d", &user, &sys, &idle); //long clk_tick = sysconf(_SC_CLK_TCK); del_user = (float)(user - last_user) / secs; del_sys = (float)(sys - last_sys) / secs; del_idle = (float)(idle - last_idle) / secs; //printf("CPU %.1fs u=%.1f%% s=%.1f%% i=%.1f%%\n", secs, del_user, del_sys, del_idle); pclose(pf); n = snprintf(oc, rem, "\"Beagle CPU %.0f%% usr / %.0f%% sys / %.0f%% idle, \"+", del_user, del_sys, del_idle); if (!rem || rem < n) { oc = lc; *oc = 0; break; } else { oc += n; rem -= n; } last_user = user; last_sys = sys; last_idle = idle; } n = snprintf(oc, rem, "\"FPGA eCPU %.1f%%\");", ecpu_use()); if (!rem || rem < n) { oc = lc; *oc = 0; break; } else { oc += n; rem -= n; } float sum_kbps = audio_kbps + waterfall_kbps + http_kbps; n = snprintf(oc, rem, "wrx_audio_stats(\"audio %.1f kB/s, waterfall %.1f kB/s (%.1f fps), http %.1f kB/s, total %.1f kB/s (%.1f kb/s)\");", audio_kbps, waterfall_kbps, waterfall_fps, http_kbps, sum_kbps, sum_kbps*8); if (!rem || rem < n) { *lc = 0; break; } else { oc += n; rem -= n; } n = snprintf(oc, rem, "wrx_config(\"%d receiver channels, %d GPS channels\");", RX_CHANS, GPS_CHANS); if (!rem || rem < n) { oc = lc; *oc = 0; break; } else { oc += n; rem -= n; } stats = 0; // only run loop once } *size = oc-op; if (*size == 0) { buf[0] = ';'; *size = 1; } return buf; break; #define DX_SPACING_ZOOM_THRESHOLD 5 #define DX_SPACING_THRESHOLD_PX 5 case STREAM_DX: float min, max; int zoom, width; n = sscanf(mc->query_string, "min=%f&max=%f&zoom=%d&width=%d", &min, &max, &zoom, &width); if (n != 4) break; float bw; bw = max - min; op = buf; oc = op; static bool first = true; static int dx_lastx; dx_lastx = 0; for (i=0, j=0; i < ARRAY_LEN(dx); i++) { dx_t *dp; dp = &dx[i]; float freq; freq = dp->freq; if (freq < min || freq > max) continue; // reduce dx label clutter if (zoom <= DX_SPACING_ZOOM_THRESHOLD) { int x = ((dp->freq - min) / bw) * width; int diff = x - dx_lastx; //printf("DX spacing %d %d %d %s\n", dx_lastx, x, diff, dp->text); if (!first && diff < DX_SPACING_THRESHOLD_PX) continue; dx_lastx = x; first = false; } n = snprintf(oc, rem, "dx(%.3f,\"%s\",\'%s\');", dp->freq, dp->mode, dp->text); if (!rem || rem < n) { *oc = 0; printf("STREAM_DX: buffer overflow %d/%d min=%f max=%f z=%d w=%d\n", i, ARRAY_LEN(dx), min, max, zoom, width); break; } else { oc += n; rem -= n; j++; } } //printf("STREAM_DX: %d <%s>\n", j, op); *size = oc-op; if (*size == 0) { buf[0] = ';'; *size = 1; } return buf; break; case STREAM_PWD: char pwd[32]; pwd[0]=0; //printf("STREAM_PWD: <%s>\n", mc->query_string); sscanf(mc->query_string, "pwd=%31s", pwd); badp = strcmp(pwd, "kiwi"); if (badp) badp = strcmp(pwd, "Kiwi"); if (badp) lprintf("bad pwd from %s\n", mc->remote_ip); op = buf; oc = op; n = snprintf(oc, rem, "wrx_setpwd(\"%s\",\"%s\");", badp? "bad":pwd, badp? "bad":WRX_KEY); if (!rem || rem < n) { *oc = 0; } else { oc += n; rem -= n; } *size = oc-op; return buf; break; default: break; } return NULL; }
void StatTask() { int i, j, prn; unsigned start = timer_ms(); while (!ready) TaskSleep(1000000); while (1) { UMS lat(StatLat), lon(StatLon); UMS hms(StatSec/60/60); TaskSleep(1000000); if (print_stats == 2) { static int fixes; if (gps.fixes > fixes) { fixes = gps.fixes; if (StatLat) printf("wikimapia.org/#lang=en&lat=%9.6f&lon=%9.6f&z=18&m=b\n", (StatNS=='S')? -StatLat:StatLat, (StatEW=='W')? -StatLon:StatLon); } continue; } printf("\n\n\n\n\n\n"); #if DECIM_CMP printf(" CH PRN SNR CA ERR RSSI GAIN BITS WDOG SUB"); #else // 12345 * 1234 123456 123456 123456 123456 123456 Up12345 123456 ######### printf(" CH PRN SNR RSSI GAIN BITS WDOG SUB NOVFL"); #endif //printf(" LS CS LO SLO DLO CA SCA DCA"); printf("\n"); for (i=0; i<gps_chans; i++) { stats_t *s = &stats[i]; char c1, c2; double snew; printf("%5d %c ", i+1, (stats_fft == i)? '*':' '); show4(prn, prn); show6(snr, snr); #if DECIM_CMP show6(snr, ca_dop); printf(" "); #endif show6(rssi, rssi); show6(rssi, gain); show6(hold, hold); show6(rssi, wdog); printf("%c", s->ca_unlocked? 'U':' '); printf("%c", (s->sub & (1<<(PARITY-1)))? 'p':' '); s->sub &= ~(1<<(PARITY-1)); // clear parity for (j=4; j>=0; j--) { printf("%c", (s->sub & (1<<j))? '1'+j:' '); if (s->sub_next & (1<<j)) { s->sub |= 1<<j; s->sub_next &= ~(1<<j); } } show7(novfl, novfl); printf(" "); #if 0 if (s->rssi) printf("%6d:E %6d:P %6d:L ", s->pe/1000, s->pp/1000, s->pl/1000); #endif #if 0 show3(rssi, lo_dop); show5(rssi, ca_dop); if (s->dir == ' ') s->f_lo=s->lo, s->f_ca=s->ca; snew = fabs(s->f_lo-s->lo); if (snew > s->s_lo) s->s_lo = snew; snew = fabs(s->f_ca-s->ca); if (snew > s->s_ca) s->s_ca = snew; showf7_1(lo, lo); showf7_1(s_lo, s_lo); showf7_1(d_lo, d_lo); showf7_4(ca, ca); showf7_4(s_ca, s_ca); showf7_4(d_ca, d_ca); c1 = c2 = '_'; if (s->rssi) { s->to++; if (s->lo < s->l_lo) { s->l_lo=s->lo; s->dir='v'; s->to=0; c1='v'; } else if (s->lo > s->h_lo) { s->h_lo=s->lo; s->dir='^'; s->to=0; c1='^'; }; if (s->ca < s->l_ca) { s->l_ca=s->ca; s->to=0; c2='v'; } else if (s->ca > s->h_ca) { s->h_ca=s->ca; s->to=0; c2='^'; }; } printf("%c%c ", c1, c2); if (s->rssi) printf("%3d%c ", s->to, s->dir); else printf(" "); #endif //if (s->dbug) printf("%9.6f %9.6f %6d %6d %6d ", // s->dbug_d1, s->dbug_d2, s->dbug_i1, s->dbug_i2, s->dbug_i3); printf(" "); for (j=0; j < s->rssi*50/3000; j++) printf("#"); printf ("\n"); #if DECIM_CMP printf(" "); show6(snr2, snr2); show6(snr2, ca_dop2); show6(snr2, ca_dop-s->ca_dop2); printf ("\n"); #endif } printf("\n"); NextTask("stat1"); printf(" SATS "); if (gps.tracking) printf("tracking %d", gps.tracking); if (gps.good) printf(", good %d", gps.good); printf("\n"); printf(" LAT "); if (StatLat) printf("%9.5fd %c %3dd %2dm %6.3fs %c ", StatLat, StatNS, lat.u, lat.m, lat.s, StatNS); if (StatLat) printf("%3dd %6.3fm %c", lat.u, lat.fm, StatNS); printf("\n"); printf(" LON "); if (StatLat) printf("%9.5fd %c %3dd %2dm %6.3fs %c ", StatLon, StatEW, lon.u, lon.m, lon.s, StatEW); if (StatLat) printf("%3dd %6.3fm %c", lon.u, lon.fm, StatEW); printf("\n"); printf(" ALT "); if (StatLat) printf("%1.0f m", StatAlt); printf("\n"); printf(" TIME "); if (StatDay != -1) printf("%s %02d:%02d:%02.0f GPST", Week[StatDay], hms.u, hms.m, hms.s); printf("\n"); printf("FIXES "); if (gps.fixes) printf("%d", gps.fixes); printf("\n"); printf(" TTFF "); if (stats_ttff) printf("%d:%02d", stats_ttff / 60, stats_ttff % 60); printf("\n"); printf(" RUN "); unsigned r = (timer_ms() - start)/1000; if (r >= 3600) printf("%02d:", r / 3600); printf("%02d:%02d", (r / 60) % 60, r % 60); printf("\n"); printf(" MAP "); if (StatLat) printf("wikimapia.org/#lang=en&lat=%9.6f&lon=%9.6f&z=18&m=b", (StatNS=='S')? -StatLat:StatLat, (StatEW=='W')? -StatLon:StatLon); printf("\n"); printf(" ECPU "); printf("%4.1f%% cmds %d/%d", ecpu_use(), ecpu_cmds, ecpu_tcmds); ecpu_cmds = ecpu_tcmds = 0; printf("\n"); int offset = (int)(adc_clock - adc_clock_nom); printf(" DECIM: %d FFT: %d -> %d CCF: %5.3fs MIN_SIG: %d ADC_CLK: %.6f %s%d (%d) ACQ: %d", decim, FFT_LEN, FFT_LEN/decim, fft_msec, min_sig, adc_clock/1000000.0, (offset >= 0)? "+":"", offset, gps.adc_clk_corr, gps.acquiring); printf("\n"); printf("\n"); NextTask("stat2"); TaskDump(); } }
int main(int argc, char *argv[]) { u2_t *up; int i; char s[32]; // enable generation of core file in /tmp scall("core_pattern", system("echo /tmp/core-%e-%s-%u-%g-%p-%t > /proc/sys/kernel/core_pattern")); const struct rlimit unlim = { RLIM_INFINITY, RLIM_INFINITY }; scall("setrlimit", setrlimit(RLIMIT_CORE, &unlim)); for (i=1; i<argc; ) { if (strcmp(argv[i], "-bg")==0) { background_mode = TRUE; bg=1; } if (strcmp(argv[i], "-off")==0) do_off = 1; if (strcmp(argv[i], "-down")==0) down = 1; if (strcmp(argv[i], "+gps")==0) do_gps = 1; if (strcmp(argv[i], "-gps")==0) do_gps = 0; if (strcmp(argv[i], "+sdr")==0) do_sdr = 1; if (strcmp(argv[i], "-sdr")==0) do_sdr = 0; if (strcmp(argv[i], "+fft")==0) do_fft = 1; if (strcmp(argv[i], "-stats")==0 || strcmp(argv[i], "+stats")==0) { if (i+1 < argc && isdigit(argv[i+1][0])) { i++; print_stats = strtol(argv[i], 0, 0); } else { print_stats = 1; } } if (strcmp(argv[i], "-eeprom")==0) create_eeprom = true; if (strcmp(argv[i], "-cmap")==0) color_map = 1; if (strcmp(argv[i], "-sim")==0) wf_sim = 1; if (strcmp(argv[i], "-real")==0) wf_real = 1; if (strcmp(argv[i], "-time")==0) wf_time = 1; if (strcmp(argv[i], "-port")==0) { i++; alt_port = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-p")==0) { alt_port = 8074; } if (strcmp(argv[i], "-dump")==0 || strcmp(argv[i], "+dump")==0) { i++; ev_dump = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-flip")==0) wf_flip = 1; if (strcmp(argv[i], "-start")==0) wf_start = 1; if (strcmp(argv[i], "-mult")==0) wf_mult = 1; if (strcmp(argv[i], "-multgen")==0) wf_mult_gen = 1; if (strcmp(argv[i], "-wmax")==0) wf_max = 1; if (strcmp(argv[i], "-olap")==0) wf_olap = 1; if (strcmp(argv[i], "-meas")==0) meas = 1; // do_fft if (strcmp(argv[i], "-none")==0) unwrap = 0; if (strcmp(argv[i], "-norm")==0) unwrap = 1; if (strcmp(argv[i], "-rev")==0) unwrap = 2; if (strcmp(argv[i], "-qi")==0) rev_iq = 1; if (strcmp(argv[i], "-ineg")==0) ineg = 1; if (strcmp(argv[i], "-qneg")==0) qneg = 1; if (strcmp(argv[i], "-file")==0) fft_file = 1; if (strcmp(argv[i], "-fftsize")==0) { i++; fftsize = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-fftuse")==0) { i++; fftuse = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-np")==0) { i++; noisePwr = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-rcordic")==0) rx_cordic = 1; if (strcmp(argv[i], "-rcic")==0) rx_cic = 1; if (strcmp(argv[i], "-rcic2")==0) rx_cic2 = 1; if (strcmp(argv[i], "-rdump")==0) rx_dump = 1; if (strcmp(argv[i], "-wcordic")==0) wf_cordic = 1; if (strcmp(argv[i], "-wcic")==0) wf_cic = 1; if (strcmp(argv[i], "-clkg")==0) spi_clkg = 1; if (strcmp(argv[i], "-wspr")==0) { i++; wspr = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-avg")==0) { i++; navg = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-tone")==0) { i++; tone = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-slc")==0) { i++; do_slice = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-rx")==0) { i++; rx_num = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-wf")==0) { i++; wf_num = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-spispeed")==0) { i++; spi_speed = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-spi")==0) { i++; spi_delay = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-ch")==0) { i++; gps_chans = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-y")==0) { i++; rx_yield = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-p0")==0) { i++; p0 = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-p1")==0) { i++; p1 = strtol(argv[i], 0, 0); } if (strcmp(argv[i], "-p2")==0) { i++; p2 = strtol(argv[i], 0, 0); } i++; while (i<argc && ((argv[i][0] != '+') && (argv[i][0] != '-'))) { i++; } } lprintf("KiwiSDR v%d.%d\n", VERSION_MAJ, VERSION_MIN); lprintf("compiled: %s %s\n", __DATE__, __TIME__); cfg_reload(CALLED_FROM_MAIN); if (!alt_port) { FILE *fp = fopen("/root/.kiwi_down", "r"); if (fp != NULL) { fclose(fp); lprintf("down by lock file\n"); down = 1; } } TaskInit(); bool need_hardware = (do_gps || do_sdr) && !down; // called early, in case another server already running so we can detect the busy socket and bail web_server_init(WS_INIT_CREATE); if (need_hardware) { peri_init(); fpga_init(); //pru_start(); u2_t ctrl = CTRL_EEPROM_WP; ctrl_clr_set(0xffff, ctrl); if (do_off) { printf("ADC_CLOCK *OFF*\n"); xit(0); } #ifdef BUILD_PROTOTYPE if (!do_gps) // prevent interference to GPS by external ADC clock on prototype #endif { ctrl |= adc_clock_enable? CTRL_OSC_EN : CTRL_ADCLK_GEN; } ctrl_clr_set(0, ctrl); if (ctrl & (CTRL_OSC_EN | CTRL_ADCLK_GEN)) printf("ADC_CLOCK %.6f MHz, CTRL_OSC_EN=%d, CTRL_ADCLK_GEN=%d\n", adc_clock/MHz, (ctrl&CTRL_OSC_EN)?1:0, (ctrl&CTRL_ADCLK_GEN)?1:0); else printf("ADC_CLOCK *OFF*\n"); } if (do_fft) { printf("==== IQ %s\n", rev_iq? "reverse":"normal"); if (ineg) printf("==== I neg\n"); if (qneg) printf("==== Q neg\n"); printf("==== unwrap %s\n", (unwrap==0)? "none" : ((unwrap==1)? "normal":"reverse")); } rx_server_init(); web_server_init(WS_INIT_START); if (do_gps) { if (!GPS_CHANS) panic("no GPS_CHANS configured"); gps_main(argc, argv); } #if 0 static int tty; if (!background_mode) { tty = open("/dev/tty", O_RDONLY | O_NONBLOCK); if (tty < 0) sys_panic("open tty"); } #endif #if 0 static int tty; if (!background_mode) { tty = open("/dev/tty", O_RDONLY | O_NONBLOCK); if (tty < 0) sys_panic("open tty"); } #endif static u64_t stats_deadline = timer_us64() + 1000000; static u64_t secs; while (TRUE) { if (!need_hardware) { usleep(10000); // pause so we don't hog the machine NextTask("main usleep"); continue; } #if 0 if (!background_mode && (now - last_input) >= 1000) { #define N_IBUF 32 char ib[N_IBUF+1]; int n = read(tty, ib, N_IBUF); printf("tty %d\n", n); if (n >= 1) { ib[n] = 0; webserver_collect_print_stats(1); } last_input = now; } #endif if ((secs % STATS_INTERVAL_SECS) == 0) { if (do_sdr) { webserver_collect_print_stats(!do_gps); if (!do_gps) nbuf_stat(); } TaskCheckStacks(); } NextTask("main stats"); if (!do_gps && print_stats) { if (!background_mode) { lprintf("ECPU %4.1f%% cmds %d/%d malloc %d\n", ecpu_use(), ecpu_cmds, ecpu_tcmds, kiwi_malloc_stat()); ecpu_cmds = ecpu_tcmds = 0; TaskDump(); printf("\n"); } } u64_t now_us = timer_us64(); s64_t diff = stats_deadline - now_us; if (diff > 0) TaskSleep(diff); stats_deadline += 1000000; secs++; } }