From 6717abe877cd4831bccafc95879c6a7a14a9cf30 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 26 Oct 2021 21:50:38 +0100 Subject: [PATCH] Noise Figure plugin - add support for sweeping gain and other device settings. --- .../NoiseFigure_plugin_gain_comparison.png | Bin 0 -> 24127 bytes plugins/channelrx/noisefigure/noisefigure.cpp | 123 ++++++++-------- plugins/channelrx/noisefigure/noisefigure.h | 22 +-- .../channelrx/noisefigure/noisefiguregui.cpp | 61 +++++--- .../channelrx/noisefigure/noisefiguregui.h | 5 +- .../channelrx/noisefigure/noisefiguregui.ui | 90 ++++++++++-- .../noisefigure/noisefiguresettings.cpp | 29 ++-- .../noisefigure/noisefiguresettings.h | 12 +- plugins/channelrx/noisefigure/readme.md | 45 ++++-- .../api/swagger/include/NoiseFigure.yaml | 12 +- .../qt5/client/SWGNoiseFigureSettings.cpp | 133 +++++++++++------- .../code/qt5/client/SWGNoiseFigureSettings.h | 38 ++--- 12 files changed, 363 insertions(+), 207 deletions(-) create mode 100644 doc/img/NoiseFigure_plugin_gain_comparison.png diff --git a/doc/img/NoiseFigure_plugin_gain_comparison.png b/doc/img/NoiseFigure_plugin_gain_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..87d5cd54e1c46e32dd4d2eec60598ea2d3b85f1f GIT binary patch literal 24127 zcmZsC1yo$yvTfrI4GHc}a19XL9RdV*4+H`sxVyUt4FN)e2X}YZ;1=B7?eFHCd(OM> zzaB7}-mJZPNv*0mtL6@Ut0;wrOn?jmfzV{6#Z^Ec=vEL2N&yiXxZ)eGNC~__eO8eY z1(ggF?EoKOEkqPVK%igIDECHiz-J^oX|2y75PApX7plkhhbai8Hz^}7^3Fy7AOpz| zd#dTF$724<>Y>KdMvq?ScUoD9rVjnP%YDKR(A$NjVNjxEC{(r8um<7Cb4hnXhYkuD6vzcufsE$x2E7ytcD zq(}sRQwQcAEfK45ovfOa&$3ozlF2a@?EX;$`DnexLX7SX4hd){UFLS2q^q;v=w}!a zOmePN3)9qk&>gLKaTe8Y-a++JJ@{Q-Qq3tnsP$z`+v>85avX`*^=ixg220}~SW61@ zBKflbho8H#p%D^lJ$@6;LTuq&Zi>>oF3tFKjLV{hT6}ssY zdb&~4R~CuL4b?E07}|aF-4sJ{FqK-3iDH^Kydd}7ftNNV@lpJk%__Bad-YIDY34;> z%y~?bRLH9j%4!<8TAdSwq##h1@p}*H6yA&eQ1hBA!taXl1u8p@og=yK6C3GdKhh>O6`im1O`W^rkLOcFl30_Q%qkBIu%JIQpbedO@To2L1QPYvdMQ_ z*!r$XK)X3d2?A`?*`N)mxbXXOp`%=S8B7I40p7%l#bIkHH#{+>F#;&eMU2l-(P$RHn%gX1xP;w0Ex#Jku*&8UK zL99&1&?0mU40n45PyPM5!UaWx#shnw=~rf#j||h#Ub9ttRK=YtiL?x z!|^Eaz0O-h!3AliHg^Z-s0qa%dX~7E`3Z!6#gI|QrB`DD8fmz&WgiQAtU`lORw;bR z_;1$ZpJ>I97jnN9T48z;u`hZV7>m72zSY6kt}iGk@H3lU+#y$sCfZBA2sjQzabxl4 zp);5Rfl>$_PO_``FCg2sctu1=vUGhiII!qkKcgEj^BDo%YxQmKu}Se$$%peZqW)7Z6eBD115tsO%-ReH{gjvZzt zEst&=$0>@2sA2Y5L9N6j#KWF{#^!DXcyx8Zlxi8I-5=u4uUei2I62Sbl>}EEL9Jg! zqoztqN}jHxpUBLTgXfuQ7O-$|oGOUp?&5Q<44!UrZGVq%&Asf7z~}hzyC@_iWJK_; zC_g_~r|QRaw>0S$Lj(rs8h!u`of#`6CI*ZO2Du=u{=h-6DfPN2j?9?1 zZOK5zx3RHd4n}&Y(sMtkdO;(vS#F9%NZiW>>su6QZM-}AGt29C2Z7Y%tA6nS8#J(= z&29Gn{^6ycF0E=gEJiW~c%4rP0yQ}u(K>Kn?p9v?IfQymhd!fY-tBPuus{kuyl; zv>exHKE<{_Ht>G9Sa%B)MlO;~l}>D!TV=4vxLR9Cl!^*(Y;cJbWlXIPQVtJu(7qF1 zN(%cXkpo{XYO;{1k>ET{r*9OKIT{(RN8wfJn9vBz1hw+&o;7}zhL47b=vJPrmt8=h z19!b(IC)qQz2s0YL)#%$gI_Xk_+{Q3&8Dkekj4ym2d=d~nHp|JbN?O@wWM0II&KDj zrrdH!VSac4b$R;h9Z)OT>8I}qb?VobH7%aOgSOsx^No#-gtm>bx@^bh9ru9MF0^<* z-5s?&WxnWiS!wl+7J5u+APDL)l!{yOeoAt^DLBiki1t6k{j9>>+|EEkDPx;-;vXA# zW_$%1LJkh@Nc^R(M_$@AZ$Dx7u8P+zVNKCDTk$If!YjG6Fx(IE=%5H;XC^&)E*`vF z@}C@27D4&nqgJ@EwSaC>3?uKxVH{R{Z9!s5{oF^!y0qJVt_LPXnY6pY2STNOV8j{SnEe~^0xfYL z@yScq*1I2CQq#=3l=U`W4o&s_PB5DM^Fu# zv@>(dN{w8sKBiVC*BmB}&x|{lRI|i2)L5us>U2UGsQbGGTF-u)P_ZK54VWrszeMhX z8<$LHrkJmt>%lon=iC{zeBH9DDYSD)l}gZS4y@oZucgb#7Y>h-Kj%9f@ia&e2v7qT z(+1v0O;_et5g*?tP#5%m-8E=H^-+4s53Z-=T33laq={n)P(Q)pDN4 z@=1fqLxO!FcLQ(|me$r(#lXw9`G)2dCl}Yl&4~BrkoNl2cH09Fme$v+U6i}!tdx$@ z+R(szsnSKc@{g_p(Ijptr}{0_4Bp5es%tg}4;DvsuC9j7{f(A?H#m{s8Mff=9&|!6n#J+2Y>6A^Zq)X{&u|qLm z<7!_(z!K|&d9jAOTd(Ey@G7TGty{gF7y1Pi^QA;drW2!aFe9(!kRU?g6oZ4cqWCA^G zLvlLSiO~GZCLxxgOp0DX${-AP6H;CY)p~=Ot8Vcd2P*?H=aIYdPCnY`Z%TeW?@%{~%DB6}tsS4fTcF7dEMN>ytkfS9REE!!NSq|`KHph zV{!kmDId84#a*&Ut0L=dIZb4yng3vFUn(}ZH?+kr)4yG{d}wNOKke5O!y4=5 zdD)qVfsO;?q4`7Z*IkwDglb7I6jLG;n9=!x!&l`ZzKwD0zshK!>bGWAY4G#h)*`u= z47a|geN1IFYCi&8myT^y;(E*S-O^Qid;26xf8nZKJn|A5rKYBuPfcC$-Rv(N#r-8A z>o))U1V#P6K8>{xSE~0}x_aXr9v4<_x=8{q+yWEh5;W$j{_?N!vCK5!?EkQ=22*VG zy%^j!{(M=?gA5yd@<5V=gEvFLQftssAeZKjTa>g69aPH>uD#w{G2F&SlpM)ypP~_sGt~_3cF+Dw@1?!2ru#EbRJRQSf*bLv5vK|j?z4mFu=x!L9G%7SF}Iwy#}}%{n%Fx!j$}w+C?w*J znIfKLdIa8G%KT>lPaCSGGB0SAHn>2O*BdJcs_5}xjEWv z&mq>CiEGcTPvk51WfnQAEcwP&$`oB#DY5YK#kc=d%~uOwPh9_mz}No$RX_61Ce6Sj zB~5IxGN0Dj6v?e7rA@w`q2#Qd*UpD<(-Ta}YdyrCTeU(8mR;t^6i!Q6tsu3aXgrZ5 zBQp@szDmd92AqgsJLfSxzRJUTyi#w7a0y5A*9`zlQ&rh zAmf*Y#h&d=udKwb&Zdq=4B}Rx4Wo1TrC+t5T~&K2*jnDwXWO_h61We9=XM6N(XDLbX5s(MaKmukKu5U;eD-~2AsQY+=;HPBC0 zc~fVhy85vizMM!)n;Ciq(*eN|rjC=`B%pyW6+lRqHa5irq>(51{P1v98yjd{M`&v! zEKUN+TK7vC5~scu=GR{q&{zh{4;2ND291gl!VmYEmL&cf;F2DTbKfwsA|dTDwv&KH zt!)Zqd?lH#i_Ks3?s9J?HJi(vkD9M;P79d#Y)=4#QcCAk`_J&$q=4Z$Y`J#@j{M@1 z&)__{P-Qd)MRZ_rXr$QLfuB-vWTL*ye>qKCz7Lun>XeSF*KLv=-luG-dF@?X>3%7h zDv25s8(zI0z0lM@q2_6OkR+kOUHr`z9+YXKa><<^}#>dB(A1`YfnM)56HS|B}r?qd7<&b(Dx5dT9`T6;+ z^+dN^Ex7|fN2*E!7yhL8D_<-!T^}6n3mm`d6N+7%Xq%Ie`uY3k9UgvENqLm^Dyek7 z3`%w#03kj;{=Ua_*KnyX*on4Q*qg2V!#hq0LN%#tYxB1t3rfcfKdmA9ZmmU?aeAF_ z6ja!tagc;l{IDdg&kZeOh$CalYl>mmdb}64v;<(~{pH7lWgKQ*Jbe7V`E)XW6nwI4 zXeXC6RPLYG01b3obetYa0R55Ykvkq4z&_S__#Jl>9+ho~C{1ANoNoMfORqV4v4hSIRFX|#0UG4tzX6YM zQu+xiqz96ZfdGp}bPyg@Z`%a~t3iGNw!^DJy@5$72_#3njfx*u>i0_ac6O8>S272x zVhiKF->jahNCIr>c$x|vdg z-|hT8yMD|b%;pNFX(xGMy~_y&Ujc%%4XP15ghc4Khxz-b2!ng^M6kedWdOxAjJdw@ zesaD@Uj>cyw1;rielS5qf`tOwF0}$}!(pL8D;)6lf;f^y?JFgbE9t@@V1hRY2oT~~ zL*@$*&Hz+&^;_a+{+I$=!vXew>e+Hd0)avIcUw>#{;d zK3%hXf{gohBSE))db!`6BH;BGmH_qCzoorGP#q&o4saS5lItmmbKtjaUq6vQb9O=; zR+bY@by9a4_bNC5!`{fhLCl0vwjYd(Ny-xZtVNRa(xmTcc>5NUm=P9{RKsDLbfRZ!1|+ zMqbep?8#0k1-=^xOF}07qQTTN!$|9m05~{3!7&$QW&?hw`_msWWA^wUR&f_D-xRG{ z-GV`(;ST|$E2G0JDG&K0%?jtDMx5L*ARo@uT*PECS?7VZj>B?O!WxdK#`|(krX*^# z9E%~;`thzfBv31OwF{QQd;-gI-bA6Xd;8<=o2AMmMbY6QA(Hx?z=*d?D^XqHn<#(K zKp-JXMmoCfJ94Ib9Ldoq{>+>&CO<~zT+KF_Z%)@jEqlDBw`c>}d_(S_L5hGo^dy>5g#0Ml^gF5R6~CTHl@l$rE+qE+s1Z zk}R3DJ=s$BdoSz8Tc@C3u%c)(H2la@_c0-;Q9DVX)fD`-Ra7l#5tRTv5hbOSXhB4z z&h7n0cTul5f(@B!UFV|cF^#uFQb9R=gVzc?2Df81n%Uk+0X5Ctvk5|$_pl{(^Yw3P z7C8i;QeHl+RoFi9NIr&{zdwJ#AL~g=<&x_g-|_b|tSPyFg+mcwVvdg?h0ykSMWy)6 zc;I9}mBes)i74ZwwX#r;I85iLtAt^^a_3df#_o14olPNQkYVNDH!3QxyLz@ADiSo_ zGoku!N^O0NXTQwiy}SJ4KOmO6DMT+s&Q@`JkkvUV8nSRMD)~d@tGY$=c@Cco639@- znm4$Y?Q!DHUvjA>{N-hDG+$-npzHlVAo3vUly<%r7Al+2 zsExS=AtZ|myiW|d=woZANEU#Pq8ggb_E@)~@bUK?6Ggbwe8&Gd94XYcZza3Z{!a_- z*WPeZE%?ul8p`S0J3SW+L~m&__`N2`D1AiIu@H^w+us=@O40-wa<&xBSP+vFaSXWd z0N(FAmKdwH#^XyA%yza=ykW_p0z6(_=CrPc+;1%T%fO^w5!wp~+1N zA-B*2oy8B>6aU6-XRC+^&hcNdq-TT8aokY)1qS*KA;$~VCD4;?^(OgtAD^z~i60Ny zHJ__bzyt$;6+@J)0+wd5T;2BW<^Rz`I(gFWuC}$kiNhxp{q-o4~$B~vxX zaOlb^)(uxRke+wJ!{7TqHqsc@LJjuk6M_NSXc9Xq3v6#m<->})7(P$lqHpv{t}IO~ z*CeVL^PNJ{|26dVY;0h1~iZJ4A5X63&yTB1Nm}>*kN~UIx z@l%0zgN$pd+hi`OvZ!tE^=?!d#StwKB^0@HJG}452>tY8PwZgREy!TKA*Q6a9WCUR zaqSt{{K0r)RQ50q`d67o3$XP6-x{WqzZ7FF$XhN*f){EGgjfg2cC7{}z!U3FLlL9~ z21}qXfMg8c?p%fuXZ9Mn;A49{?%I>}0&zl7)X)i78lS08vSa}WH1fbPn8X!hMGqv} zfv%wY;larAA15^d*@?aWEMsy}9x88`s|Iv<^=+@vG*&@c(tlgTztWwizh}liw+v8y=7^#?F zhrMEqmEWRUw^P0-Z#PaN;k`c#55B^|Wg61`#aXc}qdpXY zgvmdJ9PWDBdy{35JEud`5ux0*K(Ti`&U!$hvOR8GZa#NzYW|}-6tMTm9gOH%TJrSN zM*7zWA~lDTobU8bzajc{jU&%MoRL{%MpHra;TCRTmbY=o!$8tfi*?7X=af*3W{vmI zzI2;v&RFc{{wo9i7Vn|=iLu3DQ5bhMZkRaPl5|LRU81z zwl#5=xQxUOY7t{w_L&^w3D9uyQmZlNQfoMLnH>tK@XH-)j51JUtY?-Rvn@*(V|z&js3okY-tu*9zp?l3FaWf^J+XlWnlTA-GlP;&dl=V z8$UJYO*A+!RQQlgp8a{T*)`EFfa0VZs(tI>De-Nk^u6N!_~@oZW^&PJLIYU#6l-_mr2F!iG$w)zL7X9W36O|DdD*+EHj?< zcx2GH9#!@u@fSHUaSy@zPiW6}_N(9KK~4^p38hIEl)dF&$ceG}q`#PAQ+Fw&y|Uc6 zOz?dZd=N5dV>DI!$Dn9my72ML@DbTDvN#P}WzJ8lt*~rp$9kaW0SanZ$@`K5KxZ3! zr5n^TZYHZ~nUNSKai@R$`S{W>Na{P8+{8DD7s)n;7+$LQvdJU{UOB&+-+DQ1n<9&m zIG~Za#8!G7bH04FGz3I&WY0{u^qu7uLo#1P9c`To#)u{LnM_sk#7V~ZH*Y%HMfvE* z<-EleTV=JGG^WDcZuG}t##N{7 zAxE%XqVOp8Fi&+WZ=t4|0bV&J%N5zLd5(x>4;^{3`%TJ@F;jDSlBoQxS}zQA&!u)m zJ*`T4D-YIJ)Wy1C1;wFO(slj`l&aNozbYKEtPmYNrYdssvNt;}+1EL^!`yGUr8yH_+<%2yze6 zUx$y5O<{h&(=^>5pG(dElOi=UUOO`!rRW;93e7!^KxwQ)kg$Uwx)x<`Ioq$9`hHa1 z(!H*J3gwz67}V;Ggo5T~CS`tbgOZGHE_fDa>dm|=dbRNtoThsoklT+o9tGNGwk_G|3%H}bws;GUM_4PX%x1u;sSE-AC4Hy#U*{y?~l zZTIDm!yo*@C6;;%i_f-SkZZ6iUC{WJKl$FB&iPT%@|ELbSDxpU93SbY%se0lVdcYq ztI=Sv`sR%DBfbAyg(UIDhj>YEhB$hz;9LwpHdh;0zBB7#{HAJOrm1EDTCMkLK%}}W zTo!UmEsoCI&(KDo4>EMXkzrr|=#q!goE#g&l;M7cH=TQNr@x?dagC~g4_f));laEIIF(^#J@EUDOI$L> z0B(E4YI?IF&^1dH{-3h1bXR0oP@wCVSs9*3J9qdY`|Fdr>y!JZ!!H)&_$45H^1k5WoJWRckN+FvY|-ko8xECg)*@TVM8iTaZn@pG@Wfm;=$fhr?J^ zaSt)h$ZL|=m7I{8{$scdk6W!M5r*snu7vLdPeJ++;fx7|?Q?A}NdzzH2}mtf&=>0XVjjtii*bcWQ1wcRt=e z)iv$un<6D5W2B)mP8*a@>$=BkddN*U>D;f+d{faRsow6o-Iz=8pkvht8gN3?a8Qsr z^U=c>&Osz?fWB9OKz@&wPi&HSu(f&;%Y5zm9 z-fx}erlr+=Jz&j`F6N~ak&?XRh|&G`5yHCcDG+hw7z`oAXg@J3;UFgIz`HP;-TiPz zx=Ya9+FpMn`}c#Ko3l0Firr<&zsyMkK-}GC9$HWktkY7{L@vbks>N4PV*f+KIgToE zhRge5#ndbXTl0``7X<)QSn{^t98i|_tND#v@oLqd4gUqe+($?UqcWa4a4c`*@0?$) zb+kQ1OUd+*rV6>=w1xY%a06fSH#uzt41<$-ZNQ545>;I4EGhk_x)&)_=IqORUJD&h zG65tgkloM?Wg7ct44cv6eV2SLQJS(FNJ$j5G7TU~(duk9cX!%&!>d?e7UNj$Mn9N- z$K~-I6+L?!)xxtaW_BbeQow8c%`IIN43_P1cZO|Az0}Iw$<|iiv%P-iiJ-60NCBZ= zU*%GHJ|LwkLZoiy@Xx%*P-X^>w&D6*K$;A=2wGtyp#iUEuYSs2Z3J4;cSn)%IafAh zB|?L)@r|L!7%uA7ugmLy*UVd8O(!y=B#Ns4K4gjfe0oxTyPXZUL4+QDvZu5_J;Ox4 zWye_TgBE<~_YurbOpvxH-5m_mfG$|KKqIlqO*Hpq=)X<~K&?Um&vDZ$sAv+P5oAtC`l6)k;Nfl&+|fo0z)HCRGah!% zs+aqlxR6`~6d{m^pw*DFxT>6~%dz}&GZ>jUyEwIJcO3e!#c=~X?;++S@jV+4%vfDs z%Y~ettg8Tc&Ct_l*)ANSVlEBwxgEeU}^H76^w;)SZ zryh>PO$_d#3x-XSMEqkz|FN|a_85~(Zi_jck{%^m8G2s*1c7oT2R{{ z>r~TWgeZB`mpp&!`&STe7}n#-A6FeHsGs2QcpL!#Lzyh>I!lne&sLDy1X+Q6qnJ>Z zFJg3bSJod+p;JYg#p6j%b+}gUh%{W{!Eg|$rR$mleB|`wodFKz6!#w-c#yCcyeNkt zk(*V$LnD3-E9lr3py(;ZWrdbz?F&3r?Y5BvR`&L15H~!2D#AkwP+Qmr?sb1VkDt#@ zY@#Ifyw0*>3b}>LN-Hw{d7uCGp70XZZ@xtA`g!^Q1l4C%2XD@T4E2Gn_&Ope=g6u0 z1@QtF%fiW5RRXla^pF0XwjaMf9yyULrUzyX!MD;Q3PHCOlW=@oO2T;!T}k@W{t+j5 ze6Dh%?b8B0BB9;k}2di{AsP`n)b;GJLX< zUp+WoT|J{?p&=_5Zr}4$=U=}t{1xE&2+V7HlaQT`a^}<9{yOjKciFFY@_ArJUc&us z>@tS6i^J=4(!09;8>q0dvg2FXYH4>*v!5?tM9YMTY;;Guq++@FC(wT~HGK1Dmfx3& zs`k!>IIWpydUS#K<#+w`N|I7H*^dIwhI{Ci<`gvK!emD6Pz%qAm+#%><>)_~KB?WO z^AvDN&FAHqeO6DDnKi>-{l=l;-q1uuk^x?tZ7XEcDR&!C=c=Dgn#02(`JV9Qc^8#= zNQ*tSmT*L@3EsK7KM4MnZ0U2Tt=ui2d^nxswXFC_BCy0nTq>)hL(RlAOicTxVcK_d zjgu*6VC~O0e-`I-RX)}P`?o0ymMRgj|D?NCzV-Uo8Isll$&L(8h_G2<;fz>6K6m-? z@P+<3xFL`7yP)-uvOYDdoND8HX9|8NIW0-|-$bvgV#+q&-jDGX?&cjAiRt7v^28<6 z1(d%35zR}WB+#+OZ99uK-)yzO*KxR3Y-l(+Q?EsyhqhdX@;1}!R!e_;W6z)=Dw%30 zGSHR)kJMblQJg!VcwwXv*4#4c#epYVX`|ViL%qL~!IJWq^Mu=QqBZpzqSRS_+MS=D z$7@|Ts0s6(ONp;;r&$Gkgnc7d^$A+e^%7BRnuwf7BoFsWm#FkZw27XNXpXEW+ncjQE0q19{Sn3GRDOEiWZI~vfj zOXOK|yyvE*Dm#|YB1!bdvWhGg_6z=;N9j(z*`ZA0v?c4XxH^$a%gYMjs+Il^ zF%6<3Izn4{AR$5(gc;LRr!kw(+A9*86qZ0{$i4lZbHawSo_NP2G9Fky%C0sS8v~Y8 z2^fz0ERLpSL>0WffHg30D!l~8ea*~it-C-UC+|?{Ji023=?o3ye-H>lB?*=*%*_iP zc6>cu{WfEd-=W2!(e3l4OI8lwIr*|)%baPxMeRsh~7+~4tIW>rAX{klA|Ni zlfdx$UR#b{uXyoi^_R}>O$~QP1v}PU+OFDwpRY-E2F5koR;Da+#@Y5jD-~M+1V;abtkw zL8Rk_Qx#toa#*y?S8l;=Qy{FZd1Wui~>L`uj9k$D#?qD}lln9FtSUJUpGu-<-i z#*R0FMDQ}^aCcur$TT4U2;haPIiG{Ch|BiURSPkRHF+Ck`+2CM@q)+Q3x5mBOmnzP zN!{>|yB*qDhQDO0A&II_C)GPIano87iR>DG&iW67fC%JIz4igeF4Y&ja95o3K~%Ko zXVvMC?(8N9MQh7o-H*EX^_z6uC81`IpBBDB(rwy;7+W14cT@p@pX!w>B&LV6hGgpf zi=DG{dBdaeWOkJFVD_Zg{Gu|YC79KW><@$a3uSl-=ie|K zLU%gKG=m@q3zP>4Zav_?eKOnL%~|LA=u|{!jDWNGU4i4g>j7jpuzEf^_^|Hiv}>*0 zi4Hoph!7Ni^~i)uzXT0JbQsoi(RgVK@LC2S!}Dt+Ljp;*PUIB~3S>NmX07oueGONlRY9Ny-(?;+vY2C5UkKs_2?L60K$iU?epw3V zMaYuA@+2M(j$$73M8V3A4aDc0ZQ2R;u0@L=IuWl<{GDQ#5y$5?CrYfBFZ9cYtjFIm z>y{QCKN9Y4C5%jSL8jFe-mexhtoS|ug0xz~3SGrN9iG|&DN!jB-ZTS9>=@3R;3h69 z$(~~!P^O_bAbaDk^G|%v_l6MJ(l@+<}SsVnPDBz#tJw??Gg zJi9eGQL~Tq4Cl39=Wr1{kaSj4Z!H7_!Ao> zyv9JxqzbdVcX327({-c@iKXQDuqyhbf!UdmGJ6WoHIva@8@(~2&L~}+6Zp`Ts zEMlh(25O=eqS|1;;6((?bXG?>=|erD&PUG*qWLh)@zq;&vfvGT2!La& zsOQshg#)c*;VF>G$`WERL~(NA(8_+Ajl^Zq=$uMauLQ82FxltF&|;RMxyqxwHKoBg zb5oKQ7uSgh6CLiB0UapNV<`H)D&uLZPn~ zOizAdbyYwoX@d1ef&q>E8ht?V1M(sK4nI|N+!x2(zQ4}ylX_+>^sB6}ITaDtn$ph@ zC13U^bH3(?Y@$Il96Bkqt5Aw^``FRi01&&ge`qX{tNJtBACQGnWUs9tPZq z7etLL|9BP?;eCpO=|UaYhH0QM3OwRL&NGjlwD>M99xREnK^=O4Mtxv}y}{s_E(#1i z&+LEoZ#g{^Y%tftNR#kLCO-S3qCQH^0S-H9W0AhzRpXyC(-Q*V6a@BWWhnm|)^_Xa zAZ)e`o9bF|m0reD%68!Ffat2rR+3N6UuHIO38ubGda2Gb>$?mjtwG)g(uADuSXeb9l$TP{jjF{?kpy)PAYMweRdGU+8J{_tLrDDOMcN9jeh-pWYTwhcs`` zuCBkWuXd_i(AQw65`udM{Z;J%=&w50VaoptS!Y+=p}%W!S7gpA^!n4PWmBm1@1CDa z+)VA7(>B-wB}%8w`7JsF06t03f{Z{t zqQ8W)bWCRKTL>`-+)LExJ$Y(%n##|j_3{@C=pG+P3YDV;&&}yb@ZPv+L2@u!%tS$k z?{X(hCH{(D=otb}QFOGVEC9XyJL$0vplQ!nYdW~c`}l}yO#EzYQH`f>5LuT-@}fmh z8M;ltt#E+GO+g_;PT!RnG>U7@V3X=7PZyr3XkL z{$PWlxJnA$n%N_+QNL;YxYq>;JjWUUDK_f%d&S62ThheyX`PNx_1&)oonPZL^{x<) zZK=fu4A#`%qUOh6tm`{lbWzG!m1haNAeBvWQu1ab?&ANTiED~LSG)1lf7IM}mp zK@k34mGi;egT55po!>3)=vaNKEtGOKm{^@m`pGTHZ;39pCpfu!6$c3<76n*>yoO!X zH1;&@N9wJMdK?P-!({>kjmA6$hY311qrBqk##)8S7t|m1@D;r$RX$)COqFvLG55c= zr)rQW@BjXh`q>$M1Dp|MtXz)cUwKgbjM8Er5;f`Jy-1c9dX|Mu>9Z=oc8a#m-~HrE z4s>utk=*%xpN!(47PoyJ^NyT}Wr&o82k;4hO9NX5sW0gbk zyEeMS@n@Blt0S7d;J%gcG}M;(YfMrlZOU$(E>Dh%K27GQ+l>w-;>vvr1uF8b$mzxU zg6x)usbL4$;vYz4Wy=?rj|_aJ7n5GujM!&RL?WVD&NiWxPeHS5Z2cpB81!_z(-y_eJdLg`&a$^Xghn{Kb>FZtNU zfd1v%^7lMPeXq{S;_%u&j@d1|dd_2-QEL90ym#8M ztsmv3L(O{Pb}jlQFsc`F5>+mXjEDSFsyoa3`&|f|0!4o7niryZJ5Sm#!4HZ9mB7aD zm2egGWw1ImAJ?e$nqAMlPvfYXejO_;o)|4vXk^)+Ifq1-;@3swLX*VQKZtv*ak}0b z-BT*)v@Nt~x>8-vZ zWg&YJVU!$jCY7*4KCP+R#5P*f@-uq5x+QEOiO+Eyqy?JhZnR;R*jmJNnz>4;3@W|5 zlD)U~Xa&l8@FY+apxYUr@Lq4e7yQFV$xmX`f2&) z?Z!|79d7*8*lFk$LR4xnU;`$cFz;ESkh2oUEOuMJ4)o^zu&aFw{oADwA>^;Ynfdy!?2K3*=+7+=EF;SA|{KzimUcf1lK0a@L4nl4`?B_0T z3uNO->HaDN5MON%95|-=H~b#dQ}Z}iIjTLWp~vEHV!4T}yecOQU2j%NkZ=E$tStfC zW^74LB*E^$0-OsvKf_P7OrFES0khl1!NP}kf3Mfe&s;3hCmXQHs`Vz15yDP&c#KP-zxq}RgwlwzX|mRp)*$nUf!1}hV31h2klsgfUywg)x0#`Rj2MWO z4v_2m2c0$?;wAg`k@LcC4*IYdxu*!Vlo*{Uy~k|W1sVroIjr+b{O|GT z{aQ@iFEn4!6Nu>A7X@&_do28;6r4d}ACc}@v4qt*^c3R#l2(N4y`_zGVZ@tfAyiV5 zchE$9*OO$b$IK7nB5FwG@gF6a$uj%ip)5qv;}a|vd&SxI5epMGoDY!aBDPIKL`QN1 z(H+Wo$~dLcmQ?`|mCU~iL3qchSg{l{7HUYjs1=eCJ?nK@h6O5PE^zD=94GaIz2z=6 z`UtI@ba(WZO02bI0I)_N6ESR5_gO%VYJq?X1j=m4s zbYB9r+f|mZAr*vwlzqPpR4&B~j_j>~ndM=}td2eeuTGjW;~!-|t8x~fr-`x}QeVGI z7u!gW8?k^@N@=79gY)0LWT`lbvg~WXL(ECtFbG&J>b8%spI57u3Drgy-yIe-;>jg$^hy*lgeSd8QPW#C_4RzwF*abK=S(Q=LiZAMLvo2QN26~YQ_tclV5?a#x=r#>Q=tQSrdzq z5P^oe$ES`T#dL-f#$5-uQbHS91J|I5ozmCNK?~XGNM-Rpf<}BYKDu83L-g^VfU!fc zM>Gr&o)<{R0*Lup|GmKZJH#HM`ttH9r%d9fu#B$>55j*hWaEO^G+*e|b5#NqkYkGB zpz+Cys|u1#tTY5@aoF1V+ss~M5TYS1)ZtqvBr{qh*cf3@YugUgd8iw0n-?@JG`%|+ z@Xf6vUx}Z-lE!4f*3rD}aPkKc33S4Ko9={|8=%R2o4ldy6NxAqpZBk}vx&Ak3*1{m z!HE_IF~ZX|y96qgUz&>Dd@MeIpi)=WWN(uiq?^4C7TE|DFG7Vz-uSHH6yyU9kZ+3J z7cdN<6|C|?Lt7+GXnuDx9$IjFMBwxJ$7yH#$y{2L*kNQ6Fk__v+0LE6M1tEWt`@fB zfNc*fw=0`rtWV%-Gtola8QSzYj_ivokKk#lpZQyq`s}1yvxU7Mw03aRFJPp_5qm0Q z?BE}myEo*$zMlwm3uRzZeq8@cv4cm7iuEqGQ%>=G?Q_qHp?SiH8)EdfNba&f44}bZ zNfIF??yaQ+syBOLmpIOR5y#maC$9~;5=MrF%7cA<@I$g;aq-Q&30JqXUN^oWxwxZ% zS?g%s;n1^t-2TM*VMS>y}s0dY1&+t>xHy3rjF5LoyXu92dKEea*m7N- zENMT6xR;+^92?B!m&(Vj<&bJm+BV<*fQ1Dpmo!gfZa{&7f#5G1-7+aEjr8k_4U8YD z1#w&o&#Va03jYQNPh_|T$Q&X`IljSsxWf`DtBptZ+cMm%*1>()zeZ>ge9W0oPYwC# zeqE<}dTnQw&wv0S#=SeTXFFF{pSeQ;(}9j#whMcxc$UAdINfH4bLkH*0SbGqZ*_{80kP*7mh?kxsh52ZIdm3qg6q6YUBGf4=K8Pj z&dfDEKK3|Q)i3>Szuqo6NOR7h-l%a-v_42ptbGgVfRQO*GhoD%4Dl|4!YJJTm7gJ7 z7N>0>@ogrbs|w)xAo+klN5Z;Ix8y9Y;hhC9Lb)c?D>t}~V%YPs3%1CmRTcNfw?)}~ z#Mje#j2IfVKG&LVnZ{0!$Fcv%t~IIC4HtjD*+>BN<*}5uf2i}9eUBfnh4G$pCi2F^ z@S|IX_R=LrJYqDx&#nqx59%1S4*KFrg$4>>g$PL->+g1sIQ-FPk(yo(3qzAPjce%& zX;k#D7{&mqu4YBDxWZIbt8Ww0(wNLxh~teH;%dgQuPUptaU^j`R{f!Yhi%>%JWY_k zz#jY}EPp*FhqkH{2x~l&^}T`~?>l=aG3tP5=?qRZSOwt-mu6 z7qXCCub(IDc`E~qNN{rBLpVVSnnv0$!VRpb(L16Z6wfy;9}v=J5w#aSQb)0L5`CNQWcrfzfJnz^<_q%f1yy~ z%`iDpwg;F2&4C#e!To+Tl~UWq+8grK{}05OTZz8~f!9G^4H5n8U@BU_{{(#+tXvuQ}L zzukM30l+D^pBF=kkl|d9yzaaoWaw+3BYdaH7Cv4hg%xz z@xm}aDUU|m<)?!uq?4FS_?rk68y&mfRs7Pq_%~FNmeV9$lALZpH27+hO35zC-xGX4 z_y@)1C&j>Xzw=2d$%~pNadF+k!Roa_Hs2ZqiWTcT6pmt?6$O0RSbGwKE&G2T9_Rt}C)kt=x1BRC|qNKMx*Mmj2S#LPx>-K0d#)ZKk^`*N;taJqjG2as; z?A6#zN-<6vS`$}3b!y(@<5Uoob~CCQZ8srg=x^Z)6%NQ$Q?uw;f6zQ*`D_DC)EjGq*B4*TL+ZCzn;OdW@+0)ijV5;r()I1#M3ORo|`<9A2c#9 z06;oA_KN%D&M_HEb#tW?wC>+d%%T|@s@n6EM%F*@X?SJZRhHRU zc)J}OHGAznpP^mk{kka=B%!;OOVpYlKAsCdCPV0Q`a=uS`_pF&ds)QRPg-W_-CdwM zx(}CJSkUw$qSe+(;R^{gYcxP&$8;0n>JD{n6YgD}aonA#Y!<+mZc2JwGUR13S{j;E zHBeU&NWV8fP57zV9CbXRg!p8bg()|?d_}6meL}h>rrvpco12Y3p9{SX_&WEf&SfsZ z*WH2d#cG+mwV@>zny+;^VZFJ=tt?3dATP4OMYf)Z0m^o ziibtkohiLGV|y+D{s042n^LfPYkEzY{2lVs9x%358@r(K8=P`s_@dklHYFb}k^P%N z-L(@RUQts6i~Z<~OFJ=xYC|m&($hyv<9KKdxt(xqTdlVxwXC=e5JyqnDRC#WHV3Y) z5*!VDJyS<((W--^lDPc__{^L`m7IfgtbE3@{0rI{4%Phq9yKa%b;nM8&bFIb8NJK2 zuHbHKPNv1ln8B!YI zFLC5_(96!BOp?gCJSA)C*no7)-(Y3D;PLqnR{3xsWJAPX8%g=yH#D1p;f)#rWM)=T zZ!WWU;JC6l=QzGEu~gA4+Op-5KcZ$hjXk^aSFW(=H}zWoJJOvCuBZ(Eix^fo%R{~{ zslpu-%gEISkqC4vnVD+;P7Duo|ErB>HpNd#$ZmD`0iS9uVj|$$=kJ%o6`@DgO4$1VGr;}f<#QkfswWbJ%sd;XItnPqs%tzI&I~WH%aWr%%!7AAz za#XZ*t8+PJC^F1_+`LURQHTF@z`Q+U_y&Z>yL{-nA-sV%{o&o?G`ugSm}6$8x;Vln z;F6Lw?fgf@P{Zv(q^-Y~>T-SHNuTRQ4fsQ|C&Tt)`f*3P5Nw5;*09)Aj!|U7v{SGv zd)~}7RvMi=-RLGw`0HZUwCN4j$HfP0joA-{P%DyQ&sKU#Y1$WD4V7d#3s+oRz>oaF z+Cp&|8lmyA|5Vcv@8B@UX3)=zyJace(Bbl@mCsJxRS?xP-l+4~KYLxo*C%Nf4fs6^ zB|+EQb{ATlv;JVLR*+aT4Dd^>8BPQpC2%O~0!v#sMFDs3UTgODXUxLF z59O+gVt-?v)HH6>T^Erdw65N; z%odqx*`1qw$|Zw)-A@}@;KhpueKe=9Li2Q*eJj4oAq$GcdEJ^`c%$5ZgY`M`!P+nfo`WU2R_>?ls?2g0t+?21F}+XC?iC^8Ni{H7FoiMx0vxE0)~}(o zjMMJT$_oc=Nd07E*^Bpi(-z32ybAzfR(uR#csD*$(3tyq?qGIC(dkC8hAWJ1p~9f|(lIl0#{BHI$d6D3{4m zK#wYa|Ij{-*Em2??(IGI;pCq0&PgLaRk9Pu!jMJjwP!or@6yg&as>a7jzGh9yPMr} zQYUj%&hF9L?h-aGg~;^+-k^yia+j&bhq`^kO?f~{uqx5JTTpu;=YY;nL~4&%4BX)^ z$+~fCJUOY33$CUgkfadW2zpg}(FKY~dIfFn(=7HG_ zWxWp&(l2!3A3{?@rzs*=Z~u=23`@QLp8EeU`McnXBqmZ00|TrcSvY|f%fEOXC`p-s zCPuZ?P08;Nzw&3GHf_-N^dO6m=dj}X;12+?tA5`}^Tsc3a_AbRG`#olc1#Uwc9{?8 z%~WV#D54|)k&N&8ULQAOo@s2l@>>bCCA7BxXd&1MX;?*CO84(2b*W>nr#tgk>Kht%R|jeGY1}0Xe1@;Fo_!x#OYc{ua2w3BuMA!5rfZu@ z>*L<$iX3#@;6ALHRn@9t-M%>CQdD`$yKSIN!pxhQZBLKb1U%aI&m7yM`B|QJ| zP@lQ619J1t(4&i9tekAWJh3k=PLLQ5+{NQw`6yXNhmg(HrJ9Eq=>d&DHw2ECDJs;y zIpze24={-(KPF;#?N8>H2iQ>58@(( zlO4n=WjONKWvCB<`Ii?AG5v9otv83Ag&j&9r`ccV0V(%2KXTMcda4dwz`T-gK4MN) zt&GxuyQELsA$a5UTUJp>ilA%dA&+Jn!4a={<#Qw^{jD|%0@MfGgHwYjb!dhT0|(an znh}!Q&T_cPj+AQTa6{kWI?+_|V=T9E*~Ivygo#1d!w_Dw~mUG>`=72{SV=1 zHIcQB$h#23;?fQUgwNV7@A0Cl@ajxmaZlg@eLC^=stfIz9gOo@r*4&7sl~}{^G$@w zaNbo3Law$a!C-aQMLyF6lYm2fQiv^P2%XYZ!@AFMngFLTL$twm+-s~~(h}J#4{DjZ zO3hk!%xM`Anc50q1 zu2b!pS2!MOXX^YNOD8bjEhC1RnY{TP0U%0md%1GZ|3HU@c9Dw571pc&3Uf z!Okt>OaEn;qP&8&l|**&}V>}*AC3TF@nYZVLCzBJQ^BaQUe<|Y>ToJMw}bC<}PWy$m4ZQ={!ha)|S$0 z^ku)!Uf$3X*3_>|rUKTq8Hr@%LuM%GHnK1~_n4Rf+>WWO)0*9lW?Jm6C7REZT-xHyP&t~4UJ_oO?8@GaIc_<}CBNOF#+&TA5`MQ4Sh#KiMtMVrPR>No|rXkiu*T-!6u%nxb4(L9xm)jWoF47jo*r9 zaXz!5-M1!rFar=&5{W2ZYVO(Yi>ZZq?{F?L#Mt;BJA*b=M>0FjR4+*EyRIM3ek8s4 zb4$_=l7>5Dx{yK$$q3?SuF;qY2=wV@$Vbk`bM(pC zM4iP_@FkViXyH>ycgz>ZxWOLd5G8}K3~&JZB7(kQy+2~XfEfoH(XnK?P3D;Fbqr>Dx`Q9EV?#Ti_26s?+M@aQ-Tbh*coa#JI`;9P zpj$$`xUoX)qVt-kOzb{-%SDDaM1hEc_`j2JsItiucF`LTIKM*@QL_oYV{>zL_aafv zqLa}NZi^Z!6y69_))>K_E1Z1cj8au)uRc|&OpMF zMlqK8zT|Kq9~t@|e%+j#;x>k%UlWFl_KM)e|MCr4=L51yhs||CZ?kv>gO=(Z01O#Z z?qX9Jn8Wy?m7-OJ$AnXev2cQoU z_PVpkGBAb~1fq|O2DB+dm3s!xFY4+xBtf8w@W1l3v|=*m^1|zJJl%)$Q7b`j0FdM{ zSolv7Ao@rT+~9F2#qE&G%Q6h|dc_#ga~UlfY}w0n1Ej}E*gtCB<5#{d2k5VWB;7n; zecaZ@1RmwCeA>SFX7u!`YLE5$&o61EwLMTM=*Nkb73SgqCzXG(4!=5t15*jm&7Ci6 zIm^qI9wdLC{sBoa>EFI75PJk5XYzmDQwCZp^+dOK%j;w! zPn8xfL6UQZ2PY2CZMlx_dhT_nexP4~j1(&%8K0P2#vE+j{=N?18Pa3_9# zaYWYGlMC9+Un)cy*;UbRJU=K2?FtyAkALYm>xHy+HFh`Zw45!rOk3AtBlS#wCu#!k zeWG)sP91rc?-`80*qNDmxYM1)EN|4|sq7b5S@q`0&iN7JD+{@hwQvdKPbNz`rp{k? z{doMo0>T5OcYtZqhb{JZ!IClr6QZbjN4GC>n~`EjY+iVM|3DRs0p?CT?0u=kR&xa> zzZ`PM5N_05{SI1Yp$TQX*NT!cuPDmxrs*Fw=WYJ5+Usu|eULnbxeN)mIys-2@v%h@ z)Za3I!KIuvq1fD<9nUt;t3Puy#Fed{FOE+JI=-UIoFTxh1RTWnPDn>lhG3Nqg|0pw zUaB%Kx1)M$(VBP{#CxWwah<`%|Hv|RAi1W>lD%GviHs$om3qn6OuDaM6UXR_HhIcpmcbb*86Y-HB{subVK3o zK@LN!`*5ZGROS1!+3mYs3Ty1U*eV!;J@eg<^O>V45q_FGJhGdmkcJdphuE}K5i{6s zff4S^_!`d-uj&_lU|{&oc)t;@-)>UC{93g!3V1<$v$gEc$k2=fsn!~7uOp7oQ*sNc z415;0bd|UPOV6ER#f2mj$-bSnH+5^#NFNVKESgI`=HN=+_pF7-B|p8dsbqPKYy##^I2p6}$bHOviz)N*x(T4X!-7 zlpmzzcs|JG8=ALF4S_E0iWjRG&-Q!#MZ&7hd?Zy}5BtIGkFDnk+CkQfybQ}!%t-yd z-jCl*1?DvF!<3wH_PJ})Mt@@P@bo7HG#^a@J&8X1qAtZ{Z^(d0_5#`hjr1&LX`AGG zzPxdf8~f45D!{>+nj10lU`O$=LDz90_Uz#nA)(g#Q`~*$GjkTfVbtm&Le;IrFNTzC zU#aUNd7N=>KXk%JP7D-063+B_P?(KCd%I)_&Dk)%&ndxKfwAUYF4}F1>jT$IaPNR3;?#vIPq$Rs1 z1_npaV^LjLqwVo)>3o)~d@OAL5{D6OT0vq`JACUL`0&czMf~t=_W?bBVPDHU@rllF zTja-z>S1^z1qG5l#?xb~b0%+h-lAx%W}+vfZJc3M(f;U`1gb6M+JdO6-Akq8Ri18% z40~3w?AP<1BcWSr3h&pDf%+$gNFvi$B&2_6g#|I~B?{E#x1=(jFkD2QEii}m0q{U^|Wy)@W`ifT9=#B;BCnKgDerlC9 zsP~QhTuZR+kEOW8;6z~o&o1XIvU^-i^(K_O)WL}tWb~&&K50c`UlrYzepCGVH3JP5 zEtxNjcko%ixZ_L63J9~Wn$>b$AL+CFb>N?w{_TYQ-+Od!$Tf$LjZ>klZO(t>PatZ# Kspush(MsgFinished::create("No frequencies in list")); + getMessageQueueToGUI()->push(MsgFinished::create("Sweep list is empty")); } return; } - // Set start frequency and number of frequencies to step through - m_measurementFrequency = m_freqs[0]; - m_steps = m_freqs.size(); + // Set start value and number of values to step through + m_sweepValue = m_values[0]; + m_steps = m_values.size(); } else { - if (m_settings.m_stopFrequency < m_settings.m_startFrequency) + if (m_settings.m_stopValue < m_settings.m_startValue) { if (getMessageQueueToGUI()) { - getMessageQueueToGUI()->push(MsgFinished::create("Stop frequency must be greater or equal to start frequency")); + getMessageQueueToGUI()->push(MsgFinished::create("Stop value must be greater or equal to start value")); } return; } - // Set start frequency and number of frequencies to step through - m_measurementFrequency = m_settings.m_startFrequency * 1.e6; - if (m_settings.m_frequencySpec == NoiseFigureSettings::RANGE) { + // Set start value and number of values to step through + m_sweepValue = m_settings.m_startValue * scaleFactor; + if (m_settings.m_sweepSpec == NoiseFigureSettings::RANGE) { m_steps = m_settings.m_steps; } else { - m_steps = (m_settings.m_stopFrequency - m_settings.m_startFrequency) / m_settings.m_step + 1; + m_steps = (m_settings.m_stopValue - m_settings.m_startValue) / m_settings.m_step + 1; } } - m_state = SET_FREQUENCY; + m_state = SET_SWEEP_VALUE; QTimer::singleShot(0, this, SLOT(nextState())); break; - case SET_FREQUENCY: - // Set radio centre frequency - if (ChannelWebAPIUtils::setCenterFrequency(getDeviceSetIndex(), m_measurementFrequency)) + case SET_SWEEP_VALUE: + // Set device setting that is being swept + if (ChannelWebAPIUtils::patchDeviceSetting(getDeviceSetIndex(), m_settings.m_setting, m_sweepValue)) { - qDebug() << "NoiseFigure::nextState: Set center frequency: " << m_measurementFrequency; + qDebug() << "NoiseFigure::nextState: Set " << m_settings.m_setting << " to " << m_sweepValue; m_state = POWER_ON; QTimer::singleShot(100, this, SLOT(nextState())); } else { - qDebug() << "NoiseFigure::nextState: Unable to set center frequency: " << m_measurementFrequency; + qDebug() << "NoiseFigure::nextState: Unable to set " << m_settings.m_setting << " to " << m_sweepValue; } break; @@ -309,7 +310,7 @@ void NoiseFigure::nextState() double k = 1.38064852e-23; double bw = 1; double y = m_onPower - m_offPower; - double enr = calcENR(m_measurementFrequency/1e6); + double enr = calcENR(m_centerFrequency/1e6); double nf = 10.0*log10(pow(10.0, enr/10.0)/(pow(10.0, y/10.0)-1.0)); double temp = t*(pow(10.0, nf/10.0)-1.0); double floor = 10.0*log10(1000.0*k*t) + nf + 10*log10(bw); @@ -317,14 +318,14 @@ void NoiseFigure::nextState() // Send result to GUI if (getMessageQueueToGUI()) { - MsgNFMeasurement *msg = MsgNFMeasurement::create(m_measurementFrequency/1e6, nf, temp, y, enr, floor); + MsgNFMeasurement *msg = MsgNFMeasurement::create(m_sweepValue/scaleFactor, nf, temp, y, enr, floor); getMessageQueueToGUI()->push(msg); } m_step++; if (m_step >= m_steps) { - // All frequencies measured + // All values swept closeVISADevice(); m_state = IDLE; if (getMessageQueueToGUI()) { @@ -333,15 +334,15 @@ void NoiseFigure::nextState() } else { - // Move to next frequency - if (m_settings.m_frequencySpec == NoiseFigureSettings::LIST) { - m_measurementFrequency = m_freqs[m_step]; - } else if (m_settings.m_frequencySpec == NoiseFigureSettings::RANGE) { - m_measurementFrequency += 1e6 * (m_settings.m_stopFrequency - m_settings.m_startFrequency) / (m_settings.m_steps - 1); + // Move to next value in sweep + if (m_settings.m_sweepSpec == NoiseFigureSettings::LIST) { + m_sweepValue = m_values[m_step]; + } else if (m_settings.m_sweepSpec == NoiseFigureSettings::RANGE) { + m_sweepValue += scaleFactor * (m_settings.m_stopValue - m_settings.m_startValue) / (m_settings.m_steps - 1); } else { - m_measurementFrequency += m_settings.m_step * 1e6; + m_sweepValue += m_settings.m_step * scaleFactor; } - m_state = SET_FREQUENCY; + m_state = SET_SWEEP_VALUE; QTimer::singleShot(0, this, SLOT(nextState())); } break; @@ -454,12 +455,13 @@ void NoiseFigure::applySettings(const NoiseFigureSettings& settings, bool force) << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset << " m_fftSize: " << settings.m_fftSize << " m_fftCount: " << settings.m_fftCount - << " m_frequencySpec: " << settings.m_frequencySpec - << " m_startFrequency: " << settings.m_startFrequency - << " m_stopFrequency: " << settings.m_stopFrequency + << " m_sweepSpec: " << settings.m_sweepSpec + << " m_startValue: " << settings.m_startValue + << " m_stopValue: " << settings.m_stopValue << " m_steps: " << settings.m_steps << " m_step: " << settings.m_step - << " m_frequencies: " << settings.m_frequencies + << " m_sweepList: " << settings.m_sweepList + << " m_setting: " << settings.m_setting << " m_visaDevice: " << settings.m_visaDevice << " m_powerOnSCPI: " << settings.m_powerOnSCPI << " m_powerOffSCPI: " << settings.m_powerOffSCPI @@ -578,14 +580,14 @@ void NoiseFigure::webapiUpdateChannelSettings( if (channelSettingsKeys.contains("fftSize")) { settings.m_fftSize = response.getNoiseFigureSettings()->getFftSize(); } - if (channelSettingsKeys.contains("frequencySpec")) { - settings.m_frequencySpec = (NoiseFigureSettings::FrequencySpec)response.getNoiseFigureSettings()->getFrequencySpec(); + if (channelSettingsKeys.contains("sweepSpec")) { + settings.m_sweepSpec = (NoiseFigureSettings::SweepSpec)response.getNoiseFigureSettings()->getSweepSpec(); } - if (channelSettingsKeys.contains("startFrequency")) { - settings.m_startFrequency = response.getNoiseFigureSettings()->getStartFrequency(); + if (channelSettingsKeys.contains("startValue")) { + settings.m_startValue = response.getNoiseFigureSettings()->getStartValue(); } - if (channelSettingsKeys.contains("stopFrequency")) { - settings.m_stopFrequency = response.getNoiseFigureSettings()->getStopFrequency(); + if (channelSettingsKeys.contains("stopValue")) { + settings.m_stopValue = response.getNoiseFigureSettings()->getStopValue(); } if (channelSettingsKeys.contains("steps")) { settings.m_steps = response.getNoiseFigureSettings()->getSteps(); @@ -593,8 +595,11 @@ void NoiseFigure::webapiUpdateChannelSettings( if (channelSettingsKeys.contains("step")) { settings.m_step = response.getNoiseFigureSettings()->getStep(); } - if (channelSettingsKeys.contains("frequencies")) { - settings.m_frequencies = *response.getNoiseFigureSettings()->getFrequencies(); + if (channelSettingsKeys.contains("list")) { + settings.m_sweepList = *response.getNoiseFigureSettings()->getList(); + } + if (channelSettingsKeys.contains("setting")) { + settings.m_setting = *response.getNoiseFigureSettings()->getSetting(); } if (channelSettingsKeys.contains("visaDevice")) { settings.m_visaDevice = *response.getNoiseFigureSettings()->getVisaDevice(); @@ -715,11 +720,14 @@ void NoiseFigure::webapiFormatChannelSettings( if (channelSettingsKeys.contains("fftCount") || force) { swgNoiseFigureSettings->setFftCount(settings.m_fftCount); } - if (channelSettingsKeys.contains("frequencySpec") || force) { - swgNoiseFigureSettings->setFrequencySpec((int)settings.m_frequencySpec); + if (channelSettingsKeys.contains("sweepSpec") || force) { + swgNoiseFigureSettings->setSweepSpec((int)settings.m_sweepSpec); } - if (channelSettingsKeys.contains("stopFrequency") || force) { - swgNoiseFigureSettings->setStopFrequency(settings.m_stopFrequency); + if (channelSettingsKeys.contains("startValue") || force) { + swgNoiseFigureSettings->setStartValue(settings.m_startValue); + } + if (channelSettingsKeys.contains("stopValue") || force) { + swgNoiseFigureSettings->setStopValue(settings.m_stopValue); } if (channelSettingsKeys.contains("steps") || force) { swgNoiseFigureSettings->setSteps(settings.m_steps); @@ -727,8 +735,11 @@ void NoiseFigure::webapiFormatChannelSettings( if (channelSettingsKeys.contains("step") || force) { swgNoiseFigureSettings->setStep(settings.m_step); } - if (channelSettingsKeys.contains("frequencies") || force) { - swgNoiseFigureSettings->setFrequencies(new QString(settings.m_frequencies)); + if (channelSettingsKeys.contains("list") || force) { + swgNoiseFigureSettings->setList(new QString(settings.m_sweepList)); + } + if (channelSettingsKeys.contains("setting") || force) { + swgNoiseFigureSettings->setSetting(new QString(settings.m_setting)); } if (channelSettingsKeys.contains("visaDevice") || force) { swgNoiseFigureSettings->setVisaDevice(new QString(settings.m_visaDevice)); diff --git a/plugins/channelrx/noisefigure/noisefigure.h b/plugins/channelrx/noisefigure/noisefigure.h index 9a1deba49..f4c3e9d2d 100644 --- a/plugins/channelrx/noisefigure/noisefigure.h +++ b/plugins/channelrx/noisefigure/noisefigure.h @@ -90,29 +90,29 @@ public: MESSAGE_CLASS_DECLARATION public: - double getFrequency() const { return m_frequency; } + double getSweepValue() const { return m_sweepValue; } double getNF() const { return m_nf; } double getTemp() const { return m_temp; } double getY() const { return m_y; } double getENR() const { return m_enr; } double getFloor() const { return m_floor; } - static MsgNFMeasurement* create(double frequency, double nf, double temp, double y, double enr, double floor) + static MsgNFMeasurement* create(double sweepValue, double nf, double temp, double y, double enr, double floor) { - return new MsgNFMeasurement(frequency, nf, temp, y, enr, floor); + return new MsgNFMeasurement(sweepValue, nf, temp, y, enr, floor); } private: - double m_frequency; // In MHz + double m_sweepValue;// In MHz for centerFrequency double m_nf; // In dB double m_temp; // In Kelvin double m_y; // In dB double m_enr; // In dB double m_floor; // In dBm - MsgNFMeasurement(double frequency, double nf, double temp, double y, double enr, double floor) : + MsgNFMeasurement(double sweepValue, double nf, double temp, double y, double enr, double floor) : Message(), - m_frequency(frequency), + m_sweepValue(sweepValue), m_nf(nf), m_temp(temp), m_y(y), @@ -257,17 +257,17 @@ private: enum State { IDLE, - SET_FREQUENCY, + SET_SWEEP_VALUE, POWER_ON, MEASURE_ON, POWER_OFF, MEASURE_OFF, COMPLETE } m_state; - double m_measurementFrequency; // In Hz - QList m_freqs; // In Hz - int m_step; // Current frequency step - int m_steps; // Number of frequencies to test + double m_sweepValue; // Current sweep value + QList m_values; // Sweep values + int m_step; // Current sweep step + int m_steps; // Number of settings to sweep double m_onPower; double m_offPower; ViSession m_session; diff --git a/plugins/channelrx/noisefigure/noisefiguregui.cpp b/plugins/channelrx/noisefigure/noisefiguregui.cpp index fd9b7fbe5..626ba9e01 100644 --- a/plugins/channelrx/noisefigure/noisefiguregui.cpp +++ b/plugins/channelrx/noisefigure/noisefiguregui.cpp @@ -66,7 +66,7 @@ void NoiseFigureGUI::resizeTable() // Trailing spaces are for sort arrow int row = ui->results->rowCount(); ui->results->setRowCount(row + 1); - ui->results->setItem(row, RESULTS_COL_FREQ, new QTableWidgetItem("2000.000")); + ui->results->setItem(row, RESULTS_COL_SETTING, new QTableWidgetItem("2000.000")); ui->results->setItem(row, RESULTS_COL_NF, new QTableWidgetItem("10.00")); ui->results->setItem(row, RESULTS_COL_TEMP, new QTableWidgetItem("10000")); ui->results->setItem(row, RESULTS_COL_Y, new QTableWidgetItem("10.00")); @@ -78,24 +78,30 @@ void NoiseFigureGUI::resizeTable() void NoiseFigureGUI::measurementReceived(NoiseFigure::MsgNFMeasurement& report) { + if (m_settings.m_setting == "centerFrequency") { + ui->results->horizontalHeaderItem(0)->setText("Freq (MHz)"); + } else { + ui->results->horizontalHeaderItem(0)->setText(m_settings.m_setting); + } + ui->results->setSortingEnabled(false); int row = ui->results->rowCount(); ui->results->setRowCount(row + 1); - QTableWidgetItem *freqItem = new QTableWidgetItem(); + QTableWidgetItem *sweepItem = new QTableWidgetItem(); QTableWidgetItem *nfItem = new QTableWidgetItem(); QTableWidgetItem *tempItem = new QTableWidgetItem(); QTableWidgetItem *yItem = new QTableWidgetItem(); QTableWidgetItem *enrItem = new QTableWidgetItem(); QTableWidgetItem *floorItem = new QTableWidgetItem(); - ui->results->setItem(row, RESULTS_COL_FREQ, freqItem); + ui->results->setItem(row, RESULTS_COL_SETTING, sweepItem); ui->results->setItem(row, RESULTS_COL_NF, nfItem); ui->results->setItem(row, RESULTS_COL_TEMP, tempItem); ui->results->setItem(row, RESULTS_COL_Y, yItem); ui->results->setItem(row, RESULTS_COL_ENR, enrItem); ui->results->setItem(row, RESULTS_COL_FLOOR, floorItem); - freqItem->setData(Qt::DisplayRole, report.getFrequency()); + sweepItem->setData(Qt::DisplayRole, report.getSweepValue()); nfItem->setData(Qt::DisplayRole, report.getNF()); tempItem->setData(Qt::DisplayRole, report.getTemp()); yItem->setData(Qt::DisplayRole, report.getY()); @@ -134,10 +140,10 @@ void NoiseFigureGUI::plotChart() series->setName("Measurement"); for (int i = 0; i < ui->results->rowCount(); i++) { - double freq = ui->results->item(i, RESULTS_COL_FREQ)->data(Qt::DisplayRole).toDouble(); + double sweepValue = ui->results->item(i, RESULTS_COL_SETTING)->data(Qt::DisplayRole).toDouble(); double val = ui->results->item(i, ui->chartSelect->currentIndex() + RESULTS_COL_NF)->data(Qt::DisplayRole).toDouble(); - series->append(freq, val); + series->append(sweepValue, val); } QValueAxis *xAxis = new QValueAxis(); @@ -146,7 +152,11 @@ void NoiseFigureGUI::plotChart() m_chart->addAxis(xAxis, Qt::AlignBottom); m_chart->addAxis(yAxis, Qt::AlignLeft); - xAxis->setTitleText("Frequency (MHz)"); + if (m_settings.m_setting == "centerFrequency") { + xAxis->setTitleText("Frequency (MHz)"); + } else { + xAxis->setTitleText(m_settings.m_setting); + } yAxis->setTitleText(ui->chartSelect->currentText()); m_chart->addSeries(series); @@ -341,11 +351,17 @@ void NoiseFigureGUI::on_fftCount_valueChanged(int value) applySettings(); } +void NoiseFigureGUI::on_setting_currentTextChanged(const QString& text) +{ + m_settings.m_setting = text; + applySettings(); +} + void NoiseFigureGUI::updateFreqWidgets() { - bool range = m_settings.m_frequencySpec == NoiseFigureSettings::RANGE; - bool step = m_settings.m_frequencySpec == NoiseFigureSettings::STEP; - bool list = m_settings.m_frequencySpec == NoiseFigureSettings::LIST; + bool range = m_settings.m_sweepSpec == NoiseFigureSettings::RANGE; + bool step = m_settings.m_sweepSpec == NoiseFigureSettings::STEP; + bool list = m_settings.m_sweepSpec == NoiseFigureSettings::LIST; ui->startLabel->setVisible(range || step); ui->start->setVisible(range || step); ui->stopLabel->setVisible(range || step); @@ -354,26 +370,25 @@ void NoiseFigureGUI::updateFreqWidgets() ui->steps->setVisible(range); ui->stepLabel->setVisible(step); ui->step->setVisible(step); - ui->frequenciesLabel->setVisible(list); - ui->frequencies->setVisible(list); + ui->list->setVisible(list); } void NoiseFigureGUI::on_frequencySpec_currentIndexChanged(int index) { - m_settings.m_frequencySpec = (NoiseFigureSettings::FrequencySpec)index; + m_settings.m_sweepSpec = (NoiseFigureSettings::SweepSpec)index; updateFreqWidgets(); applySettings(); } void NoiseFigureGUI::on_start_valueChanged(double value) { - m_settings.m_startFrequency = value; + m_settings.m_startValue = value; applySettings(); } void NoiseFigureGUI::on_stop_valueChanged(double value) { - m_settings.m_stopFrequency = value; + m_settings.m_stopValue = value; applySettings(); } @@ -389,9 +404,9 @@ void NoiseFigureGUI::on_step_valueChanged(double value) applySettings(); } -void NoiseFigureGUI::on_frequencies_editingFinished() +void NoiseFigureGUI::on_list_editingFinished() { - m_settings.m_frequencies = ui->frequencies->text().trimmed(); + m_settings.m_sweepList = ui->list->text().trimmed(); applySettings(); } @@ -441,7 +456,7 @@ void NoiseFigureGUI::on_saveResults_clicked() QTextStream out(&file); // Create a CSV file from the values in the table - out << "Frequency (MHz),NF (dB),Noise Temp (K),Y (dB),ENR (dB)\n"; + out << ui->results->horizontalHeaderItem(0)->text() << ",NF (dB),Noise Temp (K),Y (dB),ENR (dB)\n"; for (int i = 0; i < ui->results->rowCount(); i++) { for (int j = 0; j < NOISEFIGURE_COLUMNS; j++) @@ -712,13 +727,15 @@ void NoiseFigureGUI::displaySettings() ui->fftCountText->setText(QString("%1k").arg(m_settings.m_fftCount / 1000)); ui->fftCount->setValue(m_settings.m_fftCount / 10000); - ui->frequencySpec->setCurrentIndex((int)m_settings.m_frequencySpec); + ui->setting->setCurrentText(m_settings.m_setting); + + ui->frequencySpec->setCurrentIndex((int)m_settings.m_sweepSpec); updateFreqWidgets(); - ui->start->setValue(m_settings.m_startFrequency); - ui->stop->setValue(m_settings.m_stopFrequency); + ui->start->setValue(m_settings.m_startValue); + ui->stop->setValue(m_settings.m_stopValue); ui->steps->setValue(m_settings.m_steps); ui->step->setValue(m_settings.m_step); - ui->frequencies->setText(m_settings.m_frequencies); + ui->list->setText(m_settings.m_sweepList); ui->fftSize->setCurrentIndex(log2(m_settings.m_fftSize) - 6); updateBW(); diff --git a/plugins/channelrx/noisefigure/noisefiguregui.h b/plugins/channelrx/noisefigure/noisefiguregui.h index f614aa611..9d45438d7 100644 --- a/plugins/channelrx/noisefigure/noisefiguregui.h +++ b/plugins/channelrx/noisefigure/noisefiguregui.h @@ -102,7 +102,7 @@ private: void plotChart(); enum MessageCol { - RESULTS_COL_FREQ, + RESULTS_COL_SETTING, RESULTS_COL_NF, RESULTS_COL_TEMP, RESULTS_COL_Y, @@ -113,12 +113,13 @@ private: private slots: void on_deltaFrequency_changed(qint64 value); void on_fftCount_valueChanged(int value); + void on_setting_currentTextChanged(const QString& text); void on_frequencySpec_currentIndexChanged(int index); void on_start_valueChanged(double value); void on_stop_valueChanged(double value); void on_steps_valueChanged(int value); void on_step_valueChanged(double value); - void on_frequencies_editingFinished(); + void on_list_editingFinished(); void on_fftSize_currentIndexChanged(int index); void on_startStop_clicked(); void on_saveResults_clicked(); diff --git a/plugins/channelrx/noisefigure/noisefiguregui.ui b/plugins/channelrx/noisefigure/noisefiguregui.ui index 7e1b04288..5500ec0ab 100644 --- a/plugins/channelrx/noisefigure/noisefiguregui.ui +++ b/plugins/channelrx/noisefigure/noisefiguregui.ui @@ -7,7 +7,7 @@ 0 0 404 - 642 + 693 @@ -43,7 +43,7 @@ 0 0 390 - 151 + 181 @@ -366,6 +366,13 @@ + + + + Qt::Vertical + + + @@ -382,6 +389,56 @@ + + + + + + Sweep + + + + + + + + 160 + 0 + + + + Device parameter to sweep + + + true + + + + centerFrequency + + + + + gain + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -502,19 +559,25 @@ - - - Freqs - - - - - + List of frequencies in MHz to measure NF at + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -618,7 +681,7 @@ 0 - 450 + 500 391 171 @@ -712,7 +775,7 @@ 0 - 160 + 210 391 268 @@ -867,7 +930,7 @@ stop steps step - frequencies + list startStop saveResults clearResults @@ -877,7 +940,6 @@ openReference clearReference chart - results diff --git a/plugins/channelrx/noisefigure/noisefiguresettings.cpp b/plugins/channelrx/noisefigure/noisefiguresettings.cpp index 35d3ac513..b742cd5bb 100644 --- a/plugins/channelrx/noisefigure/noisefiguresettings.cpp +++ b/plugins/channelrx/noisefigure/noisefiguresettings.cpp @@ -40,12 +40,12 @@ void NoiseFigureSettings::resetToDefaults() m_inputFrequencyOffset = 0; m_fftSize = 64; m_fftCount = 20000.0f; - m_frequencySpec = RANGE; - m_startFrequency = 430.0; - m_stopFrequency = 440.0; + m_sweepSpec = RANGE; + m_startValue = 430.0; + m_stopValue = 440.0; m_steps = 3; m_step = 5.0f; - m_frequencies = DEFAULT_FREQUENCIES; + m_sweepList = DEFAULT_FREQUENCIES; m_visaDevice = DEFAULT_VISA_DEVICE; m_powerOnSCPI = DEFAULT_POWER_ON; m_powerOffSCPI = DEFAULT_POWER_OFF; @@ -55,6 +55,7 @@ void NoiseFigureSettings::resetToDefaults() qDeleteAll(m_enr); m_enr << new ENR(1000.0, 15.0); m_interpolation = LINEAR; + m_setting = "centerFrequency"; m_rgbColor = QColor(0, 100, 200).rgb(); m_title = "Noise Figure"; m_streamIndex = 0; @@ -79,12 +80,12 @@ QByteArray NoiseFigureSettings::serialize() const s.writeS32(2, m_fftSize); s.writeFloat(3, m_fftCount); - s.writeS32(4, (int)m_frequencySpec); - s.writeDouble(5, m_startFrequency); - s.writeDouble(6, m_stopFrequency); + s.writeS32(4, (int)m_sweepSpec); + s.writeDouble(5, m_startValue); + s.writeDouble(6, m_stopValue); s.writeS32(7, m_steps); s.writeDouble(8, m_step); - s.writeString(9, m_frequencies); + s.writeString(9, m_sweepList); s.writeString(10, m_visaDevice); s.writeString(11, m_powerOnSCPI); @@ -109,6 +110,8 @@ QByteArray NoiseFigureSettings::serialize() const s.writeS32(26, (int)m_interpolation); + s.writeString(27, m_setting); + for (int i = 0; i < NOISEFIGURE_COLUMNS; i++) { s.writeS32(100 + i, m_resultsColumnIndexes[i]); } @@ -140,12 +143,12 @@ bool NoiseFigureSettings::deserialize(const QByteArray& data) d.readS32(2, &m_fftSize, 64); d.readFloat(3, &m_fftCount, 10000.0f); - d.readS32(4, (int*)&m_frequencySpec, NoiseFigureSettings::RANGE); - d.readDouble(5, &m_startFrequency, 430.0); - d.readDouble(6, &m_stopFrequency, 440.0); + d.readS32(4, (int*)&m_sweepSpec, NoiseFigureSettings::RANGE); + d.readDouble(5, &m_startValue, 430.0); + d.readDouble(6, &m_stopValue, 440.0); d.readS32(7, &m_steps, 3); d.readDouble(8, &m_step, 5.0); - d.readString(9, &m_frequencies, DEFAULT_FREQUENCIES); + d.readString(9, &m_sweepList, DEFAULT_FREQUENCIES); d.readString(10, &m_visaDevice, DEFAULT_VISA_DEVICE); d.readString(11, &m_powerOnSCPI, DEFAULT_POWER_ON); @@ -179,6 +182,8 @@ bool NoiseFigureSettings::deserialize(const QByteArray& data) d.readS32(26, (int*)&m_interpolation, LINEAR); + d.readString(27, &m_setting, "centerFrequency"); + for (int i = 0; i < NOISEFIGURE_COLUMNS; i++) { d.readS32(100 + i, &m_resultsColumnIndexes[i], i); } diff --git a/plugins/channelrx/noisefigure/noisefiguresettings.h b/plugins/channelrx/noisefigure/noisefiguresettings.h index a569c7e17..fb45667a5 100644 --- a/plugins/channelrx/noisefigure/noisefiguresettings.h +++ b/plugins/channelrx/noisefigure/noisefiguresettings.h @@ -50,16 +50,16 @@ struct NoiseFigureSettings int m_fftSize; Real m_fftCount; //!< Number of FFT bins to average - enum FrequencySpec { + enum SweepSpec { RANGE, STEP, LIST - } m_frequencySpec; - double m_startFrequency; - double m_stopFrequency; + } m_sweepSpec; + double m_startValue; + double m_stopValue; int m_steps; double m_step; - QString m_frequencies; + QString m_sweepList; QString m_visaDevice; QString m_powerOnSCPI; @@ -74,6 +74,8 @@ struct NoiseFigureSettings BARYCENTRIC } m_interpolation; + QString m_setting; //7: Frequency range +

7: Sweep setting

-Specifies the frequencies to measure the noise figure at. This can be specified as a: +The device setting to sweep should be entered. Predefined values include "centerFrequency" and "gain", but it is possible to +enter any setting supported by the device (that is accessible via the Web API). Not all devices support the "gain" setting. + +When "centerFrequency" is set, sweep ranges and values are in MHz. For all other settings, the values are used without any scaling. +Note that some device settings are scaled in the SDRangel GUI compared to the values in the Web API. For example, RTL SDR gain setting of +40.2 in the GUI, is 402 in the Web API. + +

8: Sweep range

+ +Specifies the values of setting (E.g. centerFrequency of gain) to measure the noise figure at. This can be specified as a: + +When the sweep setting (7) is "centerFrequency": * Range - Specify start frequency in MHz, stop frequency in MHz and the number of steps. 100, 200, 5, would measure at 100MHz, 125MHz, 150MHz, 175MHz and 200MHz. * Step - Specify start frequency in MHz, stop frequency in MHz and the step frequency in MHz. 100, 200, 25, would measure at 100MHz, 125MHz, 150MHz, 175MHz and 200MHz. * List - Specify a space or comma separated list of frequencies in MHz. "100 125 150 175 200", would measure at 100MHz, 125MHz, 150MHz, 175MHz and 200MHz. -

8: Start/stop noise figure measurement

+For other settings: + +* Range - Specify start value, stop value and the number of steps. 100, 200, 5, would measure at 100, 125, 150, 175 and 200. +* Step - Specify start value, stop value and the step. 100, 200, 25, would measure at 100, 125, 150, 175 and 200. +* List - Specify a space or comma separated list of values. "100 125 150 175 200", would measure at 100, 125, 150, 175 and 200. + +

9: Start/stop noise figure measurement

Starts or stops the noise figure measurement. When starting a new measurement, existing results are cleared. -

9: Save results

+

10: Save results

Saves the results in the table to a .csv file. -

10: Clear results

+

11: Clear results

Clears the current results from the table and chart. -

11: Open ENR dialog

+

12: Open ENR dialog

Opens the ENR dialog to allow entering the Excess Noise Ratios (ENRs) for noise source. ENR specifies the difference in noise source power output in dB from when the source is powered off compared to when it is powered on. This typically varies with frequency, so values should be entered for each calibrated frequency. When a measurement is attempted at a frequency for which a value is not specified, an interpolated value will be used. @@ -68,7 +85,7 @@ You can choose between linear and barycentric rational interpolation, and the di ![Noise figure ENR dialog](../../../doc/img/NoiseFigure_plugin_enr.png) -

12: Open Noise Source Control dialog

+

13: Open Noise Source Control dialog

Opens the noise source control dialog, to allow setting how the plugin turns the power to the noise source off and on. Two control methods are supported: A program or script can be run to turn the power on or off, or the VISA library (if installed) can be used to send SCPI commands to a programmable power supply or other test equipment. If a VISA library is not found, the VISA and SCPI fields will be disabled. @@ -78,11 +95,11 @@ not too long so that tests over a large number of frequencies take a long time t ![Noise source control dialog](../../../doc/img/NoiseFigure_plugin_control.png) -

13: Results Table

+

14: Results Table

Displays measurement results. -* Frequency - Frequency of the measurement in MHz. +* Frequency/gain - Frequency of the measurement in MHz, gain or other setting as per (7). * NF - Calculated noise figure in dB. * T - Calculated noise temperature in Kelvin with a reference temperature of 290K. * Y - Measured Y factor in dB (difference in measured power when the noise source is on and off). @@ -91,11 +108,11 @@ Displays measurement results. ![Noise figure results table](../../../doc/img/NoiseFigure_plugin_results.png) -

14: Results Chart

+

15: Results Chart

Plots the results (NF, T or Y) vs frequency as a line chart. -

15: Open reference data

+

16: Open reference data

A set of reference data in .csv format can be loaded for comparisons with the measurement results. The first column of the .csv file should contain frequency and the second the noise figure in dB. The first row should contain a header (E.g. "Frequency,NF" allthough the exact text is ignored). @@ -149,6 +166,12 @@ as the total NF is primarily determined by the LNA, if it has a decent amount of ![LNA comparison](../../../doc/img/NoiseFigure_plugin_lna_comparison.png) +In these plots, gain is swept at a single frequency (1420MHz), firstly for a B210 on its own, and then a B210 with a Nooelec H1 LNA. +While the NF is lowest at maximum gain for the standalone B210, due to the high gain of the LNA, the lowest NF for the combined devices is actually +well below the maximum B210 gain setting. + +![NF vs Gain comparison](../../../doc/img/NoiseFigure_plugin_gain_comparison.png) +

VISA libraries

VISA libraries are available for Windows, Linux and MacOS from: diff --git a/swagger/sdrangel/api/swagger/include/NoiseFigure.yaml b/swagger/sdrangel/api/swagger/include/NoiseFigure.yaml index 1d26b3266..fa5c1c27e 100644 --- a/swagger/sdrangel/api/swagger/include/NoiseFigure.yaml +++ b/swagger/sdrangel/api/swagger/include/NoiseFigure.yaml @@ -8,12 +8,13 @@ NoiseFigureSettings: type: integer fftCount: type: integer - frequencySpec: + sweepSpec: + description: "(0 - Range, 1 - Step, 2 - List)" type: integer - startFrequency: + startValue: type: number format: float - stopFrequency: + stopValue: type: number format: float steps: @@ -21,7 +22,10 @@ NoiseFigureSettings: step: type: number format: float - frequencies: + list: + type: string + setting: + description: "The device setting to sweep (E.g. centerFrequency or gain)" type: string visaDevice: type: string diff --git a/swagger/sdrangel/code/qt5/client/SWGNoiseFigureSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGNoiseFigureSettings.cpp index eb4c1df9e..5ed2c9bb5 100644 --- a/swagger/sdrangel/code/qt5/client/SWGNoiseFigureSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGNoiseFigureSettings.cpp @@ -34,18 +34,20 @@ SWGNoiseFigureSettings::SWGNoiseFigureSettings() { m_fft_size_isSet = false; fft_count = 0; m_fft_count_isSet = false; - frequency_spec = 0; - m_frequency_spec_isSet = false; - start_frequency = 0.0f; - m_start_frequency_isSet = false; - stop_frequency = 0.0f; - m_stop_frequency_isSet = false; + sweep_spec = 0; + m_sweep_spec_isSet = false; + start_value = 0.0f; + m_start_value_isSet = false; + stop_value = 0.0f; + m_stop_value_isSet = false; steps = 0; m_steps_isSet = false; step = 0.0f; m_step_isSet = false; - frequencies = nullptr; - m_frequencies_isSet = false; + list = nullptr; + m_list_isSet = false; + setting = nullptr; + m_setting_isSet = false; visa_device = nullptr; m_visa_device_isSet = false; power_on_scpi = nullptr; @@ -88,18 +90,20 @@ SWGNoiseFigureSettings::init() { m_fft_size_isSet = false; fft_count = 0; m_fft_count_isSet = false; - frequency_spec = 0; - m_frequency_spec_isSet = false; - start_frequency = 0.0f; - m_start_frequency_isSet = false; - stop_frequency = 0.0f; - m_stop_frequency_isSet = false; + sweep_spec = 0; + m_sweep_spec_isSet = false; + start_value = 0.0f; + m_start_value_isSet = false; + stop_value = 0.0f; + m_stop_value_isSet = false; steps = 0; m_steps_isSet = false; step = 0.0f; m_step_isSet = false; - frequencies = new QString(""); - m_frequencies_isSet = false; + list = new QString(""); + m_list_isSet = false; + setting = new QString(""); + m_setting_isSet = false; visa_device = new QString(""); m_visa_device_isSet = false; power_on_scpi = new QString(""); @@ -140,8 +144,11 @@ SWGNoiseFigureSettings::cleanup() { - if(frequencies != nullptr) { - delete frequencies; + if(list != nullptr) { + delete list; + } + if(setting != nullptr) { + delete setting; } if(visa_device != nullptr) { delete visa_device; @@ -190,17 +197,19 @@ SWGNoiseFigureSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&fft_count, pJson["fftCount"], "qint32", ""); - ::SWGSDRangel::setValue(&frequency_spec, pJson["frequencySpec"], "qint32", ""); + ::SWGSDRangel::setValue(&sweep_spec, pJson["sweepSpec"], "qint32", ""); - ::SWGSDRangel::setValue(&start_frequency, pJson["startFrequency"], "float", ""); + ::SWGSDRangel::setValue(&start_value, pJson["startValue"], "float", ""); - ::SWGSDRangel::setValue(&stop_frequency, pJson["stopFrequency"], "float", ""); + ::SWGSDRangel::setValue(&stop_value, pJson["stopValue"], "float", ""); ::SWGSDRangel::setValue(&steps, pJson["steps"], "qint32", ""); ::SWGSDRangel::setValue(&step, pJson["step"], "float", ""); - ::SWGSDRangel::setValue(&frequencies, pJson["frequencies"], "QString", "QString"); + ::SWGSDRangel::setValue(&list, pJson["list"], "QString", "QString"); + + ::SWGSDRangel::setValue(&setting, pJson["setting"], "QString", "QString"); ::SWGSDRangel::setValue(&visa_device, pJson["visaDevice"], "QString", "QString"); @@ -255,14 +264,14 @@ SWGNoiseFigureSettings::asJsonObject() { if(m_fft_count_isSet){ obj->insert("fftCount", QJsonValue(fft_count)); } - if(m_frequency_spec_isSet){ - obj->insert("frequencySpec", QJsonValue(frequency_spec)); + if(m_sweep_spec_isSet){ + obj->insert("sweepSpec", QJsonValue(sweep_spec)); } - if(m_start_frequency_isSet){ - obj->insert("startFrequency", QJsonValue(start_frequency)); + if(m_start_value_isSet){ + obj->insert("startValue", QJsonValue(start_value)); } - if(m_stop_frequency_isSet){ - obj->insert("stopFrequency", QJsonValue(stop_frequency)); + if(m_stop_value_isSet){ + obj->insert("stopValue", QJsonValue(stop_value)); } if(m_steps_isSet){ obj->insert("steps", QJsonValue(steps)); @@ -270,8 +279,11 @@ SWGNoiseFigureSettings::asJsonObject() { if(m_step_isSet){ obj->insert("step", QJsonValue(step)); } - if(frequencies != nullptr && *frequencies != QString("")){ - toJsonValue(QString("frequencies"), frequencies, obj, QString("QString")); + if(list != nullptr && *list != QString("")){ + toJsonValue(QString("list"), list, obj, QString("QString")); + } + if(setting != nullptr && *setting != QString("")){ + toJsonValue(QString("setting"), setting, obj, QString("QString")); } if(visa_device != nullptr && *visa_device != QString("")){ toJsonValue(QString("visaDevice"), visa_device, obj, QString("QString")); @@ -350,33 +362,33 @@ SWGNoiseFigureSettings::setFftCount(qint32 fft_count) { } qint32 -SWGNoiseFigureSettings::getFrequencySpec() { - return frequency_spec; +SWGNoiseFigureSettings::getSweepSpec() { + return sweep_spec; } void -SWGNoiseFigureSettings::setFrequencySpec(qint32 frequency_spec) { - this->frequency_spec = frequency_spec; - this->m_frequency_spec_isSet = true; +SWGNoiseFigureSettings::setSweepSpec(qint32 sweep_spec) { + this->sweep_spec = sweep_spec; + this->m_sweep_spec_isSet = true; } float -SWGNoiseFigureSettings::getStartFrequency() { - return start_frequency; +SWGNoiseFigureSettings::getStartValue() { + return start_value; } void -SWGNoiseFigureSettings::setStartFrequency(float start_frequency) { - this->start_frequency = start_frequency; - this->m_start_frequency_isSet = true; +SWGNoiseFigureSettings::setStartValue(float start_value) { + this->start_value = start_value; + this->m_start_value_isSet = true; } float -SWGNoiseFigureSettings::getStopFrequency() { - return stop_frequency; +SWGNoiseFigureSettings::getStopValue() { + return stop_value; } void -SWGNoiseFigureSettings::setStopFrequency(float stop_frequency) { - this->stop_frequency = stop_frequency; - this->m_stop_frequency_isSet = true; +SWGNoiseFigureSettings::setStopValue(float stop_value) { + this->stop_value = stop_value; + this->m_stop_value_isSet = true; } qint32 @@ -400,13 +412,23 @@ SWGNoiseFigureSettings::setStep(float step) { } QString* -SWGNoiseFigureSettings::getFrequencies() { - return frequencies; +SWGNoiseFigureSettings::getList() { + return list; } void -SWGNoiseFigureSettings::setFrequencies(QString* frequencies) { - this->frequencies = frequencies; - this->m_frequencies_isSet = true; +SWGNoiseFigureSettings::setList(QString* list) { + this->list = list; + this->m_list_isSet = true; +} + +QString* +SWGNoiseFigureSettings::getSetting() { + return setting; +} +void +SWGNoiseFigureSettings::setSetting(QString* setting) { + this->setting = setting; + this->m_setting_isSet = true; } QString* @@ -563,13 +585,13 @@ SWGNoiseFigureSettings::isSet(){ if(m_fft_count_isSet){ isObjectUpdated = true; break; } - if(m_frequency_spec_isSet){ + if(m_sweep_spec_isSet){ isObjectUpdated = true; break; } - if(m_start_frequency_isSet){ + if(m_start_value_isSet){ isObjectUpdated = true; break; } - if(m_stop_frequency_isSet){ + if(m_stop_value_isSet){ isObjectUpdated = true; break; } if(m_steps_isSet){ @@ -578,7 +600,10 @@ SWGNoiseFigureSettings::isSet(){ if(m_step_isSet){ isObjectUpdated = true; break; } - if(frequencies && *frequencies != QString("")){ + if(list && *list != QString("")){ + isObjectUpdated = true; break; + } + if(setting && *setting != QString("")){ isObjectUpdated = true; break; } if(visa_device && *visa_device != QString("")){ diff --git a/swagger/sdrangel/code/qt5/client/SWGNoiseFigureSettings.h b/swagger/sdrangel/code/qt5/client/SWGNoiseFigureSettings.h index 0f222d6c7..f25269d4a 100644 --- a/swagger/sdrangel/code/qt5/client/SWGNoiseFigureSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGNoiseFigureSettings.h @@ -51,14 +51,14 @@ public: qint32 getFftCount(); void setFftCount(qint32 fft_count); - qint32 getFrequencySpec(); - void setFrequencySpec(qint32 frequency_spec); + qint32 getSweepSpec(); + void setSweepSpec(qint32 sweep_spec); - float getStartFrequency(); - void setStartFrequency(float start_frequency); + float getStartValue(); + void setStartValue(float start_value); - float getStopFrequency(); - void setStopFrequency(float stop_frequency); + float getStopValue(); + void setStopValue(float stop_value); qint32 getSteps(); void setSteps(qint32 steps); @@ -66,8 +66,11 @@ public: float getStep(); void setStep(float step); - QString* getFrequencies(); - void setFrequencies(QString* frequencies); + QString* getList(); + void setList(QString* list); + + QString* getSetting(); + void setSetting(QString* setting); QString* getVisaDevice(); void setVisaDevice(QString* visa_device); @@ -124,14 +127,14 @@ private: qint32 fft_count; bool m_fft_count_isSet; - qint32 frequency_spec; - bool m_frequency_spec_isSet; + qint32 sweep_spec; + bool m_sweep_spec_isSet; - float start_frequency; - bool m_start_frequency_isSet; + float start_value; + bool m_start_value_isSet; - float stop_frequency; - bool m_stop_frequency_isSet; + float stop_value; + bool m_stop_value_isSet; qint32 steps; bool m_steps_isSet; @@ -139,8 +142,11 @@ private: float step; bool m_step_isSet; - QString* frequencies; - bool m_frequencies_isSet; + QString* list; + bool m_list_isSet; + + QString* setting; + bool m_setting_isSet; QString* visa_device; bool m_visa_device_isSet;