From c74c411d0ddba12e38e23932ea5154f2c6b0d06f Mon Sep 17 00:00:00 2001 From: Ramakrishnan Muthukrishnan Date: Mon, 9 Dec 2024 22:48:30 +0530 Subject: [PATCH] indent, cleanup --- Makefile | 2 +- discovered.c | 1 - discovery.c | 6 +- discovery.h | 2 +- ext.c | 5 - ext.h | 1 - main.c | 325 +++--- old_protocol.c | 3027 ++++++++++++++++++++++-------------------------- p2_discovery.c | 6 +- 9 files changed, 1580 insertions(+), 1795 deletions(-) diff --git a/Makefile b/Makefile index c985847..14de916 100644 --- a/Makefile +++ b/Makefile @@ -190,7 +190,7 @@ COMPILE=$(CC) $(CFLAGS) $(OPTIONS) $(INCLUDES) PROGRAM=pihpsdr -SRC = $(filter-out hpsdrsim.c mac_midi.c midi2.c midi3.c midi_menu.c ps_menu.c server_menu.c soundio.c ozyio.c newhpsdrsim.c beep.c alsa_midi.c iambic.c pulseaudio.c frequency.c audio.c client_server.c freqent_menu.c general_menu.c gpio_mraa.c hpsdr_discovery.c, $(wildcard *.c)) +SRC = $(filter-out p1_discovery.c p2_discovery.c hpsdrsim.c mac_midi.c midi2.c midi3.c midi_menu.c ps_menu.c server_menu.c soundio.c ozyio.c newhpsdrsim.c beep.c alsa_midi.c iambic.c pulseaudio.c frequency.c audio.c client_server.c freqent_menu.c general_menu.c gpio_mraa.c hpsdr_discovery.c, $(wildcard *.c)) HEADERS = $(wildcard *.h) OBJS = $(SRC:.c=.o) diff --git a/discovered.c b/discovered.c index 15e8248..2b1ba42 100644 --- a/discovered.c +++ b/discovered.c @@ -21,6 +21,5 @@ #include "discovered.h" int selected_device=0; -int devices=0; DISCOVERED discovered[MAX_DEVICES]; diff --git a/discovery.c b/discovery.c index 6595458..a22c856 100644 --- a/discovery.c +++ b/discovery.c @@ -61,12 +61,12 @@ GtkWidget *tcpaddr; static char ipaddr_tcp_buf[IPADDR_LEN] = "10.10.10.10"; char *ipaddr_tcp = &ipaddr_tcp_buf[0]; -void discovery(void) { +int discovery(void) { //fprintf(stderr,"discovery\n"); protocols_restore_state(); selected_device=0; - devices=0; + int devices=0; // Try to locate IP addr FILE *fp = fopen("ip.addr","r"); @@ -109,5 +109,7 @@ void discovery(void) { start_radio(d); } } + + return devices; } diff --git a/discovery.h b/discovery.h index 06394db..41c79ad 100644 --- a/discovery.h +++ b/discovery.h @@ -17,5 +17,5 @@ * */ -extern void discovery(); +extern int discovery(); extern char *ipaddr_tcp; diff --git a/ext.c b/ext.c index 58fc2a9..59b68c1 100644 --- a/ext.c +++ b/ext.c @@ -103,11 +103,6 @@ int ext_vfo_mode_changed(void * data) return 0; } -int ext_discovery(void *data) { - discovery(); - return 0; -} - void local_set_frequency(int v,long long f) { int b=get_band_from_frequency(f); if(active_receiver->id==v) { diff --git a/ext.h b/ext.h index 647f1fc..c4d9aa6 100644 --- a/ext.h +++ b/ext.h @@ -35,7 +35,6 @@ extern int ext_menu_filter(void *data); extern int ext_menu_mode(void *data); extern int ext_num_pad(void *data); extern void local_set_frequency(int v,long long f); -extern int ext_discovery(void *data); extern int ext_vfo_update(void *data); extern int ext_set_frequency(void *data); extern int ext_vfo_filter_changed(void *data); diff --git a/main.c b/main.c index efe2c8d..8ea91a6 100644 --- a/main.c +++ b/main.c @@ -81,9 +81,9 @@ static pthread_t wisdom_thread_id; static int wisdom_running = 0; static void *wisdom_thread(void *arg) { - WDSPwisdom((char *)arg); - wisdom_running = 0; - return NULL; + WDSPwisdom((char *)arg); + wisdom_running = 0; + return NULL; } // @@ -94,192 +94,193 @@ static void *wisdom_thread(void *arg) { // bool keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) { - if (radio != NULL) { - if (event->keyval == GDK_KEY_space) { - - if (getTune() == 1) { - setTune(0); - } - if (getMox() == 1) { - setMox(0); - } else if (canTransmit() || tx_out_of_band) { - setMox(1); - } else { - transmitter_set_out_of_band(transmitter); - } - g_idle_add(ext_vfo_update, NULL); - return TRUE; + if (radio != NULL) { + if (event->keyval == GDK_KEY_space) { + + if (getTune() == 1) { + setTune(0); + } + if (getMox() == 1) { + setMox(0); + } else if (canTransmit() || tx_out_of_band) { + setMox(1); + } else { + transmitter_set_out_of_band(transmitter); + } + g_idle_add(ext_vfo_update, NULL); + return TRUE; + } + if (event->keyval == GDK_KEY_d) { + vfo_move(step, TRUE); + return TRUE; + } + if (event->keyval == GDK_KEY_u) { + vfo_move(-step, TRUE); + return TRUE; + } } - if (event->keyval == GDK_KEY_d) { - vfo_move(step, TRUE); - return TRUE; - } - if (event->keyval == GDK_KEY_u) { - vfo_move(-step, TRUE); - return TRUE; - } - } - return FALSE; + return FALSE; } gboolean main_delete(GtkWidget *widget) { - if (radio != NULL) { + if (radio != NULL) { #ifdef GPIO - gpio_close(); + gpio_close(); #endif #ifdef CLIENT_SERVER - if (!radio_is_remote) { + if (!radio_is_remote) { #endif - switch (protocol) { - case ORIGINAL_PROTOCOL: - old_protocol_stop(); - break; - case NEW_PROTOCOL: - new_protocol_stop(); - break; - } + switch (protocol) { + case ORIGINAL_PROTOCOL: + old_protocol_stop(); + break; + case NEW_PROTOCOL: + new_protocol_stop(); + break; + } #ifdef CLIENT_SERVER - } + } #endif - radioSaveState(); - } - _exit(0); + radioSaveState(); + } + _exit(0); } static int init(void *data) { - char wisdom_directory[1024]; - - audio_get_cards(); - - // wait for get_cards to complete - // g_mutex_lock(&audio_mutex); - // g_mutex_unlock(&audio_mutex); - - cursor_arrow = gdk_cursor_new(GDK_ARROW); - cursor_watch = gdk_cursor_new(GDK_WATCH); - - gdk_window_set_cursor(gtk_widget_get_window(top_window), cursor_watch); - - // - // Let WDSP (via FFTW) check for wisdom file in current dir - // If there is one, the "wisdom thread" takes no time - // Depending on the WDSP version, the file is wdspWisdom or wdspWisdom00. - // sem_trywait() is not elegant, replaced this with wisdom_running variable. - // - char *c = getcwd(wisdom_directory, sizeof(wisdom_directory)); - if (c == NULL) { - perror("getcwd"); - } - strcpy(&wisdom_directory[strlen(wisdom_directory)], "/"); - g_info("Securing wisdom file in directory: %s\n", wisdom_directory); - log_info("Checking FFTW Wisdom file ..."); - wisdom_running = 1; - pthread_create(&wisdom_thread_id, NULL, wisdom_thread, wisdom_directory); - while (wisdom_running) { - // wait for the wisdom thread to complete, meanwhile - // handling any GTK events. - usleep(100000); // 100ms - while (gtk_events_pending()) { - gtk_main_iteration(); + char wisdom_directory[1024]; + + audio_get_cards(); + + // wait for get_cards to complete + // g_mutex_lock(&audio_mutex); + // g_mutex_unlock(&audio_mutex); + + cursor_arrow = gdk_cursor_new(GDK_ARROW); + cursor_watch = gdk_cursor_new(GDK_WATCH); + + gdk_window_set_cursor(gtk_widget_get_window(top_window), cursor_watch); + + // + // Let WDSP (via FFTW) check for wisdom file in current dir + // If there is one, the "wisdom thread" takes no time + // Depending on the WDSP version, the file is wdspWisdom or wdspWisdom00. + // sem_trywait() is not elegant, replaced this with wisdom_running variable. + // + char *c = getcwd(wisdom_directory, sizeof(wisdom_directory)); + if (c == NULL) { + perror("getcwd"); + } + strcpy(&wisdom_directory[strlen(wisdom_directory)], "/"); + g_info("Securing wisdom file in directory: %s\n", wisdom_directory); + log_info("Checking FFTW Wisdom file ..."); + wisdom_running = 1; + pthread_create(&wisdom_thread_id, NULL, wisdom_thread, wisdom_directory); + while (wisdom_running) { + // wait for the wisdom thread to complete, meanwhile + // handling any GTK events. + usleep(100000); // 100ms + while (gtk_events_pending()) { + gtk_main_iteration(); + } + log_info(wisdom_get_status()); } - log_info(wisdom_get_status()); - } - g_idle_add(ext_discovery, NULL); - return 0; + discovery(); + + return 0; } static void activate_pihpsdr(GtkApplication *app, gpointer data) { - load_css(); + load_css(); - GdkScreen *screen = gdk_screen_get_default(); - if (screen == NULL) { - g_info("no default screen!\n"); - _exit(0); - } + GdkScreen *screen = gdk_screen_get_default(); + if (screen == NULL) { + g_info("no default screen!\n"); + _exit(0); + } - display_width = gdk_screen_get_width(screen); - display_height = gdk_screen_get_height(screen); + display_width = gdk_screen_get_width(screen); + display_height = gdk_screen_get_height(screen); + + log_debug("width=%d height=%d", display_width, display_height); + + // Go to "window" mode if there is enough space on the screen. + // Do not forget extra space needed for window top bars, screen bars etc. + + if (display_width > (MAX_DISPLAY_WIDTH + 10) && + display_height > (MAX_DISPLAY_HEIGHT + 30)) { + display_width = MAX_DISPLAY_WIDTH; + display_height = MAX_DISPLAY_HEIGHT; + // full_screen=0;//edit (comment for full screen) + } else { + // + // Some RaspPi variants report slightly too large screen sizes + // on a 7-inch screen, e.g. 848*480 while the physical resolution is 800*480 + // Therefore, as a work-around, limit window size to 800*480 + // + if (display_width > MAX_DISPLAY_WIDTH) { + display_width = MAX_DISPLAY_WIDTH; + } + if (display_height > MAX_DISPLAY_HEIGHT) { + display_height = MAX_DISPLAY_HEIGHT; + } + full_screen = 1; + } - log_debug("width=%d height=%d", display_width, display_height); + log_debug("display_width=%d display_height=%d", display_width, + display_height); - // Go to "window" mode if there is enough space on the screen. - // Do not forget extra space needed for window top bars, screen bars etc. + top_window = gtk_application_window_new(app); + if (full_screen) { + gtk_window_fullscreen(GTK_WINDOW(top_window)); + } + gtk_widget_set_size_request(top_window, display_width, display_height); + gtk_window_set_title(GTK_WINDOW(top_window), "Verdure SDR V1.2"); + gtk_window_set_position(GTK_WINDOW(top_window), GTK_WIN_POS_CENTER_ALWAYS); + gtk_window_set_resizable(GTK_WINDOW(top_window), TRUE); // edit + GError *error; + if (!gtk_window_set_icon_from_file(GTK_WINDOW(top_window), "hpsdr.png", + &error)) { + log_warn("failed to set icon for top_window"); + if (error != NULL) { + log_warn("%s", error->message); + } + } + g_signal_connect(top_window, "delete-event", G_CALLBACK(main_delete), NULL); - if (display_width > (MAX_DISPLAY_WIDTH + 10) && - display_height > (MAX_DISPLAY_HEIGHT + 30)) { - display_width = MAX_DISPLAY_WIDTH; - display_height = MAX_DISPLAY_HEIGHT; - // full_screen=0;//edit (comment for full screen) - } else { // - // Some RaspPi variants report slightly too large screen sizes - // on a 7-inch screen, e.g. 848*480 while the physical resolution is 800*480 - // Therefore, as a work-around, limit window size to 800*480 + // We want to use the space-bar as an alternative to go to TX // - if (display_width > MAX_DISPLAY_WIDTH) { - display_width = MAX_DISPLAY_WIDTH; - } - if (display_height > MAX_DISPLAY_HEIGHT) { - display_height = MAX_DISPLAY_HEIGHT; - } - full_screen = 1; - } - - log_debug("display_width=%d display_height=%d", display_width, - display_height); - - top_window = gtk_application_window_new(app); - if (full_screen) { - gtk_window_fullscreen(GTK_WINDOW(top_window)); - } - gtk_widget_set_size_request(top_window, display_width, display_height); - gtk_window_set_title(GTK_WINDOW(top_window), "Verdure SDR V1.2"); - gtk_window_set_position(GTK_WINDOW(top_window), GTK_WIN_POS_CENTER_ALWAYS); - gtk_window_set_resizable(GTK_WINDOW(top_window), TRUE); // edit - GError *error; - if (!gtk_window_set_icon_from_file(GTK_WINDOW(top_window), "hpsdr.png", - &error)) { - log_warn("failed to set icon for top_window"); - if (error != NULL) { - log_warn("%s", error->message); - } - } - g_signal_connect(top_window, "delete-event", G_CALLBACK(main_delete), NULL); - - // - // We want to use the space-bar as an alternative to go to TX - // - gtk_widget_add_events(top_window, GDK_KEY_PRESS_MASK); - g_signal_connect(top_window, "key_press_event", G_CALLBACK(keypress_cb), - NULL); - - grid = gtk_grid_new(); - gtk_widget_set_size_request(grid, display_width, display_height); - gtk_grid_set_row_homogeneous(GTK_GRID(grid), FALSE); - gtk_grid_set_column_homogeneous(GTK_GRID(grid), FALSE); - gtk_container_add(GTK_CONTAINER(top_window), grid); - - GtkWidget *image = gtk_image_new_from_file("hpsdr.png"); - gtk_grid_attach(GTK_GRID(grid), image, 0, 0, 1, 4); - - status = gtk_label_new(""); - gtk_label_set_justify(GTK_LABEL(status), GTK_JUSTIFY_LEFT); - gtk_widget_show(status); - gtk_grid_attach(GTK_GRID(grid), status, 1, 3, 1, 1); - gtk_widget_hide(top_window); - - g_idle_add(init, NULL); + gtk_widget_add_events(top_window, GDK_KEY_PRESS_MASK); + g_signal_connect(top_window, "key_press_event", G_CALLBACK(keypress_cb), + NULL); + + grid = gtk_grid_new(); + gtk_widget_set_size_request(grid, display_width, display_height); + gtk_grid_set_row_homogeneous(GTK_GRID(grid), FALSE); + gtk_grid_set_column_homogeneous(GTK_GRID(grid), FALSE); + gtk_container_add(GTK_CONTAINER(top_window), grid); + + GtkWidget *image = gtk_image_new_from_file("hpsdr.png"); + gtk_grid_attach(GTK_GRID(grid), image, 0, 0, 1, 4); + + status = gtk_label_new(""); + gtk_label_set_justify(GTK_LABEL(status), GTK_JUSTIFY_LEFT); + gtk_widget_show(status); + gtk_grid_attach(GTK_GRID(grid), status, 1, 3, 1, 1); + gtk_widget_hide(top_window); + + g_idle_add(init, NULL); } int main(int argc, char **argv) { - GtkApplication *pihpsdr; - int status; - - pihpsdr = gtk_application_new("org.rkrishnan.pihpsdr", G_APPLICATION_FLAGS_NONE); - g_signal_connect(pihpsdr, "activate", G_CALLBACK(activate_pihpsdr), NULL); - status = g_application_run(G_APPLICATION(pihpsdr), argc, argv); - g_object_unref(pihpsdr); - return status; + GtkApplication *pihpsdr; + int status; + + pihpsdr = gtk_application_new("org.rkrishnan.pihpsdr", G_APPLICATION_FLAGS_NONE); + g_signal_connect(pihpsdr, "activate", G_CALLBACK(activate_pihpsdr), NULL); + status = g_application_run(G_APPLICATION(pihpsdr), argc, argv); + g_object_unref(pihpsdr); + return status; } diff --git a/old_protocol.c b/old_protocol.c index 5aea9cc..ecc920f 100644 --- a/old_protocol.c +++ b/old_protocol.c @@ -1,21 +1,21 @@ /* 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. -* -*/ + * 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 #include @@ -40,16 +40,13 @@ #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 "receiver.h" #include "transmitter.h" #include "signal.h" -#include "toolbar.h" #include "vfo.h" #include "ext.h" #include "iambic.h" @@ -103,23 +100,23 @@ // 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 + 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; @@ -205,189 +202,84 @@ static int how_many_receivers(); #define COMMON_MERCURY_FREQUENCY 0x80 #define PENELOPE_MIC 0x80 -#ifdef USBOZY -// -// additional defines if we include USB Ozy support -// -#include "ozyio.h" - -static GThread *ozy_EP4_rx_thread_id; -static GThread *ozy_EP6_rx_thread_id; -static gpointer ozy_ep4_rx_thread(gpointer arg); -static gpointer ozy_ep6_rx_thread(gpointer arg); -static void start_usb_receive_threads(); -static void ozyusb_write(unsigned char* buffer,int length); -#define EP6_IN_ID 0x86 // end point = 6, direction toward PC -#define EP2_OUT_ID 0x02 // end point = 2, direction from PC -#define EP6_BUFFER_SIZE 2048 -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 void old_protocol_stop() { -#ifdef USBOZY - if(device!=DEVICE_OZY) { -#endif metis_start_stop(0); -#ifdef USBOZY - } -#endif } void old_protocol_run() { -#ifdef USBOZY - if(device!=DEVICE_OZY) { -#endif metis_restart(); -#ifdef USBOZY - } -#endif } void old_protocol_set_mic_sample_rate(int rate) { - mic_sample_divisor=rate/48000; + mic_sample_divisor=rate/48000; } void old_protocol_init(int rx,int pixels,int rate) { - int i; - log_trace("old_protocol_init: num_hpsdr_receivers=%d",how_many_receivers()); + int i; + log_trace("old_protocol_init: num_hpsdr_receivers=%d",how_many_receivers()); - old_protocol_set_mic_sample_rate(rate); + old_protocol_set_mic_sample_rate(rate); - if(transmitter->local_microphone) { - if(audio_open_input()!=0) { - log_error("audio_open_input failed"); - transmitter->local_microphone=0; + if(transmitter->local_microphone) { + if(audio_open_input()!=0) { + log_error("audio_open_input failed"); + transmitter->local_microphone=0; + } } - } - display_width=pixels; + display_width=pixels; -#ifdef USBOZY -// -// if we have a USB interfaced Ozy device: -// - if (device == DEVICE_OZY) { - log_trace("old_protocol_init: initialise ozy on USB"); - ozy_initialise(); - start_usb_receive_threads(); - } - else -#endif - { - log_trace("old_protocol starting receive thread: buffer_size=%d output_buffer_size=%d",buffer_size,output_buffer_size); - if (radio->use_tcp) { - open_tcp_socket(); - } else { - open_udp_socket(); - } - receive_thread_id = g_thread_new( "old protocol", receive_thread, NULL); - if( ! receive_thread_id ) { - log_error("g_thread_new failed on receive_thread"); - exit(-1); - } - for(i=8;iuse_tcp) { + open_tcp_socket(); + } else { + open_udp_socket(); + } + receive_thread_id = g_thread_new( "old protocol", receive_thread, NULL); + if( ! receive_thread_id ) + { + log_error("g_thread_new failed on receive_thread"); + exit(-1); + } + for(i=8;i= 0) { - tmp=data_socket; - data_socket=-1; - usleep(100000); - close(tmp); + tmp=data_socket; + data_socket=-1; + usleep(100000); + close(tmp); } tmp=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); if(tmp<0) { - perror("old_protocol: create socket failed for data_socket\n"); - exit(-1); + perror("old_protocol: create socket failed for data_socket\n"); + exit(-1); } int optval = 1; if(setsockopt(tmp, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0) { - perror("data_socket: SO_REUSEADDR"); + perror("data_socket: SO_REUSEADDR"); } if(setsockopt(tmp, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval))<0) { - perror("data_socket: SO_REUSEPORT"); + perror("data_socket: SO_REUSEPORT"); } optval=0xffff; if (setsockopt(tmp, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval))<0) { - perror("data_socket: SO_SNDBUF"); + perror("data_socket: SO_SNDBUF"); } if (setsockopt(tmp, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval))<0) { - perror("data_socket: SO_RCVBUF"); + perror("data_socket: SO_RCVBUF"); } // @@ -400,7 +292,7 @@ static void open_udp_socket() { tv.tv_sec=0; tv.tv_usec=100000; if(setsockopt(tmp, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))<0) { - perror("data_socket: SO_RCVTIMEO"); + perror("data_socket: SO_RCVTIMEO"); } // bind to the interface @@ -420,10 +312,10 @@ static void open_tcp_socket() { int tmp; if (tcp_socket >= 0) { - tmp=tcp_socket; - tcp_socket=-1; - usleep(100000); - close(tmp); + tmp=tcp_socket; + tcp_socket=-1; + usleep(100000); + close(tmp); } memcpy(&data_addr,&radio->network.address,sizeof(radio->network.address)); data_addr.sin_port=htons(DATA_PORT); @@ -432,141 +324,136 @@ static void open_tcp_socket() { tmp=socket(AF_INET, SOCK_STREAM, 0); if (tmp < 0) { - perror("tcp_socket: create socket failed for TCP socket"); - exit(-1); + perror("tcp_socket: create socket failed for TCP socket"); + exit(-1); } int optval = 1; if(setsockopt(tmp, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0) { - perror("tcp_socket: SO_REUSEADDR"); + perror("tcp_socket: SO_REUSEADDR"); } if(setsockopt(tmp, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval))<0) { - perror("tcp_socket: SO_REUSEPORT"); + perror("tcp_socket: SO_REUSEPORT"); } if (connect(tmp,(const struct sockaddr *)&data_addr,sizeof(data_addr)) < 0) { - perror("tcp_socket: connect"); + perror("tcp_socket: connect"); } optval=0xffff; if (setsockopt(tmp, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval))<0) { - perror("tcp_socket: SO_SNDBUF"); + perror("tcp_socket: SO_SNDBUF"); } if (setsockopt(tmp, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval))<0) { - perror("tcp_socket: SO_RCVBUF"); + perror("tcp_socket: SO_RCVBUF"); } tcp_socket=tmp; log_trace("TCP socket established: %d", tcp_socket); } static gpointer receive_thread(gpointer arg) { - struct sockaddr_in addr; - socklen_t length; - unsigned char buffer[2048]; - int bytes_read; - int ret,left; - int ep; - uint32_t sequence; - - running=1; - - //metis_restart(); - - length=sizeof(addr); - while(running) { - - switch(device) { -#ifdef USBOZY - case DEVICE_OZY: - // should not happen - break; -#endif - - default: - for (;;) { - if (tcp_socket >= 0) { - // TCP messages may be split, so collect exactly 1032 bytes. - // Remember, this is a STREAMING protocol. - bytes_read=0; - left=1032; - while (left > 0) { - ret=recvfrom(tcp_socket,buffer+bytes_read,(size_t)(left),0,NULL,0); - if (ret < 0 && errno == EAGAIN) continue; // time-out - if (ret < 0) break; // error - bytes_read += ret; - left -= ret; - } - if (ret < 0) { - bytes_read=ret; // error case: discard whole packet - //perror("old_protocol recvfrom TCP:"); + struct sockaddr_in addr; + socklen_t length; + unsigned char buffer[2048]; + int bytes_read; + int ret,left; + int ep; + uint32_t sequence; + + running=1; + + //metis_restart(); + + length=sizeof(addr); + while(running) { + + switch(device) { + + default: + for (;;) { + if (tcp_socket >= 0) { + // TCP messages may be split, so collect exactly 1032 bytes. + // Remember, this is a STREAMING protocol. + bytes_read=0; + left=1032; + while (left > 0) { + ret=recvfrom(tcp_socket,buffer+bytes_read,(size_t)(left),0,NULL,0); + if (ret < 0 && errno == EAGAIN) continue; // time-out + if (ret < 0) break; // error + bytes_read += ret; + left -= ret; + } + if (ret < 0) { + bytes_read=ret; // error case: discard whole packet + //perror("old_protocol recvfrom TCP:"); + } + } 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:"); + } else { + // This could happen in METIS start/stop sequences + usleep(100000); + continue; + } + if(bytes_read >= 0 || errno != EAGAIN) break; + } + if(bytes_read <= 0) { + continue; } - } 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:"); - } else { - // This could happen in METIS start/stop sequences - usleep(100000); - continue; - } - if(bytes_read >= 0 || errno != EAGAIN) break; - } - if(bytes_read <= 0) { - continue; - } - if(buffer[0]==0xEF && buffer[1]==0xFE) { - switch(buffer[2]) { - case 1: - // get the end point - ep=buffer[3]&0xFF; - - // get the sequence number - sequence=((buffer[4]&0xFF)<<24)+((buffer[5]&0xFF)<<16)+((buffer[6]&0xFF)<<8)+(buffer[7]&0xFF); - - // A sequence error with a seqnum of zero usually indicates a METIS restart - // and is no error condition - if (sequence != 0 && sequence != last_seq_num+1) { - log_error("SEQ ERROR: last %ld, recvd %ld", (long) last_seq_num, (long) sequence); - sequence_errors++; - } - last_seq_num=sequence; - switch(ep) { - case 6: // EP6 - // process the data - process_ozy_input_buffer(&buffer[8]); - process_ozy_input_buffer(&buffer[520]); - break; - case 4: // EP4 + if(buffer[0]==0xEF && buffer[1]==0xFE) { + switch(buffer[2]) { + case 1: + // get the end point + ep=buffer[3]&0xFF; + + // get the sequence number + sequence=((buffer[4]&0xFF)<<24)+((buffer[5]&0xFF)<<16)+((buffer[6]&0xFF)<<8)+(buffer[7]&0xFF); + + // A sequence error with a seqnum of zero usually indicates a METIS restart + // and is no error condition + if (sequence != 0 && sequence != last_seq_num+1) { + log_error("SEQ ERROR: last %ld, recvd %ld", (long) last_seq_num, (long) sequence); + sequence_errors++; + } + last_seq_num=sequence; + switch(ep) { + case 6: // EP6 + // process the data + process_ozy_input_buffer(&buffer[8]); + process_ozy_input_buffer(&buffer[520]); + break; + case 4: // EP4 /* - ep4_sequence++; - if(sequence!=ep4_sequence) { - ep4_sequence=sequence; - } else { - int seq=(int)(sequence%32L); - if((sequence%32L)==0L) { - reset_bandscope_buffer_index(); - } - process_bandscope_buffer(&buffer[8]); - process_bandscope_buffer(&buffer[520]); - } + ep4_sequence++; + if(sequence!=ep4_sequence) { + ep4_sequence=sequence; + } else { + int seq=(int)(sequence%32L); + if((sequence%32L)==0L) { + reset_bandscope_buffer_index(); + } + process_bandscope_buffer(&buffer[8]); + process_bandscope_buffer(&buffer[520]); + } */ - break; - default: - log_error("unexpected EP %d length=%d",ep,bytes_read); - break; - } - break; - case 2: // response to a discovery packet - log_error("unexepected discovery response when not in discovery mode"); - break; - default: - log_error("unexpected packet type: 0x%02X",buffer[2]); - break; - } - } else { - log_debug("received bad header bytes on data port %02X,%02X",buffer[0],buffer[1]); - } - break; + break; + default: + log_error("unexpected EP %d length=%d",ep,bytes_read); + break; + } + break; + case 2: // response to a discovery packet + log_error("unexepected discovery response when not in discovery mode"); + break; + default: + log_error("unexpected packet type: 0x%02X",buffer[2]); + break; + } + } else { + log_debug("received bad header bytes on data port %02X,%02X",buffer[0],buffer[1]); + } + break; + } } - } - return NULL; + return NULL; } // @@ -580,188 +467,188 @@ static gpointer receive_thread(gpointer arg) { // static int rx_feedback_channel() { - // - // For radios with small FPGAS only supporting 2 RX, use RX1. - // Else, use the last RX before the TX feedback channel. - // - int ret; - switch (device) { + // + // For radios with small FPGAS only supporting 2 RX, use RX1. + // Else, use the last RX before the TX feedback channel. + // + int ret; + switch (device) { case DEVICE_METIS: case DEVICE_HERMES_LITE: - ret=0; - break; + ret=0; + break; case DEVICE_HERMES: case DEVICE_HERMES_LITE2: - ret=2; - break; + ret=2; + break; case DEVICE_ANGELIA: case DEVICE_ORION: case DEVICE_ORION2: - ret=3; - break; + ret=3; + break; default: - ret=0; - break; - } - return ret; + ret=0; + break; + } + return ret; } static int tx_feedback_channel() { - // - // Radios with small FPGAs use RX2 - // HERMES uses RX4, - // and Angelia and beyond use RX5 - // - // This is hard-coded in the firmware. - // - int ret; - switch (device) { + // + // Radios with small FPGAs use RX2 + // HERMES uses RX4, + // and Angelia and beyond use RX5 + // + // This is hard-coded in the firmware. + // + int ret; + switch (device) { case DEVICE_METIS: case DEVICE_HERMES_LITE: - ret=1; - break; + ret=1; + break; case DEVICE_HERMES: case DEVICE_HERMES_LITE2: - ret=3; - break; + ret=3; + break; case DEVICE_ANGELIA: case DEVICE_ORION: case DEVICE_ORION2: - ret=4; - break; + ret=4; + break; default: - ret=1; - break; - } - return ret; + ret=1; + break; + } + return ret; } static int first_receiver_channel() { - return 0; + return 0; } static int second_receiver_channel() { - return 1; + return 1; } static long long channel_freq(int chan) { - // - // Return the frequency associated with the current HPSDR - // RX channel (0 <= chan <= 4). - // - // This function returns the TX frequency if chan is - // outside the allowed range, and thus can be used - // to set the TX frequency. - // - // If transmitting with PURESIGNAL, the frequencies of - // the feedback and TX DAC channels are set to the TX freq. - // - // This subroutine is the ONLY place here where the VFO - // frequencies are looked at. - // - int vfonum; - long long freq; + // + // Return the frequency associated with the current HPSDR + // RX channel (0 <= chan <= 4). + // + // This function returns the TX frequency if chan is + // outside the allowed range, and thus can be used + // to set the TX frequency. + // + // If transmitting with PURESIGNAL, the frequencies of + // the feedback and TX DAC channels are set to the TX freq. + // + // This subroutine is the ONLY place here where the VFO + // frequencies are looked at. + // + int vfonum; + long long freq; - // RX1 and RX2 are normally used for the first and second receiver. - // all other channels are used for PURESIGNAL and get the TX frequency - switch (chan) { + // RX1 and RX2 are normally used for the first and second receiver. + // all other channels are used for PURESIGNAL and get the TX frequency + switch (chan) { case 0: - vfonum=receiver[0]->id; - break; - case 1: - if (diversity_enabled) { vfonum=receiver[0]->id; - } else { - vfonum=receiver[1]->id; - } - break; + break; + case 1: + if (diversity_enabled) { + vfonum=receiver[0]->id; + } else { + vfonum=receiver[1]->id; + } + break; default: // TX frequency used for all other channels - vfonum=-1; - break; - } - // Radios with small FPGAs use RX1/RX2 for feedback while transmitting, - // - if (isTransmitting() && transmitter->puresignal && (chan == rx_feedback_channel() || chan == tx_feedback_channel())) { - vfonum = -1; - } - if (vfonum < 0) { - // - // indicates that we should use the TX frequency. - // We have to adjust by the offset for CTUN mode - // - vfonum=get_tx_vfo(); - freq=vfo[vfonum].frequency-vfo[vfonum].lo; - if (vfo[vfonum].ctun) freq += vfo[vfonum].offset; - if(transmitter->xit_enabled) { - freq+=transmitter->xit; - } - if (!cw_is_on_vfo_freq) { - if(vfo[vfonum].mode==modeCWU) { - freq+=(long long)cw_keyer_sidetone_frequency; - } else if(vfo[vfonum].mode==modeCWL) { - freq-=(long long)cw_keyer_sidetone_frequency; - } + vfonum=-1; + break; } - } else { - // - // determine RX frequency associated with VFO #vfonum - // This is the center freq in CTUN mode. + // Radios with small FPGAs use RX1/RX2 for feedback while transmitting, // - freq=vfo[vfonum].frequency-vfo[vfonum].lo; - if(vfo[vfonum].rit_enabled) { - freq+=vfo[vfonum].rit; + if (isTransmitting() && transmitter->puresignal && (chan == rx_feedback_channel() || chan == tx_feedback_channel())) { + vfonum = -1; } - if (cw_is_on_vfo_freq) { - if(vfo[vfonum].mode==modeCWU) { - freq-=(long long)cw_keyer_sidetone_frequency; - } else if(vfo[vfonum].mode==modeCWL) { - freq+=(long long)cw_keyer_sidetone_frequency; - } + if (vfonum < 0) { + // + // indicates that we should use the TX frequency. + // We have to adjust by the offset for CTUN mode + // + vfonum=get_tx_vfo(); + freq=vfo[vfonum].frequency-vfo[vfonum].lo; + if (vfo[vfonum].ctun) freq += vfo[vfonum].offset; + if(transmitter->xit_enabled) { + freq+=transmitter->xit; + } + if (!cw_is_on_vfo_freq) { + if(vfo[vfonum].mode==modeCWU) { + freq+=(long long)cw_keyer_sidetone_frequency; + } else if(vfo[vfonum].mode==modeCWL) { + freq-=(long long)cw_keyer_sidetone_frequency; + } + } + } else { + // + // determine RX frequency associated with VFO #vfonum + // This is the center freq in CTUN mode. + // + freq=vfo[vfonum].frequency-vfo[vfonum].lo; + if(vfo[vfonum].rit_enabled) { + freq+=vfo[vfonum].rit; + } + if (cw_is_on_vfo_freq) { + if(vfo[vfonum].mode==modeCWU) { + freq-=(long long)cw_keyer_sidetone_frequency; + } else if(vfo[vfonum].mode==modeCWL) { + freq+=(long long)cw_keyer_sidetone_frequency; + } + } } - } - freq+=calibration; - return freq; + freq+=calibration; + return freq; } static int how_many_receivers() { - // - // For DIVERSITY, we need at least two RX channels - // When PURESIGNAL is active, we need to include the TX DAC channel. - // - int ret = receivers; // 1 or 2 - if (diversity_enabled) ret=2; // need both RX channels, even if there is only one RX + // + // For DIVERSITY, we need at least two RX channels + // When PURESIGNAL is active, we need to include the TX DAC channel. + // + int ret = receivers; // 1 or 2 + if (diversity_enabled) ret=2; // need both RX channels, even if there is only one RX #ifdef PURESIGNAL // for PureSignal, the number of receivers needed is hard-coded below. // we need at least 2, and up to 5 for Orion2 boards. This is so because // the TX DAC is hard-wired to RX4 for HERMES,STEMLAB and to RX5 for ANGELIA // and beyond. - if (transmitter->puresignal) { - switch (device) { - case DEVICE_METIS: - case DEVICE_HERMES_LITE: - ret=2; // TX feedback hard-wired to RX2 - break; - case DEVICE_HERMES: - case DEVICE_HERMES_LITE2: - ret=4; // TX feedback hard-wired to RX4 - break; - case DEVICE_ANGELIA: - case DEVICE_ORION: - case DEVICE_ORION2: - ret=5; // TX feedback hard-wired to RX5 - break; - default: - ret=2; // This is the minimum for PURESIGNAL - break; + if (transmitter->puresignal) { + switch (device) { + case DEVICE_METIS: + case DEVICE_HERMES_LITE: + ret=2; // TX feedback hard-wired to RX2 + break; + case DEVICE_HERMES: + case DEVICE_HERMES_LITE2: + ret=4; // TX feedback hard-wired to RX4 + break; + case DEVICE_ANGELIA: + case DEVICE_ORION: + case DEVICE_ORION2: + ret=5; // TX feedback hard-wired to RX5 + break; + default: + ret=2; // This is the minimum for PURESIGNAL + break; + } } - } #endif return ret; } /* -static void process_ozy_input_buffer(unsigned char *buffer) { + static void process_ozy_input_buffer(unsigned char *buffer) { int i; int r; int b=0; @@ -793,198 +680,198 @@ static void process_ozy_input_buffer(unsigned char *buffer) { int rx2channel = second_receiver_channel(); if(buffer[b++]==SYNC && buffer[b++]==SYNC && buffer[b++]==SYNC) { - // extract control bytes - control_in[0]=buffer[b++]; - control_in[1]=buffer[b++]; - control_in[2]=buffer[b++]; - control_in[3]=buffer[b++]; - control_in[4]=buffer[b++]; + // extract control bytes + control_in[0]=buffer[b++]; + control_in[1]=buffer[b++]; + control_in[2]=buffer[b++]; + control_in[3]=buffer[b++]; + control_in[4]=buffer[b++]; - // 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; + // 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 (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)); - } + 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; - } + 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; + } - int iq_samples=(512-8)/((num_hpsdr_receivers*6)+2); + int iq_samples=(512-8)/((num_hpsdr_receivers*6)+2); - for(i=0;ipuresignal) { - // - // transmitting with PURESIGNAL. Get sample pairs and feed to pscc - // - if (r == rxfdbk) { - left_sample_double_rx=left_sample_double; - right_sample_double_rx=right_sample_double; - } else if (r == 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 (r+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() && transmitter->puresignal) { + // + // transmitting with PURESIGNAL. Get sample pairs and feed to pscc + // + if (r == rxfdbk) { + left_sample_double_rx=left_sample_double; + right_sample_double_rx=right_sample_double; + } else if (r == 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 (r+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 (r == rx1channel) { - left_sample_double_main=left_sample_double; - right_sample_double_main=right_sample_double; - } else if (r == 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 (r+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() && diversity_enabled) { + // + // receiving with DIVERSITY. Get sample pairs and feed to diversity mixer + // + if (r == rx1channel) { + left_sample_double_main=left_sample_double; + right_sample_double_main=right_sample_double; + } else if (r == 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 (r+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 (r == rx1channel) { - add_iq_samples(receiver[0], left_sample_double,right_sample_double); - } else if (r == rx2channel && receivers > 1) { - add_iq_samples(receiver[1], left_sample_double,right_sample_double); - } - } - } // end of loop over the receiver channels - - // - // Process mic samples. Take them from radio or from - // "local microphone" ring buffer - // - mic_sample = (short)(buffer[b++]<<8); - mic_sample |= (short)(buffer[b++]&0xFF); - - mic_samples++; - if(mic_samples>=mic_sample_divisor) { // reduce to 48000 - fsample = transmitter->local_microphone ? audio_get_next_mic_sample() : (float) mic_sample * 0.00003051; - add_mic_sample(transmitter,fsample); - mic_samples=0; - } + if ((!isTransmitting() || duplex) && !diversity_enabled) { + // + // RX without DIVERSITY. Feed samples to RX1 and RX2 + // + if (r == rx1channel) { + add_iq_samples(receiver[0], left_sample_double,right_sample_double); + } else if (r == rx2channel && receivers > 1) { + add_iq_samples(receiver[1], left_sample_double,right_sample_double); + } + } + } // end of loop over the receiver channels - } + // + // Process mic samples. Take them from radio or from + // "local microphone" ring buffer + // + mic_sample = (short)(buffer[b++]<<8); + mic_sample |= (short)(buffer[b++]&0xFF); + + mic_samples++; + if(mic_samples>=mic_sample_divisor) { // reduce to 48000 + fsample = transmitter->local_microphone ? audio_get_next_mic_sample() : (float) mic_sample * 0.00003051; + add_mic_sample(transmitter,fsample); + mic_samples=0; + } + + } } else { - time_t t; - struct tm* gmt; - time(&t); - gmt=gmtime(&t); + time_t t; + struct tm* gmt; + time(&t); + gmt=gmtime(&t); - log_debug("%s: process_ozy_input_buffer: did not find sync: restarting\n", - asctime(gmt)); + log_debug("%s: process_ozy_input_buffer: did not find sync: restarting\n", + asctime(gmt)); - metis_start_stop(0); - metis_restart(); + metis_start_stop(0); + metis_restart(); + } } -} */ static int nreceiver; @@ -1006,103 +893,103 @@ static int nsamples; static int iq_samples; static void process_control_bytes() { - int previous_ptt; - int previous_dot; - int previous_dash; + 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; + // 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 { + 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 ); + // + // 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)); - } + if(previous_ptt!=local_ptt) { + g_idle_add(ext_mox_update,(gpointer)(long)(local_ptt)); + } - switch((control_in[0]>>3)&0x1F) { + 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]; - // log_info(" Mercury Software version: %d (0x%0X)",mercury_software_version,mercury_software_version); - } - if(penelope_software_version!=control_in[3]) { - penelope_software_version=control_in[3]; - // log_info(" Penelope Software version: %d (0x%0X)",penelope_software_version,penelope_software_version); - } - } - if(ozy_software_version!=control_in[4]) { - ozy_software_version=control_in[4]; - log_info("FPGA firmware version: %d.%d",ozy_software_version/10,ozy_software_version%10); - } - break; + 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]; + // log_info(" Mercury Software version: %d (0x%0X)",mercury_software_version,mercury_software_version); + } + if(penelope_software_version!=control_in[3]) { + penelope_software_version=control_in[3]; + // log_info(" Penelope Software version: %d (0x%0X)",penelope_software_version,penelope_software_version); + } + } + if(ozy_software_version!=control_in[4]) { + ozy_software_version=control_in[4]; + log_info("FPGA firmware version: %d.%d",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; + 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; + 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; - } + 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; + } } @@ -1113,175 +1000,175 @@ static int rx1channel; static int rx2channel; static void process_ozy_byte(int b) { - float fsample; - switch(state) { + float fsample; + switch(state) { case SYNC_0: - if(b==SYNC) { - state++; - } - break; + if(b==SYNC) { + state++; + } + break; case SYNC_1: - if(b==SYNC) { - state++; - } - break; + if(b==SYNC) { + state++; + } + break; case SYNC_2: - if(b==SYNC) { - state++; - } - break; + if(b==SYNC) { + state++; + } + break; case CONTROL_0: - control_in[0]=b; - state++; - break; + control_in[0]=b; + state++; + break; case CONTROL_1: - control_in[1]=b; - state++; - break; + control_in[1]=b; + state++; + break; case CONTROL_2: - control_in[2]=b; - state++; - break; + control_in[2]=b; + state++; + break; case CONTROL_3: - control_in[3]=b; - state++; - break; + 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; + 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; + left_sample=(int)((signed char)b<<16); + state++; + break; case LEFT_SAMPLE_MID: - left_sample|=(int)((((unsigned char)b)<<8)&0xFF00); - state++; - break; + 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; + 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; + right_sample=(int)((signed char)b<<16); + state++; + break; case RIGHT_SAMPLE_MID: - right_sample|=(int)((((unsigned char)b)<<8)&0xFF00); - state++; - break; + 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; + 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; + mic_sample=(short)(b<<8); + state++; + break; case MIC_SAMPLE_LOW: - mic_sample|=(short)(b&0xFF); - mic_samples++; - if(mic_samples>=mic_sample_divisor) { // reduce to 48000 - fsample = transmitter->local_microphone ? audio_get_next_mic_sample() : (float) mic_sample * 0.00003051; - add_mic_sample(transmitter,fsample); - mic_samples=0; - } - nsamples++; - if(nsamples==iq_samples) { - state=SYNC_0; - } else { - nreceiver=0; - state=LEFT_SAMPLE_HI; - } - break; - } + mic_sample|=(short)(b&0xFF); + mic_samples++; + if(mic_samples>=mic_sample_divisor) { // reduce to 48000 + fsample = transmitter->local_microphone ? audio_get_next_mic_sample() : (float) mic_sample * 0.00003051; + add_mic_sample(transmitter,fsample); + 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); - } + 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()) { - output_buffer[output_buffer_index++]=left_audio_sample>>8; - output_buffer[output_buffer_index++]=left_audio_sample; - output_buffer[output_buffer_index++]=right_audio_sample>>8; - output_buffer[output_buffer_index++]=right_audio_sample; - output_buffer[output_buffer_index++]=0; - output_buffer[output_buffer_index++]=0; - output_buffer[output_buffer_index++]=0; - output_buffer[output_buffer_index++]=0; - if(output_buffer_index>=OZY_BUFFER_SIZE) { - ozy_send_buffer(); - output_buffer_index=8; + if(!isTransmitting()) { + output_buffer[output_buffer_index++]=left_audio_sample>>8; + output_buffer[output_buffer_index++]=left_audio_sample; + output_buffer[output_buffer_index++]=right_audio_sample>>8; + output_buffer[output_buffer_index++]=right_audio_sample; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + if(output_buffer_index>=OZY_BUFFER_SIZE) { + ozy_send_buffer(); + output_buffer_index=8; + } } - } } // @@ -1292,630 +1179,611 @@ void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right // fully equivalent to old_protocol_iq_samples. // void old_protocol_iq_samples_with_sidetone(int isample, int qsample, int side) { - if(isTransmitting()) { - output_buffer[output_buffer_index++]=side >> 8; - output_buffer[output_buffer_index++]=side; - output_buffer[output_buffer_index++]=side >> 8; - output_buffer[output_buffer_index++]=side; - output_buffer[output_buffer_index++]=isample>>8; - output_buffer[output_buffer_index++]=isample; - output_buffer[output_buffer_index++]=qsample>>8; - output_buffer[output_buffer_index++]=qsample; - if(output_buffer_index>=OZY_BUFFER_SIZE) { - ozy_send_buffer(); - output_buffer_index=8; + if(isTransmitting()) { + output_buffer[output_buffer_index++]=side >> 8; + output_buffer[output_buffer_index++]=side; + output_buffer[output_buffer_index++]=side >> 8; + output_buffer[output_buffer_index++]=side; + output_buffer[output_buffer_index++]=isample>>8; + output_buffer[output_buffer_index++]=isample; + output_buffer[output_buffer_index++]=qsample>>8; + output_buffer[output_buffer_index++]=qsample; + if(output_buffer_index>=OZY_BUFFER_SIZE) { + ozy_send_buffer(); + output_buffer_index=8; + } } - } } void old_protocol_iq_samples(int isample,int qsample) { - if(isTransmitting()) { - output_buffer[output_buffer_index++]=0; - output_buffer[output_buffer_index++]=0; - output_buffer[output_buffer_index++]=0; - output_buffer[output_buffer_index++]=0; - output_buffer[output_buffer_index++]=isample>>8; - output_buffer[output_buffer_index++]=isample; - output_buffer[output_buffer_index++]=qsample>>8; - output_buffer[output_buffer_index++]=qsample; - if(output_buffer_index>=OZY_BUFFER_SIZE) { - ozy_send_buffer(); - output_buffer_index=8; + if(isTransmitting()) { + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=isample>>8; + output_buffer[output_buffer_index++]=isample; + output_buffer[output_buffer_index++]=qsample>>8; + output_buffer[output_buffer_index++]=qsample; + if(output_buffer_index>=OZY_BUFFER_SIZE) { + ozy_send_buffer(); + output_buffer_index=8; + } } - } } /* -static void process_bandscope_buffer(char *buffer) { -} + static void process_bandscope_buffer(char *buffer) { + } */ void ozy_send_buffer() { - int txmode=get_tx_mode(); - int txvfo=get_tx_vfo(); - int i; - BAND *band; - int num_hpsdr_receivers=how_many_receivers(); - int rx1channel = first_receiver_channel(); - int rx2channel = second_receiver_channel(); + int txmode=get_tx_mode(); + int txvfo=get_tx_vfo(); + int i; + BAND *band; + int num_hpsdr_receivers=how_many_receivers(); + int rx1channel = first_receiver_channel(); + int rx2channel = second_receiver_channel(); - output_buffer[SYNC0]=SYNC; - output_buffer[SYNC1]=SYNC; - output_buffer[SYNC2]=SYNC; + output_buffer[SYNC0]=SYNC; + output_buffer[SYNC1]=SYNC; + output_buffer[SYNC2]=SYNC; - if(metis_offset==8) { - // - // Every second packet is a "C0=0" packet - // Unless USB device - // - output_buffer[C0]=0x00; - output_buffer[C1]=0x00; - switch(active_receiver->sample_rate) { - case 48000: - output_buffer[C1]|=SPEED_48K; - break; - case 96000: - output_buffer[C1]|=SPEED_96K; - break; - case 192000: - output_buffer[C1]|=SPEED_192K; - break; - case 384000: - output_buffer[C1]|=SPEED_384K; - break; - } + if(metis_offset==8) { + // + // Every second packet is a "C0=0" packet + // Unless USB device + // + output_buffer[C0]=0x00; + output_buffer[C1]=0x00; + switch(active_receiver->sample_rate) { + case 48000: + output_buffer[C1]|=SPEED_48K; + break; + case 96000: + output_buffer[C1]|=SPEED_96K; + break; + case 192000: + output_buffer[C1]|=SPEED_192K; + break; + case 384000: + output_buffer[C1]|=SPEED_384K; + break; + } // set more bits for Atlas based device // CONFIG_BOTH seems to be critical to getting ozy to respond -#ifdef USBOZY - if ((device == DEVICE_OZY) || (device == DEVICE_METIS)) -#else - if (device == DEVICE_METIS) -#endif - { - // atlas_mic_source is FALSE when using Janus + if (device == DEVICE_METIS) + { + // atlas_mic_source is FALSE when using Janus - if (atlas_mic_source) { - output_buffer[C1] |= PENELOPE_MIC; - 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 + if (atlas_mic_source) { + output_buffer[C1] |= PENELOPE_MIC; + output_buffer[C1] |= CONFIG_BOTH; + } - output_buffer[C2]=0x00; - if(classE) { - output_buffer[C2]|=0x01; - } - band=band_get_band(vfo[VFO_A].band); - if(isTransmitting()) { - band=band_get_band(vfo[txvfo].band); - output_buffer[C2]|=band->OCtx<<1; - if(tune) { - if(OCmemory_tune_time!=0) { - struct timeval te; - gettimeofday(&te,NULL); - long long now=te.tv_sec*1000LL+te.tv_usec/1000; - if(tune_timeout>now) { - output_buffer[C2]|=OCtune<<1; - } - } else { - output_buffer[C2]|=OCtune<<1; - } - } - } else { - output_buffer[C2]|=band->OCrx<<1; - } + if (atlas_clock_source_128mhz) + output_buffer[C1] |= MERCURY_122_88MHZ_SOURCE; + output_buffer[C1] |= ((atlas_clock_source_10mhz & 3) << 2); + } - output_buffer[C3] = (receiver[0]->alex_attenuation) & 0x03; // do not set higher bits - if(active_receiver->random) { - output_buffer[C3]|=LT2208_RANDOM_ON; - } - if(active_receiver->dither) { - output_buffer[C3]|=LT2208_DITHER_ON; - } - if (filter_board == CHARLY25 && active_receiver->preamp) { - output_buffer[C3]|=LT2208_GAIN_ON; - } + output_buffer[C2]=0x00; + if(classE) { + output_buffer[C2]|=0x01; + } + band=band_get_band(vfo[VFO_A].band); + if(isTransmitting()) { + band=band_get_band(vfo[txvfo].band); + output_buffer[C2]|=band->OCtx<<1; + if(tune) { + if(OCmemory_tune_time!=0) { + struct timeval te; + gettimeofday(&te,NULL); + long long now=te.tv_sec*1000LL+te.tv_usec/1000; + if(tune_timeout>now) { + output_buffer[C2]|=OCtune<<1; + } + } else { + output_buffer[C2]|=OCtune<<1; + } + } + } else { + output_buffer[C2]|=band->OCrx<<1; + } - // - // Set ALEX RX1_ANT and RX1_OUT - // - i=receiver[0]->alex_antenna; - // - // Upon TX, we might have to activate a different RX path for the - // attenuated feedback signal. Use alex_antenna == 0, if - // the feedback signal is routed automatically/internally - // If feedback is to the second ADC, leave RX1 ANT settings untouched - // + output_buffer[C3] = (receiver[0]->alex_attenuation) & 0x03; // do not set higher bits + if(active_receiver->random) { + output_buffer[C3]|=LT2208_RANDOM_ON; + } + if(active_receiver->dither) { + output_buffer[C3]|=LT2208_DITHER_ON; + } + if (filter_board == CHARLY25 && active_receiver->preamp) { + output_buffer[C3]|=LT2208_GAIN_ON; + } + + // + // Set ALEX RX1_ANT and RX1_OUT + // + i=receiver[0]->alex_antenna; + // + // Upon TX, we might have to activate a different RX path for the + // attenuated feedback signal. Use alex_antenna == 0, if + // the feedback signal is routed automatically/internally + // If feedback is to the second ADC, leave RX1 ANT settings untouched + // #ifdef PURESIGNAL - if (isTransmitting() && transmitter->puresignal) i=receiver[PS_RX_FEEDBACK]->alex_antenna; + if (isTransmitting() && transmitter->puresignal) i=receiver[PS_RX_FEEDBACK]->alex_antenna; #endif - if (device == DEVICE_ORION2) { - i +=100; - } else if (new_pa_board) { - // New-PA setting invalid on ANAN-7000,8000 - i +=1000; - } - // - // There are several combination which do not exist (no jacket present) - // or which do not work (using EXT1-on-TX with ANAN-7000). - // In these cases, fall back to a "reasonable" case (e.g. use EXT1 if - // there is no EXT2). - // As a result, the "New PA board" setting is overriden for PURESIGNAL - // feedback: EXT1 assumes old PA board and ByPass assumes new PA board. - // - switch(i) { - case 3: // EXT1 with old pa board - case 6: // EXT1-on-TX: assume old pa board - case 1006: - output_buffer[C3] |= 0xC0; - break; - case 4: // EXT2 with old pa board - output_buffer[C3] |= 0xA0; - break; - case 5: // XVTR with old pa board - output_buffer[C3] |= 0xE0; - break; - case 104: // EXT2 with ANAN-7000: does not exit, use EXT1 - case 103: // EXT1 with ANAN-7000 - output_buffer[C3]|= 0x40; - break; - case 105: // XVTR with ANAN-7000 - output_buffer[C3]|= 0x60; - break; - case 106: // EXT1-on-TX with ANAN-7000: does not exist, use ByPass - case 107: // Bypass-on-TX with ANAN-7000 - output_buffer[C3]|= 0x20; - break; - case 1003: // EXT1 with new PA board - output_buffer[C3] |= 0x40; - break; - case 1004: // EXT2 with new PA board - output_buffer[C3] |= 0x20; - break; - case 1005: // XVRT with new PA board - output_buffer[C3] |= 0x60; - break; - case 7: // Bypass-on-TX: assume new PA board - case 1007: - output_buffer[C3] |= 0x80; - break; - } + if (device == DEVICE_ORION2) { + i +=100; + } else if (new_pa_board) { + // New-PA setting invalid on ANAN-7000,8000 + i +=1000; + } + // + // There are several combination which do not exist (no jacket present) + // or which do not work (using EXT1-on-TX with ANAN-7000). + // In these cases, fall back to a "reasonable" case (e.g. use EXT1 if + // there is no EXT2). + // As a result, the "New PA board" setting is overriden for PURESIGNAL + // feedback: EXT1 assumes old PA board and ByPass assumes new PA board. + // + switch(i) { + case 3: // EXT1 with old pa board + case 6: // EXT1-on-TX: assume old pa board + case 1006: + output_buffer[C3] |= 0xC0; + break; + case 4: // EXT2 with old pa board + output_buffer[C3] |= 0xA0; + break; + case 5: // XVTR with old pa board + output_buffer[C3] |= 0xE0; + break; + case 104: // EXT2 with ANAN-7000: does not exit, use EXT1 + case 103: // EXT1 with ANAN-7000 + output_buffer[C3]|= 0x40; + break; + case 105: // XVTR with ANAN-7000 + output_buffer[C3]|= 0x60; + break; + case 106: // EXT1-on-TX with ANAN-7000: does not exist, use ByPass + case 107: // Bypass-on-TX with ANAN-7000 + output_buffer[C3]|= 0x20; + break; + case 1003: // EXT1 with new PA board + output_buffer[C3] |= 0x40; + break; + case 1004: // EXT2 with new PA board + output_buffer[C3] |= 0x20; + break; + case 1005: // XVRT with new PA board + output_buffer[C3] |= 0x60; + break; + case 7: // Bypass-on-TX: assume new PA board + case 1007: + output_buffer[C3] |= 0x80; + break; + } #ifdef DEBUG_PROTO - CHECK(i, CASE1); - CHECK((output_buffer[C3] & 0x80) >> 7, C3_RX1_OUT); - CHECK((output_buffer[C3] & 0x60) >> 5, C3_RX1_ANT); + CHECK(i, CASE1); + CHECK((output_buffer[C3] & 0x80) >> 7, C3_RX1_OUT); + CHECK((output_buffer[C3] & 0x60) >> 5, C3_RX1_ANT); #endif - output_buffer[C4]=0x04; // duplex - // - // This is used to phase-synchronize RX1 and RX2 on some boards - // and enforces that the RX1 and RX2 frequencies are the same. - // - if (diversity_enabled) output_buffer[C4] |= 0x80; + output_buffer[C4]=0x04; // duplex + // + // This is used to phase-synchronize RX1 and RX2 on some boards + // and enforces that the RX1 and RX2 frequencies are the same. + // + if (diversity_enabled) output_buffer[C4] |= 0x80; - // 0 ... 7 maps on 1 ... 8 receivers - output_buffer[C4]|=(num_hpsdr_receivers-1)<<3; + // 0 ... 7 maps on 1 ... 8 receivers + output_buffer[C4]|=(num_hpsdr_receivers-1)<<3; // // Now we set the bits for Ant1/2/3 (RX and TX may be different) // - if(isTransmitting()) { - i=transmitter->alex_antenna; - // - // TX antenna outside allowd range: this cannot happen. - // Out of paranoia: print warning and choose ANT1 - // - if (i<0 || i>2) { - log_warn("WARNING: illegal TX antenna chosen, using ANT1"); - transmitter->alex_antenna=0; - i=0; - } - } else { - i=receiver[0]->alex_antenna; - // - // Not using ANT1,2,3: can leave relais in TX state unless using new PA board - // - if (i > 2 && !new_pa_board) i=transmitter->alex_antenna; - } + if(isTransmitting()) { + i=transmitter->alex_antenna; + // + // TX antenna outside allowd range: this cannot happen. + // Out of paranoia: print warning and choose ANT1 + // + if (i<0 || i>2) { + log_warn("WARNING: illegal TX antenna chosen, using ANT1"); + transmitter->alex_antenna=0; + i=0; + } + } else { + i=receiver[0]->alex_antenna; + // + // Not using ANT1,2,3: can leave relais in TX state unless using new PA board + // + if (i > 2 && !new_pa_board) i=transmitter->alex_antenna; + } - switch(i) { + switch(i) { case 0: // ANT 1 - output_buffer[C4]|=0x00; - break; + output_buffer[C4]|=0x00; + break; case 1: // ANT 2 - output_buffer[C4]|=0x01; - break; + output_buffer[C4]|=0x01; + break; case 2: // ANT 3 - output_buffer[C4]|=0x02; - break; + output_buffer[C4]|=0x02; + break; default: - // this happens only with the new pa board and using EXT1/EXT2/XVTR - // here we have to disconnect ANT1,2,3 - output_buffer[C4]|=0x03; - break; - } + // this happens only with the new pa board and using EXT1/EXT2/XVTR + // here we have to disconnect ANT1,2,3 + output_buffer[C4]|=0x03; + break; + } #ifdef DEBUG_PROTO - CHECK(i, CASE2); - CHECK(output_buffer[C4] & 0x03, C4_TX_REL); + CHECK(i, CASE2); + CHECK(output_buffer[C4] & 0x03, C4_TX_REL); #endif - // end of "C0=0" packet - } else { - // - // metis_offset !=8: send the other C&C packets in round-robin - // RX frequency commands are repeated for each RX - switch(command) { - case 1: // tx frequency - output_buffer[C0]=0x02; - long long txFrequency=channel_freq(-1); - output_buffer[C1]=txFrequency>>24; - output_buffer[C2]=txFrequency>>16; - output_buffer[C3]=txFrequency>>8; - output_buffer[C4]=txFrequency; - break; - case 2: // rx frequency - if(current_rx>24; - output_buffer[C2]=rxFrequency>>16; - output_buffer[C3]=rxFrequency>>8; - output_buffer[C4]=rxFrequency; - current_rx++; - } - // if we have reached the last RX channel, wrap around - if(current_rx>=num_hpsdr_receivers) { - current_rx=0; - } - break; - case 3: - { - BAND *band=band_get_current_band(); - int power=0; - - // Some HPSDR apps for the RedPitaya generate CW inside the FPGA, but while - // doing this, DriveLevel changes are processed by the server, but do not become effective. - // If the CW paddle is hit, the new PTT state is sent to piHPSDR, then the TX drive - // is sent the next time "command 3" is performed, but this often is too late and - // CW is generated with zero DriveLevel. - // Therefore, when in CW mode, send the TX drive level also when receiving. - // (it would be sufficient to do so only with internal CW). + // end of "C0=0" packet + } else { // - power=transmitter->drive_level; - if(isTransmitting() || (txmode == modeCWU) || (txmode == modeCWL)) { - if(tune && !transmitter->tune_use_drive) { - double fac=sqrt((double)transmitter->tune_percent * 0.01); - power=(int)((double)transmitter->drive_level*fac); - } /* else { */ - /* power=transmitter->drive_level; */ - /* } */ - - // printf("power: %d\n", power); + // metis_offset !=8: send the other C&C packets in round-robin + // RX frequency commands are repeated for each RX + switch(command) { + case 1: // tx frequency + output_buffer[C0]=0x02; + long long txFrequency=channel_freq(-1); + output_buffer[C1]=txFrequency>>24; + output_buffer[C2]=txFrequency>>16; + output_buffer[C3]=txFrequency>>8; + output_buffer[C4]=txFrequency; + break; + case 2: // rx frequency + if(current_rx>24; + output_buffer[C2]=rxFrequency>>16; + output_buffer[C3]=rxFrequency>>8; + output_buffer[C4]=rxFrequency; + current_rx++; + } + // if we have reached the last RX channel, wrap around + if(current_rx>=num_hpsdr_receivers) { + current_rx=0; + } + break; + case 3: + { + BAND *band=band_get_current_band(); + int power=0; + + // Some HPSDR apps for the RedPitaya generate CW inside the FPGA, but while + // doing this, DriveLevel changes are processed by the server, but do not become effective. + // If the CW paddle is hit, the new PTT state is sent to piHPSDR, then the TX drive + // is sent the next time "command 3" is performed, but this often is too late and + // CW is generated with zero DriveLevel. + // Therefore, when in CW mode, send the TX drive level also when receiving. + // (it would be sufficient to do so only with internal CW). + // + power=transmitter->drive_level; + if(isTransmitting() || (txmode == modeCWU) || (txmode == modeCWL)) { + if(tune && !transmitter->tune_use_drive) { + double fac=sqrt((double)transmitter->tune_percent * 0.01); + power=(int)((double)transmitter->drive_level*fac); + } /* else { */ + /* power=transmitter->drive_level; */ + /* } */ + + // printf("power: %d\n", power); #if 0 - if (device == DEVICE_HERMES_LITE2) { - // - // from the "intended" drive level power, calculate the - // next lower TX attenuation which can be from 0.0 to -7.5 dB - // in 0.5 dB steps, encode the step in a four-bit word and shift - // it to the upper 4 bits. - // we always use the att level that produces a little bit *less* attenuation - // than required, and down-scale the IQ samples in transmitter.c - // - // NOTE: this down-scaling does not occur when connecting a CW key to the HL2 - // and using "internal" CW, because in this case the IQ samples are - // generated in the FPGA. A typical symptom is that the CW signals are - // stronger than the "TUNE" signal, and in the case of very low drive slider - // values they can be *much* stronger. - // - // NOTE: When using predistortion (PURESIGNAL), the IQ scaling must be switched off. - // In this case, the output power can also be stronger than intended. - // - int hl2power; - if (power < 102) { - hl2power=0; // -7.5 dB TX attenuation - } else if (power < 108) { - hl2power=16; // -7.0 dB TX attenuation - } else if (power < 114) { - hl2power=32; // -6.5 dB TX attenuation - } else if (power < 121) { - hl2power=48; // -6.0 dB TX attenuation - } else if (power < 128) { - hl2power=64; // -5.5 dB TX attenuation - } else if (power < 136) { - hl2power=80; // -5.0 dB TX attenuation - } else if (power < 144) { - hl2power=96; // -4.5 dB TX attenuation - } else if (power < 152) { - hl2power=112; // -4.0 dB TX attenuation - } else if (power < 161) { - hl2power=128; // -3.5 dB TX attenuation - } else if (power < 171) { - hl2power=144; // -3.0 dB TX attenuation - } else if (power < 181) { - hl2power=160; // -2.5 dB TX attenuation - } else if (power < 192) { - hl2power=176; // -2.0 dB TX attenuation - } else if (power < 203) { - hl2power=192; // -1.5 dB TX attenuation - } else if (power < 215) { - hl2power=208; // -1.0 dB TX attenuation - } else if (power < 228) { - hl2power=224; // -0.5 dB TX attenuation - } else { - hl2power=240; // no TX attenuation - } - power=hl2power; - } + if (device == DEVICE_HERMES_LITE2) { + // + // from the "intended" drive level power, calculate the + // next lower TX attenuation which can be from 0.0 to -7.5 dB + // in 0.5 dB steps, encode the step in a four-bit word and shift + // it to the upper 4 bits. + // we always use the att level that produces a little bit *less* attenuation + // than required, and down-scale the IQ samples in transmitter.c + // + // NOTE: this down-scaling does not occur when connecting a CW key to the HL2 + // and using "internal" CW, because in this case the IQ samples are + // generated in the FPGA. A typical symptom is that the CW signals are + // stronger than the "TUNE" signal, and in the case of very low drive slider + // values they can be *much* stronger. + // + // NOTE: When using predistortion (PURESIGNAL), the IQ scaling must be switched off. + // In this case, the output power can also be stronger than intended. + // + int hl2power; + if (power < 102) { + hl2power=0; // -7.5 dB TX attenuation + } else if (power < 108) { + hl2power=16; // -7.0 dB TX attenuation + } else if (power < 114) { + hl2power=32; // -6.5 dB TX attenuation + } else if (power < 121) { + hl2power=48; // -6.0 dB TX attenuation + } else if (power < 128) { + hl2power=64; // -5.5 dB TX attenuation + } else if (power < 136) { + hl2power=80; // -5.0 dB TX attenuation + } else if (power < 144) { + hl2power=96; // -4.5 dB TX attenuation + } else if (power < 152) { + hl2power=112; // -4.0 dB TX attenuation + } else if (power < 161) { + hl2power=128; // -3.5 dB TX attenuation + } else if (power < 171) { + hl2power=144; // -3.0 dB TX attenuation + } else if (power < 181) { + hl2power=160; // -2.5 dB TX attenuation + } else if (power < 192) { + hl2power=176; // -2.0 dB TX attenuation + } else if (power < 203) { + hl2power=192; // -1.5 dB TX attenuation + } else if (power < 215) { + hl2power=208; // -1.0 dB TX attenuation + } else if (power < 228) { + hl2power=224; // -0.5 dB TX attenuation + } else { + hl2power=240; // no TX attenuation + } + power=hl2power; + } #endif - } + } - /* if(last_power!=power) { */ - /* int computed_gain = (power >> 5) + ((power + 4) >> 3); */ - /* g_print("power=%d, computed gain = %d\n",power, computed_gain); */ - /* last_power=power; */ - /* } */ + /* if(last_power!=power) { */ + /* int computed_gain = (power >> 5) + ((power + 4) >> 3); */ + /* g_print("power=%d, computed gain = %d\n",power, computed_gain); */ + /* last_power=power; */ + /* } */ - output_buffer[C0]=0x12; /* addr[6:1] = 001001b */ + output_buffer[C0]=0x12; /* addr[6:1] = 001001b */ #ifdef SW_LEVEL_CTRL - // highest power from hardware, but use software scaling to - // scale the level - output_buffer[C1]=255 & 0xFF; + // highest power from hardware, but use software scaling to + // scale the level + output_buffer[C1]=255 & 0xFF; #else - output_buffer[C1]=power & 0xFF; + output_buffer[C1]=power & 0xFF; #endif - output_buffer[C2]=0x00; - output_buffer[C3]=0x00; - output_buffer[C4]=0x00; - if(mic_boost) { - output_buffer[C2]|=0x01; - } - if(mic_linein) { - output_buffer[C2]|=0x02; - } - if(filter_board==APOLLO || device==DEVICE_HERMES_LITE2) { - output_buffer[C2]|=0x2C; - } - if((filter_board==APOLLO) && tune) { - output_buffer[C2]|=0x10; - } - if((device==DEVICE_HERMES_LITE2) && pa_enabled) { - output_buffer[C2]|=0x10; // Enable PA - } - if(band_get_current()==band6) { - output_buffer[C3]=output_buffer[C3]|0x40; // Alex 6M low noise amplifier - } - if(band->disablePA) { - output_buffer[C2]=output_buffer[C2]|0x40; // Manual Filter Selection - output_buffer[C3]=output_buffer[C3]|0x20; // bypass all RX filters - output_buffer[C3]=output_buffer[C3]|0x80; // disable Alex T/R relay - } + output_buffer[C2]=0x00; + output_buffer[C3]=0x00; + output_buffer[C4]=0x00; + if(mic_boost) { + output_buffer[C2]|=0x01; + } + if(mic_linein) { + output_buffer[C2]|=0x02; + } + if(filter_board==APOLLO || device==DEVICE_HERMES_LITE2) { + output_buffer[C2]|=0x2C; + } + if((filter_board==APOLLO) && tune) { + output_buffer[C2]|=0x10; + } + if((device==DEVICE_HERMES_LITE2) && pa_enabled) { + output_buffer[C2]|=0x10; // Enable PA + } + if(band_get_current()==band6) { + output_buffer[C3]=output_buffer[C3]|0x40; // Alex 6M low noise amplifier + } + if(band->disablePA) { + output_buffer[C2]=output_buffer[C2]|0x40; // Manual Filter Selection + output_buffer[C3]=output_buffer[C3]|0x20; // bypass all RX filters + output_buffer[C3]=output_buffer[C3]|0x80; // disable Alex T/R relay + } #ifdef PURESIGNAL - // - // If using PURESIGNAL and a feedback to EXT1, we have to manually activate the RX HPF/BPF - // filters and select "bypass" - // - if (isTransmitting() && transmitter->puresignal && receiver[PS_RX_FEEDBACK]->alex_antenna == 6) { - output_buffer[C2] |= 0x40; // enable manual filter selection - output_buffer[C3] &= 0x80; // preserve ONLY "PA enable" bit and clear all filters including "6m LNA" - output_buffer[C3] |= 0x20; // bypass all RX filters - // - // For "manual" filter selection we also need to select the appropriate TX LPF - // - // We here use the transition frequencies used in Thetis by default. Note the - // P1 firmware has different default transition frequences. - // Even more odd, HERMES routes 15m through the 10/12 LPF, while - // Angelia routes 12m through the 17/15m LPF. - // - long long txFrequency = channel_freq(-1); - if (txFrequency > 35600000L) { // > 10m so use 6m LPF - output_buffer[C4] = 0x10; - } else if (txFrequency > 24000000L) { // > 15m so use 10/12m LPF - output_buffer[C4] = 0x20; - } else if (txFrequency > 16500000L) { // > 20m so use 17/15m LPF - output_buffer[C4] = 0x40; - } else if (txFrequency > 8000000L) { // > 40m so use 30/20m LPF - output_buffer[C4] = 0x01; - } else if (txFrequency > 5000000L) { // > 80m so use 60/40m LPF - output_buffer[C4] = 0x02; - } else if (txFrequency > 2500000L) { // > 160m so use 80m LPF - output_buffer[C4] = 0x04; - } else { // < 2.5 MHz use 160m LPF - output_buffer[C4] = 0x08; - } - } + // + // If using PURESIGNAL and a feedback to EXT1, we have to manually activate the RX HPF/BPF + // filters and select "bypass" + // + if (isTransmitting() && transmitter->puresignal && receiver[PS_RX_FEEDBACK]->alex_antenna == 6) { + output_buffer[C2] |= 0x40; // enable manual filter selection + output_buffer[C3] &= 0x80; // preserve ONLY "PA enable" bit and clear all filters including "6m LNA" + output_buffer[C3] |= 0x20; // bypass all RX filters + // + // For "manual" filter selection we also need to select the appropriate TX LPF + // + // We here use the transition frequencies used in Thetis by default. Note the + // P1 firmware has different default transition frequences. + // Even more odd, HERMES routes 15m through the 10/12 LPF, while + // Angelia routes 12m through the 17/15m LPF. + // + long long txFrequency = channel_freq(-1); + if (txFrequency > 35600000L) { // > 10m so use 6m LPF + output_buffer[C4] = 0x10; + } else if (txFrequency > 24000000L) { // > 15m so use 10/12m LPF + output_buffer[C4] = 0x20; + } else if (txFrequency > 16500000L) { // > 20m so use 17/15m LPF + output_buffer[C4] = 0x40; + } else if (txFrequency > 8000000L) { // > 40m so use 30/20m LPF + output_buffer[C4] = 0x01; + } else if (txFrequency > 5000000L) { // > 80m so use 60/40m LPF + output_buffer[C4] = 0x02; + } else if (txFrequency > 2500000L) { // > 160m so use 80m LPF + output_buffer[C4] = 0x04; + } else { // < 2.5 MHz use 160m LPF + output_buffer[C4] = 0x08; + } + } #endif #ifdef DEBUG_PROTO - CHECK(output_buffer[C1], C1_DRIVE); - CHECK((output_buffer[C2] & 0xE0) >> 5, C2_FB); - CHECK(output_buffer[C3] & 0x1F, C3_HPF); - CHECK((output_buffer[C3] & 0x20) >> 5, C3_BP); - CHECK((output_buffer[C3] & 0x40) >> 6, C3_LNA); - CHECK((output_buffer[C3] & 0x80) >> 7, C3_TXDIS); - CHECK(output_buffer[C4], C4_LPF); + CHECK(output_buffer[C1], C1_DRIVE); + CHECK((output_buffer[C2] & 0xE0) >> 5, C2_FB); + CHECK(output_buffer[C3] & 0x1F, C3_HPF); + CHECK((output_buffer[C3] & 0x20) >> 5, C3_BP); + CHECK((output_buffer[C3] & 0x40) >> 6, C3_LNA); + CHECK((output_buffer[C3] & 0x80) >> 7, C3_TXDIS); + CHECK(output_buffer[C4], C4_LPF); #endif } break; - case 4: - output_buffer[C0]=0x14; - output_buffer[C1]=0x00; - -#ifdef USBOZY - if ((device == DEVICE_OZY) || (device == DEVICE_METIS)) { -#else - if (device == DEVICE_METIS) { -#endif - for(i=0;ipreamp<puresignal) { - output_buffer[C2]|=0x40; - } - output_buffer[C3]=0x00; - output_buffer[C4]=0x00; + case 4: + output_buffer[C0]=0x14; + output_buffer[C1]=0x00; + + if (device == DEVICE_METIS) { + for(i=0;ipreamp<puresignal) { + output_buffer[C2]|=0x40; + } + output_buffer[C3]=0x00; + output_buffer[C4]=0x00; - // upon TX, use transmitter->attenuation - // Usually the firmware takes care of this, but it is no - // harm to do this here as well - if (have_rx_gain) { - // - // HERMESlite has a RXgain value in the range 0-60 that - // is stored in rx_gain_slider. The firmware uses bit 6 - // of C4 to determine this case. - // - //int rxgain = adc_attenuation[active_receiver->adc]+12; // -12..48 to 0..60 - int rxgain = adc[active_receiver->adc].gain+12; // -12..48 to 0..60 - - if (rxgain < 0) rxgain=0; - if (rxgain > 60) rxgain=60; - // encode all 6 bits of RXgain in ATT value and set bit6 - if (isTransmitting()) { - // output_buffer[C4] = 0x40 | (33 - (transmitter->attenuation & 0x1F)); - output_buffer[C4] = 0x40 | (rxgain & 0x3F); - } else { - output_buffer[C4] = 0x40 | (rxgain & 0x3F); - } - } else { - if (isTransmitting()) { - output_buffer[C4]=0x20 | (transmitter->attenuation & 0x1F); - } else { - output_buffer[C4]=0x20 | (adc[0].attenuation & 0x1F); - //output_buffer[C4]=0x20 | ((int)adc[0].gain & 0x1F); - } - } - break; - case 5: - output_buffer[C0]=0x16; - output_buffer[C1]=0x00; - if(n_adc==2) { - // must set bit 5 ("Att enable") all the time - // upon transmitting, use high attenuation, since this is - // the best thing you can do when using DIVERSITY to protect - // the second ADC from strong signals from the auxiliary antenna. - // (ANAN-7000 firmware does this automatically). - if (isTransmitting()) { - output_buffer[C1]=0x3F; - } else { - // if diversity is enabled, use RX1 att value for RX2 - if (diversity_enabled) { - output_buffer[C1]=0x20 | (adc[receiver[0]->adc].attenuation & 0x1F); + // upon TX, use transmitter->attenuation + // Usually the firmware takes care of this, but it is no + // harm to do this here as well + if (have_rx_gain) { + // + // HERMESlite has a RXgain value in the range 0-60 that + // is stored in rx_gain_slider. The firmware uses bit 6 + // of C4 to determine this case. + // + //int rxgain = adc_attenuation[active_receiver->adc]+12; // -12..48 to 0..60 + int rxgain = adc[active_receiver->adc].gain+12; // -12..48 to 0..60 + + if (rxgain < 0) rxgain=0; + if (rxgain > 60) rxgain=60; + // encode all 6 bits of RXgain in ATT value and set bit6 + if (isTransmitting()) { + // output_buffer[C4] = 0x40 | (33 - (transmitter->attenuation & 0x1F)); + output_buffer[C4] = 0x40 | (rxgain & 0x3F); + } else { + output_buffer[C4] = 0x40 | (rxgain & 0x3F); + } } else { - output_buffer[C1]=0x20 | (adc[receiver[1]->adc].attenuation & 0x1F); + if (isTransmitting()) { + output_buffer[C4]=0x20 | (transmitter->attenuation & 0x1F); + } else { + output_buffer[C4]=0x20 | (adc[0].attenuation & 0x1F); + //output_buffer[C4]=0x20 | ((int)adc[0].gain & 0x1F); + } } - } - } - output_buffer[C2]=0x00; // ADC3 attenuator disabled. - if(cw_keys_reversed!=0) { - output_buffer[C2]|=0x40; - } - output_buffer[C3]=cw_keyer_speed | (cw_keyer_mode<<6); - output_buffer[C4]=cw_keyer_weight | (cw_keyer_spacing<<7); - break; - case 6: - // need to add tx attenuation and rx ADC selection - output_buffer[C0]=0x1C; - output_buffer[C1]=0x00; - output_buffer[C2]=0x00; - // if n_adc == 1, there is only a single ADC, so we can leave everything - // set to zero - if (n_adc > 1) { - // set adc of the two RX associated with the two piHPSDR receivers - if (diversity_enabled) { - // use ADC0 for RX1 and ADC1 for RX2 (fixed setting) - output_buffer[C1]|=0x04; - } else { - output_buffer[C1]|=(receiver[0]->adc<<(2*rx1channel)); - output_buffer[C1]|=(receiver[1]->adc<<(2*rx2channel)); + break; + case 5: + output_buffer[C0]=0x16; + output_buffer[C1]=0x00; + if(n_adc==2) { + // must set bit 5 ("Att enable") all the time + // upon transmitting, use high attenuation, since this is + // the best thing you can do when using DIVERSITY to protect + // the second ADC from strong signals from the auxiliary antenna. + // (ANAN-7000 firmware does this automatically). + if (isTransmitting()) { + output_buffer[C1]=0x3F; + } else { + // if diversity is enabled, use RX1 att value for RX2 + if (diversity_enabled) { + output_buffer[C1]=0x20 | (adc[receiver[0]->adc].attenuation & 0x1F); + } else { + output_buffer[C1]=0x20 | (adc[receiver[1]->adc].attenuation & 0x1F); + } + } + } + output_buffer[C2]=0x00; // ADC3 attenuator disabled. + if(cw_keys_reversed!=0) { + output_buffer[C2]|=0x40; + } + output_buffer[C3]=cw_keyer_speed | (cw_keyer_mode<<6); + output_buffer[C4]=cw_keyer_weight | (cw_keyer_spacing<<7); + break; + case 6: + // need to add tx attenuation and rx ADC selection + output_buffer[C0]=0x1C; + output_buffer[C1]=0x00; + output_buffer[C2]=0x00; + // if n_adc == 1, there is only a single ADC, so we can leave everything + // set to zero + if (n_adc > 1) { + // set adc of the two RX associated with the two piHPSDR receivers + if (diversity_enabled) { + // use ADC0 for RX1 and ADC1 for RX2 (fixed setting) + output_buffer[C1]|=0x04; + } else { + output_buffer[C1]|=(receiver[0]->adc<<(2*rx1channel)); + output_buffer[C1]|=(receiver[1]->adc<<(2*rx2channel)); + } + } + output_buffer[C3]=0x00; + output_buffer[C3]|=transmitter->attenuation; // Step attenuator of first ADC, value used when TXing + output_buffer[C4]=0x00; + break; + case 7: + output_buffer[C0]=0x1E; + output_buffer[C1]=0x00; + if((txmode==modeCWU || txmode==modeCWL) && !tune && cw_keyer_internal && !transmitter->twotone) { + output_buffer[C1]|=0x01; + } + output_buffer[C2]=cw_keyer_sidetone_volume; + output_buffer[C3]=cw_keyer_ptt_delay; + output_buffer[C4]=0x00; + break; + case 8: + output_buffer[C0]=0x20; + output_buffer[C1]=(cw_keyer_hang_time>>2) & 0xFF; + output_buffer[C2]=cw_keyer_hang_time & 0x03; + output_buffer[C3]=(cw_keyer_sidetone_frequency>>4) & 0xFF; + output_buffer[C4]=cw_keyer_sidetone_frequency & 0x0F; + break; + case 9: + output_buffer[C0]=0x22; + output_buffer[C1]=(eer_pwm_min>>2) & 0xFF; + output_buffer[C2]=eer_pwm_min & 0x03; + output_buffer[C3]=(eer_pwm_max>>3) & 0xFF; + output_buffer[C4]=eer_pwm_max & 0x03; + break; + case 10: + output_buffer[C0]=0x24; + output_buffer[C1]=0x00; + + if(isTransmitting()) { + output_buffer[C1]|=0x80; // ground RX2 on transmit, bit0-6 are Alex2 filters } + output_buffer[C2]=0x00; + if(receiver[0]->alex_antenna==5) { // XVTR + output_buffer[C2]=0x02; // Alex2 XVTR enable + } + if(transmitter->puresignal) { + output_buffer[C2]|=0x40; // Synchronize RX5 and TX frequency on transmit (ANAN-7000) + } + output_buffer[C3]=0x00; // Alex2 filters + output_buffer[C4]=0x00; // Alex2 filters + break; } - output_buffer[C3]=0x00; - output_buffer[C3]|=transmitter->attenuation; // Step attenuator of first ADC, value used when TXing - output_buffer[C4]=0x00; - break; - case 7: - output_buffer[C0]=0x1E; - output_buffer[C1]=0x00; - if((txmode==modeCWU || txmode==modeCWL) && !tune && cw_keyer_internal && !transmitter->twotone) { - output_buffer[C1]|=0x01; - } - output_buffer[C2]=cw_keyer_sidetone_volume; - output_buffer[C3]=cw_keyer_ptt_delay; - output_buffer[C4]=0x00; - break; - case 8: - output_buffer[C0]=0x20; - output_buffer[C1]=(cw_keyer_hang_time>>2) & 0xFF; - output_buffer[C2]=cw_keyer_hang_time & 0x03; - output_buffer[C3]=(cw_keyer_sidetone_frequency>>4) & 0xFF; - output_buffer[C4]=cw_keyer_sidetone_frequency & 0x0F; - break; - case 9: - output_buffer[C0]=0x22; - output_buffer[C1]=(eer_pwm_min>>2) & 0xFF; - output_buffer[C2]=eer_pwm_min & 0x03; - output_buffer[C3]=(eer_pwm_max>>3) & 0xFF; - output_buffer[C4]=eer_pwm_max & 0x03; - break; - case 10: - output_buffer[C0]=0x24; - output_buffer[C1]=0x00; - - if(isTransmitting()) { - output_buffer[C1]|=0x80; // ground RX2 on transmit, bit0-6 are Alex2 filters - } - output_buffer[C2]=0x00; - if(receiver[0]->alex_antenna==5) { // XVTR - output_buffer[C2]=0x02; // Alex2 XVTR enable - } - if(transmitter->puresignal) { - output_buffer[C2]|=0x40; // Synchronize RX5 and TX frequency on transmit (ANAN-7000) - } - output_buffer[C3]=0x00; // Alex2 filters - output_buffer[C4]=0x00; // Alex2 filters - break; - } - if(current_rx==0) { - command++; - if(command>10) { - command=1; - } - } + if(current_rx==0) { + command++; + if(command>10) { + command=1; + } + } - } + } - // set mox - if (isTransmitting()) { - if(txmode==modeCWU || txmode==modeCWL) { + // set mox + if (isTransmitting()) { + if(txmode==modeCWU || txmode==modeCWL) { // // For "internal" CW, we should not set // the MOX bit, everything is done in the FPGA. @@ -1923,274 +1791,191 @@ void ozy_send_buffer() { // However, if we are doing CAT CW, local CW or tuning/TwoTone, // we must put the SDR into TX mode *here*. // - if(tune || CAT_cw_is_active || !cw_keyer_internal || transmitter->twotone) { - output_buffer[C0]|=0x01; - } - } else { - // not doing CW? always set MOX if transmitting - output_buffer[C0]|=0x01; + if(tune || CAT_cw_is_active || !cw_keyer_internal || transmitter->twotone) { + output_buffer[C0]|=0x01; + } + } else { + // not doing CW? always set MOX if transmitting + output_buffer[C0]|=0x01; + } } - } #ifdef DEBUG_PROTO - CHECK(output_buffer[C0] & 1, PC_PTT); + CHECK(output_buffer[C0] & 1, PC_PTT); /* * ship out line after each complete run */ - if (proto_mod && command == 1) { - log_info("DIS=%d DRIVE=%3d PTT=%d i1=%4d RXout=%d RXant=%d i2=%d TXrel=%d FB=%d BP=%d LNA=%d HPF=%02x LPF=%02x", - C3_TXDIS, C1_DRIVE, PC_PTT, CASE1, C3_RX1_OUT, C3_RX1_ANT, CASE2, C4_TX_REL, - C2_FB, C3_BP, C3_LNA, C3_HPF, C4_LPF); - proto_mod=0; - } + if (proto_mod && command == 1) { + log_info("DIS=%d DRIVE=%3d PTT=%d i1=%4d RXout=%d RXant=%d i2=%d TXrel=%d FB=%d BP=%d LNA=%d HPF=%02x LPF=%02x", + C3_TXDIS, C1_DRIVE, PC_PTT, CASE1, C3_RX1_OUT, C3_RX1_ANT, CASE2, C4_TX_REL, + C2_FB, C3_BP, C3_LNA, C3_HPF, C4_LPF); + proto_mod=0; + } #endif -#ifdef USBOZY -// -// if we have a USB interfaced Ozy device: -// - if (device == DEVICE_OZY) - ozyusb_write(output_buffer,OZY_BUFFER_SIZE); - else -#endif - metis_write(0x02,output_buffer,OZY_BUFFER_SIZE); + metis_write(0x02,output_buffer,OZY_BUFFER_SIZE); - //g_print("C0=%02X C1=%02X C2=%02X C3=%02X C4=%02X\n", - // output_buffer[C0],output_buffer[C1],output_buffer[C2],output_buffer[C3],output_buffer[C4]); + //g_print("C0=%02X C1=%02X C2=%02X C3=%02X C4=%02X\n", + // output_buffer[C0],output_buffer[C1],output_buffer[C2],output_buffer[C3],output_buffer[C4]); } -#ifdef USBOZY -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) { - log_trace("%s: ozy_write timeout for %d bytes",__FUNCTION__,length); - } else { - log_trace("%s: ozy_write for %d bytes returned %d",__FUNCTION__,length,i); - } - } - -/* - -// batch up 4 USB frames (2048 bytes) then do a USB write - switch(usb_buffer_block++) - { - case 0: - default: - memcpy(usb_output_buffer, buffer, length); - break; +static int metis_write(unsigned char ep,unsigned char* buffer,int length) { + int i; - case 1: - memcpy(usb_output_buffer + 512, buffer, length); - break; + // copy the buffer over + for(i=0;i<512;i++) { + metis_buffer[i+metis_offset]=buffer[i]; + } - case 2: - memcpy(usb_output_buffer + 1024, buffer, length); - break; + if(metis_offset==8) { + metis_offset=520; + } else { + metis_buffer[0]=0xEF; + metis_buffer[1]=0xFE; + metis_buffer[2]=0x01; + metis_buffer[3]=ep; + metis_buffer[4]=(send_sequence>>24)&0xFF; + metis_buffer[5]=(send_sequence>>16)&0xFF; + metis_buffer[6]=(send_sequence>>8)&0xFF; + metis_buffer[7]=(send_sequence)&0xFF; - case 3: - memcpy(usb_output_buffer + 1024 + 512, buffer, length); -// 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) - { - 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"); + // + // When using UDP, the buffer will ALWAYS be sent. However, when using TCP, + // we must be able to suppress sending buffers HERE asynchronously + // when we want to sent a METIS start or stop packet. This is so because TCP + // is a byte stream, and data from two sources might end up interleaved + // In order not to confuse the SDR, we increase the sequence number only + // for packets actually sent. + // + if (!suppress_ozy_packet) { + // send the buffer + send_sequence++; + metis_send_buffer(&metis_buffer[0],1032); } - } - - usb_buffer_block = 0; // reset counter - break; - } -*/ -} -#endif - -static int metis_write(unsigned char ep,unsigned char* buffer,int length) { - int i; - - // copy the buffer over - for(i=0;i<512;i++) { - metis_buffer[i+metis_offset]=buffer[i]; - } - - if(metis_offset==8) { - metis_offset=520; - } else { - metis_buffer[0]=0xEF; - metis_buffer[1]=0xFE; - metis_buffer[2]=0x01; - metis_buffer[3]=ep; - metis_buffer[4]=(send_sequence>>24)&0xFF; - metis_buffer[5]=(send_sequence>>16)&0xFF; - metis_buffer[6]=(send_sequence>>8)&0xFF; - metis_buffer[7]=(send_sequence)&0xFF; + metis_offset=8; - // - // When using UDP, the buffer will ALWAYS be sent. However, when using TCP, - // we must be able to suppress sending buffers HERE asynchronously - // when we want to sent a METIS start or stop packet. This is so because TCP - // is a byte stream, and data from two sources might end up interleaved - // In order not to confuse the SDR, we increase the sequence number only - // for packets actually sent. - // - if (!suppress_ozy_packet) { - // send the buffer - send_sequence++; - metis_send_buffer(&metis_buffer[0],1032); } - metis_offset=8; - - } - return length; + return length; } static void metis_restart() { - int i; + int i; - // - // In TCP-ONLY mode, we possibly need to re-connect - // since if we come from a METIS-stop, the server - // has closed the socket. Note that the UDP socket, once - // opened is never closed. - // - if (radio->use_tcp && tcp_socket < 1) open_tcp_socket(); + // + // In TCP-ONLY mode, we possibly need to re-connect + // since if we come from a METIS-stop, the server + // has closed the socket. Note that the UDP socket, once + // opened is never closed. + // + if (radio->use_tcp && tcp_socket < 1) open_tcp_socket(); - // reset metis frame - metis_offset=8; + // reset metis frame + metis_offset=8; - // reset current rx - current_rx=0; + // reset current rx + current_rx=0; - // - // When restarting, clear the IQ and audio samples - // - for(i=8;i= 0) { + // We just have sent a METIS stop in TCP + // Radio will close the TCP connection, therefore we do this as well + tmp=tcp_socket; + tcp_socket=-1; + usleep(100000); // give some time to swallow incoming TCP packets + close(tmp); } - metis_send_buffer(buffer,1032); - // - // Wait a while before resuming sending TX/audio packets. - // This prevents mangling of data from TX/audio and Start/Stop packets. - // - usleep(100000); - suppress_ozy_packet=0; - } - if (command == 0 && tcp_socket >= 0) { - // We just have sent a METIS stop in TCP - // Radio will close the TCP connection, therefore we do this as well - tmp=tcp_socket; - tcp_socket=-1; - usleep(100000); // give some time to swallow incoming TCP packets - close(tmp); - } -#ifdef USBOZY - } -#endif } 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 - // + 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); + //g_print("%s: length=%d\n",__FUNCTION__,length); - if (tcp_socket >= 0) { - if (length != 1032) { - log_error("PROGRAMMING ERROR: TCP LENGTH != 1032"); - exit(-1); - } - if(sendto(tcp_socket,buffer,length,0,NULL, 0) != length) { - perror("sendto socket failed for TCP metis_send_data\n"); - } - } else if (data_socket >= 0) { + if (tcp_socket >= 0) { + if (length != 1032) { + log_error("PROGRAMMING ERROR: TCP LENGTH != 1032"); + exit(-1); + } + if(sendto(tcp_socket,buffer,length,0,NULL, 0) != length) { + perror("sendto socket failed for TCP metis_send_data\n"); + } + } else if (data_socket >= 0) { //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) { - log_error("%s: UDP sendto failed: %d: %s",__FUNCTION__,errno,strerror(errno)); - //perror("sendto socket failed for UDP metis_send_data\n"); + bytes_sent=sendto(data_socket,buffer,length,0,(struct sockaddr*)&data_addr,sizeof(data_addr)); + if(bytes_sent!=length) { + log_error("%s: UDP sendto failed: %d: %s",__FUNCTION__,errno,strerror(errno)); + //perror("sendto socket failed for UDP metis_send_data\n"); + } + } else { + // This should not happen + log_error("METIS send: neither UDP nor TCP socket available!"); + exit(-1); } - } else { - // This should not happen - log_error("METIS send: neither UDP nor TCP socket available!"); - exit(-1); - } } diff --git a/p2_discovery.c b/p2_discovery.c index 6d17efd..2418f43 100644 --- a/p2_discovery.c +++ b/p2_discovery.c @@ -65,8 +65,10 @@ void print_device(int i) { discovered[i].network.interface_name); } -void p2_discovery() { +int p2_discovery() { struct ifaddrs *addrs,*ifa; + int devices = 0; + getifaddrs(&addrs); ifa = addrs; while (ifa) { @@ -89,6 +91,8 @@ void p2_discovery() { for(i=0;i