Beispiel #1
0
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;
}
Beispiel #2
0
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();
	}
}
Beispiel #3
0
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++;
	}
}