#include #include #include #include #include #include typedef struct { int ytop; int ybottom; int xleft; int xright; float par1; float par2; } UG_PARMS; #define UG_TOP 0 #define UG_BOTTOM 1 #define UG_LEFT 2 #define UG_RIGHT 3 #define UG_INCREASE_PAR1 4 #define UG_DECREASE_PAR1 5 #define UG_DO_WHATEVER 6 #define MAX_UGBUTT 7 UG_PARMS ug; BUTTONS ugbutt[MAX_UGBUTT]; int ug_old_y1; int ug_old_y2; int ug_old_x1; int ug_old_x2; int users_graph_scro; void make_users_control_graph(void); void userdefined_u(void) { mix1_selfreq[0]=-1; lir_empty_da_device_buffer(); clear_da(); lir_sleep(10000); lir_empty_da_device_buffer(); } void users_eme(void) { // Called each time moon position is updated. // data in degrees is available in: // float moon_az; // float moon_el; } void userdefined_q(void) { // This routine is called when the 'Q' key is pressed // It then sends frequency information to FT1000MP via // serial port ttyS0 [com1] // 4800 baud, 8 bits, no parity, 2 stop bits // This routine written by w3sz char ft2[80]=""; char bb[80]=""; int n; float freqpre; char ft[80]=""; char zro[80]=""; char zr1[80]=""; char ffin[11]=""; char ffout[11]=""; char tenmhz[3]=""; char mhz[3]=""; char tenkhz[3]=""; char hunhz[3]=""; char opcode[3]=""; char hexfin[6]=""; char htenmhz[2]=""; char hmhz[2]=""; char htenkhz[2]=""; char hhunhz[2]=""; int ten; int mh; int khz; int hz; int op; int dtenmhz=0; int dmhz=0; int dtenkhz=0; int dhunhz=0; float freq; float lofreq; int fd1; /* file descriptor for the port */ struct termios options; strcat(bb,"bb"); strcat(zro,"0"); strcat(zr1,"0"); fd1=0; fcntl(fd1,F_SETFL,0); fd1=open("/dev/ttyS0",O_RDWR | O_NOCTTY | O_NDELAY); fcntl(fd1,F_SETFL,0); if (fd1 == -1) { perror("open_port: Unable to open /dev/ttyS0 - "); } else /* set up port parameters */ tcgetattr(fd1,&options); cfsetispeed(&options,B4800); cfsetospeed(&options,B4800); options.c_cflag|= (CLOCAL | CREAD); /* No parity */ options.c_cflag&= ~PARENB; options.c_cflag|= CSTOPB; options.c_cflag&= ~CSIZE; options.c_cflag|= CS8; options.c_oflag &= ~OPOST; tcsetattr(fd1, TCSAFLUSH,&options); /* freqpre=fg.passband_center; freqpre=freqpre*10E6; freq=(mix1_fq_mid[fftx_nx]); freq=freq*10; freq=freq+freqpre-480000; freq=freq*100; The info in mix1_fq_mid[fftx_nx] is only valid when the AFC has locked to a signal. In case AFC is deselected or the AFC failed the data may be incorrect. The number 480000 is ui.sampling_speed/2 and it should be applied only in I/Q mode. */ freq= hwfreq*1000000.0 ; freqpre=1000.0*ug.par2; /* This should be correct always. Linrad looks at the flags and selects the frequency actually in use for conversion to the baseband and adds the bfo offset 'bg.bfo_freq' in ssb mode. Look at the routine 'frequency_readout' in baseb_graph.c. for details. */ // If transverter is used, set par1 to LO frequency and // subtract LO value based on user_parameter 'par1' // par1 is multiplied by 10**8 to give IF freq in desired units //if there is no transverter, set par1 to zero lofreq= ug.par1 * 10E8; freq=freq-lofreq; //Add or subtract to put Linrad and FT1000 on same frequency // 1,000,000 equals 1 kHz; freqpre = 1000*ug.par2, so // ug.par2 is entered directly in Hz for correction freq=freq+freqpre; //test by sending corrected output to file for review /* FILE *Fp2; Fp2=fopen("aatestfile","a+"); fprintf(Fp2,"%f\n",freq); fclose(Fp2); */ // Round up to compensate for truncation freq=freq+5000; //freq=freq*10; // Add leading zeroes as necessary for proper format sprintf(ft,"%11f",freq); if ((freq < 10E10) && (freq >=10E9)) { strcat(zro,zro); strcat(zro,ft); strncpy(ft2,zro,12); } else if (freq < 10E9) { strcat(zro,zro); strcat(zro,zr1); strcat(zro,ft); strncpy(ft2,zro,12); } else { strcat(zro,ft); strncpy(ft2,zro,12); } // parse frequency information to fit FT1000MP // Let's say thefrequency number derived from Linrad is // the integer 0123456789. First of all, the // FT1000MP will only use digits from 10 Hz to 10 MHz. // So we truncate the number to 01234567. The FT1000 // wants its data in form of 4 characters followed // by the opcode '0a'. The 100-MHz digit must be '0'. //The FT1000 expects the frequency data to be in the // equivalent of 4 2-digit chunks, starting with the least // significant two digits. For the number 01234567, // the FT1000 wants to see what in Basic would be // Chr$(67h);Chr$(45h);Chr$(23h);Chr$(01h);Chr$(0Ah); // The tricky thing is that the FT1000 wants // the characters to have their values defined in hex, // as we just showed above. // If we just send the characters whose ascii number // representations are 67,45,23, and 01 out the port, // the descriptors are assumed to be hex, and // converted by the computer to decimal before being // sent. So if we tell the computer to send the // equivalent of chr$(67) the computer sends instead // chr$(43), for example. So even though 67 is // really a decimal, we must pretend that its a hex // value and convert it to its decimal equivalent // [103] and send chr$(103) out the serial port. // For the number 01234567 we need to send: // chr$(103);chr$(69);chr$(35);chr$(01);chr$(10); // where the numbers are given as decimal integers. // That is all this part of the routine does. strncpy(ffin,ft2,10); //Set opcode for FT1000 CAT command 'OAh' = 10 decimal op=10; sprintf(opcode,"%c",op); // end all strings with null character ffout[10] = '\n'; ffout[6] = ffin[1]; ffout[7] = ffin[2]; tenmhz[0] = ffout[6]; tenmhz[1] = ffout[7]; tenmhz[2] = ffout[10]; // Lookup table to convert hex to decimal // FT1000 wants to see chr$ of // of frequency number. i.e., if freq number is 28 // then it wants to see chr$((2*16)+8) or chr$(40) // so all two digit frequency numbers need to be converted // to hex. switch(tenmhz[0]) { case '0': dtenmhz=0; break; case '1': dtenmhz=16; break; case '2': dtenmhz=32; break; case '3': dtenmhz=48; break; case '4': dtenmhz=64; break; case '5': dtenmhz=80; break; case '6': dtenmhz=96; break; case '7': dtenmhz=112; break; case '8': dtenmhz=128; break; case '9': dtenmhz=144; break; default: break; } tenmhz[0]='0'; ten=atoi(tenmhz) + dtenmhz; sprintf(htenmhz,"%c",ten); ffout[4] = ffin[3]; ffout[5] = ffin[4]; mhz[0] = ffout[4]; mhz[1] = ffout[5]; mhz[2] = ffout[10]; switch(mhz[0]) { case '0': dmhz=0; break; case '1': dmhz=16; break; case '2': dmhz=32; break; case '3': dmhz=48; break; case '4': dmhz=64; break; case '5': dmhz=80; break; case '6': dmhz=96; break; case '7': dmhz=112; break; case '8': dmhz=128; break; case '9': dmhz=144; break; default: break; } mhz[0]='0'; mh=atoi(mhz) + dmhz; sprintf(hmhz,"%c",mh); ffout[2] = ffin[5]; ffout[3] = ffin[6]; tenkhz[0] = ffout[2]; tenkhz[1] = ffout[3]; tenkhz[2] = ffout[10]; switch(tenkhz[0]) { case '0': dtenkhz=0; break; case '1': dtenkhz=16; break; case '2': dtenkhz=32; break; case '3': dtenkhz=48; break; case '4': dtenkhz=64; break; case '5': dtenkhz=80; break; case '6': dtenkhz=96; break; case '7': dtenkhz=112; break; case '8': dtenkhz=128; break; case '9': dtenkhz=144; break; default: break; } tenkhz[0]='0'; khz=atoi(tenkhz) + dtenkhz; sprintf(htenkhz,"%c",khz); ffout[0] = ffin[7]; ffout[1] = ffin[8]; hunhz[0] = ffout[0]; hunhz[1] = ffout[1]; hunhz[2] = ffout[10]; switch(hunhz[0]) { case '0': dhunhz=0; break; case '1': dhunhz=16; break; case '2': dhunhz=32; break; case '3': dhunhz=48; break; case '4': dhunhz=64; break; case '5': dhunhz=80; break; case '6': dhunhz=96; break; case '7': dhunhz=112; break; case '8': dhunhz=128; break; case '9': dhunhz=144; break; default: break; } hunhz[0]='0'; hz=atoi(hunhz) + dhunhz; sprintf(hhunhz,"%c",hz); strcat(hexfin,hhunhz); strcat(hexfin,htenkhz); strcat(hexfin,hmhz); strcat(hexfin,htenmhz); strcat(hexfin,opcode); n=write(fd1,hhunhz,1); /*send data to the port */ n=write(fd1,htenkhz,1); /*send data to the port */ n=write(fd1,hmhz,1); /*send data to the port */ n=write(fd1,htenmhz,1); /* send data to the port */ n=write(fd1,opcode,1); /*send data to the port */ return; } //end of w3sz routine // ************ PROTOTYPE ROUTINES FOR USER WINDOWS *************** // User defined windows to allow mouse control. // In case several windows are desired, give them different // numbers (64 and above) and use scro[m].no to decide what to do // in your mouse_on_users_graph routine. #define USERS_GRAPH_TYPE1 64 // Define your parameters in this structure. // Save it to a file and recover it from init_users_control_window(void) void init_users_control_window(void) { char *w3szfile[10]={"aajunkfile"}; FILE *Fp; switch (rx_mode) { case MODE_WCW: *w3szfile="aawcw_file"; break; case MODE_HSMS: *w3szfile="aahsmsfile"; case MODE_QRSS: *w3szfile="aaqrssfile"; break; case MODE_NCW: *w3szfile="aancw_file"; case MODE_SSB: *w3szfile="aassb_file"; break; case MODE_FM: *w3szfile="aafm__file"; case MODE_AM: *w3szfile="aaam__file"; case MODE_TXTEST: *w3szfile="aatxtefile"; case MODE_RX_ADTEST: *w3szfile="aarxadfile"; case MODE_TUNE: *w3szfile="aatunefile"; break; } Fp=fopen(*w3szfile,"r"); if(Fp == NULL) { // Set initial values if there is no file. ug.xleft=0; ug.ytop=0; ug.par1=0.0; ug.par2=0.0; } else { fscanf(Fp,"%d%d%f%f",&ug.xleft,&ug.ytop,&ug.par1,&ug.par2); fclose(Fp); } ug.xright=ug.xleft+25*text_width; ug.ybottom=ug.ytop+3.5*text_height; users_graph_scro=no_of_scro; make_users_control_graph(); no_of_scro++; if(no_of_scro >= MAX_SCRO)lirerr(89); } void users_init_mode(void) { // A switch statement can be used to do different things depending on // the processing mode. switch (rx_mode) { case MODE_WCW: // Open a window to allow mouse control of your own things init_users_control_window(); break; case MODE_HSMS: case MODE_QRSS: break; case MODE_NCW: case MODE_SSB: // Open a window to allow mouse control of your own things init_users_control_window(); break; case MODE_FM: case MODE_AM: case MODE_TXTEST: case MODE_RX_ADTEST: case MODE_TUNE: break; } } void show_user_parms(void) { char s[80]; char *w3szfile[10]={"aajunkfile"}; // Show the user parameters on screen // and issue hardware commands if required. // Use hware_flag to direct calls to control_hware() when cpu time // is available in case whatever you want to do takes too much time // to be done immediately. // Note that mouse control is done in the narrowband processing thread // and that you can not use lir_sleep to wait for hardware response here. hide_mouse(ug.xleft, ug.xright,ug.ytop,ug.ybottom); sprintf(s,"LO(MHz) %10.6f ",ug.par1); lir_pixwrite(ug.xleft+3*text_width,ug.ytop+text_height,s); sprintf(s,"SH (Hz) %10.1f ",ug.par2); lir_pixwrite(ug.xleft+3*text_width,ug.ytop+2*text_height,s); FILE *Fp; switch (rx_mode) { case MODE_WCW: *w3szfile="aawcw_file"; break; case MODE_HSMS: *w3szfile="aahsmsfile"; case MODE_QRSS: *w3szfile="aaqrssfile"; break; case MODE_NCW: *w3szfile="aancw_file"; case MODE_SSB: *w3szfile="aassb_file"; break; case MODE_FM: *w3szfile="aafm__file"; case MODE_AM: *w3szfile="aaam__file"; case MODE_TXTEST: *w3szfile="aatxtefile"; case MODE_RX_ADTEST: *w3szfile="aarxadfile"; case MODE_TUNE: *w3szfile="aatunefile"; break; } Fp=fopen(*w3szfile,"w"); fprintf(Fp,"%d\n%d\n%f\n%f\n",ug.xleft,ug.ytop,ug.par1,ug.par2); fclose(Fp); } void mouse_continue_users_graph(void) { switch (mouse_active_flag-1) { // Move border lines immediately. // for other functions, wait until button is released. // Look in freq_control.c how to move a fixed size window. case UG_TOP: graph_borders((void*)&ug,0); ug.ytop=mouse_y; graph_borders((void*)&ug,15); break; case UG_BOTTOM: graph_borders((void*)&ug,0); ug.ybottom=mouse_y; graph_borders((void*)&ug,15); break; case UG_LEFT: graph_borders((void*)&ug,0); ug.xleft=mouse_x; graph_borders((void*)&ug,15); break; case UG_RIGHT: graph_borders((void*)&ug,0); ug.xright=mouse_x; graph_borders((void*)&ug,15); break; default: goto await_release; } if(leftpressed == BUTTON_RELEASED)goto finish; return; await_release:; if(leftpressed != BUTTON_RELEASED) return; // Assuming the user wants to control hardware we // allow commands only when data is not over the network. if( (ui.network_flag&NET_RX_INPUT) == 0) { switch (mouse_active_flag-1) { case UG_INCREASE_PAR1: ug.par1++; break; case UG_DECREASE_PAR1: ug.par1--; break; case UG_DO_WHATEVER: // Issue hardware commands or fill the screen // with whatever you like. // Use hware_flag to direct calls to control_hware() when cpu time // is available in case whatever you want to do takes too much time // to be done immediately. settextcolor(7); break; default: // This should never happen. lirerr(211053); break; } } finish:; hide_mouse(ug_old_x1,ug_old_x2,ug_old_y1,ug_old_y2); leftpressed=BUTTON_IDLE; mouse_active_flag=0; graph_borders((void*)&ug,0); lir_fillbox(ug_old_x1,ug_old_y1,ug_old_x2-ug_old_x1,ug_old_y2-ug_old_y1,0); make_users_control_graph(); } void new_user_par1(void) { ug.par1=numinput_float_data; pause_thread(THREAD_SCREEN); show_user_parms(); resume_thread(THREAD_SCREEN); } void new_user_par2(void) { ug.par2=numinput_float_data; pause_thread(THREAD_SCREEN); show_user_parms(); resume_thread(THREAD_SCREEN); } void mouse_on_users_graph(void) { int event_no; // First find out is we are on a button or border line. for(event_no=0; event_no= mouse_x && ugbutt[event_no].y1 <= mouse_y && ugbutt[event_no].y2 >= mouse_y) { ug_old_y1=ug.ytop; ug_old_y2=ug.ybottom; ug_old_x1=ug.xleft; ug_old_x2=ug.xright; mouse_active_flag=1+event_no; current_mouse_activity=mouse_continue_users_graph; return; } } // Not button or border. // Prompt the user for par1 or par2 depending on whether the mouse is // in the upper or the lower part of the window. mouse_active_flag=1; numinput_xpix=ug.xleft+11*text_width; if(mouse_x > ug.xleft+2*text_width && mouse_x (ug.ytop+ug.ybottom)/2) { numinput_ypix=ug.ytop+2*text_height; numinput_chars=12; erase_numinput_txt(); numinput_flag=FIXED_FLOAT_PARM; par_from_keyboard_routine=new_user_par2; } else { numinput_ypix=ug.ytop+text_height; numinput_chars=12; erase_numinput_txt(); numinput_flag=FIXED_FLOAT_PARM; par_from_keyboard_routine=new_user_par1; } } //added } else { // If we did not select a numeric input by setting numinput_flag // we have to set mouse_active flag. // Set the routine to mouse_nothing, we just want to // set flags when the mouse button is released. current_mouse_activity=mouse_nothing; mouse_active_flag=1; } // removed } } void make_users_control_graph(void) { pause_thread(THREAD_SCREEN); // Set a negative number here. // In case several windows are desired, give them different // negative numbers and use scro[m].no to decide what to do // in your mouse_on_users_graph routine. scro[users_graph_scro].no=USERS_GRAPH_TYPE1; // These are the coordinates of the border lines. scro[users_graph_scro].x1=ug.xleft; scro[users_graph_scro].x2=ug.xright; scro[users_graph_scro].y1=ug.ytop; scro[users_graph_scro].y2=ug.ybottom; // Each border line is treated as a button. // That is for the mouse to get hold of them so the window can be moved. ugbutt[UG_LEFT].x1=ug.xleft; ugbutt[UG_LEFT].x2=ug.xleft; ugbutt[UG_LEFT].y1=ug.ytop; ugbutt[UG_LEFT].y2=ug.ybottom; ugbutt[UG_RIGHT].x1=ug.xright; ugbutt[UG_RIGHT].x2=ug.xright; ugbutt[UG_RIGHT].y1=ug.ytop; ugbutt[UG_RIGHT].y2=ug.ybottom; ugbutt[UG_TOP].x1=ug.xleft; ugbutt[UG_TOP].x2=ug.xright; ugbutt[UG_TOP].y1=ug.ytop; ugbutt[UG_TOP].y2=ug.ytop; ugbutt[UG_BOTTOM].x1=ug.xleft; ugbutt[UG_BOTTOM].x2=ug.xright; ugbutt[UG_BOTTOM].y1=ug.ybottom; ugbutt[UG_BOTTOM].y2=ug.ybottom; // Draw the border lines graph_borders((void*)&ug,7); settextcolor(7); make_button(ug.xleft+text_width,ug.ybottom-3*text_height/2-2, ugbutt,UG_DECREASE_PAR1,25); make_button(ug.xright-text_width,ug.ybottom-3*text_height/2-2, ugbutt,UG_INCREASE_PAR1,24); make_button(ug.xleft+text_width,ug.ybottom-text_height/2-2, ugbutt,UG_DO_WHATEVER,'A'); show_user_parms(); resume_thread(THREAD_SCREEN); } // ********************************************************** // WSE drive routines // ********************************************************** // The radio hardware may be designed in many different ways. // When the user selects a new frequency there may be several // different hardware units that have to be changed. // The routine supplied here is designed to work with the // RXxxx -> RX70 -> RX10700 -> RX2500 converters. // If you have some other hardware, you may replace or modify these // routines and move them into (w)users_hwaredriver.c // // Associate a number to each frequency band that will // need a separate case in set_hardware_frequency. #define AUDIO_MODE 0 #define RX2500_TO_ANT 1 #define RX10700_TO_ANT 2 #define RX70_TO_ANT 3 #define RX144_TO_ANT 4 #define RXHFA_TO_ANT_1800 5 #define RXHFA_TO_ANT_3500 6 #define RXHFA_TO_ANT_7000 7 #define RXHFA_TO_ANT_10000 8 #define RXHFA_TO_ANT_14000 9 #define MAX_BANDS 10 #define TEST_GROUP_Y1 4 #define TEST_GROUP_Y2 TEST_GROUP_Y1 +10 #define TEST_GROUP_Y3 TEST_GROUP_Y2 +8 char *undefmsg={"Undef"}; char *device_name_rx10700={"RX10700"}; char *device_name_rx70={"RX70"}; char *device_name_rx144={"RX144"}; char *device_name_rxhfa={"RXHFA"}; char *device_name_rxhfa_gain={"Gain(RXHFA)"}; char device_bits[256]; int device_data[256]; unsigned char hware_updates[256]; char *device_name[256]; int hware_retry; int hware_device_no; int hware_data; int hware_bits; int hware_no_of_updates; char hware_outdat; typedef struct { double increment; double lowest; double highest; int direction; int label; } FQ_INFO; FQ_INFO fqinfo[MAX_BANDS]= {0.0 , 0.0 , 0.0 , 1, AUDIO_MODE, 0.025, 1.675, 2.150,-1, RXHFA_TO_ANT_1800, 0.025, 2.500, 2.500, 1, RX2500_TO_ANT, 0.025, 3.475, 3.950,-1, RXHFA_TO_ANT_3500, 0.025, 6.975, 7.450,-1, RXHFA_TO_ANT_7000, 0.025, 9.975, 10.450,-1, RXHFA_TO_ANT_10000, 0.025, 10.675, 10.750,-1, RX10700_TO_ANT, 0.025, 13.975, 14.450,-1, RXHFA_TO_ANT_14000, 0.025, 69.975, 70.450,-1, RX70_TO_ANT, 0.025, 143.975, 145.950,-1, RX144_TO_ANT }; void hware_hand_key(void) { int i; if( ui.parport != 0 && allow_parport) { i=lir_inb(parport_status)&HWARE_MORSE_KEY; if(i==0) { hand_key=TRUE; hware_outdat&=-1-HWARE_RXTX; } else { hand_key=FALSE; hware_outdat|=HWARE_RXTX; } lir_outb(hware_outdat,parport_control); } } void hware_set_rxtx(int state) { if( ui.parport != 0 && allow_parport) { lir_mutex_lock(); if(state == TRUE) { hware_outdat&=-1-HWARE_RXTX; } else { hware_outdat|=HWARE_RXTX; } lir_mutex_unlock(); lir_outb(hware_outdat,parport_control); } } void users_close_devices(void) { // WSE units do not use the parallel port. } void users_open_devices(void) { if(ui.parport == 0) { allow_parport=FALSE; } else { if(lir_parport_permission()==TRUE) { allow_parport=TRUE; } else { allow_parport=FALSE; } } } void hware_interface_test(void) { int i, pardat, j, k, xpos, bits[8]; int cntrldat; char inpins[5]={15,13,12,10,11}; char s[80]; clear_screen(); clear_hware_data(); pardat=0; cntrldat=0; lir_text(3,TEST_GROUP_Y1,"DATA PORT (address, output only)"); lir_text(2,TEST_GROUP_Y1+2,"Enter 0 to 7 for bit to toggle"); lir_text(5,TEST_GROUP_Y1+4,"Bit:"); lir_text(2,TEST_GROUP_Y1+5,"Status:"); lir_text(5,TEST_GROUP_Y1+6,"Pin:"); lir_text(3,TEST_GROUP_Y3,"CONTROL PORT input pins"); lir_text(5,TEST_GROUP_Y3+3,"Bit:"); lir_text(2,TEST_GROUP_Y3+4,"Status:"); lir_text(5,TEST_GROUP_Y3+5,"Pin:"); lir_text(5,TEST_GROUP_Y2,"Enter D to toggle data (pin 17)"); lir_text(5,TEST_GROUP_Y2+1,"Enter C to toggle clock (pin 1)"); goto show; loop:; lir_refresh_screen(); lir_sleep(10000); test_keyboard(); if(kill_all_flag) return; if(lir_inkey != 0) { process_current_lir_inkey(); if(kill_all_flag) return; if(lir_inkey >= '0' && lir_inkey <= '7') { k=1; j=lir_inkey-'0'; while(j != 0) { k<<=1; j--; } pardat^=k; } if(lir_inkey=='D') { cntrldat ^= HWARE_DATA; } if(lir_inkey=='C') { cntrldat ^= HWARE_CLOCK; } show:; j=pardat; k=0; while(k<8) { bits[k]=j&1; if(bits[k] >0)bits[k]=1; j>>=1; k++; } xpos=11; for(k=0; k<8; k++) { sprintf(s,"%1d",k); lir_text(xpos,TEST_GROUP_Y1+4,s); sprintf(s,"%1d",bits[k]); lir_text(xpos,TEST_GROUP_Y1+5,s); sprintf(s,"%1d",k+2); lir_text(xpos,TEST_GROUP_Y1+6,s); xpos+=3; } for(i=0; i<20;i++)s[i]=' '; s[20]=0; lir_text(xpos+5,TEST_GROUP_Y1+5,s); lir_text(xpos+5,TEST_GROUP_Y1+5,device_name[pardat]); s[1]=0; if( (cntrldat&HWARE_DATA) == 0) { s[0]='H'; } else { s[0]='L'; } lir_text(3,TEST_GROUP_Y2+3,"Data="); lir_text(8,TEST_GROUP_Y2+3,s); if( (cntrldat&HWARE_CLOCK) == 0) { s[0]='H'; } else { s[0]='L'; } lir_text(23,TEST_GROUP_Y2+3,"Clock="); lir_text(29,TEST_GROUP_Y2+3,s); lir_outb(pardat,ui.parport); lir_outb(cntrldat,parport_control); } i=lir_inb(parport_status); xpos=11; i >>= 3; j=8; for(k=0; k<5; k++) { settextcolor(7); if( (j & parport_ack) !=0)settextcolor(12); sprintf(s,"%1d",k+3); lir_text(xpos+1,TEST_GROUP_Y3+3,s); sprintf(s,"%1d",i&1); lir_text(xpos+1,TEST_GROUP_Y3+4,s); sprintf(s,"%1d",inpins[k]); lir_text(xpos,TEST_GROUP_Y3+5,s); xpos+=3; i >>= 1; j <<= 1; } settextcolor(7); if(lir_inkey != 'X')goto loop; } void set_rxhfa_data(int band) { if(device_data[RX144] != band) { device_data[RXHFA]=band; device_bits[RXHFA]=5; hware_updates[hware_no_of_updates]=RXHFA; hware_no_of_updates++; } } int set_rx144_data(int stepno) { int i; i=8; while(stepno >= 20) { i>>=1; stepno-=20; } if(device_data[RX144] != i) { device_data[RX144]=i; device_bits[RX144]=4; hware_updates[hware_no_of_updates]=RX144; hware_no_of_updates++; } return stepno; } void set_rx10700_data(int stepno) { int i; i=8; while(stepno != 0) { i>>=1; stepno--; } if(device_data[RX10700] != i) { device_data[RX10700]=i; device_bits[RX10700]=4; hware_updates[hware_no_of_updates]=RX10700; hware_no_of_updates++; } } int set_rx70_data(int stepno) { int i; i=16; while(stepno >= 4) { i>>=1; stepno-=4; } if(device_data[RX70] != i) { device_data[RX70]=i; device_bits[RX70]=5; hware_updates[hware_no_of_updates]=RX70; hware_no_of_updates++; } return stepno; } void set_hardware_rx_gain(int band_no) { // bit0 to bit 2 for amplifier/bypass/-10 dB. // bit0-bit2 = 6 => -10dB // bit0-bit2 = 3 => 0dB // bit0-bit2 = 5 => +10dB // // bit3 for 5 dB attenuator. // bit3 = 0 => -5dB // bit3 = 1 => 0dB int gaindat[6]={6,14,3,11,5,13}; int i; if(ui.rx_addev_no == SDR14_DEVICE_CODE) { fg.gain_increment=10; fg.gain/=10; fg.gain*=10; if(fg.gain > 0)fg.gain=0; if(fg.gain<-30)fg.gain=-30; if(hware_init_flag==0)sdr14_att_counter++; return; } if(ui.rx_addev_no == SDRIQ_DEVICE_CODE) { fg.gain_increment=1; if(fg.gain > 0)fg.gain=0; if(fg.gain<-36)fg.gain=-36; if(hware_init_flag==0)sdr14_att_counter++; return; } if( ui.parport == 0 || !allow_parport)return; switch (fqinfo[band_no].label) { case RXHFA_TO_ANT_1800: case RXHFA_TO_ANT_3500: case RXHFA_TO_ANT_7000: case RXHFA_TO_ANT_10000: case RXHFA_TO_ANT_14000: fg.gain_increment=5; fg.gain/=5; fg.gain*=5; if(fg.gain < -15)fg.gain=-15; if(fg.gain > 10)fg.gain=10; i=fg.gain/5+3; if(device_data[RXHFA_GAIN] != gaindat[i]) { device_data[RXHFA_GAIN]=gaindat[i]; device_bits[RXHFA_GAIN]=4; if(hware_no_of_updates<0)hware_no_of_updates=0; hware_updates[hware_no_of_updates]=RXHFA_GAIN; hware_no_of_updates++; hware_flag=1; hware_time=current_time(); } break; default: break; } } void set_hardware_rx_frequency(void) { float t1; int i, band_no, stepno; if(ui.rx_addev_no == SDR14_DEVICE_CODE || ui.rx_addev_no == SDRIQ_DEVICE_CODE ) { if(hware_init_flag==0)sdr14_nco_counter++; t1=fg.passband_center; fg.passband_direction=1; if(fg.passband_center > SDR14_SAMPLING_CLOCK) { i=fg.passband_center/SDR14_SAMPLING_CLOCK; t1=fg.passband_center-i*SDR14_SAMPLING_CLOCK; } if(t1 > 0.5*SDR14_SAMPLING_CLOCK) { t1=SDR14_SAMPLING_CLOCK-t1; fg.passband_direction=-1; } sdr14_freq=t1*1000000+0.5; fft1_direction=fg.passband_direction; fg.passband_increment=.025; return; } if( ui.parport == 0 || !allow_parport)return; /* // old code before Tx routines........ // First of all, stop any ongoing activities on the parallel port. lir_outb(0,ui.parport); lir_outb(HWARE_CLOCK,parport_control); // Flag unwritten data as not valid while(hware_no_of_updates >= 0) { device_data[hware_updates[hware_no_of_updates]]=-1; hware_no_of_updates--; } */ if(hware_no_of_updates >= 0)lirerr(213763); hware_no_of_updates=0; hware_flag=0; band_no=0; while(band_no < MAX_BANDS-1 && fg.passband_center > fqinfo[band_no].highest)band_no++; if(fg.passband_center < fqinfo[band_no].lowest && band_no > 0) { t1=0.5*(fqinfo[band_no].lowest+fqinfo[band_no-1].highest); if(fg.passband_center < t1)band_no--; } if(fg_old_band != band_no)set_hardware_rx_gain(band_no); fg_old_band=band_no; t1=(fg.passband_center-fqinfo[band_no].lowest)/fqinfo[band_no].increment; stepno=t1+0.5; if(stepno < 0)stepno=0; set_fq:; fg.passband_center=fqinfo[band_no].lowest+stepno*fqinfo[band_no].increment; if(fg.passband_center > fqinfo[band_no].highest+0.0000001) { stepno--; goto set_fq; } fg.passband_increment = fqinfo[band_no].increment; fg.passband_direction = fqinfo[band_no].direction; fft1_direction=fg.passband_direction; // Send a message to the screen thread to redraw the frequency scale // on the main spectrum. sc[SC_WG_FQ_SCALE]++; // Set up data to switch relays to connect units properly. // and to select the correct LO frequency for all units in use. switch (fqinfo[band_no].label) { case AUDIO_MODE: // Send nothing to the hardware, just set frequency // and direction to zero so frequency scale in waterfall and // other graphs gives audio frequency. break; case RX2500_TO_ANT: // Route the signal source to the RX2500 input. break; case RX10700_TO_ANT: // Route RX10700 output to the RX2500 input. // Route the signal source to the RX10700 input. goto set_10700; case RX70_TO_ANT: // Route RX70 output to the RX10700 input. // Route RX10700 output to the RX2500 input. // Route the signal source to the RX10700 input. goto set_70; case RXHFA_TO_ANT_1800: // Route RXHFA output to the RX70 input. // Route RX70 output to the RX10700 input. // Route RX10700 output to the RX2500 input. // Route the signal source to the RXHFA input. set_rxhfa_data(16); goto set_70; case RXHFA_TO_ANT_3500: // Route RXHFA output to the RX70 input. // Route RX70 output to the RX10700 input. // Route RX10700 output to the RX2500 input. // Route the signal source to the RXHFA input. set_rxhfa_data(8); goto set_70; case RXHFA_TO_ANT_7000: // Route RXHFA output to the RX70 input. // Route RX70 output to the RX10700 input. // Route RX10700 output to the RX2500 input. // Route the signal source to the RXHFA input. set_rxhfa_data(4); goto set_70; case RXHFA_TO_ANT_10000: // Route RXHFA output to the RX70 input. // Route RX70 output to the RX10700 input. // Route RX10700 output to the RX2500 input. // Route the signal source to the RXHFA input. set_rxhfa_data(2); goto set_70; case RXHFA_TO_ANT_14000: // Route RXHFA output to the RX70 input. // Route RX70 output to the RX10700 input. // Route RX10700 output to the RX2500 input. // Route the signal source to the RXHFA input. set_rxhfa_data(1); goto set_70; case RX144_TO_ANT: // Route RX144 output to the RX70 input. // Route RX70 output to the RX10700 input. // Route RX10700 output to the RX2500 input. // Route the signal source to the RX10700 input. stepno=set_rx144_data(stepno); set_70:; stepno=set_rx70_data(stepno); set_10700:; set_rx10700_data(stepno); break; } if(hware_no_of_updates != 0) { hware_flag=1; hware_time=current_time(); } else { hware_init_flag=0; hware_no_of_updates=-1; } } void clear_hware_data(void) { int i; // Set -1 in device_data. // A data word is max 31 bit, the sign bit is a flag // saying the data is not valid. for(i=0; i<256; i++) { device_data[i]=-1; device_name[i]=undefmsg; } device_name[RX10700]=device_name_rx10700; device_name[RX70]=device_name_rx70; device_name[RX144]=device_name_rx144; device_name[RXHFA]=device_name_rxhfa; device_name[RXHFA_GAIN]=device_name_rxhfa_gain; hware_init_flag=1; hware_no_of_updates=-1; hware_flag=0; } void control_hware(void) { int err; unsigned char outdat; char s[80]; switch(hware_flag) { case 1: hware_no_of_updates--; if(hware_no_of_updates <0) { lirerr(988342); return; } hware_device_no=hware_updates[hware_no_of_updates]; hware_error_flag=0; hware_data=device_data[hware_device_no]; hware_bits=device_bits[hware_device_no]; // A new unit is selected. // Write the number of this unit to the data port outdat=hware_device_no; lir_outb(outdat,ui.parport); hware_flag=2; // Set clock low and make data the first bit of current output. lir_mutex_lock(); if( (hware_data & 1) == 0) { hware_outdat=HWARE_DATA+HWARE_CLOCK; } else { hware_outdat=HWARE_CLOCK; } lir_outb(hware_outdat,parport_control); lir_mutex_unlock(); break; case 2: // Set clock high to clock in new data bit. lir_mutex_lock(); hware_outdat^=HWARE_CLOCK; lir_outb(hware_outdat,parport_control); lir_mutex_unlock(); hware_flag=3; hware_retry=0; break; case 3: // Read status to see if we really got the data bit into the unit. outdat=lir_inb(parport_status)&parport_ack; outdat^=parport_ack_sign; err=0; if(outdat == 0) { if( (hware_outdat&HWARE_DATA) != 0) { err=1; } } else { if( (hware_outdat&HWARE_DATA) == 0) { err=1; } } hware_retry++; if(err==1) { if(hware_retry<4)return; hware_error_flag=1; } hware_bits--; if(hware_bits == 0) { // No more. Deselect unit. lir_outb(0,ui.parport); hware_flag=4; return; } else { // Set clock low and make data the next bit of current output. hware_data=hware_data>>1; lir_mutex_lock(); if( (hware_data & 1) == 0) { hware_outdat=HWARE_DATA+HWARE_CLOCK; } else { hware_outdat=HWARE_CLOCK; } lir_outb(hware_outdat,parport_control); lir_mutex_unlock(); hware_flag=2; } break; case 4: // Select unit. This time we actually clock the new data // from the shift register into the latch. outdat=hware_device_no; lir_outb(outdat,ui.parport); hware_flag=5; return; case 5: lir_outb(0,ui.parport); if(hware_no_of_updates > 0) { hware_flag=1; } else { hware_flag=0; hware_init_flag=0; hware_no_of_updates=-1; } lir_mutex_lock(); hware_outdat=HWARE_CLOCK; lir_outb(hware_outdat,parport_control); lir_mutex_unlock(); if(hware_error_flag != 0) { sprintf(s,"ERROR: %s",device_name[hware_device_no]); wg_error(s,5); } break; } } // ******************************************************** // End WSE routines // ********************************************************