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