From 480f41ab504f3eff94e3292080659d4f6c154953 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Mon, 19 Jul 2021 17:57:13 +0100 Subject: [PATCH] Add support for character set mapping in Pager demod --- doc/img/PagerDemod_plugin.png | Bin 9310 -> 13962 bytes doc/img/PagerDemod_plugin_charset.png | Bin 0 -> 22646 bytes plugins/channelrx/demodpager/CMakeLists.txt | 3 + .../demodpager/pagerdemodcharsetdialog.cpp | 118 ++++++++++ .../demodpager/pagerdemodcharsetdialog.h | 55 +++++ .../demodpager/pagerdemodcharsetdialog.ui | 208 ++++++++++++++++++ .../channelrx/demodpager/pagerdemodgui.cpp | 10 + plugins/channelrx/demodpager/pagerdemodgui.h | 1 + plugins/channelrx/demodpager/pagerdemodgui.ui | 16 +- .../demodpager/pagerdemodsettings.cpp | 25 +++ .../channelrx/demodpager/pagerdemodsettings.h | 6 + .../channelrx/demodpager/pagerdemodsink.cpp | 15 ++ plugins/channelrx/demodpager/readme.md | 18 +- 13 files changed, 469 insertions(+), 6 deletions(-) create mode 100644 doc/img/PagerDemod_plugin_charset.png create mode 100644 plugins/channelrx/demodpager/pagerdemodcharsetdialog.cpp create mode 100644 plugins/channelrx/demodpager/pagerdemodcharsetdialog.h create mode 100644 plugins/channelrx/demodpager/pagerdemodcharsetdialog.ui diff --git a/doc/img/PagerDemod_plugin.png b/doc/img/PagerDemod_plugin.png index 2cb03ec10547fe64f96745c697257c13598441a4..0f6bae41d2ee5d683cc0d7eeb65d5646b8899f05 100644 GIT binary patch literal 13962 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 MDJ97YapUj*AFdf_IRF3v literal 9310 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

@5TsVG(|E)oXKfY1 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 B51s%3 diff --git a/doc/img/PagerDemod_plugin_charset.png b/doc/img/PagerDemod_plugin_charset.png new file mode 100644 index 0000000000000000000000000000000000000000..7493075a4a4bdbe5e9cf3ea15b6fddeb77faf963 GIT binary patch literal 22646 zcmdSBWmuGd|1D|}(%sSslG0r=gh+RHhX_cQNOyNhcS?sycPX9HT|@V|2mIyp?ET-@ zzRr1ZUU(@34#Um8K5Ko}THgtfkrG9O!-ISD=n>*uF_7G&M~@>PJ$fPy3k^J?)GHSY z{PoyYPV~*Al0kw^;Dcwzf|7!d9+ii|U+Y2vA3y&frfU1>5mGzk&*K;xB>YE@RN&u& z1Qi^$cIS{k5{#u#UY5RHdKUTEK5~aVGPuZwywPI*cqbf3x2iljlh^r;IU-6QZ+PyY z!NOWt2CVAj+Un%7`jBaIoQ}oRNAlI7J^eWzv1vA41Cfo5M!s^oX_Zs&xlJe4*IP1R zBGrT!Q3C?4&7W2rtj3D>B1h-s9PHj1ZeB5BE6=HqMQ+>AY0tS7HpFV83V=Y-x#pt_ zAP~q&mzac-_9J>itM=c_42n4u)879+^$w}oP}B8xA^#*lyf@l z5l~Z8msw0Pky%cbJ-)jhx+@Z&6TWq4_;#M5mh?8Z#}dv^$`f?T=YEsqaL_lhpu4h^ z6rbGqx%pCC`4{rOW=r3?hgH@>Gp}buV_NF~4PVY_uimfio?eyeooyVMDIexfr3{5F zp4$0}y%D?TH(QU)9BBiB1;DEe9=OdnyHdaB0v()F z%{w0PCSR}KwKHg47za0>hN8Ouh(!FE^4(VNDQAH_g*CiLg-B!}D-~^|&S?Tta-$8} zi!|A7&^rZ7OFH}AX&-#6MpTD6JM7z?q1*l{-bi(;Cd^!^PNQe&H2&R8b&}}@h~zf& z%NHK!i1UuyZZZ0oSK3Xf{YfZIQTu!+G&>iYh37*z*u!+6`v>nnVm05U?c=O6lWVoY zn_CHHtHmHHih8NNB&~NQ2sRiy>UQa|! zgsf_ZGzEBzRe79RUw@cMBON_dbzNrYJsb&h{Z5sZzDV!7>qB>LQ~%CRAE$$Fg`#w8 zzdh{WNwq>?V`=Vo{WTnnS&>_;Ztu&0(e1HG_xbM=@-w+wKX(LOZ?;)U7YN=bZQC<@ z_#rf(1$(4L@10mw?AZPiF!LY2-S2ah$Y~s})HkFl&8Moeu2Z#)K#zu4Eo2o|Ng=eMm_uO!l918$cpM)2#_@V>4n$IZ7N zc-+wezaO`v3+1~f?5@W`BDWHV=Zi7V*oX>}$KwM;3cx6Al%wGjw%^-es5`2M7R^OR$$t(Ftg`x-XfgSJw6j|*z1=ERKpHTu(3HxsG95qI4D$f3K8n+F zf$=!H=3ipYCK5iOyL%Ex->l!C+pSyd2f8F`c2l-Y7&IQX{$bXy@cLp5*8LU!D<>$1 zQnP)Gi6aJz{sHC-MSi5F16H1B`$yU=OEBE+(r5+@VvU#nW6+e8SB9l6@9Egsr?t%K zXAEy%SXA6z<=klW(O&H=l(dH4EW~Y|F=}m_*Y*V}q-}l|(sp^=+1FE1b*0-hYs^K6 zrfw9uxxNO*11U3bGAx~@`giap8xpNiS8_t3ZAvR^hRxmSvfd6cD5vk1#7s`f1vKoV z@M4aTTsX^f5}Gza-K8JC)PJHSRehFrNn|!e3(~j$aHn>?VO8|4bwV!cfN5aE6XO$s z`&+3~N@90cXWKb?%8To(wZ(Xpk>nTL_6Rh}B?{(ytZq^Um&tEQ1~|jTm`oI0FS%Ub zpM;1=ui!;kU!>iA!q#?r!S22zly{+hi(^;g{$o=O$lr5@Uk!vdU(4f?S>!HY!sgn_g! zy6~rY71}Qx9o3L6kl+r1EAiNArnC`ra)3#)2%9E;1w-tI({l0I!Hu!V;Xuh9GV;ee zhvU-}<~2zJnYV@Ma15$KtbNqwt6zr}vltP6ej<8#`c%EY4xJ2FUkkBz+uY32xObwe~q@-%o|2wvMAR&XP zb^bdi_fUX}z@3E8QBgTt1>S%_p|8VHP$S6hpA7ct|M)O%Z>gBme$yFo8u9h%j8!2) z{pqxMIlw=z8$v{KoS?lnTL<0M87bO&0n!D3u+FSaA6<`E#i%Of+B=3OgX;mEH}Bhl zFX1$$#L^_bXd}A)1ewr8*S}y6JMpdZH0p0Jw-0Zx_Ln=bwcEj~eTwuEE(f!kju+MF zLGMFBB63cwZR|@5V8`xd(lF!*{KMa$v#-#!{~4e2GNVwi{*3C3Y$yqNZJ~{Gvf3Pv2a^;pTv3|a7Oixv(>RX4JC@T`AkJ@Ita=2v zZGy3_NppXsz!-lxADLQ+tBc~_e*KL?`+Uu6@gPA|Sc+sWn7i3drLp8>A7%aPVcS~o z=@n*o|5*`_1DU_XyQ}IOir!+&HD^NOIjQSpx9W*xTh;35^tptH-ov=7m1c9I+X|kA zG{wp2LIM|Zp~)&E#Br7U)n~m9yc)yoa!TyxRLVh923)V1k3x1>E`r!)Ns>itJM0OI zOk0)@mIFlLXZocNd(TE1jqp?D3w=JUXG-f#T%tQtIq~s_+HR+PUv%P5Hx|E3ZSpp* zX3wmf5}!F_+3O^mXIb7S*B(kF@+HZLmQCQhrS=P(A`ObzRm`XjI@j%yHV*w0yggSIyDHoBkynq`*Q};` zbF`ml&q-_C@GOct)p6){#HcbBHSP=U@Y9wI2Uijy&)3Msz;0U@UJ-#ROjg|{oA3B$ z&wjZ_co12*3`ZWqrCwd2$dqI|Q%ucYoib%Am%@3EI*|-Lmt2KAB@E!2*sDwtI_>n> zGM^2w3OFmeS;ucTcU?uY)}6d|JDi~@U$BKKPZ|Agkugembeu6`j*R zkJX*VXy@1eqnc#vbmuwVii5!MGU_Ota&hduF1JW z%(8dAjk(h`!8m^e7b@ZD(=c^qyCrd0_d??+)8_TEVv69S^)?e!WuvM7;4)I_>j?Ot zeFgy$+U^Y1vu;q*Rx{p`NucRdmXg^fsI%C<-ErNk8w!r%-fCVqRP$4dF0O4>P)A(q zR%=cuC1U|NFoEy1JgjB^EVH=SQY7-Cf@jX1NtSUIxH~`iZRBkf$PR+%vG48*nk*)q zX3P8BwNwlT&Kbvr8qJ)SG_C?CGp0B^a@cP3Cmdn|{%S$egGBRx#oxVx(h85dZ!RMB^qB_LoocfuR zO=tvsY2)bffS#SB9b6`Hm8R9MKW4U=Ic_rLO)@oHIysw}{wz5omAP`Op#GY*XF>c% z3wH+Pqf=pimCw`0{m$-@(la#Q=)?ZL(V35qz!w z#-YI!&5#>W7;--Q1`SvHrWeEYOws@ihc!i|WFupU<=0(y(FCOaepj*?4Zj@FdfB3f!UW&P_fuqMCQmhGeSfUfaRs7F6QUaD%H~ybdyz>O*p6|mzmql6 zpzWvrd`@^(w@_s1fAV#=Z}5j}HTvM1So`zxf!j3>4{Dl$Mf})u0{Coz}V-DSwGO%H+VH>2>kZH9Tmz`)`kce^v>1}%_VCukJ)l~bYaU0 zNn`2Ps+|&!)=O4T(9b(@&!M5xK!{uh1T#pNv$SUG~E_m(aGR5 z5$%FTo;){*y9q6oNciA#e31Ei59`~Jto{!=r}YDxCAALcFryg;7YLdW?^Cn~c!xZ?A}PxXolJ2K8Q>s_?NbC5Y}Ym4t)QMhs+TiU8G=RWTo zO1Lx7wC=a}AwkFVV{9iY>5Ph6Q=M&^TSIwt2?Y^?Rg?U(i>tSJ|n&kC(0Y%H%(!s+WpMcUoX}T*HkxWnJ#gm#XAVPnsdPL#ppADDR;5 zFd`}_{kTZkwR+oim{P*1KzUZ&86(8sVm;?-d59jx-?bYMD0nJ9xExxll19;UO&BXk zX))_W1xEJ3oDL&mdRgPp!(9PdzLlxfNWu0yRP?u8pKK9J1mhtu!(Rp%gc;YbS6Asw z1e~0UgU_zvlu}Iuzp{=nYK|{3^f@JYecV@FMo5ZuAmHb;d2XKA>>WeR;Dod#{cD6Q zdy8j2aE2kd)pX{Tc~G%XqWKe}E9zD1g?mAHO=QzfFS^Os8YuO?4+Tfu9PbzAQzQAU zLM_Fr7xW3`OR(nR*n0gN-p_Gqd~;P@4PT8)yCzTdxOJNS(1u9uhn1ORg|)a7qa4hM z?^Jl$)&NS<`Ze?gLnwW4E-(;I=Oad@O`SbVwZjv?+czwyMvMcbY4#cZylA9qu!Y|) z%cho5-+pBJkkN4?m=)f;KNouA=C*-udS~=&6bm{+Pd%C!t#qP~@GTx#oD3_dT=Y#z zyY0jaFrfMj!^r32iJ}txXKCkLVoh)5OZa5e)au{SG2k&p_U?~*tfx3AAob{j_Zs$> zYMO6~4}TGpvM<#&lz}ZNu~yO1R>??NCEM&KG;?h>i)-dv3roM5@!SMUi;+XV>HzXp zn#2(+_%=2+Km3afE)V?pgUw6odQ9Qbr9@kwS2$~bt%OUIq1ZrYM$PR&B%VwKfhx0D`f|ZA6 zbRCy?(GniW$jI0X;R=e1`K)RZD{++}p`mNXo#{)uZnZzp&ui7{omD(nswT9Oz%SIM zo&>nwt>THTU2Cd?(R0D#0a!#Ab{OCWyYqYp2OZ#ljBzwFG*bvv9(F3H^^b}2U&;oD zgsdLlE*o&)i}^^YU8Lo74*8!*qXkQ^sMUs*md#v?{*alZ8scL)G#ph9WO9y>BMvM#lCg!v<#3MGHK{QVC;Ll?D3EnbTk7MF?1VP%4*xC zMO~pcNiu5n&#yvGHcQJ{HIeSI&@R%Td4k`63Z?h zw5Fx;c&=k<&@$(VV^1R?4_`LD<$6HD5$5LBl&~pd{5<+Ah1a@a25ePl>6br9yhX>H z)iRjMU?e3aO}21EHgk3lr0XQOL+4(IzGkz3_Cm732{R?ALUJ-V_ds%alJGIx9J?)S zR%_TU@*_X4b~ecu9OP#D4MmS47LEj7`G&YEvLo-XoW)&PRP=s(<^HBBPxu|3{q*TJ z$4AsLm{Iq4vUMAhX?&brXS>$PJes~+cGc)#s-bIc+JqZfv*~lwD8U4Y*{MAdn}Y3f z{yMD!k%~~)Ny1*>QH$JRQ-TW80TUd*_JGQaSq+NZovza-^ywJvlKAiPRg^8+K6V;q za(uf=I?tKyGI?Z){a9pf))#N;jU){|A`u$@+X%$8rkz^LW{SL}9J#8j(Y^MOOi{(H z1p5*4H$C#CC<>+TketTGXMKNq@V|_$NTK{X!OUrUd2GsaI;k)J!}BRjFuB#4-De^7 zDLEfy4T_Z3qn^EMOohs0a_NlJShx|2I8Ci7c4u{Fj>czN({SI;*K za{Ynsnz)|kPWoi!nJl>uxRFPANm<}vyF+86gz`k{hTX^N`c4?g{_vctMjpl4k;m|) zu#;h9<$mSX%OVk6A10|HFV+@p76We^In3D>=hYIlgQ~Lq4o8F5Mp%0lnUu!T@(nu^ zRU`Y=&p`?0qLDspO)oewy-LO@cxMZwGD1ucXWmgcECnja2VqUg<23jmnc0=}{`mO# zBnV8+(WKhvdq%N6CEgI0j~JVHgw3ebgoQu4we!&%88Op&7uw`@fGWuzX=JI5@NK8U z9l?&_VO z5+u7n&(TIH9S`ohJ%u?39~T}_i1VMro~EijUeI5v#qAoTR7<%!48eu5!nzdXsc=B3 z!7n|+apmy2BEp)3iMR_f_$G#2g2Hh3Iyls4cKrixHJ%|qN)$j`B31Ph;*ReX)<Zt1sb?wG=9r4Y#XS}#B37IKDTT+Mjc!ja#5XqEBZ?1Oc->%mqx zSw3BtA1J4Av@JDo#a_OAIf{om^24SLkv%WF(2wTnTavVJ4i*;gg_}JGvkoxXfS@X(a6{0$y*T@ zQyL?sg1%@4k+ejdNgsF;R=~8p+HKfwI@9aufej7TjDV8wU5hjVrfQDRbQ$RN7APf#X$2Sgi7j}7ea*H)e=ODuPRZD z5V491Ne{jU;|rdLkd#<|%tUn8M~g7gt;-cf;|~;ULfRegPpABJ%Jm}PtDdUVWCo`C zSaLvDjbc&Hd{DV~2XTpeS65qEPCgHxDv|7QpFX{pyQY4DMCFGbPPB1FYsW;HuxBfq zI!M+5j&u!vAo^b!>BStM=cP7Ip02Iz3Gg0EmE!qf8(KCAG^nx>m-IW&OlC7skEpQX z_{}C;5Sf&=>v+`%(G!ByOMU4xX?=@f)7huq>S_-7`8P9jwhLDd+c>{jDo`vOO@#K? zf6Nk>uh@ozO5`j+_-hUamRVAD<-}x~-qoesjw*26E zz!ad%Sc*S5tdOHUhepHJCAP*M_iK0^Zm?d`Q0?!(QPB23`<%cX>J(<3evc?lsK}n4 zp3i_ZR3ostG`MPS_g13`UhRu31Rio&rkr8!dlf!9I-1A2?(6G&j`@ndwRGhJ2nrs8MCDc0*sFLHLgznGyZ*jL7@M~dRAg=9y8m;v36|F8bcQ5PKYRBr?*27+991rHL*t4YpcBr{NUC`Tql% z`4u_Ed0WWo%F4Jb$Qc{acDfW+DAtORh}(fCraiC1$*mSNr#|lunk74DJ(rXuwM%|u zy56K>)zIWn%@TziVkhhUxgb9fX7TJ2m2m>)`6X&_vLY~ycsyV0^`z>@^s<(hzzw07 zId9o+lAsNgUOSU#>h5fwziiDMzdXVrr0I~9;-W~UHgSHUc$!W}Bpn5%KkDb(89(-+ z=d!H#$;SJ!*OSC9)LJ{jyju#Wn4&xzk|zj?W;jJ%kG!7O3Cs(rXDXpYP>-kA@1W67 z9@$jYqa}_9_TG*T$BvH;FrGp&e-?B@xv?x5*@`|%U*j>*6c!S*BNXya3}OjeYGFGD z?)KtG(vv!=@P`3t|lfgMQhWHJ9o zzl55Ob?^tmKn>z%PBa?D$}j8RjWi~I26|mqR;d0!Fh(D)5`X=^Ry(;E8+B@Bfo!S_ zy=g}Imy9S)tB;BDk|<-|MEV?FANbj@RxVi!=Zw!HyuK?Bf_Y-^a?}Z`aC768AoNXr zr-JI26kBr8JC#&VgQxaLiC{;I6}xacD=Rub)@!?Muql|3#=WHpLAyJKT=~w zECxWwur3`)wInLUF#Mii+Zv%#S+7iRP8b_GqgYueuE4LjY+a~3H?I0INAR6a zJ3?pwVH1if$G%USpLtYjclH#MAT2yz6Oioa z%JDvtV&pht8s47mng9a<8Z+ex0x6TX`u}spo%|%Av8z@lz~3LsFZoH&%8J1QVR5=u zxasM=DaPysU^0e=8qshVwVUvJw@S1X5)!%&#K2xuwyA~RZqo$dHMPo8X?Fo$eL$q+ z1lFI?#lfjI1YW>W`d>13)Ho&I? z0V;f8{-!2DR*ZJ<#vD@OPK$daD_HY-$~YIoN2q-XG;@0v$YD0dxaEYk`F>WS(Y~*M)+Hfw3GNqe12`Auq zun`1muY?qoR3FV1<3Zyal(q#m<%yNU^Y9q1Q^zHCmE>nO_DM}H6|Yl-eyKrszWKyi$1Q{0 zB(FJgi6<n$%mXFbeoK zc+$ka^u^eS?);aTb|x!~6mi{~&jSjTisj6i?04Ev*UX}E&Gm8k8etmRz9KkH1_uWN zG)Uh{39joqzI^RWnjt!=st0Y0s{l%p8MOu8kjJZ!aAWH$iWaa&}fr}A>2FEDR5|cJz6xKkh|Ae=b~}m@6!0SdDo3r@Zu!E7goDV;#T{RD(ki zGb_(5Mdqc$G~@O7cJOEm-Lf;6@f{wt=Vft502KPXE*eic zP!Rlyo>zfvc_C-)em4$;ZOdDTk7rN)YY*M!7ynn7q+ zAf~5@sddkkA)}wPG)1kvu*a*gN8VUNeo|ZJ4<={UReQsK$M0EmA>DRCQNxQ33zyb3|f%RkWrHpcOMM*}w!BZ?`UldmCD99WX1?J#*Fe#M`4&!Fiqs$GQ$R~*XtRvAoo<3Lq@#LOTt(9o6s`Ye;gIA&hsLU&S^Eg~}gTrz|>$)hn$pYOu zMJVn?EbVY=A{k_h;dFwE)Nf$dTkcfY;^6TuZ+kIWdlf%TN@V@4DP?#YroU&-(|IGs zjFj=7R{6fXbQi{Tp5f?Gk@y*UA>cv*U0jFcWUTb3f}PmPD!acqQp0P_#;B{~{psIcCDU6v)WPT;F5_9R#@UF}b)oqWIfAwQMvu=eyUc?4nF`P0k1S=bbIeKVuEW zK`Y)nEzJJm+$(MnW{YV5KM|{uAJbrZ*inI1FI=8DAvu{=4IDWu zE34T+U3xl+`$TNeK|}Sd&&eYFbxHA#4c>J9pQ~h}dC;FVHODIk2+jVVE|Mw8y0V1t z)J1&s35~zfD+EG;5VOf@LUfH{AlK0UY%1mGBkM-Hbx0*+BX^Yj9`f50Kh>v{9tM4cUXEEY z77s8yIVOAh$07_?UQz4gJPF=O)xuuzKSXK@fkRvyd4^%)v`{)JUdtCg|68^(6FUHQ zN5lZ^NV2%XNI(O^Pq)q7ak?}MMbXKg)0OeKkYm4gHN~Mki*HkVapfy}DS&(}Mfvtv zYbPYjw;JHhn8J<)m02Jf37;~>msP3%umi>9ozYsZCV?CI}uIax-}#ehh)XlQllpX$SyV6NzQ&zs=z zzAxGn@zn5@l`UcNUu(yq_ujT95+WiZ=iVUfMf8hVLlL)b&dB#)EPIWecwplb8h=qU@sTh# z0OB;qFu`CzmNY_#*cxCL2f&kufBM#bFM*7NG@}she{RA61*8?;P9Jf|o(KHe;Vmg=)xtJMw%u#$Qn4QT z-1OqUI0kH52%x`1$oP-mXw4mu*EAZ z6m|K-6`TImYR33`4m2Zp7716m1F>+@#CRu1;DEI#XF1?rUmhN;-v!bK#B$Z zL4Z8Pfyr??<1n#58MYM^_9Z|6x#Wx7Pg^eK^GbZ`i9LRu^;B;J$5z_C4qR^hMk)tVY3 zhZ6Eq%OTs3a}i9dX+D=U7dG@TGkLeYrL??9hBFE?vS5T1!}770$y_2ekgSg}&JGii zWXuVH#Ec%`=OurAka7@+K1!STm9}R^g`|qLO&H!Zp2+6YnMDUK$&52SD{|IK%s{g| z4Z1io*h?=lEMW^n1p?L3x?FK)=AZWzb1@L%&yT|$oEy5iR_~7D=i4WvRMNX1{(!R2 zyCGK{PNotdwu=+7LG5;xDY)puvCsZQ9bdHk?9CC{(FN|sX!#C&Tf9kSplbzfp!;Au zwsiGxL*_3oyMRLD^_ABjo7_+mAy(LKI?z%hiYP?@9~8S#35tst-EKIJd>|ea9nlAXb_mmqpmP?ObVae4rJrF zZ`G;|Mg89U#M*OxK@~Bw);L`nLi!S{I-QI)|6!~Elt6lm#&WzRpc&_+!HmR=Ho(8` znRUvipv~odkf$~@@uylO1>8=~z0~61K!ayqm&BJd24yHAD!DvsW`v+|Q5J87Tr%&x zy6$@FjIkKJj1(ice!KVx6Fv?Ea;U8kl?Q?X-4oQnSdpQE<00(lTjEGRo=C2>RO*5L zes4R)XM_r-0Dp{8M+B{~i|S>=F%($C4Q>Af|A7@!OP8qP;5AKGkn%fIhAFOFPgz3z6BSLJh3YOV7VFNojf-(qt|j_%QMjir6IfQieGJYumU6bkM!M!pjP* zZKP^81kcbA=V$s}+m{pTg8cumS6=?MSIz-2WBlIAICc3#Jx|3E*zy`mmjo+M%r=;M z^(F&RR(Q$+?p5j^PPni{&|id%{G|N-mk>cG5{Ta8 zj3;x#glRrRByb%|Wj_Of>cV+>p;2up{TwWTaWB{P|3kUgZ=tQS3dCZ3U!wzC{SJ=x z2_L*kd@or|$jVN+FCZt|@RS#51TX_rd9>gOjO*g#QOfCHY5iChgeNEJ1JG1U>_-kab?2p@rNM$gV&x;$~tJtQrzqgj`7bX-^5281GL5 zCGoSJqKY#Eo<&oWuNI;vt{;BD8lZ4i&fg}Bu#T&GX6n5t=%Zi!jHv=H|GQ&p8QMU3 z2 zwPQsdBuy_A&VY(uAb2Yb@64v%k{%i|Su2~x>nBrP2SbM`zb;sjjXU`Ai+N00SI8!h z6YK8A$e%&_z{}u z@XS4t&E6AP3Y)AsGOdEbZ+zNTxP56t^FrLBuXjYTw8@yD3eu%{vyn0aL<+!(8BSgj z>#+hwGs$+OJ1GmR5|M;*Hs8fImojdiv&S=kqq0BZgg=ELb4mBPcl! zUcvhnFc>5yL)2{Fo0#}(M=X(EizD5O(PmPLhGgGrdhKr-_b$uReF&reK2|h;3*-x- zWupJJz`axryyXv+FyDF~9Ln)B+c}I1rXR8Q|%5d4t;1q2^ zJWDzt=9_-8vAHdjCc(=+3@F4G2mj`_=wHvjG`wrm@# zW<|C?Xbu$upsDT`I_WCD2zP5sjj)%6j9`{@t)Glc+pCPL19`}ZA&g@>Q+{~{rI}+} zc8=xBqmn7qdO!*Vdo99Hjy_URMzt6-<|aR#uDDP=g?y>~ z`DPxGOo*BTFEqEJl~14n=$ITDA}nR^U6jApIaD6nqQVPwK@Ui_P$ga|0IZ4Y40=1& z0|$kKV#2#_dGyS2FGgI-*&{7dP%5O*ri!g#-i+6}sKdtW=J#k)e|CH(=z-F+<)5|H zCZC;$kQLyj3pmZ}?3n#p{o}aPsm#FXTibI?PPR229vFm}$@X z>J=Pb%$7=hzG1C^7HHN9)Q2QP7OPFkd)R!8ce_B0bdo023H;{W!L$02g50$Ne=PAo zHo&MBeadQf<+gY{T>MVH5jswz=>CDf5wbx6GGM2ADjmT|?OT3|lQq!#BQm7xBR3C4 z3wZW4An0}Yeb|5_RzdR%64O;;0Qvv_>Qn@s&3)mZp?ob8+%n_Q^L<8g4&tXMo4d_A zE{6c%=8UCN&#_rsn{!y8o8N5)6E432qC@HuWRLSU5vvvXw9C=tpJ~@UX?acS^#3qY zh14HbM}xQ^{|&PbtVotU^F9QzSHpgMSvE$LqQUeUwK9#RV)^;`vgU(`h=|sq?ZO-{ z_aQ^7PHnp_#xtv+_tfIOpO*WDAtVfKTm3!1LLYX?hw=4Le47MT-9HA(-_9vos}dg) zqlD_Zx@u(Mv_1~&#lD{&5qi3lL3uc?u7wjk$@yOeMU}r*jD(`t;zjM1%%M4vz#!~R)56X zDH5Q1JiqSDB8h0gFg7W)fRdXi!c&TVtdDKH8P|2M16*t*$UoT^J_etoRL_ZQJ+I7^ zB5IeltCA4@1s_Bxj5E#>^I*_Uh2ypi{ibNEG_w z=s~q_tQ;u*<D)(hypv}4vcRkP>`|hyG?^iSAGaE6EMnkV*Wm6zUhJxV8%LvY zO@b9O5RJm9*TE8Htw4aY=v7<+r2Qspi|?D?J}3g;zTa7>ru7`Ry=kaO zetBOhfFqBJihAe=tQ_~81_V5>Qo;fJA7y~j_d2Dkjbr7B|HStpjhu$JcF*Gdi&4%p z079Jnf(qWGne;eq_XN*&;mHqmken14UCWy4e^m=+JOTh0>GZ#!LDs+$~=jf2b8wDb!W59s(4qSFZ&BfO6%BzYN;%%r+a|>PyXv!s$MX&75ESZF6`3?`uC zqhIm(E7UV-AoEmmb1cU`$&(ibL^ZJUDK@>Kv3mljb-aMJIKa_VQhxJOO?D~`Z~8}l z{aCHbGxrf43T~PRcK~SAiKqx$UK>`-_$9tlszi|GSCJ*UAWWxQiKwX133Vz+3-x;v z&f9LNS=OnNzxzYVJO@yE)r*nzGnlV2h5uPA=&yvRB*}SOaw9Y+ChgmveA)qmo~dUa zi_t`8;|FUnHBY=u-r4VRJH<47x(`OYAnr`6 zJ%P2Z>I^fhB-D@fj_cxwplg#2sA-sfl7in`@Wx+TFq|wuwIf7~q$U$uR6%l&oR$Tb zM+1gtW3PSNUKGP_PxX!#y#5=4zE1cxQqeg`NsU?EqhD|>GPJF|`FlGHz& zJ~8t_O{i=FB`AMqLKfyIEExi_jIQn@uUXfY1I5HKHCmC`6Uo!G0%DoSVwKc2JhDNe6xr#@Y9ji5 z+I8^I=*)7yd)r{N1RqKk? z6tD^S8&OUL`jvOoJ~gDLBWIK8p#S;j>W0)m_5IXvxv$t+7M{WB#o@rQICSFys6--& zulxlL)`s=B(e=rWm53+r$HxPiDEt*(QN5QDlt-&+riPa-N*1%VsKqW)db{?VB>Yvb zzF(hjs8KL!>X>}nH}lD{x;1C223yN3%lmoO?~ znMe;tl$ES`AurM+Hd!_Xh0dlQ07+;Q#|IrsHkB68k-p^#4t-8STpIO1(Qh8w*5zfg zJu1sjOz8$QOkdKDcRhZi@!O`hUycvc|80YDsS^FGK16TriHUCo^qx}iLG}@%`9o{=ORI6(MnHbcrg7ga0&=JS`+DH@rYmd^IJiUM5g4b>x$MCqo7#d%u*p>- zF=}d=hD;bYH=uncUB9AMgIzHKopO%lu zR$GB{Iui@^b0BlQZd7}hX-~RYnCrYh|{bU6THG z1uek0U(o=(W@X_1y~bes0&f)3${EzOCQAr`9+$!}$%g@^+*T_HYz`{Dp z;^bb>!p;A$%R)@QQ`K!gS?NdjU4@Pc1SY!>G0B8V+u5c`S6y4C39hw=zIy{v#TX2* zgZ2O$HD|R88QXh_?9euS9PU}q5a4(Z9aF#`Y0*O&H&K5VNKjYWmp*ZBHeiw*gIjBA zN$-Q!PDY}x`=E7H^W(#91LUfIV_=jN#3V+7JriL^waoMjm+}`b!(7EW1_s{9)i$Vn zVm+EbVYBhZ;frFj)6dNfOBrkp1s2yb#ruerW)@`jAIPhRROMpf{;!eO5!dI3dKB{? zf_Y}_vgcIVZA;$F^8JdxtZXxB_CK{Vg&#y8ubSNkVoX4g*vjj1^$#G%6;|=RZ#)#y z0N#iRI9BtMrz+-dkbD1ixXj+~b+u&tGMpD}q_eOJgGR^T(#6p+UVB;$1bS84bczR9 z-aNU{$ba{^S6D>lR8{lGlet|^Y1aXb4jc~!x`c6sZlNF~%VO29(D$bn`P~%61_Qdu zkN7Woq-`K?bz;Qjc3Byb6XnG8fujY;+A2X3$S-|hNhAM#7KU$tpQu%YcT$d)*o^8$ zoh3pMJ?Yuk&u`N|`$q$1`#gc&P{QMrlP}qCR&gPXLg|$mIcfMDi%8FZPXI}be@uXp zu|7C*pZ}Bqud^kt6aOqV4NV$x{j*l6SJFe}r2_8d=r3G=T6?Z?0`w|=^5yl`Q}b9$ zgb=1*&u~@mKt;Y=nIq#QoDVrTJTfbO^p`Z>radH?&DJezX=Hj2OCiILVq}#aAAC7H zjPs6FO?Uf~3sAqW+WK7y2I@_34H%q90v}sjxQvz4ZH|sir5kpBgft=gH9C={;{7=KL zwuLkw_tjTSh`xS^juSaTk+z0iW+J<=fMvVNnT0WO_z6v`!4(vOHeP2B?^>Bs*Eij0 zzTu~L8ZZA*dRpx$haR=dr_pD&%cl3t$5}#sb|Xk$*aiz*ec27Pet8OMSU1R&Fd`l@ zFIv9C0BM{wJfftfw=0;;_ziVYUE+kyPCHDC)&p}Ip){xiX~~o`tHV!z&i>TMo{4*9 zOG>oe(bifxB$miRGxWe5v*!O{D`glf9kmQ zc&7J0UP+QyA+J)6+>T2fH6k9@l{luDP82aABA49njUA_4deB^Bh@6b4Tvn;gVq3*x zb5InmVdOGgyyp!_i-|TZTadx1@EK-xk;s@=1it|;` z(M_gW71o2UdVfmT3K^Gqz@ff4ZdmIOr?1pXwdkhtuhb;X_1OP0&q)P3RvS_hrPV-J zQzgi;zOiAe&^ev&rYYLO=&X=~%jJO)!b zk`i;#z_yiuUWnEIO;j`t%%TUm{d*SuNELn}O$kd{f6Ox{N4i62V*C65h?bSYUKfir zfb@I&QM-Q;kUTPJCCpV`2HAYiA|QGys;X{1f3S9cQPBZ1VrH8!IYv{ONLAp`-C>V4 zXmjP|*w+wvnwA(v#KaBV1eBTbqfe)ZIrxivuIWJz5CLVT>9!jLfJ^ZSIFZ{dEFXOs z9Vu_mpF-uf#i5VZJ$DR9VT~upc+s7zWsS^0<{;Bk-h-;G3wrAtMbM|8x)5^dRXQ6} zo==WfGywkel)lQOLxP>PO>Y$Jxu+%4WI(ftHW!3Uurn~2$U)BTlx~!;QE177C15r` z98oX;isrTtPz0m?(TJe#JTR$ZSRup8+2Q#sdokFszq*liECE+Lvfln0dQ*cdN15?t0VkF7uurP;_{`lA|ly!yafaf}g5>BPr>r zrPoIo0qIY;s;v{3nP9jq!R!-``7tRn(X>fg{)!)h)4C7GXYgKVB~Qk$rqe9$aL9QD z*KnQkoAE~tdoGS=r;BxS9X&tel^LBtZXb){U-bH?uHolsP$yB!OhSMNgBT$@PRQBl$9+79>Z8TR6Sq2PFDcm4+|A)7kKaA>kq=$J?R{(PdV^hEUXA1V_GPAIn=CbS zyLwBfk|EC$GB0;%={2jsRscH0z)~zpQY*w`(((abo@G`jiEmACC#YDXDDR2GoK!7DH+IDCX8)sfB z4H*yZcz_sw8IF(+g;i^~dE9edc!xkL!oEovSp+hI%DEyjKIr~YXZE=8OW96qM|#5z zh}>e7MIUX6a!-t%3=1OPNLi;HiX?dLDR1dY5-)rcJMzXFDrZV+MW3_&^iAqwgH2uD z{j(51U1VD2v-ktD7o21V#Y5zHb$fljy?|X6$v75#0_A7HUhA{Gqu!aI`p}HeVQ(j` zQN+CZT^0`wVN)yw!oTCm5ih_y#|syOYfuTip?2XEJ45OwTxl%uca??;v39I+S5f+5BJls`*fIIVn6|BtwL&p8M&5k z4Z*lJ@Sj}>aLY+MW|mk1zFyk63XY`hlT$2Gs<%P2^a~26M)4EbCx@54Jg1q6b#);{ zY0lc@?l~5PFRJ}gr-WTUf;(#PuFU0#-NH;L3YIi zBfr=ZpR-oUyyE%puU^=)vrNqkp!V&XugMLG4V1!#iqcie;8YWHc?wtMIpKD)y@PXn zl78mEB?gsgBJw3YQRt{SX1aQ$jlX|>5IBjaL>M(8d-#?5S{4^$bE$#vHIW&e;~>QK z`Vt&gv>h4XUEN4P^#xz06ZdQgr^z@#f@y~u``;2C9Z65xi>UYa!Fb+}$vfgo0n5^u~t?kmaLnzyCBr9KK)y0Q{ z=pU&5rY{Dw&iHa4@;aV2b=l}6?MsBUsb8N#@wFxOkoVaGfVzw2QkU7FZBRoCK5v?5 zM2d&2&*sF`ujG9)Tqc9Jaoi769-WJLGJEj7FmGeFsG46nvh)u~rt|E=VhNU@-0uae zTej(OqQ@c((cmFcINWMQO=GlW<0DfZM)*>0vG>>$v-?_IxT%lA{^%& zy5Mp%d!0x_{}U*KJued%VnqCFWoP1fRQHU%gAkc*RQuG9GBX?Cx(2R2eo+U&Zveh; z_sToARp9D^X~o?@c^gNCjg?jI9cjbnl8~x z37;uxU)3As|J>203N*_tbrygx60?=C#DaI{*KMPSNIWts}4$vUEj(+gN+yVChGQL{EimUSyi<9c%*3D0Fu$k(%O+Ky)<# u{37CZ>HgVcZT0`B_x=I||7&@R6sb{>!q1O&`3=wt-s0i}b8K}8`1N0nsl$r^ literal 0 HcmV?d00001 diff --git a/plugins/channelrx/demodpager/CMakeLists.txt b/plugins/channelrx/demodpager/CMakeLists.txt index 894406fc6..58f65cc96 100644 --- a/plugins/channelrx/demodpager/CMakeLists.txt +++ b/plugins/channelrx/demodpager/CMakeLists.txt @@ -27,10 +27,13 @@ if(NOT SERVER_MODE) ${demodpager_SOURCES} pagerdemodgui.cpp pagerdemodgui.ui + pagerdemodcharsetdialog.cpp + pagerdemodcharsetdialog.ui ) set(demodpager_HEADERS ${demodpager_HEADERS} pagerdemodgui.h + pagerdemodcharsetdialog.h ) set(TARGET_NAME demodpager) diff --git a/plugins/channelrx/demodpager/pagerdemodcharsetdialog.cpp b/plugins/channelrx/demodpager/pagerdemodcharsetdialog.cpp new file mode 100644 index 000000000..92251ba28 --- /dev/null +++ b/plugins/channelrx/demodpager/pagerdemodcharsetdialog.cpp @@ -0,0 +1,118 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "pagerdemodcharsetdialog.h" + +PagerDemodCharsetDialog::PagerDemodCharsetDialog(PagerDemodSettings *settings, + QWidget* parent) : + QDialog(parent), + m_settings(settings), + ui(new Ui::PagerDemodCharsetDialog) +{ + ui->setupUi(this); + if (settings->m_sevenbit.size() > 0) { + ui->preset->setCurrentIndex(2); // User + } + ui->readingOrder->setCurrentIndex(settings->m_rightToLeft ? 1 : 0); + for (int i = 0; i < settings->m_sevenbit.size(); i++) { + addRow(settings->m_sevenbit[i], settings->m_unicode[i]); + } + connect(ui->table, &QTableWidget::cellChanged, this, &PagerDemodCharsetDialog::on_table_cellChanged); +} + +PagerDemodCharsetDialog::~PagerDemodCharsetDialog() +{ + delete ui; +} + +void PagerDemodCharsetDialog::accept() +{ + m_settings->m_sevenbit.clear(); + m_settings->m_unicode.clear(); + for (int i = 0; i < ui->table->rowCount(); i++) + { + int sevenbit = ui->table->item(i, SEVENBIT_COL)->data(Qt::DisplayRole).toString().toInt(nullptr, 16); + int unicode = ui->table->item(i, UNICODE_COL)->data(Qt::DisplayRole).toString().toInt(nullptr, 16); + m_settings->m_sevenbit.append(sevenbit); + m_settings->m_unicode.append(unicode); + } + m_settings->m_rightToLeft = ui->readingOrder->currentIndex() == 1; + QDialog::accept(); +} + +void PagerDemodCharsetDialog::on_add_clicked() +{ + addRow(0, 0); +} + +void PagerDemodCharsetDialog::on_remove_clicked() +{ + QModelIndexList indexList = ui->table->selectionModel()->selectedRows(); + if (!indexList.isEmpty()) + { + int row = indexList.at(0).row(); + ui->table->removeRow(row); + } +} + +void PagerDemodCharsetDialog::on_preset_currentIndexChanged(int index) +{ + ui->table->setRowCount(0); + ui->readingOrder->setCurrentIndex(0); + if (index == 1) + { + // Hebrew + for (int i = 0; i < 22; i++) { + addRow(96 + i, 0x05D0 + i); + } + ui->readingOrder->setCurrentIndex(1); + } +} + +void PagerDemodCharsetDialog::addRow(int sevenBit, int unicode) +{ + ui->table->setSortingEnabled(false); + ui->table->blockSignals(true); + int row = ui->table->rowCount(); + ui->table->setRowCount(row + 1); + QTableWidgetItem *sevenbitItem = new QTableWidgetItem(); + QTableWidgetItem *unicodeItem = new QTableWidgetItem(); + QTableWidgetItem *glyphItem = new QTableWidgetItem(); + ui->table->setItem(row, SEVENBIT_COL, sevenbitItem); + ui->table->setItem(row, UNICODE_COL, unicodeItem); + ui->table->setItem(row, GLYPH_COL, glyphItem); + sevenbitItem->setFlags(Qt::ItemIsEditable | sevenbitItem->flags()); + sevenbitItem->setData(Qt::DisplayRole, QString::number(sevenBit, 16)); + unicodeItem->setFlags(Qt::ItemIsEditable | unicodeItem->flags()); + unicodeItem->setData(Qt::DisplayRole, QString::number(unicode, 16)); + glyphItem->setFlags(glyphItem->flags() & ~Qt::ItemIsEditable); + glyphItem->setData(Qt::DisplayRole, QChar(unicode)); + ui->table->blockSignals(false); + ui->table->setSortingEnabled(true); +} + +void PagerDemodCharsetDialog::on_table_cellChanged(int row, int column) +{ + if (column == UNICODE_COL) + { + // Update glyph to match entered unicode code point + int unicode = ui->table->item(row, UNICODE_COL)->data(Qt::DisplayRole).toString().toInt(nullptr, 16); + ui->table->item(row, GLYPH_COL)->setData(Qt::DisplayRole, QChar(unicode)); + } +} diff --git a/plugins/channelrx/demodpager/pagerdemodcharsetdialog.h b/plugins/channelrx/demodpager/pagerdemodcharsetdialog.h new file mode 100644 index 000000000..d94271d27 --- /dev/null +++ b/plugins/channelrx/demodpager/pagerdemodcharsetdialog.h @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_PAGERDEMODCHARSETDIALOG_H +#define INCLUDE_PAGERDEMODCHARSETDIALOG_H + +#include +#include + +#include "ui_pagerdemodcharsetdialog.h" +#include "pagerdemodsettings.h" + +class PagerDemodCharsetDialog : public QDialog { + Q_OBJECT + +public: + explicit PagerDemodCharsetDialog(PagerDemodSettings* settings, QWidget* parent = 0); + ~PagerDemodCharsetDialog(); + + PagerDemodSettings *m_settings; + +private slots: + void accept(); + void on_add_clicked(); + void on_remove_clicked(); + void on_preset_currentIndexChanged(int index); + void on_table_cellChanged(int row, int column); + +private: + Ui::PagerDemodCharsetDialog* ui; + + enum Columns { + SEVENBIT_COL, + UNICODE_COL, + GLYPH_COL + }; + + void addRow(int sevenBit, int unicode); +}; + +#endif // INCLUDE_PAGERDEMODCHARSETDIALOG_H diff --git a/plugins/channelrx/demodpager/pagerdemodcharsetdialog.ui b/plugins/channelrx/demodpager/pagerdemodcharsetdialog.ui new file mode 100644 index 000000000..5fde2fb7e --- /dev/null +++ b/plugins/channelrx/demodpager/pagerdemodcharsetdialog.ui @@ -0,0 +1,208 @@ + + + PagerDemodCharsetDialog + + + + 0 + 0 + 403 + 561 + + + + + Liberation Sans + 9 + + + + Set chararcter encoding + + + + + + + + Preset + + + + + + + Select a pre-defined character encoding + + + + Latin + + + + + Hebrew + + + + + User + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Reading Order + + + + + + + + 100 + 0 + + + + Specify the order in which characters should be displayed + + + + Left-to-right + + + + + Right-to-left + + + + + + + + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + 7-bit + + + + + Unicode + + + + + Glyph + + + + + + + + + + + + + + + + + + + + - + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + PagerDemodCharsetDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + PagerDemodCharsetDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/channelrx/demodpager/pagerdemodgui.cpp b/plugins/channelrx/demodpager/pagerdemodgui.cpp index f2086c50e..31e9a0671 100644 --- a/plugins/channelrx/demodpager/pagerdemodgui.cpp +++ b/plugins/channelrx/demodpager/pagerdemodgui.cpp @@ -41,6 +41,7 @@ #include "maincore.h" #include "pagerdemod.h" +#include "pagerdemodcharsetdialog.h" void PagerDemodGUI::resizeTable() { @@ -659,3 +660,12 @@ void PagerDemodGUI::tick() m_tickCount++; } + +void PagerDemodGUI::on_charset_clicked() +{ + PagerDemodCharsetDialog dialog(&m_settings); + if (dialog.exec() == QDialog::Accepted) + { + applySettings(); + } +} diff --git a/plugins/channelrx/demodpager/pagerdemodgui.h b/plugins/channelrx/demodpager/pagerdemodgui.h index d1bd09e7a..fd3c22ebc 100644 --- a/plugins/channelrx/demodpager/pagerdemodgui.h +++ b/plugins/channelrx/demodpager/pagerdemodgui.h @@ -105,6 +105,7 @@ private slots: void on_fmDev_valueChanged(int value); void on_baud_currentIndexChanged(int index); void on_decode_currentIndexChanged(int index); + void on_charset_clicked(); void on_filterAddress_editingFinished(); void on_clearTable_clicked(); void on_udpEnabled_clicked(bool checked); diff --git a/plugins/channelrx/demodpager/pagerdemodgui.ui b/plugins/channelrx/demodpager/pagerdemodgui.ui index 44d748ee2..51121722f 100644 --- a/plugins/channelrx/demodpager/pagerdemodgui.ui +++ b/plugins/channelrx/demodpager/pagerdemodgui.ui @@ -465,6 +465,20 @@ + + + + Select character encoding + + + + + + + :/keyboard.png:/keyboard.png + + + @@ -614,7 +628,7 @@ - + Clear messages from table diff --git a/plugins/channelrx/demodpager/pagerdemodsettings.cpp b/plugins/channelrx/demodpager/pagerdemodsettings.cpp index 37175dd6b..a78c3ae5b 100644 --- a/plugins/channelrx/demodpager/pagerdemodsettings.cpp +++ b/plugins/channelrx/demodpager/pagerdemodsettings.cpp @@ -17,6 +17,7 @@ /////////////////////////////////////////////////////////////////////////////////// #include +#include #include "dsp/dspengine.h" #include "util/simpleserializer.h" @@ -51,6 +52,7 @@ void PagerDemodSettings::resetToDefaults() m_reverseAPIPort = 8888; m_reverseAPIDeviceIndex = 0; m_reverseAPIChannelIndex = 0; + m_rightToLeft = 0; for (int i = 0; i < PAGERDEMOD_MESSAGE_COLUMNS; i++) { @@ -86,6 +88,9 @@ QByteArray PagerDemodSettings::serialize() const s.writeU32(19, m_reverseAPIDeviceIndex); s.writeU32(20, m_reverseAPIChannelIndex); s.writeBlob(21, m_scopeGUI->serialize()); + s.writeBool(22, m_rightToLeft); + s.writeBlob(23, serializeIntList(m_sevenbit)); + s.writeBlob(24, serializeIntList(m_unicode)); for (int i = 0; i < PAGERDEMOD_MESSAGE_COLUMNS; i++) { s.writeS32(100 + i, m_messageColumnIndexes[i]); @@ -112,6 +117,7 @@ bool PagerDemodSettings::deserialize(const QByteArray& data) QByteArray bytetmp; uint32_t utmp; QString strtmp; + QByteArray blob; d.readS32(1, &m_inputFrequencyOffset, 0); d.readFloat(2, &m_rfBandwidth, 20000.0f); @@ -154,6 +160,11 @@ bool PagerDemodSettings::deserialize(const QByteArray& data) d.readBlob(21, &bytetmp); m_scopeGUI->deserialize(bytetmp); } + d.readBool(22, &m_rightToLeft, false); + d.readBlob(23, &blob); + deserializeIntList(blob, m_sevenbit); + d.readBlob(24, &blob); + deserializeIntList(blob, m_unicode); for (int i = 0; i < PAGERDEMOD_MESSAGE_COLUMNS; i++) { d.readS32(100 + i, &m_messageColumnIndexes[i], i); @@ -171,4 +182,18 @@ bool PagerDemodSettings::deserialize(const QByteArray& data) } } +QByteArray PagerDemodSettings::serializeIntList(const QList& ints) const +{ + QByteArray data; + QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly); + (*stream) << ints; + delete stream; + return data; +} +void PagerDemodSettings::deserializeIntList(const QByteArray& data, QList& ints) +{ + QDataStream *stream = new QDataStream(data); + (*stream) >> ints; + delete stream; +} diff --git a/plugins/channelrx/demodpager/pagerdemodsettings.h b/plugins/channelrx/demodpager/pagerdemodsettings.h index 2df12a39b..f4906e0dd 100644 --- a/plugins/channelrx/demodpager/pagerdemodsettings.h +++ b/plugins/channelrx/demodpager/pagerdemodsettings.h @@ -60,6 +60,10 @@ struct PagerDemodSettings uint16_t m_reverseAPIChannelIndex; Serializable *m_scopeGUI; + bool m_rightToLeft; //!< Whether characters are right to left or left to right + QList m_sevenbit; + QList m_unicode; + int m_messageColumnIndexes[PAGERDEMOD_MESSAGE_COLUMNS];//!< How the columns are ordered in the table int m_messageColumnSizes[PAGERDEMOD_MESSAGE_COLUMNS]; //!< Size of the columns in the table @@ -71,6 +75,8 @@ struct PagerDemodSettings void setScopeGUI(Serializable *scopeGUI) { m_scopeGUI = scopeGUI; } QByteArray serialize() const; bool deserialize(const QByteArray& data); + QByteArray serializeIntList(const QList& ints) const; + void deserializeIntList(const QByteArray& data, QList& ints); }; #endif /* INCLUDE_PAGERDEMODSETTINGS_H */ diff --git a/plugins/channelrx/demodpager/pagerdemodsink.cpp b/plugins/channelrx/demodpager/pagerdemodsink.cpp index 27ddae207..c84eed06e 100644 --- a/plugins/channelrx/demodpager/pagerdemodsink.cpp +++ b/plugins/channelrx/demodpager/pagerdemodsink.cpp @@ -273,6 +273,21 @@ void PagerDemodSink::decodeBatch() m_numericMessage = m_numericMessage.trimmed(); // Remove trailing spaces if (getMessageQueueToChannel()) { + // Convert from 7-bit to UTF-8 using user specified encoding + for (int i = 0; i < m_alphaMessage; i++) + { + QChar c = m_alphaMessage[i]; + int idx = m_settings.m_sevenbit.indexOf(c.toLatin1()); + if (idx >= 0) { + c = m_settings.m_unicode[idx]; + } + m_alphaMessage[i] = c; + } + // Reverse reading order, if required + if (m_settings.m_rightToLeft) { + std::reverse(m_alphaMessage.begin(), m_alphaMessage.end()); + } + // Send to channel and GUI PagerDemod::MsgPagerMessage *msg = PagerDemod::MsgPagerMessage::create(m_address, m_functionBits, m_alphaMessage, m_numericMessage, m_parityErrors, m_bchErrors); getMessageQueueToChannel()->push(msg); } diff --git a/plugins/channelrx/demodpager/readme.md b/plugins/channelrx/demodpager/readme.md index 28c7eb74d..5d28f0213 100644 --- a/plugins/channelrx/demodpager/readme.md +++ b/plugins/channelrx/demodpager/readme.md @@ -54,25 +54,33 @@ Specifies how messages are decoded in the Message column in the table: The table has Numeric and Alphanumeric columns which always display the corresponding decode. -

9: Find

+

9: Character encoding

+ +Click to open the character encoding dialog, which allows a mapping from the received 7-bit alphanumeric characters to Unicode. + +![Character encoding dialog](../../../doc/img/PagerDemod_plugin_charset.png) + +Each row contains a mapping from a 7-bit value to a Unicode code point. Values should be entered in hexideicmal + +

10: Find

Entering a regular expression in the Find field displays only messages where the address matches the given regular expression. -

10: Clear Messages from table

+

11: Clear Messages from table

Pressing this button clears all messages from the table. -

11: UDP

+

12: UDP

When checked, received messages are forwarded to the specified UDP address (12) and port (13). The messages are forwarded as null terminated ASCII strings, in the format: data time address function alpha numeric -

12: UDP address

+

13: UDP address

IP address of the host to forward received messages to via UDP. -

13: UDP port

+

14: UDP port

UDP port number to forward received messages to.