/* 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 ------- pullup 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 1or 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
pin11= 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 <file-containing-string> 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 <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <bios.h>
#include <dos.h>
#include <conio.h>
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);
}
}
syntax highlighted by Code2HTML, v. 0.9.1