This file is part of a program that implements a Software-Defined Radio.
-Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
+Copyright (C) 2004-5 by Frank Brickle, AB2KT and Bob McGwier, N4HY
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
// most of what little we know here about the inner loop,
// functionally speaking
+extern void reset_meters(void);
+extern void reset_spectrum(void);
+extern void reset_counters(void);
extern void process_samples(float *, float *, float *, float *, int);
extern void setup_workspace(void);
extern void destroy_workspace(void);
//========================================================================
-void
-clear_jack_ringbuffer(jack_ringbuffer_t *rb, int nbytes) {
- int i;
- char zero = 0;
- for (i = 0; i < nbytes; i++)
- jack_ringbuffer_write(rb, &zero, 1);
+PRIVATE void
+spectrum_thread(void) {
+
+ while (top.running) {
+ sem_wait(&top.sync.pws.sem);
+
+ compute_spectrum(&uni.spec);
+
+ if (fwrite((char *) &uni.spec.label, sizeof(int), 1, top.meas.spec.fp)
+ != 1) {
+ fprintf(stderr, "error writing spectrum label\n");
+ exit(1);
+ }
+
+ if (fwrite((char *) uni.spec.output, sizeof(float), uni.spec.size, top.meas.spec.fp)
+ != uni.spec.size) {
+ fprintf(stderr, "error writing spectrum\n");
+ exit(1);
+ }
+
+ fflush(top.meas.spec.fp);
+ }
+
+ pthread_exit(0);
+}
+
+PRIVATE void
+meter_thread(void) {
+
+ while (top.running) {
+ sem_wait(&top.sync.mtr.sem);
+
+ if (fwrite((char *) &uni.meter.label, sizeof(int), 1, top.meas.mtr.fp)
+ != 1) {
+ fprintf(stderr, "error writing meter label\n");
+ exit(1);
+ }
+
+ if (fwrite((char *) uni.meter.snap.rx, sizeof(REAL), MAXRX * RXMETERPTS, top.meas.mtr.fp)
+ != MAXRX * RXMETERPTS) {
+ fprintf(stderr, "error writing rx meter\n");
+ exit(1);
+ }
+
+ if (fwrite((char *) uni.meter.snap.tx, sizeof(REAL), TXMETERPTS, top.meas.mtr.fp)
+ != TXMETERPTS) {
+ fprintf(stderr, "error writing tx meter\n");
+ exit(1);
+ }
+
+ fflush(top.meas.mtr.fp);
+ }
+
+ pthread_exit(0);
}
//========================================================================
pthread_exit(0);
}
+//========================================================================
+
PRIVATE void
gethold(void) {
if (jack_ringbuffer_write_space(top.jack.ring.o.l)
>= top.hold.size.bytes;
}
+//------------------------------------------------------------------------
+
PRIVATE void
run_mute(void) {
memset((char *) top.hold.buf.l, 0, top.hold.size.bytes);
}
uni.mode.trx = top.swch.trx.next;
- // move this out of main! -----------------------------
- {
- int k;
- for (k = 0; k < uni.multirx.nrx; k++) rx[k].tick = 0;
- }
- tx.tick = 0;
- //-----------------------------------------------------
-
top.state = top.swch.run.last;
top.swch.bfct.want = top.swch.bfct.have = 0;
jack_ringbuffer_reset(top.jack.ring.o.l);
jack_ringbuffer_reset(top.jack.ring.o.r);
+
+ reset_meters();
+ reset_spectrum();
+ reset_counters();
}
process_samples(top.hold.buf.l, top.hold.buf.r,
//========================================================================
+void
+clear_jack_ringbuffer(jack_ringbuffer_t *rb, int nbytes) {
+ int i;
+ char zero = 0;
+ for (i = 0; i < nbytes; i++)
+ jack_ringbuffer_write(rb, &zero, 1);
+}
PRIVATE void
audio_callback(jack_nframes_t nframes, void *arg) {
sem_post(&top.sync.mon.sem);
}
+//========================================================================
+
PRIVATE void
process_samples_thread(void) {
while (top.running) {
pthread_join(top.thrd.trx.id, 0);
pthread_join(top.thrd.upd.id, 0);
pthread_join(top.thrd.mon.id, 0);
+ if (uni.meter.flag)
+ pthread_join(top.thrd.mtr.id, 0);
+ if (uni.spec.flag)
+ pthread_join(top.thrd.pws.id, 0);
// stop audio processing
jack_client_close(top.jack.client);
safefree((char *) top.hold.aux.r);
safefree((char *) top.hold.aux.l);
+ fclose(top.parm.fp);
+
+ if (uni.meter.flag)
+ fclose(top.meas.mtr.fp);
+ if (uni.spec.flag)
+ fclose(top.meas.spec.fp);
+
destroy_workspace();
exit(0);
fprintf(stderr, "flags:\n");
fprintf(stderr, " -v verbose commentary\n");
fprintf(stderr, " -m do metering\n");
+ fprintf(stderr, " -s do spectrum\n");
fprintf(stderr, " -l file execute update commands in file at startup\n");
- fprintf(stderr, " -P cmdpath path to command/update pipe\n");
- fprintf(stderr, " -S s-mtrpath path to S-meter output channel\n");
- fprintf(stderr, " -W wispath path to FFTW wisdom file\n");
- fprintf(stderr, " -R rate sampling rate\n");
- fprintf(stderr, " -B bufsize internal DSP buffer size\n");
- fprintf(stderr, " -M mode start up in mode (SAM, USB, LCW, etc.)\n");
- fprintf(stderr, " -G num use num as ringbuffer mult\n");
- fprintf(stderr, " -E num use num as meter chan mult\n");
fprintf(stderr, "'file' arg unused, but available\n");
exit(1);
}
fprintf(stderr, "can't fdopen parm pipe %s\n", loc.path.parm);
exit(1);
}
+
+ // do this here 'cuz the update thread is controlling the action
+ if (uni.meter.flag) {
+ top.meas.mtr.path = loc.path.meter;
+ top.meas.mtr.fp = efopen(top.meas.mtr.path, "r+");
+ }
+ if (uni.spec.flag) {
+ top.meas.spec.path = loc.path.spec;
+ top.meas.spec.fp = efopen(top.meas.spec.path, "r+");
+ }
}
PRIVATE void
pthread_create(&top.thrd.trx.id, NULL, (void *) process_samples_thread, NULL);
sem_init(&top.sync.mon.sem, 0, 0);
pthread_create(&top.thrd.mon.id, NULL, (void *) monitor_thread, NULL);
+ if (uni.meter.flag) {
+ sem_init(&top.sync.mtr.sem, 0, 0);
+ pthread_create(&top.thrd.mtr.id, NULL, (void *) meter_thread, NULL);
+ }
+ if (uni.spec.flag) {
+ sem_init(&top.sync.pws.sem, 0, 0);
+ pthread_create(&top.thrd.pws.id, NULL, (void *) spectrum_thread, NULL);
+ }
}
//========================================================================
strcpy(loc.path.rcfile, RCBASE);
strcpy(loc.path.parm, PARMPATH);
strcpy(loc.path.meter, METERPATH);
+ strcpy(loc.path.spec, SPECPATH);
strcpy(loc.path.wisdom, WISDOMPATH);
loc.def.rate = DEFRATE;
loc.def.size = DEFSIZE;
loc.def.mode = DEFMODE;
+ loc.def.spec = DEFSPEC;
loc.def.nrx = MAXRX;
loc.mult.ring = RINGMULT;
- loc.mult.meter = METERMULT;
{
char *ep;
if ((ep = getenv("SDR_RCBASE"))) strcpy(loc.path.rcfile, ep);
if ((ep = getenv("SDR_PARMPATH"))) strcpy(loc.path.parm, ep);
if ((ep = getenv("SDR_METERPATH"))) strcpy(loc.path.meter, ep);
+ if ((ep = getenv("SDR_SPECPATH"))) strcpy(loc.path.spec, ep);
if ((ep = getenv("SDR_WISDOMPATH"))) strcpy(loc.path.wisdom, ep);
if ((ep = getenv("SDR_RINGMULT"))) loc.mult.ring = atoi(ep);
- if ((ep = getenv("SDR_METERMULT"))) loc.mult.meter = atoi(ep);
if ((ep = getenv("SDR_DEFRATE"))) loc.def.rate = atof(ep);
if ((ep = getenv("SDR_DEFSIZE"))) loc.def.size = atoi(ep);
if ((ep = getenv("SDR_DEFMODE"))) loc.def.mode = atoi(ep);
case 'v':
top.verbose = TRUE;
break;
- case 'l':
- strcpy(loc.path.rcfile, argv[++i]);
- break;
case 'm':
uni.meter.flag = TRUE;
break;
- case 'P':
- strcpy(loc.path.parm, argv[++i]);
+ case 's':
+ uni.spec.flag = TRUE;
break;
- case 'S':
- strcpy(loc.path.meter, argv[++i]);
- break;
- case 'W':
- strcpy(loc.path.wisdom, argv[++i]);
- break;
- case 'R':
- loc.def.rate = atof(argv[++i]);
- break;
- case 'B':
- loc.def.size = atoi(argv[++i]);
- break;
- case 'M':
- loc.def.mode = atoi(argv[++i]);
- break;
- case 'G':
- loc.mult.ring = atoi(argv[++i]);
- break;
- case 'E':
- loc.mult.meter = atoi(argv[++i]);
+ case 'l':
+ strcpy(loc.path.rcfile, argv[++i]);
break;
default:
usage();