]> git.rkrishnan.org Git - dttsp.git/blob - pyhw2/hardware.c
New hardware control code
[dttsp.git] / pyhw2 / hardware.c
1 // hardware.c
2 // version 2
3
4 #include <hardware.h>
5
6 // Register memory for IC11
7 int ic11_memory;                
8
9 // Register memory for IC7
10 int ic7_memory;         
11
12 BOOL rfe_enabled;               // True if RFE board is enabled
13 BOOL xvtr_enabled;              // Transverter is enabled
14 BOOL pa_enabled;                // Transverter is enabled
15
16 // Latch Memories
17 BandSetting band_relay  = bs0;
18 int external_output     = 0;
19 int mute_relay          = 0;
20 int transmit_relay      = 0;
21 int gain_relay          = 0;
22 int latch_delay         = 0;    // measured in 100ns steps (10 = 1us)
23
24 // DDS Clock properties
25 double dds_clock                = 0.0;  // DDS Clock oscillator in MHz
26 int pll_mult                    = 0;    // DDS PLL multiplier
27 double dds_clock_correction     = 0.0;  // Oscillator dds_clock_correction in MHz
28 double sysClock                 = 0.0;  // DDS Internal System Clock in MHz
29 int ioud_clock                  = 0;    // IO Update clock period
30 ushort dac_mult                 = 0;    // DAC Multiplier setting
31
32 // DDS Frequency Control properties
33 double dds_freq         = 0.0;  // Last VFO Setting in MHz
34 double if_freq          = 0.0;  // IF Frequency Offset in MHz
35 BOOL if_shift           = FALSE;// Turns Offset Baseband IF Shift On
36 BOOL spur_reduction     = FALSE;// Eliminates Phase Truncation Spurs
37 double dds_step_size    = 0.0;  // DDS Step in MHz for spur removal
38 int sample_rate         = 0;    // ADC Sampling Rate in Hz
39 int fft_length          = 0;    // Length of FFT in bins
40 double FFT_Bin_Size     = 0.0;  // Bandwidth of FFT bin
41 int tune_fft            = 0;    // Offset tuning of FFT bins
42 double tune_frac_rel    = 0.0;  // In relative frequency (frequency/m_Sample_Rate)
43 double vfo_offset       = 0.0;
44 //double last_VFO       = 0.0;  // temp store for last VFO frequency
45
46 double min_freq = 0.012;        // minimum allowable tuning frequency
47 double max_freq = 65.0;         // maximum allowable tuning frequency
48
49 // PIO register base address
50 u_short baseAdr = 0x378;
51
52 // Current Bandplan
53 BandPlan curBandPlan = IARU1;
54
55 double TWO_TO_THE_48_DIVIDED_BY_200 = 1407374883553.28;
56 long last_tuning_word = 0;
57 // private Mutex parallel_mutex = new Mutex();
58 // private Mutex dataline_mutex = new Mutex();
59
60 BOOL usb_enabled = FALSE;
61
62 //------------------------------------------------------------------------
63
64 PRIVATE int parportfd = -1;
65
66 PUBLIC BOOL openPort(char *port) {
67   int mode = IEEE1284_MODE_COMPAT;
68   if (!port) port = "/dev/parport0";
69   if ((parportfd = open(port, O_RDWR)) < 0) {
70     perror("open parallel port");
71     return FALSE;
72   }
73   ioctl(parportfd, PPCLAIM);
74   ioctl(parportfd, PPSETMODE, &mode);
75   return TRUE;
76 }
77   
78 PUBLIC void closePort(void) {
79   ioctl(parportfd, PPRELEASE);
80   close(parportfd);
81 }
82
83 double DttSP_SampleRate = 48000.0;
84
85 PUBLIC void USB_Sdr1kLatch(int l, BYTE b) {}
86 PUBLIC BYTE USB_Sdr1kGetStatusPort(void) { return 0; }
87 PUBLIC int  USB_Sdr1kGetADC(void) { return 0; }
88 PUBLIC void USB_Sdr1kDDSReset(void) {}
89 PUBLIC void USB_Sdr1kDDSWrite(BYTE addr, BYTE data) {}
90 PUBLIC void USB_Sdr1kSRLoad(BYTE reg, BYTE data) {}
91 PUBLIC void DttSP_ChangeOsc(double val) {}
92
93 PRIVATE void Delay(void) {
94   usleep(1000 * latch_delay);
95 }
96
97 PRIVATE void Sleep(int ms) {
98   usleep(1000 * ms);
99 }
100
101 PRIVATE void PWrite(BYTE data) {
102   //Write data Byte to parallel port
103   ioctl(parportfd, PPWDATA, &data);
104   //Delay to allow data line setup
105   Delay();
106 }
107
108 PRIVATE void Latch(CtrlPin vCtrlPin) {
109   //Strobe the specified pin to latch data
110   unsigned char mask;
111   switch (vCtrlPin) {
112   case EXT:
113     mask = 0xA, ioctl(parportfd, PPWCONTROL, &mask);
114     Delay();
115     mask = 0xB, ioctl(parportfd, PPWCONTROL, &mask);
116     break;
117   case BPF:
118     mask = 0x9, ioctl(parportfd, PPWCONTROL, &mask);
119     Delay();
120     mask = 0xB, ioctl(parportfd, PPWCONTROL, &mask);
121     break;
122   case DAT:
123     mask = 0xF, ioctl(parportfd, PPWCONTROL, &mask);
124     Delay();
125     mask = 0xB, ioctl(parportfd, PPWCONTROL, &mask);
126     break;
127   case ADR:
128     mask = 0x3, ioctl(parportfd, PPWCONTROL, &mask);
129     Delay();
130     mask = 0xB, ioctl(parportfd, PPWCONTROL, &mask);
131     break;
132   }
133 }
134
135 PRIVATE void ResetLatches(void) {
136   //Set all latch outputs to logic zero (relays off)
137   if (usb_enabled) {
138     gain_relay = GAIN;
139     external_output = 0;
140     USB_Sdr1kLatch(SDR1K_LATCH_EXT, (BYTE) (external_output + gain_relay));
141     setBandRelay(bsnone);
142     transmit_relay = 0;
143     mute_relay = MUTE;
144     USB_Sdr1kLatch(SDR1K_LATCH_BPF, (BYTE) (band_relay + transmit_relay + mute_relay));
145   } else {
146     PWrite(0);
147     Latch(ADR);
148     Latch(DAT);
149     gain_relay = GAIN;
150     external_output = 0;
151     PWrite((BYTE) (external_output + gain_relay));
152     Latch(EXT);
153     setBandRelay(bsnone);
154     transmit_relay = 0;
155     mute_relay = MUTE;
156     PWrite((BYTE) (band_relay + transmit_relay + mute_relay));
157     Latch(BPF);
158   }                     
159 }
160
161 PRIVATE void DDSWrite(BYTE data, BYTE addr) {
162   if (usb_enabled)
163     USB_Sdr1kDDSWrite(addr, data);
164   else {
165     PWrite(data);
166     Latch(DAT);
167     PWrite((BYTE) (addr + WRB));
168     Latch(ADR);
169     PWrite(addr);
170     Latch(ADR);
171     PWrite(WRB);
172     Latch(ADR);
173   }
174 }
175
176 PRIVATE void ResetDDS(void) {
177   if(usb_enabled)
178     USB_Sdr1kDDSReset();
179   else {
180     PWrite(RESET + WRB);
181     Latch(ADR);
182     PWrite(WRB);
183     Latch(ADR);
184   }
185   DDSWrite(COMP_PD, 29);                //Power down comparator
186   if(pll_mult == 1)
187     DDSWrite(BYPASS_PLL, 30);
188   else
189     DDSWrite((BYTE) pll_mult, 30);
190   DDSWrite(BYPASS_SINC, 32);
191 }
192
193
194 PRIVATE void CalcClock(void) {
195   sysClock = 200.0 + dds_clock_correction;
196   dds_step_size = sysClock / pow(2.0, 48.0);
197 }
198
199 PRIVATE void SetRadioFreq(double f) {
200   double vfoFreq = f;
201   long tuning_word;
202
203   // calculate software frequency to program
204   if(xvtr_enabled && f >= 144 && f <= 146)
205     f -= 116;                                                                   //Subtract 116MHz (144-28) from VFO display frequency
206
207   if (if_shift)
208     f -= if_freq;                                                               // adjust for IF shift
209   
210   f += vfo_offset;                                                              // adjust for vfo offset
211
212   tuning_word = (long) (f / sysClock * pow(2.0, 48.0));
213
214   if (spur_reduction) {
215     // start with current tuning word
216     // clear first bit, low 31 bits; set bit 31
217     unsigned long long
218       sr_tuning_word = (tuning_word & ~(0x80007fffffffLL)) | 0x000080000000LL;
219     double software_offset = (sr_tuning_word - tuning_word) * dds_step_size;
220
221     if (if_shift)                                                               //Convert the tuning fraction to rel frq
222       tune_frac_rel = 1000000.0 * (software_offset) - 11025.0;
223     else
224       tune_frac_rel = 1000000.0 * (software_offset);
225     DttSP_ChangeOsc(tune_frac_rel);
226
227     tuning_word = sr_tuning_word;
228   }
229
230   // program hardware
231   SetBPF(vfoFreq);
232
233   if (tuning_word != last_tuning_word) {
234     int i;
235     last_tuning_word = tuning_word;                //save new tuning word    
236                                 
237     //parallel_mutex.WaitOne();
238     for(i = 0; i < 6; i++) {
239       BYTE b = (BYTE) (tuning_word >> (40 - i * 8));
240       DDSWrite(b, (BYTE) (4 + i));
241     }
242     //parallel_mutex.ReleaseMutex();
243   }
244 }
245
246 PUBLIC BOOL IsHamBand(BandPlan b) {
247   if (getExtended()) return TRUE;
248   switch (b) {
249   case IARU1:
250     if      (dds_freq >= 1.8 && dds_freq <= 2.0)        return TRUE;
251     else if (dds_freq >= 3.5 && dds_freq <= 4.0)        return TRUE;
252     else if (dds_freq == 5.3305)                        return TRUE;
253     else if (dds_freq == 5.3465)                        return TRUE;
254     else if (dds_freq == 5.3665)                        return TRUE;
255     else if (dds_freq == 5.3715)                        return TRUE;
256     else if (dds_freq == 5.4035)                        return TRUE;
257     else if (dds_freq >= 7.0 && dds_freq <= 7.3)        return TRUE;
258     else if (dds_freq >= 10.1 && dds_freq <= 10.15)     return TRUE;
259     else if (dds_freq >= 14.0 && dds_freq <= 14.35)     return TRUE;
260     else if (dds_freq >= 18.068 && dds_freq <= 18.168)  return TRUE;
261     else if (dds_freq >= 21.0 && dds_freq <= 21.45)     return TRUE;
262     else if (dds_freq >= 24.89 && dds_freq <= 24.99)    return TRUE;
263     else if (dds_freq >= 21.0 && dds_freq <= 21.45)     return TRUE;
264     else if (dds_freq >= 28.0 && dds_freq <= 29.7)      return TRUE;
265     else if (dds_freq >= 50.0 && dds_freq <= 54.0)      return TRUE;
266     else if (dds_freq >= 144.0 && dds_freq <= 146.0) {
267       if (rfe_enabled && xvtr_enabled) return TRUE;
268       else                             return FALSE;
269     } else return FALSE;
270     default:
271       return FALSE;
272       // TODO: Implement other bandplans here
273   }
274 }
275
276 //------------------------------------------------------------------------
277 // Properties
278 //
279
280 PRIVATE BOOL enable_LPF0 = FALSE;
281 PUBLIC  BOOL getEnableLPF0       (void) { return enable_LPF0; }
282 PUBLIC  void setEnableLPF0 (BOOL value) { enable_LPF0 = value; };
283
284 PRIVATE BOOL extended = FALSE;
285 PUBLIC  BOOL getExtended       (void) { return extended; }
286 PUBLIC  void setExtended (BOOL value) { extended = value; }
287
288 PRIVATE BOOL x2_enabled = FALSE;
289 PUBLIC  BOOL getX2Enabled       (void) { return x2_enabled; }
290 PUBLIC  void setX2Enabled (BOOL value) { x2_enabled = value; }
291
292 PRIVATE int  x2_delay = 500;
293 PUBLIC  int  getX2Delay      (void) { return x2_delay; }
294 PUBLIC  void setX2Delay (int value) { x2_delay = value; }
295
296 PUBLIC BOOL getRFE_Enabled       (void) { return rfe_enabled; }
297 PUBLIC void setRFE_Enabled (BOOL value) {
298   rfe_enabled = value;
299   SetRadioFreq(dds_freq);
300 }
301
302 PUBLIC BOOL getPA_Enabled       (void) { return pa_enabled; }
303 PUBLIC void setPA_Enabled (BOOL value) { pa_enabled = value; }
304
305 PUBLIC BOOL getXVTR_Enabled       (void) { return xvtr_enabled; }
306 PUBLIC BOOL setXVTR_Enabled (BOOL value) {
307   xvtr_enabled = value;
308   if (xvtr_enabled) max_freq = 146.0;
309   else              max_freq = 65.0;
310 }
311
312 PUBLIC BOOL getUSB_Enabled       (void) { return usb_enabled; }
313 PUBLIC void setUSB_Enabled (BOOL value) { usb_enabled = value; }
314
315 PRIVATE XVTRTRMode current_xvtr_tr_mode = NEGATIVE;
316 PUBLIC  XVTRTRMode getCurrentXVTRTRMode             (void) { return current_xvtr_tr_mode; }
317 PUBLIC  void       setCurrentXVTRTRMode (XVTRTRMode value) {
318   current_xvtr_tr_mode = value;
319   switch (current_xvtr_tr_mode) {
320   case NEGATIVE: setXVTR_TR_Relay(TRUE);  break;        // Set to receive
321   case POSITIVE: setXVTR_TR_Relay(FALSE); break;        // Set to receive
322   case NONE:                              break;
323   }
324 }
325
326 PUBLIC int  getLatchDelay      (void) { return latch_delay; }
327 PUBLIC void setLatchDelay (int value) { latch_delay = value; }
328
329 PUBLIC double getMinFreq (void) { return min_freq; }
330 PUBLIC double getMaxFreq (void) { return max_freq; }
331
332 PUBLIC u_short getBaseAddr          (void) { return baseAdr; }
333 PUBLIC u_short setBaseAddr (u_short value) { baseAdr = value; }
334
335 PUBLIC BandSetting getBandRelay              (void) { return band_relay; }
336 PUBLIC void        setBandRelay (BandSetting value) {
337   band_relay = value;
338   if (usb_enabled)
339     USB_Sdr1kLatch(SDR1K_LATCH_BPF,
340                    (BYTE) (band_relay + transmit_relay + mute_relay));
341   else {
342     PWrite((BYTE) (band_relay + transmit_relay + mute_relay));
343     Latch(BPF);
344   }
345 }
346
347 PUBLIC BOOL getTransmitRelay (void) {
348   //Get state of TR relay on BPF board
349   if (transmit_relay == TR) return TRUE;
350   else                      return FALSE;
351 }
352 PUBLIC void setTransmitRelay (BOOL value) {
353   BYTE tmpLatch = 0;
354   BOOL tmpATTN = FALSE;
355   //If in valid Amateur BandRelay Save and output new TR Relay setting
356   if (value == TRUE) {
357     //if (IsHamBand(curBandPlan) == TRUE)
358     {
359       if (x2_enabled) {
360         SetExt(P7);             // set X2-7
361         Sleep(x2_delay);        // pause for ext. relays
362       }
363       transmit_relay = TR;      // Set to TX
364       if (rfe_enabled == TRUE) {
365         tmpATTN = getATTN_Relay();
366         if (xvtr_enabled && dds_freq >= 144) {
367           switch (current_xvtr_tr_mode) {
368           case NEGATIVE: setXVTR_TR_Relay(FALSE); break;
369           case POSITIVE: setXVTR_TR_Relay(TRUE);  break;
370           case NONE:                              break;
371           }
372         } else setAMP_Relay(TRUE);                                      //Switch RFE to transmit
373         tmpLatch = (BYTE) (transmit_relay + mute_relay + DCDR_NE);// DCDR_NE for 2-4 Decoder to stay high
374       } else
375         tmpLatch = (BYTE) (band_relay + transmit_relay + mute_relay);
376     }
377   } else {
378     transmit_relay = 0;       // Set to RX
379     if (rfe_enabled) {
380       setAMP_Relay(FALSE);
381       tmpLatch = (BYTE) (transmit_relay + mute_relay + DCDR_NE);
382       if (xvtr_enabled) {
383         switch(current_xvtr_tr_mode) {
384         case NEGATIVE: setXVTR_TR_Relay(TRUE);  break;
385         case POSITIVE: setXVTR_TR_Relay(FALSE); break;
386         case NONE:                              break;
387         }
388       }
389       setATTN_Relay(tmpATTN);
390     } else
391       tmpLatch = (BYTE) (band_relay + transmit_relay + mute_relay);
392   }
393   if (usb_enabled)
394     USB_Sdr1kLatch(SDR1K_LATCH_BPF, tmpLatch);
395   else {
396     PWrite(tmpLatch);
397     Latch(BPF);
398   }
399   if (!value && x2_enabled) {
400     Sleep(x2_delay);    // pause for ext. relays
401     ResExt(P7);         // clear X2-7 
402   }
403   if (pa_enabled) {     // set PA transmit/bias
404     if (dds_freq >= 1.8 && dds_freq <= 29.7) {
405       if (value) {      // TX
406         setPA_TransmitRelay(TRUE);
407         setPA_BiasOn(TRUE);
408       } else {          // RX
409         setPA_BiasOn(FALSE);
410         setPA_TransmitRelay(FALSE);
411       }
412     }
413   }
414 }
415
416 PUBLIC BOOL getMuteRelay (void) {
417   // Get state of MUTE relay on TRX board
418   if (mute_relay == MUTE) return FALSE;
419   else                    return TRUE;
420 }
421 PUBLIC void setMuteRelay (BOOL value) {
422   BYTE data = 0;
423   // Mute the speaker relay if TRUE
424   if (value == TRUE) mute_relay = 0;
425   else               mute_relay = MUTE;
426   if (rfe_enabled)
427     data = (BYTE) (transmit_relay + mute_relay + DCDR_NE);
428   else
429     data = (BYTE) (band_relay + transmit_relay + mute_relay);
430   if (usb_enabled) {
431     USB_Sdr1kLatch(SDR1K_LATCH_BPF, data);
432   } else {
433     PWrite(data);
434     Latch(BPF);
435   }
436 }
437
438 PUBLIC BOOL getGainRelay (void) {
439   // Get state of GAIN relay on TRX board
440   if (gain_relay == GAIN) return FALSE;
441   else                    return TRUE;
442 }
443 PUBLIC void setGainRelay (BOOL value) {
444   // Save and output state of GAIN relay on TRX board
445   if (value == TRUE) gain_relay = 0;    // 40dB or 0dB w/RFE
446   else               gain_relay = GAIN; // 26dB
447   if (usb_enabled)
448     USB_Sdr1kLatch(SDR1K_LATCH_EXT, (BYTE) (external_output + gain_relay));
449   else {
450     PWrite((BYTE) (external_output + gain_relay));
451     Latch(EXT);
452   }
453 }
454
455 PUBLIC int  getExternalOutput      (void) { return external_output; }
456 PUBLIC void setExternalOutput (int value) {
457   //Save and output state of External Control outputs on PIO board
458   external_output = value;
459   if (usb_enabled)
460       USB_Sdr1kLatch(SDR1K_LATCH_EXT, (BYTE) (external_output + gain_relay));
461   else {
462     PWrite((BYTE) (external_output + gain_relay));
463     Latch(EXT);
464   }
465 }
466
467 PUBLIC double getDDSClockCorrection         (void) { return dds_clock_correction; }
468 PUBLIC void   setDDSClockCorrection (double value) {
469   dds_clock_correction = value;
470   CalcClock();
471   SetRadioFreq(dds_freq);
472 }
473
474 PUBLIC int  getPLLMult      (void) { return pll_mult; }
475 PUBLIC void setPLLMult (int value) {
476   pll_mult = value;
477   if (pll_mult == 1) DDSWrite(BYPASS_PLL, 30);      // Bypass PLL if multiplier value is 1
478   else               DDSWrite((BYTE) pll_mult, 30); // Set for External Clock
479   CalcClock();
480 }
481
482 PUBLIC double getDDSClock         (void) { return dds_clock; }
483 PUBLIC void   setDDSClock (double value) {
484   //Compute internal DDS System Clock and Phase Truncation Elimination Step
485   dds_clock = value;
486   CalcClock();
487 }
488
489 PUBLIC BOOL getIFShift       (void) { return if_shift; }
490 PUBLIC void setIFShift (BOOL value) {
491   // Turns IF shift on and off
492   if_shift = value;
493   if (!spur_reduction) {
494     if (if_shift) DttSP_ChangeOsc(-11025.0);
495     else          DttSP_ChangeOsc(0.0);
496   }
497   SetRadioFreq(dds_freq);
498 }
499
500 PUBLIC BOOL getSpurReduction       (void) { return spur_reduction; }
501 PUBLIC BOOL setSpurReduction (BOOL value) {
502   // Turns DDS Phase Truncation Spur reduction on and off
503   spur_reduction = value;
504   if (!spur_reduction) {
505       if (if_shift) DttSP_ChangeOsc(-11025.0);
506       else          DttSP_ChangeOsc(0.0);
507   }
508   SetRadioFreq(dds_freq);
509 }
510
511 PUBLIC double getIFFreq         (void) { return if_freq; }
512 PUBLIC void   setIFFreq (double value) { if_freq = value; }
513
514 PUBLIC double getDDSFreq         (void) { return dds_freq; }
515 PUBLIC void   setDDSFreq (double value) {
516   dds_freq = value;
517   SetRadioFreq(dds_freq);
518 }
519
520 PUBLIC int  getSampleRate      (void) { return sample_rate; }
521 PUBLIC void setSampleRate (int value) {
522   sample_rate = value;
523   if (fft_length > 0)
524     FFT_Bin_Size = (sample_rate / fft_length) * 1e-6;
525 }
526
527 PUBLIC int  getFFTLength      (void) { return fft_length; }
528 PUBLIC void setFFTLength (int value) {
529   fft_length = value;
530   //Compute bandwidth of FFT bin
531   if (fft_length > 0)
532     FFT_Bin_Size = (sample_rate / fft_length) * 1e-6;
533 }
534
535 PUBLIC int getTuneFFT (void) { return tune_fft; }
536
537 PUBLIC double getTuneFracRel (void) { return tune_frac_rel; }
538
539 PUBLIC double getVFOOffset         (void) { return vfo_offset; }
540 PUBLIC void   setVFOOffset (double value) {
541   vfo_offset = value;
542   SetRadioFreq(dds_freq);
543 }
544
545 PUBLIC int  getIOUDClock      (void) { return ioud_clock; }
546 PUBLIC void setIOUDClock (int value) {
547   double bitVal, bytVal;
548   BYTE lWord;
549   int i;
550   ioud_clock = value;                   //Save value
551   bitVal = value;                       //Compute Numeric Value
552   for (i = 24; i >= 0; i -= 8) {                //Convert to binary strings
553       bytVal = bitVal / (01 << i);      //Compute binary byte Value
554       lWord = (BYTE) bytVal;            //Truncate fractional portion
555       bitVal -= lWord * (01 << i);      //Reduce value
556       switch (i) {                      //Write to byte position
557         case 32: DDSWrite(lWord, 22); break;
558         case 16: DDSWrite(lWord, 23); break;
559         case 8:  DDSWrite(lWord, 24); break;
560         case 0:  DDSWrite(lWord, 25); break;
561         }
562     }
563 }
564
565 PUBLIC u_short getDACMult          (void) { return dac_mult; }
566 PUBLIC void    setDACMult (u_short value) {
567   double bitVal, bytVal;
568   BYTE lWord;
569   int i;
570   dac_mult = value;
571   bitVal = value;                       //Compute Numeric Value
572   for (i = 8; i >= 0; i -= 8) {         //Convert to binary strings
573     bytVal = bitVal / (01 << i);        //Compute binary byte Value
574     BYTE lWord = (BYTE) bytVal; //Truncate fractional portion
575     bitVal -= lWord * (01 << i);        //Reduce value
576     switch (i) {
577     case 8: DDSWrite(lWord, 33); break;
578     case 0: DDSWrite(lWord, 34); break;
579     }
580   }
581   //Send new I DAC Multiplier value to DDS
582   bitVal = value;                       //Compute Numeric Value
583   for (i = 8; i >= 0; i -= 8) {         //Convert to binary strings.
584     bytVal = bitVal / (01 << i);        //Compute binary byte Value
585     lWord = (BYTE) bytVal;              //Truncate fractional portion
586     bitVal -= lWord * (01 << i);        //Reduce value
587       switch (i) {                      //Write to byte position
588         case 8: DDSWrite(lWord, 35); break;
589         case 0: DDSWrite(lWord, 36); break;
590       }
591   }
592 }
593
594 PUBLIC BYTE StatusPort(void) {  
595   if (usb_enabled)
596     return (BYTE) USB_Sdr1kGetStatusPort();
597   else {
598     BYTE status;
599     ioctl(parportfd, PPRSTATUS, (char *) &status);
600     return status;
601   }
602 }
603
604 PUBLIC void Init(void) {
605   setIFShift(TRUE);
606   // user setable through the setup form
607   // DDSClockCorrection = 0.000;
608   setPLLMult(1);
609   setDDSClock(200);
610   setIFFreq(0.011025);
611   setSampleRate((int) DttSP_SampleRate);
612   setFFTLength(4096);
613   //setDACMult(4095);
614 }
615
616 PUBLIC void PowerOn(void) {
617   if (rfe_enabled) {
618     // set mute/gain relays based on console
619     if (xvtr_enabled && current_xvtr_tr_mode == NEGATIVE)
620       setXVTR_TR_Relay(TRUE);
621     else
622       setXVTR_TR_Relay(FALSE);
623     //DDSFreq = dds_freq;
624     ic11_memory |= ADC_CS_NOT;          // set CS_NOT high
625     ic11_memory |= ATUCTL;
626     ic7_memory  |= PA_BIAS_NOT;
627     SRLoad(IC11, ic11_memory);                          
628     SRLoad(IC7,  ic7_memory);
629   }
630 }
631
632 PUBLIC void StandBy(void) {
633   ResetLatches();
634   if (rfe_enabled) ResetRFE();
635   if (xvtr_enabled) setXVTR_TR_Relay(FALSE);
636   // TODO: Fix bias glitch on reset w/hardware rewrite
637   if (rfe_enabled) {
638       SRLoad(IC7, PA_BIAS_NOT);
639       SRLoad(IC11, ADC_CS_NOT);
640   }
641   ResetDDS();
642 }
643
644 PUBLIC void SetExt(ExtPin pin) {
645   //Set the designated external pin high
646   external_output |= (BYTE) pin;
647   if (usb_enabled)
648     USB_Sdr1kLatch(SDR1K_LATCH_EXT, (BYTE) (external_output + gain_relay));
649   else {
650     PWrite((BYTE) (external_output + gain_relay));
651     Latch(EXT);
652   }
653 }
654
655 PUBLIC void ResExt(ExtPin pin) {
656   //Reset the designated external pin high
657   external_output &= ~(BYTE) pin;
658   if (usb_enabled)
659     USB_Sdr1kLatch(SDR1K_LATCH_EXT, (BYTE) (external_output + gain_relay));
660   else {
661     PWrite((BYTE) (external_output + gain_relay));
662     Latch(EXT);
663   }
664 }
665
666 PUBLIC BOOL PinValue(ExtPin pin) {
667   //Return TRUE if Pin is set
668   if ((external_output & (int) pin) != 0)
669     return TRUE;
670   else
671     return FALSE;
672 }
673
674 PUBLIC void SetBPF(double vfo_value) {
675   if (rfe_enabled) {
676       if (vfo_value <= 2.5) {
677         if (pa_enabled) PA_SetLPF(PA_LPF_160);
678         if (vfo_value <= 0.3 && enable_LPF0) {
679           SRLoad(IC10, BPF0);
680           SRLoad(IC9, LPF0);                                            
681         } else {
682           SRLoad(IC10, LPF9 + BPF0);
683           SRLoad(IC9, 0);
684         }
685       } else if (vfo_value <= 4) {
686         if (pa_enabled) PA_SetLPF(PA_LPF_80);
687         SRLoad(IC10, BPF1);
688         SRLoad(IC9,  LPF7);
689       } else if (vfo_value <= 6) {
690         if (pa_enabled) PA_SetLPF(PA_LPF_60_40);
691         SRLoad(IC10, BPF1);
692         SRLoad(IC9,  LPF2);
693       } else if (vfo_value <= 7.3) {
694         if (pa_enabled) PA_SetLPF(PA_LPF_60_40);
695         SRLoad(IC10, BPF2);
696         SRLoad(IC9,  LPF5);
697       } else if (vfo_value <= 10.2) {
698         if (pa_enabled) PA_SetLPF(PA_LPF_30_20);
699         SRLoad(IC10, BPF2);
700         SRLoad(IC9,  LPF4);
701       } else if (vfo_value <= 12) {
702         if (pa_enabled) PA_SetLPF(PA_LPF_OFF);
703         SRLoad(IC10, BPF2);
704         SRLoad(IC9,  LPF3);
705       } else if (vfo_value <= 14.5) {
706         if (pa_enabled) PA_SetLPF(PA_LPF_30_20);
707         SRLoad(IC10, BPF3);
708         SRLoad(IC9,  LPF3);
709       } else if (vfo_value <= 21.5) {
710         if (pa_enabled) PA_SetLPF(PA_LPF_17_15);
711         SRLoad(IC10, BPF3 + LPF8);
712         SRLoad(IC9,  0);
713       } else if (vfo_value <= 24) {
714         if (pa_enabled) PA_SetLPF(PA_LPF_12_10);
715         SRLoad(IC10, BPF3);
716         SRLoad(IC9,  LPF6);
717       } else if (vfo_value <= 30) {
718         if (pa_enabled) PA_SetLPF(PA_LPF_12_10);
719         SRLoad(IC10, BPF4);
720         SRLoad(IC9,  LPF6);
721       } else if (vfo_value <= 36) {
722         if (pa_enabled) PA_SetLPF(PA_LPF_OFF);
723         SRLoad(IC10, BPF4);
724         SRLoad(IC9,  LPF1);
725       } else if (vfo_value <= 65) {
726         if (pa_enabled) PA_SetLPF(PA_LPF_OFF);
727         SRLoad(IC10, BPF5);
728         SRLoad(IC9,  LPF1);
729       } else if (xvtr_enabled && vfo_value >= 144 && vfo_value <= 146) {
730         if (pa_enabled) PA_SetLPF(PA_LPF_OFF);
731         SRLoad(IC10, BPF4);
732         SRLoad(IC9,  LPF6);
733         setXVTR_Relay(TRUE);
734       }
735       if (xvtr_enabled && vfo_value < 144)
736         setXVTR_Relay(FALSE);
737     } else {
738       if      (vfo_value < 2.5) setBandRelay(bs0);
739       else if (vfo_value < 6)   setBandRelay(bs1);
740       else if (vfo_value < 12)  setBandRelay(bs2);
741       else if (vfo_value < 24)  setBandRelay(bs3);
742       else if (vfo_value < 36)  setBandRelay(bs4);
743       else                      setBandRelay(bs5);
744     }
745 }
746
747 PUBLIC void TestPort(void) {
748   //Toggle 1 and 0 to each of the four parallel port latches
749   if (usb_enabled) {
750     USB_Sdr1kLatch(SDR1K_LATCH_BPF, 0);
751     USB_Sdr1kLatch(SDR1K_LATCH_EXT, 0);
752     USB_Sdr1kLatch(SDR1K_LATCH_BPF, 255);
753     USB_Sdr1kLatch(SDR1K_LATCH_EXT, 255);
754   } else {
755     PWrite(0);
756     Latch(BPF);
757     Latch(ADR);
758     Latch(DAT);
759     Latch(EXT);
760     PWrite(255);
761     Latch(BPF);
762     Latch(ADR);
763     Latch(DAT);
764     Latch(EXT);
765   }
766 }
767
768 PUBLIC void RCKStrobe(BOOL ClearReg, RFE_RCK Reg) {
769   // Strobe the RFE 1:4 decoder output to transfer contents
770   // of shift register to output latches
771   BYTE data = 0;
772   if (ClearReg) data = (BYTE) (Reg);
773   else data = (BYTE) (SCLR_NOT + Reg + transmit_relay + mute_relay);
774   if (usb_enabled) {
775     USB_Sdr1kLatch(SDR1K_LATCH_BPF, data);
776     USB_Sdr1kLatch(SDR1K_LATCH_BPF, (BYTE) (SCLR_NOT + DCDR_NE + transmit_relay + mute_relay));
777   } else {
778     PWrite(data);
779     Latch(BPF);
780     PWrite((BYTE) (SCLR_NOT + DCDR_NE + transmit_relay + mute_relay));
781     Latch(BPF);
782   }
783 }
784
785 PUBLIC void SRLoad(RFE_RCK Reg, int Data) {
786   if (usb_enabled)
787     USB_Sdr1kSRLoad((BYTE) Reg, (BYTE) Data);
788   else {
789     static int choose[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
790     int i;
791     //Shift data into registers on RFE
792     //parallel_mutex.WaitOne();
793     for (i = 0; i < 8; i++) {
794       int mask = choose[i];                                                                                             // Mask the current bit
795       if ((mask & Data) == 0) {
796         PWrite((BYTE) (SCLR_NOT + DCDR_NE + transmit_relay + mute_relay));
797         Latch(BPF);
798         PWrite((BYTE) (SCLR_NOT + DCDR_NE + SCK + transmit_relay + mute_relay));
799       } else {                                                                                                                          // Current bit = 1          {
800         PWrite((BYTE) (SCLR_NOT + DCDR_NE + SER + transmit_relay + mute_relay));
801         Latch(BPF);
802         PWrite((BYTE) (SCLR_NOT + DCDR_NE + SER + SCK + transmit_relay + mute_relay));
803       }
804       Latch(BPF);
805       PWrite((BYTE) (SCLR_NOT + DCDR_NE + transmit_relay + mute_relay));
806       Latch(BPF);
807     }
808     RCKStrobe(FALSE, Reg);                                                                                                      // Strobe Register Clock
809     //parallel_mutex.ReleaseMutex();
810   }
811 }
812
813 PUBLIC void ResetRFE(void) {
814   //Reset all RFE shift registers to zero output
815   //parallel_mutex.WaitOne();
816   RCKStrobe(TRUE, IC11);
817   RCKStrobe(TRUE, IC7);
818   RCKStrobe(TRUE, IC10);
819   RCKStrobe(TRUE, IC9);
820   //parallel_mutex.ReleaseMutex();
821 }
822
823 PUBLIC BOOL getAMP_Relay       (void) { return (ic7_memory & AMP_RLYS) != 0; }
824 PUBLIC BOOL setAMP_Relay (BOOL value) {
825   //Set or reset LNA relay
826   if (value)  ic7_memory |= AMP_RLYS;
827   else        ic7_memory &= ~(AMP_RLYS);
828   SRLoad(IC7, ic7_memory);
829 }
830
831 PUBLIC BOOL getATTN_Relay       (void) { return (ic7_memory & ATTN_RLY) != 0; }
832 PUBLIC void setATTN_Relay (BOOL value) {
833   if (value)  ic7_memory |= ATTN_RLY;
834   else        ic7_memory &= ~(ATTN_RLY);
835   SRLoad(IC7, ic7_memory);
836 }
837
838 PUBLIC BOOL getXVTR_TR_Relay       (void) { return (ic7_memory & XVTR_TR_RLY) != 0; }
839 PUBLIC BOOL setXVTR_TR_Relay (BOOL value) {
840   if (value)  ic7_memory |= XVTR_TR_RLY;
841   else        ic7_memory &= ~(XVTR_TR_RLY);
842   SRLoad(IC7, ic7_memory);
843 }
844
845 PUBLIC BOOL getXVTR_Relay       (void) { return (ic7_memory & XVTR_RLY) != 0; }
846 PUBLIC BOOL setXVTR_Relay (BOOL value) {
847   if (value)  ic7_memory |= XVTR_RLY;
848   else        ic7_memory &= ~(XVTR_RLY);
849   SRLoad(IC7, ic7_memory);
850 }
851
852 PUBLIC BOOL getIMPULSE_Relay       (void) { return (ic7_memory & IMPULSE_RLY) != 0; }
853 PUBLIC BOOL setIMPULSE_Relay (BOOL value) {
854   if (value)  ic7_memory |= IMPULSE_RLY;
855   else        ic7_memory &= ~(IMPULSE_RLY);
856   SRLoad(IC7, ic7_memory);
857 }
858
859 PUBLIC void Impulse(void) {
860   //Send a single impulse to the QSD
861   SRLoad(IC7, (ic7_memory | IMPULSE));
862   SRLoad(IC7, ic7_memory);
863 }
864
865 PUBLIC void PA_SetLPF(int i) {
866   int temp = ic11_memory;
867   switch(i) {
868     case PA_LPF_OFF:    // 0
869       ic11_memory &= ~(0x07);                           // clear bits 0, 1 and 2
870       break;
871     case PA_LPF_12_10:  // 1
872       ic11_memory  = (ic11_memory | 0x01) & ~(0x06);    // set bit 0, clear bits 1,2
873       break;
874     case PA_LPF_17_15:  // 2
875       ic11_memory  = (ic11_memory | 0x02) & ~(0x05);    // set bit 1, clear bits 0,2
876       break;
877     case PA_LPF_30_20:  // 3
878       ic11_memory  = (ic11_memory | 0x03) & ~(0x04);    // set bits 0,1, clear bit 2
879       break;
880     case PA_LPF_60_40:  // 4
881       ic11_memory  = (ic11_memory | 0x04) & ~(0x03);    // set bit 2, clear bits 0,1
882       break;
883     case PA_LPF_80:     // 5
884       ic11_memory  = (ic11_memory | 0x05) & ~(0x02);    // set bits 0,2, clear bit 1
885       break;
886     case PA_LPF_160:    // 6
887       ic11_memory  = (ic11_memory | 0x06) & ~(0x01);    // set bits 1,2, clear bit 0
888       break;
889     }
890   if (temp != ic11_memory)
891     SRLoad(IC11, ic11_memory);
892 }
893
894 PUBLIC BOOL getPA_TransmitRelay       (void) { return ((ic11_memory & PATR) != 0); }
895 PUBLIC BOOL setPA_TransmitRelay (BOOL value) {
896   int temp = ic11_memory;
897   if (value) ic11_memory |= PATR;
898   else       ic11_memory &= ~(PATR);
899   if (temp != ic11_memory)
900     SRLoad(IC11, ic11_memory);
901 }
902
903 PUBLIC BOOL getPA_BiasOn       (void) { return ((ic7_memory & PA_BIAS_NOT) != 0); }
904 PUBLIC BOOL setPA_BiasOn (BOOL value) {
905   int temp = ic7_memory;
906   if (value) ic7_memory &= ~(PA_BIAS_NOT);
907   else       ic7_memory |= PA_BIAS_NOT;
908   if (temp != ic7_memory)
909     SRLoad(IC7, ic7_memory);
910 }
911
912 PUBLIC BYTE PA_GetADC(int chan) {
913   short num = 0;
914   int i;
915   // get ADC on amplifier
916   // 0 for forward power, 1 for reverse
917
918   if (usb_enabled) {
919     int data = USB_Sdr1kGetADC();
920     if (chan == 0) return (BYTE) (data & 255);
921     else           return (BYTE) (data >> 8);
922   }
923   
924   //dataline_mutex.WaitOne();
925   //parallel_mutex.WaitOne();
926   
927   ic11_memory &= ~(ADC_CS_NOT);         // CS not goes low
928   SRLoad(IC11, ic11_memory);
929   
930   ic11_memory |= ADC_DI;                                // set DI bit high for start bit
931   SRLoad(IC11, ic11_memory);
932   
933   ic11_memory |= ADC_CLK;                               // clock it into shift register
934   SRLoad(IC11, ic11_memory);
935   ic11_memory &= ~(ADC_CLK);
936   SRLoad(IC11, ic11_memory);
937   
938   // set DI bit high for single ended -- done since DI is already high
939   ic11_memory |= ADC_CLK;                               // clock it into shift register
940   SRLoad(IC11, ic11_memory);
941   ic11_memory &= ~(ADC_CLK);
942   SRLoad(IC11, ic11_memory);
943   
944   if (chan == PA_FORWARD_PWR) {
945     ic11_memory &= ~(ADC_DI);           // set DI bit low for Channel 0
946     SRLoad(IC11, ic11_memory);
947   } else {
948     // set DI bit high for Channel 1 -- done since DI is already high
949   }
950   
951   ic11_memory |= ADC_CLK;               // clock it into shift register
952   SRLoad(IC11, ic11_memory);
953   ic11_memory &= ~(ADC_CLK);
954   SRLoad(IC11, ic11_memory);
955   
956   for(i = 0; i < 8; i++) {              // read 15 bits out of DO
957     ic11_memory |= ADC_CLK;                     // clock high
958     SRLoad(IC11, ic11_memory);
959     ic11_memory &= ~(ADC_CLK);          // clock low
960     SRLoad(IC11, ic11_memory);
961       
962     if ((StatusPort() & (BYTE) PA_DATA) != 0)   // read DO 
963       num++;    // add bit              
964       
965     if (i != 7) num <<= 1;
966   }
967   
968   ic11_memory |= ADC_CS_NOT;            // CS not goes high
969   SRLoad(IC11, ic11_memory);
970   
971   //dataline_mutex.ReleaseMutex();
972   //parallel_mutex.ReleaseMutex();
973   
974   return (BYTE) (num);
975 }
976
977 PUBLIC BOOL PA_ATUTune(ATUTuneMode mode) {
978   int count = 0, delay = 0;
979
980   //dataline_mutex.WaitOne();
981
982   ic11_memory &= ~(ATUCTL);
983
984   SRLoad(IC11, ic11_memory);
985   switch (mode) {
986   case BYPASS: delay =  250; break;
987   case MEMORY: delay = 2000; break;
988   case FULL:   delay = 3250; break;
989   }
990   
991   Sleep(delay);
992   ic11_memory |= ATUCTL;
993   SRLoad(IC11, ic11_memory);
994   
995   if (mode == MEMORY || mode == FULL) {
996     while ((StatusPort() & (BYTE) PA_DATA) != 0)        { // wait for low output from ATU
997       Sleep(50);
998       if (count++ > 100) return FALSE;
999     }
1000     count = 0;
1001     while ((StatusPort() & (BYTE) PA_DATA) == 0)        { // wait for high output from ATU
1002       Sleep(50);
1003       if (count++ > 100) return FALSE;
1004     }
1005     Sleep(1000);
1006   }
1007   
1008   //dataline_mutex.ReleaseMutex();
1009   
1010   return TRUE;
1011 }