/*scan.cpp for PLL2002 scanner like RS/PRO-2033, PRO-2030 etc. This program will allow you to connect your DUMB scanner to your computer. Yes, it works with even the dumbest scanners like PRO-2033 10 channel 50 $ scanner. And will allow you to get complete control of the scanners frequency ranges and bands. For now, it only works with the scanners which use PLL2002 PLL chip, and, this includes about 90% of all scanners made by radioshack. This interface can be used like a no parts, no restrictions very low cost all scanner interface which will allow you q00% control of your scanner. You will need atleast the following interface between the computers parallel port and the scanners internal circuitry: - DB25 pins direction PLL2002/scanner Pin2 (D0) IN ------- pin9 on PLL2002 (disconnect the PLL2002 pins from the scanners UP) Pin3 (D1) IN ------- pin10 on PLL2002 (disconnect the PLL2002 pins from the scanners UP) Pin4 (D2) IN ------- pin11 on PLL2002 (disconnect the PLL2002 pins from the scanners UP) pin6 (D4) IN ------- pull-up power, connect a 10 K resistor between pin 6 and pin 13 of the db25 pin7 (d5) IN ------- VHF frontend-select (disconnect this control pins from the scanners UP) pin8 (D6) IN ------- UHF frontend select (disconnect this control pins from the scanners UP) pin9 (D7) IN ------- 800 Mhz frontend select (disconnect this control pins from the scanners UP) pin13 (S4) OUT ------- squelch output, connect a 10 K resistor between pin 6 and pin 13 of the db25 pins 18-25 ground ------- connect one or two of these to scanner ground It is very highly recommended that all these signals into the scanner be buffered by 74LS244 and those signals out of the scanner be buffered by a NPN transistor like 2N3904 As alaways, be very-very careful to not fry your scanners circuitry and LSI chips like PLL2002 etc. PLL2002 control protocol ( reverse engineered from CRO waveforms and logic analyzer dumps ) The PLL 2002 has two registers: R register= This divides the RefOsc to generate the Ref freq which is 4.1666/5 /10 /15 kHz typically This value sets the basic PLL step size N register= This divides the VCO to generate the signal to be compared against the Ref Freq. The value, in conjuction with R sets the frequency the scanner is tuned to. The PLL2002 uses the 3-wire protocol to load values into these registers: pin 9 = CLOCK, this is toggled from low - hi-lo to shift one bit into internal registers pin 10 = DATA, this holds the bit value to be toggled into internal registers with the clock as above pin 11 = ENABLE or LE, this toggled lo-hi-lo to COMPLETE the transfer of the data packet. Toggling this signals the PLL2002 to load the R or N register R packet 16 bits MSB first hold the R Value, 1 Control Bit always signal that it is a R packet, then LE is toggled to complete this pkt N packet 24 bits, MSB first, the first 8 (dummy)bits are always low, the next 8 bits hold the N value, the a 0 control bit signals pkt completion In fact writing the following string to the LPT1 by copy lpt1 programs the PLL2002 to 162550 (Q:WHY ?) 00100100100100102320100100100100102320100100100100102320400010010232010010232010010010232232232010232232010232010010010010232010010010040 usage scan > scan.001 // scans VHF band from 137 to 174 MHZ and logs frequencies found into scan.001 scan 162550 // loads frequency into scanner scan R N // raw mode, allows U to experiment by setting different step sizes etc etc etc. Use borland C++ 3.0 etc to compile this program by: bcc scan.cpp This program is intended ONLY for educational purposes. blah blah blah..... */ #include #include #include #include #include #include void _CType delay (unsigned __Millisecond); #define VHF_STUFF_DATA 0x24 #define UHF_STUFF_DATA 0x25 #define NUM_N_BITS 24 #define NUM_R_BITS 17 #define NUM_CONTROL_BITS 1 #define NUM_STOP_BITS 1 #define VHF_MULTIPLIER 2 #define UHF_MULTIPLIER 3 #define VHF_R_VALUE 0x820 #define UHF_R_VALUE 0x9C0 #define REF_FREQ 10400 #define FIRST_IF 10850 #define SECOND_IF 450 #define LPT1 0x378 #define LPT2 0x278 #define LPT1_INT 0x07 #define LPT2_INT 0x05 #define VHF_LO_EDGE 0x628E // 137.000 MHz #define VHF_HI_EDGE 0x7F76 // 174.000 MHz #define UHF_LO_EDGE 0x7B7C // 406 MHz #define UHF_HI_EDGE 0x9c9c // 512 MHz #define HAM_LO_EDGE 0x6806 // 144 Mhz #define HAM_HI_EDGE 0x6B26 // 148 Mhz #define VHFHI_LO_EDGE 0x6B26 #define VHFHI_HI_EDGE 0x7f76 #define WTHR_LO_EDGE 0x7666 #define WTHR_HI_EDGE 0x7684 #define DATA_PORT(p) (p+0) #define STATUS_PORT(p) (p+1) #define CONTROL_PORT(p) (p+2) #define IS_SQUELCH_OPEN(p) ( (inport(STATUS_PORT(p)) ^ 0x10 ) & 0x10) #define VHF_TUNER_ENABLE 0x20 #define UHF_TUNER_ENABLE 0x40 char zero_byte = 0x30; char zero_byte_clock = 0x31; char one_byte = 0x32; char one_byte_clock = 0x33; char control_byte = 0x40; char one_string = {232}; char zero_string = {010}; char control_string = {040}; /* struct ref_data_t{ short dummy_bit:1=0; short r_val_msd:8; short r_val_lsd:8; short ctl_bit:1=1; }; struct div_data_t{ short stuff_data:8; short n_val_msd:8; short n_val_lsd:8; short ctl_bit:1=0; }; struct pp_data_t { short clock:1; //serial clock out short data:1; //serial data out short enable:1; // serial latch enable short mute:1=0; //maybe used to muto audio to speaker, no effect on LOut short pullup:1=1; //supplies pullup power short vhf:1; short uhf:1; short dummy2:1=0; }; struct pp_status_t{ short dummy:4; short squelch:1; // squelch output from scanner short dummy1:1; short discr:1; // discriminator op , also interrupts the PP short dummy2:1; }; */ struct scan_data_t{ char data_0; char data_1; char data_2; }; struct scan_data_t r_data[19]; struct scan_data_t n_data[26]; int write_scan_data_byte(struct scan_data_t * p_r_data, char scan_data, char band) { if( scan_data == 0) { p_r_data->data_0= (0x30 | (band & 0xf0)); p_r_data->data_1= (0x31 | (band & 0xf0)); p_r_data->data_2= (0x30 | (band & 0xf0)); } else if( scan_data == 1) { p_r_data->data_0= (0x32 | (band & 0xf0)); p_r_data->data_1= (0x33 | (band & 0xf0)); p_r_data->data_2= (0x32 | (band & 0xf0)); } else if( scan_data == 4) { p_r_data->data_0= (0x30 | (band & 0xf0)); p_r_data->data_1= (0x34 | (band & 0xf0)); p_r_data->data_2= (0x30 | (band & 0xf0)); } return 0; } int write_r_data( unsigned short pport, unsigned short UHF_VHF, unsigned short r_latch_data) { int i, current_r_data_byte; char band; if( UHF_VHF == 1) band= 0x40; else band= 0x20; current_r_data_byte= 0; write_scan_data_byte(&(r_data[current_r_data_byte]), 0, band); // dummy current_r_data_byte++; for (i = 0; i< 16; i++) { if( (r_latch_data << i) & 0x8000) { write_scan_data_byte( &(r_data[current_r_data_byte]), 1, band); current_r_data_byte++; } else { write_scan_data_byte( &(r_data[current_r_data_byte]), 0, band); current_r_data_byte++; } } write_scan_data_byte(&(r_data[current_r_data_byte]), 1, band); // control=1 current_r_data_byte++; write_scan_data_byte(&(r_data[current_r_data_byte]), 4, band); // LATCH current_r_data_byte++; char *p_char; for( i=0, p_char= (char*)&r_data; i < sizeof(r_data); i++) { // fprintf( stderr, "%c", p_char[i]); outport( pport, (unsigned short)p_char[i]); } return 0; } int write_n_data( unsigned short pport, unsigned short UHF_VHF, unsigned short n_latch_data) { int i, current_n_data_byte; char band; if( UHF_VHF == 1) band= 0x40; else band= 0x20; current_n_data_byte= 0; for (i = 0; i< 8; i++) { write_scan_data_byte( &(n_data[current_n_data_byte]), 0, band); current_n_data_byte++; } for (i = 0; i< 16; i++) { if( (n_latch_data << i) & 0x8000) { write_scan_data_byte( &(n_data[current_n_data_byte]), 1, band); current_n_data_byte++; } else { write_scan_data_byte( &(n_data[current_n_data_byte]), 0, band); current_n_data_byte++; } } write_scan_data_byte(&(n_data[current_n_data_byte]), 0, band); // CONTROL=0 current_n_data_byte++; write_scan_data_byte(&(n_data[current_n_data_byte]), 4, band); // LATCH current_n_data_byte++; char *p_char; for( i=0, p_char= (char*)&n_data; i < sizeof(n_data); i++) { // fprintf( stderr, "%c", p_char[i]); outport( pport, (unsigned short)p_char[i]); } return 0; } int write_rn_data( unsigned short pport, unsigned short UHF_VHF, unsigned short r_latch_data, unsigned short n_latch_data) { write_r_data( pport, UHF_VHF, r_latch_data); write_n_data( pport, UHF_VHF, n_latch_data); return 0; } int check_squelch(unsigned short port) { unsigned long start_time; unsigned long cur_time; int i; start_time= cur_time= biostime(0, 0L); // while( ((unsigned long)cur_time - (unsigned long)start_time) < 2) for( i = 0; i < 18; i++) { delay(1); cur_time= biostime(0, 0L); if( IS_SQUELCH_OPEN(port)) return 1; } return 0; } int my_delay( unsigned short delay) { unsigned long start_time; unsigned long cur_time; start_time= cur_time= biostime(0, 0L); // fprintf( stderr, "0cur_time=0x%lx, start_time=0x%lx, delay=%x\n", cur_time, start_time, delay); while( (unsigned short)((unsigned long)cur_time - (unsigned long)start_time) < delay) { cur_time= biostime(0, 0L); // fprintf( stderr, "1cur_time=0x%lx, start_time=0x%lx, delay=0x%x\n", cur_time, start_time, delay); if(kbhit()) return 1; } return 0; } int print_frequency( int UHF_VHF, unsigned short n_data, int prompt) { unsigned long freq, l_data; l_data = n_data; if( UHF_VHF) freq= ((l_data * 25)/2) + 10850; else freq= (l_data * 5) + 10850; if( prompt) fprintf( stderr, "scanning freq=%-.6ld, nfound= %-.4d \r", freq, prompt -1); else fprintf( stdout, "%-.6ld\n", freq); return 0; } void main(int argc, char **argv) { int pport= 0x378; unsigned int R_data, N_data= VHF_LO_EDGE; int i, found_this_pass ; int band; unsigned long l_freq, l_ref; if( argc == 1) { fprintf( stderr, "SCANNING VHF BAND , press any key to exit\n"); for( i = 0; i < 100; i ++) { found_this_pass = 0; l_freq= VHF_LO_EDGE; if( l_freq > 406000) { band= 1; N_data = ((l_freq - 10850) * 2) / 25 ; R_data = UHF_R_VALUE; } else { band = 0; N_data = (l_freq - 10850) / 5; R_data = VHF_R_VALUE; } fprintf( stdout, "scan no %d\n", i); for( N_data= VHF_LO_EDGE; N_data < VHF_HI_EDGE ; N_data++) { print_frequency(0, N_data, found_this_pass + 1); //prompt if( kbhit()) { fprintf(stderr, "\nclosing\n"); return ; } write_rn_data( pport, 0, R_data, N_data); if(check_squelch(pport)) { print_frequency( 0, N_data, 0); found_this_pass ++; my_delay(100); // my_delay( 5000); } } } // scan the VHF band 10 times } else if (argc ==2 ) { // tune to that frequency sscanf( argv[1], "%ld", &l_freq); fprintf( stderr, "\nl_freq=%ld\n", l_freq); if( l_freq > 406000) { band= 1; N_data = ((l_freq - 10850) * 2) / 25 ; R_data = UHF_R_VALUE; } else { band = 0; N_data = (l_freq - 10850) / 5; R_data = VHF_R_VALUE; } write_rn_data( pport, band, R_data, N_data ); } else if (argc == 3) { //raw mode sscanf( argv[1], "%ld", &l_freq); sscanf( argv[2], "%ld", &l_ref ); fprintf( stderr, "\nl_freq=%ld, l_ref=%ld\n", l_freq, l_ref); if( l_freq > 406000) { band= 1; N_data = l_freq; R_data = l_ref; } else { band = 0; N_data = l_freq; R_data = l_ref; } N_data = (l_freq - 10850) / 5; write_rn_data( pport, band, R_data, N_data ); } }