]> git.rkrishnan.org Git - dttsp.git/blobdiff - jDttSP/sdr.c
Major update
[dttsp.git] / jDttSP / sdr.c
index aad64d3f50f12469f2e0ff4ace01dce398084646..937481344388e71f1a9f2f53056566a72ffdc13c 100644 (file)
@@ -115,6 +115,8 @@ setup_all(void) {
   uni.mix.rx.flag = uni.mix.tx.flag = FALSE;
   uni.mix.rx.gain = uni.mix.tx.gain = 1.0;
   
+  uni.cpdlen = loc.def.comp;
+
   uni.tick = 0;
 }
 
@@ -146,7 +148,7 @@ setup_rx(int k) {
      we just created */
   rx[k].buf.i = newCXB(FiltOvSv_fetchsize(rx[k].filt.ovsv),
                       FiltOvSv_fetchpoint(rx[k].filt.ovsv),
-                      "init rx.buf.i");
+                      "init rx[k].buf.i");
   rx[k].buf.o = newCXB(FiltOvSv_storesize(rx[k].filt.ovsv),
                       FiltOvSv_storepoint(rx[k].filt.ovsv),
                       "init rx[k].buf.o");
@@ -161,17 +163,16 @@ setup_rx(int k) {
                         uni.samplerate,
                         "SDR RX Oscillator");
 
-  rx[k].agc.gen = newDigitalAgc(agcMED,        // Mode
-                            7,         // Hang
-                            7,         // Size
-                            48,        // Ramp
-                            3,         // Over
-                            3,         // Rcov
-                            CXBsize(rx[k].buf.o),      // BufSize
-                            100.0,     // MaxGain
-                            0.707,     // Limit
-                            1.0,       // CurGain
-                            CXBbase(rx[k].buf.o));
+  rx[k].agc.gen = newDigitalAgc(agcSLOW,       // Mode
+                               7,              // Hang
+                               48,             // Ramp
+                               3,              // Over
+                               3,              // Rcov
+                               CXBsize(rx[k].buf.o),   // BufSize
+                               2500.0,         // MaxGain
+                               0.707,          // Limit
+                               1.0,            // CurGain
+                               CXBbase(rx[k].buf.o));
   rx[k].agc.flag = TRUE;
 
   /* demods */
@@ -236,7 +237,12 @@ setup_rx(int k) {
   rx[k].squelch.thresh = -30.0;
   rx[k].squelch.power = 0.0;
   rx[k].squelch.flag = rx[k].squelch.running = rx[k].squelch.set = FALSE;
-  rx[k].squelch.num = (int) (0.0395 * uni.samplerate + 0.5);
+  rx[k].squelch.num = uni.buflen - 10;
+
+  rx[k].cpd.gen = newWSCompander(uni.cpdlen,
+                                0.0,
+                                rx[k].buf.o);
+  rx[k].cpd.flag = FALSE;
 
   rx[k].mode = uni.mode.sdr;
   rx[k].bin.flag = FALSE;
@@ -281,6 +287,9 @@ setup_tx(void) {
                    FiltOvSv_storepoint(tx.filt.ovsv),
                    "init tx.buf.o");
   
+  tx.dcb.flag = FALSE;
+  tx.dcb.gen = newDCBlocker(DCB_MED, tx.buf.i);
+
   /* conversion */
   tx.osc.freq = 0.0;
   tx.osc.phase = 0.0;
@@ -291,12 +300,12 @@ setup_tx(void) {
                      uni.samplerate,
                      "SDR TX Oscillator");
 
+
   tx.agc.gen = newDigitalAgc(agcFAST,  // Mode
                             3,         // Hang
-                            3,         // Size
+                            48,        // Ramp
                             3,         // Over
                             3,         // Rcov
-                            48,        // Ramp
                             CXBsize(tx.buf.o), // BufSize
                             1.0,       // MaxGain
                             0.900,     // Limit
@@ -304,9 +313,14 @@ setup_tx(void) {
                             CXBbase(tx.buf.o));
   tx.agc.flag = TRUE;
 
-  tx.spr.gen = newSpeechProc(0.4, 10.0, CXBbase(tx.buf.i), CXBsize(tx.buf.i));
+  tx.spr.gen = newSpeechProc(0.4, 10.0, CXBbase(tx.buf.o), CXBsize(tx.buf.o));
   tx.spr.flag = FALSE;
 
+  tx.cpd.gen = newWSCompander(uni.cpdlen,
+                             0.0,
+                             tx.buf.o);
+  tx.cpd.flag = FALSE;
+
   tx.scl.dc = cxzero;
   tx.scl.pre.val = 1.0;
   tx.scl.pre.flag = FALSE;
@@ -345,6 +359,7 @@ destroy_workspace(void) {
   delSpeechProc(tx.spr.gen);
   delDigitalAgc(tx.agc.gen);
   delOSC(tx.osc.gen);
+  delDCBlocker(tx.dcb.gen);
   delvec_COMPLEX(tx.filt.save);
   delFiltOvSv(tx.filt.ovsv);
   delFIR_Bandpass_COMPLEX(tx.filt.coef);
@@ -405,20 +420,21 @@ do_rx_meter(int k, CXB buf, int tap) {
   uni.meter.rx.val[k][tap] = 0;
   
   switch (uni.meter.rx.type) {
-  case AVG_SIGNAL_STRENGTH:
-    for (i = 0; i < len; i++)
-      uni.meter.rx.val[k][tap] += Csqrmag(vec[i]);
-    uni.meter.rx.val[k][tap] =
-      uni.meter.rx.avg[k][tap] =
-        0.9 * uni.meter.rx.avg[k][tap] + log10(uni.meter.rx.val[k][tap] + 1e-20);
-    break;
   case SIGNAL_STRENGTH:
     for (i = 0; i < len; i++)
       uni.meter.rx.val[k][tap] += Csqrmag(vec[i]);
+    if (tap == 3) rx[k].norm = uni.meter.rx.val[k][tap] / len;
     uni.meter.rx.avg[k][tap] =
       uni.meter.rx.val[k][tap] =
         10.0 * log10(uni.meter.rx.val[k][tap] + 1e-20);
     break;
+  case AVG_SIGNAL_STRENGTH:
+    for (i = 0; i < len; i++)
+      uni.meter.rx.val[k][tap] += Csqrmag(vec[i]);
+    uni.meter.rx.val[k][tap] =
+      uni.meter.rx.avg[k][tap] =
+        0.9 * uni.meter.rx.avg[k][tap] + log10(uni.meter.rx.val[k][tap] + 1e-20);
+    break;
   case ADC_REAL:
     for(i = 0; i < len; i++)
       uni.meter.rx.val[k][tap] = max(fabs(vec[i].re), uni.meter.rx.val[k][tap]);
@@ -429,6 +445,9 @@ do_rx_meter(int k, CXB buf, int tap) {
       uni.meter.rx.val[k][tap] = max(fabs(vec[i].im), uni.meter.rx.val[k][tap]);
     uni.meter.rx.val[k][tap] = 20.0 * log10(uni.meter.rx.val[k][tap] + 1e-10);
     break;
+  case AGC_GAIN:
+    uni.meter.rx.val[k][tap] = 20.0 * log10(rx[k].agc.gen->gain.now + 1e-80);
+    break;
   default:
     break;
   }
@@ -456,28 +475,35 @@ do_tx_meter(CXB buf, int tap) {
       uni.meter.tx.val[tap] =
         10.0 * log10(uni.meter.tx.val[tap] + 1e-20);
     break;
-  case ADC_REAL:
-    for(i = 0; i < len; i++)
-      uni.meter.tx.val[tap] = max(fabs(vec[i].re), uni.meter.tx.val[tap]);
-    uni.meter.tx.val[tap] = 20.0 * log10(uni.meter.tx.val[tap] + 1e-10);
+  case ALC:
+    {
+      REAL tmp = 20.0 * log10(tx.agc.gen->gain.now);
+      uni.meter.tx.val[tap] =
+       tmp < 0.0 ? tmp : min(20.0, 20.0 * log10(tx.agc.gen->gain.raw));
+    }
     break;
-  case ADC_IMAG:
-    for(i = 0; i < len; i++)
-      uni.meter.tx.val[tap] = max(fabs(vec[i].im), uni.meter.tx.val[tap]);
-    uni.meter.tx.val[tap] = 20.0 * log10(uni.meter.tx.val[tap] + 1e-10);
+  case PWR:
+    for(i = 0, uni.meter.tx.val[tap] = 1e-20; i < CXBhave(tx.buf.o); i++)
+      uni.meter.tx.val[tap] += Csqrmag(CXBdata(tx.buf.o, i));
+    uni.meter.tx.val[tap] /= 2048.0;
+    break;
+  case PKPWR:
+    for(i = 0, uni.meter.tx.val[tap] = 1e-20; i < CXBhave(tx.buf.o); i++) 
+      uni.meter.tx.val[tap] = max(uni.meter.tx.val[tap],
+                                 Csqrmag(CXBdata(tx.buf.o,i)));
     break;
   default:
     break;
   }
 }
 
-PRIVATE BOOLEAN
+PRIVATE void
 do_rx_spectrum(int k, CXB buf, int type) {
   if (uni.spec.flag && k == uni.spec.rxk && type == uni.spec.type) {
     memcpy((char *) &CXBdata(uni.spec.accum, uni.spec.fill),
           (char *) CXBbase(buf),
-          CXBhave(buf)); 
-    uni.spec.fill = (uni.spec.fill + uni.spec.buflen) % uni.spec.size;
+          CXBsize(buf) * sizeof(COMPLEX)); 
+    uni.spec.fill = (uni.spec.fill + CXBsize(buf)) % uni.spec.size;
   }
 }
 
@@ -485,8 +511,8 @@ PRIVATE void
 do_tx_spectrum(CXB buf) {
   memcpy((char *) &CXBdata(uni.spec.accum, uni.spec.fill),
         (char *) CXBbase(buf),
-        CXBhave(buf));
-  uni.spec.fill = (uni.spec.fill + uni.spec.buflen) % uni.spec.size;
+        CXBsize(buf) * sizeof(COMPLEX));
+  uni.spec.fill = (uni.spec.fill + CXBsize(buf)) % uni.spec.size;
 }
 
 //========================================================================
@@ -497,9 +523,13 @@ should_do_rx_squelch(int k) {
   if (rx[k].squelch.flag) {
     int i, n = CXBhave(rx[k].buf.o);
     rx[k].squelch.power = 0.0;
+
     for (i = 0; i < n; i++)
       rx[k].squelch.power += Csqrmag(CXBdata(rx[k].buf.o, i));
-    return rx[k].squelch.thresh > 10.0 * log10(rx[k].squelch.power);
+
+    return
+      10.0 * log10(rx[k].squelch.power) < rx[k].squelch.thresh;
+
   } else
     return rx[k].squelch.set = FALSE;
 }
@@ -510,14 +540,25 @@ should_do_rx_squelch(int k) {
 PRIVATE void
 do_squelch(int k) {
   rx[k].squelch.set = TRUE;
+  
   if (!rx[k].squelch.running) {
-    int i, m = rx[k].squelch.num, n = CXBhave(rx[k].buf.o) - m;
+    int i,
+        m = rx[k].squelch.num,
+        n = CXBhave(rx[k].buf.o) - m;
+
     for (i = 0; i < m; i++)
-      CXBdata(rx[k].buf.o, i) = Cscl(CXBdata(rx[k].buf.o, i), 1.0 - (REAL) i / m);
-    memset((void *) (CXBbase(rx[k].buf.o) + m), 0, n * sizeof(COMPLEX));
+      CXBdata(rx[k].buf.o, i) =
+       Cscl(CXBdata(rx[k].buf.o, i), 1.0 - (REAL) i / m);
+  
+    memset((void *) (CXBbase(rx[k].buf.o) + m),
+          0,
+          n * sizeof(COMPLEX));
     rx[k].squelch.running = TRUE;
+
   } else
-    memset((void *) CXBbase(rx[k].buf.o), 0, CXBhave(rx[k].buf.o) * sizeof(COMPLEX));
+    memset((void *) CXBbase(rx[k].buf.o),
+          0,
+          CXBhave(rx[k].buf.o) * sizeof(COMPLEX));
 }
 
 // lift squelch
@@ -527,8 +568,11 @@ PRIVATE void
 no_squelch(int k) {
   if (rx[k].squelch.running) {
     int i, m = rx[k].squelch.num;
+
     for (i = 0; i < m; i++)
-      CXBdata(rx[k].buf.o, i) = Cscl(CXBdata(rx[k].buf.o, i), (REAL) i / m);
+      CXBdata(rx[k].buf.o, i) =
+       Cscl(CXBdata(rx[k].buf.o, i), (REAL) i / m);
+
     rx[k].squelch.running = FALSE;
   }
 }
@@ -582,12 +626,16 @@ do_rx_pre(int k) {
     do_rx_meter(k, rx[k].buf.o, RXMETER_POST_FILT);
     do_rx_spectrum(k, rx[k].buf.o, SPEC_POST_FILT);
     
+    if (rx[k].cpd.flag)
+      WSCompand(rx[k].cpd.gen);
+
     if (should_do_rx_squelch(k))
       do_squelch(k);
     
     else if (rx[k].agc.flag)
       DigitalAgc(rx[k].agc.gen, rx[k].tick);
-    
+
+    do_rx_spectrum(k, rx[k].buf.o, SPEC_POST_AGC);
   }
 }
 
@@ -682,18 +730,19 @@ do_rx(int k) {
 PRIVATE void
 do_tx_pre(void) {
 
-if (tx.scl.pre.flag) {
-int i, n = CXBhave(tx.buf.i);
+  if (tx.scl.pre.flag) {
+    int i, n = CXBhave(tx.buf.i);
     for (i = 0; i < n; i++)
       CXBdata(tx.buf.i, i) = Cmplx(CXBreal(tx.buf.i, i) * tx.scl.pre.val, 0.0);
   }
 
   correctIQ(tx.buf.i, tx.iqfix);
 
-  if (tx.spr.flag) SpeechProcessor(tx.spr.gen);
+  if (tx.dcb.flag) DCBlock(tx.dcb.gen);
 
   if (tx.tick == 0) reset_OvSv(tx.filt.ovsv);
   filter_OvSv(tx.filt.ovsv);
+
 }
 
 PRIVATE void
@@ -712,6 +761,9 @@ do_tx_post(void) {
       CXBdata(tx.buf.o, i) = Cscl(CXBdata(tx.buf.o, i), tx.scl.post.val);
   }
 
+  if (tx.spr.flag) SpeechProcessor(tx.spr.gen);
+  if (tx.cpd.flag) WSCompand(tx.cpd.gen);
+
   if (uni.spec.flag)
     do_tx_spectrum(tx.buf.o);
 
@@ -825,16 +877,16 @@ process_samples(float *bufl, float *bufr,
        do_rx(k), rx[k].tick++;
        // mix
        for (i = 0; i < n; i++)
-          bufl[i] += CXBimag(rx[k].buf.o, i),
-         bufr[i] += CXBreal(rx[k].buf.o, i);
+          bufl[i] += (float) CXBimag(rx[k].buf.o, i),
+         bufr[i] += (float) CXBreal(rx[k].buf.o, i);
        CXBhave(rx[k].buf.o) = n;
       }
 
     // late mixing of aux buffers
     if (uni.mix.rx.flag)
       for (i = 0; i < n; i++)
-       bufl[i] += auxl[i] * uni.mix.rx.gain,
-       bufr[i] += auxr[i] * uni.mix.rx.gain;
+       bufl[i] += (float) (auxl[i] * uni.mix.rx.gain),
+       bufr[i] += (float) (auxr[i] * uni.mix.rx.gain);
 
     break;
 
@@ -843,8 +895,8 @@ process_samples(float *bufl, float *bufr,
     // early mixing of aux buffers
     if (uni.mix.tx.flag)
       for (i = 0; i < n; i++)
-       bufl[i] += auxl[i] * uni.mix.tx.gain,
-       bufr[i] += auxr[i] * uni.mix.tx.gain;
+       bufl[i] += (float) (auxl[i] * uni.mix.tx.gain),
+       bufr[i] += (float) (auxr[i] * uni.mix.tx.gain);
 
     for (i = 0; i < n; i++)
       CXBimag(tx.buf.i, i) = bufl[i], CXBreal(tx.buf.i, i) = bufr[i];