Exemple #1
0
void spin_ms(u4_t msec)
{
	u4_t tref = timer_ms(), diff;
	
	do {
		diff = time_diff(timer_ms(), tref);
	} while (diff < msec);
}
Exemple #2
0
void config_file_update()
{
	int i, group;
	static u4_t key_last_update;
	const scan_code *kp, *lp;
	key_last_t *kl;
	key_last_t key[N_GROUPS];

	for (i=1; i<N_GROUPS; i++) { key[i].key = 0; key[i].lp = 0; }

	for (i=0; i<N_KEYS; i++) {
		kp = &front_pnl_key[i];
		if (kp->group == 0) continue;
		assert(kp->group < N_GROUPS);
		lp = &front_pnl_led[i];
		
		if (LED_ON(lp)) {	// state of key LED determines whether we consider it "pushed" or not
			key[kp->group].key = KEY(i);
			key[kp->group].lp = lp;
		}
	}

	// check for state change of keys in a group
	for (i=1; i<N_GROUPS; i++) {
		kl = &key_last[i];

		if (kl->key != key[i].key) {
			kl->key = key[i].key;
			kl->lp = key[i].lp;
			key_need_update = TRUE;
		}
	}
	
	// only update file periodically
	if (key_need_update && (time_diff(timer_ms(), key_last_update) > 10000)) {
		FILE *fp;
		
		key_need_update = FALSE;
		key_last_update = timer_ms();

		sprintf(dbuf, "%s/.5370.%s.keys", ROOT_DIR, conf_profile);
		scallz("fopen", fp = fopen(dbuf, "w"));
		for (i=1; i<N_GROUPS; i++) {
			if (key_last[i].key) {
				//printf("store \"%s\": key 0x%02x %s\n", conf_profile, key_last[i].key, (key_last[i].lp)->name);
				fprintf(fp, "rcl key 0x%02x %s\n", key_last[i].key, (key_last[i].lp)->name);
			}
		}
		fclose(fp);
	}
}
Exemple #3
0
void handler_dev_arm_write(u2_t addr, u1_t data)
{

	assert (addr == WREG_LDACCW || addr == WREG_LDACSTART || addr == WREG_LDACSTOP ||
		addr == WREG_O2 || addr == WREG_O1 || addr == WREG_O3);

#ifdef DEBUG
	if (trace_regs) {
		if ((addr == WREG_O3) && isActive(O3_N3_OVRST, data)) printf("R3 "); else
		if ((addr == WREG_O3) && isActive(O3_N0_OVRST, data)) printf("R0 "); else
		printf("%s=%02x ", arm_wreg[addr - ADDR_ARM(0)], data);
	}
#endif

	// let PRU count N0/N3 overflows while measuring
	// FIXME: is this test valid for all measurement modes? O2_ARM_EN instead? TI +/- vs +only mode?
	if ((addr == WREG_O2) && isActive(O2_MAN_ARM, data)) {
		num_meas++;
		if (meas_time == 0) meas_time = timer_ms();

#ifdef DEBUG
		if (trace_regs) { printf("* "); fflush(stdout); }
#endif
		freq_record(0, REG_STR, 0, 0, 0, "* ");

		if (use_pru) {
			#if 0
			//assert(pru->count == PRU_DONE);
			if (pru->count != PRU_DONE) {
				printf("write O2_MAN_ARM: pru->count != PRU_DONE? [i.e. PRU never saw EOM]\n");
			}
			#endif
			
			bus_write(addr, data);	// let arm command go through
			n3_ovfl_sent = n0_ovfl_sent = ovfl_none = 0;

			send_pru_cmd(PRU_CLEAR);

			hold_off = TRUE;
			pru->count = PRU_COUNT;
			return;
		}
	}

	// ignore WREG_O3 writes to clear overflow bits while PRU is doing it
	if (use_pru && hold_off && (addr == WREG_O3)) {
		return;
	}

#ifdef FREQ_DEBUG
	if (use_pru && !hold_off) {
		if (addr == WREG_O3) {
			if (isActive(O3_N3_OVRST, data) || isActive(O3_N0_OVRST, data))
				freq_record(0, REG_READ, addr, data, 0, 0);
		}
	}
#endif

	bus_write(addr, data);
}
Exemple #4
0
int sender(int socket, FILE* fin, FILE* fout, int buf_size) {
	int ret = 0;
	char *buf;
	int fp, fs;
	int delta_t;

	buf = (char*)malloc(max(buf_size, 1024));
	if (buf == NULL) {
		printf("Error on malloc() !\n");
		return -1;
	}

	fp = ftell(fin);
	fseek(fin, 0, SEEK_END);
	fs = ftell(fin);
	fs -= fp;
	fseek(fin, fp, SEEK_SET);
	fread((void*)buf, fs, 1, fin);

	ret = sendl(socket, buf, fs, 0);
	if (ret<0) {
		printf("Error on sendl() !\n");
		free(buf);
		return -1;
	}
	printf("sent %d bytes\n", ret);

	printf("receiving...\n");
	printf("\n");
	delta_t = timer_ms();
	ret = recvw(socket, buf, buf_size, recvwcb, (void*)fout);
	if (ret<0) {
		printf("Error on recvw() !\n");
		free(buf);
		return -1;
	}
	delta_t = timer_ms() - delta_t;
	printf("\n");
	printf("received a total of %d bytes in %.3f seconds at %d KB/s\n", ret, (double)delta_t/1000.0, (int)floor((double)ret/(double)delta_t));


	free(buf);

	return ret;
}
Exemple #5
0
/*------------------------------------------------------------------------
*
* PROTOTYPE  :  int32_t FLZ_AVCheck(void *data)
*
* DESCRIPTION :
*
*/
int32_t FLZ_AVCheck(void *data)
{
    FLI_STRUCT *fli = (FLI_STRUCT*)data;
    uint32_t temps = timer_ms();
    if ( ((V3XA.State & 1)) || (temps>=(uint32_t)(FLZ_time+fli->Header.Struct.speed)) )
    {
		FLI_Unpack(fli);
		FLZ_time = temps;
		return !FLZ_SkipFrame;
    }
    return 0;
}
Exemple #6
0
void web_server(void *param)
{
	user_iface_t *ui = (user_iface_t *) param;
	struct mg_server *server = ui->server;
	const char *err;
	u4_t current_timer = 0, last_timer = timer_ms();
	
	while (1) {
		mg_poll_server(server, 0);		// passing 0 effects a poll
		current_timer = timer_ms();
		
		if (time_diff(current_timer, last_timer) > WEB_SERVER_POLL_MS) {
			last_timer = current_timer;
			mg_iterate_over_connections(server, iterate_callback);
		}
		
		NextTaskL("web server");
	}
	
	//mg_destroy_server(&server);
}
void TaskInit()
{
	static bool init;
    TASK *t;
	
	//printf("MAX_TASKS %d\n", MAX_TASKS);
	epoch = start_us = timer_us();
	start_ms = timer_ms();
	t = Tasks;
	cur_task = cur_low = t;
	prio_low = t;
	t->next = t->prev = NULL;
	task_init(t, 0, NULL, NULL, "main", LOW_PRIORITY);
}
Exemple #8
0
// mechanism to spread out recall key presses over time
static bool kdelay(delay)
{
	static u4_t key_delay, total_delay;

	key_delay = time_diff(timer_ms(), key_epoch);
	total_delay = delay + 100;
	
	if ((key_delay >= total_delay) && (total_delay > key_threshold)) {
		key_threshold = total_delay;
		return TRUE;
	}
	
	return FALSE;
}
Exemple #9
0
void layoutHome(void)
{
	if (layoutLast == layoutHome || layoutLast == layoutScreensaver) {
		oledClear();
	} else {
		layoutSwipe();
	}
	layoutLast = layoutHome;
	const char *label = storage_isInitialized() ? storage_getLabel() : _("Go to trezor.io/start");
	const uint8_t *homescreen = storage_getHomescreen();
	if (homescreen) {
		BITMAP b;
		b.width = 128;
		b.height = 64;
		b.data = homescreen;
		oledDrawBitmap(0, 0, &b);
	} else {
		if (label && strlen(label) > 0) {
			oledDrawBitmap(44, 4, &bmp_logo48);
			oledDrawStringCenter(OLED_HEIGHT - 8, label, FONT_STANDARD);
		} else {
			oledDrawBitmap(40, 0, &bmp_logo64);
		}
	}
	if (storage_noBackup()) {
		oledBox(0, 0, 127, 8, false);
		oledDrawStringCenter(0, "SEEDLESS", FONT_STANDARD);
	} else
	if (storage_unfinishedBackup()) {
		oledBox(0, 0, 127, 8, false);
		oledDrawStringCenter(0, "BACKUP FAILED!", FONT_STANDARD);
	} else
	if (storage_needsBackup()) {
		oledBox(0, 0, 127, 8, false);
		oledDrawStringCenter(0, "NEEDS BACKUP!", FONT_STANDARD);
	}
	oledRefresh();

	// Reset lock screen timeout
	system_millis_lock_start = timer_ms();
}
Exemple #10
0
u1_t handler_dev_display_read(u2_t addr)
{
	u1_t data;

	assert (addr == RREG_KEY_SCAN);

	// For reasons that are not understood, when the -O3 optimized version of the app are run in
	// auto-start mode the reset key push is not detected most of the time unless this delay is added.
	// Oddly, this bug doesn't appear if the optimized version is run from the command line, which makes no sense.
	// It doesn't appear to be code getting optimized away or a missing volatile declaration but rather timing related.
#ifndef DEBUG
	delay(1);
#endif

	data = bus_read(addr);

	if (data != KEY_IDLE) {
		process_key(data);
	} else

	if (sim_key) {
		data = sim_key;
		
		// simulate reset key down for an extended period
		if (reset_key_down) {
			if ((time_diff(timer_ms(), reset_key_down) > 1250)) reset_key_down = 0;
		} else {
			if (sim_running) {
				if (!sim_key_intr) sim_key = 0;		// allow it to be read twice, but generate interrupt only once
			} else {
				sim_key = 0;	// only once for non-simulator uses
			}
		}
		
		sim_key_intr = 0;
		process_key(data);
	}

	return data;
}
Exemple #11
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();
	}
}
Exemple #12
0
bool change_settings_ui(menu_e *menu, u1_t key, bool *skip_first, cfg_t *cfg)
{
	int i;
	bool save_cfg = FALSE;
	s1_t ki;

	// scroll the menu list forward
	if (key == KEY(TI)) {
		if (*skip_first) {
			*skip_first = FALSE;
		} else {
			*menu = *menu+1;
			if (*menu == M_LAST) *menu = 0;
		}
menu_up_down:
		dsp_7seg_str(DSP_LEFT, menu_str[*menu], DSP_CLEAR);
		if (((*menu == M_IP) || (*menu == M_NM) || (*menu == M_GW))) {
			display_ipaddr(cfg->if_ipinfo[*menu-M_IP]);
		}
		wait_key_release();
	} else

	// scroll the menu list backward
	if (key == KEY(FREQ)) {
		if (*skip_first) {
			*skip_first = FALSE;
		} else {
			if (*menu == 0) *menu = M_LAST;
			*menu = *menu-1;
		}
		goto menu_up_down;
	}
	
	// inc/dec a byte of the ip/nm/gw address
	// hold key down for auto-repeat
	ki = 0;

	for (i=0; settings_keys[i].key; i++) {
		if (key == KEY(settings_keys[i].key)) {
			ki = settings_keys[i].key_idx;
			break;
		}
	}
	
	if (ki) {
		bool first_time = TRUE;
		u4_t td, tref = timer_ms(), tcmp = 256, tinc = 32;
		do {
			td = time_diff(timer_ms(), tref);
			if (((*menu == M_IP) || (*menu == M_NM) || (*menu == M_GW)) && (first_time || (td >= tcmp))) {
				if (ki > 0) {
					cfg->if_ipinfo[*menu-M_IP][ki-1]++;
				} else {
					cfg->if_ipinfo[*menu-M_IP][-ki-1]--;
				}
				display_ipaddr(cfg->if_ipinfo[*menu-M_IP]);
				first_time = FALSE;
				tcmp += tinc;
			}
		} while (key_down());
		save_cfg = TRUE;	// change has been made
	}
	
	return save_cfg;
}
Exemple #13
0
// return zero if command processed locally
char *sim_input()
{
	int i, n=0, k, key;
	char *cp = ibuf;
	char key_name[16];
	
	if (!boot_time) boot_time = timer_ms();
	
	// check for 5370 power loss (we may still be running via USB power)
	if (!(bus_read(RREG_LDACSR) & DSR_VOK)) {
		lprintf("5370 power loss\n");
		usleep(1000000);
		while (!(bus_read(RREG_LDACSR) & DSR_VOK)) {
			sched_yield();
			usleep(250000);
		}
		lprintf("5370 power on\n");
		usleep(1000000);
		sys_reset = TRUE;
		return 0;
	}

	// can't recall any keys until self-test is finished
	if (self_test && boot_time && (time_diff(timer_ms(), boot_time) > SELF_TEST_DELAY)) {
		self_test = FALSE;
	}
	
	if (!self_test && !need_recall_file && !recall_active) {
		config_file_update();
	}
	
	if (!self_test && need_recall_file) {
		sprintf(dbuf, "%s/.5370.%s.keys", ROOT_DIR, conf_profile);
		if ((kfp = fopen(dbuf, "r")) != NULL) {
			key_epoch = timer_ms(); key_threshold = rcl_key = 0;
			recall_active = TRUE;
		} else {
			printf("no key profile named \"%s\", will create one\n", conf_profile);
		}
		need_recall_file = FALSE;
	}
	
	if (recall_active && kfp && !self_test && kdelay(rcl_key * 256)) {
		if (fgets(dbuf, N_DBUF, kfp)) {
			if (sscanf(dbuf, "rcl key 0x%02x %16s", &key, key_name) == 2) {
				cp = "k-\n"; n=3;	// virtual command to get key press thru code below
				rcl_key++;
			}
		} else {
			fclose(kfp);
			kfp = 0;
			recall_active = FALSE;
		}
	}

#ifdef DEBUG
 #ifdef HPIB_SIM
	if (bug_stdev) {
		if (kdelay(0)) hpib_input("tr\n", 0);
		if (kdelay(500)) hpib_input("ta+0.05\n", 0);
		if (kdelay(1000)) find_bug();
	}
 #endif

	if (bug_freq) {
		if (kdelay(0)) { cp = "k fn3\n"; n=6; }
		if (kdelay(500) && gate1) { cp = "k gt1\n"; n=6; }
		if (kdelay(500) && gate2) { cp = "k gt2\n"; n=6; }
		if (kdelay(500) && gate3) { cp = "k gt3\n"; n=6; }
		if (kdelay(500) && gate4) { cp = "k gt4\n"; n=6; }
		//if (kdelay(1000)) { cp = "t\n"; n=2; }
		//if (kdelay(1500)) { cp = "z\n"; n=2; }
	}
#endif

#ifdef HPIB_SIM
 	// handle HPIB data over the network
 	char *nb;
 	i = net_poll(NET_HPIB, &nb);
	if (i) {
		if (strncmp(nb, "GET ", 4) == 0) {
			nb = dbuf;
			sprintf(nb, "attempted web connection on port %d, you want port %s instead\n",
				HPIB_TCP_PORT, WEBSERVER_PORT);
			printf("%s", nb);
			// nothing we tried could get message to show up in browser, unlike below
			//net_send(NET_HPIB, nb, strlen(nb), NO_COPY(TRUE), FLUSH(TRUE));
			net_disconnect(NET_HPIB);
		} else {
			hpib_input(nb, i);
		}
	}
#endif

 	// handle keyboard commands over the network
	if (!n) {
		n = net_poll(NET_TELNET, &cp);
		if (n) {
			cp[n] = 0;
			if (strncmp(cp, "GET ", 4) == 0) {
				// this message will show up in browser due to net_send(NET_TELNET, ...) in lprintf()
				lprintf("attempted web connection on port %d, you want port %s instead\n",
					TELNET_TCP_PORT, WEBSERVER_PORT);
				net_disconnect(NET_TELNET);
				n = 0;
			}
		}
	}

	if (!n) {
		n = webserver_to_app(cp, N_IBUF-2);	// N_IBUF-2: leave room for \n\0
		
		if (n) {
			cp[n] = 0;
			if (cp[n-1] != '\n') {
				strcat(cp, "\n");	// make sure there is a trailing \n
				n++;
			}
		}
	}

	if (!n) {
		if (background_mode)
			return 0;
		n = read(tty, cp, N_IBUF);
		if (n >= 1) cp[n] = 0;
	}

	if (n >= 1) {

		if ((n == 1) || (*cp == '?') || (strcmp(cp, "help\n") == 0) || ((*cp == 'h') && (n == 2))) {
			printf("commands:\n"
				"d\t\tshow instrument display including unit and key LEDs\n"
				"h <HPIB cmd>\temulate HPIB command input, e.g. \"h md2\"\n"
				"h?\t\tprints reminder list of HPIB commands\n"
				"k <fn1 .. fn4>\temulate function key 1-4 press, e.g. \"k fn1\" is TI key\n"
				"k <gt1 .. gt4>\temulate gate time key 1-4 press\n"
				"k <st1 .. st8>\temulate statistics key 1-8 press\n"
				"k <ss1 .. ss5>\temulate sample size key 1-5 press\n"
				"k <m1 .. m6>\temulate \"misc\" key 1-6 press\n"
				"\t\t1 TI only, 2 +/- TI, 3 ext h.off, 4 per compl, 5 ext arm, 6 man rate\n"
				"m\t\trun measurement extension example code\n"
				"s\t\tshow measurement statistics\n"
				"rc\t\tshow values of count-chain registers (one sample)\n"
				"rcl|recall [name]   load key settings from current or named profile\n"
				"sto|store name      save key settings to named profile\n"
				"r\t\treset instrument\n"
				"q\t\tquit\n"
				"\n");
			return 0;
		}
		
		if ((*cp == 'r') && (n == 2)) {
			dsp_7seg_str(DSP_LEFT, "reset", DSP_CLEAR);
			sys_reset = TRUE;
			return 0;
		}

		if (*cp == 'q') {
			printf("quit\n");
			delay(1000);	// let webserver show message
			exit(0);
		}
		
		// process command starting with '-' as args
		if (*cp == '-') {
			#define NARGS 16
			int argc; char *argv[NARGS];
			
			argc = 1 + split(cp, &argc, &argv[1], NARGS);
			sim_args(FALSE, argc, argv);
			hpib_args(FALSE, argc, argv);
			return 0;
		}
		
		if (*cp == 'm') {
			meas_extend_example(0);
			return 0;
		}
		
		// show what's on the 7 segment display, units display and key LEDs
		if (*cp == 'd') {
			dsp_7seg_translate(dbuf, 0);
			printf("display: %s\n", dbuf);
			dsp_key_leds_translate(dbuf);		// which keys have their LEDs lit
			printf("keys: %s\n", dbuf);
			return 0;
		}

		// emulate a key press by causing an interrupt and returning the correct
		// scan code for the subsequent read of the RREG_KEY_SCAN register
		if (*cp == 'k') {
			k = 0;
			
			if (*(cp+1) == '-') {					// key press from recall above
				k = -1;
			} else
			if (sscanf(cp, "k fn%d", &n) == 1) {	// function keys 1..4
				if (n >= 1 && n <= 4)
					k = skey_func[n-1];
			} else
			if (sscanf(cp, "k gt%d", &n) == 1) {	// gate time keys 1..4
				if (n >= 1 && n <= 4)
					k = skey_gate[n-1];
			} else
			if (sscanf(cp, "k st%d", &n) == 1) {	// statistics keys 1..8
				if (n >= 1 && n <= 8)
					k = skey_stat[n-1];
			} else
			if (sscanf(cp, "k ss%d", &n) == 1) {	// sample size keys 1..5
				if (n >= 1 && n <= 5)
					k = skey_samp[n-1];
			} else
			if (sscanf(cp, "k m%d", &n) == 1) {		// misc keys 1..6
				if (n >= 1 && n <= 6)
					k = skey_misc[n-1];
			} else

#if defined(DEBUG) || defined(NET_PRINTF)
			// for remote debugging of menu mode
			if (strcmp(cp, "k r\n") == 0) {
				k = RESET;
			} else
			if (strcmp(cp, "k rd\n") == 0) {
				k = RESET;
				reset_key_down = timer_ms();
			} else
			if (strcmp(cp, "k d\n") == 0) {
				k = TI;
			} else
			if (strcmp(cp, "k u\n") == 0) {
				k = FREQ;
			} else
#endif
			;
			
			if (k > 0) {
				sim_key = KEY(k);
				sim_key_intr = 1;
				printf("key press: %s (%d 0x%02x)\n", front_pnl_led[k].name, n, sim_key);
			} else
			if (k == -1) {
				sim_key = key;
				sim_key_intr = 1;
				printf("recall: key 0x%02x %s\n", key, key_name);
			} else {
				cp[strlen(cp)-1] = 0;
				printf("bad key command: \"%s\"\n", cp);
			}
			
			num_meas = 0;
			return 0;
		}
		
		if (strcmp(cp, "rcl\n")==0 || strcmp(cp, "recall\n")==0) {
			printf("recall key settings from current profile \"%s\"\n", conf_profile);
			need_recall_file = TRUE;
			return 0;
		}

		if (sscanf(cp, "rcl %16s", conf_profile)==1 || sscanf(cp, "recall %16s", conf_profile)==1) {
			printf("recall key settings from profile \"%s\"\n", conf_profile);
			need_recall_file = TRUE;
			return 0;
		}
		
		if (strcmp(cp, "sto\n")==0 || strcmp(cp, "store\n")==0) {
			printf("usage: sto|store name\n");
			return 0;
		}

		if (sscanf(cp, "store %16s", conf_profile)==1 || sscanf(cp, "sto %16s", conf_profile)==1) {
			printf("store key settings to profile \"%s\"\n", conf_profile);
			return 0;
		}

		// measure number of measurements-per-second
		if (*cp == 's' && n==2) {
			if (num_meas) {
				printf("%.1f meas/s\n", (float)num_meas / ((float)(timer_ms()-meas_time)/1000.0));
				num_meas = meas_time = 0;
			}

			return 0;
		}

#ifdef DEBUG
		if (*cp == 'r' && cp[1] == 'c' && n==3) {
			dump_regs = BIT_AREG(N0ST) | BIT_AREG(N1N2H) | BIT_AREG(N1N2L) | BIT_AREG(N0H) | BIT_AREG(N0L);
			return 0;
		}

		if (*cp == 'z') {
			//trace_regs ^= 1;
			//trace_iDump(1);
			hps ^= 1;
			return 0;
		}
#endif

#ifdef HPIB_SIM
		// emulate input of an HPIB command
		// e.g. "h md2" "h mr" "h md1" "h tb1" "h tb0"
		if (*cp == 'h' && cp[1] == ' ') {
			hpib_input(cp+2, 0);	// presumes that hpib input is processed before another sim input
			num_meas = 0;
			return 0;
		}
#endif

		if (*cp == 'h' && cp[1] == '?') {
			printf("HPIB command reminder list: (shown uppercase but may be typed as lowercase)\n"
			"function: FN1 TI, FN2 trig lvl, FN3 freq, FN4 period\n"
			"gate: GT1 single period, GT2 0.01s, GT3 0.1s, GT4 1s\n"
			"statistics: ST1 mean, ST2 std dev, ST3 min, ST4 max, ST5 dsp ref, ST6 clr ref, ST7 dsp evts, ST8 set ref, ST9 dsp all\n"
			"sample sizes: SS1 1, SS2 100, SS3 1k, SS4 10k, SS5 100k, SB <4 bytes> (set size for binary xfer)\n"
			"mode: MD1 front pnl, MD2 hold until \"MR\" cmd, MD3 fast (only if addressed), MD4 fast (wait until addressed)\n"
			"input: IN1 start+stop, IN2 stop only, IN3 start only, IN4 start+stop swap\n"
			"slope: SA1 start+, SA2 start-, S01 stop+, S02 stop-, SL slope local, SR slope remote\n"
			"arm select: AR1 +TI only, AR2 +/-TI\n"
			"ext arming: EA0 dis, EA1 ena, SE1 slope+, SE2 slope-, EH0 hold-off dis, EH1 hold-off ena\n"
			"int arming: IA1 auto, IA2 start ch arm, IA3 stop ch arm\n"
			"trigger: TL trig local, TR trig remote, TA <volts> start lvl, TO <volts> stop lvl\n"
			"binary mode: TB0 disable, TB1 enable, TB2 fast-mode enable (virtual cmd)\n"
			"other: MR man rate, MI man input, PC period compl, TE teach (store), LN learn (recall)\n"
			"\n");
			return 0;
		}

		return cp;	// pass to caller
	} else {
		return 0;
	}
}
Exemple #14
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;
}
 void _NextTaskL()
#endif
{
	int i;
    TASK *t, *tn;
    u4_t now, quanta;

	t = cur_task;

    // don't switch until quanta expired (if any)
    if (t->quanta && ((timer_ms() - start_ms) < t->quanta))
    	return;
    
    ev(EV_NEXTTASK, "NextTask", "");
    
    now = timer_us();
    quanta = now - start_us;
    t->usec += quanta;
	
    if (slice) {
    	TSLICE *ts = &slices[slice-1];
    	ts->id = t->id;
    	ts->usec = quanta;
    	ts->wakeup = rx0_wakeup;
    	ts->twoke = now - rx0_twoke;
    	
    	#ifdef DEBUG
    		ts->s = s;
    	#endif
    	
    	slice++;
    	
    	if (slice == NSLICES) {
    		u4_t maxv=0; int maxi=0;
    		for (i=0; i<NSLICES; i++) {
    			ts = &slices[i];
    			if (ts->usec > maxv) { maxv = ts->usec; maxi = i; }
    		}
    		for (i=0; i<NSLICES; i++) {
    			ts = &slices[i];
    			printf("%4d T%02d %7.3f %7.3f w%d %s %s %s %s\n",
    				i, ts->id, ((float) ts->usec) / 1e3, ((float) ts->twoke) / 1e3,
    				ts->wakeup, Tasks[ts->id].name,
    				ts->s? ts->s : "", ts->msg,
    				(i==maxi)? "############################################": (
    				(ts->usec>=2000.0)? "------------------------------------------":"") );
    		}
    		xit(0);
    		slice = 0;
    	}
    }
    
    if (setjmp(t->jb)) {
    	return;
    }
    
	//printf("P%d-%s %.3f ms pc %p\n", t->id, t->name, ((float) quanta) / 1e3, (void *) t->pc); fflush(stdout);
    
    for (i=0; i<MAX_TASKS; i++) {
    	TASK *tp = Tasks + i;
    	if (tp->valid && tp->deadline && (tp->deadline < now)) {
    		tp->deadline = 0;
    		tp->stopped = FALSE;
    		tp->wakeup = TRUE;
//printf("wake T%02d\n", tp->id);
    	}
    }
    
    if (t->priority == HIGH_PRIORITY) {
		do {	// after a high priority finishes run next high priority
			t = t->next;
		} while (t && t->stopped);
		
    	if (!t) {	// no other high priority, so run next low priority
    		t = cur_low;
    		do {
    			t = t->next;
    			if (!t) t = prio_low;
    		} while (t->stopped);
    	}
    } else {
    	// run _all_ high priority after each low priority finishes
		for (t = prio_high; t && t->stopped; t = t->next)
			;
    	if (!t) {	// no high priority so run next low priority
    		t = cur_task;
    		do {
    			t = t->next;
    			if (!t) t = prio_low;
    		} while (t->stopped);
    	}
    }

    cur_task = t;
    if (t->priority == LOW_PRIORITY) cur_low = t;
    t->run++;

	//printf("N%d-%s pc %p\n", t->id, t->name, (void *) t->pc); fflush(stdout);
	start_us = now;
	if (t->quanta) start_ms = timer_ms();
    longjmp(t->jb, 1);
}
Exemple #16
0
void w2a_admin(void *param)
{
	int n, i, j;
	conn_t *conn = (conn_t *) param;
	static char json_buf[16384];
	u4_t ka_time = timer_sec();
	
	// send initial values
	send_msg(conn, SM_NO_DEBUG, "ADM init=%d", RX_CHANS);
	
	nbuf_t *nb = NULL;
	while (TRUE) {
	
		if (nb) web_to_app_done(conn, nb);
		n = web_to_app(conn, &nb);
				
		if (n) {
			char *cmd = nb->buf;
			cmd[n] = 0;		// okay to do this -- see nbuf.c:nbuf_allocq()

			ka_time = timer_sec();

			if (rx_common_cmd("W/F", conn, cmd))
				continue;
			
			//printf("ADMIN: %d <%s>\n", strlen(cmd), cmd);

			i = strcmp(cmd, "SET init");
			if (i == 0) {
				continue;
			}

			i = strcmp(cmd, "SET gps_update");
			if (i == 0) {
				gps_stats_t::gps_chan_t *c;
				
				char *cp = json_buf;
				n = sprintf(cp, "{ \"FFTch\":%d, \"ch\":[ ", gps.FFTch); cp += n;
				
				for (i=0; i < gps_chans; i++) {
					c = &gps.ch[i];
					int un = c->ca_unlocked;
					n = sprintf(cp, "%s{ \"ch\":%d, \"prn\":%d, \"snr\":%d, \"rssi\":%d, \"gain\":%d, \"hold\":%d, \"wdog\":%d"
						", \"unlock\":%d, \"parity\":%d, \"sub\":%d, \"sub_renew\":%d, \"novfl\":%d }",
						i? ", ":"", i, c->prn, c->snr, c->rssi, c->gain, c->hold, c->wdog,
						un, c->parity, c->sub, c->sub_renew, c->novfl); cp += n;
					c->parity = 0;
					for (j = 0; j < SUBFRAMES; j++) {
						if (c->sub_renew & (1<<j)) {
							c->sub |= 1<<j;
							c->sub_renew &= ~(1<<j);
						}
					}
				}

				n = sprintf(cp, " ]"); cp += n;

				UMS hms(gps.StatSec/60/60);
				
				unsigned r = (timer_ms() - gps.start)/1000;
				if (r >= 3600) {
					n = sprintf(cp, ", \"run\":\"%d:%02d:%02d\"", r / 3600, (r / 60) % 60, r % 60); cp += n;
				} else {
					n = sprintf(cp, ", \"run\":\"%d:%02d\"", (r / 60) % 60, r % 60); cp += n;
				}

				if (gps.ttff) {
					n = sprintf(cp, ", \"ttff\":\"%d:%02d\"", gps.ttff / 60, gps.ttff % 60); cp += n;
				} else {
					n = sprintf(cp, ", \"ttff\":null"); cp += n;
				}

				if (gps.StatDay != -1) {
					n = sprintf(cp, ", \"gpstime\":\"%s %02d:%02d:%02.0f\"", Week[gps.StatDay], hms.u, hms.m, hms.s); cp += n;
				} else {
					n = sprintf(cp, ", \"gpstime\":null"); cp += n;
				}

				if (gps.StatLat) {
					n = sprintf(cp, ", \"lat\":\"%8.6f %c\"", gps.StatLat, gps.StatNS); cp += n;
					n = sprintf(cp, ", \"lon\":\"%8.6f %c\"", gps.StatLon, gps.StatEW); cp += n;
					n = sprintf(cp, ", \"alt\":\"%1.0f m\"", gps.StatAlt); cp += n;
					n = sprintf(cp, ", \"map\":\"<a href='http://wikimapia.org/#lang=en&lat=%8.6f&lon=%8.6f&z=18&m=b' target='_blank'>wikimapia.org</a>\"",
						gps.sgnLat, gps.sgnLon); cp += n;
				} else {
					n = sprintf(cp, ", \"lat\":null"); cp += n;
				}
					
				n = sprintf(cp, ", \"acq\":%d, \"track\":%d, \"good\":%d, \"fixes\":%d, \"adc_clk\":%.6f, \"adc_corr\":%d",
					gps.acquiring? 1:0, gps.tracking, gps.good, gps.fixes, (adc_clock - adc_clock_offset)/1e6, gps.adc_clk_corr); cp += n;

				n = sprintf(cp, " }"); cp += n;
				send_encoded_msg_mc(conn->mc, "ADM", "gps_update", "%s", json_buf);

				continue;
			}

			i = strcmp(cmd, "SET sdr_hu_update");
			if (i == 0) {
				gps_stats_t::gps_chan_t *c;
				
				char *cp = json_buf;
				n = sprintf(cp, "{ "); cp += n;
				if (gps.StatLat) {
					n = sprintf(cp, "\"lat\":\"%8.6f\", \"lon\":\"%8.6f\"",
						gps.sgnLat, gps.sgnLon); cp += n;
				}
				n = sprintf(cp, " }"); cp += n;
				send_encoded_msg_mc(conn->mc, "ADM", "sdr_hu_update", "%s", json_buf);

				continue;
			}

			int force_check;
			i = sscanf(cmd, "SET force_check=%d force_build=%d", &force_check, &force_build);
			if (i == 2) {
				check_for_update(force_check);
				continue;
			}

			i = strcmp(cmd, "SET reload_index_params");
			if (i == 0) {
				reload_index_params();
				continue;
			}

			i = strcmp(cmd, "SET extint_load_extension_configs");
			if (i == 0) {
				extint_load_extension_configs(conn);
				continue;
			}

			i = strcmp(cmd, "SET restart");
			if (i == 0) {
				lprintf("ADMIN: restart requested by admin..\n");
				exit(0);
			}

			i = strcmp(cmd, "SET reboot");
			if (i == 0) {
				lprintf("ADMIN: reboot requested by admin..\n");
				system("reboot");
				while (true)
					usleep(100000);
			}

			i = strcmp(cmd, "SET power_off");
			if (i == 0) {
				lprintf("ADMIN: power off requested by admin..\n");
				system("poweroff");
				while (true)
					usleep(100000);
			}

			printf("ADMIN: unknown command: <%s>\n", cmd);
			continue;
		}
		
		conn->keep_alive = timer_sec() - ka_time;
		bool keepalive_expired = (conn->keep_alive > KEEPALIVE_SEC);
		if (keepalive_expired) {
			printf("ADMIN KEEP-ALIVE EXPIRED\n");
			rx_server_remove(conn);
			return;
		}

		TaskSleep(250000);
	}
}
Exemple #17
0
int main(int argn, char ** argv) {
    if(argn < 4) {
        usage("Wrong argument count", *argv);
    }
    
    // read width and height
    const int w = atoi(argv[1]);
    const int h = atoi(argv[2]);
    if(w < 1 || h < 1) {
        usage("Both width and height must be positive integers", *argv);
    }
    const int pix_count = w * h;
    
    // read sigma and prepare normalized kernel (sum = 1)
    const float sigma = atof(argv[3]);
    float kernel[MAX_KERNEL_RADIUS + 1];
    float kernel_sum = 0.0f;
    for(int k = 0; k <= MAX_KERNEL_RADIUS; k++) {
        kernel_sum += kernel[k] = gaussian(sigma, k);
    }
    kernel_sum = 2.0 * kernel_sum - kernel[0];
    for(int k = 0; k <= MAX_KERNEL_RADIUS; k++) {
        kernel[k] /= kernel_sum;
    }
    
    // dump the kernel
    printf("Convolution kernel:");
    for(int k = -MAX_KERNEL_RADIUS; k <= MAX_KERNEL_RADIUS; k++) {
        printf(" %f", kernel[k < 0 ? -k : k]);
    }
    printf("\n");
    
    // prepare buffers
    uint8_t * const data_ptr = (uint8_t*)malloc(pix_count);
    uint8_t * const temp_ptr = (uint8_t*)malloc(pix_count);
    
    // measure time of processing of all images
    const double begin = timer_ms();
    for(int i = 4; i < argn; i++) {
        // read input data
        printf("Processing '%s'\n", argv[i]);
        FILE * const src_file = fopen(argv[i], "rb");
        if(NULL == src_file || 1 != fread(data_ptr, pix_count, 1, src_file)) {
            error(argv[i]);
        }
        fclose(src_file);
        
        // vertical pass: for each pixel
        uint8_t * out_pix_ptr = temp_ptr;
        for(int y = 0; y < h; y++) {
            for(int x = 0; x < w; x++) {
                // sum up all weighted neighbors and the pixel itself
                float result = kernel[0] * get_pix(data_ptr, w, h, x, y);
                for(int k = 1; k <= MAX_KERNEL_RADIUS; k++) {
                    result += kernel[k] * (get_pix(data_ptr, w, h, x, y + k)
                                         + get_pix(data_ptr, w, h, x, y - k));
                }
                *(out_pix_ptr++) = saturate((int)result, 256);
            }
        }
        
        // horizontal pass: for each pixel
        out_pix_ptr = data_ptr;
        for(int y = 0; y < h; y++) {
            for(int x = 0; x < w; x++) {
                // sum up all weighted neighbors and the pixel itself
                float result = kernel[0] * get_pix(temp_ptr, w, h, x, y);
                for(int k = 1; k <= MAX_KERNEL_RADIUS; k++) {
                    result += kernel[k] * (get_pix(temp_ptr, w, h, x + k, y)
                                         + get_pix(temp_ptr, w, h, x - k, y));
                }
                *(out_pix_ptr++) = saturate((int)result, 256);
            }
        }
        
        // compose output filename
        char out_path[MAX_PATH_LEN + 1];
        snprintf(out_path, MAX_PATH_LEN, "%s.out.gray", argv[i]);
        
        // write data to output file
        FILE * const out_file = fopen(out_path, "wb");
        if(NULL == out_file || 1 != fwrite(data_ptr, pix_count, 1, out_file)) {
            error(out_path);
        }
        fclose(out_file);
    }
    const double end = timer_ms();
    
    // print total time
    printf("time: %f ms, %d images => %f ms/image\n",
           end - begin, argn - 4, (end - begin) / (argn - 4));
    
    // cleanup
    free(temp_ptr);
    free(data_ptr);
    return 0;
}