--- /dev/null
+UNAME_N := $(shell uname -n)
+
+CC=gcc
+LINK=gcc
+OPTIONS=-g -D $(UNAME_N)
+GTKINCLUDES=`pkg-config --cflags gtk+-3.0`
+GTKLIBS=`pkg-config --libs gtk+-3.0`
+LIBS=-lwiringPi -lpigpio -lrt -lm -lwdsp -lpthread $(GTKLIBS)
+INCLUDES=$(GTKINCLUDES)
+
+COMPILE=$(CC) $(OPTIONS) $(INCLUDES)
+
+PROGRAM=pihpsdr
+
+
+SOURCES= \
+band.c \
+filter.c \
+main.c \
+meter.c \
+mode.c \
+new_discovery.c \
+new_protocol.c \
+new_protocol_programmer.c \
+panadapter.c \
+property.c \
+radio.c \
+rotary_encoder.c \
+splash.c \
+toolbar.c \
+vfo.c \
+waterfall.c
+
+HEADERS= \
+agc.h \
+alex.h \
+band.h \
+bandstack.h \
+channel.h \
+discovered.h \
+filter.h \
+meter.h \
+mode.h \
+new_discovery.h \
+new_protocol.h \
+panadapter.h \
+property.h \
+radio.h \
+rotary_encoder.h \
+splash.h \
+toolbar.h \
+vfo.h \
+waterfall.h \
+xvtr.h
+
+OBJS= \
+band.o \
+filter.o \
+main.o \
+meter.o \
+mode.o \
+new_discovery.o \
+new_protocol.o \
+new_protocol_programmer.o \
+panadapter.o \
+property.o \
+radio.o \
+rotary_encoder.o \
+splash.o \
+toolbar.o \
+vfo.o \
+waterfall.o
+
+all: $(PROGRAM) $(HEADERS) $(SOURCES)
+
+$(PROGRAM): $(OBJS)
+ $(LINK) -o $(PROGRAM) $(OBJS) $(LIBS)
+
+.c.o:
+ $(COMPILE) $(OPTIONS) -c -o $@ $<
+
+
+clean:
+ -rm -f *.o
+ -rm -f $(PROGRAM)
+
--- /dev/null
+#define AGC_OFF 0
+#define AGC_LONG 1
+#define AGC_SLOW 2
+#define AGC_MEDIUM 3
+#define AGC_FAST 4
+
--- /dev/null
+#define ALEX_RX_ANTENNA_NONE 0x00000000
+#define ALEX_RX_ANTENNA_XVTR 0x00000900
+#define ALEX_RX_ANTENNA_EXT1 0x00000A00
+#define ALEX_RX_ANTENNA_EXT2 0x00000C00
+#define ALEX_RX_ANTENNA_BYPASS 0x00000800
+
+#define ALEX_TX_ANTENNA_1 0x01000000
+#define ALEX_TX_ANTENNA_2 0x02000000
+#define ALEX_TX_ANTENNA_3 0x04000000
+
+#define ALEX_ATTENUATION_0dB 0x00000000
+#define ALEX_ATTENUATION_10dB 0x00004000
+#define ALEX_ATTENUATION_20dB 0x00002000
+#define ALEX_ATTENUATION_30dB 0x00006000
+
+#define ALEX_30_20_LPF 0x00100000
+#define ALEX_60_40_LPF 0x00200000
+#define ALEX_80_LPF 0x00400000
+#define ALEX_160_LPF 0x00800000
+#define ALEX_6_BYPASS_LPF 0x20000000
+#define ALEX_12_10_LPF 0x40000000
+#define ALEX_17_15_LPF 0x80000000
+
+#define ALEX_13MHZ_HPF 0x00000002
+#define ALEX_20MHZ_HPF 0x00000004
+#define ALEX_9_5MHZ_HPF 0x00000010
+#define ALEX_6_5MHZ_HPF 0x00000020
+#define ALEX_1_5MHZ_HPF 0x00000040
+#define ALEX_BYPASS_HPF 0x00000800
+
+#define ALEX_6M_PREAMP 0x00000008
--- /dev/null
+#include <stdio.h>
+
+#include "bandstack.h"
+#include "band.h"
+#include "filter.h"
+#include "mode.h"
+#include "xvtr.h"
+#include "alex.h"
+#include "property.h"
+
+int band=band20;
+int xvtr_band=band160;
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief bandstack
+*/
+/* ----------------------------------------------------------------------------*/
+BANDSTACK_ENTRY bandstack_entries160[] =
+ {{1810000LL,modeCWL,filterF4,-2800,-200,-2800,-200},
+ {1835000LL,modeCWU,filterF0,-2800,-200,-2800,-200},
+ {1845000LL,modeUSB,filterF5,-2800,-200,-2800,-200}};
+
+BANDSTACK_ENTRY bandstack_entries80[] =
+ {{3501000LL,modeCWL,filterF0,-2800,-200,-2800,-200},
+ {3751000LL,modeLSB,filterF5,-2800,-200,-2800,-200},
+ {3850000LL,modeLSB,filterF5,-2800,-200,-2800,-200}};
+
+BANDSTACK_ENTRY bandstack_entries60[] =
+ {{5330500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+ {5346500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+ {5366500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+ {5371500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+ {5403500LL,modeUSB,filterF5,-2800,-200,-2800,-200}};
+
+BANDSTACK_ENTRY bandstack_entries40[] =
+ {{7001000LL,modeCWL,filterF0,-2800,-200,-2800,-200},
+ {7152000LL,modeLSB,filterF5,-2800,-200,-2800,-200},
+ {7255000LL,modeLSB,filterF5,-2800,-200,-2800,-200}};
+
+BANDSTACK_ENTRY bandstack_entries30[] =
+ {{10120000LL,modeCWU,filterF0,200,2800,200,2800},
+ {10130000LL,modeCWU,filterF0,200,2800,200,2800},
+ {10140000LL,modeCWU,filterF4,200,2800,200,2800}};
+
+BANDSTACK_ENTRY bandstack_entries20[] =
+ {{14010000LL,modeCWU,filterF0,200,2800,200,2800},
+ {14230000LL,modeUSB,filterF5,200,2800,200,2800},
+ {14336000LL,modeUSB,filterF5,200,2800,200,2800}};
+
+BANDSTACK_ENTRY bandstack_entries18[] =
+ {{18068600LL,modeCWU,filterF0,200,2800,200,2800},
+ {18125000LL,modeUSB,filterF5,200,2800,200,2800},
+ {18140000LL,modeUSB,filterF5,200,2800,200,2800}};
+
+BANDSTACK_ENTRY bandstack_entries15[] =
+ {{21001000LL,modeCWU,filterF0,200,2800,200,2800},
+ {21255000LL,modeUSB,filterF5,200,2800,200,2800},
+ {21300000LL,modeUSB,filterF5,200,2800,200,2800}};
+
+BANDSTACK_ENTRY bandstack_entries12[] =
+ {{24895000LL,modeCWU,filterF0,200,2800,200,2800},
+ {24900000LL,modeUSB,filterF5,200,2800,200,2800},
+ {24910000LL,modeUSB,filterF5,200,2800,200,2800}};
+
+BANDSTACK_ENTRY bandstack_entries10[] =
+ {{28010000LL,modeCWU,filterF0,200,2800,200,2800},
+ {28300000LL,modeUSB,filterF5,200,2800,200,2800},
+ {28400000LL,modeUSB,filterF5,200,2800,200,2800}};
+
+BANDSTACK_ENTRY bandstack_entries50[] =
+ {{50010000LL,modeCWU,filterF0,200,2800,200,2800},
+ {50125000LL,modeUSB,filterF5,200,2800,200,2800},
+ {50200000LL,modeUSB,filterF5,200,2800,200,2800}};
+
+BANDSTACK_ENTRY bandstack_entriesGEN[] =
+ {{909000LL,modeAM,filterF6,-6000,6000,-6000,60000},
+ {5975000LL,modeAM,filterF6,-6000,6000,-6000,60000},
+ {13845000LL,modeAM,filterF6,-6000,6000,-6000,60000}};
+
+BANDSTACK_ENTRY bandstack_entriesWWV[] =
+ {{2500000LL,modeSAM,filterF6,200,2800,200,2800},
+ {5000000LL,modeSAM,filterF6,200,2800,200,2800},
+ {10000000LL,modeSAM,filterF6,200,2800,200,2800},
+ {15000000LL,modeSAM,filterF6,200,2800,200,2800},
+ {20000000LL,modeSAM,filterF6,200,2800,200,2800}};
+
+BANDSTACK bandstack160={3,1,bandstack_entries160};
+BANDSTACK bandstack80={3,1,bandstack_entries80};
+BANDSTACK bandstack60={5,1,bandstack_entries60};
+BANDSTACK bandstack40={3,1,bandstack_entries40};
+BANDSTACK bandstack30={3,1,bandstack_entries30};
+BANDSTACK bandstack20={3,1,bandstack_entries20};
+BANDSTACK bandstack18={3,1,bandstack_entries18};
+BANDSTACK bandstack15={3,1,bandstack_entries15};
+BANDSTACK bandstack12={3,1,bandstack_entries12};
+BANDSTACK bandstack10={3,1,bandstack_entries10};
+BANDSTACK bandstack50={3,1,bandstack_entries50};
+BANDSTACK bandstackGEN={3,1,bandstack_entriesGEN};
+BANDSTACK bandstackWWV={5,1,bandstack_entriesWWV};
+
+BAND bands[BANDS] =
+ {{"160",&bandstack160,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"80",&bandstack80,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"60",&bandstack60,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"40",&bandstack40,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"30",&bandstack30,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"20",&bandstack20,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"18",&bandstack18,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"15",&bandstack15,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"12",&bandstack12,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"10",&bandstack10,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"50",&bandstack50,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"GEN",&bandstackGEN,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
+ {"WWV",&bandstackWWV,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB}};
+
+#define NUM_BAND_LIMITS 22
+
+BAND_LIMITS bandLimits[NUM_BAND_LIMITS] = {
+ {1800000LL,2000000LL},
+ {3500000LL,4000000LL},
+ {5330500LL,5403500LL},
+ {7000000LL,7300000LL},
+ {10100000LL,10150000LL},
+ {14000000LL,14350000LL},
+ {18068000LL,18168000LL},
+ {21000000LL,21450000LL},
+ {24890000LL,24990000LL},
+ {28000000LL,29700000LL},
+ {50000000LL,54000000LL},
+ {144000000LL,148000000LL},
+ {222000000LL,224980000LL},
+ {420000000LL,450000000LL},
+ {902000000LL,928000000LL},
+ {1240000000LL,1300000000LL},
+ {2300000000LL,2450000000LL},
+ {3456000000LL,3456400000LL},
+ {5760000000LL,5760400000LL},
+ {10368000000LL,10368400000LL},
+ {24192000000LL,24192400000LL},
+ {47088000000LL,47088400000LL}
+};
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief xvtr
+*/
+/* ----------------------------------------------------------------------------*/
+static XVTR_ENTRY xvtr[12]=
+ {{"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0},
+ {"",0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0,modeUSB,filterF5,-2800,-200,-2800,-200,0,0,0,0}};
+
+
+BANDSTACK_ENTRY *bandstack_entry_get_current() {
+ BANDSTACK *bandstack=bands[band].bandstack;
+ BANDSTACK_ENTRY *entry=&bandstack->entry[bandstack->current_entry];
+ return entry;
+}
+
+BANDSTACK_ENTRY *bandstack_entry_next() {
+ BANDSTACK *bandstack=bands[band].bandstack;
+ bandstack->current_entry++;
+ if(bandstack->current_entry==bandstack->entries) {
+ bandstack->current_entry=0;
+ }
+ BANDSTACK_ENTRY *entry=&bandstack->entry[bandstack->current_entry];
+ return entry;
+}
+
+int band_get_current() {
+ return band;
+}
+
+BAND *band_get_current_band() {
+ BAND *b=&bands[band];
+ return b;
+}
+
+BAND *band_get_band(int b) {
+ BAND *band=&bands[b];
+ return band;
+}
+
+BAND *band_set_current(int b) {
+ band=b;
+ return &bands[b];
+}
+
+
+void bandSaveState() {
+ char name[128];
+ char value[128];
+ int current;
+ BANDSTACK_ENTRY* entry;
+
+ int b;
+ int stack;
+ for(b=0;b<BANDS;b++) {
+ sprintf(value,"%d",bands[b].bandstack->entries);
+ sprintf(name,"band.%d.entries",b);
+ setProperty(name,value);
+
+ sprintf(value,"%d",bands[b].bandstack->current_entry);
+ sprintf(name,"band.%d.current",b);
+ setProperty(name,value);
+
+ sprintf(value,"%d",bands[b].preamp);
+ sprintf(name,"band.%d.preamp",b);
+ setProperty(name,value);
+
+ sprintf(value,"%ld",bands[b].alexRxAntenna);
+ sprintf(name,"band.%d.alexRxAntenna",b);
+ setProperty(name,value);
+
+ sprintf(value,"%ld",bands[b].alexTxAntenna);
+ sprintf(name,"band.%d.alexTxAntenna",b);
+ setProperty(name,value);
+
+ sprintf(value,"%ld",bands[b].alexAttenuation);
+ sprintf(name,"band.%d.alexAttenuation",b);
+ setProperty(name,value);
+
+ for(stack=0;stack<bands[b].bandstack->entries;stack++) {
+ entry=bands[b].bandstack->entry;
+ entry+=stack;
+
+ sprintf(value,"%lld",entry->frequencyA);
+ sprintf(name,"band.%d.stack.%d.a",b,stack);
+ setProperty(name,value);
+
+ sprintf(value,"%d",entry->mode);
+ sprintf(name,"band.%d.stack.%d.mode",b,stack);
+ setProperty(name,value);
+
+ sprintf(value,"%d",entry->filter);
+ sprintf(name,"band.%d.stack.%d.filter",b,stack);
+ setProperty(name,value);
+
+ sprintf(value,"%d",entry->var1Low);
+ sprintf(name,"band.%d.stack.%d.var1Low",b,stack);
+ setProperty(name,value);
+
+ sprintf(value,"%d",entry->var1High);
+ sprintf(name,"band.%d.stack.%d.var1High",b,stack);
+ setProperty(name,value);
+
+ sprintf(value,"%d",entry->var2Low);
+ sprintf(name,"band.%d.stack.%d.var2Low",b,stack);
+ setProperty(name,value);
+
+ sprintf(value,"%d",entry->var2High);
+ sprintf(name,"band.%d.stack.%d.var2High",b,stack);
+ setProperty(name,value);
+
+ }
+ }
+
+ sprintf(value,"%d",band);
+ setProperty("band",value);
+}
+
+void bandRestoreState() {
+ char* value;
+
+ int b;
+ int stack;
+ char name[128];
+ BANDSTACK_ENTRY* entry;
+ int current;
+
+
+ for(b=0;b<BANDS;b++) {
+ sprintf(name,"band.%d.entries",b);
+ value=getProperty(name);
+ if(value) bands[b].bandstack->entries=atoi(value);
+
+ sprintf(name,"band.%d.current",b);
+ value=getProperty(name);
+ if(value) bands[b].bandstack->current_entry=atoi(value);
+
+ sprintf(name,"band.%d.preamp",b);
+ value=getProperty(name);
+ if(value) bands[b].preamp=atoi(value);
+
+ sprintf(name,"band.%d.alexRxAntenna",b);
+ value=getProperty(name);
+ if(value) bands[b].alexRxAntenna=atoi(value);
+
+ sprintf(name,"band.%d.alexTxAntenna",b);
+ value=getProperty(name);
+ if(value) bands[b].alexTxAntenna=atoi(value);
+
+ sprintf(name,"band.%d.alexAttenuation",b);
+ value=getProperty(name);
+ if(value) bands[b].alexAttenuation=atoi(value);
+ for(stack=0;stack<bands[b].bandstack->entries;stack++) {
+ entry=bands[b].bandstack->entry;
+ entry+=stack;
+
+ sprintf(name,"band.%d.stack.%d.a",b,stack);
+ value=getProperty(name);
+ if(value) entry->frequencyA=atoll(value);
+
+ sprintf(name,"band.%d.stack.%d.mode",b,stack);
+ value=getProperty(name);
+ if(value) entry->mode=atoi(value);
+
+ sprintf(name,"band.%d.stack.%d.filter",b,stack);
+ value=getProperty(name);
+ if(value) entry->filter=atoi(value);
+
+ sprintf(name,"band.%d.stack.%d.var1Low",b,stack);
+ value=getProperty(name);
+ if(value) entry->var1Low=atoi(value);
+
+ sprintf(name,"band.%d.stack.%d.var1High",b,stack);
+ value=getProperty(name);
+ if(value) entry->var1High=atoi(value);
+
+ sprintf(name,"band.%d.stack.%d.var2Low",b,stack);
+ value=getProperty(name);
+ if(value) entry->var2Low=atoi(value);
+
+ sprintf(name,"band.%d.stack.%d.var2High",b,stack);
+ value=getProperty(name);
+ if(value) entry->var2High=atoi(value);
+
+ }
+ }
+ value=getProperty("band");
+ if(value) band=atoi(value);
+}
+
+
--- /dev/null
+/**
+* @file band.h
+* @brief Header files for the Amateur Radio band stack.
+* @author John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* @version 0.1
+* @date 2009-04-11
+*/
+// band.h
+
+/* Copyright (C)
+* 2009 - John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* 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 the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include "bandstack.h"
+
+#define band160 0
+#define band80 1
+#define band60 2
+#define band40 3
+#define band30 4
+#define band20 5
+#define band17 6
+#define band15 7
+#define band12 8
+#define band10 9
+#define band6 10
+#define bandGen 11
+#define bandWWV 12
+
+#define BANDS 13
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief Bandlimit definition
+*/
+struct _BAND_LIMITS {
+ long long minFrequency;
+ long long maxFrequency;
+};
+
+typedef struct _BAND_LIMITS BAND_LIMITS;
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief Band definition
+*/
+struct _BAND {
+ char title[16];
+ BANDSTACK *bandstack;
+ unsigned char OCrx;
+ unsigned char OCtx;
+ int preamp;
+ unsigned long alexRxAntenna;
+ unsigned long alexTxAntenna;
+ unsigned long alexAttenuation;
+};
+
+typedef struct _BAND BAND;
+
+int band;
+int xvtr_band;
+gboolean displayHF;
+
+int band_get_current();
+BAND *band_get_current_band();
+BAND *band_get_band(int b);
+BAND *band_set_current(int b);
+
+BANDSTACK_ENTRY *bandstack_entry_next();
+BANDSTACK_ENTRY *bandstack_entry_get_current();
+
+/*
+void bandSaveState();
+void bandRestoreState();
+void forceBand(int band,int setup);
+void configureXVTRButton(int setup);
+GtkWidget* buildBandUI();
+
+int remoteSetBand(gpointer *data);
+
+BAND_LIMITS* getBandLimits(long long minDisplay,long long maxDisplay);
+XVTR_ENTRY* getXvtrEntry(int i);
+
+*/
+
--- /dev/null
+/**
+* @file bandstack.h
+* @brief Bandstack definition files
+* @author John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* @version 0.1
+* @date 2009-04-11
+*/
+// bandstack.h
+
+/* Copyright (C)
+* This program is free software; you can redistribute it and/or2009 - John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+*/
+
+#ifndef BANDSTACK_H
+#define BANDSTACK_H
+/* --------------------------------------------------------------------------*/
+/**
+* @brief Bandstack definition
+*/
+struct _BANDSTACK_ENTRY {
+ long long frequencyA;
+ int mode;
+ int filter;
+ int var1Low;
+ int var1High;
+ int var2Low;
+ int var2High;
+};
+
+typedef struct _BANDSTACK_ENTRY BANDSTACK_ENTRY;
+
+struct _BANDSTACK {
+ int entries;
+ int current_entry;
+ BANDSTACK_ENTRY *entry;
+};
+
+typedef struct _BANDSTACK BANDSTACK;
+
+#endif
+
--- /dev/null
+#define CHANNEL_RX0 0
+#define CHANNEL_RX1 1
+#define CHANNEL_RX2 2
+#define CHANNEL_RX3 3
+#define CHANNEL_RX4 4
+#define CHANNEL_RX5 5
+#define CHANNEL_RX6 6
+#define CHANNEL_RX7 7
+#define CHANNEL_TX 8
+#define CHANNEL_BS 9
+#define CHANNEL_SUBRX 10
+
--- /dev/null
+#include <netinet/in.h>
+
+#define MAX_DEVICES 16
+
+#define DEVICE_METIS 0
+#define DEVICE_HERMES 1
+#define DEVICE_GRIFFIN 2
+#define DEVICE_ANGELIA 4
+#define DEVICE_ORION 5
+#define DEVICE_HERMES_LITE 6
+
+#define NEW_DEVICE_ATLAS 0
+#define NEW_DEVICE_HERMES 1
+#define NEW_DEVICE_HERMES2 2
+#define NEW_DEVICE_ANGELIA 3
+#define NEW_DEVICE_ORION 4
+#define NEW_DEVICE_ANAN_10E 5
+#define NEW_DEVICE_HERMES_LITE 6
+
+#define STATE_AVAILABLE 2
+#define STATE_SENDING 3
+
+#define ORIGINAL_PROTOCOL 0
+#define NEW_PROTOCOL 1
+
+struct _DISCOVERED {
+ int protocol;
+ int device;
+ char name[16];
+ int software_version;
+ unsigned char mac_address[6];
+ int status;
+ int address_length;
+ struct sockaddr_in address;
+ int interface_length;
+ struct sockaddr_in interface_address;
+ char interface_name[64];
+};
+
+typedef struct _DISCOVERED DISCOVERED;
+
+extern int selected_device;
+extern int devices;
+extern DISCOVERED discovered[MAX_DEVICES];
+
--- /dev/null
+#include "filter.h"
+
+FILTER filterLSB[FILTERS]={
+ {-5150,-150,"5.0k"},
+ {-4550,-150,"4.4k"},
+ {-3950,-150,"3.8k"},
+ {-3450,-150,"3.3k"},
+ {-3050,-150,"2.9k"},
+ {-2850,-150,"2.7k"},
+ {-2550,-150,"2.4k"},
+ {-2250,-150,"2.1k"},
+ {-1950,-150,"1.8k"},
+ {-1150,-150,"1.0k"}/*,
+ {-2850,-150,"Var1"},
+ {-2850,-150,"Var2"}*/
+ };
+
+FILTER filterDIGL[FILTERS]={
+ {-5150,-150,"5.0k"},
+ {-4550,-150,"4.4k"},
+ {-3950,-150,"3.8k"},
+ {-3450,-150,"3.3k"},
+ {-3050,-150,"2.9k"},
+ {-2850,-150,"2.7k"},
+ {-2550,-150,"2.4k"},
+ {-2250,-150,"2.1k"},
+ {-1950,-150,"1.8k"},
+ {-1150,-150,"1.0k"}/*,
+ {-2850,-150,"Var1"},
+ {-2850,-150,"Var2"}*/
+ };
+
+FILTER filterUSB[FILTERS]={
+ {150,5150,"5.0k"},
+ {150,4550,"4.4k"},
+ {150,3950,"3.8k"},
+ {150,3450,"3.3k"},
+ {150,3050,"2.9k"},
+ {150,2850,"2.7k"},
+ {150,2550,"2.4k"},
+ {150,2250,"2.1k"},
+ {150,1950,"1.8k"},
+ {150,1150,"1.0k"}/*,
+ {150,2850,"Var1"},
+ {150,2850,"Var2"}*/
+ };
+
+FILTER filterDIGU[FILTERS]={
+ {150,5150,"5.0k"},
+ {150,4550,"4.4k"},
+ {150,3950,"3.8k"},
+ {150,3450,"3.3k"},
+ {150,3050,"2.9k"},
+ {150,2850,"2.7k"},
+ {150,2550,"2.4k"},
+ {150,2250,"2.1k"},
+ {150,1950,"1.8k"},
+ {150,1150,"1.0k"}/*,
+ {150,2850,"Var1"},
+ {150,2850,"Var2"}*/
+ };
+
+FILTER filterCWL[FILTERS]={
+ {500,500,"1.0k"},
+ {400,400,"800"},
+ {375,375,"750"},
+ {300,300,"600"},
+ {250,250,"500"},
+ {200,200,"400"},
+ {125,125,"250"},
+ {50,50,"100"},
+ {25,25,"50"},
+ {13,13,"25"}/*,
+ {250,250,"Var1"},
+ {250,250,"Var2"}*/
+ };
+
+FILTER filterCWU[FILTERS]={
+ {500,500,"1.0k"},
+ {400,400,"800"},
+ {375,375,"750"},
+ {300,300,"600"},
+ {250,250,"500"},
+ {200,200,"400"},
+ {125,125,"250"},
+ {50,50,"100"},
+ {25,25,"50"},
+ {13,13,"25"}/*,
+ {250,250,"Var1"},
+ {250,250,"Var2"}*/
+ };
+
+FILTER filterAM[FILTERS]={
+ {-8000,8000,"16k"},
+ {-6000,6000,"12k"},
+ {-5000,5000,"10k"},
+ {-4000,4000,"8k"},
+ {-3300,3300,"6.6k"},
+ {-2600,2600,"5.2k"},
+ {-2000,2000,"4.0k"},
+ {-1550,1550,"3.1k"},
+ {-1450,1450,"2.9k"},
+ {-1200,1200,"2.4k"}/*,
+ {-3300,3300,"Var1"},
+ {-3300,3300,"Var2"}*/
+ };
+
+FILTER filterSAM[FILTERS]={
+ {-8000,8000,"16k"},
+ {-6000,6000,"12k"},
+ {-5000,5000,"10k"},
+ {-4000,4000,"8k"},
+ {-3300,3300,"6.6k"},
+ {-2600,2600,"5.2k"},
+ {-2000,2000,"4.0k"},
+ {-1550,1550,"3.1k"},
+ {-1450,1450,"2.9k"},
+ {-1200,1200,"2.4k"}/*,
+ {-3300,3300,"Var1"},
+ {-3300,3300,"Var2"}*/
+ };
+
+FILTER filterFMN[FILTERS]={
+ {-8000,8000,"16k"},
+ {-6000,6000,"12k"},
+ {-5000,5000,"10k"},
+ {-4000,4000,"8k"},
+ {-3300,3300,"6.6k"},
+ {-2600,2600,"5.2k"},
+ {-2000,2000,"4.0k"},
+ {-1550,1550,"3.1k"},
+ {-1450,1450,"2.9k"},
+ {-1200,1200,"2.4k"}/*,
+ {-3300,3300,"Var1"},
+ {-3300,3300,"Var2"}*/
+ };
+
+FILTER filterDSB[FILTERS]={
+ {-8000,8000,"16k"},
+ {-6000,6000,"12k"},
+ {-5000,5000,"10k"},
+ {-4000,4000,"8k"},
+ {-3300,3300,"6.6k"},
+ {-2600,2600,"5.2k"},
+ {-2000,2000,"4.0k"},
+ {-1550,1550,"3.1k"},
+ {-1450,1450,"2.9k"},
+ {-1200,1200,"2.4k"}/*,
+ {-3300,3300,"Var1"},
+ {-3300,3300,"Var2"}*/
+ };
+
+FILTER filterSPEC[FILTERS]={
+ {-8000,8000,"16k"},
+ {-6000,6000,"12k"},
+ {-5000,5000,"10k"},
+ {-4000,4000,"8k"},
+ {-3300,3300,"6.6k"},
+ {-2600,2600,"5.2k"},
+ {-2000,2000,"4.0k"},
+ {-1550,1550,"3.1k"},
+ {-1450,1450,"2.9k"},
+ {-1200,1200,"2.4k"}/*,
+ {-3300,3300,"Var1"},
+ {-3300,3300,"Var2"}*/
+ };
+
+FILTER filterDRM[FILTERS]={
+ {-8000,8000,"16k"},
+ {-6000,6000,"12k"},
+ {-5000,5000,"10k"},
+ {-4000,4000,"8k"},
+ {-3300,3300,"6.6k"},
+ {-2600,2600,"5.2k"},
+ {-2000,2000,"4.0k"},
+ {-1550,1550,"3.1k"},
+ {-1450,1450,"2.9k"},
+ {-1200,1200,"2.4k"}/*,
+ {-3300,3300,"Var1"},
+ {-3300,3300,"Var2"}*/
+ };
+
+FILTER *filters[]={filterLSB,filterUSB,filterDSB,filterCWL,filterCWU,filterFMN,filterAM,filterDIGU,filterSPEC,filterDIGL,filterSAM,filterDRM};
+
--- /dev/null
+/**
+* @file filter.h
+* @brief Header files to define the filters.
+* @author John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* @version 0.1
+* @date 2009-04-11
+*/
+// filter.h
+/* Copyright (C)
+* 2009 - John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* 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 the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+*/
+
+#include "mode.h"
+
+// disable Var1 and Var2 (change to 12 to enable)
+#define FILTERS 10
+
+#define CW_PITCH 600
+
+struct _FILTER {
+ int low;
+ int high;
+ char* title;
+};
+
+typedef struct _FILTER FILTER;
+
+#define filterF0 0
+#define filterF1 1
+#define filterF2 2
+#define filterF3 3
+#define filterF4 4
+#define filterF5 5
+#define filterF6 6
+#define filterF7 7
+#define filterF8 8
+#define filterF9 9
+#define filterVar1 10
+#define filterVar2 11
+
+int filter;
+
+int filterLow;
+int filterHigh;
+
+int txFilterLowCut;
+int txFilterHighCut;
+
+int filterVar1Low;
+int filterVar1High;
+int filterVar2Low;
+int filterVar2High;
+
+
+FILTER *filters[MODES];
+
+/*
+int updateFilter(void * data);
+GtkWidget* buildFilterUI();
+void filterSaveState();
+void filterRestoreState();
+void setFilterValues(int mode);
+void setFilter(int filter);
+void setTxFilters();
+*/
--- /dev/null
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <semaphore.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "main.h"
+#include "channel.h"
+#include "discovered.h"
+#include "new_discovery.h"
+#include "new_protocol.h"
+#include "wdsp.h"
+#include "vfo.h"
+#include "meter.h"
+#include "panadapter.h"
+#include "splash.h"
+#include "waterfall.h"
+#include "toolbar.h"
+#include "radio.h"
+
+#define VFO_HEIGHT (display_height/8)
+#define VFO_WIDTH ((display_width/4)*3)
+#define METER_HEIGHT (display_height/8)
+#define METER_WIDTH (display_width/4)
+#define PANADAPTER_HEIGHT (display_height/4)
+#define TOOLBAR_HEIGHT (display_height/4)
+#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+TOOLBAR_HEIGHT))
+
+struct utsname unameData;
+
+gint display_width;
+gint display_height;
+
+static gint update_timer_id;
+static gint updates_per_second=10;
+
+static gint save_timer_id;
+
+static float *samples;
+
+static int start=0;
+
+static GtkWidget *discovery_dialog;
+
+gint update(gpointer data) {
+ int result;
+ GetPixels(isTransmitting()==0?CHANNEL_RX0:CHANNEL_TX,samples,&result);
+ if(result==1) {
+ panadapter_update(samples,isTransmitting());
+ if(!isTransmitting()) {
+ waterfall_update(samples);
+ }
+ }
+
+ if(!isTransmitting()) {
+ float m=GetRXAMeter(CHANNEL_RX0, 1/*WDSP.S_AV*/);
+ meter_update(SMETER,(double)m,0.0);
+ } else {
+
+ DISCOVERED *d=&discovered[selected_device];
+
+ double constant1=5.0;
+ double constant2=0.108;
+
+ switch(d->device) {
+ case NEW_DEVICE_ATLAS:
+ constant1=3.3;
+ constant2=0.09;
+ break;
+ case NEW_DEVICE_HERMES:
+ constant1=3.3;
+ constant2=0.09;
+ break;
+ case NEW_DEVICE_HERMES2:
+ constant1=3.3;
+ constant2=0.095;
+ break;
+ case NEW_DEVICE_ANGELIA:
+ constant1=3.3;
+ constant2=0.095;
+ break;
+ case NEW_DEVICE_ORION:
+ constant1=5.0;
+ constant2=0.108;
+ break;
+ case NEW_DEVICE_ANAN_10E:
+ constant1=3.3;
+ constant2=0.09;
+ break;
+ case NEW_DEVICE_HERMES_LITE:
+ constant1=3.3;
+ constant2=0.09;
+ break;
+ }
+
+ int power=alex_forward_power;
+ if(power==0) {
+ power=exciter_power;
+ }
+ double v1;
+ double fwd;
+ double rev;
+ v1=((double)power/4095.0)*constant1;
+ fwd=(v1*v1)/constant2;
+
+ rev=0.0;
+ if(alex_forward_power!=0) {
+ power=alex_reverse_power;
+ v1=((double)power/4095.0)*constant1;
+ rev=(v1*v1)/constant2;
+ }
+ meter_update(POWER,fwd,rev);
+ }
+
+ return TRUE;
+}
+
+static gint save_cb(gpointer data) {
+ radioSaveState();
+ saveProperties(property_path);
+ return TRUE;
+}
+
+static void start_cb(GtkWidget *widget, gpointer data) {
+fprintf(stderr,"start_cb\n");
+ selected_device=(int)data;
+ start=1;
+ gtk_widget_destroy(discovery_dialog);
+}
+
+static void configure_cb(GtkWidget *widget, gpointer data) {
+}
+
+
+gint init(void* arg) {
+
+ GtkWidget *window;
+ GtkWidget *grid;
+ GtkWidget *vfo;
+ GtkWidget *meter;
+ GtkWidget *panadapter;
+ GtkWidget *waterfall;
+ GtkWidget *toolbar;
+
+ DISCOVERED* d;
+
+ char wisdom_directory[1024];
+ char wisdom_file[1024];
+
+ fprintf(stderr,"init\n");
+
+ // check if wisdom file exists
+ getcwd(wisdom_directory, sizeof(wisdom_directory));
+ strcpy(&wisdom_directory[strlen(wisdom_directory)],"/");
+ strcpy(wisdom_file,wisdom_directory);
+ strcpy(&wisdom_file[strlen(wisdom_file)],"wdspWisdom");
+ if(access(wisdom_file,F_OK)<0) {
+ WDSPwisdom (wisdom_directory);
+ }
+
+ while(!start) {
+ new_discovery();
+ if(devices==0) {
+ fprintf(stderr,"No devices found!\n");
+ GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT;
+ discovery_dialog = gtk_message_dialog_new (GTK_WINDOW(splash_window),
+ flags,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK_CANCEL,
+ "No devices found! Retry Discovery?");
+ gint result=gtk_dialog_run (GTK_DIALOG (discovery_dialog));
+ if(result==GTK_RESPONSE_CANCEL) {
+ _exit(0);
+ }
+ } else if(devices==1) {
+ selected_device=0;
+ start=1;
+ } else {
+ fprintf(stderr,"%s: found %d devices.\n", (char *)arg, devices);
+ GtkDialogFlags flags=GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
+ discovery_dialog = gtk_dialog_new_with_buttons ("Discovered",
+ GTK_WINDOW(splash_window),
+ flags,
+ "Discover",
+ GTK_RESPONSE_REJECT,
+ NULL);
+
+ GtkWidget *content;
+
+// g_signal_connect_swapped(discovery_dialog,"response",G_CALLBACK(gtk_widget_destroy),discovery_dialog);
+
+ content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog));
+
+ GtkWidget *grid=gtk_grid_new();
+ gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+ gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+
+ int i;
+ char text[128];
+ for(i=0;i<devices;i++) {
+ d=&discovered[i];
+ sprintf(text,"%s %s (%02X:%02X:%02X:%02X:%02X:%02X) on interface %s\n",
+ d->name,
+ inet_ntoa(d->address.sin_addr),
+ d->mac_address[0],
+ d->mac_address[1],
+ d->mac_address[2],
+ d->mac_address[3],
+ d->mac_address[4],
+ d->mac_address[5],
+ d->interface_name);
+
+ GtkWidget *label=gtk_label_new(text);
+ gtk_widget_show(label);
+ gtk_grid_attach(GTK_GRID(grid),label,0,i,3,1);
+
+ GtkWidget *start_button=gtk_button_new_with_label("Start");
+ gtk_widget_show(start_button);
+ gtk_grid_attach(GTK_GRID(grid),start_button,3,i,1,1);
+ g_signal_connect(start_button,"pressed",G_CALLBACK(start_cb),(gpointer *)i);
+
+ GtkWidget *configure_button=gtk_button_new_with_label("Configure");
+ gtk_widget_show(configure_button);
+ gtk_grid_attach(GTK_GRID(grid),configure_button,4,i,1,1);
+ g_signal_connect(configure_button,"pressed",G_CALLBACK(configure_cb),(gpointer *)i);
+ }
+
+ gtk_container_add (GTK_CONTAINER (content), grid);
+ gtk_widget_show_all(discovery_dialog);
+ gint result=gtk_dialog_run(GTK_DIALOG(discovery_dialog));
+ }
+ }
+
+ d=&discovered[selected_device];
+ sprintf(property_path,"%02X-%02X-%02X-%02X-%02X-%02X.props",
+ d->mac_address[0],
+ d->mac_address[1],
+ d->mac_address[2],
+ d->mac_address[3],
+ d->mac_address[4],
+ d->mac_address[5]);
+
+ loadProperties(property_path);
+ radioRestoreState();
+
+ samples=malloc(display_width*sizeof(float));
+
+ //selected_device=0;
+ setSampleRate(48000);
+ new_protocol_init(0,display_width);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), "pihpsdr");
+
+ //g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (window), 0);
+
+ grid = gtk_grid_new();
+ gtk_container_add(GTK_CONTAINER(window), grid);
+
+ vfo = vfo_init(VFO_WIDTH,VFO_HEIGHT,window);
+ gtk_grid_attach(GTK_GRID(grid), vfo, 0, 0, 3, 1);
+
+ meter = meter_init(METER_WIDTH,METER_HEIGHT);
+ gtk_grid_attach(GTK_GRID(grid), meter, 3, 0, 1, 1);
+
+ panadapter = panadapter_init(display_width,PANADAPTER_HEIGHT);
+ gtk_grid_attach(GTK_GRID(grid), panadapter, 0, 1, 4, 1);
+
+ waterfall = waterfall_init(display_width,WATERFALL_HEIGHT);
+ gtk_grid_attach(GTK_GRID(grid), waterfall, 0, 2, 4, 1);
+
+ toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,window);
+ gtk_grid_attach(GTK_GRID(grid), toolbar, 0, 3, 4, 1);
+
+ splash_close();
+
+
+ gtk_widget_show_all (window);
+
+ gtk_window_fullscreen(GTK_WINDOW(window));
+
+ GdkCursor *cursor=gdk_cursor_new(GDK_ARROW);
+ GdkWindow *gdk_window = gtk_widget_get_window(window);
+ gdk_window_set_cursor(gdk_window,cursor);
+
+/*
+ GdkDisplay *display=gdk_display_get_default();
+ if(display==NULL) {
+ fprintf(stderr,"no default display!\n");
+ _exit(0);
+ }
+
+ GdkCursor *cursor=gdk_cursor_new_for_display(display,GDK_ARROW);
+*/
+
+ update_timer_id=gdk_threads_add_timeout(1000/updates_per_second, update, NULL);
+
+ // save every 30 seconds
+ save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL);
+
+ vfo_update(NULL);
+
+ return 0;
+}
+
+
+int
+main (int argc,
+ char *argv[])
+{
+ gtk_init (&argc, &argv);
+
+ uname(&unameData);
+ fprintf(stderr,"sysname: %s\n",unameData.sysname);
+ fprintf(stderr,"nodename: %s\n",unameData.nodename);
+ fprintf(stderr,"release: %s\n",unameData.release);
+ fprintf(stderr,"version: %s\n",unameData.version);
+ fprintf(stderr,"machine: %s\n",unameData.machine);
+
+ GdkScreen *screen=gdk_screen_get_default();
+ if(screen==NULL) {
+ fprintf(stderr,"no default screen!\n");
+ _exit(0);
+ }
+
+
+ //display_width=gdk_screen_get_width(screen);
+ //display_height=gdk_screen_get_height(screen);
+ display_width=800;
+ display_height=480;
+
+ splash_show("splash.png", 0, display_width, display_height);
+
+ g_idle_add(init,(void *)argv[0]);
+
+ gtk_main();
+
+ return 0;
+}
--- /dev/null
+#include <sys/utsname.h>
+extern struct utsname unameData;
--- /dev/null
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "meter.h"
+
+static GtkWidget *meter;
+static cairo_surface_t *meter_surface = NULL;
+
+static int meter_width;
+static int meter_height;
+
+static void
+meter_clear_surface (void)
+{
+ cairo_t *cr;
+ cr = cairo_create (meter_surface);
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+}
+
+meter_configure_event_cb (GtkWidget *widget,
+ GdkEventConfigure *event,
+ gpointer data)
+{
+ if (meter_surface)
+ cairo_surface_destroy (meter_surface);
+
+ meter_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+ CAIRO_CONTENT_COLOR,
+ gtk_widget_get_allocated_width (widget),
+ gtk_widget_get_allocated_height (widget));
+
+ /* Initialize the surface to black */
+ meter_clear_surface ();
+
+ return TRUE;
+}
+
+/* Redraw the screen from the surface. Note that the ::draw
+ * signal receives a ready-to-be-used cairo_t that is already
+ * clipped to only draw the exposed areas of the widget
+ */
+static gboolean
+meter_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data) {
+ cairo_set_source_surface (cr, meter_surface, 0, 0);
+ cairo_paint (cr);
+
+ return FALSE;
+}
+
+GtkWidget* meter_init(int width,int height) {
+
+ meter_width=width;
+ meter_height=height;
+
+ meter = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (meter, width, height);
+
+ /* Signals used to handle the backing surface */
+ g_signal_connect (meter, "draw",
+ G_CALLBACK (meter_draw_cb), NULL);
+ g_signal_connect (meter,"configure-event",
+ G_CALLBACK (meter_configure_event_cb), NULL);
+
+
+ return meter;
+}
+
+
+void meter_update(int meter_type,double value,double reverse) {
+
+ char sf[32];
+ int text_location;
+ cairo_t *cr;
+ cr = cairo_create (meter_surface);
+
+ // clear the meter
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ switch(meter_type) {
+ case SMETER:
+ // value is dBm
+ text_location=10;
+ cairo_select_font_face(cr, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ double level=value+(double)get_attenuation();
+ if(meter_width>=114) {
+ int db=meter_width/114; // S9+60 (9*6)+60
+ int i;
+ cairo_set_line_width(cr, 1.0);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ for(i=0;i<54;i++) {
+ cairo_move_to(cr,(double)(i*db),(double)meter_height-20);
+ if(i%18==0) {
+ cairo_line_to(cr,(double)(i*db),(double)(meter_height-30));
+ } else if(i%6==0) {
+ cairo_line_to(cr,(double)(i*db),(double)(meter_height-25));
+ }
+ }
+ cairo_stroke(cr);
+
+ cairo_set_font_size(cr, 12);
+ cairo_move_to(cr, (double)(18*db)-3.0, (double)meter_height);
+ cairo_show_text(cr, "3");
+ cairo_move_to(cr, (double)(36*db)-3.0, (double)meter_height);
+ cairo_show_text(cr, "6");
+
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ cairo_move_to(cr,(double)(54*db),(double)meter_height-20);
+ cairo_line_to(cr,(double)(54*db),(double)(meter_height-30));
+ cairo_move_to(cr,(double)(74*db),(double)meter_height-20);
+ cairo_line_to(cr,(double)(74*db),(double)(meter_height-30));
+ cairo_move_to(cr,(double)(94*db),(double)meter_height-20);
+ cairo_line_to(cr,(double)(94*db),(double)(meter_height-30));
+ cairo_move_to(cr,(double)(114*db),(double)meter_height-20);
+ cairo_line_to(cr,(double)(114*db),(double)(meter_height-30));
+ cairo_stroke(cr);
+
+ cairo_move_to(cr, (double)(54*db)-3.0, (double)meter_height);
+ cairo_show_text(cr, "9");
+ cairo_move_to(cr, (double)(74*db)-12.0, (double)meter_height);
+ cairo_show_text(cr, "+20");
+ cairo_move_to(cr, (double)(94*db)-9.0, (double)meter_height);
+ cairo_show_text(cr, "+40");
+ cairo_move_to(cr, (double)(114*db)-6.0, (double)meter_height);
+ cairo_show_text(cr, "+60");
+
+ cairo_set_source_rgb(cr, 0, 1, 0);
+ cairo_move_to(cr,(double)((level+127.0)*db),(double)meter_height-30);
+ cairo_line_to(cr,(double)((level+127.0)*db),(double)(meter_height-50));
+ cairo_stroke(cr);
+
+ text_location=(db*114)+5;
+ }
+
+ cairo_set_font_size(cr, 16);
+ sprintf(sf,"%d dBm",(int)level);
+ cairo_move_to(cr, text_location, 45);
+ cairo_show_text(cr, sf);
+ break;
+ case POWER:
+ // value is Watts
+ cairo_select_font_face(cr, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size(cr, 18);
+
+ sprintf(sf,"FWD: %3.2f W",value);
+ cairo_move_to(cr, 10, 25);
+ cairo_show_text(cr, sf);
+
+ // value is Watts
+ double swr=(value+reverse)/(value-reverse);
+ cairo_select_font_face(cr, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size(cr, 18);
+
+ sprintf(sf,"SWR: %1.2f:1",swr);
+ cairo_move_to(cr, 10, 45);
+ cairo_show_text(cr, sf);
+
+/*
+ sprintf(sf,"REV: %3.2f W",reverse);
+ cairo_move_to(cr, 10, 45);
+ cairo_show_text(cr, sf);
+*/
+ break;
+ }
+
+ cairo_destroy(cr);
+ gtk_widget_queue_draw (meter);
+}
--- /dev/null
+#define SMETER 0
+#define POWER 1
+
+
+GtkWidget* meter_init(int width,int height);
+void meter_update(int meter_type,double value,double reverse);
--- /dev/null
+char *mode_string[]={"LSB","USB","DSB","CWL","CWU","FMN","AM","DIGU","SPEC","DIGL","SAM","DRM"};
+
--- /dev/null
+/**
+* @file mode.h
+* @brief Header files for the mode functions
+* @author John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* @version 0.1
+* @date 2009-04-12
+*/
+// mode.h
+
+/* Copyright (C)
+* 2009 - John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* 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 the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+*/
+
+#define modeLSB 0
+#define modeUSB 1
+#define modeDSB 2
+#define modeCWL 3
+#define modeCWU 4
+#define modeFMN 5
+#define modeAM 6
+#define modeDIGU 7
+#define modeSPEC 8
+#define modeDIGL 9
+#define modeSAM 10
+#define modeDRM 11
+
+#define MODES 12
+
+int mode;
+
+char *mode_string[MODES];
+
+/*
+int updateMode(void * data);
+
+void setMode(int mode);
+void modeSaveState();
+void modeRestoreState();
+GtkWidget* buildModeUI();
+char* modeToString();
+*/
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <ifaddrs.h>
+#include <pthread.h>
+#include <string.h>
+#include <errno.h>
+
+#include "discovered.h"
+//#include "discovery.h"
+
+int selected_device=0;
+int devices=0;
+DISCOVERED discovered[MAX_DEVICES];
+
+static char interface_name[64];
+static struct sockaddr_in interface_addr={0};
+static int interface_length;
+
+#define DISCOVERY_PORT 1024
+static int discovery_socket;
+static struct sockaddr_in discovery_addr;
+
+void new_discover(struct ifaddrs* iface);
+
+static pthread_t discover_thread_id;
+void* new_discover_receive_thread(void* arg);
+
+void print_device(int i) {
+ fprintf(stderr,"discovery: found protocol=%d device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
+ discovered[i].protocol,
+ discovered[i].device,
+ discovered[i].software_version,
+ discovered[i].status,
+ inet_ntoa(discovered[i].address.sin_addr),
+ discovered[i].mac_address[0],
+ discovered[i].mac_address[1],
+ discovered[i].mac_address[2],
+ discovered[i].mac_address[3],
+ discovered[i].mac_address[4],
+ discovered[i].mac_address[5],
+ discovered[i].interface_name);
+}
+
+void new_discovery() {
+ devices=0;
+ selected_device=0;
+ struct ifaddrs *addrs,*ifa;
+ getifaddrs(&addrs);
+ ifa = addrs;
+ while (ifa) {
+ if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
+ if((ifa->ifa_flags&IFF_UP)==IFF_UP
+ && (ifa->ifa_flags&IFF_RUNNING)==IFF_RUNNING
+ && (ifa->ifa_flags&IFF_LOOPBACK)!=IFF_LOOPBACK) {
+ new_discover(ifa);
+ }
+ }
+ ifa = ifa->ifa_next;
+ }
+ freeifaddrs(addrs);
+
+
+ fprintf(stderr, "new_discovery found %d devices\n",devices);
+
+ int i;
+ for(i=0;i<devices;i++) {
+ print_device(i);
+ }
+}
+
+void new_discover(struct ifaddrs* iface) {
+ int rc;
+ struct sockaddr_in *sa;
+ //char *addr;
+
+ strcpy(interface_name,iface->ifa_name);
+ fprintf(stderr,"new_discover: looking for HPSDR devices on %s\n",interface_name);
+
+ // send a broadcast to locate metis boards on the network
+ discovery_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+ if(discovery_socket<0) {
+ perror("new_discover: create socket failed for discovery_socket\n");
+ exit(-1);
+ }
+
+ int optval = 1;
+ setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+
+ sa = (struct sockaddr_in *) iface->ifa_addr;
+ //addr = inet_ntoa(sa->sin_addr);
+
+ // bind to this interface and the discovery port
+ interface_addr.sin_family = AF_INET;
+ interface_addr.sin_addr.s_addr = sa->sin_addr.s_addr;
+ interface_addr.sin_port = htons(DISCOVERY_PORT);
+ if(bind(discovery_socket,(struct sockaddr*)&interface_addr,sizeof(interface_addr))<0) {
+ perror("new_discover: bind socket failed for discovery_socket\n");
+ exit(-1);
+ }
+
+ fprintf(stderr,"new_discover: bound to %s\n",interface_name);
+
+ // allow broadcast on the socket
+ int on=1;
+ rc=setsockopt(discovery_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
+ if(rc != 0) {
+ fprintf(stderr,"new_discover: cannot set SO_BROADCAST: rc=%d\n", rc);
+ exit(-1);
+ }
+
+ // setup to address
+ struct sockaddr_in to_addr={0};
+ to_addr.sin_family=AF_INET;
+ to_addr.sin_port=htons(DISCOVERY_PORT);
+ to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST);
+
+ // start a receive thread to collect discovery response packets
+ rc=pthread_create(&discover_thread_id,NULL,new_discover_receive_thread,NULL);
+ if(rc != 0) {
+ fprintf(stderr,"pthread_create failed on new_discover_receive_thread: rc=%d\n", rc);
+ exit(-1);
+ }
+
+
+ // send discovery packet
+ unsigned char buffer[60];
+ buffer[0]=0x00;
+ buffer[1]=0x00;
+ buffer[2]=0x00;
+ buffer[3]=0x00;
+ buffer[4]=0x02;
+ int i;
+ for(i=5;i<60;i++) {
+ buffer[i]=0x00;
+ }
+
+ if(sendto(discovery_socket,buffer,60,0,(struct sockaddr*)&to_addr,sizeof(to_addr))<0) {
+ perror("new_discover: sendto socket failed for discovery_socket\n");
+ exit(-1);
+ }
+
+ // wait for receive thread to complete
+ void* status;
+ pthread_join(discover_thread_id,&status);
+
+ close(discovery_socket);
+
+ fprintf(stderr,"new_discover: exiting discover for %s\n",iface->ifa_name);
+}
+
+void* new_discover_receive_thread(void* arg) {
+ struct sockaddr_in addr;
+ int len;
+ unsigned char buffer[2048];
+ int bytes_read;
+ struct timeval tv;
+ int i;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ setsockopt(discovery_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
+
+ len=sizeof(addr);
+ while(1) {
+ bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&len);
+ if(bytes_read<0) {
+ fprintf(stderr,"new_discover: bytes read %d\n", bytes_read);
+ perror("new_discover: recvfrom socket failed for discover_receive_thread");
+ break;
+ }
+ fprintf(stderr,"new_discover: received %d bytes\n",bytes_read);
+ if(bytes_read==1444) {
+ if(devices>0) {
+ break;
+ }
+ } else {
+ if(buffer[0]==0 && buffer[1]==0 && buffer[2]==0 && buffer[3]==0) {
+ int status = buffer[4] & 0xFF;
+ if (status == 2 || status == 3) {
+ if(devices<MAX_DEVICES) {
+ discovered[devices].protocol=NEW_PROTOCOL;
+ discovered[devices].device=buffer[11]&0xFF;
+ switch(discovered[devices].device) {
+ case NEW_DEVICE_ATLAS:
+ strcpy(discovered[devices].name,"Atlas");
+ break;
+ case NEW_DEVICE_HERMES:
+ strcpy(discovered[devices].name,"Hermes");
+ break;
+ case NEW_DEVICE_HERMES2:
+ strcpy(discovered[devices].name,"Hermes2");
+ break;
+ case NEW_DEVICE_ANGELIA:
+ strcpy(discovered[devices].name,"Angelia");
+ break;
+ case NEW_DEVICE_ORION:
+ strcpy(discovered[devices].name,"Orion");
+ break;
+ case NEW_DEVICE_ANAN_10E:
+ strcpy(discovered[devices].name,"Anan-10E");
+ break;
+ case NEW_DEVICE_HERMES_LITE:
+ strcpy(discovered[devices].name,"Hermes Lite");
+ break;
+ default:
+ strcpy(discovered[devices].name,"Unknown");
+ break;
+ }
+ discovered[devices].software_version=buffer[13]&0xFF;
+ for(i=0;i<6;i++) {
+ discovered[devices].mac_address[i]=buffer[i+5];
+ }
+ discovered[devices].status=status;
+ memcpy((void*)&discovered[devices].address,(void*)&addr,sizeof(addr));
+ discovered[devices].address_length=sizeof(addr);
+ memcpy((void*)&discovered[devices].interface_address,(void*)&interface_addr,sizeof(interface_addr));
+ discovered[devices].interface_length=sizeof(interface_addr);
+ strcpy(discovered[devices].interface_name,interface_name);
+ fprintf(stderr,"new_discover: found protocol=%d device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
+ discovered[devices].protocol,
+ discovered[devices].device,
+ discovered[devices].software_version,
+ discovered[devices].status,
+ inet_ntoa(discovered[devices].address.sin_addr),
+ discovered[devices].mac_address[0],
+ discovered[devices].mac_address[1],
+ discovered[devices].mac_address[2],
+ discovered[devices].mac_address[3],
+ discovered[devices].mac_address[4],
+ discovered[devices].mac_address[5],
+ discovered[devices].interface_name);
+ devices++;
+ }
+ }
+ }
+ }
+ }
+ fprintf(stderr,"new_discover: exiting new_discover_receive_thread\n");
+ pthread_exit(NULL);
+}
--- /dev/null
+
+void new_discovery(void);
--- /dev/null
+
+//#define ECHO_MIC
+
+#include <gtk/gtk.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <math.h>
+
+#include "alex.h"
+#include "new_protocol.h"
+#include "channel.h"
+#include "discovered.h"
+#include "wdsp.h"
+#include "radio.h"
+#include "vfo.h"
+#include "toolbar.h"
+
+#define PI 3.1415926535897932F
+
+static int receiver;
+static int running=0;
+
+int data_socket;
+
+static struct sockaddr_in base_addr;
+static int base_addr_length;
+
+static struct sockaddr_in receiver_addr;
+static int receiver_addr_length;
+
+static struct sockaddr_in transmitter_addr;
+static int transmitter_addr_length;
+
+static struct sockaddr_in high_priority_addr;
+static int high_priority_addr_length;
+
+static struct sockaddr_in audio_addr;
+static int audio_addr_length;
+
+static struct sockaddr_in iq_addr;
+static int iq_addr_length;
+
+static struct sockaddr_in data_addr;
+static int data_addr_length;
+
+static pthread_t new_protocol_thread_id;
+static pthread_t new_protocol_timer_thread_id;
+
+sem_t response_sem;
+
+static long rx_sequence = 0;
+
+static long high_priority_sequence = 0;
+static long general_sequence = 0;
+static long rx_specific_sequence = 0;
+static long tx_specific_sequence = 0;
+
+static int lt2208Dither = 0;
+static int lt2208Random = 0;
+static int attenuation = 20; // 20dB
+
+static long long ddsAFrequency = 14250000;
+static int filterLow=150;
+static int filterHigh=2550;
+static int mode=modeUSB;
+static unsigned long alex_rx_antenna=0;
+static unsigned long alex_tx_antenna=0;
+static unsigned long alex_attenuation=0;
+
+static int buffer_size=BUFFER_SIZE;
+static int fft_size=4096;
+static int sampleRate=48000;
+static int dspRate=48000;
+static int outputRate=48000;
+
+static int micSampleRate=48000;
+static int micDspRate=48000;
+static int micOutputRate=192000;
+
+static int spectrumWIDTH=800;
+static int SPECTRUM_UPDATES_PER_SECOND=10;
+
+static int mox=0;
+static int tune=0;
+static float phase = 0.0F;
+
+static int ptt;
+static int dot;
+static int dash;
+static int pll_locked;
+static int adc_overload;
+unsigned int exciter_power;
+unsigned int alex_forward_power;
+unsigned int alex_reverse_power;
+static int supply_volts;
+
+long response_sequence;
+int response;
+
+int send_high_priority=0;
+int send_general=0;
+
+static void initAnalyzer(int channel,int buffer_size);
+static void* new_protocol_thread(void* arg);
+static void* new_protocol_timer_thread(void* arg);
+
+void filter_board_changed() {
+ send_general=1;
+}
+
+void pa_changed() {
+ send_general=1;
+}
+
+void tuner_changed() {
+ send_general=1;
+}
+
+void cw_changed() {
+}
+
+void set_attenuation(int value) {
+ attenuation=value;
+}
+
+int get_attenuation() {
+ return attenuation;
+}
+
+void set_alex_rx_antenna(unsigned long v) {
+ alex_rx_antenna=v;
+ send_high_priority=1;
+}
+
+void set_alex_tx_antenna(unsigned long v) {
+ alex_tx_antenna=v;
+ send_high_priority=1;
+}
+
+void set_alex_attenuation(unsigned long v) {
+ alex_attenuation=v;
+ send_high_priority=1;
+}
+
+void setSampleRate(int rate) {
+ sampleRate=rate;
+}
+
+int getSampleRate() {
+ return sampleRate;
+}
+
+void setFrequency(long long f) {
+ ddsAFrequency=f;
+ send_high_priority=1;
+}
+
+long long getFrequency() {
+ return ddsAFrequency;
+}
+
+void setMode(int m) {
+ mode=m;
+ SetRXAMode(receiver, mode);
+ SetTXAMode(CHANNEL_TX, mode);
+}
+
+int getMode() {
+ return mode;
+}
+
+void setFilter(int low,int high) {
+ if(mode==modeCWL) {
+ filterLow=-cwPitch-low;
+ filterHigh=-cwPitch+high;
+ } else if(mode==modeCWU) {
+ filterLow=cwPitch-low;
+ filterHigh=cwPitch+high;
+ } else {
+ filterLow=low;
+ filterHigh=high;
+ }
+
+ RXANBPSetFreqs(receiver,(double)filterLow,(double)filterHigh);
+ SetRXABandpassFreqs(receiver, (double)filterLow, (double)filterHigh);
+ SetRXASNBAOutputBandwidth(receiver, (double)filterLow, (double)filterHigh);
+
+ SetTXABandpassFreqs(CHANNEL_TX, (double)filterLow, (double)filterHigh);
+}
+
+int getFilterLow() {
+ return filterLow;
+}
+
+int getFilterHigh() {
+ return filterHigh;
+}
+
+void setMox(int state) {
+ if(mox!=state) {
+ mox=state;
+ send_high_priority=1;
+ }
+}
+
+int getMox() {
+ return mox;
+}
+
+void setTune(int state) {
+ if(tune!=state) {
+ tune=state;
+ send_high_priority=1;
+ send_general=1;
+ }
+}
+
+int getTune() {
+ return tune;
+}
+
+int isTransmitting() {
+ return ptt!=0 || mox!=0 || tune!=0;
+}
+
+double getDrive() {
+ return (double)drive/255.0;
+}
+
+void setDrive(double value) {
+ drive=(int)(value*255.0);
+ send_high_priority=1;
+}
+
+double getTuneDrive() {
+ return (double)tune_drive/255.0;
+}
+
+void setTuneDrive(double value) {
+ tune_drive=(int)(value*255.0);
+ send_high_priority=1;
+}
+
+void new_protocol_init(int rx,int pixels) {
+ int rc;
+ receiver=rx;
+ spectrumWIDTH=pixels;
+
+ fprintf(stderr,"new_protocol_init: %d\n",rx);
+
+ rc=sem_init(&response_sem, 0, 0);
+
+ fprintf(stderr,"OpenChannel %d buffer_size=%d fft_size=%d sampleRate=%d dspRate=%d outputRate=%d\n",
+ rx,
+ buffer_size,
+ fft_size,
+ sampleRate,
+ dspRate,
+ outputRate);
+
+ OpenChannel(rx,
+ buffer_size,
+ fft_size,
+ sampleRate,
+ dspRate,
+ outputRate,
+ 0, // receive
+ 1, // run
+ 0.010, 0.025, 0.0, 0.010, 0);
+
+ fprintf(stderr,"OpenChannel %d buffer_size=%d fft_size=%d sampleRate=%d dspRate=%d outputRate=%d\n",
+ CHANNEL_TX,
+ buffer_size,
+ fft_size,
+ micSampleRate,
+ micDspRate,
+ micOutputRate);
+
+ OpenChannel(CHANNEL_TX,
+ buffer_size,
+ fft_size,
+ micSampleRate,
+ micDspRate,
+ micOutputRate,
+ 1, // transmit
+ 1, // run
+ 0.010, 0.025, 0.0, 0.010, 0);
+
+ fprintf(stderr,"XCreateAnalyzer %d\n",rx);
+ int success;
+ XCreateAnalyzer(rx, &success, 262144, 1, 1, "");
+ if (success != 0) {
+ fprintf(stderr, "XCreateAnalyzer %d failed: %d\n" ,rx,success);
+ }
+ initAnalyzer(rx,buffer_size);
+
+ XCreateAnalyzer(CHANNEL_TX, &success, 262144, 1, 1, "");
+ if (success != 0) {
+ fprintf(stderr, "XCreateAnalyzer CHANNEL_TX failed: %d\n" ,success);
+ }
+ initAnalyzer(CHANNEL_TX,BUFFER_SIZE);
+
+ rc=pthread_create(&new_protocol_thread_id,NULL,new_protocol_thread,NULL);
+ if(rc != 0) {
+ fprintf(stderr,"pthread_create failed on new_protocol_thread for receiver %d: rc=%d\n", receiver, rc);
+ exit(-1);
+ }
+
+ SetRXAMode(rx, mode);
+ SetRXABandpassFreqs(rx, (double)filterLow, (double)filterHigh);
+ SetRXAAGCMode(rx, agc);
+ SetRXAAGCTop(rx,agc_gain);
+
+ SetRXAAMDSBMode(CHANNEL_RX0, 0);
+ SetRXAShiftRun(CHANNEL_RX0, 0);
+ SetRXAEMNRgainMethod(CHANNEL_RX0, 1);
+ SetRXAEMNRnpeMethod(CHANNEL_RX0, 0);
+ SetRXAEMNRaeRun(CHANNEL_RX0, 1);
+ SetRXAEMNRPosition(CHANNEL_RX0, 0);
+ SetRXAEMNRRun(CHANNEL_RX0, 0);
+ SetRXAANRRun(CHANNEL_RX0, 0);
+ SetRXAANFRun(CHANNEL_RX0, 0);
+
+ SetTXAMode(CHANNEL_TX, mode);
+ SetTXABandpassFreqs(CHANNEL_TX, (double)filterLow, (double)filterHigh);
+ SetTXABandpassWindow(CHANNEL_TX, 1);
+ SetTXABandpassRun(CHANNEL_TX, 1);
+
+ SetTXACFIRRun(CHANNEL_TX, 1);
+ SetTXAEQRun(CHANNEL_TX, 0);
+ SetTXACTCSSRun(CHANNEL_TX, 0);
+ SetTXAAMSQRun(CHANNEL_TX, 0);
+ SetTXACompressorRun(CHANNEL_TX, 0);
+ SetTXAosctrlRun(CHANNEL_TX, 0);
+ SetTXAPreGenRun(CHANNEL_TX, 0);
+ SetTXAPostGenRun(CHANNEL_TX, 0);
+
+}
+
+static void initAnalyzer(int channel,int buffer_size) {
+ int flp[] = {0};
+ double KEEP_TIME = 0.1;
+ int spur_elimination_ffts = 1;
+ int data_type = 1;
+ int fft_size = 8192;
+ int window_type = 4;
+ double kaiser_pi = 14.0;
+ int overlap = 2048;
+ int clip = 0;
+ int span_clip_l = 0;
+ int span_clip_h = 0;
+ int pixels=spectrumWIDTH;
+ int stitches = 1;
+ int avm = 0;
+ double tau = 0.001 * 120.0;
+ int MAX_AV_FRAMES = 60;
+ int display_average = MAX(2, (int) MIN((double) MAX_AV_FRAMES, (double) SPECTRUM_UPDATES_PER_SECOND * tau));
+ double avb = exp(-1.0 / (SPECTRUM_UPDATES_PER_SECOND * tau));
+ int calibration_data_set = 0;
+ double span_min_freq = 0.0;
+ double span_max_freq = 0.0;
+
+ int max_w = fft_size + (int) MIN(KEEP_TIME * (double) SPECTRUM_UPDATES_PER_SECOND, KEEP_TIME * (double) fft_size * (double) SPECTRUM_UPDATES_PER_SECOND);
+
+ fprintf(stderr,"SetAnalyzer channel=%d\n",channel);
+ SetAnalyzer(channel,
+ spur_elimination_ffts, //number of LO frequencies = number of ffts used in elimination
+ data_type, //0 for real input data (I only); 1 for complex input data (I & Q)
+ flp, //vector with one elt for each LO frequency, 1 if high-side LO, 0 otherwise
+ fft_size, //size of the fft, i.e., number of input samples
+ buffer_size, //number of samples transferred for each OpenBuffer()/CloseBuffer()
+ window_type, //integer specifying which window function to use
+ kaiser_pi, //PiAlpha parameter for Kaiser window
+ overlap, //number of samples each fft (other than the first) is to re-use from the previous
+ clip, //number of fft output bins to be clipped from EACH side of each sub-span
+ span_clip_l, //number of bins to clip from low end of entire span
+ span_clip_h, //number of bins to clip from high end of entire span
+ pixels, //number of pixel values to return. may be either <= or > number of bins
+ stitches, //number of sub-spans to concatenate to form a complete span
+ avm, //averaging mode
+ display_average, //number of spans to (moving) average for pixel result
+ avb, //back multiplier for weighted averaging
+ calibration_data_set, //identifier of which set of calibration data to use
+ span_min_freq, //frequency at first pixel value8192
+ span_max_freq, //frequency at last pixel value
+ max_w //max samples to hold in input ring buffers
+ );
+}
+
+
+static void new_protocol_general() {
+ unsigned char buffer[60];
+
+fprintf(stderr,"new_protocol_general: receiver=%d\n", receiver);
+
+ memset(buffer, 0, sizeof(buffer));
+
+ buffer[0]=general_sequence>>24;
+ buffer[1]=general_sequence>>16;
+ buffer[2]=general_sequence>>8;
+ buffer[3]=general_sequence;
+
+ // use defaults apart from
+ buffer[37]=0x08; // phase word (not frequency)
+ buffer[58]=pa; // enable PA 0x01
+ if((filter_board==APOLLO) && tune && apollo_tuner) {
+ buffer[58]|=0x02;
+ }
+
+ if(filter_board==ALEX) {
+ buffer[59]=0x01; // enable Alex 0
+ }
+
+ if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&base_addr,base_addr_length)<0) {
+ fprintf(stderr,"sendto socket failed for general\n");
+ exit(1);
+ }
+
+ general_sequence++;
+}
+
+static void new_protocol_high_priority(int run,int tx,int drive) {
+ unsigned char buffer[1444];
+
+//fprintf(stderr,"new_protocol_high_priority: run=%d tx=%d drive=%d tx_ant=0x%08x rx_ant=0x%08x\n", run, tx, drive, alex_tx_antenna, alex_rx_antenna);
+ memset(buffer, 0, sizeof(buffer));
+
+ buffer[0]=high_priority_sequence>>24;
+ buffer[1]=high_priority_sequence>>16;
+ buffer[2]=high_priority_sequence>>8;
+ buffer[3]=high_priority_sequence;
+
+ buffer[4]=run|(tx<<1);
+
+ extern long long ddsAFrequency;
+
+ long phase=(long)((4294967296.0*(double)ddsAFrequency)/122880000.0);
+
+// rx
+ buffer[9]=phase>>24;
+ buffer[10]=phase>>16;
+ buffer[11]=phase>>8;
+ buffer[12]=phase;
+
+// tx
+ buffer[329]=phase>>24;
+ buffer[330]=phase>>16;
+ buffer[331]=phase>>8;
+ buffer[332]=phase;
+
+
+ buffer[345]=drive;
+
+// alex HPF filters
+/*
+if (frequency < 1800000) HPF <= 6'b100000; // bypass
+else if (frequency < 6500000) HPF <= 6'b010000; // 1.5MHz HPF
+else if (frequency < 9500000) HPF <= 6'b001000; // 6.5MHz HPF
+else if (frequency < 13000000) HPF <= 6'b000100; // 9.5MHz HPF
+else if (frequency < 20000000) HPF <= 6'b000001; // 13MHz HPF
+else HPF <= 6'b000010; // 20MHz HPF
+*/
+
+ long filters=0x00000000;
+// set HPF
+ if(ddsAFrequency<1800000L) {
+ filters|=ALEX_BYPASS_HPF;
+ } else if(ddsAFrequency<6500000L) {
+ filters|=ALEX_1_5MHZ_HPF;
+ } else if(ddsAFrequency<9500000L) {
+ filters|=ALEX_6_5MHZ_HPF;
+ } else if(ddsAFrequency<13000000L) {
+ filters|=ALEX_9_5MHZ_HPF;
+ } else if(ddsAFrequency<20000000L) {
+ filters|=ALEX_13MHZ_HPF;
+ } else {
+ filters|=ALEX_20MHZ_HPF;
+ }
+// alex LPF filters
+/*
+if (frequency > 32000000) LPF <= 7'b0010000; // > 10m so use 6m LPF^M
+else if (frequency > 22000000) LPF <= 7'b0100000; // > 15m so use 12/10m LPF^M
+else if (frequency > 15000000) LPF <= 7'b1000000; // > 20m so use 17/15m LPF^M
+else if (frequency > 8000000) LPF <= 7'b0000001; // > 40m so use 30/20m LPF ^M
+else if (frequency > 4500000) LPF <= 7'b0000010; // > 80m so use 60/40m LPF^M
+else if (frequency > 2400000) LPF <= 7'b0000100; // > 160m so use 80m LPF ^M
+else LPF <= 7'b0001000; // < 2.4MHz so use 160m LPF^M
+*/
+
+ if(ddsAFrequency>32000000) {
+ filters|=ALEX_6_BYPASS_LPF;
+ } else if(ddsAFrequency>22000000) {
+ filters|=ALEX_12_10_LPF;
+ } else if(ddsAFrequency>15000000) {
+ filters|=ALEX_17_15_LPF;
+ } else if(ddsAFrequency>8000000) {
+ filters|=ALEX_30_20_LPF;
+ } else if(ddsAFrequency>4500000) {
+ filters|=ALEX_60_40_LPF;
+ } else if(ddsAFrequency>2400000) {
+ filters|=ALEX_80_LPF;
+ } else {
+ filters|=ALEX_160_LPF;
+ }
+
+ filters|=alex_rx_antenna;
+ filters|=alex_tx_antenna;
+ filters|=alex_attenuation;
+
+ if(tx) {
+ filters|=0x08000000;
+ }
+
+/*
+ buffer[1420]=filters>>24;
+ buffer[1421]=filters>>16;
+ buffer[1422]=filters>>8;
+ buffer[1423]=filters;
+*/
+
+ buffer[1432]=filters>>24;
+ buffer[1433]=filters>>16;
+ buffer[1434]=filters>>8;
+ buffer[1435]=filters;
+
+ //buffer[1442]=attenuation;
+ buffer[1443]=attenuation;
+
+//fprintf(stderr,"[4]=%02X\n", buffer[4]);
+//fprintf(stderr,"filters=%04X\n", filters);
+
+ if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&high_priority_addr,high_priority_addr_length)<0) {
+ fprintf(stderr,"sendto socket failed for high priority\n");
+ exit(1);
+ }
+
+ high_priority_sequence++;
+}
+
+static void new_protocol_transmit_specific() {
+ unsigned char buffer[60];
+
+ memset(buffer, 0, sizeof(buffer));
+
+ buffer[0]=tx_specific_sequence>>24;
+ buffer[1]=tx_specific_sequence>>16;
+ buffer[2]=tx_specific_sequence>>8;
+ buffer[3]=tx_specific_sequence;
+
+ buffer[4]=1; // 1 DAC
+ buffer[5]=0; // no CW
+ if(cw_keyer_internal) {
+ buffer[5]|=0x02;
+ }
+ if(cw_keys_reversed) {
+ buffer[5]|=0x04;
+ }
+ if(cw_keyer_mode==KEYER_MODE_A) {
+ buffer[5]|=0x08;
+ }
+ if(cw_keyer_mode==KEYER_MODE_B) {
+ buffer[5]|=0x28;
+ }
+ if(cw_keyer_spacing) {
+ buffer[5]|=0x40;
+ }
+ if(cw_breakin) {
+ buffer[5]|=0x80;
+ }
+
+ buffer[6]=cw_keyer_sidetone_volume; // sidetone off
+ buffer[7]=cw_keyer_sidetone_frequency>>8; buffer[8]=cw_keyer_sidetone_frequency; // sidetone frequency
+ buffer[9]=cw_keyer_speed; // cw keyer speed
+ buffer[10]=cw_keyer_weight; // cw weight
+ buffer[11]=cw_keyer_hang_time>>8; buffer[12]=cw_keyer_hang_time; // cw hang delay
+ buffer[13]=0; // rf delay
+ buffer[50]=orion_mic;
+ buffer[51]=0x7F; // Line in gain
+
+ if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&transmitter_addr,transmitter_addr_length)<0) {
+ fprintf(stderr,"sendto socket failed for tx specific\n");
+ exit(1);
+ }
+
+ tx_specific_sequence++;
+
+}
+
+static void new_protocol_receive_specific() {
+ unsigned char buffer[1444];
+ int i;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ buffer[0]=rx_specific_sequence>>24;
+ buffer[1]=rx_specific_sequence>>16;
+ buffer[2]=rx_specific_sequence>>8;
+ buffer[3]=rx_specific_sequence;
+
+ buffer[4]=2; // 2 ADCs
+ buffer[5]=0; // dither off
+ if(lt2208Dither) {
+ buffer[5]=0x01<<receiver;
+ }
+ buffer[6]=0; // random off
+ if(lt2208Random) {
+ buffer[6]=0x01<<receiver;
+ }
+ buffer[7]=0x00;
+ for(i=0;i<receivers;i++) {
+ buffer[7]|=(1<<i);
+ }
+
+ for(i=0;i<receivers;i++) {
+ buffer[17+(i*6)]=adc[i];
+ }
+
+ buffer[18]=((sampleRate/1000)>>8)&0xFF;
+ buffer[19]=(sampleRate/1000)&0xFF;
+ buffer[22]=24;
+
+ buffer[24]=((sampleRate/1000)>>8)&0xFF;
+ buffer[25]=(sampleRate/1000)&0xFF;
+ buffer[28]=24;
+
+ if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&receiver_addr,receiver_addr_length)<0) {
+ fprintf(stderr,"sendto socket failed for start: receiver=%d\n",receiver);
+ exit(1);
+ }
+
+ rx_specific_sequence++;
+}
+
+static void new_protocol_start() {
+ running=1;
+ new_protocol_transmit_specific();
+ new_protocol_receive_specific();
+ int rc=pthread_create(&new_protocol_timer_thread_id,NULL,new_protocol_timer_thread,NULL);
+ if(rc != 0) {
+ fprintf(stderr,"pthread_create failed on new_protocol_timer_thread: %d\n", rc);
+ exit(-1);
+ }
+}
+
+void new_protocol_stop() {
+ new_protocol_high_priority(0,0,0);
+ running=0;
+ sleep(1);
+}
+
+/*
+float sineWave(float* buf, int samples, float phase, float freq) {
+ float phase_step = 2 * PI * freq / 192000.0F;
+ int i;
+ for (i = 0; i < samples; i++) {
+ buf[i] = (float) sin(phase);
+ phase += phase_step;
+ }
+ return phase;
+}
+*/
+float sineWave(double* buf, int samples, float phase, float freq) {
+ float phase_step = 2 * PI * freq / 192000.0F;
+ int i;
+ for (i = 0; i < samples; i++) {
+ buf[i*2] = (double) sin(phase);
+ phase += phase_step;
+ }
+ return phase;
+}
+
+double calibrate(int v) {
+ // Angelia
+ double v1;
+ v1=(double)v/4095.0*3.3;
+
+ return (v1*v1)/0.095;
+}
+
+void* new_protocol_thread(void* arg) {
+
+ DISCOVERED* d=&discovered[selected_device];
+
+ struct sockaddr_in addr;
+ int length;
+ unsigned char buffer[2048];
+ int bytesread;
+ short sourceport;
+
+ long sequence;
+ long long timestamp;
+ int bitspersample;
+ int samplesperframe;
+
+ int b;
+ int leftsample;
+ int rightsample;
+ float leftsamplefloat;
+ float rightsamplefloat;
+
+ int previous_ptt;
+ int previous_dot;
+ int previous_dash;
+
+ int samples;
+ //float leftinputbuffer[BUFFER_SIZE];
+ //float rightinputbuffer[BUFFER_SIZE];
+ double iqinputbuffer[BUFFER_SIZE*2];
+
+ int outputsamples;
+ //float leftoutputbuffer[BUFFER_SIZE];
+ //float rightoutputbuffer[BUFFER_SIZE];
+ double audiooutputbuffer[BUFFER_SIZE*2];
+
+ short leftaudiosample;
+ short rightaudiosample;
+ long audiosequence;
+ unsigned char audiobuffer[1444];
+ int audioindex;
+
+ int micsample;
+ float micsamplefloat;
+
+ int micsamples;
+/*
+ float micleftinputbuffer[BUFFER_SIZE]; // 48000
+ float micrightinputbuffer[BUFFER_SIZE];
+*/
+ double micinputbuffer[BUFFER_SIZE*2];
+
+ int micoutputsamples;
+/*
+ float micleftoutputbuffer[BUFFER_SIZE*4]; // 192000
+ float micrightoutputbuffer[BUFFER_SIZE*4];
+*/
+ double micoutputbuffer[BUFFER_SIZE*4*2];
+
+ int isample;
+ int qsample;
+ long tx_iq_sequence;
+ unsigned char iqbuffer[1444];
+ int iqindex;
+
+ int i, j;
+fprintf(stderr,"new_protocol_thread: receiver=%d\n", receiver);
+
+ micsamples=0;
+ iqindex=4;
+
+ switch(sampleRate) {
+ case 48000:
+ outputsamples=BUFFER_SIZE;
+ break;
+ case 96000:
+ outputsamples=BUFFER_SIZE/2;
+ break;
+ case 192000:
+ outputsamples=BUFFER_SIZE/4;
+ break;
+ case 384000:
+ outputsamples=BUFFER_SIZE/8;
+ break;
+ }
+
+ micoutputsamples=BUFFER_SIZE*4; // 48000 in, 192000 out
+
+fprintf(stderr,"outputsamples=%d\n", outputsamples);
+ data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+ if(data_socket<0) {
+ fprintf(stderr,"metis: create socket failed for data_socket: receiver=%d\n",receiver);
+ exit(-1);
+ }
+
+ int optval = 1;
+ setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+
+ // bind to the interface
+ if(bind(data_socket,(struct sockaddr*)&d->interface_address,d->interface_length)<0) {
+ fprintf(stderr,"metis: bind socket failed for data_socket: receiver=%d\n",receiver);
+ exit(-1);
+ }
+
+ memcpy(&base_addr,&d->address,d->address_length);
+ base_addr_length=d->address_length;
+ base_addr.sin_port=htons(GENERAL_REGISTERS_FROM_HOST_PORT);
+
+ memcpy(&receiver_addr,&d->address,d->address_length);
+ receiver_addr_length=d->address_length;
+ receiver_addr.sin_port=htons(RECEIVER_SPECIFIC_REGISTERS_FROM_HOST_PORT);
+
+ memcpy(&transmitter_addr,&d->address,d->address_length);
+ transmitter_addr_length=d->address_length;
+ transmitter_addr.sin_port=htons(TRANSMITTER_SPECIFIC_REGISTERS_FROM_HOST_PORT);
+
+ memcpy(&high_priority_addr,&d->address,d->address_length);
+ high_priority_addr_length=d->address_length;
+ high_priority_addr.sin_port=htons(HIGH_PRIORITY_FROM_HOST_PORT);
+
+ memcpy(&audio_addr,&d->address,d->address_length);
+ audio_addr_length=d->address_length;
+ audio_addr.sin_port=htons(AUDIO_FROM_HOST_PORT);
+
+ memcpy(&iq_addr,&d->address,d->address_length);
+ iq_addr_length=d->address_length;
+ iq_addr.sin_port=htons(TX_IQ_FROM_HOST_PORT);
+
+ memcpy(&data_addr,&d->address,d->address_length);
+ data_addr_length=d->address_length;
+ data_addr.sin_port=htons(RX_IQ_TO_HOST_PORT+receiver);
+
+ samples=0;
+ audioindex=4; // leave space for sequence
+ audiosequence=0L;
+
+ new_protocol_general();
+ new_protocol_start();
+ new_protocol_high_priority(1,0,drive);
+
+ while(running) {
+ bytesread=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length);
+ if(bytesread<0) {
+ fprintf(stderr,"recvfrom socket failed for new_protocol_thread: receiver=%d", receiver);
+ exit(1);
+ }
+
+ short sourceport=ntohs(addr.sin_port);
+
+//fprintf(stderr,"received packet length %d from port %d\n",bytesread,sourceport);
+
+ if(sourceport==RX_IQ_TO_HOST_PORT) {
+
+ sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+ timestamp=((long long)(buffer[4]&0xFF)<<56)+((long long)(buffer[5]&0xFF)<<48)+((long long)(buffer[6]&0xFF)<<40)+((long long)(buffer[7]&0xFF)<<32);
+ ((long long)(buffer[8]&0xFF)<<24)+((long long)(buffer[9]&0xFF)<<16)+((long long)(buffer[10]&0xFF)<<8)+(long long)(buffer[11]&0xFF);
+ bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
+ samplesperframe=((buffer[14]&0xFF)<<8)+(buffer[15]&0xFF);
+
+//fprintf(stderr,"samples per frame %d\n",samplesperframe);
+
+ //if(!isTransmitting()) {
+ b=16;
+ for(i=0;i<samplesperframe;i++) {
+ leftsample = (int)((signed char) buffer[b++]) << 16;
+ leftsample += (int)((unsigned char)buffer[b++]) << 8;
+ leftsample += (int)((unsigned char)buffer[b++]);
+ rightsample = (int)((signed char) buffer[b++]) << 16;
+ rightsample += (int)((unsigned char)buffer[b++]) << 8;
+ rightsample += (int)((unsigned char)buffer[b++]);
+
+ leftsamplefloat=(float)leftsample/8388607.0; // for 24 bits
+ rightsamplefloat=(float)rightsample/8388607.0; // for 24 bits
+
+ //leftinputbuffer[samples]=leftsamplefloat;
+ //rightinputbuffer[samples]=rightsamplefloat;
+ iqinputbuffer[samples*2]=(double)leftsamplefloat;
+ iqinputbuffer[(samples*2)+1]=(double)rightsamplefloat;
+
+ samples++;
+ if(samples==BUFFER_SIZE) {
+ int error;
+ fexchange0(CHANNEL_RX0+receiver, iqinputbuffer, audiooutputbuffer, &error);
+ if(error!=0) {
+ fprintf(stderr,"fexchange0 returned error: %d for receiver %d\n", error,receiver);
+ }
+
+ Spectrum0(1, CHANNEL_RX0+receiver, 0, 0, iqinputbuffer);
+
+ for(j=0;j<outputsamples;j++) {
+ leftaudiosample=(short)(audiooutputbuffer[j*2]*32767.0*volume);
+ rightaudiosample=(short)(audiooutputbuffer[(j*2)+1]*32767.0*volume);
+
+ audiobuffer[audioindex++]=leftaudiosample>>8;
+ audiobuffer[audioindex++]=leftaudiosample;
+ audiobuffer[audioindex++]=rightaudiosample>>8;
+ audiobuffer[audioindex++]=rightaudiosample;
+
+ if(audioindex>=sizeof(audiobuffer)) {
+ // insert the sequence
+ audiobuffer[0]=audiosequence>>24;
+ audiobuffer[1]=audiosequence>>16;
+ audiobuffer[2]=audiosequence>>8;
+ audiobuffer[3]=audiosequence;
+ // send the buffer
+ if(sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length)<0) {
+ fprintf(stderr,"sendto socket failed for audio\n");
+ exit(1);
+ }
+ audioindex=4;
+ audiosequence++;
+ }
+ }
+ samples=0;
+ }
+ }
+ //}
+
+ } else if(sourceport==COMMAND_RESPONCE_TO_HOST_PORT) {
+ // command/response
+ response_sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+ response=buffer[4]&0xFF;
+ fprintf(stderr,"response_sequence=%ld response=%d\n",response_sequence,response);
+ sem_post(&response_sem);
+
+ } else if(sourceport==HIGH_PRIORITY_TO_HOST_PORT) {
+ // high priority
+ sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+
+ previous_ptt=ptt;
+ previous_dot=dot;
+ previous_dash=dash;
+
+ ptt=buffer[4]&0x01;
+ dot=(buffer[4]>>1)&0x01;
+ dash=(buffer[4]>>2)&0x01;
+ pll_locked=(buffer[4]>>3)&0x01;
+ adc_overload=buffer[5]&0x01;
+ exciter_power=((buffer[6]&0xFF)<<8)|(buffer[7]&0xFF);
+ alex_forward_power=((buffer[14]&0xFF)<<8)|(buffer[15]&0xFF);
+ alex_reverse_power=((buffer[22]&0xFF)<<8)|(buffer[23]&0xFF);
+ supply_volts=((buffer[49]&0xFF)<<8)|(buffer[50]&0xFF);
+
+ if(previous_ptt!=ptt) {
+ //send_high_priority=1;
+ previous_ptt=ptt;
+ g_idle_add(ptt_update,(gpointer)ptt);
+ }
+
+ } else if(sourceport==MIC_LINE_TO_HOST_PORT) {
+ // Mic/Line data
+ sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+ if(isTransmitting()) {
+ b=4;
+
+ for(i=0;i<720;i++) {
+ if(byte_swap) {
+ micsample = (int)((unsigned char)buffer[b++] & 0xFF);
+ micsample |= (int)((signed char) buffer[b++]) << 8;
+ } else {
+ micsample = (int)((signed char) buffer[b++]) << 8;
+ micsample |= (int)((unsigned char)buffer[b++] & 0xFF);
+ }
+ micsamplefloat = (float)micsample/32767.0F; // 16 bit sample
+
+ micinputbuffer[micsamples*2]=(double)(micsamplefloat*mic_gain);
+ micinputbuffer[(micsamples*2)+1]=0.0;
+
+ micsamples++;
+
+ if(micsamples==BUFFER_SIZE) {
+ int error;
+
+ if(tune==1) {
+ //float tunefrequency = (float)((filterLow + filterHigh - filterLow) / 2);
+ float tunefrequency = (float)((filterHigh - filterLow) / 2);
+ phase=sineWave(micinputbuffer, BUFFER_SIZE, phase, tunefrequency);
+ }
+
+ fexchange0(CHANNEL_TX, micinputbuffer, micoutputbuffer, &error);
+ if(error!=0) {
+ fprintf(stderr,"fexchange0 returned error: %d for transmitter\n", error);
+ }
+
+ for(j=0;j<micoutputsamples;j++) {
+ isample=(int)(micoutputbuffer[j*2]*8388607.0); // 24 bit
+ qsample=(int)(micoutputbuffer[(j*2)+1]*8388607.0); // 24 bit
+
+ iqbuffer[iqindex++]=isample>>16;
+ iqbuffer[iqindex++]=isample>>8;
+ iqbuffer[iqindex++]=isample;
+ iqbuffer[iqindex++]=qsample>>16;
+ iqbuffer[iqindex++]=qsample>>8;
+ iqbuffer[iqindex++]=qsample;
+
+ if(iqindex>=sizeof(iqbuffer)) {
+ // insert the sequence
+ iqbuffer[0]=tx_iq_sequence>>24;
+ iqbuffer[1]=tx_iq_sequence>>16;
+ iqbuffer[2]=tx_iq_sequence>>8;
+ iqbuffer[3]=tx_iq_sequence;
+
+ // send the buffer
+ if(sendto(data_socket,iqbuffer,sizeof(iqbuffer),0,(struct sockaddr*)&iq_addr,iq_addr_length)<0) {
+ fprintf(stderr,"sendto socket failed for iq\n");
+ exit(1);
+ }
+ iqindex=4;
+ tx_iq_sequence++;
+ }
+
+ }
+ //Spectrum(CHANNEL_TX, 0, 0, micrightoutputbuffer, micleftoutputbuffer);
+ Spectrum0(1, CHANNEL_TX, 0, 0, micoutputbuffer);
+ micsamples=0;
+ }
+#ifdef ECHO_MIC
+ audiobuffer[audioindex++]=micsample>>8;
+ audiobuffer[audioindex++]=micsample;
+ audiobuffer[audioindex++]=micsample>>8;
+ audiobuffer[audioindex++]=micsample;
+
+ if(audioindex>=sizeof(audiobuffer)) {
+ // insert the sequence
+ audiobuffer[0]=audiosequence>>24;
+ audiobuffer[1]=audiosequence>>16;
+ audiobuffer[2]=audiosequence>>8;
+ audiobuffer[3]=audiosequence;
+ // send the buffer
+ if(sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length)<0) {
+ fprintf(stderr,"sendto socket failed for audio\n");
+ exit(1);
+ }
+ audioindex=4;
+ audiosequence++;
+ }
+#endif
+ }
+ }
+ } else {
+ }
+
+ if(running) {
+ if(send_general==1) {
+ new_protocol_general();
+ send_general=0;
+ }
+ if(send_high_priority==1) {
+ new_protocol_high_priority(1,isTransmitting(),tune==0?drive:tune_drive);
+ send_high_priority=0;
+ }
+ }
+
+ }
+
+ close(data_socket);
+}
+
+void* new_protocol_timer_thread(void* arg) {
+ int count=0;
+fprintf(stderr,"new_protocol_timer_thread\n");
+ while(running) {
+ usleep(100000); // 100ms
+ if(running) {
+ if(count==0) {
+ new_protocol_transmit_specific();
+ count=1;
+ } else {
+ new_protocol_receive_specific();
+ count=0;
+ }
+ }
+ }
+}
--- /dev/null
+
+// port definitions from host
+#define GENERAL_REGISTERS_FROM_HOST_PORT 1024
+#define PROGRAMMING_FROM_HOST_PORT 1024
+#define RECEIVER_SPECIFIC_REGISTERS_FROM_HOST_PORT 1025
+#define TRANSMITTER_SPECIFIC_REGISTERS_FROM_HOST_PORT 1026
+#define HIGH_PRIORITY_FROM_HOST_PORT 1027
+#define AUDIO_FROM_HOST_PORT 1028
+#define TX_IQ_FROM_HOST_PORT 1029
+
+// port definitions to host
+#define COMMAND_RESPONCE_TO_HOST_PORT 1024
+#define HIGH_PRIORITY_TO_HOST_PORT 1025
+#define MIC_LINE_TO_HOST_PORT 1026
+#define WIDE_BAND_TO_HOST_PORT 1027
+#define RX_IQ_TO_HOST_PORT 1035
+
+#define BUFFER_SIZE 1024
+
+#define modeLSB 0
+#define modeUSB 1
+#define modeDSB 2
+#define modeCWL 3
+#define modeCWU 4
+#define modeFMN 5
+#define modeAM 6
+#define modeDIGU 7
+#define modeSPEC 8
+#define modeDIGL 9
+#define modeSAM 10
+#define modeDRM 11
+
+extern int data_socket;
+extern sem_t response_sem;
+
+extern long response_sequence;
+extern int response;
+
+extern unsigned int exciter_power;
+extern unsigned int alex_forward_power;
+extern unsigned int alex_reverse_power;
+
+void new_protocol_init(int rx,int pixels);
+void new_protocol_stop();
+
+void filter_board_changed();
+void pa_changed();
+void tuner_changed();
+void cw_changed();
+
+void set_attenuation(int value);
+int get_attenuation();
+
+void set_alex_rx_antenna(unsigned long v);
+void set_alex_tx_antenna(unsigned long v);
+void set_alex_attenuation(unsigned long v);
+
+void setMox(int state);
+int getMox();
+void setTune(int state);
+int getTune();
+int isTransmitting();
+
+double getDrive();
+void setDrive(double d);
+double getTuneDrive();
+void setTuneDrive(double d);
+
+void setSampleRate(int rate);
+int getSampleRate();
+void setFrequency(long long f);
+long long getFrequency();
+void setMode(int m);
+int getMode();
+void setFilter(int low,int high);
+int getFilterLow();
+int getFilterHigh();
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+#include <sys/stat.h>
+#include <ifaddrs.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <time.h>
+#include <math.h>
+#include <errno.h>
+
+
+#include "discovered.h"
+#include "new_protocol.h"
+#include "new_protocol.h"
+
+static long sequence;
+static long block_sequence;
+
+static struct sockaddr_in program_addr;
+static int program_addr_length;
+
+static char* source;
+static long blocks;
+
+static pthread_t programmer_thread_id;
+static pthread_t programmer_response_thread_id;
+
+static int running;
+
+void *programmer_thread(void *arg);
+void *programmer_response_thread(void *arg);
+
+void new_protocol_programmer(char *filename ) {
+ int rc;
+
+ fprintf(stderr,"new_protocol_programmer: %s\n",filename);
+
+ sequence=0L;
+ block_sequence=0L;
+
+ DISCOVERED* d=&discovered[selected_device];
+
+ memcpy(&program_addr,&d->address,d->address_length);
+ program_addr_length=d->address_length;
+ program_addr.sin_port=htons(PROGRAMMING_FROM_HOST_PORT);
+
+ FILE *fp;
+ long length;
+
+ fp=fopen(filename,"rb");
+
+ if(fp==NULL) {
+ fprintf(stderr, "file %s not found!\n", filename);
+ exit(-1);
+ }
+
+ fseek(fp,0L,SEEK_END);
+ length=ftell(fp);
+ fseek(fp,0L,SEEK_SET);
+ fprintf(stderr,"the file's length is %ld bytes\n",length);
+
+ long source_size=((length+511)/512)*512;
+ fprintf(stderr,"allocating %ld bytes\n",source_size);
+ source=(char *)malloc(source_size);
+
+ blocks=source_size/256;
+
+ // read the file in
+ int r;
+ int b=0;
+ while((r==fread(&source[b],sizeof(char),512, fp))>0) {
+ b+=r;
+ }
+
+ fclose(fp);
+
+ // start the thread to program
+ rc=pthread_create(&programmer_thread_id,NULL,programmer_thread,NULL);
+ if(rc != 0) {
+ fprintf(stderr,"pthread_create failed on programmer_thread: rc=%d\n", rc);
+ exit(-1);
+ }
+
+}
+
+void programmer_erase() {
+ char buffer[60];
+
+ fprintf(stderr,"programmer_erase\n");
+ memset(buffer, 0, sizeof(buffer));
+
+ buffer[0]=sequence>>24;
+ buffer[1]=sequence>>16;
+ buffer[2]=sequence>>8;
+ buffer[3]=sequence;
+
+ buffer[4]=0x04; // Erase command
+
+ if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&program_addr,program_addr_length)<0) {
+ fprintf(stderr,"sendto socket failed for erase\n");
+ exit(1);
+ }
+
+}
+
+void programmer_send_block(long block) {
+ char buffer[265];
+
+ fprintf(stderr,"programmer_send_block: %ld\n",block);
+
+ memset(buffer, 0, sizeof(buffer));
+
+ buffer[0]=block_sequence>>24;
+ buffer[1]=block_sequence>>16;
+ buffer[2]=block_sequence>>8;
+ buffer[3]=block_sequence;
+
+ buffer[4]=0x05; // Program command
+
+
+ buffer[5]=blocks>>24;
+ buffer[6]=blocks>>16;
+ buffer[7]=blocks>>8;
+ buffer[8]=blocks;
+
+
+ // copy a block (256 bytes)
+ memcpy(&buffer[9],&source[block*256],256);
+
+ if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&program_addr,program_addr_length)<0) {
+ fprintf(stderr,"sendto socket failed for erase\n");
+ exit(1);
+ }
+}
+
+void *programmer_thread(void *arg) {
+
+ int result;
+ struct timespec ts;
+
+ fprintf(stderr,"programmer_thread\n");
+ programmer_erase();
+
+ // wait for the response to the erase command
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec+=120; // wait for 30 seconds
+ result=sem_timedwait(&response_sem,&ts);
+ if(result==-1) {
+ if(errno == ETIMEDOUT) {
+ fprintf(stderr,"timedout waiting for response for erase (start)\n");
+ exit(1);
+ } else {
+ fprintf(stderr,"sem_timedwait failed for response for erase (start): %d\n",errno);
+ exit(1);
+ }
+ }
+ if(response!=0x03) {
+ fprintf(stderr,"response error %d for erase (start)\n", response);
+ exit(1);
+ }
+
+ // wait for the erase to complete
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec+=120; // wait for 30 seconds
+ result=sem_timedwait(&response_sem,&ts);
+ if(result==-1) {
+ if(errno == ETIMEDOUT) {
+ fprintf(stderr,"timedout waiting for response for erase (complete)\n");
+ exit(1);
+ } else {
+ fprintf(stderr,"sem_timedwait failed for response for erase (complete): %d\n",errno);
+ exit(1);
+ }
+ }
+ if(response!=0x03) {
+ fprintf(stderr,"response error %d for erase (complete)\n", response);
+ exit(1);
+ }
+
+ long b=0;
+
+ while(b<blocks) {
+ programmer_send_block(b);
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec+=5; // wait for 5 seconds
+ result=sem_timedwait(&response_sem,&ts);
+ if(result==-1) {
+ if(errno == ETIMEDOUT) {
+ fprintf(stderr,"timedout waiting for response for sent block\n");
+ exit(1);
+ } else {
+ fprintf(stderr,"sem_timedwait failed for response for sent block: %d\n",errno);
+ exit(1);
+ }
+ }
+ if(response!=0x04) {
+ fprintf(stderr,"response error %d waiting for sent block\n", response);
+ exit(1);
+ }
+ block_sequence++;
+ }
+
+}
--- /dev/null
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <semaphore.h>
+#include "new_protocol.h"
+#include "panadapter.h"
+#include "vfo.h"
+
+static GtkWidget *panadapter;
+static cairo_surface_t *panadapter_surface = NULL;
+
+static float* samples;
+
+static gint last_x;
+static gboolean has_moved=FALSE;
+static gboolean pressed=FALSE;
+
+static float panadapter_max=-60.0;
+static float panadapter_min=-160.0;
+
+static gfloat hz_per_pixel;
+static gfloat filter_left;
+static gfloat filter_right;
+
+static int display_width;
+static int panadapter_height;
+
+static void
+panadapter_clear_surface (void)
+{
+ cairo_t *cr;
+
+ cr = cairo_create (panadapter_surface);
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+}
+
+/* Create a new surface of the appropriate size to store our scribbles */
+static gboolean
+panadapter_configure_event_cb (GtkWidget *widget,
+ GdkEventConfigure *event,
+ gpointer data)
+{
+ if (panadapter_surface)
+ cairo_surface_destroy (panadapter_surface);
+
+ panadapter_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+ CAIRO_CONTENT_COLOR,
+ gtk_widget_get_allocated_width (widget),
+ gtk_widget_get_allocated_height (widget));
+
+ /* Initialize the surface to white */
+ panadapter_clear_surface ();
+
+ /* We've handled the configure event, no need for further processing. */
+ return TRUE;
+}
+
+/* Redraw the screen from the surface. Note that the ::draw
+ * signal receives a ready-to-be-used cairo_t that is already
+ * clipped to only draw the exposed areas of the widget
+ */
+static gboolean
+panadapter_draw_cb (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer data)
+{
+ cairo_set_source_surface (cr, panadapter_surface, 0, 0);
+ cairo_paint (cr);
+
+ return FALSE;
+}
+
+static gboolean
+panadapter_button_press_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
+{
+ int x=(int)event->x;
+ if (event->button == 1) {
+ last_x=(int)event->x;
+ has_moved=FALSE;
+ pressed=TRUE;
+ }
+ return TRUE;
+}
+
+static gboolean
+panadapter_button_release_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
+{
+ int x=(int)event->x;
+ if (event->button == 1) {
+ if(has_moved) {
+ // drag
+ vfo_move((int)((float)(x-last_x)*hz_per_pixel));
+ } else {
+ // move to this frequency
+ vfo_move((int)((float)(x-(display_width/2))*hz_per_pixel));
+ }
+ last_x=x;
+ pressed=FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+panadapter_motion_notify_event_cb (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer data)
+{
+ int x, y;
+ GdkModifierType state;
+ gdk_window_get_device_position (event->window,
+ event->device,
+ &x,
+ &y,
+ &state);
+ if((state & GDK_BUTTON1_MASK == GDK_BUTTON1_MASK) || pressed) {
+ int moved=last_x-x;
+ vfo_move((int)((float)moved*hz_per_pixel));
+ last_x=x;
+ has_moved=TRUE;
+ }
+
+ return TRUE;
+}
+
+static void
+close_window (void)
+{
+ if (panadapter_surface)
+ cairo_surface_destroy (panadapter_surface);
+
+ gtk_main_quit ();
+}
+
+void panadapter_update(float *data,int tx) {
+ int i;
+ int result;
+
+ float saved_max;
+ float saved_min;
+ gfloat saved_hz_per_pixel;
+
+ samples=data;
+ //if(result==1) {
+ if(panadapter_surface) {
+
+ if(tx) {
+ saved_max=panadapter_max;
+ saved_min=panadapter_min;
+ saved_hz_per_pixel=hz_per_pixel;
+
+ panadapter_max=30;
+ panadapter_min=-100;
+ hz_per_pixel=192000.0/(double)display_width;
+ }
+
+ //clear_panadater_surface();
+ cairo_t *cr;
+ cr = cairo_create (panadapter_surface);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ // filter
+ cairo_set_source_rgb (cr, 0.25, 0.25, 0.25);
+ filter_left=(double)display_width/2.0+((double)getFilterLow()/hz_per_pixel);
+ filter_right=(double)display_width/2.0+((double)getFilterHigh()/hz_per_pixel);
+ cairo_rectangle(cr, filter_left, 0.0, filter_right-filter_left, (double)panadapter_height);
+ cairo_fill(cr);
+
+ // plot the levels
+ int V = (int)(panadapter_max - panadapter_min);
+ int numSteps = V / 20;
+ for (i = 1; i < numSteps; i++) {
+ int num = panadapter_max - i * 20;
+ int y = (int)floor((panadapter_max - num) * panadapter_height / V);
+
+ cairo_set_source_rgb (cr, 0, 1, 1);
+ cairo_set_line_width(cr, 1.0);
+ cairo_move_to(cr,0.0,(double)y);
+ cairo_line_to(cr,(double)display_width,(double)y);
+
+ cairo_set_source_rgb (cr, 0, 1, 1);
+ cairo_select_font_face(cr, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size(cr, 12);
+ char v[32];
+ sprintf(v,"%d dBm",num);
+ cairo_move_to(cr, 1, (double)y);
+ cairo_show_text(cr, v);
+ }
+ cairo_stroke(cr);
+
+ // plot frequency markers
+ long f;
+ for(i=0;i<display_width;i++) {
+ f = getFrequency() - ((long) getSampleRate() / 2) + (long) (hz_per_pixel * i);
+ if (f > 0) {
+ if ((f % 20000) < (long) hz_per_pixel) {
+ cairo_set_source_rgb (cr, 0, 1, 1);
+ cairo_set_line_width(cr, 1.0);
+ cairo_move_to(cr,(double)i,0.0);
+ cairo_line_to(cr,(double)i,(double)panadapter_height);
+
+ cairo_set_source_rgb (cr, 0, 1, 1);
+ cairo_select_font_face(cr, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size(cr, 12);
+ char v[32];
+ sprintf(v,"%0ld.%03ld",f/1000000,(f%1000000)/1000);
+ cairo_move_to(cr, (double)i, (double)(panadapter_height-10));
+ cairo_show_text(cr, v);
+ }
+ }
+ }
+ cairo_stroke(cr);
+
+ // cursor
+ cairo_set_source_rgb (cr, 1, 0, 0);
+ cairo_set_line_width(cr, 1.0);
+ cairo_move_to(cr,(double)display_width/2.0,0.0);
+ cairo_line_to(cr,(double)display_width/2.0,(double)panadapter_height);
+ cairo_stroke(cr);
+
+ // signal
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_set_line_width(cr, 1.0);
+
+ double s1,s2;
+ samples[0]=panadapter_min-20;
+ samples[display_width-1]=panadapter_min-20;
+ for(i=1;i<display_width;i++) {
+ s1=samples[i-1]+get_attenuation();
+ s1 = floor((panadapter_max - s1)
+ * (double) panadapter_height
+ / (panadapter_max - panadapter_min));
+ s2=samples[i]+get_attenuation();
+ s2 = floor((panadapter_max - s2)
+ * (double) panadapter_height
+ / (panadapter_max - panadapter_min));
+ cairo_move_to(cr, (double)i-1, s1);
+ cairo_line_to(cr, (double)i, s2);
+ }
+ cairo_stroke(cr);
+ //cairo_close_path(cr);
+ //cairo_fill(cr);
+
+ cairo_destroy (cr);
+ gtk_widget_queue_draw (panadapter);
+
+ if(tx) {
+ panadapter_max=saved_max;
+ panadapter_min=saved_min;
+ hz_per_pixel=saved_hz_per_pixel;
+ }
+
+ }
+ //}
+}
+
+GtkWidget* panadapter_init(int width,int height) {
+ //GtkWidget *panadapter_frame;
+
+ display_width=width;
+ panadapter_height=height;
+
+ samples=malloc(display_width*sizeof(float));
+ hz_per_pixel=(double)getSampleRate()/(double)display_width;
+
+ //panadapter_frame = gtk_frame_new (NULL);
+ panadapter = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (panadapter, width, height);
+
+ //gtk_container_add (GTK_CONTAINER (panadapter_frame), panadapter);
+
+ /* Signals used to handle the backing surface */
+ g_signal_connect (panadapter, "draw",
+ G_CALLBACK (panadapter_draw_cb), NULL);
+ g_signal_connect (panadapter,"configure-event",
+ G_CALLBACK (panadapter_configure_event_cb), NULL);
+
+ /* Event signals */
+ g_signal_connect (panadapter, "motion-notify-event",
+ G_CALLBACK (panadapter_motion_notify_event_cb), NULL);
+ g_signal_connect (panadapter, "button-press-event",
+ G_CALLBACK (panadapter_button_press_event_cb), NULL);
+ g_signal_connect (panadapter, "button-release-event",
+ G_CALLBACK (panadapter_button_release_event_cb), NULL);
+
+ /* Ask to receive events the drawing area doesn't normally
+ * subscribe to. In particular, we need to ask for the
+ * button press and motion notify events that want to handle.
+ */
+ gtk_widget_set_events (panadapter, gtk_widget_get_events (panadapter)
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_BUTTON1_MOTION_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK);
+
+ //return panadapter_frame;
+ return panadapter;
+}
--- /dev/null
+void panadapter_update(float* data,int tx);
+
+GtkWidget* panadapter_init(int width,int height);
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "property.h"
+
+PROPERTY* properties;
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief Load Properties
+*
+* @param filename
+*/
+void loadProperties(char* filename) {
+ char string[80];
+ char* name;
+ char* value;
+ FILE* f=fopen(filename,"r");
+ properties=NULL;
+ PROPERTY* property;
+
+ fprintf(stderr,"loadProperties: %s\n",filename);
+
+ if(f) {
+ while(fgets(string,sizeof(string),f)) {
+ if(string[0]!='#') {
+ name=strtok(string,"=");
+ value=strtok(NULL,"\n");
+ property=malloc(sizeof(PROPERTY));
+ property->name=malloc(strlen(name)+1);
+ strcpy(property->name,name);
+ property->value=malloc(strlen(value)+1);
+ strcpy(property->value,value);
+ property->next_property=properties;
+ properties=property;
+ }
+ }
+ fclose(f);
+ }
+}
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief Save Properties
+*
+* @param filename
+*/
+void saveProperties(char* filename) {
+ PROPERTY* property=properties;
+ FILE* f=fopen(filename,"w+");
+ char line[512];
+ if(!f) {
+ fprintf(stderr,"can't open %s\n",filename);
+ exit(1);
+ }
+ while(property) {
+ sprintf(line,"%s=%s\n",property->name,property->value);
+ fwrite(line,1,strlen(line),f);
+ property=property->next_property;
+ }
+ fclose(f);
+}
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief Get Properties
+*
+* @param name
+*
+* @return
+*/
+char* getProperty(char* name) {
+ char* value=NULL;
+ PROPERTY* property=properties;
+ while(property) {
+ if(strcmp(name,property->name)==0) {
+ value=property->value;
+ break;
+ }
+ property=property->next_property;
+ }
+ return value;
+}
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief Set Properties
+*
+* @param name
+* @param value
+*/
+void setProperty(char* name,char* value) {
+ PROPERTY* property=properties;
+ while(property) {
+ if(strcmp(name,property->name)==0) {
+ break;
+ }
+ property=property->next_property;
+ }
+ if(property) {
+ // just update
+ free(property->value);
+ property->value=malloc(strlen(value)+1);
+ strcpy(property->value,value);
+ } else {
+ // new property
+ property=malloc(sizeof(PROPERTY));
+ property->name=malloc(strlen(name)+1);
+ strcpy(property->name,name);
+ property->value=malloc(strlen(value)+1);
+ strcpy(property->value,value);
+ property->next_property=properties;
+ properties=property;
+ }
+}
+
--- /dev/null
+typedef struct _PROPERTY PROPERTY;
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief Property structure
+*/
+struct _PROPERTY {
+ char* name;
+ char* value;
+ PROPERTY* next_property;
+};
+
+void loadProperties(char* filename);
+char* getProperty(char* name);
+void setProperty(char* name,char* value);
+
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "radio.h"
+#include "agc.h"
+#include "band.h"
+#include "discovered.h"
+#include "property.h"
+
+char property_path[128];
+
+int sample_rate=48000;
+int filter_board=ALEX;
+int pa=PA_ENABLED;
+int apollo_tuner=0;
+
+int panadapter_high=-80;
+int panadapter_low=-160;
+
+int waterfall_high=-100;
+int waterfall_low=-150;
+int waterfall_automatic=1;
+
+double volume=0.2;
+double mic_gain=1.5;
+
+int orion_mic=MIC_BOOST|ORION_MIC_PTT_ENABLED|ORION_MIC_PTT_TIP_BIAS_RING|ORION_MIC_BIAS_ENABLED;
+
+int agc=AGC_MEDIUM;
+double agc_gain=60.0;
+
+int nr=0;
+int nb=0;
+int anf=0;
+int snb=0;
+
+int cwPitch=600;
+
+int tune_drive=6;
+int drive=60;
+
+int receivers=2;
+int adc[2]={0,1};
+
+int locked=0;
+
+int step=100;
+
+int byte_swap=0;
+
+int cw_keys_reversed=0; // 0=disabled 1=enabled
+int cw_keyer_speed=12; // 1-60 WPM
+int cw_keyer_mode=KEYER_STRAIGHT;
+int cw_keyer_weight=30; // 0-100
+int cw_keyer_spacing=0; // 0=on 1=off
+int cw_keyer_internal=1; // 0=external 1=internal
+int cw_keyer_sidetone_volume=127; // 0-127
+int cw_keyer_ptt_delay=20; // 0-255ms
+int cw_keyer_hang_time=300; // ms
+int cw_keyer_sidetone_frequency=400; // Hz
+int cw_breakin=1; // 0=disabled 1=enabled
+
+void radioRestoreState() {
+ char *value;
+ value=getProperty("sample_rate");
+ if(value) sample_rate=atoi(value);
+ value=getProperty("filter_board");
+ if(value) filter_board=atoi(value);
+ value=getProperty("apollo_tuner");
+ if(value) apollo_tuner=atoi(value);
+ value=getProperty("pa");
+ if(value) pa=atoi(value);
+ value=getProperty("panadapter_high");
+ if(value) panadapter_high=atoi(value);
+ value=getProperty("panadapter_low");
+ if(value) panadapter_low=atoi(value);
+ value=getProperty("waterfall_high");
+ if(value) waterfall_high=atoi(value);
+ value=getProperty("waterfall_low");
+ if(value) waterfall_low=atoi(value);
+ value=getProperty("waterfall_automatic");
+ if(value) waterfall_automatic=atoi(value);
+ value=getProperty("volume");
+ if(value) volume=atof(value);
+ value=getProperty("mic_gain");
+ if(value) mic_gain=atof(value);
+ value=getProperty("orion_mic");
+ if(value) orion_mic=atof(value);
+ value=getProperty("nr");
+ if(value) nr=atoi(value);
+ value=getProperty("nb");
+ if(value) nb=atoi(value);
+ value=getProperty("anf");
+ if(value) anf=atoi(value);
+ value=getProperty("snb");
+ if(value) snb=atoi(value);
+ value=getProperty("agc");
+ if(value) agc=atoi(value);
+ value=getProperty("agc_gain");
+ if(value) agc_gain=atof(value);
+ value=getProperty("step");
+ if(value) step=atoi(value);
+ value=getProperty("byte_swap");
+ if(value) byte_swap=atoi(value);
+ value=getProperty("cw_keys_reversed");
+ if(value) cw_keys_reversed=atoi(value);
+ value=getProperty("cw_keyer_speed");
+ if(value) cw_keyer_speed=atoi(value);
+ value=getProperty("cw_keyer_mode");
+ if(value) cw_keyer_mode=atoi(value);
+ value=getProperty("cw_keyer_weight");
+ if(value) cw_keyer_weight=atoi(value);
+ value=getProperty("cw_keyer_spacing");
+ if(value) cw_keyer_spacing=atoi(value);
+ value=getProperty("cw_keyer_internal");
+ if(value) cw_keyer_internal=atoi(value);
+ value=getProperty("cw_keyer_sidetone_volume");
+ if(value) cw_keyer_sidetone_volume=atoi(value);
+ value=getProperty("cw_keyer_ptt_delay");
+ if(value) cw_keyer_ptt_delay=atoi(value);
+ value=getProperty("cw_keyer_hang_time");
+ if(value) cw_keyer_hang_time=atoi(value);
+ value=getProperty("cw_keyer_sidetone_frequency");
+ if(value) cw_keyer_sidetone_frequency=atoi(value);
+ value=getProperty("cw_breakin");
+ if(value) cw_breakin=atoi(value);
+
+
+ bandRestoreState();
+}
+
+void radioSaveState() {
+ char value[80];
+ sprintf(value,"%d",sample_rate);
+ setProperty("sample_rate",value);
+ sprintf(value,"%d",filter_board);
+ setProperty("filter_board",value);
+ sprintf(value,"%d",apollo_tuner);
+ setProperty("apollo_tuner",value);
+ sprintf(value,"%d",pa);
+ setProperty("pa",value);
+ sprintf(value,"%d",panadapter_high);
+ setProperty("panadapter_high",value);
+ sprintf(value,"%d",panadapter_low);
+ setProperty("panadapter_low",value);
+ sprintf(value,"%d",waterfall_high);
+ setProperty("waterfall_high",value);
+ sprintf(value,"%d",waterfall_low);
+ setProperty("waterfall_low",value);
+ sprintf(value,"%d",waterfall_automatic);
+ setProperty("waterfall_automatic",value);
+ sprintf(value,"%f",volume);
+ setProperty("volume",value);
+ sprintf(value,"%f",mic_gain);
+ setProperty("mic_gain",value);
+ sprintf(value,"%d",orion_mic);
+ setProperty("orion_mic",value);
+ sprintf(value,"%d",nr);
+ setProperty("nr",value);
+ sprintf(value,"%d",nb);
+ setProperty("nb",value);
+ sprintf(value,"%d",anf);
+ setProperty("anf",value);
+ sprintf(value,"%d",snb);
+ setProperty("snb",value);
+ sprintf(value,"%d",agc);
+ setProperty("agc",value);
+ sprintf(value,"%f",agc_gain);
+ setProperty("agc_gain",value);
+ sprintf(value,"%d",step);
+ setProperty("step",value);
+ sprintf(value,"%d",byte_swap);
+ setProperty("byte_swap",value);
+ sprintf(value,"%d",cw_keys_reversed);
+ setProperty("cw_keys_reversed",value);
+ sprintf(value,"%d",cw_keyer_speed);
+ setProperty("cw_keyer_speed",value);
+ sprintf(value,"%d",cw_keyer_mode);
+ setProperty("cw_keyer_mode",value);
+ sprintf(value,"%d",cw_keyer_weight);
+ setProperty("cw_keyer_weight",value);
+ sprintf(value,"%d",cw_keyer_spacing);
+ setProperty("cw_keyer_spacing",value);
+ sprintf(value,"%d",cw_keyer_internal);
+ setProperty("cw_keyer_internal",value);
+ sprintf(value,"%d",cw_keyer_sidetone_volume);
+ setProperty("cw_keyer_sidetone_volume",value);
+ sprintf(value,"%d",cw_keyer_ptt_delay);
+ setProperty("cw_keyer_ptt_delay",value);
+ sprintf(value,"%d",cw_keyer_hang_time);
+ setProperty("cw_keyer_hang_time",value);
+ sprintf(value,"%d",cw_keyer_sidetone_frequency);
+ setProperty("cw_keyer_sidetone_frequency",value);
+ sprintf(value,"%d",cw_breakin);
+ setProperty("cw_breakin",value);
+
+ bandSaveState();
+}
--- /dev/null
+
+#define MIC_IN 0x00
+#define LINE_IN 0x01
+#define MIC_BOOST 0x02
+#define ORION_MIC_PTT_ENABLED 0x00
+#define ORION_MIC_PTT_DISABLED 0x04
+#define ORION_MIC_PTT_RING_BIAS_TIP 0x00
+#define ORION_MIC_PTT_TIP_BIAS_RING 0x08
+#define ORION_MIC_BIAS_DISABLED 0x00
+#define ORION_MIC_BIAS_ENABLED 0x10
+
+extern char property_path[];
+
+#define NONE 0
+
+#define ALEX 1
+#define APOLLO 2
+
+#define PA_DISABLED 0
+#define PA_ENABLED 1
+
+#define APOLLO_TUNER 1
+
+#define KEYER_STRAIGHT 0
+#define KEYER_MODE_A 1
+#define KEYER_MODE_B 2
+
+extern int sample_rate;
+extern int filter_board;
+extern int pa;
+extern int apollo_tuner;
+
+extern int panadapter_high;
+extern int panadapter_low;
+
+extern int waterfall_high;
+extern int waterfall_low;
+extern int waterfall_automatic;
+
+extern double volume;
+extern double mic_gain;
+extern int agc;
+extern double agc_gain;
+
+extern int nr;
+extern int nb;
+extern int anf;
+extern int snb;
+
+extern int cwPitch;
+
+extern int orion_mic;
+
+extern int tune_drive;
+extern int drive;
+
+int receivers;
+int adc[2];
+
+int locked;
+
+extern int step;
+
+extern int byte_swap;
+
+extern int cw_keys_reversed;
+extern int cw_keyer_speed;
+extern int cw_keyer_mode;
+extern int cw_keyer_weight;
+extern int cw_keyer_spacing;
+extern int cw_keyer_internal;
+extern int cw_keyer_sidetone_volume;
+extern int cw_keyer_ptt_delay;
+extern int cw_keyer_hang_time;
+extern int cw_keyer_sidetone_frequency;
+extern int cw_breakin;
+
+extern void radioRestoreState();
+extern void radioSaveState();
+
--- /dev/null
+#include <stdio.h>
+#include <pigpio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sched.h>
+#include <pthread.h>
+#include <wiringPi.h>
+
+#include "rotary_encoder.h"
+#include "main.h"
+
+#define SYSFS_GPIO_DIR "/sys/class/gpio"
+
+#define RASPBERRYPI_VFO_ENCODER_A 14
+#define RASPBERRYPI_VFO_ENCODER_B 15
+
+#define ODROID_VFO_ENCODER_A 108
+#define ODROID_VFO_ENCODER_B 97
+#define ODROID_VFO_ENCODER_A_PIN 23
+#define ODROID_VFO_ENCODER_B_PIN 24
+
+#define AF_ENCODER_A 20
+#define AF_ENCODER_B 26
+#define AF_FUNCTION 21
+
+#define RF_ENCODER_A 16
+#define RF_ENCODER_B 19
+#define RF_FUNCTION 13
+
+#define FUNCTION 12
+#define BAND 6
+
+static int VFO_ENCODER_A=14;
+static int VFO_ENCODER_B=15;
+
+static int VFO_ENCODER_A_PIN=0;
+static int VFO_ENCODER_B_PIN=0;
+
+static volatile int vfoEncoderPos;
+static volatile int afEncoderPos;
+static volatile int afFunction;
+static volatile int rfEncoderPos;
+static volatile int rfFunction;
+static volatile int function;
+static volatile int band;
+
+static void afFunctionAlert(int gpio, int level, uint32_t tick) {
+ afFunction=(level==0);
+}
+
+static void rfFunctionAlert(int gpio, int level, uint32_t tick) {
+ rfFunction=(level==0);
+}
+
+static void functionAlert(int gpio, int level, uint32_t tick) {
+ function=(level==0);
+}
+
+static void bandAlert(int gpio, int level, uint32_t tick) {
+ band=(level==0);
+}
+
+static void vfoEncoderPulse(int gpio, int level, unsigned int tick) {
+ static int levA=0, levB=0, lastGpio = -1;
+
+//fprintf(stderr,"vfoEncoderPulse:%d=%d\n",gpio,level);
+ if (gpio == VFO_ENCODER_A) levA = level; else levB = level;
+
+ if (gpio != lastGpio) /* debounce */
+ {
+ lastGpio = gpio;
+
+ if ((gpio == VFO_ENCODER_A) && (level == 0))
+ {
+ if (!levB) ++vfoEncoderPos;
+ }
+ else if ((gpio == VFO_ENCODER_B) && (level == 1))
+ {
+ if (levA) --vfoEncoderPos;
+ }
+ }
+}
+
+static void afEncoderPulse(int gpio, int level, uint32_t tick)
+{
+ static int levA=0, levB=0, lastGpio = -1;
+
+ if (gpio == AF_ENCODER_A) levA = level; else levB = level;
+
+ if (gpio != lastGpio) /* debounce */
+ {
+ lastGpio = gpio;
+
+ if ((gpio == AF_ENCODER_A) && (level == 0))
+ {
+ if (!levB) ++afEncoderPos;
+ }
+ else if ((gpio == AF_ENCODER_B) && (level == 1))
+ {
+ if (levA) --afEncoderPos;
+ }
+ }
+}
+
+static void rfEncoderPulse(int gpio, int level, uint32_t tick)
+{
+ static int levA=0, levB=0, lastGpio = -1;
+
+ if (gpio == RF_ENCODER_A) levA = level; else levB = level;
+
+ if (gpio != lastGpio) /* debounce */
+ {
+ lastGpio = gpio;
+
+ if ((gpio == RF_ENCODER_A) && (level == 0))
+ {
+ if (!levB) ++rfEncoderPos;
+ }
+ else if ((gpio == RF_ENCODER_B) && (level == 1))
+ {
+ if (levA) --rfEncoderPos;
+ }
+ }
+}
+
+void interruptB(void) {
+ vfoEncoderPulse(VFO_ENCODER_B,digitalRead(VFO_ENCODER_B_PIN),0);
+}
+
+void interruptA(void) {
+ vfoEncoderPulse(VFO_ENCODER_A,digitalRead(VFO_ENCODER_A_PIN),0);
+}
+
+int encoder_init() {
+
+ if(strcmp(unameData.nodename,"raspberrypi")==0) {
+
+ VFO_ENCODER_A=RASPBERRYPI_VFO_ENCODER_A;
+ VFO_ENCODER_B=RASPBERRYPI_VFO_ENCODER_B;
+ VFO_ENCODER_A_PIN=0;
+ VFO_ENCODER_B_PIN=0;
+
+ fprintf(stderr,"encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
+
+ if(gpioInitialise()<0) {
+ fprintf(stderr,"Cannot initialize GPIO\n");
+ return -1;
+ }
+
+ gpioSetMode(VFO_ENCODER_A, PI_INPUT);
+ gpioSetMode(VFO_ENCODER_B, PI_INPUT);
+ gpioSetPullUpDown(VFO_ENCODER_A, PI_PUD_UP);
+ gpioSetPullUpDown(VFO_ENCODER_B, PI_PUD_UP);
+ gpioSetAlertFunc(VFO_ENCODER_A, vfoEncoderPulse);
+ gpioSetAlertFunc(VFO_ENCODER_B, vfoEncoderPulse);
+ vfoEncoderPos=0;
+
+
+ gpioSetMode(AF_FUNCTION, PI_INPUT);
+ gpioSetPullUpDown(AF_FUNCTION,PI_PUD_UP);
+ gpioSetAlertFunc(AF_FUNCTION, afFunctionAlert);
+ afFunction=0;
+
+ gpioSetMode(AF_ENCODER_A, PI_INPUT);
+ gpioSetMode(AF_ENCODER_B, PI_INPUT);
+ gpioSetPullUpDown(AF_ENCODER_A, PI_PUD_OFF);
+ gpioSetPullUpDown(AF_ENCODER_B, PI_PUD_OFF);
+ gpioSetAlertFunc(AF_ENCODER_A, afEncoderPulse);
+ gpioSetAlertFunc(AF_ENCODER_B, afEncoderPulse);
+ afEncoderPos=0;
+
+ gpioSetMode(RF_FUNCTION, PI_INPUT);
+ gpioSetPullUpDown(RF_FUNCTION,PI_PUD_UP);
+ gpioSetAlertFunc(RF_FUNCTION, rfFunctionAlert);
+ rfFunction=0;
+
+ gpioSetMode(RF_ENCODER_A, PI_INPUT);
+ gpioSetMode(RF_ENCODER_B, PI_INPUT);
+ gpioSetPullUpDown(RF_ENCODER_A, PI_PUD_OFF);
+ gpioSetPullUpDown(RF_ENCODER_B, PI_PUD_OFF);
+ gpioSetAlertFunc(RF_ENCODER_A, rfEncoderPulse);
+ gpioSetAlertFunc(RF_ENCODER_B, rfEncoderPulse);
+ rfEncoderPos=0;
+
+ gpioSetMode(FUNCTION, PI_INPUT);
+ gpioSetPullUpDown(FUNCTION,PI_PUD_UP);
+ gpioSetAlertFunc(FUNCTION, functionAlert);
+
+ gpioSetMode(BAND, PI_INPUT);
+ gpioSetPullUpDown(BAND,PI_PUD_UP);
+ gpioSetAlertFunc(BAND, bandAlert);
+
+ } else if(strcmp(unameData.nodename,"odroid")==0) {
+
+ VFO_ENCODER_A=ODROID_VFO_ENCODER_A;
+ VFO_ENCODER_B=ODROID_VFO_ENCODER_B;
+ VFO_ENCODER_A_PIN=ODROID_VFO_ENCODER_A_PIN;
+ VFO_ENCODER_B_PIN=ODROID_VFO_ENCODER_B_PIN;
+
+ fprintf(stderr,"encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
+
+ if (wiringPiSetup () < 0) {
+ printf ("Unable to setup wiringPi: %s\n", strerror (errno));
+ return 1;
+ }
+
+ FILE *fp;
+
+ fp = popen("echo 97 > /sys/class/gpio/export\n", "r");
+ pclose(fp);
+ fp = popen("echo \"in\" > /sys/class/gpio/gpio97/direction\n", "r");
+ pclose(fp);
+ fp = popen("chmod 0666 /sys/class/gpio/gpio97/value\n", "r");
+ pclose(fp);
+
+ fp = popen("echo 108 > /sys/class/gpio/export\n", "r");
+ pclose(fp);
+ fp = popen("echo \"in\" > /sys/class/gpio/gpio108/direction\n", "r");
+ pclose(fp);
+ fp = popen("chmod 0666 /sys/class/gpio/gpio108/value\n", "r");
+ pclose(fp);
+
+ if ( wiringPiISR (24, INT_EDGE_BOTH, &interruptB) < 0 ) {
+ printf ("Unable to setup ISR: %s\n", strerror (errno));
+ return 1;
+ }
+
+ if ( wiringPiISR (23, INT_EDGE_BOTH, &interruptA) < 0 ) {
+ printf ("Unable to setup ISR: %s\n", strerror (errno));
+ return 1;
+ }
+ } else {
+ fprintf(stderr,"Unknown nodename: %s. Rotary Encoder not enabled.\n",unameData.nodename);
+ return 1;
+ }
+
+
+ return 0;
+}
+
+void encoder_close() {
+ if(strcmp(unameData.nodename,"odroid")==0) {
+ FILE *fp;
+ fp = popen("echo 97 > /sys/class/gpio/unexport\n", "r");
+ pclose(fp);
+ fp = popen("echo 108 > /sys/class/gpio/unexport\n", "r");
+ pclose(fp);
+ }
+}
+
+int vfo_encoder_get_pos() {
+ int pos=vfoEncoderPos;
+
+ if(strcmp(unameData.nodename,"raspberrypi")==0) {
+ if(pos<0 && pos>-12) {
+ pos=0;
+ } else if(pos>0 && pos<12) {
+ pos=0;
+ }
+ pos=pos/12;
+ vfoEncoderPos=vfoEncoderPos-(pos*12);
+ } else if(strcmp(unameData.nodename,"odroid")==0) {
+ vfoEncoderPos=0;
+ }
+ return pos;
+}
+
+int af_encoder_get_pos() {
+ int pos=afEncoderPos;
+ afEncoderPos=0;
+ return pos;
+}
+
+int af_function_get_state() {
+ return afFunction;
+}
+
+int rf_encoder_get_pos() {
+ int pos=rfEncoderPos;
+ rfEncoderPos=0;
+ return pos;
+}
+
+int rf_function_get_state() {
+ return rfFunction;
+}
+
+int function_get_state() {
+ return function;
+}
+
+int band_get_state() {
+ return band;
+}
--- /dev/null
+int encoder_init();
+void encoder_close();
+int vfo_encoder_get_pos();
+int af_encoder_get_pos();
+int af_function_get_state();
+
--- /dev/null
+#include <gtk/gtk.h>
+
+GtkWidget *splash_window;
+
+/* Close the splash screen */
+void splash_close()
+{
+ gtk_widget_destroy(splash_window);
+}
+
+
+void splash_show(char* image_name,int time,int width,int height)
+{
+ GtkWidget *image;
+ splash_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_size_request(splash_window, width, height);
+ gtk_window_set_decorated(GTK_WINDOW(splash_window), FALSE);
+ gtk_window_set_position(GTK_WINDOW(splash_window),GTK_WIN_POS_CENTER_ALWAYS);
+ gtk_window_set_resizable(GTK_WINDOW(splash_window), FALSE);
+ image=gtk_image_new_from_file(image_name);
+ gtk_container_add(GTK_CONTAINER(splash_window), image);
+ gtk_widget_show_all (splash_window);
+}
--- /dev/null
+
+extern GtkWidget* splash_window;
+
+void splash_close(void);
+void splash_show(char* image_name,int time,int width,int height);
--- /dev/null
+cd ~/pihpsdr
+sudo ~/pihpsdr/pihpsdr
--- /dev/null
+#include <gtk/gtk.h>
+#include <semaphore.h>
+#include <stdio.h>
+
+#include "toolbar.h"
+#include "mode.h"
+#include "filter.h"
+#include "bandstack.h"
+#include "band.h"
+#include "discovered.h"
+#include "new_protocol.h"
+#include "rotary_encoder.h"
+#include "vfo.h"
+#include "alex.h"
+#include "agc.h"
+#include "channel.h"
+#include "wdsp.h"
+#include "radio.h"
+#include "property.h"
+
+static int width;
+static int height;
+
+static int column=0;
+
+static GtkWidget *parent_window;
+static GtkWidget *toolbar;
+static GtkWidget *toolbar_bottom;
+static GtkWidget *toolbar_top;
+
+static GtkWidget *last_band;
+static GtkWidget *last_mode;
+static GtkWidget *last_filter;
+
+static GtkWidget *af_gain_label;
+static GtkWidget *audio_scale;
+static GtkWidget *agc_gain_label;
+static GtkWidget *agc_scale;
+static GtkWidget *mic_gain_label;
+static GtkWidget *mic_scale;
+static GtkWidget *drive_scale;
+static GtkWidget *tune_scale;
+
+static GdkRGBA white;
+static GdkRGBA gray;
+
+static void band_select_cb(GtkWidget *widget, gpointer data) {
+ GtkWidget *label;
+ int b=(int)data;
+ BANDSTACK_ENTRY *entry;
+ if(b==band_get_current()) {
+ entry=bandstack_entry_next();
+ } else {
+ BAND* band=band_set_current(b);
+ entry=bandstack_entry_get_current();
+ gtk_widget_override_background_color(last_band, GTK_STATE_NORMAL, &white);
+ last_band=widget;
+ gtk_widget_override_background_color(last_band, GTK_STATE_NORMAL, &gray);
+ }
+ setFrequency(entry->frequencyA);
+ setMode(entry->mode);
+ FILTER* band_filters=filters[entry->mode];
+ FILTER* band_filter=&band_filters[entry->filter];
+ setFilter(band_filter->low,band_filter->high);
+
+ BAND *band=band_get_current_band();
+ set_alex_rx_antenna(band->alexRxAntenna);
+ set_alex_tx_antenna(band->alexTxAntenna);
+ set_alex_attenuation(band->alexAttenuation);
+ vfo_update(NULL);
+}
+
+static void band_cb(GtkWidget *widget, gpointer data) {
+ GtkWidget *dialog=gtk_dialog_new_with_buttons("Band",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+ GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ GtkWidget *grid=gtk_grid_new();
+ gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+ gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+ GtkWidget *b;
+ int i;
+ for(i=0;i<BANDS;i++) {
+ BAND* band=band_get_band(i);
+ GtkWidget *b=gtk_button_new_with_label(band->title);
+ gtk_widget_override_background_color(b, GTK_STATE_NORMAL, &white);
+ gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
+ if(i==band_get_current()) {
+ gtk_widget_override_background_color(b, GTK_STATE_NORMAL, &gray);
+ last_band=b;
+ }
+ gtk_widget_show(b);
+ gtk_grid_attach(GTK_GRID(grid),b,i%5,i/5,1,1);
+ g_signal_connect(b,"clicked",G_CALLBACK(band_select_cb),(gpointer *)i);
+ }
+
+ gtk_container_add(GTK_CONTAINER(content),grid);
+
+ GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
+ gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
+ gtk_widget_show_all(dialog);
+
+ g_signal_connect_swapped (dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
+
+ int result=gtk_dialog_run(GTK_DIALOG(dialog));
+
+}
+
+static void mode_select_cb(GtkWidget *widget, gpointer data) {
+ int m=(int)data;
+ BANDSTACK_ENTRY *entry;
+ entry=bandstack_entry_get_current();
+ entry->mode=m;
+ setMode(entry->mode);
+ FILTER* band_filters=filters[entry->mode];
+ FILTER* band_filter=&band_filters[entry->filter];
+ setFilter(band_filter->low,band_filter->high);
+ gtk_widget_override_background_color(last_mode, GTK_STATE_NORMAL, &white);
+ last_mode=widget;
+ gtk_widget_override_background_color(last_mode, GTK_STATE_NORMAL, &gray);
+ vfo_update(NULL);
+}
+
+static void mode_cb(GtkWidget *widget, gpointer data) {
+ BANDSTACK_ENTRY *entry=bandstack_entry_get_current();
+ GtkWidget *dialog=gtk_dialog_new_with_buttons("Mode",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+ GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ GtkWidget *grid=gtk_grid_new();
+ gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+ gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+
+ GtkWidget *b;
+ int i;
+ for(i=0;i<MODES;i++) {
+ GtkWidget *b=gtk_button_new_with_label(mode_string[i]);
+ if(i==entry->mode) {
+ gtk_widget_override_background_color(b, GTK_STATE_NORMAL, &gray);
+ last_mode=b;
+ } else {
+ gtk_widget_override_background_color(b, GTK_STATE_NORMAL, &white);
+ }
+ gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
+ gtk_widget_show(b);
+ gtk_grid_attach(GTK_GRID(grid),b,i%5,i/5,1,1);
+ g_signal_connect(b,"pressed",G_CALLBACK(mode_select_cb),(gpointer *)i);
+ }
+ gtk_container_add(GTK_CONTAINER(content),grid);
+ GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
+ gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
+ gtk_widget_show_all(dialog);
+
+ g_signal_connect_swapped (dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
+
+ int result=gtk_dialog_run(GTK_DIALOG(dialog));
+
+}
+
+static void filter_select_cb(GtkWidget *widget, gpointer data) {
+ int f=(int)data;
+ BANDSTACK_ENTRY *entry;
+ entry=bandstack_entry_get_current();
+ entry->filter=f;
+ FILTER* band_filters=filters[entry->mode];
+ FILTER* band_filter=&band_filters[entry->filter];
+ setFilter(band_filter->low,band_filter->high);
+ gtk_widget_override_background_color(last_filter, GTK_STATE_NORMAL, &white);
+ last_filter=widget;
+ gtk_widget_override_background_color(last_filter, GTK_STATE_NORMAL, &gray);
+ vfo_update(NULL);
+}
+
+static void filter_cb(GtkWidget *widget, gpointer data) {
+ BANDSTACK_ENTRY *entry=bandstack_entry_get_current();
+ FILTER* band_filters=filters[entry->mode];
+ GtkWidget *dialog=gtk_dialog_new_with_buttons("Mode",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+ GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ GtkWidget *grid=gtk_grid_new();
+ gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+ gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+
+ GtkWidget *b;
+ int i;
+ for(i=0;i<FILTERS;i++) {
+ FILTER* band_filter=&band_filters[i];
+ GtkWidget *b=gtk_button_new_with_label(band_filters[i].title);
+ gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
+ if(i==entry->filter) {
+ gtk_widget_override_background_color(b, GTK_STATE_NORMAL, &gray);
+ last_filter=b;
+ } else {
+ gtk_widget_override_background_color(b, GTK_STATE_NORMAL, &white);
+ }
+ gtk_widget_show(b);
+ gtk_grid_attach(GTK_GRID(grid),b,i%5,i/5,1,1);
+ g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i);
+ }
+ gtk_container_add(GTK_CONTAINER(content),grid);
+ GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
+ gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
+ gtk_widget_show_all(dialog);
+
+ g_signal_connect_swapped (dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
+
+ int result=gtk_dialog_run(GTK_DIALOG(dialog));
+
+}
+
+static void agc_select_cb(GtkWidget *widget, gpointer data) {
+ agc=(int)data;
+ SetRXAAGCMode(CHANNEL_RX0, agc);
+}
+
+static void agcgain_value_changed_cb(GtkWidget *widget, gpointer data) {
+ agc_gain=gtk_range_get_value(GTK_RANGE(widget));
+ SetRXAAGCTop(CHANNEL_RX0, agc_gain);
+}
+
+void set_agc_gain(double value) {
+ agc_gain=value;
+ gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
+ SetRXAAGCTop(CHANNEL_RX0, agc_gain);
+}
+
+static void afgain_value_changed_cb(GtkWidget *widget, gpointer data) {
+ volume=gtk_range_get_value(GTK_RANGE(widget));
+}
+
+void set_af_gain(double value) {
+ volume=value;
+ gtk_range_set_value (GTK_RANGE(audio_scale),volume);
+}
+
+static void micgain_value_changed_cb(GtkWidget *widget, gpointer data) {
+ mic_gain=gtk_range_get_value(GTK_RANGE(widget));
+}
+
+static void nr_cb(GtkWidget *widget, gpointer data) {
+ nr=nr==0?1:0;
+ SetRXAANRRun(CHANNEL_RX0, nr);
+}
+
+static void nb_cb(GtkWidget *widget, gpointer data) {
+ nb=nb==0?1:0;
+ SetRXAEMNRRun(CHANNEL_RX0, nb);
+}
+
+static void anf_cb(GtkWidget *widget, gpointer data) {
+ anf=anf==0?1:0;
+ SetRXAANFRun(CHANNEL_RX0, anf);
+}
+
+static void snb_cb(GtkWidget *widget, gpointer data) {
+ snb=snb==0?1:0;
+ SetRXASNBARun(CHANNEL_RX0, snb);
+}
+
+static void linein_cb(GtkWidget *widget, gpointer data) {
+ if((orion_mic&0x01)==LINE_IN) {
+ orion_mic=orion_mic&0xFE;
+ } else {
+ orion_mic=orion_mic|LINE_IN;
+ }
+}
+
+static void micboost_cb(GtkWidget *widget, gpointer data) {
+ if((orion_mic&0x02)==MIC_BOOST) {
+ orion_mic=orion_mic&0xFD;
+ } else {
+ orion_mic=orion_mic|MIC_BOOST;
+ }
+}
+
+static void byteswap_cb(GtkWidget *widget, gpointer data) {
+ byte_swap=byte_swap?0:1;
+}
+
+static void ptt_cb(GtkWidget *widget, gpointer data) {
+ if((orion_mic&0x04)==ORION_MIC_PTT_ENABLED) {
+ orion_mic=orion_mic|ORION_MIC_PTT_DISABLED;
+ } else {
+ orion_mic=orion_mic&0xFB;
+ }
+}
+
+static void ptt_ring_cb(GtkWidget *widget, gpointer data) {
+ if((orion_mic&0x08)==ORION_MIC_PTT_RING_BIAS_TIP) {
+ orion_mic=orion_mic|ORION_MIC_PTT_TIP_BIAS_RING;
+ } else {
+ orion_mic=orion_mic&0xF7;
+ }
+}
+
+static void bias_cb(GtkWidget *widget, gpointer data) {
+ if((orion_mic&0x10)==ORION_MIC_BIAS_DISABLED) {
+ orion_mic=orion_mic|ORION_MIC_BIAS_ENABLED;
+ } else {
+ orion_mic=orion_mic&0xEF;
+ }
+}
+
+static void audio_cb(GtkWidget *widget, gpointer data) {
+ GtkWidget *dialog=gtk_dialog_new_with_buttons("Audio",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+
+ GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ GtkWidget *grid=gtk_grid_new();
+
+ gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+ gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+
+ GtkWidget *b_off=gtk_radio_button_new_with_label(NULL,"Off");
+ gtk_widget_override_font(b_off, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_off), agc==AGC_OFF);
+ gtk_widget_show(b_off);
+ gtk_grid_attach(GTK_GRID(grid),b_off,0,0,2,1);
+ g_signal_connect(b_off,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_OFF);
+
+ GtkWidget *b_long=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_off),"Long");
+ gtk_widget_override_font(b_long, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_long), agc==AGC_LONG);
+ gtk_widget_show(b_long);
+ gtk_grid_attach(GTK_GRID(grid),b_long,0,1,2,1);
+ g_signal_connect(b_long,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_LONG);
+
+ GtkWidget *b_slow=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_long),"Slow");
+ gtk_widget_override_font(b_slow, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_slow), agc==AGC_SLOW);
+ gtk_widget_show(b_slow);
+ gtk_grid_attach(GTK_GRID(grid),b_slow,0,2,2,1);
+ g_signal_connect(b_slow,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_SLOW);
+
+ GtkWidget *b_medium=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_slow),"Medium");
+ gtk_widget_override_font(b_medium, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_medium), agc==AGC_MEDIUM);
+ gtk_widget_show(b_medium);
+ gtk_grid_attach(GTK_GRID(grid),b_medium,0,3,2,1);
+ g_signal_connect(b_medium,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_MEDIUM);
+
+ GtkWidget *b_fast=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_medium),"Fast");
+ gtk_widget_override_font(b_fast, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_fast), agc==AGC_FAST);
+ gtk_widget_show(b_fast);
+ gtk_grid_attach(GTK_GRID(grid),b_fast,0,4,2,1);
+ g_signal_connect(b_fast,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_FAST);
+
+
+ GtkWidget *b_nr=gtk_check_button_new_with_label("NR");
+ gtk_widget_override_font(b_nr, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr), nr==1);
+ gtk_widget_show(b_nr);
+ gtk_grid_attach(GTK_GRID(grid),b_nr,2,0,2,1);
+ g_signal_connect(b_nr,"toggled",G_CALLBACK(nr_cb),NULL);
+
+ GtkWidget *b_nb=gtk_check_button_new_with_label("NB");
+ gtk_widget_override_font(b_nb, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nb), nb==1);
+ gtk_widget_show(b_nb);
+ gtk_grid_attach(GTK_GRID(grid),b_nb,2,1,2,1);
+ g_signal_connect(b_nb,"toggled",G_CALLBACK(nb_cb),NULL);
+
+ GtkWidget *b_anf=gtk_check_button_new_with_label("ANF");
+ gtk_widget_override_font(b_anf, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_anf), anf==1);
+ gtk_widget_show(b_anf);
+ gtk_grid_attach(GTK_GRID(grid),b_anf,2,2,2,1);
+ g_signal_connect(b_anf,"toggled",G_CALLBACK(anf_cb),NULL);
+
+ GtkWidget *b_snb=gtk_check_button_new_with_label("SNB");
+ gtk_widget_override_font(b_snb, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_snb), snb==1);
+ gtk_widget_show(b_snb);
+ gtk_grid_attach(GTK_GRID(grid),b_snb,2,3,2,1);
+ g_signal_connect(b_snb,"toggled",G_CALLBACK(snb_cb),NULL);
+
+ gtk_container_add(GTK_CONTAINER(content),grid);
+ GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
+ gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show_all(dialog);
+
+ g_signal_connect_swapped (dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
+
+ int result=gtk_dialog_run(GTK_DIALOG(dialog));
+
+}
+
+void set_drive(double value) {
+ setDrive(value);
+ gtk_range_set_value (GTK_RANGE(drive_scale),value);
+}
+
+static void drive_value_changed_cb(GtkWidget *widget, gpointer data) {
+ setDrive(gtk_range_get_value(GTK_RANGE(widget)));
+}
+
+void set_tune(double value) {
+ setTuneDrive(value);
+ gtk_range_set_value (GTK_RANGE(tune_scale),value);
+}
+
+static void tune_value_changed_cb(GtkWidget *widget, gpointer data) {
+ setTuneDrive(gtk_range_get_value(GTK_RANGE(widget)));
+}
+
+static void yes_cb(GtkWidget *widget, gpointer data) {
+ encoder_close();
+ _exit(0);
+}
+
+static void halt_cb(GtkWidget *widget, gpointer data) {
+ encoder_close();
+ system("shutdown -h -P now");
+ _exit(0);
+}
+
+static void exit_cb(GtkWidget *widget, gpointer data) {
+
+ radioSaveState();
+ saveProperties(property_path);
+
+ GtkWidget *dialog=gtk_dialog_new_with_buttons("Audio",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+
+ GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ GtkWidget *grid=gtk_grid_new();
+
+ gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+ gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+
+ GtkWidget *label=gtk_label_new("Exit?");
+ gtk_widget_override_font(label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(label);
+ gtk_grid_attach(GTK_GRID(grid),label,1,0,1,1);
+
+ GtkWidget *b_yes=gtk_button_new_with_label("Yes (to CLI)");
+ gtk_widget_override_font(b_yes, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(b_yes);
+ gtk_grid_attach(GTK_GRID(grid),b_yes,0,1,1,1);
+ g_signal_connect(b_yes,"pressed",G_CALLBACK(yes_cb),NULL);
+
+ GtkWidget *b_halt=gtk_button_new_with_label("Halt System");
+ gtk_widget_override_font(b_halt, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(b_halt);
+ gtk_grid_attach(GTK_GRID(grid),b_halt,2,1,1,1);
+ g_signal_connect(b_halt,"pressed",G_CALLBACK(halt_cb),NULL);
+
+ gtk_container_add(GTK_CONTAINER(content),grid);
+ GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Cancel",GTK_RESPONSE_OK);
+ gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show_all(dialog);
+
+ g_signal_connect_swapped (dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
+
+ int result=gtk_dialog_run(GTK_DIALOG(dialog));
+
+}
+
+static void apollo_cb(GtkWidget *widget, gpointer data);
+
+static void alex_cb(GtkWidget *widget, gpointer data) {
+fprintf(stderr,"alex_cb\n");
+ if(filter_board==ALEX) {
+fprintf(stderr,"alex_cb: was ALEX setting NONE\n");
+ filter_board=NONE;
+ } else if(filter_board==NONE) {
+fprintf(stderr,"alex_cb: was NONE setting ALEX\n");
+ filter_board=ALEX;
+ } else if(filter_board==APOLLO) {
+fprintf(stderr,"alex_cb: was APOLLO setting ALEX\n");
+ GtkWidget *w=(GtkWidget *)data;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), FALSE);
+ filter_board=ALEX;
+ }
+ filter_board_changed();
+}
+
+static void apollo_cb(GtkWidget *widget, gpointer data) {
+fprintf(stderr,"apollo_cb\n");
+ if(filter_board==APOLLO) {
+fprintf(stderr,"apollo_cb: was APOLLO setting NONE\n");
+ filter_board=NONE;
+ } else if(filter_board==NONE) {
+fprintf(stderr,"apollo_cb: was NONE setting APOLLO\n");
+ filter_board=APOLLO;
+ } else if(filter_board==ALEX) {
+fprintf(stderr,"apollo_cb: was ALEX setting APOLLO\n");
+ GtkWidget *w=(GtkWidget *)data;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), FALSE);
+ filter_board=APOLLO;
+ }
+ filter_board_changed();
+}
+
+static void apollo_tuner_cb(GtkWidget *widget, gpointer data) {
+ apollo_tuner=apollo_tuner==1?0:1;
+ tuner_changed();
+}
+
+static void pa_cb(GtkWidget *widget, gpointer data) {
+ pa=pa==1?0:1;
+ pa_changed();
+}
+
+static void cw_keyer_internal_cb(GtkWidget *widget, gpointer data) {
+ cw_keyer_internal=cw_keyer_internal==1?0:1;
+ cw_changed();
+}
+
+static void cw_keyer_speed_value_changed_cb(GtkWidget *widget, gpointer data) {
+ cw_keyer_speed=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+ cw_changed();
+}
+
+static void cw_breakin_cb(GtkWidget *widget, gpointer data) {
+ cw_breakin=cw_breakin==1?0:1;
+ cw_changed();
+}
+
+static void cw_keyer_hang_time_value_changed_cb(GtkWidget *widget, gpointer data) {
+ cw_keyer_hang_time=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+ cw_changed();
+}
+
+static void cw_keys_reversed_cb(GtkWidget *widget, gpointer data) {
+ cw_keys_reversed=cw_keys_reversed==1?0:1;
+ cw_changed();
+}
+
+static void cw_keyer_mode_cb(GtkWidget *widget, gpointer data) {
+ cw_keyer_mode=(int)data;
+ cw_changed();
+}
+
+static void config_cb(GtkWidget *widget, gpointer data) {
+ GtkWidget *dialog=gtk_dialog_new_with_buttons("Audio",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+ GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ GtkWidget *grid=gtk_grid_new();
+ gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+ gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+
+ GtkWidget *linein_b=gtk_check_button_new_with_label("Line In");
+ gtk_widget_override_font(linein_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linein_b), (orion_mic&0x01)==LINE_IN);
+ gtk_widget_show(linein_b);
+ gtk_grid_attach(GTK_GRID(grid),linein_b,0,0,1,1);
+ g_signal_connect(linein_b,"toggled",G_CALLBACK(linein_cb),NULL);
+
+ GtkWidget *micboost_b=gtk_check_button_new_with_label("Boost");
+ gtk_widget_override_font(micboost_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micboost_b), (orion_mic&0x02)==MIC_BOOST);
+ gtk_widget_show(micboost_b);
+ gtk_grid_attach(GTK_GRID(grid),micboost_b,0,1,1,1);
+ g_signal_connect(micboost_b,"toggled",G_CALLBACK(micboost_cb),NULL);
+
+ GtkWidget *byteswap_b=gtk_check_button_new_with_label("Byte swap");
+ gtk_widget_override_font(byteswap_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (byteswap_b), byte_swap);
+ gtk_widget_show(byteswap_b);
+ gtk_grid_attach(GTK_GRID(grid),byteswap_b,0,2,1,1);
+ g_signal_connect(byteswap_b,"toggled",G_CALLBACK(byteswap_cb),NULL);
+
+ DISCOVERED* d=&discovered[selected_device];
+ if(d->device==NEW_DEVICE_ORION) {
+ GtkWidget *ptt_b=gtk_check_button_new_with_label("PTT Enabled");
+ gtk_widget_override_font(ptt_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_b), (orion_mic&0x04)==ORION_MIC_PTT_ENABLED);
+ gtk_widget_show(ptt_b);
+ gtk_grid_attach(GTK_GRID(grid),ptt_b,0,3,1,1);
+ g_signal_connect(ptt_b,"toggled",G_CALLBACK(ptt_cb),NULL);
+
+ GtkWidget *ptt_ring_b=gtk_check_button_new_with_label("PTT On Ring");
+ gtk_widget_override_font(ptt_ring_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_ring_b), (orion_mic&0x08)==ORION_MIC_PTT_RING_BIAS_TIP);
+ gtk_widget_show(ptt_ring_b);
+ gtk_grid_attach(GTK_GRID(grid),ptt_ring_b,0,4,1,1);
+ g_signal_connect(ptt_ring_b,"toggled",G_CALLBACK(ptt_ring_cb),NULL);
+
+ GtkWidget *bias_b=gtk_check_button_new_with_label("BIAS Enabled");
+ gtk_widget_override_font(bias_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bias_b), (orion_mic&0x10)==ORION_MIC_BIAS_ENABLED);
+ gtk_widget_show(bias_b);
+ gtk_grid_attach(GTK_GRID(grid),bias_b,0,5,1,1);
+ g_signal_connect(bias_b,"toggled",G_CALLBACK(bias_cb),NULL);
+ }
+
+ GtkWidget *alex_b=gtk_check_button_new_with_label("ALEX");
+ gtk_widget_override_font(alex_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (alex_b), filter_board==ALEX);
+ gtk_widget_show(alex_b);
+ gtk_grid_attach(GTK_GRID(grid),alex_b,1,0,1,1);
+
+ GtkWidget *apollo_b=gtk_check_button_new_with_label("APOLLO");
+ gtk_widget_override_font(apollo_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apollo_b), filter_board==APOLLO);
+ gtk_widget_show(apollo_b);
+ gtk_grid_attach(GTK_GRID(grid),apollo_b,1,1,1,1);
+
+ g_signal_connect(alex_b,"toggled",G_CALLBACK(alex_cb),apollo_b);
+ g_signal_connect(apollo_b,"toggled",G_CALLBACK(apollo_cb),alex_b);
+
+ GtkWidget *apollo_tuner_b=gtk_check_button_new_with_label("Auto Tuner");
+ gtk_widget_override_font(apollo_tuner_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apollo_tuner_b), apollo_tuner);
+ gtk_widget_show(apollo_tuner_b);
+ gtk_grid_attach(GTK_GRID(grid),apollo_tuner_b,1,2,1,1);
+ g_signal_connect(apollo_tuner_b,"toggled",G_CALLBACK(apollo_tuner_cb),NULL);
+
+ GtkWidget *pa_b=gtk_check_button_new_with_label("PA");
+ gtk_widget_override_font(pa_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pa_b), pa);
+ gtk_widget_show(pa_b);
+ gtk_grid_attach(GTK_GRID(grid),pa_b,1,3,1,1);
+ g_signal_connect(pa_b,"toggled",G_CALLBACK(pa_cb),NULL);
+
+ gtk_container_add(GTK_CONTAINER(content),grid);
+ GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
+ gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show_all(dialog);
+
+ g_signal_connect_swapped (dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
+
+ int result=gtk_dialog_run(GTK_DIALOG(dialog));
+}
+
+static void cw_cb(GtkWidget *widget, gpointer data) {
+ GtkWidget *dialog=gtk_dialog_new_with_buttons("CW",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+ GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ GtkWidget *grid=gtk_grid_new();
+ //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+ gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+
+
+ GtkWidget *cw_keyer_internal_b=gtk_check_button_new_with_label("CW Internal - Speed (WPM)");
+ gtk_widget_override_font(cw_keyer_internal_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_keyer_internal_b), cw_keyer_internal);
+ gtk_widget_show(cw_keyer_internal_b);
+ gtk_grid_attach(GTK_GRID(grid),cw_keyer_internal_b,0,0,1,1);
+ g_signal_connect(cw_keyer_internal_b,"toggled",G_CALLBACK(cw_keyer_internal_cb),NULL);
+
+ GtkWidget *cw_keyer_speed_b=gtk_spin_button_new_with_range(1.0,60.0,1.0);
+ gtk_widget_override_font(cw_keyer_speed_b, pango_font_description_from_string("Arial 18"));
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(cw_keyer_speed_b),(double)cw_keyer_speed);
+ gtk_widget_show(cw_keyer_speed_b);
+ gtk_grid_attach(GTK_GRID(grid),cw_keyer_speed_b,1,0,1,1);
+ g_signal_connect(cw_keyer_speed_b,"value_changed",G_CALLBACK(cw_keyer_speed_value_changed_cb),NULL);
+
+ GtkWidget *cw_breakin_b=gtk_check_button_new_with_label("CW Break In - Delay (ms)");
+ gtk_widget_override_font(cw_breakin_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_breakin_b), cw_breakin);
+ gtk_widget_show(cw_breakin_b);
+ gtk_grid_attach(GTK_GRID(grid),cw_breakin_b,0,1,1,1);
+ g_signal_connect(cw_breakin_b,"toggled",G_CALLBACK(cw_breakin_cb),NULL);
+
+ GtkWidget *cw_keyer_hang_time_b=gtk_spin_button_new_with_range(0.0,1000.0,1.0);
+ gtk_widget_override_font(cw_keyer_hang_time_b, pango_font_description_from_string("Arial 18"));
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(cw_keyer_hang_time_b),(double)cw_keyer_hang_time);
+ gtk_widget_show(cw_keyer_hang_time_b);
+ gtk_grid_attach(GTK_GRID(grid),cw_keyer_hang_time_b,1,1,1,1);
+ g_signal_connect(cw_keyer_hang_time_b,"value_changed",G_CALLBACK(cw_keyer_hang_time_value_changed_cb),NULL);
+
+ GtkWidget *cw_keyer_straight=gtk_radio_button_new_with_label(NULL,"CW KEYER STRAIGHT");
+ gtk_widget_override_font(cw_keyer_straight, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_keyer_straight), cw_keyer_mode==KEYER_STRAIGHT);
+ gtk_widget_show(cw_keyer_straight);
+ gtk_grid_attach(GTK_GRID(grid),cw_keyer_straight,0,2,1,1);
+ g_signal_connect(cw_keyer_straight,"pressed",G_CALLBACK(cw_keyer_mode_cb),(gpointer *)KEYER_STRAIGHT);
+
+ GtkWidget *cw_keyer_mode_a=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(cw_keyer_straight),"CW KEYER MODE A");
+ gtk_widget_override_font(cw_keyer_mode_a, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_keyer_mode_a), cw_keyer_mode==KEYER_MODE_A);
+ gtk_widget_show(cw_keyer_mode_a);
+ gtk_grid_attach(GTK_GRID(grid),cw_keyer_mode_a,0,3,1,1);
+ g_signal_connect(cw_keyer_mode_a,"pressed",G_CALLBACK(cw_keyer_mode_cb),(gpointer *)KEYER_MODE_A);
+
+ GtkWidget *cw_keyer_mode_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(cw_keyer_mode_a),"CW KEYER MODE B");
+ gtk_widget_override_font(cw_keyer_mode_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_keyer_mode_b), cw_keyer_mode==KEYER_MODE_B);
+ gtk_widget_show(cw_keyer_mode_b);
+ gtk_grid_attach(GTK_GRID(grid),cw_keyer_mode_b,0,4,1,1);
+ g_signal_connect(cw_keyer_mode_b,"pressed",G_CALLBACK(cw_keyer_mode_cb),(gpointer *)KEYER_MODE_B);
+
+/*
+int cw_keyer_speed=12; // 1-60 WPM
+int cw_keyer_weight=30; // 0-100
+int cw_keyer_spacing=0; // 0=on 1=off
+int cw_keyer_sidetone_volume=127; // 0-127
+int cw_keyer_ptt_delay=20; // 0-255ms
+int cw_keyer_hang_time=10; // ms
+int cw_keyer_sidetone_frequency=400; // Hz
+*/
+
+ gtk_container_add(GTK_CONTAINER(content),grid);
+ GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
+ gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show_all(dialog);
+
+ g_signal_connect_swapped (dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
+
+ int result=gtk_dialog_run(GTK_DIALOG(dialog));
+}
+
+static void adc_cb(GtkWidget *widget, gpointer data) {
+ int adc0=adc[0];
+ adc[0]=adc[1];
+ adc[1]=adc0;
+
+ char label[16];
+ gtk_grid_remove_row(GTK_GRID(toolbar_top),0);
+
+ sprintf(label,"RX0=%d",adc[0]);
+ GtkWidget *rx0=gtk_label_new(label);
+ gtk_widget_override_font(rx0, pango_font_description_from_string("Arial 16"));
+ gtk_widget_show(rx0);
+ gtk_grid_attach(GTK_GRID(toolbar_top),rx0,0,0,1,1);
+
+ sprintf(label,"RX1=%d",adc[1]);
+ GtkWidget *rx1=gtk_label_new(label);
+ gtk_widget_override_font(rx1, pango_font_description_from_string("Arial 16"));
+ gtk_widget_show(rx1);
+ gtk_grid_attach(GTK_GRID(toolbar_top),rx1,1,0,1,1);
+}
+
+static void lock_cb(GtkWidget *widget, gpointer data) {
+ locked=locked==1?0:1;
+ vfo_update(NULL);
+}
+
+static void mox_cb(GtkWidget *widget, gpointer data) {
+ gtk_grid_remove_row (GTK_GRID(toolbar_top),0);
+ if(getTune()==1) {
+ setTune(0);
+ }
+ setMox(getMox()==0?1:0);
+ vfo_update(NULL);
+ if(getMox()) {
+ mic_gain_label=gtk_label_new("Mic Gain:");
+ gtk_widget_override_font(mic_gain_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(mic_gain_label);
+ gtk_grid_attach(GTK_GRID(toolbar_top),mic_gain_label,0,0,1,1);
+
+ mic_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
+ gtk_range_set_value (GTK_RANGE(mic_scale),mic_gain);
+ gtk_widget_show(mic_scale);
+ gtk_grid_attach(GTK_GRID(toolbar_top),mic_scale,1,0,2,1);
+ g_signal_connect(G_OBJECT(mic_scale),"value_changed",G_CALLBACK(micgain_value_changed_cb),NULL);
+
+ GtkWidget *drive_label=gtk_label_new("Drive:");
+ gtk_widget_override_font(drive_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(drive_label);
+ gtk_grid_attach(GTK_GRID(toolbar_top),drive_label,3,0,1,1);
+
+ drive_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
+ gtk_range_set_value (GTK_RANGE(drive_scale),getDrive());
+ gtk_widget_show(drive_scale);
+ gtk_grid_attach(GTK_GRID(toolbar_top),drive_scale,4,0,2,1);
+ g_signal_connect(G_OBJECT(drive_scale),"value_changed",G_CALLBACK(drive_value_changed_cb),NULL);
+ } else {
+ af_gain_label=gtk_label_new("AF:");
+ gtk_widget_override_font(af_gain_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(af_gain_label);
+ gtk_grid_attach(GTK_GRID(toolbar_top),af_gain_label,0,0,1,1);
+
+ audio_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
+ gtk_range_set_value (GTK_RANGE(audio_scale),volume);
+ gtk_widget_show(audio_scale);
+ gtk_grid_attach(GTK_GRID(toolbar_top),audio_scale,1,0,2,1);
+ g_signal_connect(G_OBJECT(audio_scale),"value_changed",G_CALLBACK(afgain_value_changed_cb),NULL);
+
+ agc_gain_label=gtk_label_new("AGC:");
+ gtk_widget_override_font(agc_gain_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(agc_gain_label);
+ gtk_grid_attach(GTK_GRID(toolbar_top),agc_gain_label,3,0,1,1);
+
+ agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 120.0, 1.0);
+ gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
+ gtk_widget_show(agc_scale);
+ gtk_grid_attach(GTK_GRID(toolbar_top),agc_scale,4,0,2,1);
+ g_signal_connect(G_OBJECT(agc_scale),"value_changed",G_CALLBACK(agcgain_value_changed_cb),NULL);
+
+ }
+ //gtk_widget_queue_draw(toolbar_top);
+}
+
+int ptt_update(void *data) {
+ BANDSTACK_ENTRY *entry;
+ entry=bandstack_entry_get_current();
+ int ptt=(int)data;
+ if((entry->mode==modeCWL || entry->mode==modeCWU) && cw_keyer_internal==1) {
+ if(ptt!= getMox()) {
+ mox_cb(NULL,NULL);
+ }
+ } else {
+ mox_cb(NULL,NULL);
+ }
+ return 0;
+}
+
+static void tune_cb(GtkWidget *widget, gpointer data) {
+ gtk_grid_remove_row (GTK_GRID(toolbar_top),0);
+ if(getMox()==1) {
+ setMox(0);
+ }
+ setTune(getTune()==0?1:0);
+ vfo_update(NULL);
+ if(getTune()) {
+ GtkWidget *tune_label=gtk_label_new("Tune Drive:");
+ gtk_widget_override_font(tune_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(tune_label);
+ gtk_grid_attach(GTK_GRID(toolbar_top),tune_label,0,0,1,1);
+
+ tune_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
+ gtk_range_set_value (GTK_RANGE(tune_scale),getTuneDrive());
+ gtk_widget_show(tune_scale);
+ gtk_grid_attach(GTK_GRID(toolbar_top),tune_scale,1,0,2,1);
+ g_signal_connect(G_OBJECT(tune_scale),"value_changed",G_CALLBACK(tune_value_changed_cb),NULL);
+ } else {
+ af_gain_label=gtk_label_new("AF:");
+ gtk_widget_override_font(af_gain_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(af_gain_label);
+ gtk_grid_attach(GTK_GRID(toolbar_top),af_gain_label,0,0,1,1);
+
+ audio_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
+ gtk_range_set_value (GTK_RANGE(audio_scale),volume);
+ gtk_widget_show(audio_scale);
+ gtk_grid_attach(GTK_GRID(toolbar_top),audio_scale,1,0,2,1);
+ g_signal_connect(G_OBJECT(audio_scale),"value_changed",G_CALLBACK(afgain_value_changed_cb),NULL);
+
+ agc_gain_label=gtk_label_new("AGC:");
+ gtk_widget_override_font(agc_gain_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(agc_gain_label);
+ gtk_grid_attach(GTK_GRID(toolbar_top),agc_gain_label,3,0,1,1);
+
+ agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 120.0, 1.0);
+ gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
+ gtk_widget_show(agc_scale);
+ gtk_grid_attach(GTK_GRID(toolbar_top),agc_scale,4,0,2,1);
+ g_signal_connect(G_OBJECT(agc_scale),"value_changed",G_CALLBACK(agcgain_value_changed_cb),NULL);
+ }
+}
+
+GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent) {
+ width=my_width;
+ height=my_height;
+ parent_window=parent;
+
+ white.red=1.0;
+ white.green=1.0;
+ white.blue=1.0;
+ white.alpha=0.0;
+
+ gray.red=0.25;
+ gray.green=0.25;
+ gray.blue=0.25;
+ gray.alpha=0.0;
+
+ toolbar=gtk_grid_new();
+ gtk_widget_set_size_request (toolbar, width, height);
+ gtk_grid_set_row_homogeneous(GTK_GRID(toolbar), TRUE);
+
+ toolbar_top=gtk_grid_new();
+ gtk_grid_set_column_homogeneous(GTK_GRID(toolbar_top),TRUE);
+
+ toolbar_bottom=gtk_grid_new();
+ gtk_grid_set_column_homogeneous(GTK_GRID(toolbar_bottom),FALSE);
+
+ GtkWidget *band=gtk_button_new_with_label("Band");
+ gtk_widget_override_font(band, pango_font_description_from_string("Arial 20"));
+ g_signal_connect(G_OBJECT(band),"clicked",G_CALLBACK(band_cb),NULL);
+ gtk_widget_show(band);
+ gtk_grid_attach(GTK_GRID(toolbar_bottom),band,column,0,1,1);
+ column++;
+
+ GtkWidget *mode=gtk_button_new_with_label("Mode");
+ gtk_widget_override_font(mode, pango_font_description_from_string("Arial 20"));
+ g_signal_connect(G_OBJECT(mode),"clicked",G_CALLBACK(mode_cb),NULL);
+ gtk_widget_show(mode);
+ gtk_grid_attach(GTK_GRID(toolbar_bottom),mode,column,0,1,1);
+ column++;
+
+ GtkWidget *filter=gtk_button_new_with_label("Filter");
+ gtk_widget_override_font(filter, pango_font_description_from_string("Arial 20"));
+ g_signal_connect(G_OBJECT(filter),"clicked",G_CALLBACK(filter_cb),NULL);
+ gtk_widget_show(filter);
+ gtk_grid_attach(GTK_GRID(toolbar_bottom),filter,column,0,1,1);
+ column++;
+
+ GtkWidget *audio=gtk_button_new_with_label("Audio");
+ gtk_widget_override_font(audio, pango_font_description_from_string("Arial 20"));
+ g_signal_connect(G_OBJECT(audio),"clicked",G_CALLBACK(audio_cb),NULL);
+ gtk_widget_show(audio);
+ gtk_grid_attach(GTK_GRID(toolbar_bottom),audio,column,0,1,1);
+ column++;
+
+ GtkWidget *config=gtk_button_new_with_label("Config");
+ gtk_widget_override_font(config, pango_font_description_from_string("Arial 20"));
+ g_signal_connect(G_OBJECT(config),"clicked",G_CALLBACK(config_cb),NULL);
+ gtk_widget_show(config);
+ gtk_grid_attach(GTK_GRID(toolbar_bottom),config,column,0,1,1);
+ column++;
+
+ GtkWidget *cw=gtk_button_new_with_label("CW");
+ gtk_widget_override_font(cw, pango_font_description_from_string("Arial 20"));
+ g_signal_connect(G_OBJECT(cw),"clicked",G_CALLBACK(cw_cb),NULL);
+ gtk_widget_show(cw);
+ gtk_grid_attach(GTK_GRID(toolbar_bottom),cw,column,0,1,1);
+ column++;
+
+ GtkWidget *exit=gtk_button_new_with_label("Exit");
+ gtk_widget_override_font(exit, pango_font_description_from_string("Arial 20"));
+ g_signal_connect(G_OBJECT(exit),"clicked",G_CALLBACK(exit_cb),NULL);
+ gtk_widget_show(exit);
+ gtk_grid_attach(GTK_GRID(toolbar_bottom),exit,column,0,1,1);
+ column++;
+
+ GtkWidget *lock=gtk_button_new_with_label("Lock");
+ gtk_widget_override_font(lock, pango_font_description_from_string("Arial 20"));
+ g_signal_connect(G_OBJECT(lock),"clicked",G_CALLBACK(lock_cb),NULL);
+ gtk_widget_show(lock);
+ gtk_grid_attach(GTK_GRID(toolbar_bottom),lock,column,0,1,1);
+ column++;
+
+ GtkWidget *tune=gtk_button_new_with_label("Tune");
+ gtk_widget_override_font(tune, pango_font_description_from_string("Arial 20"));
+ g_signal_connect(G_OBJECT(tune),"clicked",G_CALLBACK(tune_cb),NULL);
+ gtk_widget_show(tune);
+ gtk_grid_attach(GTK_GRID(toolbar_bottom),tune,column,0,1,1);
+ column++;
+
+ GtkWidget *tx=gtk_button_new_with_label("Mox");
+ gtk_widget_override_font(tx, pango_font_description_from_string("Arial 20"));
+ g_signal_connect(G_OBJECT(tx),"clicked",G_CALLBACK(mox_cb),NULL);
+ gtk_widget_show(tx);
+ gtk_grid_attach(GTK_GRID(toolbar_bottom),tx,column,0,1,1);
+ column++;
+
+
+ // default to receive controls on top bar
+ af_gain_label=gtk_label_new("AF:");
+ gtk_widget_override_font(af_gain_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(af_gain_label);
+ gtk_grid_attach(GTK_GRID(toolbar_top),af_gain_label,0,0,1,1);
+
+ audio_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
+ gtk_range_set_value (GTK_RANGE(audio_scale),volume);
+ gtk_widget_show(audio_scale);
+ gtk_grid_attach(GTK_GRID(toolbar_top),audio_scale,1,0,2,1);
+ g_signal_connect(G_OBJECT(audio_scale),"value_changed",G_CALLBACK(afgain_value_changed_cb),NULL);
+
+ agc_gain_label=gtk_label_new("AGC:");
+ gtk_widget_override_font(agc_gain_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(agc_gain_label);
+ gtk_grid_attach(GTK_GRID(toolbar_top),agc_gain_label,3,0,1,1);
+
+ agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 120.0, 1.0);
+ gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
+ gtk_widget_show(agc_scale);
+ gtk_grid_attach(GTK_GRID(toolbar_top),agc_scale,4,0,2,1);
+ g_signal_connect(G_OBJECT(agc_scale),"value_changed",G_CALLBACK(agcgain_value_changed_cb),NULL);
+
+/*
+
+ GtkWidget *drive_label=gtk_label_new("Drive:");
+ gtk_widget_override_font(drive_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(drive_label);
+ gtk_grid_attach(toolbar_top,drive_label,6,0,1,1);
+
+ drive_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
+ gtk_range_set_value (drive_scale,getTuneDrive());
+ gtk_widget_show(drive_scale);
+ gtk_grid_attach(toolbar_top,drive_scale,7,0,2,1);
+ g_signal_connect(G_OBJECT(drive_scale),"value_changed",G_CALLBACK(drive_value_changed_cb),NULL);
+
+ GtkWidget *tune_label=gtk_label_new("Tune:");
+ gtk_widget_override_font(tune_label, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show(tune_label);
+ gtk_grid_attach(toolbar_top,tune_label,9,0,1,1);
+
+ tune_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
+ gtk_range_set_value (tune_scale,getTuneDrive());
+ gtk_widget_show(tune_scale);
+ gtk_grid_attach(toolbar_top,tune_scale,10,0,2,1);
+ g_signal_connect(G_OBJECT(tune_scale),"value_changed",G_CALLBACK(tune_value_changed_cb),NULL);
+*/
+
+ gtk_grid_attach(GTK_GRID(toolbar),toolbar_top,0,0,1,1);
+ gtk_widget_show(toolbar_top);
+ gtk_grid_attach(GTK_GRID(toolbar),toolbar_bottom,0,1,1,1);
+ gtk_widget_show(toolbar_bottom);
+
+ return toolbar;
+}
--- /dev/null
+void set_agc_gain(double value);
+void set_af_gain(double value);
+void set_drive(double drive);
+void set_tune(double tune);
+int ptt_update(void *data);
+GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent);
--- /dev/null
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <math.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "mode.h"
+#include "filter.h"
+#include "bandstack.h"
+#include "band.h"
+#include "new_protocol.h"
+#include "rotary_encoder.h"
+#include "radio.h"
+#include "vfo.h"
+#include "channel.h"
+#include "wdsp.h"
+
+static GtkWidget *parent_window;
+
+static GtkWidget *vfo;
+static cairo_surface_t *vfo_surface = NULL;
+
+static pthread_t rotary_encoder_thread_id;
+
+static int steps[]={1,10,25,50,100,250,500,1000,2500,5000,6250,9000,10000,12500,15000,20000,25000,30000,50000,100000,0};
+static char *step_labels[]={"1Hz","10Hz","25Hz","50Hz","100Hz","250Hz","500Hz","1kHz","2.5kHz","5kHz","6.25kHz","9kHz","10kHz","12.5kHz","15kHz","20kHz","25kHz","30kHz","50kHz","100kHz",0};
+static int af_function=0;
+static int previous_af_function=0;
+static int rf_function=0;
+static int previous_rf_function=0;
+static int band_button=0;
+static int previous_band_button=0;
+
+static GtkWidget* menu=NULL;
+static GtkWidget* band_menu=NULL;
+
+void vfo_step(int steps) {
+ if(!locked) {
+ BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
+ entry->frequencyA=entry->frequencyA+(steps*step);
+ setFrequency(entry->frequencyA);
+ vfo_update(NULL);
+ }
+}
+
+void vfo_move(int hz) {
+ if(!locked) {
+ BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
+ entry->frequencyA=(entry->frequencyA+hz)/step*step;
+ setFrequency(entry->frequencyA);
+ vfo_update(NULL);
+ }
+}
+
+static int rotary_encoder_changed(void *data) {
+ if(!locked) {
+ int pos=*(int*)data;
+ BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
+ entry->frequencyA=entry->frequencyA+(pos*step);
+ setFrequency(entry->frequencyA);
+ vfo_update(NULL);
+ }
+ free(data);
+ return 0;
+}
+
+static int af_encoder_changed(void *data) {
+ int pos=*(int*)data;
+ if(pos!=0) {
+ if(af_function) {
+ // agc gain
+ double gain=agc_gain;
+ gain+=(double)pos;
+ if(gain<0.0) {
+ gain=0.0;
+ } else if(gain>120.0) {
+ gain=120.0;
+ }
+ set_agc_gain(gain);
+ } else {
+ // af gain
+ double gain=volume;
+ gain+=(double)pos/20.0;
+ if(gain<0.0) {
+ gain=0.0;
+ } else if(gain>1.0) {
+ gain=1.0;
+ }
+ set_af_gain(gain);
+ }
+ }
+ free(data);
+ return 0;
+}
+
+static int rf_encoder_changed(void *data) {
+ int pos=*(int*)data;
+ if(pos!=0) {
+ if(rf_function) {
+ // tune drive
+ double d=getTuneDrive();
+ d+=(double)pos/10.0;
+ if(d<0.0) {
+ d=0.0;
+ } else if(d>1.0) {
+ d=1.0;
+ }
+ set_tune(d);
+ } else {
+ // drive
+ double d=getDrive();
+ d+=(double)pos/10.0;
+ if(d<0.0) {
+ d=0.0;
+ } else if(d>1.0) {
+ d=1.0;
+ }
+ set_drive(d);
+ }
+ }
+ free(data);
+ return 0;
+}
+
+static int band_pressed(void *data) {
+ int function=*(int*)data;
+
+ BANDSTACK_ENTRY *entry;
+ if(function) {
+ entry=bandstack_entry_next();
+ } else {
+ int b=band_get_current();
+ b++;
+ if(b>=BANDS) {
+ b=0;
+ }
+ BAND* band=band_set_current(b);
+ entry=bandstack_entry_get_current();
+ }
+
+ setFrequency(entry->frequencyA);
+ setMode(entry->mode);
+ FILTER* band_filters=filters[entry->mode];
+ FILTER* band_filter=&band_filters[entry->filter];
+ setFilter(band_filter->low,band_filter->high);
+
+ BAND *band=band_get_current_band();
+ set_alex_rx_antenna(band->alexRxAntenna);
+ set_alex_tx_antenna(band->alexTxAntenna);
+ set_alex_attenuation(band->alexAttenuation);
+ vfo_update(NULL);
+
+
+ free(data);
+ return 0;
+}
+
+static void* rotary_encoder_thread(void *arg) {
+ int pos;
+ while(1) {
+
+ pos=vfo_encoder_get_pos();
+ if(pos!=0) {
+ int *p=malloc(sizeof(int));
+ *p=pos;
+ g_idle_add(rotary_encoder_changed,(gpointer)p);
+ }
+
+ af_function=af_function_get_state();
+ if(af_function!=previous_af_function) {
+ fprintf(stderr,"af_function: %d\n",af_function);
+ previous_af_function=af_function;
+ }
+ pos=af_encoder_get_pos();
+ if(pos!=0) {
+ int *p=malloc(sizeof(int));
+ *p=pos;
+ g_idle_add(af_encoder_changed,(gpointer)p);
+ }
+
+ rf_function=rf_function_get_state();
+ if(rf_function!=previous_rf_function) {
+ fprintf(stderr,"rf_function: %d\n",rf_function);
+ previous_rf_function=rf_function;
+ }
+ pos=rf_encoder_get_pos();
+ if(pos!=0) {
+ int *p=malloc(sizeof(int));
+ *p=pos;
+ g_idle_add(rf_encoder_changed,(gpointer)p);
+ }
+
+ int band_button=band_get_state();
+ if(band_button!=previous_band_button) {
+ fprintf(stderr,"band_button: %d\n",band_button);
+ previous_band_button=band_button;
+ if(band_button) {
+ int function=function_get_state();
+ g_idle_add(band_pressed,(gpointer)function);
+ }
+ }
+
+#ifdef raspberrypi
+ gpioDelay(100000); // 10 per second
+#endif
+#ifdef odroid
+ usleep(100000);
+#endif
+ }
+}
+
+static gboolean vfo_configure_event_cb (GtkWidget *widget,
+ GdkEventConfigure *event,
+ gpointer data)
+{
+ if (vfo_surface)
+ cairo_surface_destroy (vfo_surface);
+
+ vfo_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+ CAIRO_CONTENT_COLOR,
+ gtk_widget_get_allocated_width (widget),
+ gtk_widget_get_allocated_height (widget));
+
+ /* Initialize the surface to black */
+ cairo_t *cr;
+ cr = cairo_create (vfo_surface);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ /* We've handled the configure event, no need for further processing. */
+ return TRUE;
+}
+
+static gboolean vfo_draw_cb (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer data)
+{
+ cairo_set_source_surface (cr, vfo_surface, 0, 0);
+ cairo_paint (cr);
+
+ return FALSE;
+}
+
+int vfo_update(void *data) {
+ BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
+ FILTER* band_filters=filters[entry->mode];
+ FILTER* band_filter=&band_filters[entry->filter];
+ if(vfo_surface) {
+ cairo_t *cr;
+ cr = cairo_create (vfo_surface);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ cairo_select_font_face(cr, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size(cr, 36);
+
+ if(isTransmitting()) {
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ } else {
+ cairo_set_source_rgb(cr, 0, 1, 0);
+ }
+
+ char sf[32];
+ sprintf(sf,"%0lld.%06lld MHz %s %s",entry->frequencyA/(long long)1000000,entry->frequencyA%(long long)1000000,mode_string[entry->mode],band_filter->title);
+ cairo_move_to(cr, 130, 45);
+ cairo_show_text(cr, sf);
+
+ cairo_set_font_size(cr, 18);
+ sprintf(sf,"Step %dHz",step);
+ cairo_move_to(cr, 10, 25);
+ cairo_show_text(cr, sf);
+
+ if(locked) {
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ cairo_move_to(cr, 10, 50);
+ cairo_show_text(cr, "Locked");
+ }
+
+ cairo_destroy (cr);
+ gtk_widget_queue_draw (vfo);
+ }
+ return 0;
+}
+
+static gboolean
+vfo_step_select_cb (GtkWidget *widget,
+ gpointer data)
+{
+ step=steps[(int)data];
+ vfo_update(NULL);
+}
+
+static gboolean
+vfo_press_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
+{
+ GtkWidget *dialog=gtk_dialog_new_with_buttons("VFO",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+
+ GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ GtkWidget *grid=gtk_grid_new();
+
+ gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+ gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+
+ GtkWidget *step_rb=NULL;
+ int i=0;
+ while(steps[i]!=0) {
+ if(i==0) {
+ step_rb=gtk_radio_button_new_with_label(NULL,step_labels[i]);
+ } else {
+ step_rb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(step_rb),step_labels[i]);
+ }
+ gtk_widget_override_font(step_rb, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (step_rb), steps[i]==step);
+ gtk_widget_show(step_rb);
+ gtk_grid_attach(GTK_GRID(grid),step_rb,i/5,i%5,1,1);
+ g_signal_connect(step_rb,"pressed",G_CALLBACK(vfo_step_select_cb),(gpointer *)i);
+ i++;
+ }
+
+ gtk_container_add(GTK_CONTAINER(content),grid);
+ GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
+ gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
+ gtk_widget_show_all(dialog);
+
+ g_signal_connect_swapped (dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
+
+ int result=gtk_dialog_run(GTK_DIALOG(dialog));
+
+ return TRUE;
+}
+
+GtkWidget* vfo_init(int width,int height,GtkWidget *parent) {
+
+ parent_window=parent;
+
+ vfo = gtk_drawing_area_new ();
+ /* set a minimum size */
+ gtk_widget_set_size_request (vfo, width, height);
+
+ /* Signals used to handle the backing surface */
+ g_signal_connect (vfo, "draw",
+ G_CALLBACK (vfo_draw_cb), NULL);
+ g_signal_connect (vfo,"configure-event",
+ G_CALLBACK (vfo_configure_event_cb), NULL);
+
+ if(encoder_init() == 0) {
+ int rc=pthread_create(&rotary_encoder_thread_id, NULL, rotary_encoder_thread, NULL);
+ if(rc<0) {
+ fprintf(stderr,"pthread_create for rotary_encoder_thread failed %d\n",rc);
+ }
+ } else {
+ fprintf(stderr,"encoder_init failed\n");
+ }
+
+ /* Event signals */
+ g_signal_connect (vfo, "button-press-event",
+ G_CALLBACK (vfo_press_event_cb), NULL);
+ gtk_widget_set_events (vfo, gtk_widget_get_events (vfo)
+ | GDK_BUTTON_PRESS_MASK);
+
+ BAND *band=band_get_current_band();
+ BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
+ setFrequency(entry->frequencyA);
+ setMode(entry->mode);
+ FILTER* band_filters=filters[entry->mode];
+ FILTER* band_filter=&band_filters[entry->filter];
+ setFilter(band_filter->low,band_filter->high);
+
+ set_alex_rx_antenna(band->alexRxAntenna);
+ set_alex_tx_antenna(band->alexTxAntenna);
+ set_alex_attenuation(band->alexAttenuation);
+
+ return vfo;
+}
--- /dev/null
+
+GtkWidget* vfo_init(int width,int height,GtkWidget *parent);
+void vfo_step(int steps);
+void vfo_move(int hz);
+int vfo_update(void*);
--- /dev/null
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <math.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <string.h>
+#include "vfo.h"
+#include "new_protocol.h"
+#include "waterfall.h"
+
+static GtkWidget *waterfall;
+static GdkPixbuf *pixbuf = NULL;
+
+static float highThreshold = -100.0f;
+static float lowThreshold = -150.0f;
+
+static int colorLowR=0; // black
+static int colorLowG=0;
+static int colorLowB=0;
+
+static int colorMidR=255; // red
+static int colorMidG=0;
+static int colorMidB=0;
+
+static int colorHighR=255; // yellow
+static int colorHighG=255;
+static int colorHighB=0;
+
+
+static gint first_x;
+static gint last_x;
+static gboolean has_moved=FALSE;
+static gboolean pressed=FALSE;
+
+static gfloat hz_per_pixel;
+
+#define BANDS 7
+
+static long long frequency[BANDS];
+static gint mode[BANDS];
+static gint band=4;
+
+static int display_width;
+static int waterfall_height;
+
+/* Create a new surface of the appropriate size to store our scribbles */
+static gboolean
+waterfall_configure_event_cb (GtkWidget *widget,
+ GdkEventConfigure *event,
+ gpointer data)
+{
+ return TRUE;
+}
+
+/* Redraw the screen from the surface. Note that the ::draw
+ * signal receives a ready-to-be-used cairo_t that is already
+ * clipped to only draw the exposed areas of the widget
+ */
+static gboolean
+waterfall_draw_cb (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer data)
+{
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+ cairo_paint (cr);
+ return TRUE;
+}
+
+static gboolean
+waterfall_button_press_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
+{
+ int x=(int)event->x;
+ if (event->button == 1) {
+ last_x=(int)event->x;
+ has_moved=FALSE;
+ pressed=TRUE;
+ }
+ return TRUE;
+}
+
+static gboolean
+waterfall_button_release_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
+{
+ int x=(int)event->x;
+ if (event->button == 1) {
+ if(has_moved) {
+ // drag
+ vfo_move((int)((float)(x-last_x)*hz_per_pixel));
+ } else {
+ // move to this frequency
+ vfo_move((int)((float)(x-(display_width/2))*hz_per_pixel));
+ }
+ last_x=x;
+ pressed=FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+waterfall_motion_notify_event_cb (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer data)
+{
+ int x, y;
+ GdkModifierType state;
+ gdk_window_get_device_position (event->window,
+ event->device,
+ &x,
+ &y,
+ &state);
+ if((state & GDK_BUTTON1_MASK == GDK_BUTTON1_MASK) || pressed) {
+ int moved=last_x-x;
+ vfo_move((int)((float)moved*hz_per_pixel));
+ last_x=x;
+ has_moved=TRUE;
+ }
+
+ return TRUE;
+}
+
+void waterfall_update(float *data) {
+
+
+ int i;
+
+ char *pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+ int width=gdk_pixbuf_get_width(pixbuf);
+ int height=gdk_pixbuf_get_height(pixbuf);
+ int rowstride=gdk_pixbuf_get_rowstride(pixbuf);
+ int channels=gdk_pixbuf_get_n_channels(pixbuf);
+
+ memmove(&pixels[rowstride],pixels,(height-1)*rowstride);
+
+ float sample;
+ int average=0;
+ char *p;
+ p=pixels;
+ for(i=0;i<width;i++) {
+ sample=data[i]+get_attenuation();
+ average+=(int)sample;
+ if(sample<lowThreshold) {
+ *p++=colorLowR;
+ *p++=colorLowG;
+ *p++=colorLowB;
+ } else if(sample>highThreshold) {
+ *p++=colorHighR;
+ *p++=colorHighG;
+ *p++=colorHighB;
+ } else {
+ float range=highThreshold-lowThreshold;
+ float offset=sample-lowThreshold;
+ float percent=offset/range;
+ if(percent<(2.0f/9.0f)) {
+ float local_percent = percent / (2.0f/9.0f);
+ *p++ = (int)((1.0f-local_percent)*colorLowR);
+ *p++ = (int)((1.0f-local_percent)*colorLowG);
+ *p++ = (int)(colorLowB + local_percent*(255-colorLowB));
+ } else if(percent<(3.0f/9.0f)) {
+ float local_percent = (percent - 2.0f/9.0f) / (1.0f/9.0f);
+ *p++ = 0;
+ *p++ = (int)(local_percent*255);
+ *p++ = 255;
+ } else if(percent<(4.0f/9.0f)) {
+ float local_percent = (percent - 3.0f/9.0f) / (1.0f/9.0f);
+ *p++ = 0;
+ *p++ = 255;
+ *p++ = (int)((1.0f-local_percent)*255);
+ } else if(percent<(5.0f/9.0f)) {
+ float local_percent = (percent - 4.0f/9.0f) / (1.0f/9.0f);
+ *p++ = (int)(local_percent*255);
+ *p++ = 255;
+ *p++ = 0;
+ } else if(percent<(7.0f/9.0f)) {
+ float local_percent = (percent - 5.0f/9.0f) / (2.0f/9.0f);
+ *p++ = 255;
+ *p++ = (int)((1.0f-local_percent)*255);
+ *p++ = 0;
+ } else if(percent<(8.0f/9.0f)) {
+ float local_percent = (percent - 7.0f/9.0f) / (1.0f/9.0f);
+ *p++ = 255;
+ *p++ = 0;
+ *p++ = (int)(local_percent*255);
+ } else {
+ float local_percent = (percent - 8.0f/9.0f) / (1.0f/9.0f);
+ *p++ = (int)((0.75f + 0.25f*(1.0f-local_percent))*255.0f);
+ *p++ = (int)(local_percent*255.0f*0.5f);
+ *p++ = 255;
+ }
+ }
+
+ }
+
+
+ lowThreshold=(float)((average/display_width));
+ highThreshold=lowThreshold+50.0;
+
+ gtk_widget_queue_draw (waterfall);
+
+}
+
+GtkWidget* waterfall_init(int width,int height) {
+ display_width=width;
+ waterfall_height=height;
+
+ hz_per_pixel=(double)getSampleRate()/(double)display_width;
+
+ //waterfall_frame = gtk_frame_new (NULL);
+ waterfall = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (waterfall, width, height);
+
+ /* Signals used to handle the backing surface */
+ g_signal_connect (waterfall, "draw",
+ G_CALLBACK (waterfall_draw_cb), NULL);
+ g_signal_connect (waterfall,"configure-event",
+ G_CALLBACK (waterfall_configure_event_cb), NULL);
+
+ pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+
+ /* Event signals */
+ g_signal_connect (waterfall, "motion-notify-event",
+ G_CALLBACK (waterfall_motion_notify_event_cb), NULL);
+ g_signal_connect (waterfall, "button-press-event",
+ G_CALLBACK (waterfall_button_press_event_cb), NULL);
+ g_signal_connect (waterfall, "button-release-event",
+ G_CALLBACK (waterfall_button_release_event_cb), NULL);
+
+ /* Ask to receive events the drawing area doesn't normally
+ * subscribe to. In particular, we need to ask for the
+ * button press and motion notify events that want to handle.
+ */
+ gtk_widget_set_events (waterfall, gtk_widget_get_events (waterfall)
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_BUTTON1_MOTION_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK);
+
+ return waterfall;
+}
--- /dev/null
+
+void waterfall_update(float *data);
+GtkWidget* waterfall_init(int width,int height);
--- /dev/null
+/**
+* @file xvtr.h
+* @brief XVTR definition files
+* @author John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* @version 0.1
+* @date 2009-04-11
+*/
+// xvtr.h
+
+/* Copyright (C)
+* This program is free software; you can redistribute it and/or2009 - John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+*/
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief XVTR definition
+*/
+struct _XVTR_ENTRY {
+ char name[32];
+ long long rxFrequency;
+ long long rxFrequencyMin;
+ long long rxFrequencyMax;
+ long long rxFrequencyLO;
+ long long txFrequency;
+ long long txFrequencyMin;
+ long long txFrequencyMax;
+ long long txFrequencyLO;
+ int fullDuplex;
+ int mode;
+ int filter;
+ int var1Low;
+ int var1High;
+ int var2Low;
+ int var2High;
+ int step;
+ int preamp;
+ int alexRxAntenna;
+ int alexTxAntenna;
+ int alexAttenuation;
+};
+
+typedef struct _XVTR_ENTRY XVTR_ENTRY;
+