Return-Path: Received: from post.thorcom.com (post.thorcom.com [195.171.43.25]) by klubnl.pl (8.14.4/8.14.4/Debian-8+deb8u2) with ESMTP id wBTLFqxE026463 for ; Sat, 29 Dec 2018 22:15:59 +0100 Received: from majordom by post.thorcom.com with local (Exim 4.14) id 1gdLtr-0006Fc-BD for rs_out_1@blacksheep.org; Sat, 29 Dec 2018 21:12:03 +0000 Received: from [195.171.43.32] (helo=relay1.thorcom.net) by post.thorcom.com with esmtp (Exim 4.14) id 1gdLtq-0006FT-1l for rsgb_lf_group@blacksheep.org; Sat, 29 Dec 2018 21:12:02 +0000 Received: from rhcavuit04.kulnet.kuleuven.be ([2a02:2c40:0:c0::25:137]) by relay1.thorcom.net with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.91_59-0488984) (envelope-from ) id 1gdLtn-0007Zu-R2 for rsgb_lf_group@blacksheep.org; Sat, 29 Dec 2018 21:12:00 +0000 X-KULeuven-Envelope-From: rik.strobbe@kuleuven.be X-KULeuven-Scanned: Found to be clean X-KULeuven-ID: 3B200120003.A3E50 X-KULeuven-Information: Katholieke Universiteit Leuven Received: from icts-p-smtps-1.cc.kuleuven.be (icts-p-smtps-1e.kulnet.kuleuven.be [134.58.240.33]) by rhcavuit04.kulnet.kuleuven.be (Postfix) with ESMTP id 3B200120003 for ; Sat, 29 Dec 2018 22:11:43 +0100 (CET) Received: from ICTS-S-EXMBX22.luna.kuleuven.be (icts-s-exmbx22.luna.kuleuven.be [10.112.11.57]) (using TLSv1.2 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by icts-p-smtps-1.cc.kuleuven.be (Postfix) with ESMTPS id 268BF40B4 for ; Sat, 29 Dec 2018 22:11:43 +0100 (CET) Received: from ICTS-S-EXMBX27.luna.kuleuven.be (10.112.11.62) by ICTS-S-EXMBX22.luna.kuleuven.be (10.112.11.57) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Sat, 29 Dec 2018 22:11:42 +0100 Received: from ICTS-S-EXMBX27.luna.kuleuven.be ([fe80::291a:cc4f:6953:698a]) by ICTS-S-EXMBX27.luna.kuleuven.be ([fe80::291a:cc4f:6953:698a%25]) with mapi id 15.00.1395.000; Sat, 29 Dec 2018 22:11:43 +0100 X-Kuleuven: This mail passed the K.U.Leuven mailcluster From: Rik Strobbe To: "rsgb_lf_group@blacksheep.org" Thread-Topic: LF: JT9-5 decodes in km07ks Thread-Index: AQHUn1oD6Rcx4hHVo0+8PHMuvIp9f6WVdypagACqnoCAABPn6w== Date: Sat, 29 Dec 2018 21:11:43 +0000 Message-ID: <1546117902661.30732@kuleuven.be> References: <340063417.10486355.1546075700695.ref@mail.yahoo.com> <340063417.10486355.1546075700695@mail.yahoo.com> <1546076873573.21670@kuleuven.be>,<005b0259-df03-2249-3996-2828834a0072@freenet.de> In-Reply-To: <005b0259-df03-2249-3996-2828834a0072@freenet.de> Accept-Language: nl-BE, en-GB, en-US Content-Language: nl-BE X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.112.50.1] MIME-Version: 1.0 X-Spam-Score: -2.3 (--) X-Spam-Report: Spam detection software, running on the system "relay1.thorcom.net", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: Hello Wolf, thanks! since I have been playing a bit with arduino's (my 15 year old son is keen of those and I can only encourage that) I can more or less "read" C language. Content analysis details: (-2.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [2a02:2c40:0:c0:0:0:25:137 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 HTML_MESSAGE BODY: HTML included in message X-Scan-Signature: 09c8b56a50715c1e0fc689a0ac41ebdf Subject: Re: LF: JT9-5 decodes in km07ks Content-Type: multipart/alternative; boundary="_000_154611790266130732kuleuvenbe_" X-Spam-Checker-Version: SpamAssassin 2.63 (2004-01-11) on post.thorcom.com X-Spam-Level: X-Spam-Status: No, hits=0.9 required=5.0 tests=HTML_30_40,HTML_MESSAGE, LINES_OF_YELLING,LINES_OF_YELLING_2,TO_ADDRESS_EQ_REAL autolearn=no version=2.63 X-SA-Exim-Scanned: Yes Sender: owner-rsgb_lf_group@blacksheep.org Precedence: bulk Reply-To: rsgb_lf_group@blacksheep.org X-Listname: rsgb_lf_group X-SA-Exim-Rcpt-To: rs_out_1@blacksheep.org X-SA-Exim-Scanned: No; SAEximRunCond expanded to false --_000_154611790266130732kuleuvenbe_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Hello Wolf, thanks! since I have been playing a bit with arduino's (my 15 year old son is keen = of those and I can only encourage that) I can more or less "read" C langua= ge. I will appreciate it if you could send me the code snippet with data type d= efs and the filter table. I will try to translate it to Free Pascal. 73 & HNY Rik ________________________________ Van: owner-rsgb_lf_group@blacksheep.org namens Wolfgang B=FCscher Verzonden: zaterdag 29 december 2018 21:54 Aan: rsgb_lf_group@blacksheep.org Onderwerp: Re: LF: JT9-5 decodes in km07ks Hi Rik, > (maybe I should ask Wolf for advice) You're welcome. The "image rejecting up/down converter" is written in plain= C. It should be easily portable. Uses a 37-tap FIR filter for the Hilbert = transformer that rejects the "unwanted" mixing product. Not sure if the sourcecode (indentation) survives the emailing process, but= fyi it's attached below. If you think it's usable for your project, I can send everything (including= the data type definitions and the filter coefficient table). Cheers, Wolf . Below: Core of the "universal frequency converter / mixer" as currently use= d in Spectrum Lab (this is the simple one, without forward and reverse FFT)= . void SOUND_RunThroughMixer( T_SOUND_FREQ_CONVERTER *pcnv, // contains all parameters for a conve= rter T_Float *input_samples, T_Float *input_samples_q, T_Float *output_samples, T_Float *output_samples_q, int number_of_samples ) /* Frequency mixer. May transform the frequency for some kind of RX. * Can optionally cancel one sideband using a Hilbert transformer, * I/Q-mixer etc. */ { int sample_i, j; T_Float d, y, dbl_i, dbl_q; const T_Float* coeff_ptr; T_Float* queue_ptr; T_Float* input_queue_end; double dblPhzInc; int iCosTableIndex, iSineTableOffset =3D 0; T_Float dblNcoI, dblNcoQ; double dblNcoPhase =3D pcnv->dblNcoPhase; // use local var for speed // Prepare the NCO for the "mixer" frequency ... // Note: SoundTab_fltCosTable[SOUND_COS_TABLE_LEN] contains exactly ONE P= ERIOD. // "Negative" frequencies are possible by inverting the Q-channel . if(pcnv->dblFSample!=3D0) dblPhzInc =3D (double)SOUND_COS_TABLE_LEN * pcnv->dblOscillatorFreq /= pcnv->dblFSample; else dblPhzInc =3D 0; // mixer frequency is ZERO, so noo phase increment if(dblPhzInc > 0) { // array index offset to read a SINE WAVE from a COSINE TABLE : iSineTableOffset =3D (int) (0.499 + 3.0 * (T_Float)SOUND_COS_TABLE_LEN= / 4.0); } else // phase increment negative, "negative" mixer frequency .... { dblPhzInc =3D -dblPhzInc; // Make sure the table reading index INCREME= NTS, // because the wrap test will not look for neg= ative indices. // Get array index offset to read a NEGATIVE SINE WAVE from a COSINE T= ABLE : iSineTableOffset =3D (int)(0.499 + (T_Float)SOUND_COS_TABLE_LEN / 4.0)= ; } // end if if(dblNcoPhase<0) dblNcoPhase =3D 0; if(pcnv->fDcReject) { // Accumulate & remove a bit DC offset from the new chunk: for(sample_i=3D0; sample_idblMixerDcOffset =3D pcnv->dblMixerDcOffset * 0.9999 + input_samples[sample_i] * 0.0001; // bad style to modifying the INPUT samples // but this won't hurt anyone :> input_samples[sample_i] -=3D pcnv->dblMixerDcOffset; } } if(pcnv->iMixerScheme=3D=3DCFG_FREQ_MIX_DSB) { // No sideband rejection: // This is a simple and very fast mixer without sideband-rejection. // No complicated broadband 90=B0 phase shifter required. for(sample_i=3D0; sample_i=3D(T_Float)SOUND_COS_TABLE_LEN) // "while", not "= if" !! dblNcoPhase -=3D(T_Float)SOUND_COS_TABLE_LEN; // table index wr= ap d =3D SoundTab_fltCosTable[(int)dblNcoPhase]; // DSB mixer: simply multiply the input signal with the NCO output : *output_samples++ =3D (*input_samples++) * d; } } // end if else if(pcnv->iMixerScheme=3D=3DCFG_FREQ_MIX_COMPLEX) { // Complex multiplication of complex input : // (a + j*b ) * ( c + j*d ) =3D a*c - b*d + j * ( a*d + b*c ) // To do this, SOUND_RunThroughMixer() must be called with // TWO source- and TWO destination blocks. // (real and imaginary parts are in sepearate blocks) if( (input_samples!=3DNULL) && (input_samples_q!=3DNULL) &&(output_samples!=3DNULL) && (output_samples_q!=3DNULL) ) { T_Float inp_i, inp_q, outp_i, outp_q; for(sample_i=3D0; sample_i=3D(T_Float)SOUND_COS_TABLE_LEN) // "while", n= ot "if" !! dblNcoPhase -=3D(T_Float)SOUND_COS_TABLE_LEN; // table inde= x wrap iCosTableIndex =3D (int)dblNcoPhase; dblNcoI =3D SoundTab_fltCosTable[iCosTableIndex]; dblNcoQ =3D SoundTab_fltCosTable[(iCosTableIndex+iSineTableOffset= ) % SOUND_COS_TABLE_LEN]; // Get complex input sample, multiply with complex oscillator, an= d put into output buffers: inp_i =3D *(input_samples++); inp_q =3D *(input_samples_q++); outp_i =3D inp_i * dblNcoI - inp_q * dblNcoQ; outp_q =3D inp_i * dblNcoQ + inp_q * dblNcoI; *output_samples++ =3D outp_i; *output_samples_q++ =3D outp_q; } } } // end if else if( (pcnv->iMixerScheme =3D=3D CFG_FREQ_MIX_LSB_DOWNCONVERTER ) || (pcnv->iMixerScheme =3D=3D CFG_FREQ_MIX_USB_DOWNCONVERTER ) ) { // Optimized mixer for "downconversion". // Based on a schematic diagram from the ARRL handbook 1996, // page 17.73: "The R2: An image-rejecting D-C Receiver" // Principle: Splitter, TWO Mixers (with I and Q output), // audio phase shift network, summer, filter. // Note: 90=B0 phase shifting is done AFTER mixing (in contrast to t= he // schemes CFG_FREQ_MIX_LSB_UP and CFG_FREQ_MIX_USB_UP. for(sample_i=3D0; sample_i=3D(T_Float)SOUND_COS_TABLE_LEN) // "while", not = "if" !! dblNcoPhase -=3D(T_Float)SOUND_COS_TABLE_LEN; // table index wr= ap iCosTableIndex =3D (int)dblNcoPhase; dblNcoI =3D SoundTab_fltCosTable[iCosTableIndex]; dblNcoQ =3D SoundTab_fltCosTable[(iCosTableIndex+iSineTableOffset) % = SOUND_COS_TABLE_LEN]; // Now mix the incoming (higher-frequency) signal ..input_samples[].. // with a sine and a cosine signal from the NCO ("LO"). dbl_i =3D input_samples[sample_i]; // this is the INPUT signal if(pcnv->iMixerScheme =3D=3D CFG_FREQ_MIX_LSB_DOWNCONVERTER) { dbl_q =3D dbl_i * dblNcoI; // LSB (below NCO freq) moved DOWN dbl_i =3D dbl_i * dblNcoQ; } else // the "other" sideband with reversed oscillator phases: { dbl_q =3D dbl_i * dblNcoQ; // USB (above NCO freq) moved DOWN dbl_i =3D dbl_i * dblNcoI; } // arrived here: dbl_i is the output of the "I"-mixer, // dbl_q is the output of the "Q"-mixer. // Let the I-channel run through a delay line [ length (N-1)/2 ] // to compensate the delay from the hilbert trafo (see below). if( (pcnv->iDelayQIndex < 0) ||(pcnv->iDelayQIndex >=3D ((SOUND_Hilbert_filter_length-1)/2)) ) pcnv->iDelayQIndex =3D 0; y =3D pcnv->dblDelayQueue[pcnv->iDelayQIndex]; pcnv->dblDelayQueue[pcnv->iDelayQIndex++] =3D dbl_i; dbl_i =3D y; // Let the Q-channel run through a broadband 90=B0 phase shifter // (hilbert transformer, implemented as FIR filter here). // keep the circular buffer pointer 'valid' all the time : input_queue_end =3D &pcnv->dblHilbertQueue[SOUND_Hilbert_filter_lengt= h-1]; if( (pcnv->pdblHilbertQPointer < &pcnv->dblHilbertQueue[0]) ||(pcnv->pdblHilbertQPointer > input_queue_end) ) pcnv->pdblHilbertQPointer =3D &pcnv->dblHilbertQueue[0]; if( --pcnv->pdblHilbertQPointer < &pcnv->dblHilbertQueue[0] ) pcnv->pdblHilbertQPointer =3D input_queue_end; // deal with wra= paround *pcnv->pdblHilbertQPointer =3D dbl_q; // hilbert trafo input queue_ptr =3D pcnv->pdblHilbertQPointer; // pointer to read from inp= ut queue coeff_ptr =3D &SOUND_HilbertCoeffs[0]; // pointer to read from coeff = table y =3D 0.0; // clear the 'global adder' j =3D (SOUND_Hilbert_filter_length+1)/2 -1; // j=3D12 for 25th-order= filter while( j-- ) // do the MAC's (with every 2nd coeff ZERO) { // coeffs[0], [2], [4].. are (almost) zero and are not calculated // so just skip the 'queue' pointer ++queue_ptr; ++coeff_ptr; if( queue_ptr > input_queue_end ) // deal with wraparound queue_ptr =3D &pcnv->dblHilbertQueue[0]; // odd coefficients, non-zero, do a MAC-operation : y +=3D ( (*queue_ptr++) * (*coeff_ptr++) ); if( queue_ptr > input_queue_end ) // deal with wraparound queue_ptr =3D &pcnv->dblHilbertQueue[0]; } dbl_q =3D y; // filter output =3D sum from all 'taps' // finally add the output of the "audio phase-shift network"... output_samples[sample_i] =3D dbl_i + dbl_q; } // end for (sample_i ... ) } // end if <..mixer_scheme =3D=3D CFG_FREQ_MIX_USB_DOWNCONVERTER > else // neither "double side band" nor "USB DOWNCONVERTER".... { for(sample_i=3D0; sample_iiDelayQIndex < 0) ||(pcnv->iDelayQIndex >=3D ((SOUND_Hilbert_filter_length-1)/2)) ) pcnv->iDelayQIndex =3D 0; dbl_i =3D pcnv->dblDelayQueue[pcnv->iDelayQIndex]; pcnv->dblDelayQueue[pcnv->iDelayQIndex++] =3D input_samples[sample_i]; // Generate the Q-value by passing the real input through a // hilbert transformer (which is implemented as an FIR filter here). // keep the circular buffer pointer 'valid' all the time : input_queue_end =3D &pcnv->dblHilbertQueue[SOUND_Hilbert_filter_lengt= h-1]; if( (pcnv->pdblHilbertQPointer < &pcnv->dblHilbertQueue[0]) ||(pcnv->pdblHilbertQPointer > input_queue_end) ) pcnv->pdblHilbertQPointer =3D &pcnv->dblHilbertQueue[0]; if( --pcnv->pdblHilbertQPointer < &pcnv->dblHilbertQueue[0] ) pcnv->pdblHilbertQPointer =3D input_queue_end; // deal with wra= paround *pcnv->pdblHilbertQPointer =3D input_samples[sample_i]; // filter in= put =3D "X" queue_ptr =3D pcnv->pdblHilbertQPointer; // pointer to read from inp= ut queue coeff_ptr =3D &SOUND_HilbertCoeffs[0]; // pointer to read from coeff = table y =3D 0.0; // clear the 'global adder' j =3D (SOUND_Hilbert_filter_length+1)/2 -1; // j=3D12 for 25th-order= filter while( j-- ) // do the MAC's (with every 2nd coeff ZERO) { // coeffs[0], [2], [4].. are (almost) zero and are not calculated // so just skip the 'queue' pointer #if(0) // not optimized: y +=3D ( (*queue_ptr++) * (*coeff_ptr++) ); // here's the MAC #else // optimized: ++queue_ptr; ++coeff_ptr; #endif if( queue_ptr > input_queue_end ) // deal with wraparound queue_ptr =3D &pcnv->dblHilbertQueue[0]; // odd coefficients, non-zero, do a MAC-operation : y +=3D ( (*queue_ptr++) * (*coeff_ptr++) ); if( queue_ptr > input_queue_end ) // deal with wraparound queue_ptr =3D &pcnv->dblHilbertQueue[0]; } dbl_q =3D y; // filter output =3D sum from all 'taps' // Let the NCO (numerical controlled oscillator) produce quadrature-p= hase signals : dblNcoPhase +=3D dblPhzInc; while(dblNcoPhase >=3D(T_Float)SOUND_COS_TABLE_LEN) // "while", not "= if" !! dblNcoPhase -=3D(T_Float)SOUND_COS_TABLE_LEN; // table index wr= ap iCosTableIndex =3D (int)dblNcoPhase; dblNcoI =3D SoundTab_fltCosTable[iCosTableIndex]; dblNcoQ =3D SoundTab_fltCosTable[(iCosTableIndex + iSineTableOffset) = % SOUND_COS_TABLE_LEN]; if(pcnv->iMixerScheme=3D=3DCFG_FREQ_MIX_LSB_UP) { // multiply the I- and Q- samples with the sin- and cos- output // of the local oscillator. output_samples[sample_i] =3D dbl_q * dblNcoI // multiply with "cosine" - dbl_i * dblNcoQ; // multiply with "sine" } else // not LSB but USB: { output_samples[sample_i] =3D dbl_i * dblNcoI // multiply with "cosine" - dbl_q * dblNcoQ; // multiply with "sine" } } // end for (sample_i ... ) } // end if pcnv->dblNcoPhase =3D dblNcoPhase; // save the NCO phase for next block } // end SOUND_RunThroughMixer() On 29.12.2018 10:47, Rik Strobbe wrote: Hello Markus, nice copy on N1BUG, this might be a new distance record for Paul. Thanks for your help with the JT9-2 and JT9-5 resampling. Lifting the frequency restriction on TX is "peanuts", but on RX I would nee= d to implement frequency conversion in SpecLab style. I will have a look to that (maybe I should ask Wolf for advice). 73, Rik ON7YD - OR7T ________________________________ Van: owner-rsgb_lf_group@blacksheep.org namens Markus Vester Verzonden: zaterdag 29 december 2018 10:28 Aan: rsgb_lf_group@blacksheep.org Onderwerp: Re: LF: JT9-5 decodes in km07ks Thanks to Rik for the software, and to Spiros and Dionysios for their repor= ts. This is what I picked up using JT9-2 18-12-28 21:38 2038 -25 0.1 648 2 CQ SV8CS KM07 18-12-28 21:40 2040 -25 0.1 1200 2 LA3EQ JO28XJ 18-12-28 21:42 2042 -26 0.1 648 2 CQ SV8CS KM07 18-12-28 21:44 2044 -26 0.2 1200 2 LA3EQ JO28XJ 18-12-28 21:48 2048 -25 0.1 1250 2 LA3EQ JO28XJ 18-12-28 21:52 2052 -25 0.2 1250 2 LA3EQ JO28XJ 18-12-28 21:56 2056 -25 0.2 1250 2 LA3EQ JO28XJ 18-12-28 22:00 2100 -28 0.3 1250 2 LA3EQ JO28XJ and later JT9-5: 18-12-29 02:30 0130 -34 -0.7 615 5 VVV N1BUG 5 18-12-29 02:40 0140 -34 -0.6 615 5 VVV N1BUG 5 18-12-29 03:30 0230 -35 -0.6 615 5 VVV N1BUG 5 As my LF transceiver needs to be parked on 135.5 kHz I am always struggling= with audio frequency restrictions in WSJT, WSPR and JT-9 software. My work= around are frequency conversions in two separate SpecLab instances for RX a= nd TX, connected to the left and right channels of a single VB-Audio virtua= l cable instance. However there is a noticable latency in this process. Best 73, Markus (DF6NM) -----Urspr=FCngliche Mitteilung----- Von: Dionysios Vlachiotis An: rsgb_lf_group ; rsgb_lf_group Verschickt: Sa, 29. Dez 2018 8:39 Betreff: LF: JT9-5 decodes in km07ks 245 -28 -0.4 650 5 CQ DF6NM JN59 2255 -27 -0.4 650 5 CQ DF6NM JN59 2315 -27 -0.5 650 5 CQ DF6NM JN59 2325 -24 -0.3 650 5 CQ DF6NM JN59 0035 -23 -0.2 650 5 CQ DF6NM JN59 0045 -21 -0.3 650 5 CQ DF6NM JN59 73 de SV8RV Zakynthos isl. GREECE (km07ks) -----Urspr=FCngliche Mitteilung----- Von: SV8CS-Spiros Chimarios An: rsgb_lf_group Verschickt: Sa, 29. Dez 2018 5:56 Betreff: LF: SV8CS SlowJT9 Good morning. Decoded only DF6NM during the night (JT9-5) - 136 KHz. 2245 -30 -0.4 650 5 CQ DF6NM JN59 2255 -29 -0.4 650 5 CQ DF6NM JN59 2315 -27 -0.4 650 5 CQ DF6NM JN59 2325 -26 -0.4 650 5 CQ DF6NM JN59 0035 -21 -0.6 650 5 CQ DF6NM JN59 0045 -20 -0.4 650 5 CQ DF6NM JN59 73, Spiros/SV8CS --_000_154611790266130732kuleuvenbe_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable

Hello Wolf,


thanks!

since I have been playing a bit with arduino's (my 15 year old=  son is keen of those  and I can only encourage that) I can = more or less "read" C language.

I will appreciate it if you could send me the code snippet wit= h data type defs and the filter table.

I will try to translate it to Free Pascal.


73 & HNY


Rik



Van: owner-rsgb_lf_group@bl= acksheep.org <owner-rsgb_lf_group@blacksheep.org> namens Wolfgang B= =FCscher <dl4yhf@freenet.de>
Verzonden: zaterdag 29 december 2018 21:54
Aan: rsgb_lf_group@blacksheep.org
Onderwerp: Re: LF: JT9-5 decodes in km07ks
 
Hi Rik,

>  (maybe I should ask Wolf for advice)

You're welcome. The "image rejecting up/down converter" is writte= n in plain C. It should be easily portable. Uses a 37-tap FIR filter for th= e Hilbert transformer that rejects the "unwanted" mixing product.=
Not sure if the sourcecode (indentation) survives the emailing process, but= fyi it's attached below.
If you think it's usable for your project, I can send everything (including= the data type definitions and the filter coefficient table).

Cheers,
  Wolf .

Below: Core of the "universal frequency converter / mixer" as cur= rently used in Spectrum Lab (this is the simple one, without forward and re= verse FFT).


void SOUND_RunThroughMixer(
      T_SOUND_FREQ_CONVERTER *pcnv,  // conta= ins all parameters for a converter
      T_Float *input_samples,  T_Float *input= _samples_q,
      T_Float *output_samples, T_Float *output_sam= ples_q,
      int    number_of_samples )  /* Frequency mixer. May transform the frequency for some kind of RX.<= br>   * Can optionally cancel one sideband using a Hilbert transformer,   * I/Q-mixer etc.
  */
{
 int    sample_i, j;
 T_Float d, y, dbl_i, dbl_q;
 const T_Float* coeff_ptr;
 T_Float* queue_ptr;
 T_Float* input_queue_end;
 double  dblPhzInc;
 int     iCosTableIndex, iSineTableOffset =3D 0;  T_Float dblNcoI, dblNcoQ;
 double  dblNcoPhase =3D pcnv->dblNcoPhase;  // use local= var for speed


  // Prepare the NCO for the "mixer" frequency ...
  // Note: SoundTab_fltCosTable[SOUND_COS_TABLE_LEN] contains exactly = ONE PERIOD.
  //       "Negative" frequenc= ies are possible by inverting the Q-channel .
  if(pcnv->dblFSample!=3D0)
      dblPhzInc =3D (double)SOUND_COS_TABLE_LEN * = pcnv->dblOscillatorFreq / pcnv->dblFSample;
    else
      dblPhzInc =3D 0;   // mixer freque= ncy is ZERO, so noo phase increment

  if(dblPhzInc > 0)
   { // array index offset to read a SINE WAVE from a COSINE TABL= E :
     iSineTableOffset =3D (int) (0.499 + 3.0 * (T_F= loat)SOUND_COS_TABLE_LEN / 4.0);
   }
  else   // phase increment negative, "negative" m= ixer frequency ....
   {
     dblPhzInc =3D -dblPhzInc; // Make sure the table r= eading index INCREMENTS,
            &nb= sp;            =     // because the wrap test will not look for negative indi= ces.
     // Get array index offset to read a NEGATIVE SINE = WAVE from a COSINE TABLE :
     iSineTableOffset =3D (int)(0.499 + (T_Float)SO= UND_COS_TABLE_LEN / 4.0);
   } // end if <produce NEGATIVE frequencies ... possible only= with I/Q mult. >
  if(dblNcoPhase<0) dblNcoPhase =3D 0;


  if(pcnv->fDcReject)
   { // Accumulate & remove a bit DC offset from the new chun= k:
     for(sample_i=3D0; sample_i<number_of_samples; &= #43;+sample_i)
       {
         pcnv->dblMixerDcOffset = =3D
            &nb= sp;        pcnv->dblMixerDcOffset&nbs= p; * 0.9999
            &nb= sp;      + input_samples[sample_i] * 0.0001;          // bad style to modifying = the INPUT samples
         //  but this won't hu= rt anyone :>
         input_samples[sample_i] -= =3D pcnv->dblMixerDcOffset;
       }
   }

  if(pcnv->iMixerScheme=3D=3DCFG_FREQ_MIX_DSB)
   { // No sideband rejection:
     //   This is a simple and very fast mixe= r without sideband-rejection.
     //   No complicated broadband 90=B0 phas= e shifter required.
    for(sample_i=3D0; sample_i<number_of_samples; +&#= 43;sample_i)
     {
      // Run the NCO (numerical controlled oscilla= tor)
      dblNcoPhase +=3D dblPhzInc;
      while(dblNcoPhase >=3D(T_Float)SOUND_COS_= TABLE_LEN) // "while", not "if" !!
            dblNcoPh= ase -=3D(T_Float)SOUND_COS_TABLE_LEN; // table index wrap
      d =3D SoundTab_fltCosTable[(int)dblNcoPhase]= ;

      // DSB mixer: simply multiply the input sign= al with the NCO output :
      *output_samples++ =3D (*input_sample= s++) * d;
     }
   }  // end if <frequency converter WITHOUT sideband rej= ection>
  else
  if(pcnv->iMixerScheme=3D=3DCFG_FREQ_MIX_COMPLEX)
   { // Complex multiplication of complex input :
     //   (a + j*b ) * ( c + j*d )&nb= sp; =3D  a*c - b*d + j * ( a*d + b*c )
     // To do this, SOUND_RunThroughMixer() must be cal= led with
     //   TWO source-  and TWO destinati= on blocks.
     //  (real and imaginary parts are in sepearat= e blocks)
     if(  (input_samples!=3DNULL) && (inpu= t_samples_q!=3DNULL)
        &&(output_samples!=3DNUL= L) && (output_samples_q!=3DNULL) )
      {
        T_Float inp_i, inp_q, outp_i, ou= tp_q;
        for(sample_i=3D0; sample_i<nu= mber_of_samples; ++sample_i)
         {
          // Run the NCO (nume= rical controlled oscillator; here with quadrature output)
          dblNcoPhase +=3D= dblPhzInc;
          while(dblNcoPhase &g= t;=3D(T_Float)SOUND_COS_TABLE_LEN) // "while", not "if"= !!
            &nb= sp;   dblNcoPhase -=3D(T_Float)SOUND_COS_TABLE_LEN; // table inde= x wrap
          iCosTableIndex =3D (= int)dblNcoPhase;
          dblNcoI =3D SoundTab= _fltCosTable[iCosTableIndex];
          dblNcoQ =3D SoundTab= _fltCosTable[(iCosTableIndex+iSineTableOffset) % SOUND_COS_TABLE_LEN];<= br>
          // Get complex input= sample, multiply with complex oscillator, and put into output buffers:
          inp_i =3D *(input_sa= mples++);
          inp_q =3D *(input_sa= mples_q++);
          outp_i =3D inp_i * d= blNcoI - inp_q * dblNcoQ;
          outp_q =3D inp_i * d= blNcoQ + inp_q * dblNcoI;
          *output_samples+= +   =3D outp_i;
          *output_samples_q= 3;+ =3D outp_q;
         }
     }
   }  // end if <frequency converter WITHOUT sideband rej= ection>
  else
  if(   (pcnv->iMixerScheme =3D=3D CFG_FREQ_MIX_LSB_DOWNC= ONVERTER )
     || (pcnv->iMixerScheme =3D=3D CFG_FREQ_MIX_USB_= DOWNCONVERTER ) )
   {   // Optimized mixer for "downconversion"= ;.
       // Based on a schematic diagram from t= he ARRL handbook 1996,
       // page 17.73:   "The R= 2: An image-rejecting D-C Receiver"
       // Principle: Splitter, TWO Mixers (wi= th I and Q output),
       //      =       audio phase shift network, summer, filter.        // Note: 90=B0 phase shifting is done = AFTER mixing (in contrast to the
       //      =      schemes  CFG_FREQ_MIX_LSB_UP  and  = CFG_FREQ_MIX_USB_UP.
    for(sample_i=3D0; sample_i<number_of_samples; +&#= 43;sample_i)
     {
      // Let the NCO (numerical controlled oscilla= tor) produce quadrature-phase signals :
      dblNcoPhase +=3D dblPhzInc;
      while(dblNcoPhase >=3D(T_Float)SOUND_COS_= TABLE_LEN)  // "while", not "if" !!
            dblNcoPh= ase -=3D(T_Float)SOUND_COS_TABLE_LEN; // table index wrap
      iCosTableIndex =3D (int)dblNcoPhase;
      dblNcoI =3D SoundTab_fltCosTable[iCosTableIn= dex];
      dblNcoQ =3D SoundTab_fltCosTable[(iCosTableI= ndex+iSineTableOffset) % SOUND_COS_TABLE_LEN];

      // Now mix the incoming (higher-frequency) s= ignal ..input_samples[]..
      //       =   with a sine and a cosine signal from the NCO ("LO").
      dbl_i =3D input_samples[sample_i]; &nbs= p; // this is the INPUT signal

      if(pcnv->iMixerScheme =3D=3D CFG_FREQ_MIX= _LSB_DOWNCONVERTER)
       {
        dbl_q =3D  dbl_i * dblNcoI;=    // LSB (below NCO freq) moved DOWN
        dbl_i =3D  dbl_i * dblNcoQ;=
       }
      else  // the "other" sideband= with reversed oscillator phases:
       {
        dbl_q =3D  dbl_i * dblNcoQ;=    // USB (above NCO freq) moved DOWN
        dbl_i =3D  dbl_i * dblNcoI;=
       }
      // arrived here: dbl_i is the output of the = "I"-mixer,
      //       =         dbl_q is the output of the "= ;Q"-mixer.


      // Let the I-channel run through a delay lin= e [ length (N-1)/2 ]
      //  to compensate the delay from the hi= lbert trafo (see below).
      if(  (pcnv->iDelayQIndex < 0)
         ||(pcnv->iDelayQIndex &= gt;=3D ((SOUND_Hilbert_filter_length-1)/2)) )
            pcnv->= ;iDelayQIndex =3D 0;
      y =3D pcnv->dblDelayQueue[pcnv->iDelay= QIndex];
      pcnv->dblDelayQueue[pcnv->iDelayQIndex= ++] =3D dbl_i;
      dbl_i =3D y;

      // Let the Q-channel run through a broadband= 90=B0 phase shifter
      // (hilbert transformer, implemented as FIR = filter here).
      //    keep the circular buffe= r pointer 'valid' all the time :
      input_queue_end =3D &pcnv->dblHilbert= Queue[SOUND_Hilbert_filter_length-1];
      if(  (pcnv->pdblHilbertQPointer <= &pcnv->dblHilbertQueue[0])
         ||(pcnv->pdblHilbertQPo= inter > input_queue_end) )
            pcnv->= ;pdblHilbertQPointer =3D &pcnv->dblHilbertQueue[0];
      if( --pcnv->pdblHilbertQPointer < &= ;pcnv->dblHilbertQueue[0] )
            pcnv->= ;pdblHilbertQPointer =3D input_queue_end; // deal with wraparound
      *pcnv->pdblHilbertQPointer =3D dbl_q;&nbs= p;    // hilbert trafo input
      queue_ptr =3D pcnv->pdblHilbertQPointer;&= nbsp; // pointer to read from input queue
      coeff_ptr =3D &SOUND_HilbertCoeffs[0]; /= / pointer to read from coeff table
      y =3D 0.0;     &nbs= p;            // cle= ar the 'global adder'
      j =3D (SOUND_Hilbert_filter_length+1)/2 = -1;  // j=3D12 for 25th-order filter
      while( j-- )     &n= bsp;        // do the MAC's (with every = 2nd coeff ZERO)
        {
         // coeffs[0], [2], [4].. a= re (almost) zero and are not calculated
         //    =             &nb= sp;      so just skip the 'queue' pointer
         ++queue_ptr; = ++coeff_ptr;
         if( queue_ptr > input_q= ueue_end ) // deal with wraparound
             qu= eue_ptr =3D &pcnv->dblHilbertQueue[0];
         // odd coefficients, non-z= ero, do a MAC-operation :
         y +=3D ( (*queue_ptr&#= 43;+) * (*coeff_ptr++) );
         if( queue_ptr > input_q= ueue_end ) // deal with wraparound
             qu= eue_ptr =3D &pcnv->dblHilbertQueue[0];
        }
      dbl_q =3D y;    // filter out= put =3D sum from all 'taps'

      // finally add the output of the "audio= phase-shift network"...
      output_samples[sample_i] =3D dbl_i + dbl= _q;

     } // end for (sample_i ... )
   } // end if <..mixer_scheme =3D=3D CFG_FREQ_MIX_USB_DOWNCON= VERTER >
  else // neither "double side band" nor "USB DOWNCONVE= RTER"....
   {
    for(sample_i=3D0; sample_i<number_of_samples; +&#= 43;sample_i)
     {
      // Let the I-value run through a delay line = [ length (N-1)/2 ]
      //  to compensate the delay from the hi= lbert trafo (see below).
      if(  (pcnv->iDelayQIndex < 0)
         ||(pcnv->iDelayQIndex &= gt;=3D ((SOUND_Hilbert_filter_length-1)/2)) )
            pcnv->= ;iDelayQIndex =3D 0;
      dbl_i =3D pcnv->dblDelayQueue[pcnv->iD= elayQIndex];
      pcnv->dblDelayQueue[pcnv->iDelayQIndex= ++]
            =3D inpu= t_samples[sample_i];

      // Generate the Q-value by passing the real = input through a
      // hilbert transformer (which is implemented= as an FIR filter here).
      //    keep the circular buffe= r pointer 'valid' all the time :
      input_queue_end =3D &pcnv->dblHilbert= Queue[SOUND_Hilbert_filter_length-1];
      if(  (pcnv->pdblHilbertQPointer <= &pcnv->dblHilbertQueue[0])
         ||(pcnv->pdblHilbertQPo= inter > input_queue_end) )
            pcnv->= ;pdblHilbertQPointer =3D &pcnv->dblHilbertQueue[0];
      if( --pcnv->pdblHilbertQPointer < &= ;pcnv->dblHilbertQueue[0] )
            pcnv->= ;pdblHilbertQPointer =3D input_queue_end; // deal with wraparound
      *pcnv->pdblHilbertQPointer =3D input_samp= les[sample_i];  // filter input =3D "X"
      queue_ptr =3D pcnv->pdblHilbertQPointer;&= nbsp; // pointer to read from input queue
      coeff_ptr =3D &SOUND_HilbertCoeffs[0]; /= / pointer to read from coeff table
      y =3D 0.0;     &nbs= p;            // cle= ar the 'global adder'
      j =3D (SOUND_Hilbert_filter_length+1)/2 = -1;  // j=3D12 for 25th-order filter
      while( j-- )     &n= bsp;        // do the MAC's (with every = 2nd coeff ZERO)
        {
         // coeffs[0], [2], [4].. a= re (almost) zero and are not calculated
         //    =             &nb= sp;      so just skip the 'queue' pointer
#if(0)   // not optimized:
         y +=3D ( (*queue_ptr&#= 43;+) * (*coeff_ptr++) );  // here's the MAC
#else    // optimized:
         ++queue_ptr; = ++coeff_ptr;
#endif
         if( queue_ptr > input_q= ueue_end ) // deal with wraparound
             qu= eue_ptr =3D &pcnv->dblHilbertQueue[0];
         // odd coefficients, non-z= ero, do a MAC-operation :
         y +=3D ( (*queue_ptr&#= 43;+) * (*coeff_ptr++) );
         if( queue_ptr > input_q= ueue_end ) // deal with wraparound
             qu= eue_ptr =3D &pcnv->dblHilbertQueue[0];
        }
      dbl_q =3D y;    // filter out= put =3D sum from all 'taps'

      // Let the NCO (numerical controlled oscilla= tor) produce quadrature-phase signals :
      dblNcoPhase +=3D dblPhzInc;
      while(dblNcoPhase >=3D(T_Float)SOUND_COS_= TABLE_LEN) // "while", not "if" !!
            dblNcoPh= ase -=3D(T_Float)SOUND_COS_TABLE_LEN; // table index wrap
      iCosTableIndex =3D (int)dblNcoPhase;
      dblNcoI =3D SoundTab_fltCosTable[iCosTableIn= dex];
      dblNcoQ =3D SoundTab_fltCosTable[(iCosTableI= ndex + iSineTableOffset) % SOUND_COS_TABLE_LEN];

      if(pcnv->iMixerScheme=3D=3DCFG_FREQ_MIX_L= SB_UP)
       {
        // multiply the I- and Q- sample= s with the sin- and cos- output
        //     of th= e local oscillator.
        output_samples[sample_i] =3D
            &nb= sp; dbl_q * dblNcoI  // multiply with "cosine"
            - dbl_i = * dblNcoQ; // multiply with "sine"
       }
      else // not LSB but USB:
       {
        output_samples[sample_i] =3D
            &nb= sp; dbl_i * dblNcoI  // multiply with "cosine"
            - dbl_q = * dblNcoQ; // multiply with "sine"
       }
     } // end for (sample_i ... )
   } // end if <frequency UP converter with sideband rejection= >

  pcnv->dblNcoPhase =3D dblNcoPhase;  // save the NCO phase fo= r next block

} // end SOUND_RunThroughMixer()




On 29.12.2018 10:47, Rik Strobbe wrote:

Hello Markus,


nice copy on N1BUG, this might be a new distance record for Paul.


Thanks for your help with the JT9-2 and JT9-5 resampling.

Lifting the frequency restriction on TX is "peanuts", but on R= X I would need to implement frequency conversion in SpecLab style.

I will have a look to that (maybe I should ask Wolf for advice).


73, Rik  ON7YD - OR7T




Van: owner-rsgb_lf_group@blacksheep.org <owner-rsgb_lf_group@blacksheep.org> namens Markus Vester <markusvester@aol.com>
Verzonden: zaterdag 29 december 2018 10:28
Aan: rsgb_lf_group@blacksheep.org
Onderwerp: Re: LF: JT9-5 decodes in km07ks
 
Thanks to Rik for the software, and to Spiros and Dionysios for their = reports. This is what I picked up using JT9-2

18-12-28 21:38 2038 -25  0.1  648 2  CQ SV8CS KM07 &nbs= p;      
18-12-28 21:40 2040 -25  0.1 1200 2  LA3EQ JO28XJ  &nbs= p;      
18-12-28 21:42 2042 -26  0.1  648 2  CQ SV8CS KM07 &nbs= p;      
18-12-28 21:44 2044 -26  0.2 1200 2  LA3EQ JO28XJ  &nbs= p;      
18-12-28 21:48 2048 -25  0.1 1250 2  LA3EQ JO28XJ  &nbs= p;      
18-12-28 21:52 2052 -25  0.2 1250 2  LA3EQ JO28XJ  &nbs= p;      
18-12-28 21:56 2056 -25  0.2 1250 2  LA3EQ JO28XJ  &nbs= p;      
18-12-28 22:00 2100 -28  0.3 1250 2  LA3EQ JO28XJ  &nbs= p;      

and later JT9-5:

18-12-29 02:30 0130 -34 -0.7  615 5  VVV N1BUG 5   = ;       
18-12-29 02:40 0140 -34 -0.6  615 5  VVV N1BUG 5   = ;       
18-12-29 03:30 0230 -35 -0.6  615 5  VVV N1BUG 5   = ;       

As my LF transceiver needs to be parked on 135.5 kHz I am al= ways struggling with audio frequency restrictions in WSJT, WSPR&n= bsp;and JT-9 software. My workaround are frequency conversions in two separ= ate SpecLab instances for RX and TX, connected to the left and ri= ght channels of a single VB-Audio virtual cable instance. However th= ere is a noticable latency in this process.

Best 73,
Markus (DF6NM)


-----Urspr=FCngliche Mitteilung-----
Von: Dionysios Vlachiotis <sv8rv@otenet.gr>
An: rsgb_lf_group <rsgb_lf_group@blacksheep.org>; rsgb_lf_group <rsgb_lf_group@yahoogroups.co.uk>
Verschickt: Sa, 29. Dez 2018 8:39
Betreff: LF: JT9-5 decodes in km07ks

245 -28 -0.4  650 5  CQ DF6NM JN59    &n= bsp;   
2255 -27 -0.4  650 5  CQ DF6NM JN59    &= nbsp;   
2315 -27 -0.5  650 5  CQ DF6NM JN59    &= nbsp;   
2325 -24 -0.3  650 5  CQ DF6NM JN59    &= nbsp;   
0035 -23 -0.2  650 5  CQ DF6NM JN59    &= nbsp;   
0045 -21 -0.3  650 5  CQ DF6NM JN59    &= nbsp;
 
73 de SV8RV
Zakynthos isl. GREECE (km07ks)

-----Urspr=FCngliche Mitteilung-----
Von: SV8CS-Spiros Chimarios <zante@otenet.gr>
An: rsgb_lf_group <rsgb_lf_group@blacksheep.org>
Verschickt: Sa, 29. Dez 2018 5:56
Betreff: LF: SV8CS SlowJT9

Good morning.
Decoded only DF6NM during the night (JT9-5) – 136 KHz.
 
2245 -30 -0.4  650 5  CQ DF6NM JN59    &= nbsp;   
2255 -29 -0.4  650 5  CQ DF6NM JN59    &= nbsp;   
2315 -27 -0.4  650 5  CQ DF6NM JN59    &= nbsp;   
2325 -26 -0.4  650 5  CQ DF6NM JN59    &= nbsp;   
0035 -21 -0.6  650 5  CQ DF6NM JN59    &= nbsp;   
0045 -20 -0.4  650 5  CQ DF6NM JN59 
 
73, Spiros/SV8CS

--_000_154611790266130732kuleuvenbe_--