#include #include #include #include #include "globdef.h" #include "uidef.h" #include "fft1def.h" #include "fft2def.h" #include "fft3def.h" #include "screendef.h" #include "seldef.h" #include "sigdef.h" #include "hwaredef.h" #include "thrdef.h" #include "rusage.h" #include "options.h" extern char netsend_rx_multi_group[]; #define TIMF1_MIN_POSTTIME 0.1 void set_raw_userfreq(void) { net_rxdata_16.userx_freq=-1; net_rxdata_16.userx_no=-1; net_rxdata_18.userx_freq=-1; net_rxdata_18.userx_no=-1; net_rxdata_24.userx_freq=-1; net_rxdata_24.userx_no=-1; } void finish_rx_read(short int *buf) { char *charbuf; int comp_flag; int read_time; int i, j, k, m, ix, nn, mm; float *za, *zb; double dt1; short int *ya, *yb; if(hware_flag != 0) { dt1=current_time(); if(dt1 - hware_time > 0.005) { control_hware(); hware_time=dt1; } } hware_hand_key(); if(disksave_flag < 2) { read_time=ms_since_midnight(); } else { dt1=diskread_time+diskread_block_counter*ad_read_fragments/ui.rx_ad_speed; read_time=dt1/(24*3600); dt1-=24*3600*read_time; read_time=1000*dt1; read_time%=24*3600000; } if( (ui.network_flag & NET_RX_INPUT) != 0) { if(abs(latest_listsend_time-read_time) > 1500) { latest_listsend_time=read_time; net_send_slaves_freq(); } } comp_flag=FALSE; charbuf=(void*)buf; if(disksave_flag == 1) { if( (ui.rx_input_mode&DWORD_INPUT) == 0) { fwrite(buf,1,ad_read_bytes,save_file); } else { comp_flag=TRUE; compress_rawdat(); fwrite(rawsave_tmp,1,save_rw_bytes,save_file); } } set_raw_userfreq(); // ******************* SEND RAW16 ***************************** if( (ui.network_flag & NET_RXOUT_RAW16) != 0) { net_rxdata_16.time=read_time; net_rxdata_16.passband_center=fg.passband_center; net_rxdata_16.passband_direction=fg.passband_direction; j=0; if( (ui.rx_input_mode&DWORD_INPUT) == 0) { while(j < (int)ad_read_bytes) { net_rxdata_16.buf[netsend_ptr_16 ]=charbuf[j ]; net_rxdata_16.buf[netsend_ptr_16+1]=charbuf[j+1]; netsend_ptr_16+=2; j+=2; if(netsend_ptr_16 >= NET_MULTICAST_PAYLOAD) { raw16_blknum++; net_rxdata_16.block_no=raw16_blknum; net_rxdata_16.ptr=next_blkptr_16; lir_send_raw16(); next_blkptr_16=j; if(next_blkptr_16 >= ad_read_bytes)next_blkptr_16=0; netsend_ptr_16=0; } } } else { while(j < (int)ad_read_bytes) { net_rxdata_16.buf[netsend_ptr_16 ]=charbuf[j+2]; net_rxdata_16.buf[netsend_ptr_16+1]=charbuf[j+3]; netsend_ptr_16+=2; j+=4; if(netsend_ptr_16 >= NET_MULTICAST_PAYLOAD) { raw16_blknum++; net_rxdata_16.block_no=raw16_blknum; net_rxdata_16.ptr=next_blkptr_16; lir_send_raw16(); next_blkptr_16=j/2; if(next_blkptr_16 >= ad_read_bytes/2)next_blkptr_16=0; netsend_ptr_16=0; } } } } // ******************* SEND RAW18 ***************************** if( (ui.network_flag & NET_RXOUT_RAW18) != 0) { if(comp_flag == FALSE) { compress_rawdat(); } net_rxdata_18.time=read_time; net_rxdata_18.passband_center=fg.passband_center; net_rxdata_18.passband_direction=fg.passband_direction; j=0; while(j < (int)save_rw_bytes) { net_rxdata_18.buf[netsend_ptr_18]=rawsave_tmp[j]; netsend_ptr_18++; j++; if(netsend_ptr_18 >= NET_MULTICAST_PAYLOAD) { raw18_blknum++; net_rxdata_18.block_no=raw18_blknum; net_rxdata_18.ptr=next_blkptr_18; lir_send_raw18(); next_blkptr_18=j; if( next_blkptr_18 >= save_rw_bytes)next_blkptr_18=0; netsend_ptr_18=0; } } } // ******************* SEND RAW24 ***************************** if( (ui.network_flag & NET_RXOUT_RAW24) != 0) { net_rxdata_24.time=read_time; net_rxdata_24.passband_center=fg.passband_center; net_rxdata_24.passband_direction=fg.passband_direction; j=0; while(j < (int)ad_read_bytes) { net_rxdata_24.buf[netsend_ptr_24 ]=charbuf[j+1]; net_rxdata_24.buf[netsend_ptr_24+1]=charbuf[j+2]; net_rxdata_24.buf[netsend_ptr_24+2]=charbuf[j+3]; netsend_ptr_24+=3; j+=4; if(netsend_ptr_24 >= NET_MULTICAST_PAYLOAD) { raw24_blknum++; net_rxdata_24.block_no=raw24_blknum; net_rxdata_24.ptr=next_blkptr_24; lir_send_raw24(); next_blkptr_24=j; if( next_blkptr_24 >= ad_read_bytes)next_blkptr_24=0; netsend_ptr_24=0; } } } if( (ui.network_flag&NET_RXOUT_FFT1) != 0) { // It is important for slow computers that may be connected via the // network that we distribute packets evenly in time. // The fft1 transform may be very large and it could arrive at a rate // of 25 Hz or even lower. // The A/D interrupt rate is high when we send fft1 transforms. // (see buf.c) // It may be different if input is from the network or from the // hard disk. mm=ad_read_bytes/(1-fft1_interleave_ratio); if( (ui.rx_input_mode&DWORD_INPUT) == 0)mm*=2; k=(fft1net_pa-fft1net_px+fft1net_size)&fft1net_mask; if( k > mm+fft1_blockbytes) { mm+=ad_read_bytes/2; } if( k < 1.5*mm) { mm-=ad_read_bytes/2; } mm&=-4; if( k > mm) { net_rxdata_fft1.time=read_time; net_rxdata_fft1.passband_center=fg.passband_center; net_rxdata_fft1.passband_direction=fg.passband_direction; j=0; while(j < mm) { net_rxdata_fft1.buf[netsend_ptr_fft1 ]=fft1_netsend_buffer[fft1net_px ]; net_rxdata_fft1.buf[netsend_ptr_fft1+1]=fft1_netsend_buffer[fft1net_px+1]; net_rxdata_fft1.buf[netsend_ptr_fft1+2]=fft1_netsend_buffer[fft1net_px+2]; net_rxdata_fft1.buf[netsend_ptr_fft1+3]=fft1_netsend_buffer[fft1net_px+3]; netsend_ptr_fft1+=4; j+=4; fft1net_px=(fft1net_px+4)&fft1net_mask; if(netsend_ptr_fft1 >= NET_MULTICAST_PAYLOAD) { fft1_blknum++; net_rxdata_fft1.block_no=fft1_blknum; net_rxdata_fft1.ptr=next_blkptr_fft1; lir_send_fft1(); next_blkptr_fft1=fft1net_px&(fft1_blockbytes-1); netsend_ptr_fft1=0; } } } } if(genparm[SECOND_FFT_ENABLE] != 0) { // ******************* SEND TIMF2 ***************************** if( (ui.network_flag & NET_RXOUT_TIMF2) ) { net_rxdata_timf2.time=read_time; net_rxdata_timf2.passband_center=fg.passband_center; net_rxdata_timf2.passband_direction=fg.passband_direction; // Set userx_freq to sampling speed. net_rxdata_timf2.userx_freq=timf1_sampling_speed; j=0; mm=((timf2_pn2-timf2_pt+timf2_totbytes)&timf2_mask); if(mm>(timf2_mask>>1))mm=0; mm*=2; if( mm <= ad_read_bytes) { mm=0; } else { if( mm > 4*ad_read_bytes) { mm=1.25*ad_read_bytes; } else { mm=ad_read_bytes; } } if( (ui.rx_input_mode&DWORD_INPUT) == 0)mm*=2; if(swfloat) { // Set userx_no to the number of receiver RF channels with // the sign negative to indicate float format. net_rxdata_timf2.userx_no=-ui.rx_rf_channels; mm*=2; while(j < mm) { za=(void*)&net_rxdata_timf2.buf[netsend_ptr_timf2]; zb=&timf2_float[timf2_pt]; for(nn=0; nn= NET_MULTICAST_PAYLOAD) { timf2_blknum++; net_rxdata_timf2.block_no=timf2_blknum; net_rxdata_timf2.ptr=next_blkptr_timf2; lir_send_timf2(); next_blkptr_timf2=j/2; if(next_blkptr_timf2 >= ad_read_bytes/2)next_blkptr_timf2=0; netsend_ptr_timf2=0; } } } else { // Set userx_no to the number of receiver RF channels. net_rxdata_timf2.userx_no=ui.rx_rf_channels; while(j < mm) { ya=(void*)(&net_rxdata_timf2.buf[netsend_ptr_timf2]); yb=(void*)(&timf2_shi[timf2_pt]); for(nn=0; nn= NET_MULTICAST_PAYLOAD) { timf2_blknum++; net_rxdata_timf2.block_no=timf2_blknum; net_rxdata_timf2.ptr=next_blkptr_timf2; lir_send_timf2(); next_blkptr_timf2=j; if(next_blkptr_timf2 >= ad_read_bytes)next_blkptr_timf2=0; netsend_ptr_timf2=0; } } } } // ******************* SEND FFT2 ***************************** if( (ui.network_flag & NET_RXOUT_FFT2) ) { // It is important for slow computers that may be connected via the // network that we distribute packets evenly in time. // The fft2 transform may be very large and it could arrive at a rate // of 1 Hz or even lower. // It may be different if input is from the network or from the // hard disk. mm=1.1*ad_read_bytes/(1-fft2_interleave_ratio); m=mm; if( (ui.rx_input_mode&DWORD_INPUT) != 0)mm/=2; k=(fft2_pa-fft2_pt+fft2_totbytes)&fft2_mask; if( k > mm+fft2_blockbytes) { mm+=m/2; } if( k < 1.5*mm) { mm-=m/2; } mm&=-4; if( k > mm) { net_rxdata_fft2.time=read_time; net_rxdata_fft2.passband_center=fg.passband_center; net_rxdata_fft2.passband_direction=fg.passband_direction; j=0; if(fft_cntrl[FFT2_CURMODE].mmx == 0) { mm*=2; charbuf=(void*)(fft2_float); while(j < mm) { net_rxdata_fft2.buf[netsend_ptr_fft2 ]=charbuf[4*fft2_pt ]; net_rxdata_fft2.buf[netsend_ptr_fft2+1]=charbuf[4*fft2_pt+1]; net_rxdata_fft2.buf[netsend_ptr_fft2+2]=charbuf[4*fft2_pt+2]; net_rxdata_fft2.buf[netsend_ptr_fft2+3]=charbuf[4*fft2_pt+3]; netsend_ptr_fft2+=4; j+=4; fft2_pt=(fft2_pt+1)&fft2_mask; if(netsend_ptr_fft2 >= NET_MULTICAST_PAYLOAD) { fft2_blknum++; if( (fft2_blknum&1) == 0) { // If fft2_blknum is even, send these things: // Set userx_no to the number of receiver RF channels with // the sign negative to indicate float format. net_rxdata_fft2.userx_no=-ui.rx_rf_channels; // Set userx_freq to sampling speed. net_rxdata_fft2.userx_freq=timf1_sampling_speed; } else { // If fft2_blknum is odd, send these things: net_rxdata_fft2.userx_no=fft2_n; net_rxdata_fft2.userx_freq=genparm[SECOND_FFT_SINPOW]; } net_rxdata_fft2.block_no=fft2_blknum; net_rxdata_fft2.ptr=next_blkptr_fft2; lir_send_fft2(); next_blkptr_fft2=fft2_pt&(fft2_blockbytes-1); netsend_ptr_fft2=0; } } } else { charbuf=(void*)(fft2_short_int); while(j < mm) { net_rxdata_fft2.buf[netsend_ptr_fft2 ]=charbuf[2*fft2_pt ]; net_rxdata_fft2.buf[netsend_ptr_fft2+1]=charbuf[2*fft2_pt+1]; netsend_ptr_fft2+=2; j+=2; fft2_pt=(fft2_pt+1)&fft2_mask; if(netsend_ptr_fft2 >= NET_MULTICAST_PAYLOAD) { fft2_blknum++; if( (fft2_blknum&1) == 0) { // If fft2_blknum is even, send these things: // Set userx_no to the number of receiver RF channels. net_rxdata_fft2.userx_no=ui.rx_rf_channels; // Set userx_freq to sampling speed. net_rxdata_fft2.userx_freq=timf1_sampling_speed; } else { // If fft2_blknum is odd, send these things: net_rxdata_fft2.userx_no=fft2_n; net_rxdata_fft2.userx_freq=genparm[SECOND_FFT_SINPOW]; } net_rxdata_fft2.block_no=fft2_blknum; net_rxdata_fft2.ptr=next_blkptr_fft2; lir_send_fft2(); next_blkptr_fft2=fft2_pt&(fft2_blockbytes-1); netsend_ptr_fft2=0; } } } } } } if(ampinfo_flag != 0) { if(rxin_local_workload_reset != workload_reset_flag) { rxin_local_workload_reset = workload_reset_flag; for(i=0; i ad_maxamp[j])ad_maxamp[j]=ix; } } } else { for(i=0; i ad_maxamp[j])ad_maxamp[j]=ix; } } } } // Increment the bufin semaphore in case there is enough // data for fft1 to make at least one transform. // This may be incorrect because the px pointer may have been // updated already by the fft1 thread. This will not happen often // and it is harmless. It will just awake the fft1 thread to // make it find it does not have enough data. while( ((timf1p_pa-rxinput_local_px+timf1_bytes)&timf1_bytemask) > timf1_usebytes) { rxinput_local_px=(rxinput_local_px+timf1_blockbytes)&timf1_bytemask; lir_sem_post(SEM_TIMF1); rxinput_posttime=0; rxin_block_counter++; } // Make sure we do not post to SEM_TIMF1 with larger time // intervals than TIMF1_MIN_POSTTIME seconds rxinput_posttime+=1/TIMF1_MIN_POSTTIME; if( rxinput_posttime > interrupt_rate) { lir_sem_post(SEM_TIMF1); rxinput_posttime=0; rxin_block_counter++; } } void rx_file_input(void) { fpos_t pos; int i, j, k; char *ch; double dt1, read_start_time, ideal_block_count; double total_time1, total_time2; float t2; #if (RUSAGE_OLD == 1) int wlcnt,wlcnt_max; int local_reset; float t1,t3; double cpu_time1; double cpu_time2; wlcnt_max=4*ui.rx_ad_speed/ad_read_fragments; cpu_time1=lir_get_cpu_time(); wlcnt=wlcnt_max; local_reset=workload_reset_flag; #endif i=0; if(savefile_repeat_flag == 1)fgetpos(save_file,&pos); total_time1=current_time(); read_start_time=total_time1; diskread_timer=current_time(); total_time2=current_time(); diskread_block_counter=0; thread_status_flag[THREAD_RX_FILE_INPUT]=THRFLAG_ACTIVE; while(thread_command_flag[THREAD_RX_FILE_INPUT] == THRFLAG_ACTIVE) { #if (RUSAGE_OLD==1) wlcnt--; if(wlcnt==0) { wlcnt=wlcnt_max; total_time2=current_time(); cpu_time2=lir_get_cpu_time(); t3=100/(total_time2-total_time1); t1=(cpu_time2-cpu_time1)*t3; if(t1<0)t1=0; workloads[THREAD_RX_FILE_INPUT]=t1; if(local_reset != workload_reset_flag) { local_reset=workload_reset_flag; total_time1=total_time2; cpu_time1=cpu_time2; } } #endif if(audio_dump_flag != 0) { lir_sched_yield(); while( ((timf1p_pa+(ad_read_bytes<<1)-timf1p_px+timf1_bytes)& timf1_bytemask) > timf1_bytes-(ad_read_bytes<<1) ) { lir_sleep(5000); } lir_sem_post(SEM_SCREEN); ideal_block_count=diskread_block_counter-0.4; dt1=ideal_block_count/interrupt_rate; read_start_time=current_time()-dt1; } else { if(diskread_block_counter > interrupt_rate) { lir_sem_post(SEM_SCREEN); total_time2=current_time(); dt1=total_time2-read_start_time; ideal_block_count=dt1*interrupt_rate; t2=diskread_block_counter-ideal_block_count-0.6; if(t2 >0) { t2/=interrupt_rate; lir_sleep(1000000*t2); } total_time2=current_time(); dt1=total_time2-read_start_time; measured_ad_speed=diskread_block_counter*(ad_read_fragments/dt1); } } diskread_block_counter++; if(diskread_pause_flag !=0 ) { lir_sleep(100000); goto skip_read; } if( disksave_flag == 4)goto end_savfile; if( (ui.rx_input_mode&DWORD_INPUT) == 0) { rxin_isho=(void*)(&timf1_char[timf1p_pa]); timf1p_pa=(timf1p_pa+ad_read_bytes)&timf1_bytemask; if( (ui.rx_input_mode&BYTE_INPUT) != 0) { ch=(void*)rxin_isho; j=ad_read_bytes>>1; k=j; i=fread(rxin_isho,1,j,save_file); while(j > 0) { j--; rxin_isho[j]=(ch[j]+128)<<8; } if(i != k) { i*=2; goto end_savfile; } } else { i=fread(rxin_isho,1,ad_read_bytes,save_file); if(i != ad_read_bytes)goto end_savfile; } } else { if( (ui.rx_input_mode&BYTE_INPUT) != 0) { // Read 24 bit wav files here. rxin_isho=(void*)(&timf1_char[timf1p_pa]); timf1p_pa=(timf1p_pa+ad_read_bytes)&timf1_bytemask; ch=(void*)rxin_isho; j=3*(ad_read_bytes>>2); k=j; i=fread(rxin_isho,1,j,save_file); j/=3; while(j > 0) { j--; ch[4*j+3]=ch[3*j+2]; ch[4*j+2]=ch[3*j+1]; ch[4*j+1]=ch[3*j ]; ch[4*j ]=0; } if(i != k) { i*=4; i/=3; goto end_savfile; } } else { i=fread(rawsave_tmp,1,save_rw_bytes,save_file); expand_rawdat(); rxin_isho=(void*)(&timf1_char[timf1p_pa]); timf1p_pa=(timf1p_pa+ad_read_bytes)&timf1_bytemask; if(i != save_rw_bytes) { end_savfile:; if(savefile_repeat_flag == 1) { fsetpos(save_file,&pos); total_time1=current_time(); read_start_time=total_time1; diskread_timer=current_time(); diskread_block_counter=0; } else { if(disksave_flag == 2) { diskread_block_counter=2; disksave_flag=4; } if( (disksave_flag & 4) != 0) { if(diskread_block_counter/interrupt_rate >= total_wttim) { disksave_flag=8; goto end_file_rxin; } } } // Clear the 200 last bytes. WAV files contain big numbers // appended to the signal data in the file that create huge pulses k=(timf1p_pa-ad_read_bytes-200+i+timf1_bytes)&timf1_bytemask; while(k != timf1p_pa) { timf1_char[k]=0; k=(k+1)&timf1_bytemask; } } } } finish_rx_read(rxin_isho); if(kill_all_flag) goto file_rxin_error_exit; skip_read:; } end_file_rxin:; file_rxin_error_exit:; thread_status_flag[THREAD_RX_FILE_INPUT]=THRFLAG_RETURNED; while(thread_command_flag[THREAD_RX_FILE_INPUT] != THRFLAG_NOT_ACTIVE) { lir_sleep(1000); } }