]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
merge
authorpa3gsb <pa3gsb@gmail.com>
Sun, 25 Feb 2018 13:56:58 +0000 (14:56 +0100)
committerpa3gsb <pa3gsb@gmail.com>
Sun, 25 Feb 2018 13:56:58 +0000 (14:56 +0100)
1  2 
Makefile
Makefile.orig
audio.c
gpio.c
gpio.c.orig
radio.c.orig
radioberry.c
radioberry.c.orig
transmitter.c.orig
transmitter.h.orig

diff --cc Makefile
index b069e86c1145a8f322835cf6c4bf128af151d2d8,d0b4fcd01f1ab00908aaf1cef59904eb82ce604d..f4aa416d7a1a7cf4a7209c13be2479fba83e19d3
+++ b/Makefile
@@@ -30,6 -30,6 +30,13 @@@ LOCALCW_INCLUDE=LOCALC
  # 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
  
@@@ -138,16 -137,19 +145,18 @@@ endi
  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
diff --cc Makefile.orig
index ff0926db2ed98afcd3e5bff4566af7168dfd9e33,ff0926db2ed98afcd3e5bff4566af7168dfd9e33..a43e6b9b8dea281c9e9ee6720942a69ecc264f4c
@@@ -6,30 -6,30 +6,32 @@@ GIT_VERSION := $(shell git describe --a
  # 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
@@@ -56,6 -56,6 +81,7 @@@ RADIOBERRY_INCLUDE=RADIOBERR
  
  ifeq ($(RADIOBERRY_INCLUDE),RADIOBERRY)
  RADIOBERRY_OPTIONS=-D RADIOBERRY
++RADIOBERRYLIBS=-lpigpio
  RADIOBERRY_SOURCES= \
  radioberry_discovery.c \
  radioberry.c
@@@ -115,31 -115,31 +141,19 @@@ endi
  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 \
@@@ -159,8 -159,8 +173,15 @@@ ifeq ($(I2C_INCLUDE),I2C
    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 \
@@@ -191,6 -191,6 +216,7 @@@ discovery.c 
  filter.c \
  main.c \
  new_menu.c \
++about_menu.c \
  exit_menu.c \
  radio_menu.c \
  rx_menu.c \
@@@ -211,6 -211,6 +237,7 @@@ filter_menu.c 
  noise_menu.c \
  agc_menu.c \
  vox_menu.c \
++fft_menu.c \
  diversity_menu.c \
  freqent_menu.c \
  tx_menu.c \
@@@ -229,6 -229,6 +256,7 @@@ property.c 
  radio.c \
  receiver.c \
  rigctl.c \
++rigctl_menu.c \
  toolbar.c \
  transmitter.c \
  sliders.c \
@@@ -240,11 -240,11 +268,15 @@@ vox.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 \
@@@ -256,6 -256,6 +288,7 @@@ discovered.h 
  discovery.h \
  filter.h \
  new_menu.h \
++about_menu.h \
  rx_menu.h \
  exit_menu.h \
  radio_menu.h \
@@@ -276,6 -276,6 +309,7 @@@ filter_menu.h 
  noise_menu.h \
  agc_menu.h \
  vox_menu.h \
++fft_menu.h \
  diversity_menu.h \
  freqent_menu.h \
  tx_menu.h \
@@@ -293,6 -293,6 +327,7 @@@ property.h 
  radio.h \
  receiver.h \
  rigctl.h \
++rigctl_menu.h \
  toolbar.h \
  transmitter.h \
  sliders.h \
@@@ -304,11 -304,11 +339,15 @@@ vox.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 \
@@@ -318,6 -318,6 +357,7 @@@ filter.o 
  version.o \
  main.o \
  new_menu.o \
++about_menu.o \
  rx_menu.o \
  exit_menu.o \
  radio_menu.o \
@@@ -338,6 -338,6 +378,7 @@@ filter_menu.o 
  noise_menu.o \
  agc_menu.o \
  vox_menu.o \
++fft_menu.o \
  diversity_menu.o \
  freqent_menu.o \
  tx_menu.o \
@@@ -356,6 -356,6 +397,7 @@@ property.o 
  radio.o \
  receiver.o \
  rigctl.o \
++rigctl_menu.o \
  toolbar.o \
  transmitter.o \
  sliders.o \
@@@ -366,37 -366,37 +408,28 @@@ vox.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
  
diff --cc audio.c
index 4924159de054595090f06b655b9232def42fb3df,b689bd7c8f00bca32807b9f87414e164a6c4cb23..cb668d5ce9e1270db714f731cae6731533c126c1
+++ b/audio.c
@@@ -159,9 -164,8 +167,10 @@@ fprintf(stderr,"audio_open_output: hand
  
    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;
  }
        
diff --cc gpio.c
index d573739c10856b28f9fc59c2caab61dfd577fe80,183bd742ec5f78e1e2db6e050c7033eed67e4e55..2d51accd74fae0b9e271a1c66d6be7161189bd2c
--- 1/gpio.c
--- 2/gpio.c
+++ b/gpio.c
@@@ -66,7 -62,7 +62,9 @@@
  
  int settle_time=DEFAULT_SETTLE_TIME;
  static gint release_timer=-1;
--
++#ifdef RADIOBERRY
++#include <pigpio.h>
++#endif
  
  #ifdef CONTROLLER2
  
@@@ -839,15 -832,6 +837,7 @@@ void gpio_restore_state() 
    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() {
@@@ -970,56 -944,6 +950,55 @@@ fprintf(stderr,"setup_encoder_pin: pin=
      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;
  
diff --cc gpio.c.orig
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..72ecd238208fd87d2bb0fcde7c6554b199d09508
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1570 @@@
++/* 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;
++}
diff --cc radio.c.orig
index f9127079a099de997232c9e31487f194b74d192f,f9127079a099de997232c9e31487f194b74d192f..d7b94edc08e75eab4f31c9a75781904d657db4c4
@@@ -1,4 -1,4 +1,4 @@@
--/* Copyright (C)
++/* Copyrieht (C)
  * 2015 - John Melton, G0ORX/N6LYT
  *
  * This program is free software; you can redistribute it and/or
@@@ -23,6 -23,6 +23,9 @@@
  #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;
@@@ -90,17 -90,17 +104,24 @@@ static GtkWidget *waterfall
  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;
@@@ -110,7 -110,7 +131,7 @@@ RECEIVER *active_receiver
  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;
@@@ -123,10 -123,10 +144,10 @@@ int classE=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;
@@@ -145,7 -145,7 +166,6 @@@ double display_average_time=120.0
  
  int waterfall_high=-100;
  int waterfall_low=-150;
--int waterfall_automatic=1;
  
  int display_sliders=1;
  
@@@ -160,11 -160,11 +180,11 @@@ int mic_bias_enabled=0
  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;
  
@@@ -237,8 -237,8 +257,8 @@@ int OCfull_tune_time=2800; // m
  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;
@@@ -249,10 -249,10 +269,7 @@@ int eer_pwm_max=800
  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;
  
@@@ -262,7 -262,7 +279,6 @@@ int tx_equalizer[4]={0,0,0,0}
  int enable_rx_equalizer=0;
  int rx_equalizer[4]={0,0,0,0};
  
--int deviation=2500;
  int pre_emphasize=0;
  
  int vox_setting=0;
@@@ -276,9 -276,9 +292,13 @@@ int diversity_enabled=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); 
@@@ -331,7 -331,7 +351,7 @@@ void start_radio() 
    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) {
@@@ -620,8 -620,8 +793,14 @@@ void setVox(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);
    }
  }
  
@@@ -723,8 -723,8 +889,31 @@@ int getTune() 
    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
    }
@@@ -797,7 -797,7 +980,7 @@@ long long getFrequency() 
  }
  
  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;
@@@ -905,6 -905,6 +1085,8 @@@ fprintf(stderr,"radioRestoreState: %s\n
      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);
  }
@@@ -1103,6 -1103,6 +1287,8 @@@ void radioSaveState() 
      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);
  }
@@@ -1307,3 -1307,3 +1480,62 @@@ void calculate_display_average(RECEIVE
    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;
++  }
++}
diff --cc radioberry.c
index 5c832c54d1252ab71faea116e09438015df8c820,712e7243ef11a9e860a9a429cd84a0f94cf7f684..9033d2de841677d5cb0657ee72af817108ffd2a4
@@@ -431,4 -332,5 +431,4 @@@ void spiWriter() 
                printf("Code tx mode spi executed in %f milliseconds.\n", elapsd);
                gettimeofday(&t20, 0);
        }
- }
+ }
 -
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..112c171f6cb3b3133e165415cf07a2a58c0ce6e6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,383 @@@
++/* 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);
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1adc8d698aa422e7e5a64fcac113376648e16b63
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1013 @@@
++/* 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
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..fa7ee57ce2267d9ea8df97583b21e77ed1832167
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,154 @@@
++/* 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
++
++