}
+
#ifdef CLIENT_SERVER
loadProperties("remote.props");
gtk_widget_show_all(discovery_dialog);
fprintf(stderr,"showing device dialog\n");
- // autostart if enabled and only one device
+ // autostart if one device and autostart enabled
g_print("%s: devices=%d autostart=%d\n",__FUNCTION__,devices,autostart);
if(devices==1 && autostart) {
if(start_cb(NULL,NULL,(gpointer)d)) return;
}
}
-
}
display_filled=display_filled==1?0:1;
}
+static void gradient_cb(GtkWidget *widget, gpointer data) {
+ display_gradient=display_gradient==1?0:1;
+}
+
static void frames_per_second_value_changed_cb(GtkWidget *widget, gpointer data) {
updates_per_second=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
active_receiver->fps=updates_per_second;
gtk_grid_attach(GTK_GRID(grid),filled_b,col,row,1,1);
g_signal_connect(filled_b,"toggled",G_CALLBACK(filled_cb),NULL);
+ col++;
+
+ GtkWidget *gradient_b=gtk_check_button_new_with_label("Gradient");
+ //gtk_widget_override_font(filled_b, pango_font_description_from_string("Arial 18"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gradient_b), display_gradient);
+ gtk_widget_show(gradient_b);
+ gtk_grid_attach(GTK_GRID(grid),gradient_b,col,row,1,1);
+ g_signal_connect(gradient_b,"toggled",G_CALLBACK(gradient_cb),NULL);
+
row++;
col=0;
#define LT2208_RANDOM_OFF 0x00
#define LT2208_RANDOM_ON 0x10
+// state machine buffer processing
+enum {
+ SYNC_0=0,
+ SYNC_1,
+ SYNC_2,
+ CONTROL_0,
+ CONTROL_1,
+ CONTROL_2,
+ CONTROL_3,
+ CONTROL_4,
+ LEFT_SAMPLE_HI,
+ LEFT_SAMPLE_MID,
+ LEFT_SAMPLE_LOW,
+ RIGHT_SAMPLE_HI,
+ RIGHT_SAMPLE_MID,
+ RIGHT_SAMPLE_LOW,
+ MIC_SAMPLE_HI,
+ MIC_SAMPLE_LOW,
+ SKIP
+};
+static int state=SYNC_0;
+
//#define DEBUG_PROTO 1
#ifdef DEBUG_PROTO
static int command=1;
-enum {
- SYNC_0=0,
- SYNC_1,
- SYNC_2,
- CONTROL_0,
- CONTROL_1,
- CONTROL_2,
- CONTROL_3,
- CONTROL_4,
- LEFT_SAMPLE_HI,
- LEFT_SAMPLE_MID,
- LEFT_SAMPLE_LOW,
- RIGHT_SAMPLE_HI,
- RIGHT_SAMPLE_MID,
- RIGHT_SAMPLE_LOW,
- MIC_SAMPLE_HI,
- MIC_SAMPLE_LOW,
- SKIP
-};
-static int state=SYNC_0;
-
static GThread *receive_thread_id;
static gpointer receive_thread(gpointer arg);
static void process_ozy_input_buffer(unsigned char *buffer);
static unsigned char usb_output_buffer[EP6_BUFFER_SIZE];
static unsigned char ep6_inbuffer[EP6_BUFFER_SIZE];
static unsigned char usb_buffer_block = 0;
+#define USB_TIMEOUT -7
#endif
+static GMutex dump_mutex;
+
+void dump_buffer(unsigned char *buffer,int length,const char *who) {
+ g_mutex_lock(&dump_mutex);
+ g_print("%s: %s: %d\n",__FUNCTION__,who,length);
+ int i=0;
+ int line=0;
+ while(i<length) {
+ g_print("%02X",buffer[i]);
+ i++;
+ line++;
+ if(line==16) {
+ g_print("\n");
+ line=0;
+ }
+ }
+ if(line!=0) {
+ g_print("\n");
+ }
+ g_print("\n");
+ g_mutex_unlock(&dump_mutex);
+}
+
void old_protocol_stop() {
- metis_start_stop(0);
+#ifdef USBOZY
+ if(device!=DEVICE_OZY) {
+#endif
+ g_print("%s\n",__FUNCTION__);
+ metis_start_stop(0);
+#ifdef USBOZY
+ }
+#endif
}
void old_protocol_run() {
- metis_restart();
+#ifdef USBOZY
+ if(device!=DEVICE_OZY) {
+#endif
+ g_print("%s\n",__FUNCTION__);
+ metis_restart();
+#ifdef USBOZY
+ }
+#endif
}
void old_protocol_set_mic_sample_rate(int rate) {
exit( -1 );
}
g_print( "receive_thread: id=%p\n",receive_thread_id);
- }
+ g_print("old_protocol_init: prime radio\n");
+ for(i=8;i<OZY_BUFFER_SIZE;i++) {
+ output_buffer[i]=0;
+ }
- g_print("old_protocol_init: prime radio\n");
- for(i=8;i<OZY_BUFFER_SIZE;i++) {
- output_buffer[i]=0;
+ metis_restart();
}
- metis_restart();
-
}
#ifdef USBOZY
{
bytes = ozy_read(EP6_IN_ID,ep6_inbuffer,EP6_BUFFER_SIZE); // read a 2K buffer at a time
+ //g_print("%s: read %d bytes\n",__FUNCTION__,bytes);
+ //dump_buffer(ep6_inbuffer,bytes,__FUNCTION__);
+
if (bytes == 0)
{
g_print("old_protocol_ep6_read: ozy_read returned 0 bytes... retrying\n");
memcpy(&data_addr,&radio->info.network.address,radio->info.network.address_length);
data_addr.sin_port=htons(DATA_PORT);
data_socket=tmp;
- g_print("UDP socket established: %d\n", data_socket);
+ g_print("%s: UDP socket established: %d for %s:%d\n",__FUNCTION__,data_socket,inet_ntoa(data_addr.sin_addr),ntohs(data_addr.sin_port));
}
static void open_tcp_socket() {
g_print( "old_protocol: receive_thread\n");
running=1;
+ //metis_restart();
+
length=sizeof(addr);
while(running) {
} else if (data_socket >= 0) {
bytes_read=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length);
if(bytes_read < 0 && errno != EAGAIN) perror("old_protocol recvfrom UDP:");
+ //g_print("%s: bytes_read=%d\n",__FUNCTION__,bytes_read);
} else {
// This could happen in METIS start/stop sequences
usleep(100000);
return ret;
}
+/*
static void process_ozy_input_buffer(unsigned char *buffer) {
int i;
int r;
metis_restart();
}
}
+*/
+
+static int nreceiver;
+static int left_sample;
+static int right_sample;
+static short mic_sample;
+static double left_sample_double;
+static double right_sample_double;
+double left_sample_double_rx;
+double right_sample_double_rx;
+double left_sample_double_tx;
+double right_sample_double_tx;
+double left_sample_double_main;
+double right_sample_double_main;
+double left_sample_double_aux;
+double right_sample_double_aux;
+
+static int nsamples;
+static int iq_samples;
+
+static void process_control_bytes() {
+ int previous_ptt;
+ int previous_dot;
+ int previous_dash;
+
+ // do not set ptt. In PURESIGNAL, this would stop the
+ // receiver sending samples to WDSP abruptly.
+ // Do the RX-TX change only via ext_mox_update.
+ previous_ptt=local_ptt;
+ previous_dot=dot;
+ previous_dash=dash;
+ local_ptt=(control_in[0]&0x01)==0x01;
+ dash=(control_in[0]&0x02)==0x02;
+ dot=(control_in[0]&0x04)==0x04;
+
+ if (cw_keyer_internal) {
+ // Stops CAT cw transmission if paddle hit in "internal" CW
+ if ((dash || dot) && cw_keyer_internal) cw_key_hit=1;
+ } else {
+#ifdef LOCALCW
+ //
+ // report "key hit" event to the local keyer
+ // (local keyer will stop CAT cw if necessary)
+ if (dash != previous_dash) keyer_event(0, dash);
+ if (dot != previous_dot ) keyer_event(1, dot );
+#endif
+ }
+
+ if(previous_ptt!=local_ptt) {
+ g_idle_add(ext_mox_update,(gpointer)(long)(local_ptt));
+ }
+
+ switch((control_in[0]>>3)&0x1F) {
+ case 0:
+ adc_overload=control_in[1]&0x01;
+ if (device != DEVICE_HERMES_LITE2) {
+ //
+ // HL2 uses these bits of the protocol for a different purpose:
+ // C1 unused except the ADC overload bit
+ // C2/C3 contains underflow/overflow and TX FIFO count
+ //
+ IO1=(control_in[1]&0x02)?0:1;
+ IO2=(control_in[1]&0x04)?0:1;
+ IO3=(control_in[1]&0x08)?0:1;
+ if(mercury_software_version!=control_in[2]) {
+ mercury_software_version=control_in[2];
+ g_print(" Mercury Software version: %d (0x%0X)\n",mercury_software_version,mercury_software_version);
+ }
+ if(penelope_software_version!=control_in[3]) {
+ penelope_software_version=control_in[3];
+ g_print(" Penelope Software version: %d (0x%0X)\n",penelope_software_version,penelope_software_version);
+ }
+ }
+ if(ozy_software_version!=control_in[4]) {
+ ozy_software_version=control_in[4];
+ g_print("FPGA firmware version: %d.%d\n",ozy_software_version/10,ozy_software_version%10);
+ }
+ break;
+ case 1:
+ if (device != DEVICE_HERMES_LITE2) {
+ //
+ // HL2 uses C1/C2 for measuring the temperature
+ //
+ exciter_power=((control_in[1]&0xFF)<<8)|(control_in[2]&0xFF); // from Penelope or Hermes
+ temperature=0;
+ } else {
+ exciter_power=0;
+ temperature+=((control_in[1]&0xFF)<<8)|(control_in[2]&0xFF); // HL2
+ n_temperature++;
+ if(n_temperature==10) {
+ average_temperature=temperature/10;
+ temperature=0;
+ n_temperature=0;
+ }
+ }
+ alex_forward_power=((control_in[3]&0xFF)<<8)|(control_in[4]&0xFF); // from Alex or Apollo
+ break;
+ case 2:
+ alex_reverse_power=((control_in[1]&0xFF)<<8)|(control_in[2]&0xFF); // from Alex or Apollo
+ if (device != DEVICE_HERMES_LITE2) {
+ AIN3=((control_in[3]&0xFF)<<8)|(control_in[4]&0xFF); // For Penelope or Hermes
+ current=0;
+ } else {
+ AIN3=0;
+ current+=((control_in[3]&0xFF)<<8)|(control_in[4]&0xFF); // HL2
+ n_current++;
+ if(n_current==10) {
+ average_current=current/10;
+ current=0;
+ n_current=0;
+ }
+ }
+ break;
+ case 3:
+ AIN4=((control_in[1]&0xFF)<<8)|(control_in[2]&0xFF); // For Penelope or Hermes
+ AIN6=((control_in[3]&0xFF)<<8)|(control_in[4]&0xFF); // For Penelope or Hermes
+ break;
+ }
+
+}
+
+static int num_hpsdr_receivers;
+static int rxfdbk;
+static int txfdbk;
+static int rx1channel;
+static int rx2channel;
+
+static void process_ozy_byte(int b) {
+ int i,j;
+ switch(state) {
+ case SYNC_0:
+ if(b==SYNC) {
+ state++;
+ }
+ break;
+ case SYNC_1:
+ if(b==SYNC) {
+ state++;
+ }
+ break;
+ case SYNC_2:
+ if(b==SYNC) {
+ state++;
+ }
+ break;
+ case CONTROL_0:
+ control_in[0]=b;
+ state++;
+ break;
+ case CONTROL_1:
+ control_in[1]=b;
+ state++;
+ break;
+ case CONTROL_2:
+ control_in[2]=b;
+ state++;
+ break;
+ case CONTROL_3:
+ control_in[3]=b;
+ state++;
+ break;
+ case CONTROL_4:
+ control_in[4]=b;
+ process_control_bytes();
+ nreceiver=0;
+ iq_samples=(512-8)/((num_hpsdr_receivers*6)+2);
+ nsamples=0;
+ state++;
+ break;
+ case LEFT_SAMPLE_HI:
+ left_sample=(int)((signed char)b<<16);
+ state++;
+ break;
+ case LEFT_SAMPLE_MID:
+ left_sample|=(int)((((unsigned char)b)<<8)&0xFF00);
+ state++;
+ break;
+ case LEFT_SAMPLE_LOW:
+ left_sample|=(int)((unsigned char)b&0xFF);
+ left_sample_double=(double)left_sample/8388607.0; // 24 bit sample 2^23-1
+ state++;
+ break;
+ case RIGHT_SAMPLE_HI:
+ right_sample=(int)((signed char)b<<16);
+ state++;
+ break;
+ case RIGHT_SAMPLE_MID:
+ right_sample|=(int)((((unsigned char)b)<<8)&0xFF00);
+ state++;
+ break;
+ case RIGHT_SAMPLE_LOW:
+ right_sample|=(int)((unsigned char)b&0xFF);
+ right_sample_double=(double)right_sample/8388607.0; // 24 bit sample 2^23-1
+
+ if (isTransmitting() && transmitter->puresignal) {
+ //
+ // transmitting with PURESIGNAL. Get sample pairs and feed to pscc
+ //
+ if (nreceiver == rxfdbk) {
+ left_sample_double_rx=left_sample_double;
+ right_sample_double_rx=right_sample_double;
+ } else if (nreceiver == txfdbk) {
+ left_sample_double_tx=left_sample_double;
+ right_sample_double_tx=right_sample_double;
+ }
+ // this is pure paranoia, it allows for txfdbk < rxfdbk
+ if (nreceiver+1 == num_hpsdr_receivers) {
+ add_ps_iq_samples(transmitter, left_sample_double_tx,right_sample_double_tx,left_sample_double_rx,right_sample_double_rx);
+ }
+ }
+
+ if (!isTransmitting() && diversity_enabled) {
+ //
+ // receiving with DIVERSITY. Get sample pairs and feed to diversity mixer
+ //
+ if (nreceiver == rx1channel) {
+ left_sample_double_main=left_sample_double;
+ right_sample_double_main=right_sample_double;
+ } else if (nreceiver == rx2channel) {
+ left_sample_double_aux=left_sample_double;
+ right_sample_double_aux=right_sample_double;
+ }
+ // this is pure paranoia, it allows for rx2channel < rx1channel
+ if (nreceiver+1 == num_hpsdr_receivers) {
+ add_div_iq_samples(receiver[0], left_sample_double_main,right_sample_double_main,left_sample_double_aux,right_sample_double_aux);
+ // if we have a second receiver, display "auxiliary" receiver as well
+ if (receivers >1) add_iq_samples(receiver[1], left_sample_double_aux,right_sample_double_aux);
+ }
+ }
+
+ if ((!isTransmitting() || duplex) && !diversity_enabled) {
+ //
+ // RX without DIVERSITY. Feed samples to RX1 and RX2
+ //
+ if (nreceiver == rx1channel) {
+ add_iq_samples(receiver[0], left_sample_double,right_sample_double);
+ } else if (nreceiver == rx2channel && receivers > 1) {
+ add_iq_samples(receiver[1], left_sample_double,right_sample_double);
+ }
+ }
+ nreceiver++;
+ if(nreceiver==num_hpsdr_receivers) {
+ state++;
+ } else {
+ state=LEFT_SAMPLE_HI;
+ }
+ break;
+ case MIC_SAMPLE_HI:
+ mic_sample=(short)(b<<8);
+ state++;
+ break;
+ case MIC_SAMPLE_LOW:
+ mic_sample|=(short)(b&0xFF);
+ if(!transmitter->local_microphone) {
+ mic_samples++;
+ if(mic_samples>=mic_sample_divisor) { // reduce to 48000
+ add_mic_sample(transmitter,(float)mic_sample/32768.0);
+ mic_samples=0;
+ }
+ }
+ nsamples++;
+ if(nsamples==iq_samples) {
+ state=SYNC_0;
+ } else {
+ nreceiver=0;
+ state=LEFT_SAMPLE_HI;
+ }
+ break;
+ }
+}
+
+static void process_ozy_input_buffer(unsigned char *buffer) {
+ int i;
+ num_hpsdr_receivers=how_many_receivers();
+ rxfdbk = rx_feedback_channel();
+ txfdbk = tx_feedback_channel();
+ rx1channel = first_receiver_channel();
+ rx2channel = second_receiver_channel();
+ for(i=0;i<512;i++) {
+ process_ozy_byte(buffer[i]&0xFF);
+ }
+}
void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample) {
if(!isTransmitting()) {
void ozy_send_buffer() {
+
int txmode=get_tx_mode();
int txvfo=get_tx_vfo();
int i;
if(metis_offset==8) {
//
// Every second packet is a "C0=0" packet
+ // Unless USB device
//
output_buffer[C0]=0x00;
output_buffer[C1]=0x00;
if (device == DEVICE_METIS)
#endif
{
- if (atlas_mic_source)
+ // atlas_mic_source is FALSE when using Janus
+
+ if (atlas_mic_source) {
output_buffer[C1] |= PENELOPE_MIC;
- output_buffer[C1] |= CONFIG_BOTH;
+ output_buffer[C1] |= CONFIG_BOTH;
+ }
+
if (atlas_clock_source_128mhz)
output_buffer[C1] |= MERCURY_122_88MHZ_SOURCE;
output_buffer[C1] |= ((atlas_clock_source_10mhz & 3) << 2);
+ }
+
+#ifdef USBOZY
+ // check for Janus
+ if (device == DEVICE_OZY && !atlas_mic_source) {
+ output_buffer[C2]=0x00;
+ output_buffer[C3]=0x00;
+ output_buffer[C4]=0x00;
+ ozyusb_write(output_buffer,OZY_BUFFER_SIZE);
+ return;
}
+#endif
output_buffer[C2]=0x00;
if(classE) {
static void ozyusb_write(unsigned char* buffer,int length)
{
int i;
+ i = ozy_write(EP2_OUT_ID,buffer,length);
+ if(i!=length) {
+ if(i==USB_TIMEOUT) {
+ g_print("%s: ozy_write timeout for %d bytes\n",__FUNCTION__,length);
+ } else {
+ g_print("%s: ozy_write for %d bytes returned %d\n",__FUNCTION__,length,i);
+ }
+ }
+
+/*
// batch up 4 USB frames (2048 bytes) then do a USB write
switch(usb_buffer_block++)
case 3:
memcpy(usb_output_buffer + 1024 + 512, buffer, length);
- usb_buffer_block = 0; // reset counter
// and write the 4 usb frames to the usb in one 2k packet
i = ozy_write(EP2_OUT_ID,usb_output_buffer,EP6_BUFFER_SIZE);
+
+ //dump_buffer(usb_output_buffer,EP6_BUFFER_SIZE,__FUNCTION__);
+
+ //g_print("%s: written %d\n",__FUNCTION__,i);
+ //dump_buffer(usb_output_buffer,EP6_BUFFER_SIZE);
+
if(i != EP6_BUFFER_SIZE)
{
- perror("old_protocol: OzyWrite ozy failed");
+ if(i==USB_TIMEOUT) {
+ while(i==USB_TIMEOUT) {
+ g_print("%s: USB_TIMEOUT: ozy_write ...\n",__FUNCTION__);
+ i = ozy_write(EP2_OUT_ID,usb_output_buffer,EP6_BUFFER_SIZE);
+ }
+ g_print("%s: ozy_write TIMEOUT\n",__FUNCTION__);
+ } else {
+ perror("old_protocol: OzyWrite ozy failed");
+ }
}
+
+ usb_buffer_block = 0; // reset counter
break;
}
+*/
}
#endif
usleep(250000);
// start the data flowing
- metis_start_stop(1);
+#ifdef USBOZY
+ if(device!=DEVICE_OZY) {
+#endif
+ metis_start_stop(1);
+#ifdef USBOZY
+ }
+#endif
}
static void metis_start_stop(int command) {
}
static void metis_send_buffer(unsigned char* buffer,int length) {
+ int bytes_sent;
//
// Send using either the UDP or TCP socket. Do not use TCP for
// packets that are not 1032 bytes long
//
+ //g_print("%s: length=%d\n",__FUNCTION__,length);
+
if (tcp_socket >= 0) {
if (length != 1032) {
g_print("PROGRAMMING ERROR: TCP LENGTH != 1032\n");
perror("sendto socket failed for TCP metis_send_data\n");
}
} else if (data_socket >= 0) {
- if(sendto(data_socket,buffer,length,0,(struct sockaddr*)&data_addr,sizeof(data_addr))!=length) {
- perror("sendto socket failed for UDP metis_send_data\n");
+//g_print("%s: sendto %d for %s:%d length=%d\n",__FUNCTION__,data_socket,inet_ntoa(data_addr.sin_addr),ntohs(data_addr.sin_port),length);
+ bytes_sent=sendto(data_socket,buffer,length,0,(struct sockaddr*)&data_addr,sizeof(data_addr));
+ if(bytes_sent!=length) {
+ g_print("%s: UDP sendto failed: %d: %s\n",__FUNCTION__,errno,strerror(errno));
+ //perror("sendto socket failed for UDP metis_send_data\n");
}
} else {
// This should not happen
* modified further Laurence Barker G8NJJ to add USB functionality to pihpsdr
*/
+#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> // tolower
#define OZY_BUFFER_SIZE 512
+#define OZY_IO_TIMEOUT 10
//#define OZY_IO_TIMEOUT 500
-#define OZY_IO_TIMEOUT 2000
+//#define OZY_IO_TIMEOUT 2000
#define MAX_EPO_PACKET_SIZE 64
static int init=0;
int rc;
int bytes;
+ bytes=0;
rc = libusb_bulk_transfer(ozy_handle,(unsigned char)ep,buffer,buffer_size,&bytes,OZY_IO_TIMEOUT);
if(rc==0) {
rc=bytes;
+ } else if(rc==-7) {
+ g_print("%s: timeout bytes=%d ep=%d\n",__FUNCTION__,bytes,ep);
+ libusb_clear_halt(ozy_handle,(unsigned char)ep);
}
-
+ rc=buffer_size;
return rc;
}
ozy_get_firmware_string(ozy_firmware_version,8);
fprintf(stderr,"Ozy FX2 version: %s\n",ozy_firmware_version);
- ozy_i2c_readvars();
+ //ozy_i2c_readvars();
ozy_close();
sleep(1);
ozy_open();
int atlas_clock_source_128mhz=0;
int atlas_config=0;
int atlas_mic_source=0;
+int atlas_janus=0;
int classE=0;
int panadapter_low=-140;
int display_filled=1;
+int display_gradient=0;
int display_detector_mode=DETECTOR_MODE_AVERAGE;
int display_average_mode=AVERAGE_MODE_LOG_RECURSIVE;
double display_average_time=120.0;
value=getProperty("display_filled");
if(value) display_filled=atoi(value);
+ value=getProperty("display_gradient");
+ if(value) display_gradient=atoi(value);
value=getProperty("display_zoompan");
if(value) display_zoompan=atoi(value);
value=getProperty("display_sliders");
sprintf(value,"%d",display_filled);
setProperty("display_filled",value);
+ sprintf(value,"%d",display_gradient);
+ setProperty("display_gradient",value);
sprintf(value,"%d",display_zoompan);
setProperty("display_zoompan",value);
sprintf(value,"%d",display_sliders);
extern int atlas_clock_source_128mhz;
extern int atlas_config;
extern int atlas_mic_source;
+extern int atlas_janus;
extern int classE;
extern int panadapter_low;
extern int display_filled;
+extern int display_gradient;
extern int display_detector_mode;
extern int display_average_mode;
extern double display_average_time;
atlas_penelope=atlas_penelope==1?0:1;
}
+static void janus_cb(GtkWidget *widget, gpointer data) {
+ atlas_janus=atlas_janus==1?0:1;
+}
+
void radio_menu(GtkWidget *parent) {
parent_window=parent;
g_signal_connect(pene_tx_b,"toggled",G_CALLBACK(penelopetx_cb),NULL);
row++;
+ GtkWidget *janus_b=gtk_check_button_new_with_label("Janus");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (janus_b), atlas_janus);
+ gtk_grid_attach(GTK_GRID(grid),janus_b,col,row,1,1);
+ g_signal_connect(janus_b,"toggled",G_CALLBACK(janus_cb),NULL);
+ row++;
+
if(row>temp_row) temp_row=row;
}
#include "client_server.h"
#endif
+#define LINE_WIDTH 0.5
+
//static float panadapter_max=-60.0;
//static float panadapter_min=-160.0;
//clear_panadater_surface();
cairo_t *cr;
cr = cairo_create (rx->panadapter_surface);
- cairo_set_line_width(cr, 1.0);
+ cairo_set_line_width(cr, LINE_WIDTH);
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
cairo_rectangle(cr,0,0,display_width,display_height);
cairo_fill(cr);
}
double dbm_per_line=(double)display_height/((double)rx->panadapter_high-(double)rx->panadapter_low);
- cairo_set_line_width(cr, 1.0);
+ cairo_set_line_width(cr, LINE_WIDTH);
cairo_select_font_face(cr, "FreeMono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 12);
char v[32];
// band edges
if(band->frequencyMin!=0LL) {
cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
- cairo_set_line_width(cr, 1.0);
+ cairo_set_line_width(cr, LINE_WIDTH);
if((min_display<band->frequencyMin)&&(max_display>band->frequencyMin)) {
i=(band->frequencyMin-min_display)/(long long)HzPerPixel;
cairo_move_to(cr,(double)i,0.0);
} else {
cairo_set_source_rgb (cr, 0.5, 0.0, 0.0);
}
- cairo_set_line_width(cr, 1.0);
+ cairo_set_line_width(cr, LINE_WIDTH);
cairo_move_to(cr,vfofreq+(offset/HzPerPixel),0.0);
cairo_line_to(cr,vfofreq+(offset/HzPerPixel),(double)display_height);
cairo_stroke(cr);
cairo_line_to(cr, (double)i, s2);
}
- if(display_filled) {
- cairo_close_path (cr);
+ cairo_pattern_t *gradient;
+ if(display_gradient) {
+ gradient = cairo_pattern_create_linear(0.0, display_height, 0.0, 0.0);
+ // calculate where S9 is
+ double S9=-73;
+ if(vfo[rx->id].frequency>30000000LL) {
+ S9=-93;
+ }
+ S9 = floor((rx->panadapter_high - S9)
+ * (double) display_height
+ / (rx->panadapter_high - rx->panadapter_low));
+ S9 = 1.0-(S9/(double)display_height);
+
+ if(active) {
+ cairo_pattern_add_color_stop_rgb (gradient,0.0,0.0,1.0,0.0); // Green
+ cairo_pattern_add_color_stop_rgb (gradient,S9/3.0,1.0,0.65,0.0); // Orange
+ cairo_pattern_add_color_stop_rgb (gradient,(S9/3.0)*2.0,1.0,1.0,0.0); // Yellow
+ cairo_pattern_add_color_stop_rgb (gradient,S9,1.0,0.0,0.0); // Red
+ } else {
+ cairo_pattern_add_color_stop_rgb (gradient,0.0,0.0,0.5,0.0); // Green
+ cairo_pattern_add_color_stop_rgb (gradient,S9/3.0,0.5,0.325,0.0); // Orange
+ cairo_pattern_add_color_stop_rgb (gradient,(S9/3.0)*2.0,0.5,0.5,0.0); // Yellow
+ cairo_pattern_add_color_stop_rgb (gradient,S9,0.5,0.0,0.0); // Red
+ }
+ cairo_set_source(cr, gradient);
+ } else {
if(active) {
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0,0.5);
} else {
cairo_set_source_rgba(cr, 0.5, 0.5, 0.5,0.5);
}
- cairo_fill_preserve (cr);
}
- if(active) {
- cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
- } else {
- cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
+
+ if(display_filled) {
+ cairo_close_path (cr);
+ cairo_fill_preserve (cr);
}
- cairo_set_line_width(cr, 1.0);
+ cairo_set_line_width(cr, LINE_WIDTH);
cairo_stroke(cr);
+ if(display_gradient) {
+ cairo_pattern_destroy(gradient);
+ }
+
#ifdef GPIO
if(rx->id==0 && controller==CONTROLLER1) {
}
static void zoom_value_changed_cb(GtkWidget *widget, gpointer data) {
+g_print("zoom_value_changed_cb\n");
g_mutex_lock(&pan_zoom_mutex);
g_mutex_lock(&active_receiver->display_mutex);
#ifdef CLIENT_SERVER
}
void set_zoom(int rx,double value) {
+g_print("set_zoom: %f\n",value);
receiver[rx]->zoom=value;
- receiver_change_zoom(receiver[rx],value);
if(display_zoompan) {
- g_signal_handler_block(G_OBJECT(zoom_scale),zoom_signal_id);
gtk_range_set_value (GTK_RANGE(zoom_scale),receiver[rx]->zoom);
- g_signal_handler_unblock(G_OBJECT(zoom_scale),zoom_signal_id);
- g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
- gtk_range_set_range(GTK_RANGE(pan_scale),0.0,(double)(active_receiver->zoom==1?active_receiver->pixels:active_receiver->pixels-active_receiver->width));
- gtk_range_set_value (GTK_RANGE(pan_scale),active_receiver->pan);
- g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
- if(active_receiver->zoom==1) {
- gtk_widget_set_sensitive(pan_scale, FALSE);
- } else {
- gtk_widget_set_sensitive(pan_scale, TRUE);
- }
} else {
if(scale_status!=ZOOM || scale_rx!=rx) {
if(scale_status!=NO_FUNCTION) {
}
void remote_set_zoom(int rx,double value) {
+g_print("remote_set_zoom: rx=%d zoom=%f\n",rx,value);
g_mutex_lock(&pan_zoom_mutex);
g_signal_handler_block(G_OBJECT(zoom_scale),zoom_signal_id);
g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
g_signal_handler_unblock(G_OBJECT(zoom_scale),zoom_signal_id);
g_mutex_unlock(&pan_zoom_mutex);
+g_print("remote_set_zoom: EXIT\n");
}
void update_zoom(double zoom) {
+g_print("update_zoom: %f\n",zoom);
int z=active_receiver->zoom+(int)zoom;
if(z>MAX_ZOOM) z=MAX_ZOOM;
if(z<1) z=1;
}
static void pan_value_changed_cb(GtkWidget *widget, gpointer data) {
+g_print("pan_value_changed_cb\n");
g_mutex_lock(&pan_zoom_mutex);
#ifdef CLIENT_SERVER
if(radio_is_remote) {
}
void set_pan(int rx,double value) {
+g_print("set_pan: %f\n",value);
receiver[rx]->pan=(int)value;
if(display_zoompan) {
- g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
gtk_range_set_value (GTK_RANGE(pan_scale),receiver[rx]->pan);
- g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
} else {
if(scale_status!=PAN || scale_rx!=rx) {
if(scale_status!=NO_FUNCTION) {
}
void remote_set_pan(int rx,double value) {
+g_print("remote_set_pan: rx=%d pan=%f\n",rx,value);
g_mutex_lock(&pan_zoom_mutex);
g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
gtk_range_set_range(GTK_RANGE(pan_scale),0.0,(double)(receiver[rx]->zoom==1?receiver[rx]->pixels:receiver[rx]->pixels-receiver[rx]->width));
set_pan(rx,value);
g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
g_mutex_unlock(&pan_zoom_mutex);
+g_print("remote_set_pan: EXIT\n");
}
void update_pan(double pan) {
+ g_mutex_lock(&pan_zoom_mutex);
if(active_receiver->zoom>1) {
int p=active_receiver->pan+(int)pan;
if(p<0) p=0;
if(p>(active_receiver->pixels-active_receiver->width)) p=active_receiver->pixels-active_receiver->width;
set_pan(active_receiver->id,(double)p);
}
+ g_mutex_lock(&pan_zoom_mutex);
}
GtkWidget *zoompan_init(int my_width, int my_height) {
width=my_width;
height=my_height;
-g_print("%s: width=%d height=%d\n",__FUNCTION__,width,height);
+fprintf(stderr,"zoompan_init: width=%d height=%d\n", width,height);
zoompan=gtk_grid_new();
gtk_widget_set_size_request (zoompan, width, height);