# uncomment the line below to include support for STEMlab discovery
#STEMLAB_DISCOVERY=STEMLAB_DISCOVERY
++#uncomment the line below for the platform being compiled on
++UNAME_N=raspberrypi
++#UNAME_N=odroid
++#UNAME_N=up
++#UNAME_N=pine64
++#UNAME_N=jetsen
++
CC=gcc
LINK=gcc
ifeq ($(LOCALCW_INCLUDE),LOCALCW)
LOCALCW_OPTIONS=-D LOCALCW
LOCALCW_SOURCES= \
+ beep.c \
iambic.c
LOCALCW_HEADERS= \
+ beep.h \
iambic.h
LOCALCW_OBJS= \
-beep.o \
iambic.o
endif
ifeq ($(GPIO_INCLUDE),GPIO)
GPIO_OPTIONS=-D GPIO
- GPIO_LIBS=-lwiringPi -lpigpio
- GPIO_LIBS=-lwiringPi
++ GPIO_LIBS=-lwiringPi -lpigpio
GPIO_SOURCES= \
gpio.c \
encoder_menu.c
# uncomment the line below to include GPIO
GPIO_INCLUDE=GPIO
++# uncomment the line below to include MCP23017 I2C
++#I2C_INCLUDE=I2C
++
# uncomment the line below to include USB Ozy support
--USBOZY_INCLUDE=USBOZY
++# USBOZY_INCLUDE=USBOZY
# uncomment the line below to include support for psk31
#PSK_INCLUDE=PSK
# uncomment the line to below include support for FreeDV codec2
--#FREEDV_INCLUDE=FREEDV
++FREEDV_INCLUDE=FREEDV
++
++# uncomment the line below to include Pure Signal support
++#PURESIGNAL_INCLUDE=PURESIGNAL
++
++# uncomment the line below to include Pure Signal support
++#PURESIGNAL_INCLUDE=PURESIGNAL
# uncomment the line to below include support for sx1509 i2c expander
#SX1509_INCLUDE=sx1509
# uncomment the line to below include support local CW keyer
--#LOCALCW_INCLUDE=LOCALCW
++LOCALCW_INCLUDE=LOCALCW
--# uncomment the line below to include MCP23017 I2C
--#I2C_INCLUDE=I2C
--
--#uncomment the line below for the platform being compiled on
--UNAME_N=raspberrypi
--#UNAME_N=odroid
--#UNAME_N=up
--#UNAME_N=pine64
--#UNAME_N=x86
++# uncomment the line below to include support for STEMlab discovery
++#STEMLAB_DISCOVERY=STEMLAB_DISCOVERY
CC=gcc
LINK=gcc
# uncomment the line below for various debug facilities
#DEBUG_OPTION=-D DEBUG
++ifeq ($(PURESIGNAL_INCLUDE),PURESIGNAL)
++PURESIGNAL_OPTIONS=-D PURESIGNAL
++PURESIGNAL_SOURCES= \
++ps_menu.c
++PURESIGNAL_HEADERS= \
++ps_menu.h
++PURESIGNAL_OBJS= \
++ps_menu.o
++endif
++
++ifeq ($(REMOTE_INCLUDE),REMOTE)
++REMOTE_OPTIONS=-D REMOTE
++REMOTE_SOURCES= \
++remote_radio.c \
++remote_receiver.c
++REMOTE_HEADERS= \
++remote_radio.h \
++remote_receiver.h
++REMOTE_OBJS= \
++remote_radio.o \
++remote_receiver.o
++endif
++
ifeq ($(USBOZY_INCLUDE),USBOZY)
USBOZY_OPTIONS=-D USBOZY
USBOZY_LIBS=-lusb-1.0
ifeq ($(RADIOBERRY_INCLUDE),RADIOBERRY)
RADIOBERRY_OPTIONS=-D RADIOBERRY
++RADIOBERRYLIBS=-lpigpio
RADIOBERRY_SOURCES= \
radioberry_discovery.c \
radioberry.c
ifeq ($(LOCALCW_INCLUDE),LOCALCW)
LOCALCW_OPTIONS=-D LOCALCW
LOCALCW_SOURCES= \
--beep.c \
iambic.c
LOCALCW_HEADERS= \
--beep.h \
iambic.h
LOCALCW_OBJS= \
--beep.o \
iambic.o
endif
ifeq ($(GPIO_INCLUDE),GPIO)
GPIO_OPTIONS=-D GPIO
<<<<<<< HEAD
-- GPIO_LIBS=-lwiringPi -lpigpio
-- endif
-- ifeq ($(UNAME_N),odroid)
-- GPIO_LIBS=-lwiringPi
-- endif
-- ifeq ($(SX1509_INCLUDE),sx1509)
-- GPIO_OPTIONS=-D GPIO
-- GPIO_OPTIONS+=-D sx1509
-- GPIO_LIBS+=-lsx1509
-- endif
--=======
GPIO_LIBS=-lwiringPi -lpigpio
++=======
++ GPIO_LIBS=-lwiringPi
>>>>>>> upstream/master
GPIO_SOURCES= \
gpio.c \
I2C_OBJS=i2c.o
endif
--#uncomment if build for SHORT FRAMES (MIC and Audio)
--SHORT_FRAMES=-D SHORT_FRAMES
++ifeq ($(STEMLAB_DISCOVERY), STEMLAB_DISCOVERY)
++STEMLAB_OPTIONS=-D STEMLAB_DISCOVERY \
++ `pkg-config --cflags avahi-gobject` \
++ `pkg-config --cflags libcurl`
++STEMLAB_LIBS=`pkg-config --libs avahi-gobject` `pkg-config --libs libcurl`
++STEMLAB_SOURCES=stemlab_discovery.c
++STEMLAB_HEADERS=stemlab_discovery.h
++STEMLAB_OBJS=stemlab_discovery.o
++endif
GTKINCLUDES=`pkg-config --cflags gtk+-3.0`
GTKLIBS=`pkg-config --libs gtk+-3.0`
AUDIO_LIBS=-lasound
#AUDIO_LIBS=-lsoundio
++OPTIONS=-g -Wno-deprecated-declarations $(PURESIGNAL_OPTIONS) $(REMOTE_OPTIONS) $(RADIOBERRY_OPTIONS) $(USBOZY_OPTIONS) $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(PSK_OPTIONS) $(STEMLAB_OPTIONS) -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
++
<<<<<<< HEAD
--OPTIONS=-g -D $(UNAME_N) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(RADIOBERRY_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(PSK_OPTIONS) $(SHORT_FRAMES) -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
++LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(RADIOBERRYLIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS) $(STEMLAB_LIBS)
=======
--OPTIONS=-g -Wno-deprecated-declarations -D $(UNAME_N) $(USBOZY_OPTIONS) $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(PSK_OPTIONS) $(SHORT_FRAMES) -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
++LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS) $(STEMLAB_LIBS)
>>>>>>> upstream/master
--
--LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS)
INCLUDES=$(GTKINCLUDES)
COMPILE=$(CC) $(OPTIONS) $(INCLUDES)
++.c.o:
++ $(COMPILE) -c -o $@ $<
++
PROGRAM=pihpsdr
SOURCES= \
audio.c \
++audio_waterfall.c \
band.c \
configure.c \
frequency.c \
filter.c \
main.c \
new_menu.c \
++about_menu.c \
exit_menu.c \
radio_menu.c \
rx_menu.c \
noise_menu.c \
agc_menu.c \
vox_menu.c \
++fft_menu.c \
diversity_menu.c \
freqent_menu.c \
tx_menu.c \
radio.c \
receiver.c \
rigctl.c \
++rigctl_menu.c \
toolbar.c \
transmitter.c \
sliders.c \
update.c \
store.c \
store_menu.c \
--memory.c
++memory.c \
++led.c \
++ext.c \
++error_handler.c
HEADERS= \
audio.h \
++audio_waterfall.h \
agc.h \
alex.h \
band.h \
discovery.h \
filter.h \
new_menu.h \
++about_menu.h \
rx_menu.h \
exit_menu.h \
radio_menu.h \
noise_menu.h \
agc_menu.h \
vox_menu.h \
++fft_menu.h \
diversity_menu.h \
freqent_menu.h \
tx_menu.h \
radio.h \
receiver.h \
rigctl.h \
++rigctl_menu.h \
toolbar.h \
transmitter.h \
sliders.h \
update.h \
store.h \
store_menu.h \
--memory.h
++memory.h \
++led.h \
++ext.h \
++error_handler.h
OBJS= \
audio.o \
++audio_waterfall.o \
band.o \
configure.o \
frequency.o \
version.o \
main.o \
new_menu.o \
++about_menu.o \
rx_menu.o \
exit_menu.o \
radio_menu.o \
noise_menu.o \
agc_menu.o \
vox_menu.o \
++fft_menu.o \
diversity_menu.o \
freqent_menu.o \
tx_menu.o \
radio.o \
receiver.o \
rigctl.o \
++rigctl_menu.o \
toolbar.o \
transmitter.o \
sliders.o \
update.o \
store.o \
store_menu.o \
--memory.o
++memory.o \
++led.o \
++ext.o \
++error_handler.o
--<<<<<<< HEAD
--all: prebuild $(PROGRAM) $(HEADERS) $(LIMESDR_HEADERS) $(RADIOBERRY_HEADERS) $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) $(SOURCES) $(LIMESDR_SOURCES) $(RADIOBERRY_SOURCES) $(FREEDV_SOURCES) $(GPIO_SOURCES) $(PSK_SOURCES)
--=======
--all: prebuild $(PROGRAM) $(HEADERS) $(USBOZY_HEADERS) $(LIMESDR_HEADERS) $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(I2C_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) $(SOURCES) $(USBOZY_SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) $(PSK_SOURCES)
-->>>>>>> upstream/master
++$(PROGRAM): $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(PSK_OBJS) $(RADIOBERRY_OBJS) $(PURESIGNAL_OBJS) $(STEMLAB_OBJS)
++ $(LINK) -o $(PROGRAM) $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(LIBS) $(RADIOBERRY_OBJS) $(PURESIGNAL_OBJS) $(STEMLAB_OBJS)
++
++all: prebuild $(PROGRAM) $(HEADERS) $(REMOTE_HEADERS) $(RADIOBERRY_HEADERS) $(USBOZY_HEADERS) $(LIMESDR_HEADERS) $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(I2C_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) $(PURESIGNAL_HEADERS) $(STEMLAB_HEADERS) $(SOURCES) $(REMOTE_SOURCES) $(USBOZY_SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) $(PSK_SOURCES) $(RADIOBERRY_SOURCES) $(PURESIGNAL_SOURCES) $(STEMLAB_SOURCES)
prebuild:
rm -f version.o
--<<<<<<< HEAD
--$(PROGRAM): $(OBJS) $(LIMESDR_OBJS) $(RADIOBERRY_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(GPIO_OBJS) $(PSK_OBJS)
-- $(LINK) -o $(PROGRAM) $(OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(RADIOBERRY_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(LIBS)
--=======
--$(PROGRAM): $(OBJS) $(USBOZY_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(PSK_OBJS)
-- $(LINK) -o $(PROGRAM) $(OBJS) $(USBOZY_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(LIBS)
-->>>>>>> upstream/master
--
--.c.o:
-- $(COMPILE) -c -o $@ $<
--
--
clean:
-rm -f *.o
-rm -f $(PROGRAM)
--install:
-- cp pihpsdr ../pihpsdr
-- cp pihpsdr ./release/pihpsdr
-- cd release; echo $(GIT_VERSION) > pihpsdr/latest
-- cd release; tar cvf pihpsdr_$(GIT_VERSION).tar pihpsdr
++install: $(PROGRAM)
++ cp $(PROGRAM) /usr/local/bin
++
++release: $(PROGRAM)
++ cp $(PROGRAM) release/pihpsdr
cd release; tar cvf pihpsdr.tar pihpsdr
++ cd release; tar cvf pihpsdr-$(GIT_VERSION).tar pihpsdr
rx->playback_offset=0;
rx->playback_buffer=(unsigned char *)malloc(OUTPUT_BUFFER_SIZE);
+
+ playback_cw_buffer = (unsigned char *)malloc(OUTPUT_BUFFER_SIZE);
+ fprintf(stderr,"audio_open_output: rx=%d audio_device=%d handle=%p buffer=%p\n",rx->id,rx->audio_device,rx->playback_handle,rx->playback_buffer);
return 0;
}
int settle_time=DEFAULT_SETTLE_TIME;
static gint release_timer=-1;
--
++#ifdef RADIOBERRY
++#include <pigpio.h>
++#endif
#ifdef CONTROLLER2
if(value) ENABLE_E4_BUTTON=atoi(value);
#endif
- #ifdef LOCALCW
- value=getProperty("ENABLE_CW_BUTTONS");
- if(value) ENABLE_CW_BUTTONS=atoi(value);
- value=getProperty("CWL_BUTTON");
- if(value) CWL_BUTTON=atoi(value);
- value=getProperty("CWR_BUTTON");
- if(value) CWR_BUTTON=atoi(value);
- #endif
+
}
void gpio_save_state() {
wiringPiISR(pin,INT_EDGE_RISING,pAlert);
}
-
+#ifdef LOCALCW
+#ifdef RADIOBERRY
+#define BUTTON_STEADY_TIME_US 5000
+static void setup_button(int button, gpioAlertFunc_t pAlert) {
+ gpioSetMode(button, PI_INPUT);
+ gpioSetPullUpDown(button,PI_PUD_UP);
+ // give time to settle to avoid false triggers
+ usleep(10000);
+ gpioSetAlertFunc(button, pAlert);
+ gpioGlitchFilter(button, BUTTON_STEADY_TIME_US);
+}
+
+static void cwAlert(int gpio, int level, uint32_t tick) {
+ //fprintf(stderr,"cw key at pin %d \n", gpio);
+ if (cw_keyer_internal == 0 ){
+ //fprintf(stderr,"call keyer_event...\n");
+ keyer_event(gpio, cw_active_level == 0 ? level : (level==0));
+ }
+}
+
+/*
+static unsigned long cwl_debounce=0;
+static void cwlAlert() {
+ int t=millis();
+ if(t - cwl_debounce > settle_time) {
+ int level=digitalRead(CWL_BUTTON);
+ if (cw_keyer_internal == 0 ){
+ fprintf(stderr,"call keyer_event CWL Button \n");
+ keyer_event(CWL_BUTTON, cw_active_level == 0 ? level : (level==0));
+ }
+ cwl_debounce=t;
+ }
+}
+static unsigned long cwr_debounce=0;
+static void cwrAlert() {
+ int t=millis();
+ if(t - cwr_debounce > settle_time) {
+ int level=digitalRead(CWR_BUTTON);
+ if (cw_keyer_internal == 0 ){
+ fprintf(stderr,"call keyer_event CWR Button \n");
+ keyer_event(CWR_BUTTON, cw_active_level == 0 ? level : (level==0));
+ }
+ cwr_debounce=t;
+ }
+}
+*/
+#endif
+#endif
+
int gpio_init() {
int i;
--- /dev/null
--- /dev/null
++/* Copyright (C)
++* 2015 - John Melton, G0ORX/N6LYT
++*
++* 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 <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++#include <unistd.h>
++#include <stdint.h>
++#include <fcntl.h>
++#include <poll.h>
++#include <sched.h>
++#include <wiringPi.h>
++#include <semaphore.h>
++
++#include "band.h"
++#include "channel.h"
++#include "discovered.h"
++#include "mode.h"
++#include "filter.h"
++#include "bandstack.h"
++#include "toolbar.h"
++#include "gpio.h"
++#include "radio.h"
++#include "toolbar.h"
++#include "main.h"
++#include "property.h"
++#include "vfo.h"
++#include "wdsp.h"
++#ifdef PSK
++#include "psk.h"
++#endif
++#include "new_menu.h"
++#include "encoder_menu.h"
++#include "gpio.h"
++#ifdef CONTROLLER2
++#include "i2c.h"
++#endif
++#include "ext.h"
++#include "sliders.h"
++
++<<<<<<< HEAD
++#ifdef RADIOBERRY
++#include <pigpio.h>
++#endif
++
++// debounce settle time in ms
++#define DEFAULT_SETTLE_TIME 150
++
++int settle_time=DEFAULT_SETTLE_TIME;
++static gint release_timer=-1;
++
++
++=======
++// debounce settle time in ms
++#define DEFAULT_SETTLE_TIME 150
++
++int settle_time=DEFAULT_SETTLE_TIME;
++static gint release_timer=-1;
++
++
++>>>>>>> upstream/master
++#ifdef CONTROLLER2
++
++int ENABLE_VFO_ENCODER=1;
++int ENABLE_VFO_PULLUP=0;
++int VFO_ENCODER_A=1;
++int VFO_ENCODER_B=0;
++#ifdef VFO_HAS_FUNCTION
++int VFO_FUNCTION=12;
++#endif
++int ENABLE_E1_ENCODER=1;
++int ENABLE_E1_PULLUP=0;
++int E1_ENCODER_A=28;
++int E1_ENCODER_B=25;
++int E1_FUNCTION=3;
++int ENABLE_E2_ENCODER=1;
++int ENABLE_E2_PULLUP=0;
++int E2_ENCODER_A=7;
++int E2_ENCODER_B=29;
++int E2_FUNCTION=2;
++int ENABLE_E3_ENCODER=1;
++int ENABLE_E3_PULLUP=0;
++int E3_ENCODER_A=27;
++int E3_ENCODER_B=24;
++int E3_FUNCTION=4;
++int ENABLE_E4_ENCODER=1;
++int ENABLE_E4_PULLUP=0;
++int E4_ENCODER_A=6;
++int E4_ENCODER_B=10;
++int E4_FUNCTION=5;
++
++int ENABLE_E1_BUTTON=1;
++int ENABLE_E2_BUTTON=1;
++int ENABLE_E3_BUTTON=1;
++int ENABLE_E4_BUTTON=1;
++
++int I2C_INTERRUPT=16;
++
++#else
++// uses wiringpi pin numbers
++int ENABLE_VFO_ENCODER=1;
++int ENABLE_VFO_PULLUP=1;
++int VFO_ENCODER_A=1;
++int VFO_ENCODER_B=0;
++int ENABLE_E1_ENCODER=1;
++int ENABLE_E1_PULLUP=0;
++int E1_ENCODER_A=28;
++int E1_ENCODER_B=25;
++int E1_FUNCTION=6;
++int ENABLE_E2_ENCODER=1;
++int ENABLE_E2_PULLUP=0;
++int E2_ENCODER_A=27;
++int E2_ENCODER_B=24;
++int E2_FUNCTION=10;
++int ENABLE_E3_ENCODER=1;
++int ENABLE_E3_PULLUP=0;
++int E3_ENCODER_A=7;
++int E3_ENCODER_B=29;
++int E3_FUNCTION=11;
++int ENABLE_S1_BUTTON=1;
++int S1_BUTTON=23;
++int ENABLE_S2_BUTTON=1;
++int S2_BUTTON=26;
++int ENABLE_S3_BUTTON=1;
++int S3_BUTTON=22;
++int ENABLE_S4_BUTTON=1;
++int S4_BUTTON=21;
++int ENABLE_S5_BUTTON=1;
++int S5_BUTTON=5;
++int ENABLE_S6_BUTTON=1;
++int S6_BUTTON=4;
++int ENABLE_MOX_BUTTON=1;
++int MOX_BUTTON=2;
++int ENABLE_FUNCTION_BUTTON=1;
++int FUNCTION_BUTTON=3;
++int ENABLE_E1_BUTTON=1;
++int ENABLE_E2_BUTTON=1;
++int ENABLE_E3_BUTTON=1;
++int ENABLE_CW_BUTTONS=1;
++#endif
++<<<<<<< HEAD
++#ifdef LOCALCW
++int CWL_BUTTON=1;
++int CWR_BUTTON=24;
++#endif
++=======
++
++>>>>>>> upstream/master
++
++static volatile int vfoEncoderPos;
++static volatile int vfo_A;
++static volatile int vfo_B;
++static volatile int vfoFunction;
++static volatile int e1EncoderPos;
++static volatile int e1Function;
++int e1_encoder_action=ENCODER_AF_GAIN;
++static volatile int e2EncoderPos;
++static volatile int e2Function;
++int e2_encoder_action=ENCODER_DRIVE;
++static volatile int e3EncoderPos;
++static volatile int e3Function;
++int e3_encoder_action=ENCODER_ATTENUATION;
++#ifdef CONTROLLER2
++static volatile int e4EncoderPos;
++static volatile int e4Function;
++int e4_encoder_action=ENCODER_MIC_GAIN;
++#endif
++static volatile int function_state;
++static volatile int band_state;
++static volatile int bandstack_state;
++static volatile int mode_state;
++static volatile int filter_state;
++static volatile int noise_state;
++static volatile int agc_state;
++static volatile int mox_state;
++static volatile int lock_state;
++
++static gpointer rotary_encoder_thread(gpointer data);
++static GThread *rotary_encoder_thread_id;
++
++static int previous_function_button=0;
++static int e1_function=0;
++static int previous_e1_function=0;
++static int e2_function=0;
++static int previous_e2_function=0;
++static int e3_function=0;
++static int previous_e3_function=0;
++#ifdef CONTROLLER2
++static int e4_function=0;
++static int previous_e4_function=0;
++#endif
++static int band_button=0;
++static int previous_band_button=0;
++static int bandstack_button=0;
++static int previous_bandstack_button=0;
++static int mode_button=0;
++static int previous_mode_button=0;
++static int filter_button=0;
++static int previous_filter_button=0;
++static int noise_button=0;
++static int previous_noise_button=0;
++static int agc_button=0;
++static int previous_agc_button=0;
++static int mox_button=0;
++static int previous_mox_button=0;
++
++static int running=0;
++
++char *encoder_string[] = {
++"AF GAIN",
++"AGC GAIN",
++"ATTENUATION",
++"MIC GAIN",
++"DRIVE",
++"RIT",
++"CW SPEED",
++"CW FREQUENCY",
++"PANADAPTER HIGH",
++"PANADAPTER LOW",
++"SQUELCH",
++"COMP"
++};
++
++static int mox_pressed(void *data) {
++ if(running) sim_mox_cb(NULL,NULL);
++ return 0;
++}
++
++static int s1_pressed(void *data) {
++ if(running) sim_s1_pressed_cb(NULL,NULL);
++ return 0;
++}
++
++static int s1_released(void *data) {
++ if(running) sim_s1_released_cb(NULL,NULL);
++ return 0;
++}
++
++static int s2_pressed(void *data) {
++ if(running) sim_s2_pressed_cb(NULL,NULL);
++ return 0;
++}
++
++static int s2_released(void *data) {
++ if(running) sim_s2_released_cb(NULL,NULL);
++ return 0;
++}
++
++static int s3_pressed(void *data) {
++ if(running) sim_s3_pressed_cb(NULL,NULL);
++ return 0;
++}
++
++static int s3_released(void *data) {
++ if(running) sim_s3_released_cb(NULL,NULL);
++ return 0;
++}
++
++static int s4_pressed(void *data) {
++ if(running) sim_s4_pressed_cb(NULL,NULL);
++ return 0;
++}
++
++static int s4_released(void *data) {
++ if(running) sim_s4_released_cb(NULL,NULL);
++ return 0;
++}
++
++static int s5_pressed(void *data) {
++ if(running) sim_s5_pressed_cb(NULL,NULL);
++ return 0;
++}
++
++static int s5_released(void *data) {
++ if(running) sim_s5_released_cb(NULL,NULL);
++ return 0;
++}
++
++static int s6_pressed(void *data) {
++ if(running) sim_s6_pressed_cb(NULL,NULL);
++ return 0;
++}
++
++static int s6_released(void *data) {
++ if(running) sim_s6_released_cb(NULL,NULL);
++ return 0;
++}
++
++static int function_pressed(void *data) {
++ if(running) sim_function_cb(NULL,NULL);
++ return 0;
++}
++
++static int vfo_function_pressed(void *data) {
++ RECEIVER *rx;
++ if(receivers==2) {
++ if(active_receiver==receiver[0]) {
++ rx=receiver[1];
++ } else {
++ rx=receiver[0];
++ }
++ active_receiver=rx;
++ g_idle_add(menu_active_receiver_changed,NULL);
++ g_idle_add(ext_vfo_update,NULL);
++ g_idle_add(sliders_active_receiver_changed,NULL);
++ }
++ return 0;
++}
++
++static int vfo_function_released(void *data) {
++ return 0;
++}
++
++static int e_function_pressed(void *data) {
++ int encoder=(int)data;
++ start_encoder(encoder);
++ return 0;
++}
++
++static unsigned long e1debounce=0;
++
++static void e1FunctionAlert() {
++ int level=digitalRead(E1_FUNCTION);
++ if(level==0) {
++ if(running) g_idle_add(e_function_pressed,(gpointer)1);
++ }
++}
++
++static unsigned long e2debounce=0;
++
++static void e2FunctionAlert() {
++ int level=digitalRead(E2_FUNCTION);
++ if(level==0) {
++ if(running) g_idle_add(e_function_pressed,(gpointer)2);
++ }
++}
++
++static unsigned long e3debounce=0;
++
++static void e3FunctionAlert() {
++ int level=digitalRead(E3_FUNCTION);
++ if(level==0) {
++ if(running) g_idle_add(e_function_pressed,(gpointer)3);
++ }
++}
++
++#ifdef CONTROLLER2
++static unsigned long e4debounce=0;
++
++static void e4FunctionAlert() {
++ int level=digitalRead(E4_FUNCTION);
++ if(level==0) {
++ if(running) g_idle_add(e_function_pressed,(gpointer)4);
++ }
++}
++#endif
++
++#ifndef CONTROLLER2
++static unsigned long function_debounce=0;
++
++static void functionAlert() {
++ int t=millis();
++ if(t-function_debounce > settle_time) {
++ int level=digitalRead(FUNCTION_BUTTON);
++ if(level==0) {
++ if(running) g_idle_add(function_pressed,NULL);
++ }
++ function_debounce=t;
++ }
++}
++
++static unsigned long s1_debounce=0;
++static gint s1_timer=-1;
++
++static gboolean s1_timer_cb(gpointer data) {
++ int level=digitalRead(S1_BUTTON);
++ if(level==1) {
++ s1_timer=-1;
++ g_idle_add(s1_released,NULL);
++ return FALSE;
++ }
++ return TRUE;
++}
++
++static void s1Alert() {
++ int t=millis();
++ if(t-s1_debounce > settle_time) {
++ int level=digitalRead(S1_BUTTON);
++ if(level==0) {
++ g_idle_add(s1_pressed,NULL);
++ s1_timer=g_timeout_add(settle_time,s1_timer_cb,NULL);
++ } else {
++ if(s1_timer!=-1) {
++ g_source_remove(s1_timer);
++ s1_timer==-1;
++ }
++ g_idle_add(s1_released,NULL);
++ }
++ s1_debounce=t;
++ }
++}
++
++static unsigned long s2_debounce=0;
++static gint s2_timer=-1;
++
++static gboolean s2_timer_cb(gpointer data) {
++ int level=digitalRead(S2_BUTTON);
++ if(level==1) {
++ s2_timer=-1;
++ g_idle_add(s2_released,NULL);
++ return FALSE;
++ }
++ return TRUE;
++}
++
++static void s2Alert() {
++ int t=millis();
++ if(t-s2_debounce > settle_time) {
++ int level=digitalRead(S2_BUTTON);
++ if(level==0) {
++ g_idle_add(s2_pressed,NULL);
++ s2_timer=g_timeout_add(settle_time,s2_timer_cb,NULL);
++ } else {
++ if(s2_timer!=-1) {
++ g_source_remove(s2_timer);
++ s2_timer==-1;
++ }
++ g_idle_add(s2_released,NULL);
++ }
++ s2_debounce=t;
++ }
++}
++
++static unsigned long s3_debounce=0;
++static gint s3_timer=-1;
++
++static gboolean s3_timer_cb(gpointer data) {
++ int level=digitalRead(S3_BUTTON);
++ if(level==1) {
++ s3_timer=-1;
++ g_idle_add(s3_released,NULL);
++ return FALSE;
++ }
++ return TRUE;
++}
++
++static void s3Alert() {
++ int t=millis();
++ if(t-s3_debounce > settle_time) {
++ int level=digitalRead(S3_BUTTON);
++ if(level==0) {
++ g_idle_add(s3_pressed,NULL);
++ s3_timer=g_timeout_add(settle_time,s3_timer_cb,NULL);
++ } else {
++ if(s3_timer!=-1) {
++ g_source_remove(s3_timer);
++ s3_timer==-1;
++ }
++ g_idle_add(s3_released,NULL);
++ }
++ s3_debounce=t;
++ }
++}
++
++static unsigned long s4_debounce=0;
++static gint s4_timer=-1;
++
++static gboolean s4_timer_cb(gpointer data) {
++ int level=digitalRead(S4_BUTTON);
++ if(level==1) {
++ s4_timer=-1;
++ g_idle_add(s4_released,NULL);
++ return FALSE;
++ }
++ return TRUE;
++}
++
++static void s4Alert() {
++ int t=millis();
++ if(t-s4_debounce > settle_time) {
++ int level=digitalRead(S4_BUTTON);
++ if(level==0) {
++ g_idle_add(s4_pressed,NULL);
++ s4_timer=g_timeout_add(settle_time,s4_timer_cb,NULL);
++ } else {
++ if(s4_timer!=-1) {
++ g_source_remove(s4_timer);
++ s4_timer==-1;
++ }
++ g_idle_add(s4_released,NULL);
++ }
++ s4_debounce=t;
++ }
++}
++
++static unsigned long s5_debounce=0;
++static gint s5_timer=-1;
++
++static gboolean s5_timer_cb(gpointer data) {
++ int level=digitalRead(S5_BUTTON);
++ if(level==1) {
++ s5_timer=-1;
++ g_idle_add(s5_released,NULL);
++ return FALSE;
++ }
++ return TRUE;
++}
++
++static void s5Alert() {
++ int t=millis();
++ if(t-s5_debounce > settle_time) {
++ int level=digitalRead(S5_BUTTON);
++ if(level==0) {
++ g_idle_add(s5_pressed,NULL);
++ s5_timer=g_timeout_add(settle_time,s5_timer_cb,NULL);
++ } else {
++ if(s5_timer!=-1) {
++ g_source_remove(s5_timer);
++ s5_timer==-1;
++ }
++ g_idle_add(s5_released,NULL);
++ }
++ s5_debounce=t;
++ }
++}
++
++static unsigned long s6_debounce=0;
++static gint s6_timer=-1;
++
++static gboolean s6_timer_cb(gpointer data) {
++ int level=digitalRead(S6_BUTTON);
++ if(level==1) {
++ s6_timer=-1;
++ g_idle_add(s6_released,NULL);
++ return FALSE;
++ }
++ return TRUE;
++}
++
++static void s6Alert() {
++ int t=millis();
++ if(t-s6_debounce > settle_time) {
++ int level=digitalRead(S6_BUTTON);
++ if(level==0) {
++ g_idle_add(s6_pressed,NULL);
++ s6_timer=g_timeout_add(settle_time,s6_timer_cb,NULL);
++ } else {
++ if(s6_timer!=-1) {
++ g_source_remove(s6_timer);
++ s6_timer==-1;
++ }
++ g_idle_add(s6_released,NULL);
++ }
++ s6_debounce=t;
++ }
++}
++
++static unsigned long mox_debounce=0;
++
++static void moxAlert() {
++ int t=millis();
++ if(t-mox_debounce > settle_time) {
++ int level=digitalRead(MOX_BUTTON);
++ if(level==0) {
++ g_idle_add(mox_pressed,(gpointer)NULL);
++ }
++ mox_debounce=t;
++ }
++}
++#endif
++
++
++#ifdef VFO_HAS_FUNCTION
++static unsigned long vfo_debounce=0;
++
++static void vfoFunctionAlert() {
++ int t=millis();
++ if(t-vfo_debounce > settle_time) {
++ int level=digitalRead(VFO_FUNCTION);
++ if(level==0) {
++ if(running) g_idle_add(vfo_function_pressed,NULL);
++ } else {
++ if(running) g_idle_add(vfo_function_released,NULL);
++ }
++ vfo_debounce=t;
++ }
++}
++#endif
++
++static void vfoEncoderInt(int A_or_B) {
++ int switch_A=digitalRead(VFO_ENCODER_A);
++ int switch_B=digitalRead(VFO_ENCODER_B);
++ if(vfo_A==switch_A && vfo_B==switch_B) {
++ return; // same as last
++ }
++ vfo_A=switch_A;
++ vfo_B=switch_B;
++ if(switch_A && switch_B) {
++ if(A_or_B==VFO_ENCODER_B) {
++ vfoEncoderPos--;
++ } else {
++ vfoEncoderPos++;
++ }
++ }
++}
++
++static void vfoEncoderA() {
++ vfoEncoderInt(VFO_ENCODER_A);
++}
++
++static void vfoEncoderB() {
++ vfoEncoderInt(VFO_ENCODER_B);
++}
++
++static void e1EncoderInterrupt(int gpio) {
++ static int e1CurrentA=1, e1CurrentB=1;
++
++ int levelA=digitalRead(E1_ENCODER_A);
++ int levelB=digitalRead(E1_ENCODER_B);
++
++ if(e1CurrentA==levelA && e1CurrentB==levelB) {
++ return;
++ }
++
++ e1CurrentA=levelA;
++ e1CurrentB=levelB;
++
++ if(levelA && levelB) {
++ if(gpio==E1_ENCODER_B) {
++ --e1EncoderPos;
++ } else {
++ ++e1EncoderPos;
++ }
++ }
++}
++
++static void e1EncoderA() {
++ e1EncoderInterrupt(E1_ENCODER_A);
++}
++
++static void e1EncoderB() {
++ e1EncoderInterrupt(E1_ENCODER_B);
++}
++
++static void e2EncoderInterrupt(int gpio) {
++ static int e2CurrentA=1, e2CurrentB=1;
++
++ int levelA=digitalRead(E2_ENCODER_A);
++ int levelB=digitalRead(E2_ENCODER_B);
++
++ if(e2CurrentA==levelA && e2CurrentB==levelB) {
++ return;
++ }
++
++ e2CurrentA=levelA;
++ e2CurrentB=levelB;
++
++ if(levelA && levelB) {
++ if(gpio==E2_ENCODER_B) {
++ --e2EncoderPos;
++ } else {
++ ++e2EncoderPos;
++ }
++ }
++}
++
++static void e2EncoderA() {
++ e2EncoderInterrupt(E2_ENCODER_A);
++}
++
++static void e2EncoderB() {
++ e2EncoderInterrupt(E2_ENCODER_B);
++}
++
++static void e3EncoderInterrupt(int gpio) {
++ static int e3CurrentA=1, e3CurrentB=1;
++
++ int levelA=digitalRead(E3_ENCODER_A);
++ int levelB=digitalRead(E3_ENCODER_B);
++
++ if(e3CurrentA==levelA && e3CurrentB==levelB) {
++ return;
++ }
++
++ e3CurrentA=levelA;
++ e3CurrentB=levelB;
++
++ if(levelA && levelB) {
++ if(gpio==E3_ENCODER_B) {
++ --e3EncoderPos;
++ } else {
++ ++e3EncoderPos;
++ }
++ }
++}
++
++static void e3EncoderA() {
++ e3EncoderInterrupt(E3_ENCODER_A);
++}
++
++static void e3EncoderB() {
++ e3EncoderInterrupt(E3_ENCODER_B);
++}
++
++#ifdef CONTROLLER2
++static void e4EncoderInterrupt(int gpio) {
++ static int e4CurrentA=1, e4CurrentB=1;
++
++ int levelA=digitalRead(E4_ENCODER_A);
++ int levelB=digitalRead(E4_ENCODER_B);
++
++ if(e4CurrentA==levelA && e4CurrentB==levelB) {
++ return;
++ }
++
++ e4CurrentA=levelA;
++ e4CurrentB=levelB;
++
++ if(levelA && levelB) {
++ if(gpio==E4_ENCODER_B) {
++ --e4EncoderPos;
++ } else {
++ ++e4EncoderPos;
++ }
++ }
++<<<<<<< HEAD
++}
++
++static void e4EncoderA() {
++ e4EncoderInterrupt(E4_ENCODER_A);
++=======
++}
++
++static void e4EncoderA() {
++ e4EncoderInterrupt(E4_ENCODER_A);
++}
++
++static void e4EncoderB() {
++ e4EncoderInterrupt(E4_ENCODER_B);
++>>>>>>> upstream/master
++}
++#endif
++
++<<<<<<< HEAD
++static void e4EncoderB() {
++ e4EncoderInterrupt(E4_ENCODER_B);
++}
++#endif
++
++=======
++>>>>>>> upstream/master
++#ifdef CONTROLLER2
++static void pI2CInterrupt() {
++ int level=digitalRead(I2C_INTERRUPT);
++ if(level==0) {
++ i2c_interrupt();
++ }
++}
++#endif
++
++void gpio_restore_state() {
++ char* value;
++ loadProperties("gpio.props");
++ value=getProperty("ENABLE_VFO_ENCODER");
++ if(value) ENABLE_VFO_ENCODER=atoi(value);
++ value=getProperty("ENABLE_VFO_PULLUP");
++ if(value) ENABLE_VFO_PULLUP=atoi(value);
++ value=getProperty("VFO_ENCODER_A");
++ if(value) VFO_ENCODER_A=atoi(value);
++ value=getProperty("VFO_ENCODER_B");
++ if(value) VFO_ENCODER_B=atoi(value);
++ value=getProperty("ENABLE_E1_ENCODER");
++ if(value) ENABLE_E1_ENCODER=atoi(value);
++ value=getProperty("ENABLE_E1_PULLUP");
++ if(value) ENABLE_E1_PULLUP=atoi(value);
++ value=getProperty("E1_ENCODER_A");
++ if(value) E1_ENCODER_A=atoi(value);
++ value=getProperty("E1_ENCODER_B");
++ if(value) E1_ENCODER_B=atoi(value);
++ value=getProperty("ENABLE_E2_ENCODER");
++ if(value) ENABLE_E2_ENCODER=atoi(value);
++ value=getProperty("ENABLE_E2_PULLUP");
++ if(value) ENABLE_E2_PULLUP=atoi(value);
++ value=getProperty("E2_ENCODER_A");
++ if(value) E2_ENCODER_A=atoi(value);
++ value=getProperty("E2_ENCODER_B");
++ if(value) E2_ENCODER_B=atoi(value);
++ value=getProperty("ENABLE_E3_ENCODER");
++ if(value) ENABLE_E3_ENCODER=atoi(value);
++ value=getProperty("ENABLE_E3_PULLUP");
++ if(value) ENABLE_E3_PULLUP=atoi(value);
++ value=getProperty("E3_ENCODER_A");
++ if(value) E3_ENCODER_A=atoi(value);
++ value=getProperty("E3_ENCODER_B");
++ if(value) E3_ENCODER_B=atoi(value);
++#ifdef CONTROLLER2
++ value=getProperty("ENABLE_E4_ENCODER");
++ if(value) ENABLE_E4_ENCODER=atoi(value);
++ value=getProperty("ENABLE_E4_PULLUP");
++ if(value) ENABLE_E4_PULLUP=atoi(value);
++ value=getProperty("E4_ENCODER_A");
++ if(value) E4_ENCODER_A=atoi(value);
++ value=getProperty("E4_ENCODER_B");
++ if(value) E4_ENCODER_B=atoi(value);
++#endif
++#ifndef CONTROLLER2
++ value=getProperty("ENABLE_S1_BUTTON");
++ if(value) ENABLE_S1_BUTTON=atoi(value);
++ value=getProperty("S1_BUTTON");
++ if(value) S1_BUTTON=atoi(value);
++ value=getProperty("ENABLE_S2_BUTTON");
++ if(value) ENABLE_S2_BUTTON=atoi(value);
++ value=getProperty("S2_BUTTON");
++ if(value) S2_BUTTON=atoi(value);
++ value=getProperty("ENABLE_S3_BUTTON");
++ if(value) ENABLE_S3_BUTTON=atoi(value);
++ value=getProperty("S3_BUTTON");
++ if(value) S3_BUTTON=atoi(value);
++ value=getProperty("ENABLE_S4_BUTTON");
++ if(value) ENABLE_S4_BUTTON=atoi(value);
++ value=getProperty("S4_BUTTON");
++ if(value) S4_BUTTON=atoi(value);
++ value=getProperty("ENABLE_S5_BUTTON");
++ if(value) ENABLE_S5_BUTTON=atoi(value);
++ value=getProperty("S5_BUTTON");
++ if(value) S5_BUTTON=atoi(value);
++ value=getProperty("ENABLE_S6_BUTTON");
++ if(value) ENABLE_S6_BUTTON=atoi(value);
++ value=getProperty("S6_BUTTON");
++ if(value) S6_BUTTON=atoi(value);
++ value=getProperty("ENABLE_FUNCTION_BUTTON");
++ if(value) ENABLE_FUNCTION_BUTTON=atoi(value);
++ value=getProperty("FUNCTION_BUTTON");
++ if(value) FUNCTION_BUTTON=atoi(value);
++ value=getProperty("ENABLE_MOX_BUTTON");
++ if(value) ENABLE_MOX_BUTTON=atoi(value);
++ value=getProperty("MOX_BUTTON");
++ if(value) MOX_BUTTON=atoi(value);
++#endif
++
++ value=getProperty("ENABLE_E1_BUTTON");
++ if(value) ENABLE_E1_BUTTON=atoi(value);
++ value=getProperty("ENABLE_E2_BUTTON");
++ if(value) ENABLE_E2_BUTTON=atoi(value);
++ value=getProperty("ENABLE_E3_BUTTON");
++ if(value) ENABLE_E3_BUTTON=atoi(value);
++#ifdef CONTROLLER2
++ value=getProperty("ENABLE_E4_BUTTON");
++ if(value) ENABLE_E4_BUTTON=atoi(value);
++#endif
++
++<<<<<<< HEAD
++#ifdef LOCALCW
++ value=getProperty("ENABLE_CW_BUTTONS");
++ if(value) ENABLE_CW_BUTTONS=atoi(value);
++ value=getProperty("CWL_BUTTON");
++ if(value) CWL_BUTTON=atoi(value);
++ value=getProperty("CWR_BUTTON");
++ if(value) CWR_BUTTON=atoi(value);
++#endif
++
++=======
++>>>>>>> upstream/master
++}
++
++void gpio_save_state() {
++ char value[80];
++
++ sprintf(value,"%d",ENABLE_VFO_ENCODER);
++ setProperty("ENABLE_VFO_ENCODER",value);
++ sprintf(value,"%d",ENABLE_VFO_PULLUP);
++ setProperty("ENABLE_VFO_PULLUP",value);
++ sprintf(value,"%d",VFO_ENCODER_A);
++ setProperty("VFO_ENCODER_A",value);
++ sprintf(value,"%d",VFO_ENCODER_B);
++ setProperty("VFO_ENCODER_B",value);
++ sprintf(value,"%d",ENABLE_E1_ENCODER);
++ setProperty("ENABLE_E1_ENCODER",value);
++ sprintf(value,"%d",ENABLE_E1_PULLUP);
++ setProperty("ENABLE_E1_PULLUP",value);
++ sprintf(value,"%d",E1_ENCODER_A);
++ setProperty("E1_ENCODER_A",value);
++ sprintf(value,"%d",E1_ENCODER_B);
++ setProperty("E1_ENCODER_B",value);
++ sprintf(value,"%d",ENABLE_E2_ENCODER);
++ setProperty("ENABLE_E2_ENCODER",value);
++ sprintf(value,"%d",ENABLE_E2_PULLUP);
++ setProperty("ENABLE_E2_PULLUP",value);
++ sprintf(value,"%d",E2_ENCODER_A);
++ setProperty("E2_ENCODER_A",value);
++ sprintf(value,"%d",E2_ENCODER_B);
++ setProperty("E2_ENCODER_B",value);
++ sprintf(value,"%d",ENABLE_E3_ENCODER);
++ setProperty("ENABLE_E3_ENCODER",value);
++ sprintf(value,"%d",ENABLE_E3_PULLUP);
++ setProperty("ENABLE_E3_PULLUP",value);
++ sprintf(value,"%d",E3_ENCODER_A);
++ setProperty("E3_ENCODER_A",value);
++ sprintf(value,"%d",E3_ENCODER_B);
++ setProperty("E3_ENCODER_B",value);
++#ifdef CONTROLLER2
++ sprintf(value,"%d",ENABLE_E4_ENCODER);
++ setProperty("ENABLE_E4_ENCODER",value);
++ sprintf(value,"%d",ENABLE_E4_PULLUP);
++ setProperty("ENABLE_E4_PULLUP",value);
++ sprintf(value,"%d",E4_ENCODER_A);
++ setProperty("E4_ENCODER_A",value);
++ sprintf(value,"%d",E4_ENCODER_B);
++ setProperty("E4_ENCODER_B",value);
++#endif
++#ifndef CONTROLLER2
++ sprintf(value,"%d",ENABLE_S1_BUTTON);
++ setProperty("ENABLE_S1_BUTTON",value);
++ sprintf(value,"%d",S1_BUTTON);
++ setProperty("S1_BUTTON",value);
++ sprintf(value,"%d",ENABLE_S2_BUTTON);
++ setProperty("ENABLE_S2_BUTTON",value);
++ sprintf(value,"%d",S2_BUTTON);
++ setProperty("S2_BUTTON",value);
++ sprintf(value,"%d",ENABLE_S3_BUTTON);
++ setProperty("ENABLE_S3_BUTTON",value);
++ sprintf(value,"%d",S3_BUTTON);
++ setProperty("S3_BUTTON",value);
++ sprintf(value,"%d",ENABLE_S4_BUTTON);
++ setProperty("ENABLE_S4_BUTTON",value);
++ sprintf(value,"%d",S4_BUTTON);
++ setProperty("S4_BUTTON",value);
++ sprintf(value,"%d",ENABLE_S5_BUTTON);
++ setProperty("ENABLE_S5_BUTTON",value);
++ sprintf(value,"%d",S5_BUTTON);
++ setProperty("S5_BUTTON",value);
++ sprintf(value,"%d",ENABLE_S6_BUTTON);
++ setProperty("ENABLE_S6_BUTTON",value);
++ sprintf(value,"%d",S6_BUTTON);
++ setProperty("S6_BUTTON",value);
++ sprintf(value,"%d",ENABLE_FUNCTION_BUTTON);
++ setProperty("ENABLE_FUNCTION_BUTTON",value);
++ sprintf(value,"%d",FUNCTION_BUTTON);
++ setProperty("FUNCTION_BUTTON",value);
++ sprintf(value,"%d",ENABLE_MOX_BUTTON);
++ setProperty("ENABLE_MOX_BUTTON",value);
++ sprintf(value,"%d",MOX_BUTTON);
++ setProperty("MOX_BUTTON",value);
++#endif
++
++ sprintf(value,"%d",ENABLE_E1_BUTTON);
++ setProperty("ENABLE_E1_BUTTON",value);
++ sprintf(value,"%d",ENABLE_E2_BUTTON);
++ setProperty("ENABLE_E2_BUTTON",value);
++ sprintf(value,"%d",ENABLE_E3_BUTTON);
++ setProperty("ENABLE_E3_BUTTON",value);
++#ifdef CONTROLLER2
++ sprintf(value,"%d",ENABLE_E4_BUTTON);
++ setProperty("ENABLE_E4_BUTTON",value);
++<<<<<<< HEAD
++#endif
++
++#ifdef LOCALCW
++ sprintf(value,"%d",ENABLE_CW_BUTTONS);
++ setProperty("ENABLE_CW_BUTTONS",value);
++ sprintf(value,"%d",CWL_BUTTON);
++ setProperty("CWL_BUTTON",value);
++ sprintf(value,"%d",CWR_BUTTON);
++ setProperty("CWR_BUTTON",value);
++=======
++>>>>>>> upstream/master
++#endif
++ saveProperties("gpio.props");
++}
++
++static void setup_pin(int pin, int up_down, void(*pAlert)(void)) {
++fprintf(stderr,"setup_pin: pin=%d mode=%d updown=%d\n",pin,INPUT,up_down);
++ pinMode(pin,INPUT);
++ pullUpDnControl(pin,up_down);
++<<<<<<< HEAD
++ usleep(10000);
++ wiringPiISR(pin,INT_EDGE_BOTH,pAlert);
++}
++
++
++static void setup_encoder_pin(int pin, int up_down, void(*pAlert)(void)) {
++fprintf(stderr,"setup_encoder_pin: pin=%d updown=%d\n",pin,up_down);
++ pinMode(pin,INPUT);
++ pullUpDnControl(pin,up_down);
++ usleep(10000);
++ wiringPiISR(pin,INT_EDGE_RISING,pAlert);
++}
++
++#ifdef LOCALCW
++#ifdef RADIOBERRY
++#define BUTTON_STEADY_TIME_US 5000
++static void setup_button(int button, gpioAlertFunc_t pAlert) {
++ gpioSetMode(button, PI_INPUT);
++ gpioSetPullUpDown(button,PI_PUD_UP);
++ // give time to settle to avoid false triggers
++=======
++>>>>>>> upstream/master
++ usleep(10000);
++ wiringPiISR(pin,INT_EDGE_BOTH,pAlert);
++}
++
++<<<<<<< HEAD
++static void cwAlert(int gpio, int level, uint32_t tick) {
++ //fprintf(stderr,"cw key at pin %d \n", gpio);
++ if (cw_keyer_internal == 0 ){
++ //fprintf(stderr,"call keyer_event...\n");
++ keyer_event(gpio, cw_active_level == 0 ? level : (level==0));
++ }
++}
++
++/*
++static unsigned long cwl_debounce=0;
++static void cwlAlert() {
++ int t=millis();
++ if(t - cwl_debounce > settle_time) {
++ int level=digitalRead(CWL_BUTTON);
++ if (cw_keyer_internal == 0 ){
++ fprintf(stderr,"call keyer_event CWL Button \n");
++ keyer_event(CWL_BUTTON, cw_active_level == 0 ? level : (level==0));
++ }
++ cwl_debounce=t;
++ }
++}
++
++static unsigned long cwr_debounce=0;
++static void cwrAlert() {
++ int t=millis();
++ if(t - cwr_debounce > settle_time) {
++ int level=digitalRead(CWR_BUTTON);
++ if (cw_keyer_internal == 0 ){
++ fprintf(stderr,"call keyer_event CWR Button \n");
++ keyer_event(CWR_BUTTON, cw_active_level == 0 ? level : (level==0));
++ }
++ cwr_debounce=t;
++ }
++}
++*/
++#endif
++#endif
++=======
++
++static void setup_encoder_pin(int pin, int up_down, void(*pAlert)(void)) {
++fprintf(stderr,"setup_encoder_pin: pin=%d updown=%d\n",pin,up_down);
++ pinMode(pin,INPUT);
++ pullUpDnControl(pin,up_down);
++ usleep(10000);
++ wiringPiISR(pin,INT_EDGE_RISING,pAlert);
++}
++>>>>>>> upstream/master
++
++int gpio_init() {
++ int i;
++
++ fprintf(stderr,"gpio_wiringpi: gpio_init\n");
++
++ gpio_restore_state();
++
++ wiringPiSetup(); // use WiringPi pin numbers
++<<<<<<< HEAD
++
++#ifdef RADIOBERRY
++ if (gpioInitialise() < 0) {
++ fprintf(stderr,"radioberry_protocol: gpio could not be initialized. \n");
++ exit(-1);
++ }
++#endif
++=======
++>>>>>>> upstream/master
++
++ if(ENABLE_VFO_ENCODER) {
++#ifdef CONTROLLER2
++#ifdef VFO_HAS_FUNCTION
++ setup_pin(VFO_FUNCTION, PUD_UP, &vfoFunctionAlert);
++ vfoFunction=0;
++#endif
++ vfo_A=1;
++ vfo_B=1;
++ setup_encoder_pin(VFO_ENCODER_A,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,&vfoEncoderA);
++ setup_encoder_pin(VFO_ENCODER_B,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,&vfoEncoderB);
++#else
++ vfo_A=1;
++ vfo_B=1;
++ setup_encoder_pin(VFO_ENCODER_A,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,&vfoEncoderA);
++ setup_encoder_pin(VFO_ENCODER_B,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,&vfoEncoderB);
++ //setup_pin(VFO_ENCODER_A,ENABLE_VFO_PULLUP?PUD_UP:PUD_OFF,&vfoEncoderA);
++ //setup_pin(VFO_ENCODER_B,ENABLE_VFO_PULLUP?PUD_UP:PUD_OFF,&vfoEncoderB);
++#endif
++ vfoEncoderPos=0;
++ }
++
++ setup_pin(E1_FUNCTION, PUD_UP, &e1FunctionAlert);
++ e1Function=0;
++
++ if(ENABLE_E1_ENCODER) {
++ setup_encoder_pin(E1_ENCODER_A,ENABLE_E1_PULLUP?PUD_UP:PUD_OFF,&e1EncoderA);
++ setup_encoder_pin(E1_ENCODER_B,ENABLE_E1_PULLUP?PUD_UP:PUD_OFF,&e1EncoderB);
++ e1EncoderPos=0;
++ }
++
++ setup_pin(E2_FUNCTION, PUD_UP, &e2FunctionAlert);
++ e2Function=0;
++
++ if(ENABLE_E2_ENCODER) {
++ setup_encoder_pin(E2_ENCODER_A,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2EncoderA);
++ setup_encoder_pin(E2_ENCODER_B,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2EncoderB);
++ e2EncoderPos=0;
++ }
++
++ setup_pin(E3_FUNCTION, PUD_UP, &e3FunctionAlert);
++ e3Function=0;
++
++ if(ENABLE_E3_ENCODER) {
++ setup_encoder_pin(E3_ENCODER_A,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3EncoderA);
++ setup_encoder_pin(E3_ENCODER_B,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3EncoderB);
++ e3EncoderPos=0;
++ }
++
++#ifdef CONTROLLER2
++ setup_pin(E4_FUNCTION, PUD_UP, &e4FunctionAlert);
++ e4Function=0;
++
++ if(ENABLE_E4_ENCODER) {
++ setup_encoder_pin(E4_ENCODER_A,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4EncoderA);
++ setup_encoder_pin(E4_ENCODER_B,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4EncoderB);
++ e4EncoderPos=0;
++ }
++#endif
++
++#ifndef CONTROLLER2
++ if(ENABLE_FUNCTION_BUTTON) {
++<<<<<<< HEAD
++ //setup_pin(FUNCTION_BUTTON, PUD_UP, &functionAlert);
++=======
++ setup_pin(FUNCTION_BUTTON, PUD_UP, &functionAlert);
++>>>>>>> upstream/master
++ }
++
++ if(ENABLE_MOX_BUTTON) {
++ setup_pin(MOX_BUTTON, PUD_UP, &moxAlert);
++ }
++
++ if(ENABLE_S1_BUTTON) {
++ setup_pin(S1_BUTTON, PUD_UP, &s1Alert);
++ }
++
++ if(ENABLE_S2_BUTTON) {
++ setup_pin(S2_BUTTON, PUD_UP, &s2Alert);
++ }
++
++ if(ENABLE_S3_BUTTON) {
++ setup_pin(S3_BUTTON, PUD_UP, &s3Alert);
++ }
++
++ if(ENABLE_S4_BUTTON) {
++ setup_pin(S4_BUTTON, PUD_UP, &s4Alert);
++ }
++
++ if(ENABLE_S5_BUTTON) {
++ setup_pin(S5_BUTTON, PUD_UP, &s5Alert);
++ }
++
++ if(ENABLE_S6_BUTTON) {
++ setup_pin(S6_BUTTON, PUD_UP, &s6Alert);
++ }
++#endif
++
++ rotary_encoder_thread_id = g_thread_new( "rotary encoder", rotary_encoder_thread, NULL);
++ if( ! rotary_encoder_thread_id )
++ {
++ fprintf(stderr,"g_thread_new failed on rotary_encoder_thread\n");
++ exit( -1 );
++ }
++ fprintf(stderr, "rotary_encoder_thread: id=%p\n",rotary_encoder_thread_id);
++
++#ifdef CONTROLLER2
++ // setup i2c
++ i2c_init();
++
++ // setup interrupt pin
++ fprintf(stderr,"setup i2c interrupt: pin=%d\n",I2C_INTERRUPT);
++ //digitalWrite(I2C_INTERRUPT,0); // clear pin
++ pinMode(I2C_INTERRUPT,INPUT);
++ pullUpDnControl(I2C_INTERRUPT,PUD_UP);
++ usleep(10000);
++ //wiringPiISR(I2C_INTERRUPT,INT_EDGE_FALLING,pI2CInterrupt);
++ wiringPiISR(I2C_INTERRUPT,INT_EDGE_BOTH,pI2CInterrupt);
++#endif
++<<<<<<< HEAD
++
++#ifdef LOCALCW
++ fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABLE_CW_BUTTONS, CWL_BUTTON, CWR_BUTTON);
++ if(ENABLE_CW_BUTTONS) {
++ /*
++ setup_pin(CWL_BUTTON, PUD_UP, &cwlAlert);
++ setup_pin(CWR_BUTTON, PUD_UP, &cwrAlert);
++ */
++
++ #ifdef RADIOBERRY
++ setup_button(CWL_BUTTON, cwAlert);
++ setup_button(CWR_BUTTON, cwAlert);
++ #endif
++
++
++ }
++#endif
++=======
++>>>>>>> upstream/master
++
++ return 0;
++}
++
++void gpio_close() {
++ running=0;
++}
++
++int vfo_encoder_get_pos() {
++ int pos=vfoEncoderPos;
++
++ if(vfo_encoder_divisor>1) {
++ if(pos<0 && pos>-vfo_encoder_divisor) {
++ pos=0;
++ } else if(pos>0 && pos<vfo_encoder_divisor) {
++ pos=0;
++ }
++ pos=pos/vfo_encoder_divisor;
++ vfoEncoderPos=vfoEncoderPos-(pos*vfo_encoder_divisor);
++ } else {
++ vfoEncoderPos=0;
++ }
++ return pos;
++}
++
++int e1_encoder_get_pos() {
++ int pos=e1EncoderPos;
++ e1EncoderPos=0;
++ return pos;
++}
++
++int e2_encoder_get_pos() {
++ int pos=e2EncoderPos;
++ e2EncoderPos=0;
++ return pos;
++}
++
++int e3_encoder_get_pos() {
++ int pos=e3EncoderPos;
++ e3EncoderPos=0;
++ return pos;
++}
++
++int e3_function_get_state() {
++ return e3Function;
++}
++
++#ifdef CONTROLLER2
++int e4_encoder_get_pos() {
++ int pos=e4EncoderPos;
++ e4EncoderPos=0;
++ return pos;
++}
++#endif
++
++int function_get_state() {
++ return function_state;
++}
++
++int band_get_state() {
++ return band_state;
++}
++
++int bandstack_get_state() {
++ return bandstack_state;
++}
++
++int mode_get_state() {
++ return mode_state;
++}
++
++int filter_get_state() {
++ return filter_state;
++}
++
++int noise_get_state() {
++ return noise_state;
++}
++
++int agc_get_state() {
++ return agc_state;
++}
++
++int mox_get_state() {
++ return mox_state;
++}
++
++int lock_get_state() {
++ return lock_state;
++}
++
++
++static int vfo_encoder_changed(void *data) {
++ if(!locked) {
++ int pos=(int)data;
++ vfo_step(pos);
++ }
++ //free(data);
++ return 0;
++}
++
++static encoder_changed(int action,int pos) {
++ double value;
++ int mode;
++ int id;
++ FILTER * band_filters=filters[vfo[active_receiver->id].mode];
++ FILTER *band_filter;
++ FILTER *filter;
++ int new_val;
++
++ switch(action) {
++ case ENCODER_AF_GAIN:
++ value=active_receiver->volume;
++ value+=(double)pos/100.0;
++ if(value<0.0) {
++ value=0.0;
++ } else if(value>1.0) {
++ value=1.0;
++ }
++ set_af_gain(value);
++ break;
++ case ENCODER_AGC_GAIN:
++ value=active_receiver->agc_gain;
++ value+=(double)pos;
++ if(value<-20.0) {
++ value=-20.0;
++ } else if(value>120.0) {
++ value=120.0;
++ }
++ set_agc_gain(value);
++ break;
++ case ENCODER_ATTENUATION:
++ value=(double)adc_attenuation[active_receiver->adc];
++ value+=(double)pos;
++ if(value<0.0) {
++ value=0.0;
++ } else if (value>31.0) {
++ value=31.0;
++ }
++ set_attenuation_value(value);
++ break;
++ case ENCODER_MIC_GAIN:
++ value=mic_gain;
++ //gain+=(double)pos/100.0;
++ value+=(double)pos;
++ if(value<-10.0) {
++ value=-10.0;
++ } else if(value>50.0) {
++ value=50.0;
++ }
++ set_mic_gain(value);
++ break;
++ case ENCODER_DRIVE:
++ value=getDrive();
++ value+=(double)pos;
++ if(value<0.0) {
++ value=0.0;
++ } else if(value>100.0) {
++ value=100.0;
++ }
++ set_drive(value);
++ break;
++ case ENCODER_RIT:
++ value=(double)vfo[active_receiver->id].rit;
++ value+=(double)(pos*rit_increment);
++ if(value<-1000.0) {
++ value=-1000.0;
++ } else if(value>1000.0) {
++ value=1000.0;
++ }
++ vfo[active_receiver->id].rit=(int)value;
++ if(protocol==NEW_PROTOCOL) {
++ schedule_high_priority();
++ }
++ vfo_update();
++ break;
++ case ENCODER_CW_SPEED:
++ value=(double)cw_keyer_speed;
++ value+=(double)pos;
++ if(value<1.0) {
++ value=1.0;
++ } else if(value>60.0) {
++ value=60.0;
++ }
++ cw_keyer_speed=(int)value;
++ vfo_update();
++ break;
++ case ENCODER_CW_FREQUENCY:
++ value=(double)cw_keyer_sidetone_frequency;
++ value+=(double)pos;
++ if(value<0.0) {
++ value=0.0;
++ } else if(value>1000.0) {
++ value=1000.0;
++ }
++ cw_keyer_sidetone_frequency=(int)value;
++ vfo_update();
++ break;
++ case ENCODER_PANADAPTER_HIGH:
++ value=(double)active_receiver->panadapter_high;
++ value+=(double)pos;
++ active_receiver->panadapter_high=(int)value;
++ break;
++ case ENCODER_PANADAPTER_LOW:
++ value=(double)active_receiver->panadapter_low;
++ value+=(double)pos;
++ active_receiver->panadapter_low=(int)value;
++ break;
++ case ENCODER_SQUELCH:
++ value=active_receiver->squelch;
++ value+=(double)pos;
++ if(value<0.0) {
++ value=0.0;
++ } else if(value>100.0) {
++ value=100.0;
++ }
++ active_receiver->squelch=value;
++ set_squelch(active_receiver);
++ break;
++ case ENCODER_COMP:
++ value=(double)transmitter->compressor_level;
++ value+=(double)pos;
++ if(value<0.0) {
++ value=0.0;
++ } else if(value>20.0) {
++ value=20.0;
++ }
++ transmitter->compressor_level=(int)value;
++ set_compression(transmitter);
++ break;
++ }
++}
++
++static int e1_encoder_changed(void *data) {
++ int pos=(int)data;
++ if(active_menu==E1_MENU) {
++ encoder_select(pos);
++ } else {
++ encoder_changed(e1_encoder_action,pos);
++ }
++ //free(data);
++ return 0;
++}
++
++static int e2_encoder_changed(void *data) {
++ int pos=(int)data;
++ if(active_menu==E2_MENU) {
++ encoder_select(pos);
++ } else {
++ encoder_changed(e2_encoder_action,pos);
++ }
++ //free(data);
++ return 0;
++}
++
++static int e3_encoder_changed(void *data) {
++ int pos=(int)data;
++ if(active_menu==E3_MENU) {
++ encoder_select(pos);
++ } else {
++ encoder_changed(e3_encoder_action,pos);
++ }
++ //free(data);
++ return 0;
++}
++
++#ifdef CONTROLLER2
++static int e4_encoder_changed(void *data) {
++ int pos=(int)data;
++ if(active_menu==E4_MENU) {
++ encoder_select(pos);
++ } else {
++ encoder_changed(e4_encoder_action,pos);
++ }
++ //free(data);
++ return 0;
++}
++#endif
++
++static gpointer rotary_encoder_thread(gpointer data) {
++ int pos;
++
++ // ignore startup glitches
++ sleep(2);
++
++ //g_mutex_lock(&m_running);
++ running=1;
++ //g_mutex_unlock(&m_running);
++ while(1) {
++
++ pos=vfo_encoder_get_pos();
++ if(pos!=0) {
++ g_idle_add(vfo_encoder_changed,(gpointer)pos);
++ }
++
++ pos=e1_encoder_get_pos();
++ if(pos!=0) {
++ g_idle_add(e1_encoder_changed,(gpointer)pos);
++ }
++
++ pos=e2_encoder_get_pos();
++ if(pos!=0) {
++ g_idle_add(e2_encoder_changed,(gpointer)pos);
++ }
++
++ pos=e3_encoder_get_pos();
++ if(pos!=0) {
++ g_idle_add(e3_encoder_changed,(gpointer)pos);
++ }
++
++#ifdef CONTROLLER2
++ pos=e4_encoder_get_pos();
++ if(pos!=0) {
++ g_idle_add(e4_encoder_changed,(gpointer)pos);
++ }
++#endif
++
++#ifdef sx1509
++ // buttons only generate interrupt when
++ // pushed onODER_AF_GAIN = 0,
++ function_state = 0;
++ band_state = 0;
++ bandstack_state = 0;
++ mode_state = 0;
++ filter_state = 0;
++ noise_state = 0;
++ agc_state = 0;
++ mox_state = 0;
++ lock_state = 0;
++#endif
++//fprintf(stderr,"gpio_thread: lock\n");
++ //g_mutex_lock(&m_running);
++ if(running==0) {
++fprintf(stderr,"gpio_thread: unlock (running==0)\n");
++ //g_mutex_unlock(&m_running);
++ g_thread_exit(NULL);
++ }
++ usleep(100000);
++
++//fprintf(stderr,"gpio_thread: unlock (running==1)\n");
++ //g_mutex_unlock(&m_running);
++ }
++ return NULL;
++}
--/* Copyright (C)
++/* Copyrieht (C)
* 2015 - John Melton, G0ORX/N6LYT
*
* This program is free software; you can redistribute it and/or
#include <string.h>
#include <semaphore.h>
#include <math.h>
++#include <sys/time.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
#include <wdsp.h>
#include "agc.h"
#include "band.h"
#include "property.h"
++#include "new_menu.h"
#include "new_protocol.h"
#include "old_protocol.h"
++#ifdef RADIOBERRY
++#include "radioberry.h"
++#endif
#include "store.h"
#ifdef LIMESDR
#include "lime_protocol.h"
#ifdef FREEDV
#include "freedv.h"
#endif
++#include "audio_waterfall.h"
#ifdef GPIO
#include "gpio.h"
#endif
#include "vfo.h"
++#include "vox.h"
#include "meter.h"
#include "rx_panadapter.h"
#include "tx_panadapter.h"
#include "waterfall.h"
#include "sliders.h"
#include "toolbar.h"
++#include "rigctl.h"
++#include "ext.h"
#define min(x,y) (x<y?x:y)
#define max(x,y) (x<y?y:x)
--#define DISPLAY_INCREMENT (display_height/32)
--#define MENU_HEIGHT (DISPLAY_INCREMENT*2)
--#define MENU_WIDTH ((display_width/32)*3)
--#define VFO_HEIGHT (DISPLAY_INCREMENT*4)
++#define MENU_HEIGHT (30)
++#define MENU_WIDTH (64)
++#define VFO_HEIGHT (60)
#define VFO_WIDTH (display_width-METER_WIDTH-MENU_WIDTH)
--#define METER_HEIGHT (DISPLAY_INCREMENT*4)
--#define METER_WIDTH ((display_width/32)*8)
--#define PANADAPTER_HEIGHT (DISPLAY_INCREMENT*8)
--#define SLIDERS_HEIGHT (DISPLAY_INCREMENT*6)
--#define TOOLBAR_HEIGHT (DISPLAY_INCREMENT*2)
--#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
++#define METER_HEIGHT (60)
++#define METER_WIDTH (200)
++#define PANADAPTER_HEIGHT (105)
++#define SLIDERS_HEIGHT (90)
++#define TOOLBAR_HEIGHT (30)
++#define WATERFALL_HEIGHT (105)
#ifdef PSK
--#define PSK_WATERFALL_HEIGHT (DISPLAY_INCREMENT*6)
++#define PSK_WATERFALL_HEIGHT (90)
#define PSK_HEIGHT (display_height-(VFO_HEIGHT+PSK_WATERFALL_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
#endif
++#ifdef FREEDV
++#define FREEDV_WATERFALL_HEIGHT (105)
++#endif
++
static GtkWidget *fixed;
static GtkWidget *vfo_panel;
static GtkWidget *meter;
static GtkWidget *psk;
static GtkWidget *psk_waterfall;
#endif
++static GtkWidget *audio_waterfall;
#ifdef GPIO
static GtkWidget *encoders;
static cairo_surface_t *encoders_surface = NULL;
#endif
++#ifdef WIRIINGPI
++static GtkWidget *encoders;
++static cairo_surface_t *encoders_surface = NULL;
++#endif
++
++int region=REGION_OTHER;
int echo=0;
static gint save_timer_id;
--DISCOVERED *radio;
++DISCOVERED *radio=NULL;
char property_path[128];
sem_t property_sem;
TRANSMITTER *transmitter;
int buffer_size=1024; // 64, 128, 256, 512, 1024
--int fft_size=4096; // 1024, 2048, 4096, 8192, 16384
++int fft_size=2048; // 1024, 2048, 4096, 8192, 16384
int atlas_penelope=0;
int atlas_clock_source_10mhz=0;
int tx_out_of_band=0;
int tx_cfir=0;
--int tx_alc=1;
int tx_leveler=0;
++int alc=TXA_ALC_AV;
--double tone_level=0.0;
++double tone_level=0.2;
int filter_board=ALEX;
//int pa=PA_ENABLED;
int waterfall_high=-100;
int waterfall_low=-150;
--int waterfall_automatic=1;
int display_sliders=1;
int mic_ptt_enabled=0;
int mic_ptt_tip_bias_ring=0;
--double tune_drive=10;
--double drive=50;
++//double tune_drive=10;
++//double drive=50;
--int drive_level=0;
--int tune_drive_level=0;
++//int drive_level=0;
++//int tune_drive_level=0;
int receivers=RECEIVERS;
int OCmemory_tune_time=550; // ms
long long tune_timeout;
++int analog_meter=0;
int smeter=RXA_S_AV;
--int alc=TXA_ALC_PK;
int local_audio=0;
int local_microphone=0;
int tx_filter_low=150;
int tx_filter_high=2850;
--#ifdef FREEDV
--char freedv_tx_text_data[64];
--#endif
--
++static int pre_tune_mode;
static int pre_tune_filter_low;
static int pre_tune_filter_high;
int enable_rx_equalizer=0;
int rx_equalizer[4]={0,0,0,0};
--int deviation=2500;
int pre_emphasize=0;
int vox_setting=0;
double i_rotate[2]={1.0,1.0};
double q_rotate[2]={0.0,0.0};
++double meter_calibration=0.0;
++double display_calibration=0.0;
++
void reconfigure_radio() {
int i;
int y;
++//fprintf(stderr,"reconfigure_radio: receivers=%d\n",receivers);
int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT;
if(display_sliders) {
rx_height-=SLIDERS_HEIGHT;
for(i=0;i<receivers;i++) {
reconfigure_receiver(receiver[i],rx_height/receivers);
gtk_fixed_move(GTK_FIXED(fixed),receiver[i]->panel,0,y);
++ receiver[i]->x=0;
++ receiver[i]->y=y;
y+=rx_height/receivers;
}
gtk_fixed_move(GTK_FIXED(fixed),sliders,0,y);
}
gtk_widget_show_all(sliders);
-- // force change of sliders for mic or linein
-- g_idle_add(linein_changed,NULL);
} else {
if(sliders!=NULL) {
gtk_container_remove(GTK_CONTAINER(fixed),sliders);
int i;
int x;
int y;
--fprintf(stderr,"start_radio: selected radio=%p device=%d\n",radio,radio->device);
++//fprintf(stderr,"start_radio: selected radio=%p device=%d\n",radio,radio->device);
gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_WATCH));
int rc;
}
sem_post(&property_sem);
-- status_text("starting radio ...");
++ char text[256];
++ //for(i=0;i<devices;i++) {
++ switch(radio->protocol) {
++ case ORIGINAL_PROTOCOL:
++ case NEW_PROTOCOL:
++#ifdef USBOZY
++ if(radio->device==DEVICE_OZY) {
++ sprintf(text,"%s (%s) on USB /dev/ozy\n", radio->name, radio->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2");
++ } else {
++#endif
++ sprintf(text,"Starting %s (%s v%d.%d)",
++ radio->name,
++ radio->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2",
++ radio->software_version/10,
++ radio->software_version%10);
++ break;
++ }
++ //}
++
++
++
++ status_text(text);
++
++ sprintf(text,"piHPSDR: %s (%s v%d.%d) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s",
++ radio->name,
++ radio->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2",
++ radio->software_version/10,
++ radio->software_version%10,
++ inet_ntoa(radio->info.network.address.sin_addr),
++ radio->info.network.mac_address[0],
++ radio->info.network.mac_address[1],
++ radio->info.network.mac_address[2],
++ radio->info.network.mac_address[3],
++ radio->info.network.mac_address[4],
++ radio->info.network.mac_address[5],
++ radio->info.network.interface_name);
++
++fprintf(stderr,"title: length=%d\n", (int)strlen(text));
++
++ gtk_window_set_title (GTK_WINDOW (top_window), text);
++
protocol=radio->protocol;
device=radio->device;
sprintf(property_path,"limesdr.props");
break;
#endif
++#ifdef RADIOBERRY
++ case RADIOBERRY_PROTOCOL:
++ sprintf(property_path,"radioberry.props");
++ break;
++#endif
++ }
++
++ switch(radio->protocol) {
++ case ORIGINAL_PROTOCOL:
++ switch(radio->device) {
++ case DEVICE_ORION2:
++ //meter_calibration=3.0;
++ //display_calibration=3.36;
++ break;
++ default:
++ //meter_calibration=-2.44;
++ //display_calibration=-2.1;
++ break;
++ }
++ break;
++ case NEW_PROTOCOL:
++ switch(radio->device) {
++ case NEW_DEVICE_ORION2:
++ //meter_calibration=3.0;
++ //display_calibration=3.36;
++ break;
++ default:
++ //meter_calibration=-2.44;
++ //display_calibration=-2.1;
++ break;
++ }
++ break;
}
++
++
++ adc_attenuation[0]=0;
++ adc_attenuation[1]=0;
++//fprintf(stderr,"meter_calibration=%f display_calibration=%f\n", meter_calibration, display_calibration);
radioRestoreState();
++ radio_change_region(region);
++
y=0;
fixed=gtk_fixed_new();
gtk_container_remove(GTK_CONTAINER(top_window),grid);
gtk_container_add(GTK_CONTAINER(top_window), fixed);
--fprintf(stderr,"radio: vfo_init\n");
++//fprintf(stderr,"radio: vfo_init\n");
vfo_panel = vfo_init(VFO_WIDTH,VFO_HEIGHT,top_window);
gtk_fixed_put(GTK_FIXED(fixed),vfo_panel,0,y);
--fprintf(stderr,"radio: meter_init\n");
++//fprintf(stderr,"radio: meter_init\n");
meter = meter_init(METER_WIDTH,METER_HEIGHT,top_window);
gtk_fixed_put(GTK_FIXED(fixed),meter,VFO_WIDTH,y);
fprintf(stderr,"Create %d receivers: height=%d\n",receivers,rx_height);
-- for(i=0;i<MAX_RECEIVERS;i++) {
++ for(i=0;i<RECEIVERS;i++) {
receiver[i]=create_receiver(i, buffer_size, fft_size, display_width, updates_per_second, display_width, rx_height);
-- g_object_ref((gpointer)receiver[i]->panel);
++ setSquelch(receiver[i]);
if(i<receivers) {
++ receiver[i]->x=0;
++ receiver[i]->y=y;
gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,0,y);
--fprintf(stderr,"receiver %d: height=%d y=%d\n",receiver[i]->id,rx_height,y);
++ g_object_ref((gpointer)receiver[i]->panel);
set_displaying(receiver[i],1);
y+=rx_height;
} else {
set_displaying(receiver[i],0);
}
}
++
++ if((protocol==ORIGINAL_PROTOCOL) && (RECEIVERS==2) && (receiver[0]->sample_rate!=receiver[1]->sample_rate)) {
++ receiver[1]->sample_rate=receiver[0]->sample_rate;
++ }
++
active_receiver=receiver[0];
fprintf(stderr,"Create transmitter\n");
transmitter=create_transmitter(CHANNEL_TX, buffer_size, fft_size, updates_per_second, display_width, tx_height);
-- g_object_ref((gpointer)transmitter->panel);
++ transmitter->x=0;
++ transmitter->y=VFO_HEIGHT;
++ //gtk_fixed_put(GTK_FIXED(fixed),transmitter->panel,0,VFO_HEIGHT);
++
++#ifdef PURESIGNAL
++ tx_set_ps_sample_rate(transmitter,protocol==NEW_PROTOCOL?192000:active_receiver->sample_rate);
++ if(((protocol==ORIGINAL_PROTOCOL) && (device!=DEVICE_METIS)) || ((protocol==NEW_PROTOCOL) && (device!=NEW_DEVICE_ATLAS))) {
++ receiver[PS_TX_FEEDBACK]=create_pure_signal_receiver(PS_TX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
++ receiver[PS_RX_FEEDBACK]=create_pure_signal_receiver(PS_RX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
++ }
++#endif
++#ifdef AUDIO_WATERFALL
++ audio_waterfall=audio_waterfall_init(200,100);
++ gtk_fixed_put(GTK_FIXED(fixed),audio_waterfall,0,VFO_HEIGHT+20);
++#endif
++
++#ifdef GPIO
++ if(gpio_init()<0) {
++ fprintf(stderr,"GPIO failed to initialize\n");
++ }
++#endif
++<<<<<<< HEAD
++#ifdef LOCALCW
++ // init local keyer if enabled
++ if (cw_keyer_internal == 0) {
++ fprintf(stderr,"Initialize keyer.....\n");
++ keyer_update();
++ }
++#endif
++=======
++>>>>>>> upstream/master
++
switch(radio->protocol) {
case ORIGINAL_PROTOCOL:
old_protocol_init(0,display_width,receiver[0]->sample_rate);
break;
#ifdef LIMESDR
case LIMESDR_PROTOCOL:
-- lime_protocol_init(0,display_width);
++ lime_protocol_init(0,display_width,receiver[0]->sample_rate);
break;
++#endif
++#ifdef RADIOBERRY
++ case RADIOBERRY_PROTOCOL:
++ radioberry_protocol_init(0,display_width);
++ break;
#endif
}
--#ifdef GPIO
-- if(gpio_init()<0) {
-- fprintf(stderr,"GPIO failed to initialize\n");
-- }
--#ifdef LOCALCW
-- // init local keyer if enabled
-- else if (cw_keyer_internal == 0)
-- keyer_update();
--#endif
--#endif
--#ifdef I2C
-- i2c_init();
--#endif
++
++//#ifdef I2C
++// i2c_init();
++//#endif
if(display_sliders) {
fprintf(stderr,"create sliders\n");
y+=SLIDERS_HEIGHT;
}
++
toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window);
gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
y+=TOOLBAR_HEIGHT;
gtk_widget_show_all (fixed);
++//#ifdef FREEDV
++// if(!active_receiver->freedv) {
++// gtk_widget_hide(audio_waterfall);
++// }
++//#endif
-- // force change of sliders for mic or linein
-- g_idle_add(linein_changed,NULL);
++
// save every 30 seconds
--fprintf(stderr,"start save timer\n");
save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL);
#ifdef PSK
-- if(active_receiver->mode==modePSK) {
++ if(vfo[active_receiver->id].mode==modePSK) {
show_psk();
} else {
show_waterfall();
}
#endif
-- launch_rigctl();
++ if(rigctl_enable) {
++ launch_rigctl();
++ }
calcDriveLevel();
-- calcTuneDriveLevel();
++
++#ifdef PURESIGNAL
++ if(transmitter->puresignal) {
++ tx_set_ps(transmitter,transmitter->puresignal);
++ }
++#endif
if(protocol==NEW_PROTOCOL) {
schedule_high_priority();
}
-- g_idle_add(vfo_update,(gpointer)NULL);
++ g_idle_add(ext_vfo_update,(gpointer)NULL);
--fprintf(stderr,"set cursor\n");
gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
--for(i=0;i<MAX_VFOS;i++) {
-- fprintf(stderr,"start_radio: vfo %d band=%d bandstack=%d frequency=%lld mode=%d filter=%d rit=%lld lo=%%ld offset=%lld\n",
-- i,
-- vfo[i].band,
-- vfo[i].bandstack,
-- vfo[i].frequency,
-- vfo[i].mode,
-- vfo[i].filter,
-- vfo[i].rit,
-- vfo[i].lo,
-- vfo[i].offset);
--}
}
++void disable_rigctl() {
++ fprintf(stderr,"RIGCTL: disable_rigctl()\n");
++ close_rigctl_ports();
++}
++
void radio_change_receivers(int r) {
++ fprintf(stderr,"radio_change_receivers: from %d to %d\n",receivers,r);
switch(r) {
case 1:
if(receivers==2) {
}
reconfigure_radio();
active_receiver=receiver[0];
++ if(protocol==NEW_PROTOCOL) {
++ schedule_high_priority();
++ }
}
void radio_change_sample_rate(int rate) {
}
old_protocol_set_mic_sample_rate(rate);
old_protocol_run();
++#ifdef PURESIGNAL
++ tx_set_ps_sample_rate(transmitter,rate);
++#endif
break;
#ifdef LIMESDR
case LIMESDR_PROTOCOL:
++ lime_protocol_change_sample_rate(rate);
break;
#endif
}
static void rxtx(int state) {
int i;
-- int y=VFO_HEIGHT;
if(state) {
// switch to tx
++#ifdef FREEDV
++ if(active_receiver->freedv) {
++ freedv_reset_tx_text_index();
++ }
++#endif
++#ifdef PURESIGNAL
++ RECEIVER *rx_feedback=receiver[PS_RX_FEEDBACK];
++ RECEIVER *tx_feedback=receiver[PS_TX_FEEDBACK];
++
++ rx_feedback->samples=0;
++ tx_feedback->samples=0;
++#endif
++
for(i=0;i<receivers;i++) {
SetChannelState(receiver[i]->id,0,i==(receivers-1));
set_displaying(receiver[i],0);
if(protocol==NEW_PROTOCOL) {
schedule_high_priority();
++ schedule_receive_specific();
++ }
++ g_object_ref((gpointer)receiver[i]->panel);
++ g_object_ref((gpointer)receiver[i]->panadapter);
++ if(receiver[i]->waterfall!=NULL) {
++ g_object_ref((gpointer)receiver[i]->waterfall);
}
gtk_container_remove(GTK_CONTAINER(fixed),receiver[i]->panel);
}
-- gtk_fixed_put(GTK_FIXED(fixed),transmitter->panel,0,y);
++//#ifdef FREEDV
++// if(active_receiver->freedv) {
++// gtk_widget_show(audio_waterfall);
++// }
++//#endif
++ gtk_fixed_put(GTK_FIXED(fixed),transmitter->panel,transmitter->x,transmitter->y);
SetChannelState(transmitter->id,1,0);
tx_set_displaying(transmitter,1);
--#ifdef FREEDV
-- if(active_receiver->mode==modeFREEDV) {
-- freedv_reset_tx_text_index();
-- }
--#endif
} else {
SetChannelState(transmitter->id,0,1);
if(protocol==NEW_PROTOCOL) {
schedule_high_priority();
++ schedule_receive_specific();
}
tx_set_displaying(transmitter,0);
++ g_object_ref((gpointer)transmitter->panel);
++ g_object_ref((gpointer)transmitter->panadapter);
gtk_container_remove(GTK_CONTAINER(fixed),transmitter->panel);
-- int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT;
-- if(display_sliders) {
-- rx_height-=SLIDERS_HEIGHT;
-- }
++//#ifdef FREEDV
++// if(active_receiver->freedv) {
++// gtk_widget_hide(audio_waterfall);
++// }
++//#endif
for(i=0;i<receivers;i++) {
++ gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,receiver[i]->x,receiver[i]->y);
SetChannelState(receiver[i]->id,1,0);
set_displaying(receiver[i],1);
-- gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,0,y);
-- y+=(rx_height/receivers);
}
++//#ifdef FREEDV
++// if(active_receiver->freedv) {
++// gtk_widget_show(audio_waterfall);
++// }
++//#endif
}
-- gtk_widget_show_all(fixed);
-- g_idle_add(linein_changed,NULL);
++#ifdef PURESIGNAL
++ if(transmitter->puresignal) {
++ SetPSMox(transmitter->id,state);
++ }
++#endif
}
void setMox(int state) {
vox=state;
rxtx(state);
}
++ g_idle_add(ext_vfo_update,(gpointer)NULL);
++}
++
++void vox_changed(int state) {
++ setVox(state);
}
++
void setTune(int state) {
int i;
}
}
-- int mode=vfo[VFO_A].mode;;
++ int mode=vfo[VFO_A].mode;
if(split) {
mode=vfo[VFO_B].mode;
}
-- double freq=(double)cw_keyer_sidetone_frequency;
--
-- pre_tune_filter_low=transmitter->filter_low;
-- pre_tune_filter_high=transmitter->filter_high;
++ pre_tune_mode=mode;
switch(mode) {
-- case modeUSB:
-- case modeCWU:
-- case modeDIGU:
-- SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
-- transmitter->filter_low=cw_keyer_sidetone_frequency-100;
-- transmitter->filter_high=cw_keyer_sidetone_frequency+100;
-- freq=(double)(cw_keyer_sidetone_frequency+100);
-- break;
case modeLSB:
case modeCWL:
case modeDIGL:
SetTXAPostGenToneFreq(transmitter->id,-(double)cw_keyer_sidetone_frequency);
-- transmitter->filter_low=-cw_keyer_sidetone_frequency-100;
-- transmitter->filter_high=-cw_keyer_sidetone_frequency+100;
-- freq=(double)(-cw_keyer_sidetone_frequency-100);
-- break;
-- case modeDSB:
-- SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
-- transmitter->filter_low=cw_keyer_sidetone_frequency-100;
-- transmitter->filter_high=cw_keyer_sidetone_frequency+100;
-- freq=(double)(cw_keyer_sidetone_frequency+100);
break;
-- case modeAM:
-- case modeSAM:
-- case modeFMN:
++ default:
SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
-- transmitter->filter_low=cw_keyer_sidetone_frequency-100;
-- transmitter->filter_high=cw_keyer_sidetone_frequency+100;
-- freq=(double)(cw_keyer_sidetone_frequency+100);
break;
}
-- SetTXABandpassFreqs(transmitter->id,transmitter->filter_low,transmitter->filter_high);
--
--
-- SetTXAMode(transmitter->id,modeDIGU);
-- SetTXAPostGenMode(transmitter->id,0);
SetTXAPostGenToneMag(transmitter->id,0.99999);
++ SetTXAPostGenMode(transmitter->id,0);
SetTXAPostGenRun(transmitter->id,1);
++
++ switch(mode) {
++ case modeCWL:
++ cw_keyer_internal=0;
++ tx_set_mode(transmitter,modeLSB);
++ break;
++ case modeCWU:
++ cw_keyer_internal=0;
++ tx_set_mode(transmitter,modeUSB);
++ break;
++ }
++ rxtx(tune);
} else {
++ rxtx(tune);
SetTXAPostGenRun(transmitter->id,0);
-- SetTXAMode(transmitter->id,transmitter->mode);
-- transmitter->filter_low=pre_tune_filter_low;
-- transmitter->filter_high=pre_tune_filter_high;
-- SetTXABandpassFreqs(transmitter->id,transmitter->filter_low,transmitter->filter_high);
++ switch(pre_tune_mode) {
++ case modeCWL:
++ case modeCWU:
++ tx_set_mode(transmitter,pre_tune_mode);
++ cw_keyer_internal=1;
++ break;
++ }
++
}
-- rxtx(tune);
}
}
return tune;
}
++void radio_cw_setup() {
++ int mode=vfo[VFO_A].mode;;
++ if(split) {
++ mode=vfo[VFO_B].mode;
++ }
++
++ double freq=(double)cw_keyer_sidetone_frequency;
++ switch(mode) {
++ case modeCWU:
++ SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
++ break;
++ case modeLSB:
++ SetTXAPostGenToneFreq(transmitter->id,-(double)cw_keyer_sidetone_frequency);
++ break;
++ }
++ SetTXAPostGenMode(transmitter->id,0);
++ SetTXAPostGenToneMag(transmitter->id,0.99999);
++}
++
++void radio_cw_key(int state) {
++ SetTXAPostGenRun(transmitter->id,state);
++}
++
int isTransmitting() {
-- return ptt || mox || vox || tune;
++ return ptt | mox | vox | tune;
}
void setFrequency(long long f) {
switch(protocol) {
case NEW_PROTOCOL:
case ORIGINAL_PROTOCOL:
--<<<<<<< HEAD
#ifdef RADIOBERRY
case RADIOBERRY_PROTOCOL:
#endif
-- if(ctun) {
-- long long minf=entry->frequencyA-(long long)(sample_rate/2);
-- long long maxf=entry->frequencyA+(long long)(sample_rate/2);
--=======
if(vfo[v].ctun) {
long long minf=vfo[v].frequency-(long long)(active_receiver->sample_rate/2);
long long maxf=vfo[v].frequency+(long long)(active_receiver->sample_rate/2);
-->>>>>>> upstream/master
if(f<minf) f=minf;
if(f>maxf) f=maxf;
vfo[v].offset=f-vfo[v].frequency;
#ifdef LIMESDR
case LIMESDR_PROTOCOL:
{
-- long long minf=entry->frequency-(long long)(active_receiver->sample_rate/2);
-- long long maxf=entry->frequency+(long long)(active_receiver->sample_rate/2);
++fprintf(stderr,"setFrequency: %lld\n",f);
++ long long minf=vfo[v].frequency-(long long)(active_receiver->sample_rate/2);
++ long long maxf=vfo[v].frequency+(long long)(active_receiver->sample_rate/2);
if(f<minf) f=minf;
if(f>maxf) f=maxf;
-- ddsOffset=f-entry->frequency;
-- wdsp_set_offset(ddsOffset);
++ vfo[v].offset=f-vfo[v].frequency;
++ set_offset(active_receiver,vfo[v].offset);
return;
}
break;
#ifdef RADIOBERRY
case RADIOBERRY_PROTOCOL:
#endif
-- schedule_frequency_changed();
break;
#ifdef LIMESDR
case LIMESDR_PROTOCOL:
lime_protocol_set_frequency(f);
-- ddsOffset=0;
-- wdsp_set_offset(ddsOffset);
++ vfo[v].offset=0;
++ set_offset(active_receiver,vfo[v].offset);
break;
#endif
}
}
double getDrive() {
-- return drive;
++ return transmitter->drive;
}
static int calcLevel(double d) {
}
level=(int)(actual_volts*255.0);
++
++//fprintf(stderr,"calcLevel: %f calib=%f level=%d\n",d, gbb, level);
return level;
}
void calcDriveLevel() {
-- drive_level=calcLevel(drive);
++ transmitter->drive_level=calcLevel(transmitter->drive);
if(mox && protocol==NEW_PROTOCOL) {
schedule_high_priority();
}
++//fprintf(stderr,"calcDriveLevel: drive=%d drive_level=%d\n",transmitter->drive,transmitter->drive_level);
}
void setDrive(double value) {
-- drive=value;
++ transmitter->drive=value;
calcDriveLevel();
}
double getTuneDrive() {
-- return tune_drive;
++ return transmitter->tune_percent;
}
--void calcTuneDriveLevel() {
-- tune_drive_level=calcLevel(tune_drive);
-- if(tune && protocol==NEW_PROTOCOL) {
-- schedule_high_priority();
-- }
--}
++void setSquelch(RECEIVER *rx) {
++ double am_sq=((rx->squelch/100.0)*160.0)-160.0;
++ SetRXAAMSQThreshold(rx->id, am_sq);
++ SetRXAAMSQRun(rx->id, rx->squelch_enable);
--void setTuneDrive(double value) {
-- tune_drive=value;
-- calcTuneDriveLevel();
++ double fm_sq=pow(10.0, -2.0*rx->squelch/100.0);
++ SetRXAFMSQThreshold(rx->id, fm_sq);
++ SetRXAFMSQRun(rx->id, rx->squelch_enable);
}
void set_attenuation(int value) {
}
}
--int get_attenuation() {
-- return active_receiver->attenuation;
--}
--
void set_alex_rx_antenna(int v) {
if(active_receiver->id==0) {
active_receiver->alex_antenna=v;
sem_wait(&property_sem);
loadProperties(property_path);
++ value=getProperty("region");
++ if(value) region=atoi(value);
value=getProperty("buffer_size");
if(value) buffer_size=atoi(value);
value=getProperty("fft_size");
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("drive");
-- if(value) drive=atof(value);
-- value=getProperty("tune_drive");
-- if(value) tune_drive=atof(value);
value=getProperty("mic_gain");
if(value) mic_gain=atof(value);
value=getProperty("mic_boost");
if(value) OCfull_tune_time=atoi(value);
value=getProperty("OCmemory_tune_time");
if(value) OCmemory_tune_time=atoi(value);
--#ifdef FREEDV
-- strcpy(freedv_tx_text_data,"NO TEXT DATA");
-- value=getProperty("freedv_tx_text_data");
-- if(value) strcpy(freedv_tx_text_data,value);
--#endif
++ value=getProperty("analog_meter");
++ if(value) analog_meter=atoi(value);
value=getProperty("smeter");
if(value) smeter=atoi(value);
value=getProperty("alc");
if(value) rx_equalizer[3]=atoi(value);
value=getProperty("rit_increment");
if(value) rit_increment=atoi(value);
-- value=getProperty("deviation");
-- if(value) deviation=atoi(value);
value=getProperty("pre_emphasize");
if(value) pre_emphasize=atoi(value);
value=getProperty("filterB");
if(value) filterB=atoi(value);
++ value=getProperty("tone_level");
++ if(value) tone_level=atof(value);
++
#ifdef GPIO
value=getProperty("e1_encoder_action");
if(value) e1_encoder_action=atoi(value);
bandRestoreState();
memRestoreState();
vfo_restore_state();
++#ifdef FREEDV
++ freedv_restore_state();
++#endif
++ value=getProperty("rigctl_enable");
++ if(value) rigctl_enable=atoi(value);
++ value=getProperty("rigctl_port_base");
++ if(value) rigctl_port_base=atoi(value);
++
++ value=getProperty("adc_0_attenuation");
++ if(value) adc_attenuation[0]=atoi(value);
++ value=getProperty("adc_1_attenuation");
++ if(value) adc_attenuation[1]=atoi(value);
sem_post(&property_sem);
}
char value[80];
sem_wait(&property_sem);
++ sprintf(value,"%d",region);
++ setProperty("region",value);
sprintf(value,"%d",buffer_size);
setProperty("buffer_size",value);
sprintf(value,"%d",fft_size);
setProperty("filter_board",value);
sprintf(value,"%d",tx_out_of_band);
setProperty("tx_out_of_band",value);
--/*
-- sprintf(value,"%d",apollo_tuner);
-- setProperty("apollo_tuner",value);
-- sprintf(value,"%d",pa);
-- setProperty("pa",value);
--*/
sprintf(value,"%d",updates_per_second);
setProperty("updates_per_second",value);
sprintf(value,"%d",display_filled);
setProperty("panadapter_low",value);
sprintf(value,"%d",display_sliders);
setProperty("display_sliders",value);
--/*
-- sprintf(value,"%d",display_toolbar);
-- setProperty("display_toolbar",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,"%f",drive);
-- setProperty("drive",value);
-- sprintf(value,"%f",tune_drive);
-- setProperty("tune_drive",value);
sprintf(value,"%d",mic_boost);
setProperty("mic_boost",value);
sprintf(value,"%d",mic_linein);
setProperty("OCfull_tune_time",value);
sprintf(value,"%d",OCmemory_tune_time);
setProperty("OCmemory_tune_time",value);
--#ifdef FREEDV
-- if(strlen(freedv_tx_text_data)>0) {
-- setProperty("freedv_tx_text_data",freedv_tx_text_data);
-- }
--#endif
++ sprintf(value,"%d",analog_meter);
++ setProperty("analog_meter",value);
sprintf(value,"%d",smeter);
setProperty("smeter",value);
sprintf(value,"%d",alc);
#endif
sprintf(value,"%d",local_microphone);
setProperty("local_microphone",value);
--// sprintf(value,"%d",n_selected_input_device);
--// setProperty("n_selected_input_device",value);
sprintf(value,"%d",enable_tx_equalizer);
setProperty("enable_tx_equalizer",value);
setProperty("rx_equalizer.3",value);
sprintf(value,"%d",rit_increment);
setProperty("rit_increment",value);
-- sprintf(value,"%d",deviation);
-- setProperty("deviation",value);
sprintf(value,"%d",pre_emphasize);
setProperty("pre_emphasize",value);
setProperty("vox_enabled",value);
sprintf(value,"%f",vox_threshold);
setProperty("vox_threshold",value);
--/*
-- sprintf(value,"%f",vox_gain);
-- setProperty("vox_gain",value);
--*/
sprintf(value,"%f",vox_hang);
setProperty("vox_hang",value);
sprintf(value,"%d",filterB);
setProperty("filterB",value);
++ sprintf(value,"%f",tone_level);
++ setProperty("tone_level",value);
++
#ifdef GPIO
sprintf(value,"%d",e1_encoder_action);
setProperty("e1_encoder_action",value);
setProperty("e3_encoder_action",value);
#endif
++ sprintf(value,"%d",adc_attenuation[0]);
++ setProperty("adc_0_attenuation",value);
++ sprintf(value,"%d",adc_attenuation[1]);
++ setProperty("adc_1_attenuation",value);
vfo_save_state();
sprintf(value,"%d",receivers);
receiver_save_state(receiver[i]);
}
transmitter_save_state(transmitter);
++#ifdef FREEDV
++ freedv_save_state();
++#endif
filterSaveState();
bandSaveState();
memSaveState();
++
++ sprintf(value,"%d",rigctl_enable);
++ setProperty("rigctl_enable",value);
++ sprintf(value,"%d",rigctl_port_base);
++ setProperty("rigctl_port_base",value);
++
saveProperties(property_path);
sem_post(&property_sem);
}
SetDisplayAvBackmult(rx->id, 0, display_avb);
SetDisplayNumAverage(rx->id, 0, display_average);
}
++
++void set_filter_type(int filter_type) {
++ int i;
++
++ fprintf(stderr,"set_filter_type: %d\n",filter_type);
++ for(i=0;i<RECEIVERS;i++) {
++ receiver[i]->low_latency=filter_type;
++ RXASetMP(receiver[i]->id, filter_type);
++ }
++ transmitter->low_latency=filter_type;
++ TXASetMP(transmitter->id, filter_type);
++}
++
++void set_filter_size(int filter_size) {
++ int i;
++
++ fprintf(stderr,"set_filter_size: %d\n",filter_size);
++ for(i=0;i<RECEIVERS;i++) {
++ receiver[i]->fft_size=filter_size;
++ RXASetNC(receiver[i]->id, filter_size);
++ }
++ transmitter->fft_size=filter_size;
++ TXASetNC(transmitter->id, filter_size);
++}
++
++#ifdef FREEDV
++void set_freedv(int state) {
++fprintf(stderr,"set_freedv: rx=%p state=%d\n",active_receiver,state);
++ g_mutex_lock(&active_receiver->freedv_mutex);
++ active_receiver->freedv=state;
++ if(active_receiver->freedv) {
++ SetRXAPanelRun(active_receiver->id, 0);
++ init_freedv(active_receiver);
++ transmitter->freedv_samples=0;
++ } else {
++ SetRXAPanelRun(active_receiver->id, 1);
++ close_freedv(active_receiver);
++ }
++ g_mutex_unlock(&active_receiver->freedv_mutex);
++ g_idle_add(ext_vfo_update,NULL);
++}
++#endif
++
++void radio_change_region(int r) {
++ region=r;
++ if(region==REGION_UK) {
++ channel_entries=UK_CHANNEL_ENTRIES;
++ band_channels_60m=&band_channels_60m_UK[0];
++ bandstack60.entries=UK_CHANNEL_ENTRIES;
++ bandstack60.current_entry=0;
++ bandstack60.entry=bandstack_entries60_UK;
++ } else {
++ channel_entries=OTHER_CHANNEL_ENTRIES;
++ band_channels_60m=&band_channels_60m_OTHER[0];
++ bandstack60.entries=OTHER_CHANNEL_ENTRIES;
++ bandstack60.current_entry=0;
++ bandstack60.entry=bandstack_entries60_OTHER;
++ }
++}
printf("Code tx mode spi executed in %f milliseconds.\n", elapsd);
gettimeofday(&t20, 0);
}
- }
+ }
-
--- /dev/null
--- /dev/null
++/* Copyright (C)
++* 2017 - Johan Maas, PA3GSB
++*
++* 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 <stdlib.h>
++#include <stdio.h>
++#include <semaphore.h>
++#include <pthread.h>
++
++#include <string.h>
++#include <errno.h>
++#include <math.h>
++
++#include "audio.h"
++
++#include "band.h"
++#include "channel.h"
++#include "discovered.h"
++#include "mode.h"
++#include "filter.h"
++#include "old_protocol.h"
++#include "radio.h"
++#include "toolbar.h"
++#include "vox.h"
++#include <semaphore.h>
++#ifdef PSK
++#include "psk.h"
++#endif
++#include "receiver.h"
++#include "transmitter.h"
++#include "vfo.h"
++
++#include <pigpio.h>
++#include "ext.h"
++
++#define OUTPUT_BUFFER_SIZE 1024
++#define SPEED_48K 0x00
++#define SPEED_96K 0x01
++#define SPEED_192K 0x02
++#define SPEED_384K 0x03
++
++static int display_width;
++static int running;
++static int sampleSpeed =0;
++
++unsigned char iqdata[6];
++unsigned char tx_iqdata[6];
++
++static pthread_t radioberry_thread_id;
++static void start_radioberry_thread();
++static void *radioberry_thread(void* arg);
++
++static void setSampleSpeed();
++static void handleReceiveStream();
++
++struct timeval t0;
++struct timeval t1;
++struct timeval t10;
++struct timeval t11;
++struct timeval t20;
++struct timeval t21;
++float elapsed;
++
++#define RADIOSTATE_RX 0
++#define RADIOSTATE_TX 1
++static int radiostate = RADIOSTATE_RX;
++
++void spiWriter();
++void spiReader();
++
++
++int prev_drive_level;
++
++static int rxcount =0;
++static int txcount =0;
++
++sem_t mutex;
++
++#ifdef PSK
++static int psk_samples=0;
++static int psk_divisor=6;
++#endif
++
++static int h;
++
++
++#define HANDLER_STEADY_TIME_US 5000
++void setup_handler(int pin, gpioAlertFunc_t pAlert) {
++ gpioSetMode(pin, PI_INPUT);
++ gpioSetPullUpDown(pin,PI_PUD_UP);
++ // give time to settle to avoid false triggers
++ usleep(10000);
++ gpioSetAlertFunc(pin, pAlert);
++ gpioGlitchFilter(pin, HANDLER_STEADY_TIME_US);
++}
++
++void cwPTT_Alert(int gpio, int level, uint32_t tick) {
++ //fprintf(stderr,"radioberry ptt swith %d 0=ptt off and 1=ptt on\n", level);
++ //fprintf(stderr,"%d - %d -%d - %d\n", running, cw_breakin, transmitter->mode, level);
++ if (running && cw_breakin && (transmitter->mode==modeCWU || transmitter->mode==modeCWL)){
++ g_idle_add(ext_mox_update,(gpointer)level);
++ }
++}
++
++float timedifference_msec(struct timeval t0, struct timeval t1)
++{
++ return (t1.tv_sec - t0.tv_sec) * 1000.0f + (t1.tv_usec - t0.tv_usec) / 1000.0f;
++}
++
++void radioberry_protocol_init(int rx,int pixels) {
++ int i;
++
++ fprintf(stderr,"radioberry_protocol_init\n");
++ sem_init(&mutex, 0, 1); //mutal exlusion
++ display_width=pixels;
++ fprintf(stderr,"radioberry_protocol: buffer size: =%d\n", buffer_size);
++
++/*
++ if (gpioInitialise() < 0) {
++ fprintf(stderr,"radioberry_protocol: gpio could not be initialized. \n");
++ exit(-1);
++ }
++<<<<<<< HEAD
++*/
++
++ gpioSetMode(13, PI_INPUT); //rx1_FIFOEmpty
++ gpioSetMode(16, PI_INPUT); //rx2_FIFOEmpty
++=======
++#endif
++
++ gpioSetMode(13, PI_INPUT);
++>>>>>>> upstream/master
++ gpioSetMode(20, PI_INPUT);
++ gpioSetMode(21, PI_OUTPUT);
++
++ setup_handler(17, cwPTT_Alert);
++
++
++ h = spiOpen(0, 15625000, 49155);
++ if (h < 0) {
++ fprintf(stderr,"radioberry_protocol: spi bus could not be initialized. \n");
++ exit(-1);
++ }
++
++ printf("init done \n");
++
++ setSampleSpeed();
++
++ if(transmitter->local_microphone) {
++ if(audio_open_input()!=0) {
++ fprintf(stderr,"audio_open_input failed\n");
++ transmitter->local_microphone=0;
++ }
++ }
++
++ start_radioberry_thread();
++}
++
++static void start_radioberry_thread() {
++ int rc;
++ fprintf(stderr,"radioberry_protocol starting radioberry thread\n");
++ rc=pthread_create(&radioberry_thread_id,NULL,radioberry_thread,NULL);
++ if(rc != 0) {
++ fprintf(stderr,"radioberry_protocol: pthread_create failed on radioberry_thread: rc=%d\n", rc);
++ exit(-1);
++ }
++}
++
++static void *radioberry_thread(void* arg) {
++ fprintf(stderr, "radioberry_protocol: radioberry_thread\n");
++
++ running=1;
++
++ gettimeofday(&t20, 0);
++ gettimeofday(&t0, 0);
++
++ gpioSetMode(13, PI_INPUT);
++ gpioSetMode(20, PI_INPUT);
++ gpioSetMode(21, PI_OUTPUT);
++
++ while(running) {
++
++ sem_wait(&mutex);
++
++ if (isTransmitting())
++ radiostate = RADIOSTATE_TX;
++ else
++ radiostate = RADIOSTATE_RX;
++
++ if(radiostate == RADIOSTATE_TX) {
++ gpioWrite(21, 1);
++ }
++ else
++ {
++ gpioWrite(21, 0);
++ spiReader();
++ handleReceiveStream();
++ sem_post(&mutex);
++ }
++ }
++}
++
++void radioberry_protocol_iq_samples(int isample,int qsample) {
++
++ if(radiostate == RADIOSTATE_TX) {
++
++ tx_iqdata[0] = 0;
++ tx_iqdata[1] = transmitter->drive / 6.4; // convert drive level from 0-255 to 0-39 )
++ if (prev_drive_level != transmitter->drive) {
++ printf("drive level %d - corrected drive level %d \n", transmitter->drive_level, tx_iqdata[1]);
++ prev_drive_level = transmitter->drive;
++ }
++ tx_iqdata[2] = isample>>8;
++ tx_iqdata[3] = isample;
++ tx_iqdata[4] = qsample>>8;
++ tx_iqdata[5] = qsample;
++
++ spiWriter();
++
++ sem_post(&mutex);
++ }
++
++}
++
++void *radioberry_protocol_process_local_mic(unsigned char *buffer,int le) {
++ int b;
++ short mic_sample;
++ // always 48000 samples per second
++
++ b=0;
++ int i;
++ for(i=0;i<1024;i++) {
++ if(le) {
++ mic_sample = (short)((buffer[b++]&0xFF) | (buffer[b++]<<8));
++ } else {
++ mic_sample = (short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
++ }
++ if(active_receiver->freedv) {
++ add_freedv_mic_sample(transmitter,mic_sample);
++ } else {
++ add_mic_sample(transmitter,mic_sample);
++ }
++ }
++}
++
++static void handleReceiveStream() {
++ int left_sample;
++ int right_sample;
++ double left_sample_double;
++ double right_sample_double;
++ int r;
++
++ left_sample = (int)((signed char) iqdata[0]) << 16;
++ left_sample += (int)((unsigned char)iqdata[1]) << 8;
++ left_sample += (int)((unsigned char)iqdata[2]);
++ right_sample = (int)((signed char) iqdata[3]) << 16;
++ right_sample += (int)((unsigned char)iqdata[4]) << 8;
++ right_sample += (int)((unsigned char)iqdata[5]);
++
++ left_sample_double=(double)left_sample/8388607.0; // 24 bit sample 2^23-1
++ right_sample_double=(double)right_sample/8388607.0; // 24 bit sample 2^23-1
++
++ for(r=0;r<RECEIVERS;r++) {
++ add_iq_samples(receiver[r], left_sample_double,right_sample_double);
++ }
++}
++
++void setSampleSpeed() {
++ switch(active_receiver->sample_rate) {
++ case 48000:
++ sampleSpeed=SPEED_48K;
++ break;
++ case 96000:
++ sampleSpeed=SPEED_96K;
++ break;
++ case 192000:
++ sampleSpeed=SPEED_192K;
++ break;
++ case 384000:
++ sampleSpeed=SPEED_384K;
++ break;
++ }
++}
++
++void radioberry_protocol_stop() {
++
++ running=FALSE;
++
++ if (h !=0)
++ spiClose(h);
++
++#ifndef GPIO
++ gpioTerminate();
++#endif
++
++}
++
++void spiReader() {
++ // wait till rxFIFO buffer is filled with at least one element
++ while ( gpioRead(13) == 1) {};
++
++ setSampleSpeed();
++
++ int v=receiver[0]->id;
++ long long rxFrequency=vfo[v].frequency-vfo[v].lo;
++ if(vfo[v].rit_enabled) {
++ rxFrequency+=vfo[v].rit;
++ }
++ if(vfo[active_receiver->id].mode==modeCWU) {
++ rxFrequency-=(long long)cw_keyer_sidetone_frequency;
++ } else if(vfo[active_receiver->id].mode==modeCWL) {
++ rxFrequency+=(long long)cw_keyer_sidetone_frequency;
++ }
++
++ iqdata[0] = (sampleSpeed & 0x03);
++ iqdata[1] = (((active_receiver->random << 6) & 0x40) | ((active_receiver->dither <<5) & 0x20) | (attenuation & 0x1F));
++ iqdata[2] = ((rxFrequency >> 24) & 0xFF);
++ iqdata[3] = ((rxFrequency >> 16) & 0xFF);
++ iqdata[4] = ((rxFrequency >> 8) & 0xFF);
++ iqdata[5] = (rxFrequency & 0xFF);
++
++ spiXfer(h, iqdata, iqdata, 6);
++
++ //firmware: tdata(56'h00010203040506) -> 0-1-2-3-4-5-6 (element 0 contains 0; second element contains 1)
++ rxcount ++;
++ if (rxcount == 48000) {
++ rxcount = 0;
++ gettimeofday(&t1, 0);
++ elapsed = timedifference_msec(t0, t1);
++ printf("Code rx mode spi executed in %f milliseconds.\n", elapsed);
++ gettimeofday(&t0, 0);
++ }
++}
++
++void spiWriter() {
++ while ( gpioRead(20) == 1) {};
++
++<<<<<<< HEAD
++ spiXfer(rx1_spi_handler, tx_iqdata, tx_iqdata, 6);
++
++ long long txFrequency;
++ if(split) {
++ txFrequency=vfo[VFO_B].frequency-vfo[VFO_A].lo+vfo[VFO_B].offset;
++ } else {
++ txFrequency=vfo[VFO_A].frequency-vfo[VFO_B].lo+vfo[VFO_A].offset;
++ }
++ tx_iqdata[0] = cw_keyer_speed | (cw_keyer_mode<<6);
++ tx_iqdata[1] = cw_keyer_weight | (cw_keyer_spacing<<7);
++ tx_iqdata[2] = ((txFrequency >> 24) & 0xFF);
++ tx_iqdata[3] = ((txFrequency >> 16) & 0xFF);
++ tx_iqdata[4] = ((txFrequency >> 8) & 0xFF);
++ tx_iqdata[5] = (txFrequency & 0xFF);
++
++ spiXfer(rx2_spi_handler, tx_iqdata, tx_iqdata, 6);
++=======
++ spiXfer(h, tx_iqdata, tx_iqdata, 6);
++>>>>>>> upstream/master
++
++ txcount ++;
++ if (txcount == 48000) {
++ txcount = 0;
++ gettimeofday(&t21, 0);
++ float elapsd = timedifference_msec(t20, t21);
++ printf("Code tx mode spi executed in %f milliseconds.\n", elapsd);
++ gettimeofday(&t20, 0);
++ }
++}
--- /dev/null
--- /dev/null
++/* Copyright (C)
++* 2017 - John Melton, G0ORX/N6LYT
++*
++* 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 <math.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++#include <wdsp.h>
++
++#include "alex.h"
++#include "band.h"
++#include "bandstack.h"
++#include "channel.h"
++#include "main.h"
++#include "receiver.h"
++#include "meter.h"
++#include "mode.h"
++#include "property.h"
++#include "radio.h"
++#include "vfo.h"
++#include "vox.h"
++#include "meter.h"
++#include "toolbar.h"
++#include "tx_panadapter.h"
++#include "waterfall.h"
++#include "receiver.h"
++#include "transmitter.h"
++#include "new_protocol.h"
++#include "old_protocol.h"
++#ifdef FREEDV
++#include "freedv.h"
++#endif
++#include "audio_waterfall.h"
++#include "ext.h"
++<<<<<<< HEAD
++
++double getNextSideToneSample();
++=======
++>>>>>>> upstream/master
++
++#define min(x,y) (x<y?x:y)
++#define max(x,y) (x<y?y:x)
++
++static int filterLow;
++static int filterHigh;
++
++static int waterfall_samples=0;
++static int waterfall_resample=8;
++
++<<<<<<< HEAD
++int key = 0;
++
++=======
++>>>>>>> upstream/master
++static gint update_out_of_band(gpointer data) {
++ TRANSMITTER *tx=(TRANSMITTER *)data;
++ tx->out_of_band=0;
++ vfo_update();
++ return FALSE;
++}
++
++void transmitter_set_out_of_band(TRANSMITTER *tx) {
++ tx->out_of_band=1;
++ tx->out_of_band_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000,update_out_of_band, tx, NULL);
++}
++
++void transmitter_set_deviation(TRANSMITTER *tx) {
++ SetTXAFMDeviation(tx->id, (double)tx->deviation);
++}
++
++void transmitter_set_am_carrier_level(TRANSMITTER *tx) {
++ SetTXAAMCarrierLevel(tx->id, tx->am_carrier_level);
++}
++
++void transmitter_set_ctcss(TRANSMITTER *tx,int run,double frequency) {
++ tx->ctcss=run;
++ tx->ctcss_frequency=frequency;
++fprintf(stderr,"transmitter_set_ctcss: ctcss_frequency=%f run=%d\n",tx->ctcss_frequency,tx->ctcss);
++ SetTXACTCSSFreq(tx->id, tx->ctcss_frequency);
++ SetTXACTCSSRun(tx->id, tx->ctcss);
++}
++
++void transmitter_set_compressor_level(TRANSMITTER *tx,double level) {
++ tx->compressor_level=level;
++ SetTXACompressorGain(tx->id, tx->compressor_level);
++}
++
++void transmitter_set_compressor(TRANSMITTER *tx,int state) {
++ tx->compressor=state;
++ SetTXACompressorRun(tx->id, tx->compressor);
++}
++
++void reconfigure_transmitter(TRANSMITTER *tx,int height) {
++ gtk_widget_set_size_request(tx->panadapter, tx->width, height);
++}
++
++void transmitter_save_state(TRANSMITTER *tx) {
++ char name[128];
++ char value[128];
++
++ sprintf(name,"transmitter.%d.fps",tx->id);
++ sprintf(value,"%d",tx->fps);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.filter_low",tx->id);
++ sprintf(value,"%d",tx->filter_low);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.filter_high",tx->id);
++ sprintf(value,"%d",tx->filter_high);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.alex_antenna",tx->id);
++ sprintf(value,"%d",tx->alex_antenna);
++ setProperty(name,value);
++
++ sprintf(name,"transmitter.%d.panadapter_low",tx->id);
++ sprintf(value,"%d",tx->panadapter_low);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.panadapter_high",tx->id);
++ sprintf(value,"%d",tx->panadapter_high);
++ setProperty(name,value);
++
++ sprintf(name,"transmitter.%d.local_microphone",tx->id);
++ sprintf(value,"%d",tx->local_microphone);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.input_device",tx->id);
++ sprintf(value,"%d",tx->input_device);
++ setProperty(name,value);
++
++ sprintf(name,"transmitter.%d.low_latency",tx->id);
++ sprintf(value,"%d",tx->low_latency);
++ setProperty(name,value);
++#ifdef PURESIGNAL
++ sprintf(name,"transmitter.%d.puresignal",tx->id);
++ sprintf(value,"%d",tx->puresignal);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.auto_on",tx->id);
++ sprintf(value,"%d",tx->auto_on);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.single_on",tx->id);
++ sprintf(value,"%d",tx->single_on);
++ setProperty(name,value);
++#endif
++ sprintf(name,"transmitter.%d.ctcss",tx->id);
++ sprintf(value,"%d",tx->ctcss);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.ctcss_frequency",tx->id);
++ sprintf(value,"%f",tx->ctcss_frequency);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.deviation",tx->id);
++ sprintf(value,"%d",tx->deviation);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.am_carrier_level",tx->id);
++ sprintf(value,"%f",tx->am_carrier_level);
++ setProperty(name,value);
++#ifdef FREEDV
++ if(strlen(tx->freedv_text_data)>0) {
++ sprintf(name,"transmitter.%d.freedv_text_data",tx->id);
++ sprintf(value,"%s",tx->freedv_text_data);
++ setProperty(name,value);
++ }
++#endif
++ sprintf(name,"transmitter.%d.drive",tx->id);
++ sprintf(value,"%d",tx->drive);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.tune_percent",tx->id);
++ sprintf(value,"%d",tx->tune_percent);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.tune_use_drive",tx->id);
++ sprintf(value,"%d",tx->tune_use_drive);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.drive_level",tx->id);
++ sprintf(value,"%d",tx->drive_level);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.compressor",tx->id);
++ sprintf(value,"%d",tx->compressor);
++ setProperty(name,value);
++ sprintf(name,"transmitter.%d.compressor_level",tx->id);
++ sprintf(value,"%f",tx->compressor_level);
++ setProperty(name,value);
++}
++
++void transmitter_restore_state(TRANSMITTER *tx) {
++ char name[128];
++ char *value;
++
++ sprintf(name,"transmitter.%d.fps",tx->id);
++ value=getProperty(name);
++ if(value) tx->fps=atoi(value);
++ sprintf(name,"transmitter.%d.filter_low",tx->id);
++ value=getProperty(name);
++ if(value) tx->filter_low=atoi(value);
++ sprintf(name,"transmitter.%d.filter_high",tx->id);
++ value=getProperty(name);
++ if(value) tx->filter_high=atoi(value);
++ sprintf(name,"transmitter.%d.alex_antenna",tx->id);
++ value=getProperty(name);
++ if(value) tx->alex_antenna=atoi(value);
++
++ sprintf(name,"transmitter.%d.panadapter_low",tx->id);
++ value=getProperty(name);
++ if(value) tx->panadapter_low=atoi(value);
++ sprintf(name,"transmitter.%d.panadapter_high",tx->id);
++ value=getProperty(name);
++ if(value) tx->panadapter_high=atoi(value);
++
++ sprintf(name,"transmitter.%d.local_microphone",tx->id);
++ value=getProperty(name);
++ if(value) tx->local_microphone=atoi(value);
++ sprintf(name,"transmitter.%d.input_device",tx->id);
++ value=getProperty(name);
++ if(value) tx->input_device=atoi(value);
++ sprintf(name,"transmitter.%d.low_latency",tx->id);
++ value=getProperty(name);
++ if(value) tx->low_latency=atoi(value);
++#ifdef PURESIGNAL
++ sprintf(name,"transmitter.%d.puresignal",tx->id);
++ value=getProperty(name);
++ if(value) tx->puresignal=atoi(value);
++ sprintf(name,"transmitter.%d.auto_on",tx->id);
++ value=getProperty(name);
++ if(value) tx->auto_on=atoi(value);
++ sprintf(name,"transmitter.%d.single_on",tx->id);
++ value=getProperty(name);
++ if(value) tx->single_on=atoi(value);
++#endif
++ sprintf(name,"transmitter.%d.ctcss",tx->id);
++ value=getProperty(name);
++ if(value) tx->ctcss=atoi(value);
++ sprintf(name,"transmitter.%d.ctcss_frequency",tx->id);
++ value=getProperty(name);
++ if(value) tx->ctcss_frequency=atof(value);
++ sprintf(name,"transmitter.%d.deviation",tx->id);
++ value=getProperty(name);
++ if(value) tx->deviation=atoi(value);
++ sprintf(name,"transmitter.%d.am_carrier_level",tx->id);
++ value=getProperty(name);
++ if(value) tx->am_carrier_level=atof(value);
++#ifdef FREEDV
++ sprintf(name,"transmitter.%d.freedv_text_data",tx->id);
++ value=getProperty(name);
++ if(value) strcpy(tx->freedv_text_data,value);
++#endif
++ sprintf(name,"transmitter.%d.drive",tx->id);
++ value=getProperty(name);
++ if(value) tx->drive=atoi(value);
++ sprintf(name,"transmitter.%d.tune_percent",tx->id);
++ value=getProperty(name);
++ if(value) tx->tune_percent=atoi(value);
++ sprintf(name,"transmitter.%d.tune_use_drive",tx->id);
++ value=getProperty(name);
++ if(value) tx->tune_use_drive=atoi(value);
++ sprintf(name,"transmitter.%d.drive_level",tx->id);
++ value=getProperty(name);
++ if(value) tx->drive_level=atoi(value);
++ sprintf(name,"transmitter.%d.compressor",tx->id);
++ value=getProperty(name);
++ if(value) tx->compressor=atoi(value);
++ sprintf(name,"transmitter.%d.compressor_level",tx->id);
++ value=getProperty(name);
++ if(value) tx->compressor_level=atof(value);
++}
++
++static gboolean update_display(gpointer data) {
++ TRANSMITTER *tx=(TRANSMITTER *)data;
++ int rc;
++
++ int i;
++
++//fprintf(stderr,"update_display: tx id=%d\n",tx->id);
++ if(tx->displaying) {
++#ifdef AUDIO_SAMPLES
++ if(audio_samples!=NULL) {
++ GetPixels(CHANNEL_AUDIO,0,audio_samples,&rc);
++ if(rc) {
++ audio_waterfall_update();
++ }
++ }
++#endif
++#ifdef PURESIGNAL
++ if(tx->puresignal && tx->feedback) {
++ RECEIVER *tx_feedback=receiver[PS_TX_FEEDBACK];
++ GetPixels(tx_feedback->id,0,tx_feedback->pixel_samples,&rc);
++ memcpy(tx->pixel_samples,tx_feedback->pixel_samples,sizeof(float)*tx->pixels);
++ } else {
++#endif
++ GetPixels(tx->id,0,tx->pixel_samples,&rc);
++#ifdef PURESIGNAL
++ }
++#endif
++ if(rc) {
++ tx_panadapter_update(tx);
++ }
++
++ transmitter->alc=GetTXAMeter(tx->id, alc);
++ double constant1=3.3;
++ double constant2=0.095;
++
++#ifdef RADIOBERRY
++ if(protocol==ORIGINAL_PROTOCOL || protocol==RADIOBERRY_PROTOCOL) {
++#else
++ if(protocol==ORIGINAL_PROTOCOL) {
++#endif
++ switch(device) {
++ case DEVICE_METIS:
++ constant1=3.3;
++ constant2=0.09;
++ break;
++ case DEVICE_HERMES:
++ constant1=3.3;
++ constant2=0.095;
++ break;
++ case DEVICE_ANGELIA:
++ constant1=3.3;
++ constant2=0.095;
++ break;
++ case DEVICE_ORION:
++ constant1=5.0;
++ constant2=0.108;
++ break;
++ case DEVICE_ORION2:
++ constant1=5.0;
++ constant2=0.108;
++ break;
++ case DEVICE_HERMES_LITE:
++ break;
++#ifdef RADIOBERRY
++ case RADIOBERRY_SPI_DEVICE:
++ break;
++#endif
++ }
++
++ int power=alex_forward_power;
++ if(power==0) {
++ power=exciter_power;
++ }
++ double v1;
++ v1=((double)power/4095.0)*constant1;
++ transmitter->fwd=(v1*v1)/constant2;
++
++ power=exciter_power;
++ v1=((double)power/4095.0)*constant1;
++ transmitter->exciter=(v1*v1)/constant2;
++
++ transmitter->rev=0.0;
++ if(alex_forward_power!=0) {
++ power=alex_reverse_power;
++ v1=((double)power/4095.0)*constant1;
++ transmitter->rev=(v1*v1)/constant2;
++ }
++ } else {
++ switch(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_ORION2:
++ constant1=5.0;
++ constant2=0.108;
++ break;
++ case NEW_DEVICE_HERMES_LITE:
++ constant1=3.3;
++ constant2=0.09;
++ break;
++#ifdef RADIOBERRY
++ case RADIOBERRY_SPI_DEVICE:
++ constant1=3.3;
++ constant2=0.09;
++ break;
++#endif
++ }
++
++ int power=alex_forward_power;
++ if(power==0) {
++ power=exciter_power;
++ }
++ double v1;
++ v1=((double)power/4095.0)*constant1;
++ transmitter->fwd=(v1*v1)/constant2;
++
++ power=exciter_power;
++ v1=((double)power/4095.0)*constant1;
++ transmitter->exciter=(v1*v1)/constant2;
++
++ transmitter->rev=0.0;
++ if(alex_forward_power!=0) {
++ power=alex_reverse_power;
++ v1=((double)power/4095.0)*constant1;
++ transmitter->rev=(v1*v1)/constant2;
++ }
++ }
++
++ meter_update(active_receiver,POWER,transmitter->fwd,transmitter->rev,transmitter->exciter,transmitter->alc);
++
++ return TRUE; // keep going
++ }
++ return FALSE; // no more timer events
++}
++
++
++static void init_analyzer(TRANSMITTER *tx) {
++ int flp[] = {0};
++ double keep_time = 0.1;
++ int n_pixout=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=tx->pixels;
++ int stitches = 1;
++ int avm = 0;
++ double tau = 0.001 * 120.0;
++ 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) tx->fps, keep_time * (double) fft_size * (double) tx->fps);
++
++ overlap = (int)max(0.0, ceil(fft_size - (double)tx->mic_sample_rate / (double)tx->fps));
++
++ fprintf(stderr,"SetAnalyzer id=%d buffer_size=%d overlap=%d\n",tx->id,tx->output_samples,overlap);
++
++
++ SetAnalyzer(tx->id,
++ n_pixout,
++ 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
++ tx->output_samples, //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
++ 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 create_visual(TRANSMITTER *tx) {
++
++ fprintf(stderr,"transmitter: create_visual: id=%d\n",tx->id);
++
++ tx->panel=gtk_fixed_new();
++ gtk_widget_set_size_request (tx->panel, tx->width, tx->height);
++
++ if(tx->display_panadapter) {
++ tx_panadapter_init(tx,tx->width,tx->height);
++ gtk_fixed_put(GTK_FIXED(tx->panel),tx->panadapter,0,0);
++ }
++
++ gtk_widget_show_all(tx->panel);
++
++}
++
++TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps, int width, int height) {
++ int rc;
++
++ TRANSMITTER *tx=malloc(sizeof(TRANSMITTER));
++ tx->id=id;
++ tx->buffer_size=buffer_size;
++ tx->fft_size=fft_size;
++ tx->fps=fps;
++
++#ifdef RADIOBERRY
++ if(protocol==ORIGINAL_PROTOCOL || protocol==RADIOBERRY_PROTOCOL) {
++#else
++ if(protocol==ORIGINAL_PROTOCOL) {
++#endif
++ tx->mic_sample_rate=48000;
++ tx->mic_dsp_rate=48000;
++ tx->iq_output_rate=48000;
++ tx->output_samples=tx->buffer_size;
++ tx->pixels=width; // to allow 48k to 24k conversion
++ } else {
++ tx->mic_sample_rate=48000;
++ tx->mic_dsp_rate=96000;
++ tx->iq_output_rate=192000;
++ tx->output_samples=tx->buffer_size*4;
++ tx->pixels=width*4; // to allow 192k to 24k conversion
++ }
++
++ tx->width=width;
++ tx->height=height;
++ tx->display_panadapter=1;
++ tx->display_waterfall=0;
++
++ tx->panadapter_high=0;
++ tx->panadapter_low=-60;
++
++ tx->displaying=0;
++
++ tx->alex_antenna=ALEX_TX_ANTENNA_1;
++
++fprintf(stderr,"create_transmitter: id=%d buffer_size=%d mic_sample_rate=%d mic_dsp_rate=%d iq_output_rate=%d output_samples=%d fps=%d\n",tx->id, tx->buffer_size, tx->mic_sample_rate, tx->mic_dsp_rate, tx->iq_output_rate, tx->output_samples,tx->fps);
++
++ tx->filter_low=tx_filter_low;
++ tx->filter_high=tx_filter_high;
++
++ tx->out_of_band=0;
++
++ tx->low_latency=0;
++
++#ifdef PURESIGNAL
++ tx->puresignal=0;
++ tx->feedback=0;
++ tx->twotone=0;
++ tx->auto_on=0;
++ tx->single_on=0;
++#endif
++
++ tx->ctcss=0;
++ tx->ctcss_frequency=100.0;
++
++ tx->deviation=2500;
++ tx->am_carrier_level=0.5;
++
++#ifdef FREEDV
++ strcpy(tx->freedv_text_data,"Call, Name and Location");
++ tx->freedv_samples=0;
++#endif
++
++ tx->drive=50;
++ tx->tune_percent=10;
++ tx->tune_use_drive=0;
++
++ tx->compressor=0;
++ tx->compressor_level=0.0;
++
++ tx->local_microphone=0;
++
++ transmitter_restore_state(tx);
++
++
++ // allocate buffers
++fprintf(stderr,"transmitter: allocate buffers: mic_input_buffer=%d iq_output_buffer=%d pixels=%d\n",tx->buffer_size,tx->output_samples,tx->pixels);
++ tx->mic_input_buffer=malloc(sizeof(double)*2*tx->buffer_size);
++ tx->iq_output_buffer=malloc(sizeof(double)*2*tx->output_samples);
++ tx->samples=0;
++ tx->pixel_samples=malloc(sizeof(float)*tx->pixels);
++fprintf(stderr,"transmitter: allocate buffers: mic_input_buffer=%p iq_output_buffer=%p pixels=%p\n",tx->mic_input_buffer,tx->iq_output_buffer,tx->pixel_samples);
++
++ fprintf(stderr,"create_transmitter: OpenChannel id=%d buffer_size=%d fft_size=%d sample_rate=%d dspRate=%d outputRate=%d\n",
++ tx->id,
++ tx->buffer_size,
++ 2048, // tx->fft_size,
++ tx->mic_sample_rate,
++ tx->mic_dsp_rate,
++ tx->iq_output_rate);
++
++ OpenChannel(tx->id,
++ tx->buffer_size,
++ 2048, // tx->fft_size,
++ tx->mic_sample_rate,
++ tx->mic_dsp_rate,
++ tx->iq_output_rate,
++ 1, // transmit
++ 0, // run
++ 0.010, 0.025, 0.0, 0.010, 0);
++
++ TXASetNC(tx->id, tx->fft_size);
++ TXASetMP(tx->id, tx->low_latency);
++
++
++ int mode=vfo[VFO_A].mode;
++ if(split) {
++ mode=vfo[VFO_B].mode;
++ }
++
++ SetTXABandpassWindow(tx->id, 1);
++ SetTXABandpassRun(tx->id, 1);
++
++ SetTXAFMEmphPosition(tx->id,pre_emphasize);
++
++ SetTXACFIRRun(tx->id, protocol==NEW_PROTOCOL?1:0); // turned on if new protocol
++ if(enable_tx_equalizer) {
++ SetTXAGrphEQ(tx->id, tx_equalizer);
++ SetTXAEQRun(tx->id, 1);
++ } else {
++ SetTXAEQRun(tx->id, 0);
++ }
++
++ transmitter_set_ctcss(tx,tx->ctcss,tx->ctcss_frequency);
++ SetTXAAMSQRun(tx->id, 0);
++ SetTXAosctrlRun(tx->id, 0);
++
++ SetTXAALCAttack(tx->id, 1);
++ SetTXAALCDecay(tx->id, 10);
++ SetTXAALCSt(tx->id, 1); // turn it on (always on)
++
++ SetTXALevelerAttack(tx->id, 1);
++ SetTXALevelerDecay(tx->id, 500);
++ SetTXALevelerTop(tx->id, 5.0);
++ SetTXALevelerSt(tx->id, tx_leveler);
++
++ SetTXAPreGenMode(tx->id, 0);
++ SetTXAPreGenToneMag(tx->id, 0.0);
++ SetTXAPreGenToneFreq(tx->id, 0.0);
++ SetTXAPreGenRun(tx->id, 0);
++
++ SetTXAPostGenMode(tx->id, 0);
++ SetTXAPostGenToneMag(tx->id, tone_level);
++ SetTXAPostGenTTMag(tx->id, tone_level,tone_level);
++ SetTXAPostGenToneFreq(tx->id, 0.0);
++ SetTXAPostGenRun(tx->id, 0);
++
++ double gain=pow(10.0, mic_gain / 20.0);
++ SetTXAPanelGain1(tx->id,gain);
++ SetTXAPanelRun(tx->id, 1);
++
++ SetTXAFMDeviation(tx->id, (double)tx->deviation);
++ SetTXAAMCarrierLevel(tx->id, tx->am_carrier_level);
++
++ SetTXACompressorGain(tx->id, tx->compressor_level);
++ SetTXACompressorRun(tx->id, tx->compressor);
++
++ tx_set_mode(tx,mode);
++
++ XCreateAnalyzer(tx->id, &rc, 262144, 1, 1, "");
++ if (rc != 0) {
++ fprintf(stderr, "XCreateAnalyzer id=%d failed: %d\n",tx->id,rc);
++ } else {
++ init_analyzer(tx);
++ }
++
++ create_visual(tx);
++
++ return tx;
++}
++
++void tx_set_mode(TRANSMITTER* tx,int mode) {
++ if(tx!=NULL) {
++ tx->mode=mode;
++ SetTXAMode(tx->id, tx->mode);
++ tx_set_filter(tx,tx_filter_low,tx_filter_high);
++ }
++}
++
++void tx_set_filter(TRANSMITTER *tx,int low,int high) {
++ int mode;
++ if(split) {
++ mode=vfo[1].mode;
++ } else {
++ mode=vfo[0].mode;
++ }
++//fprintf(stderr,"tx_set_filter: tx=%p mode=%d low=%d high=%d\n",tx,mode,low,high);
++ switch(mode) {
++ case modeLSB:
++ case modeCWL:
++ case modeDIGL:
++ tx->filter_low=-high;
++ tx->filter_high=-low;
++ break;
++ case modeUSB:
++ case modeCWU:
++ case modeDIGU:
++ tx->filter_low=low;
++ tx->filter_high=high;
++ break;
++ case modeDSB:
++ case modeAM:
++ case modeSAM:
++ tx->filter_low=-high;
++ tx->filter_high=high;
++ break;
++ case modeFMN:
++ if(tx->deviation==2500) {
++ tx->filter_low=-4000;
++ tx->filter_high=4000;
++ } else {
++ tx->filter_low=-8000;
++ tx->filter_high=8000;
++ }
++ break;
++ case modeDRM:
++ tx->filter_low=7000;
++ tx->filter_high=17000;
++ break;
++ }
++
++ double fl=tx->filter_low;
++ double fh=tx->filter_high;
++
++ if(split) {
++ fl+=vfo[VFO_B].offset;
++ fh+=vfo[VFO_B].offset;
++ } else {
++ fl+=vfo[VFO_A].offset;
++ fh+=vfo[VFO_A].offset;
++ }
++ SetTXABandpassFreqs(tx->id, fl,fh);
++}
++
++void tx_set_pre_emphasize(TRANSMITTER *tx,int state) {
++ SetTXAFMEmphPosition(tx->id,state);
++}
++
++static void full_tx_buffer(TRANSMITTER *tx) {
++ long isample;
++ long qsample;
++ double gain;
++ int j;
++ int error;
++ int mode;
++
++ switch(protocol) {
++#ifdef RADIOBERRY
++ case RADIOBERRY_PROTOCOL:
++#endif
++ case ORIGINAL_PROTOCOL:
++ gain=32767.0; // 16 bit
++ break;
++ case NEW_PROTOCOL:
++ gain=8388607.0; // 24 bit
++ break;
++ }
++
++ update_vox(tx);
++
++ fexchange0(tx->id, tx->mic_input_buffer, tx->iq_output_buffer, &error);
++ if(error!=0) {
++ fprintf(stderr,"full_tx_buffer: id=%d fexchange0: error=%d\n",tx->id,error);
++ }
++
++#ifdef PURESIGNAL
++ if(tx->displaying && !(tx->puresignal && tx->feedback)) {
++#else
++ if(tx->displaying) {
++#endif
++ Spectrum0(1, tx->id, 0, 0, tx->iq_output_buffer);
++ }
++
++ if(isTransmitting()) {
++
++ if(radio->device==NEW_DEVICE_ATLAS && atlas_penelope) {
++ if(tune && !transmitter->tune_use_drive) {
++ gain=gain*((double)transmitter->drive_level*100.0/(double)transmitter->tune_percent);
++ } else {
++ gain=gain*(double)transmitter->drive_level;
++ }
++ }
++
++ for(j=0;j<tx->output_samples;j++) {
++ double is=tx->iq_output_buffer[j*2];
++ double qs=tx->iq_output_buffer[(j*2)+1];
++ isample=is>=0.0?(long)floor(is*gain+0.5):(long)ceil(is*gain-0.5);
++ qsample=qs>=0.0?(long)floor(qs*gain+0.5):(long)ceil(qs*gain-0.5);
++ switch(protocol) {
++ case ORIGINAL_PROTOCOL:
++ old_protocol_iq_samples(isample,qsample);
++ break;
++ case NEW_PROTOCOL:
++ new_protocol_iq_samples(isample,qsample);
++ break;
++#ifdef RADIOBERRY
++ case RADIOBERRY_PROTOCOL:
++ radioberry_protocol_iq_samples(isample,qsample);
++ break;
++#endif
++ }
++ }
++ }
++
++}
++
++void add_mic_sample(TRANSMITTER *tx,short mic_sample) {
++ int mode;
++ double sample;
++ double mic_sample_double;
++ int i,s;
++
++ if(split) {
++ mode=vfo[1].mode;
++ } else {
++ mode=vfo[0].mode;
++ }
++
++<<<<<<< HEAD
++ if (tune) {
++ mic_sample_double=0.0;
++ }
++ else if(mode==modeCWL || mode==modeCWU) {
++ if (isTransmitting()) {
++ if (key == 1) {
++ mic_sample_double = getNextSideToneSample();
++ cw_audio_write(mic_sample_double * cw_keyer_sidetone_volume/ 127.0);
++ mic_sample_double = mic_sample_double * 200000; //* amplitude
++ } else mic_sample_double=0.0;
++ }
++ } else {
++=======
++ if(mode==modeCWL || mode==modeCWU || tune) {
++ mic_sample_double=0.0;
++ } else {
++ //long sam=mic_sample<<16;
++ //sample=(double)sam;
++ //mic_sample_double=(1.0 / 2147483648.0) * sample;
++>>>>>>> upstream/master
++ mic_sample_double=(double)mic_sample/32768.0;
++ }
++ tx->mic_input_buffer[tx->samples*2]=mic_sample_double;
++ tx->mic_input_buffer[(tx->samples*2)+1]=0.0; //mic_sample_double;
++ tx->samples++;
++ if(tx->samples==tx->buffer_size) {
++ full_tx_buffer(tx);
++ tx->samples=0;
++ }
++
++#ifdef AUDIO_WATERFALL
++ if(audio_samples!=NULL && isTransmitting()) {
++ if(waterfall_samples==0) {
++ audio_samples[audio_samples_index]=(float)mic_sample;
++ audio_samples_index++;
++ if(audio_samples_index>=AUDIO_WATERFALL_SAMPLES) {
++ //Spectrum(CHANNEL_AUDIO,0,0,audio_samples,audio_samples);
++ audio_samples_index=0;
++ }
++ }
++ waterfall_samples++;
++ if(waterfall_samples==waterfall_resample) {
++ waterfall_samples=0;
++ }
++ }
++#endif
++}
++
++#ifdef PURESIGNAL
++void add_ps_iq_samples(TRANSMITTER *tx, double i_sample_tx,double q_sample_tx, double i_sample_rx, double q_sample_rx) {
++ RECEIVER *tx_feedback=receiver[PS_TX_FEEDBACK];
++ RECEIVER *rx_feedback=receiver[PS_RX_FEEDBACK];
++
++//fprintf(stderr,"add_ps_iq_samples: samples=%d i_rx=%f q_rx=%f i_tx=%f q_tx=%f\n",rx_feedback->samples, i_sample_rx,q_sample_rx,i_sample_tx,q_sample_tx);
++
++ tx_feedback->iq_input_buffer[tx_feedback->samples*2]=i_sample_tx;
++ tx_feedback->iq_input_buffer[(tx_feedback->samples*2)+1]=q_sample_tx;
++ rx_feedback->iq_input_buffer[rx_feedback->samples*2]=i_sample_rx;
++ rx_feedback->iq_input_buffer[(rx_feedback->samples*2)+1]=q_sample_rx;
++
++ tx_feedback->samples=tx_feedback->samples+1;
++ rx_feedback->samples=rx_feedback->samples+1;
++
++ if(rx_feedback->samples>=rx_feedback->buffer_size) {
++ if(isTransmitting()) {
++ pscc(transmitter->id, rx_feedback->buffer_size, tx_feedback->iq_input_buffer, rx_feedback->iq_input_buffer);
++ if(transmitter->displaying) {
++ if(transmitter->feedback) {
++ Spectrum0(1, tx_feedback->id, 0, 0, tx_feedback->iq_input_buffer);
++ //} else {
++ // Spectrum0(1, rx_feedback->id, 0, 0, rx_feedback->iq_input_buffer);
++ }
++ }
++ }
++ rx_feedback->samples=0;
++ tx_feedback->samples=0;
++ }
++}
++#endif
++
++#ifdef FREEDV
++void add_freedv_mic_sample(TRANSMITTER *tx, short mic_sample) {
++ int i,s;
++
++ //if(active_receiver->freedv && isTransmitting() && !tune) {
++ if(!tune) {
++ if(tx->freedv_samples==0) {
++ //int modem_samples=mod_sample_freedv(mic_sample);
++ short vs=(short)((double)mic_sample*pow(10.0, mic_gain / 20.0));
++ int modem_samples=mod_sample_freedv(vs);
++ if(modem_samples!=0) {
++ for(s=0;s<modem_samples;s++) {
++ for(i=0;i<freedv_resample;i++) { // 8K to 48K
++ add_mic_sample(tx,mod_out[s]);
++ }
++ }
++ }
++ }
++ tx->freedv_samples++;
++ if(tx->freedv_samples>=freedv_resample) {
++ tx->freedv_samples=0;
++ }
++ }
++}
++#endif
++
++void tx_set_displaying(TRANSMITTER *tx,int state) {
++ tx->displaying=state;
++ if(state) {
++ tx->update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/tx->fps, update_display, (gpointer)tx, NULL);
++<<<<<<< HEAD
++ }
++}
++
++#ifdef PURESIGNAL
++void tx_set_ps(TRANSMITTER *tx,int state) {
++ tx->puresignal=state;
++ if(state) {
++ SetPSControl(tx->id, 0, 0, 1, 0);
++ } else {
++ SetPSControl(tx->id, 1, 0, 0, 0);
++ }
++ vfo_update();
++}
++
++void tx_set_twotone(TRANSMITTER *tx,int state) {
++ transmitter->twotone=state;
++ if(state) {
++ SetTXAPostGenMode(transmitter->id, 1);
++ SetTXAPostGenRun(transmitter->id, 1);
++ } else {
++ SetTXAPostGenRun(transmitter->id, 0);
++=======
++>>>>>>> upstream/master
++ }
++ g_idle_add(ext_mox_update,(gpointer)(long)state);
++}
++
++void tx_set_ps_sample_rate(TRANSMITTER *tx,int rate) {
++ SetPSFeedbackRate (tx->id,rate);
++}
++#endif
++
++void cw_sidetone_mute(int mute){
++ key = mute;
++}
++
++<<<<<<< HEAD
++int asteps = 0;
++double timebase = 0.0;
++#define TIMESTEP (1.0 / 48000)
++#ifndef M_PI
++#define M_PI 3.14159265358979323846
++#endif
++double getNextSideToneSample() {
++ double angle = cw_keyer_sidetone_frequency * 2 * M_PI * timebase;
++ timebase += TIMESTEP;
++ asteps++;
++ if (asteps == 48000) {
++ timebase = 0.0;
++ asteps = 0;
++ }
++ return sin(angle);
++}
++=======
++#ifdef PURESIGNAL
++void tx_set_ps(TRANSMITTER *tx,int state) {
++ tx->puresignal=state;
++ if(state) {
++ SetPSControl(tx->id, 0, 0, 1, 0);
++ } else {
++ SetPSControl(tx->id, 1, 0, 0, 0);
++ }
++ vfo_update();
++}
++
++void tx_set_twotone(TRANSMITTER *tx,int state) {
++ transmitter->twotone=state;
++ if(state) {
++ SetTXAPostGenMode(transmitter->id, 1);
++ SetTXAPostGenRun(transmitter->id, 1);
++ } else {
++ SetTXAPostGenRun(transmitter->id, 0);
++ }
++ g_idle_add(ext_mox_update,(gpointer)(long)state);
++}
++
++void tx_set_ps_sample_rate(TRANSMITTER *tx,int rate) {
++ SetPSFeedbackRate (tx->id,rate);
++}
++#endif
++>>>>>>> upstream/master
--- /dev/null
--- /dev/null
++/* Copyright (C)
++* 2017 - John Melton, G0ORX/N6LYT
++*
++* 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.
++*
++*/
++
++#ifndef _TRANSMITTER_H
++#define _TRANSMITTER_H
++
++#include <gtk/gtk.h>
++
++#define AUDIO_BUFFER_SIZE 260
++
++typedef struct _transmitter {
++ int id;
++ int fps;
++ int displaying;
++ int mic_sample_rate;
++ int mic_dsp_rate;
++ int iq_output_rate;
++ int buffer_size;
++ int fft_size;
++ int pixels;
++ int samples;
++ int output_samples;
++ double *mic_input_buffer;
++ double *iq_output_buffer;
++
++ float *pixel_samples;
++ int display_panadapter;
++ int display_waterfall;
++ gint update_timer_id;
++
++ int mode;
++ int filter_low;
++ int filter_high;
++
++/*
++ long long frequency;
++ long long display_frequency;
++ long long dds_frequency;
++ long long dds_offset;
++*/
++ int alex_antenna;
++
++ int width;
++ int height;
++
++ GtkWidget *panel;
++ GtkWidget *panadapter;
++
++ int panadapter_low;
++ int panadapter_high;
++
++ cairo_surface_t *panadapter_surface;
++
++ int local_microphone;
++ int input_device;
++
++ int out_of_band;
++ gint out_of_band_timer_id;
++
++ int low_latency;
++
++#ifdef PURESIGNAL
++ int puresignal;
++ int twotone;
++ int feedback;
++ int auto_on;
++ int single_on;
++#endif
++
++ double ctcss_frequency;
++ int ctcss;
++
++ int deviation;
++
++ double am_carrier_level;
++
++ int attenuation;
++
++ int drive;
++ int tune_use_drive;
++ int tune_percent;
++
++ int drive_level;
++
++#ifdef FREEDV
++ char freedv_text_data[64];
++ int freedv_text_index;
++ int freedv_samples;
++#endif
++
++ int compressor;
++ double compressor_level;
++
++ double fwd;
++ double exciter;
++ double rev;
++ double alc;
++
++ int x;
++ int y;
++
++} TRANSMITTER;
++
++extern TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps, int width, int height);
++
++void reconfigure_transmitter(TRANSMITTER *tx,int height);
++
++
++extern void tx_set_mode(TRANSMITTER* tx,int m);
++extern void tx_set_filter(TRANSMITTER *tx,int low,int high);
++extern void transmitter_set_deviation(TRANSMITTER *tx);
++extern void transmitter_set_am_carrier_level(TRANSMITTER *tx);
++extern void tx_set_pre_emphasize(TRANSMITTER *tx,int state);
++extern void transmitter_set_ctcss(TRANSMITTER *tx,int run,double frequency);
++
++extern void add_mic_sample(TRANSMITTER *tx,short mic_sample);
++extern void add_freedv_mic_sample(TRANSMITTER *tx,short mic_sample);
++
++extern void transmitter_save_state(TRANSMITTER *tx);
++extern void transmitter_set_out_of_band(TRANSMITTER *tx);
++extern void tx_set_displaying(TRANSMITTER *tx,int state);
++
++extern void tx_set_ps(TRANSMITTER *tx,int state);
++extern void tx_set_twotone(TRANSMITTER *tx,int state);
++
++extern void transmitter_set_compressor_level(TRANSMITTER *tx,double level);
++extern void transmitter_set_compressor(TRANSMITTER *tx,int state);
++
++extern void tx_set_ps_sample_rate(TRANSMITTER *tx,int rate);
++extern void add_ps_iq_samples(TRANSMITTER *tx, double i_sample_0,double q_sample_0, double i_sample_1, double q_sample_1);
++<<<<<<< HEAD
++
++extern void cw_sidetone_mute(int mute);
++=======
++>>>>>>> upstream/master
++#endif
++
++