From 821c3ea016072fbb7ab6e852bfcda1d2eb131e59 Mon Sep 17 00:00:00 2001 From: zeefaad Date: Tue, 30 Sep 2025 13:31:59 +0200 Subject: [PATCH] QAM add constellation plot --- QAM/qam | Bin 21376 -> 26472 bytes QAM/qam.c | 60 +++++++++++++------- plot/plot_constellation.c | 113 ++++++++++++++++++++++++++++++++++++++ plot/plot_constellation.h | 35 ++++++++++++ {WAV => wav}/wav.c | 0 {WAV => wav}/wav.h | 0 6 files changed, 188 insertions(+), 20 deletions(-) create mode 100644 plot/plot_constellation.c create mode 100644 plot/plot_constellation.h rename {WAV => wav}/wav.c (100%) rename {WAV => wav}/wav.h (100%) diff --git a/QAM/qam b/QAM/qam index 95b9039e96cbc7d861da5581812f2841efc8645e..8f1a68baf2fd59163ee921852101425809f8c6e5 100755 GIT binary patch literal 26472 zcmeHweRx#Wx$mApG@@aGf`av9w9pelVgT_-DTm=><3@=_Oe~ypWD=4Iq=qC;CW2m( zv>_gbfnI8lO1-w`w(6xVtx+kZUO$Ep30i6cel()hXi;a3A1P9emOA(Md)Hc%J(J9N z?(^I~?mw(Nv)}c8u6MobW3RpT%*r}@(SjV0$1-V{^)D8&jx!a-uNm=x&H(tWE3J{Z zUSOSXodSHg&=lXV0Jtg@3`>W3noctHc4&SkJWtCRXgnmOUe;8gIT?_8xnyO~4gQA- zO3y$;PnG9a{8Ys>zLfz$GSIC@R!51jt&W@0VY{w(OhcoW12O8wv|dc>8E8>}NkbD) z#)O|zZ7&o0!DI5v)v_}6wrIUfI9|&e$TFA+`B}4o*kI@rs%05y^lo@JT+Mu@e+Kt! zJp+xOrCP6Lt`f+E2eqDoro8K+r<+Ji{MW#AkHxyYZ0%R7<8L7Q2@}gL#)p0Fs%y)w zoE9ran&EpakKm_)#+0LR!>8oDwo#< ztw3PKs)qVNQ@An|4g{3wkb+ggHH}td!)mLlp~-5xB^0*m8dgl@#R@ev*H>FN%wH6k zA8ZPT8gBb`ZGAN)Nx2~yUL34P;qyb4tLHV;HH3t$X!GiVl?tC13RZ@LF1^x*x;p#T zV0~D`uWznZ86~H*gGzN_z2+%uX(-ra)CNi}ZK&0zw2Nsbt_p_jP)NHrKUi0Jn-vPK zMkTDK`o<76YpllRaFf*-6sZ8iRdsWqYURy=n#$Tbt0oi-@={rC1=qkE1R+$lGGx^> zGzRO5)d7SmVQ*DsU0p*JqK^AVm5%zV%32B`M$pj31p-xTDg!mO^_6wCx5IWgSXXCN zDdn1~x`rmuR)=cC08PQ*%@)k9;@#&8<`DO(lcyFHlTb`Tm114BXyM#>fvH7PXIQCh z(ezY)+U2S2@`t-+Do2V3_eIi%OP)ACMv7Rj&=hqzq?HVHhv9yxD6~)6qv*4| z-}8PQ`N6%oT@JTS!<~|}=5uRtiymf;*7tdqoYeAQTRTMl6w9aON7vTo^R7QBO+P24 zZ`OZiT(qA>E0(oOukQ@KRMVY|ab)nAUWfDEF6&vbVp#`V^pToI(B-0YU13tUi$2B> z0ef8ZNiMn>*DRCkh*YXjxl;iUo>a=KP+8J-2!&AKqMM~J8Dm{^u7OPQRj3^8$a+RI z3SD&aOe(HWInqo_Nx8CuSIZ*Zti6c)D|l7(5h^QJr$Ql=KV4#+vZQ-cRLffFqO-r5)L5Z%lpke?fNLrgLb`h%Z*kGjQX+EQ;G&=HqHl50 z&vDVWy69tF^mZ40oQuBAML*X??{Lw-=A!R%(cKHsn2XM}p-BfSRF3t%zz_kuDilKc zg(@r8?h1vF?o(O0_Eac@^ovwhuJHb>Agr}e`; zCz|^h*0xStES!_ry^cO%*PB@6G_d-8%#8;A+=t&|?*hAbyyi4#WiF3#& zVuC+Td>HW#!GA%VLp;$g_)m#*T1jjX{C?sb>WLP??BNf#{|<2u-Goo@<-|E;69t0*D{)St2}|(B#J$A(z5-#w)xuJ=972h9!GB7e zLnpCC@cW5#$Rt_>zneIRN}>@s`|FgC7Df&&b0Y6Jtw;Mx%j_w!DbG8bXPt&dO^!Le z#Ilap6nQUP4;6Ii&9iD@z}cL;oM1+OcnrGwi;GlOKP}ngy|9IHdo_go43VEcmEe-E zoJgOu`{UWp?*3tpXTNjktMF(TxJMhvOZL=wFPuN1PybqGuO(&I&=&aw6}B z^PT9dSK(Z8Oa(~sD#UVs?okjtH|-tp7k>DyngN{l5-T8E4jVUMq^@)#YqvU4du!CH z@qTjjn0I1NjpMzOm-<-z4`{Mu-b-TpX;cRtw_Y89)o$=>RB$G~L5A~c#X}S;xG~cGH`f@@6)?5!8v;2RiNTEHg12bHy&s7n9&)`F77?PuGB%QT8s_ z;$@Vr$)oJPWusB(*eE*=Qmzl4!R1(ux3C+G!}vU}9J~|# z9@MU5-X-O`l+Ka^RQcN^R%R&}1-S{8C*8(n8HmdcNF<~FLe#*iI_&Iz2fd@qiCWR} z4uuZ~4i5_Oaq?R24g{|Q!SimKiN9{2*8QGSH~LxlUonfA-x zO?4=4%a(M%ok(+6r2L>0DT%?a?r7uisD1E9pMRzN?3R&s82!A9?(>3?RwWVTNITwX zAC>ApifgAGXI@93cS_WbZ$5)T=#Kh_dmpurM)trHbd@Uf7P|{I@$R&|J7b;$5j##l zwdf4{!#nmu`A46xJsz?9O|JX|`HpnF{)~=yBGvIw#8DHl-B5@*9(3G-5%|nyL`+nU zA}U8`+I`+lwks-}WtN~hcOfht5%lj!NqeV#K&m(n0~ZZyjB`TiP_2RCf+33%{IqU& zBPW*aH4%sbCq z_VoI-pkbWoSk$nBP4e(c777iCIxe}zxT~^)h-E7B?OI}R{tH%oSDqV60qPQO~K zpd^JMBa=Vm$?T!YxM(tZA7S*yIeK})=zaKebD!)`G8s3scd;NrIqrEf1Ql9{@n*)t zP|i}x<#%dnmdPQ&`f1j77pohCC9Rw#BAvf$aA9qq8UG#{tkjJn@>>Thm8O)owXS{0 zT60#^erTrMamQ$7B4R((JEGHmh#jiev!!+IHW9%s-6gV(BHOeG^f7ii*tfQMy0E6u z_we4ixOqj(cSLr-^kt+g!YKy*kkcFbp+->ANw~|YiLQ-39o@0@ZBOKd4F$aYX|Wmh z_B$SLwI9IXd0=K6$Ax#(-*88A-w`t>BouDOac8{uQw}Ar5n}W@(To|&jFKLc!OXLd zT!W{U76%fXk>HD-Ct|GYzVva#3C=Z+f*c}fdrV!pmQ~X^Fvu=s8FaIf#xQ zPa8xf?P>)584n7XBM6;OI*#e&?Cu;8c2_H0*L9g;@AGaNuSXD9E3BZZK9_511hE@) zepZt(keg^Cog1IrCIh6aqu?6(fHAIif`%Dtk&+{e)vmwPGh z?h`r5n&refsJvRWp6Imu*-*XXDLmADj!V*SALE4Ek0SeL+9&RK*~pSN6Fhx;=e(PT z?htwU1bvG9hD)t#CpvrrZX%eC?f8^ftMEMQraI9!vYlvw6U|*P7yQln@B1kBBFyfh zQ}Nm8YqI`K>>18`e2X8{sNI6NzK$w&vr4>Rg4qE#RF&4Vm;Cu6w)-fVd~>@svV{TM zKq(lIn2-SKQmpT|ve-)1$F($WS9S|)c#J)Mb8elF&UMCr(MPYf^Zq<1(#GdlPy|5W z%sdLV@oCwK+@tOSZ3NNs^-k51Cs7B>`TSFejHSrt+(K=+R9P0P+%-GnYe|Z<@yQt_ z&`6}yiT*}xNAD4`czG!DC4IXOGZGB`4UdmRlb@hadus%9gp}odbWfx$kDkcYbhOU+ z*{YaARSX?qG509^H-m~O3K(W!P(^cY3F*EsG~$TYbfQQ($sV|kNF&r*C=9Ot>Hxe zv}>4!9`@sp8QAsML3TCJk%QIa#I#>|Uul2a8Sp5%zb&8D+21x&0WXPgSE9SuWKgxu17YS&5}$~LsuS5Cy@zIK zd(JMDX+;i2j*#7VhVqH|UyNj4kKE4qrwA}mX-0655{;^{2z0L0Nd*$nZU?KkFc$A02(?XIo0u?bZh z=84rr?86Xxxq!Mwyd1U?k6$vTF;z8iz)LX&z~vL}l#;0BTnmTN<2#nhtPR8uzAuJ)41R(~4wfiC1Pnidmb0`^6 zYl}5sKnrBNM}`TG4r%W?P`Vhl-f!!Tjox`Enq4QguhWHH2mO?^U#v#UyU?VsP%Vlb zCu|*hUf_e#d!EQKJ{TSJw5~mP>YcxJS}_|!qsN(HcZD7_j@(2?v;(O&EJhn5xXpNN zv$o3$p8$i{Z?pv}>g z(g1y_cE3i+O8b67i;N!h&Y~V`l@Ugi|4b3cl(|lMpgLT5Bvg@&c@Vjt-qYdFI=rSK z0)}+Zx88;Q)>xk01$8;skcJ&RRf|)l$li&J5N>L7X&~C%2Lo{MkRz*R5s5!>RD2!S z6fQt3D=T3Hn4MPM)_ud|;qPpgMOG&(##kcj$Fj|`26jBzTjG)CqmlBSND1et&%5DX z?_!-h(fci^c^{Q0;S+#Zl-X|p&e*f=0(c#@Pk>T#6ha;>m+iPbAH_$*-Bz%`#%y%w zQ>n+ZH|~7IwcYAtB_hqoBjtU39Ev~dgKzOpDC5Oras1a3EG(LG_gxPEH|I~ri!t{T z*wYY@ZWVv&FRHH5^5cV2qnON@SGZr>9aI zz7*t7%-|NnUerF0R(cu_;d6e+d*U4KcHjn(ybQO6Z_B;R^I!vV|AwWx(w_0 zrL6zz9o-`^@aOE}>YMLStn@ou+$F@4H)P=bzz6z|-^@1HF-HKoFOCczgY?Gu)hJv& zzOq|)bINg-OdnGB)OuL%w2!lg>Wy>Rk1_8L_|}JG4tK%Ss)JK2Vihg_Fty#?h2~?3 zxG&}(i$}f#2JvC5L_bS&3;qAbkTbNU!U0QW3qCJeay(joBHAo-%TKUrm0ILrM}0n; zvDJ=aK*VK-y^zhSR>}_{YWl&-Y?}^~9U4qT5g%+3FfMwB zGQq_G!Vy(5+Nfd_Q8C(}Vzkv2BMYTP?QQP3Y#E3PH(OG@M-W$Bb`7m3aT%=Wipx`I zC-EU#g14PdMVoiA-nYmDnPL#X_bs*_9*J<1y$EZ!S^O@Qcl{5gA%S6Up!qZi@P^u3 zfK_9RS_RO;gz(4KwcD{Ki`wf!I}deCy{g^h-SlVdXjeExm_7=K2^U|6$0%W zg0cSin_~UNXZc-<_&$`?y0*h=?ipgmz5>kDZB*T-WH!Wv1(z-X7g3Pe5$M%G<88QL zN~zhx_uJSC>BHxXn)%+s7>4gLX7~cQKL`^7jRo!ACsp_7tg$9 z*fc7`tCsRlAPVstUr}@^^UvOm{GK~FN4*>QO>FSu_#8wW@kVs%2l(v8=N&{b0rUCS z!aOFneV_rCH?Gg&8wm5Ei2%Lh{g1cMeHg+cy!-{1vhyd>J!B?a#0=wj>v!Nd<&D?x z=ktq2cjkKsyid$Z;;H6B`i6Lv9rA9Rq5P8&yb1-z((p#=pak4fs+w98G)fAz~4bJm4|EVYMUy?-_14gRuV6p5eE6|Jtk)hexP2-nuHFz$#?_@$6v zW%_0d+^`q8580kMf?HN>?Bw}nf4^uP=#pAA9@Ds=uw}!${>rK4#S?!%P1*53=r5P_ zuEMREG0Nc=Bz^&le(e8mqknzX+qXY7d-ZZ_@xlcQtZ&b`(Y9(in zM}EF=gO5Mw^GO{*R6p*6(sKNKPgie36O7`ggu&*JkH3E8Zxh*;BdmE1_4w^&ooWf+ z^>a$xV(wo*DslSevXlO^#{m(F`FXLdK0crzeX>sD8e)@Fr4+9CR*Qy~=WD}e9t1KL zpY}iCg*u)Ji@UHx0Q{0e$z&n$kuN2aivV{6)&bu3ax%&1-2eVcGPxbF=hbAAzvuNG zNhXgIe?6HTi*CK-jb!pl!27T_RslE;JCiMdw_y{x9dH(24a5M~<8@FE;MegYiCZl< z1Ns2tfPTPV;{9O-poKTXEr7ZBQbRl7@9}k(80me`Cq%+dtR&Cvi!INZ0?*gZI5lqz zd?FpMnl1kylS%%#!J2<6-!RK>i7p4+dJr2T@WC2cuwdlatG%bM&TFw|pF4BnwDA{H z&WF#x`E`ol4syw1{p!Qm z$ax~gkAeR#_}m#u=?@zv1^7Vf!RK|f1Am8|;?sw#ln*|T`3?U(w2hxJF=aTAnKn$y zp$yw~d^h5kX=mp^UD)Qa*OJLKkWbmkX%ZXbL1JGRi#DIl?@zePnVKsyRAbEl6LOcm zl}vt*@ilV8*5*)%eEuf>2kaw&1N?szN63E}^h4OG-j~LIHpOS3YewI?Dvduk#piEG zA3&db5VlhGbM6-(Y5#KYzs6ThY5aL9ei``lz+aojUz6g8!EXnjXEdbj4|^t6{(n** zeY`x4Uz+0Y0H5!`bJO@%ivKeBH{mt!{xtsX6#qE*!|+W3yo?wqzh2yv-_njoKNt(X z^asiyaT}KdfF^m)1rurfoJ=Ppa54fXBXBYTCnIn&0_hPj=SG-wB6$B~;#n3<2LCt% z=h+oZc!8jjtUd?MDu_*2WPGbjk~yye-xrj`SM*HhDv&z2g6kJ1!~fe?$p+$GdOggg z8B>K8;8z@&`Zb>~7n!DG4Z(D}0`fe-EWVVHmb98>&ZE<6R!lR@`WxSkm1NF1@au{j zy8I#>62|XtEswALO5*bf6JB6TeUKGVymAq|UptP+8^MhqcoY!)Ud_jseFZmui_!lN zm(=-j8D(Fg`@sSYZ`80x!&^1HOT&9Ld_=>Y8t&KdRSnHH`yh6hT z8s4a3jfS^sc$bFvYWRqTJ2l*|;j0?Hr{QNBo}v%UI9tPSXn2K&3pBh@!x{~5)$lG2 z@73@T4NW+mN|n26-n?)63bCTS#5ZMn(bS?TzNy7irx#y2MHa_KdNAbh9B%zJnaN>) z9g2=uk3-TqUWSsN2zm}qCh5hGd70!{LS=`PpC!Bk%bc^PMXgd~Jk~j>@n`5Y$k2Yv zR7EjseRh5iMsa5UTaE$a!zlObxEVWq);kk++V#W|V_=Yejt7H`kPCeyu0zou$U?6{ zxwLQ2x0Gjb$Uc@uo?mvRe1)DEO})B6_u-S7-U4ALfBJ-;Z#{j9(vW9GWdD&x-ivy( z+%Nt~$;-1RvgZk1(cIU`r00yZ%sg&*)3lx8y4~d&6ig?J9efvmNdIrnLSL)x|4iF= zbiv%887dCzb)b+6=p6ppUY=*nm-V z^PK6C{@}K(@&#Gw7iFPO%R*lOx^J*~s{-_bA^QI+v6FAj(TDcz(z>01>W}<1LZTw^m-N=&~n)Y$A&t{_L4{ z%=~GrorW9cQ0;rZ(DSXfVkIei63G5@7Wsvs7r4%)Gxp1~$Tw>Hlhk&#C3_}N+Mww_ zKTBDVJve0lho*m_+e`M%K>uYH`%h<~bG<}A8#ChhN*4Ke7Wy%vW4^jT`N{c|DL2df zIa27Dw=dIj7$-~@W|6-P^r6oAo2%{oNKdF0+Rimu?A(-v-k62HHVb`A7W)4Lo#QLB ze{Rbn|5O(GAF|Lt$U^@@==s+7^}_WD6;3M;3*n*q^EjdBTiv?7WG@psf8lt^!D_fb z8!+IO%2h>G7G7oGT2ssSELBz`UTOrY+?)I$R^!Y=9O7437px9c)rP9%yhSWb0=5%a zuy{_19dPC^wgOizx^C{AMS<%UEV#ig3zW^7yU4~#jDc0nb=6hVtib%G*Ul+fIM1p! zuUCSBMjmI_q>csjyU+47=M|y@u}LPI zVsiXp8kc7n*5cU1n}Y%MjzrAVSFQ>UItNmnjhLn_?^x0)coW8=0+pcOg%1-teKB+($yD*Rin9mq+Gs z$}|IkKv~JWfPL+J904lzMx%xG8JHP@)lCh7l{m^0eSyVh9;YeV((hFt4OG_GuENot z)#`lA3}efinshxg&(ur_UalMxlWF72qL1lA4zJ==S5+@So7^7ivqjYznknm3(Oh`H z3h(4l%{02I9uEWM`JNdiktwH=W>#2^MIEp+L!az9KtYK-DO9?toSd4*Qm1;Rkyupf zgi>_`X&Rpgi>46*L3weh&k{{z@f6oI!l08#Q(PPeisN2WC=Lx>QQ6$oR9jiEJ0uT* z9bltca*(N2gy4rOmji}F3a&J{`i5|@XhnTcYX%$u9Ru7{JhC_;TYcSM=H|1$a0K5>6Z>56HHP(e`5xu!699)B|%tu9` z1_@D7aAlw-gvltdvKqPu({9a~yKr*2a)r{@6OQPcJc_AYRa*rg8ekchA}LOpM&GuI zsv1_U!s~l;=lFku+y~;bC~ixV%z5nw`Ze7Ev#(-sE~ni3Td+=HGH|>?Q&-$Z)6yJZ zTvC|wv;DsSqokJ~2DKI|YruCmMp!{VkSl z^!0Mx`Zv&6q$%I*hZ$)0zaSzh)Bh?^xz}X$&Hj>s%e0>H-^dx*2tN0&3~u(X3?!e4 z{!_;IPa4xYeAp&N-|U|m*i9iMQ@+tR^^br@{karEGW&4`n*BTKbI&eQ|A(M4CiG8| zSr=(&_9+cJv;TY_47a{d>lrBT-i-C>(G6kXK_jSPX8Hd+L%(#M5;U-oo!ga6 z`x(-6$hgOU=KqcG89@y*%YO;K0b{|uSs8Qehb%i!rhrEkt%-c%qyAhp8aFb zo;}=ie!uViKJWK_@BQ7^Z{~NGxu`tPW;1jeWqi{h)?XwkF3nh^Gltqex7lz zaT>^@ak&&b8#+cwhK2=7j%4cXRQzoC6(y&k_K=WzxzfsUlB1#FkT~`7nN@f;{Np)N zPD9O4mN#AUjVu^d&S;pf$Jm7DO1*GJCUmNLPghXu1h~OfzVLLlWy=@ ztn6h&7kErAaW{-?y$+?94W}x34Os>gA+Ns6hz*BMK{X5wwcgUV0yWHM`=@c2($i4; zxmfANXGno;_(P?qp)T)w=rNxE-K4w65>;NV_H(hJkTg`yB4WZW!oGIRwN*x5s}ZIz znr|~~0zVxzraXmfK4mB1VslXclV_g2dBN|de>k<{%#yo=oG&h#aggqH^+7tDbhK09I(B_;7=|>9K@Wl9?Ih<@P%Rvw4 zpnG!A>5daub}9#9q;l8hpg)*{{tr3mpXZ?eA_u)K2mO^C^wl}&4LRtK5aAdFP*VbIUd z76!gEhx|d%i;T%eWU*Azl+)~ z%>j=;;C4&V5e2Kg>za(F#j8{ukjnTjZNMLVs!w14@}j2 z>gpP+p^U+yTDe&7@lgo1frcu{?XF(uao749JaxYB!fe1>S7%g9<=X1H#%9pg`h5X_ zX0P{F1Lo>Ev|P?ywai_!XyLs1?wKVsOJ*C%{G4R=vSe=7WsGhfMzhfv5pB5g1jhSm zA}?`C$5@!8F|Vn#K~53+3dd)TuPtZ$FofnC(-bXu-vb!#Mj11JGue(AUY@W=c|Bk2ei2rku20R!n%<=716ln@<6%CyNF0mR6f5w)G`d)q z2rB0NH2RkmjbI>+o<4v_(&*=<$?JYi+s-t)q5K>J8mgX51!;6OwF#ahjjrcZGA5f z(H&{@rZl=*G7IjyGE6vX4G&<*hojTI!6EzWVTN?e# zY4pxC`lK{^R~mhC8ofJ>es&stR~lU{jRiNHM(3QNQ(qc=iYA_dry_7F0{^EY@PYlj zlUCcY0xOi?b2Wz1jp0CEqTgzJwqTF&J2877$cbtDako!#AxC@-d9g?WY1(e$oJwN- z0)L7)r;u1!;J+fysV~+o@P8%FsU+4Z@ShOpG!^R*_(Q}wrNmkV{(a({N@7g{-$I;I zNNlCRzek)?M{Kdcze}7`M$9E}KXFbKvFQT8g*c~(m{Z`Zh;wR)IRt(aaZU*_L*Pq@ zb1I0%zW`y{w}?B4M+82PIEVgNzre2~&LKY*7Who!9O`4;0>6+rhxk~hz|SYnp*_|i z@Uw|?>W{Sw{7m8;;$uw$A4{A=du*k^^N4duk1Yny_MGwV!r*}wR`7_`b~L`Y(wq^V zvDa#!dp&}ZnD~dehVfx-iG9jFP(g#Y&pq@_g8YL7bA|#F(G`9PA$En+6A}BAR?6*B z5b{40^0R+JaKRT=FmCm{ceT|sG|I9)Zyop|FaZWOC<6tFNUeR!f|Ne}Yn@vUU87}I zmDM))CP*4q@U1|h6`ETPdSaplQnVVeem;Kz2)3K|r2K^+E~7Su(_U;fWUF9fDSGl6 zE4X2s6*9Mlj9UBgqbKYaMrtkloxC-KqrXRpPS`IF2hE)!bEmb<>WPf9g1yly(5>KZ z>RG|X#l2=1D?M1Eg+^PUDp*}o9IEKDs`pwwheuiMUl~i)vxVxYHnYnXGP_F6o$L3> z;@hG&co2pMxEzK4a}DE!eMJww2}^G-g{nZUpxM`J?qHcQ?ud5rdAbNbR_(AIwDqUV z6q&nVi?g>VsC#5%i9J zD`bSKx+OjuI6QFRvI^SFZUnCz!Lx5IMPs&^JAm&HcpO3M=&(XJ5AEH_WF32)4XP$I#TrM0;(<9X=?fDX6$82)!Ym zA{V5QS)Mt>_JQ?2w9Fy2%+2wTc}#TW(XtBMBcJLKyNpEflQGL;Xj6O zA1gIqv~R6LaUC6*ep|to{$SO9D_9YRUjw10(IIpHgP(jM{TvWa+ClX5e!9;aLaF^{d^1LX%l+3;b|9MZX}&&an##~aG(c%LOZ9*Q`s1J(nDuw_HXb&SO| zj}g&PIf|$pEj8ozt!7$OILa(TbM8V|x`XK7!HUjavrklUG9Fwss5Z_4rCYWJx)mN- zl;EOua{xJUtKd^mf!>6NvDe%$tUQA|H1U)>EGHj3`3x>UARoaC&HakI47OJ60rwU3 z2b!FC6=nkD_u=XR{RLd?C%dD~L+D+2lyQ-PDRy;qru= zkfYu!xZnZ|iWV-zBuFc`ghf>03|#Zko%XYtXnKyh-@bJQg4bsDA((xo<_`PTSF@hz zrPkfYwz0~=4Vw|u*5Li?pI2{AFUWR(%7Wkyd1e+fV^jqd8`$ed~E5N{)(M zil{nCn8UEra#SQSWW*!@c`_q385Nq0-n)2;qkM{a!&BV;iJmXJrA*eO_G2tmP)_=I zc@tD>u*M9YUEyrRHbrU(~YXeeeMaSJTAZ$NFI``1`BqeegG2XV+Mv z(bI}SMK2hd5pEMa+g&rQ&_=SYki!b)yKy{dwHLNxb!-Ly1gpE~Q?v`kie*gfZR{I* z%`i`@#QNm;tEkZcYs4G+=LUEo*K^OJvGciJVdrAM%U`Y#(bGV=n4^LS3A-MjW-Jpp zL9w6Y&r;G6s~z(JD)@5*3(Mks;aqQYK1xbD?<%l@8yAauNC5d+*rTAbomQ}_3xVni zRXuA}?|X_hvOakq^2;dSp5KeT0qvhSAq)zt7;}50|G_eX8`S{R73{S_Ef{F-7X;zf zf#6B%x-po;)Q^;@$6yN6UJ!jslwyB;cW~n(6c-YAJ*f9a8)N|-Pn9UkxL@MG8CJ~r zztL`3K8reX`9+9`3|^7wuZW(8g`dMCjt6K2P0N2@(26#$L#dQiu<)>wMMroESqy+` zVi|frHG;IJtgkRz#ke9{{sYumposZq2vzVVY@=r4F>0T9FScbco0_w%;LE$X6^;HG zMOdMV&7u1lCTK7OG~5$>i2*LhSd9Qb3sN7fld@Mj$`>HH0R)3SF7D+{zkRtoDhWbWXI2XuF>=s9c)1ZHOE8d!}N+ zfMK{Te5Q@hdTp=yC!2wLzYRmnYYVXHvOj6|Z}WvWFS8jzGeXQ3t__+8A@rhyx>P)h z65`nXUM?ch^VDdB;c0HuqRT}iR)L9?XYjyNBtA_xqjHsC3QgNE%_%8n3?~d$Fx_k( zm{=`C36&Gpqr%v99d|EF= zDd>I?biatvG8s?%*`l(&Q71T}ugBgOjcP`oV%(m_B^oS(0$~Ut?~U$c9$OybVh%}4 zJ*A{1^zdLs@H-J zWa8ORco_te@m(yQ@Ln@cr!2KP!LuD7CxVL+S3KK)q)|M@2=0K<@)ZR4AO#SxJ+e4a zO3a665Je7T#Yum7Y%$-kKZ5R!q5wYf&{r*R^BOk?5u}QY!bhIJr)q>;W4gE%7oNyq-gT$7x zyD&>7Vv}SP`?26Gu-d|7tez-3rRe3U2tCM3>hW7^{soSro)J1cSRpMtgkR!>;GS?` zmcVF`qor-P{Ru2Kt0HYj#yrCjIe6fOw}U5x2PC)u^gpqls9l7$lMc->BmPIx=QiS? z6hu@-^tt8IpCQz0$Y?nqeQpH>&>Yv1!)PM^W)u%MD>-;M+8j+O8X%r*_gPX_wC^`` z^q}{1>akW?VMO^)mw-&$H&UKqVuuTiN0G>eZ6HMk&wxKKpBmA zUw&KaSiP(mV>x8?x(b-bmLYX`YoB89{1!{JIIh3dF0dD4NLhY@86Hp^2J-2N1@`58 zc-srgdnfGQIbK_arQ(S)`!Y~U-nEDL4j;L__7LChL)0l2keE z5HqH|(EOuIu! z-0&P#AOR0}28NnY=7zWITO87_S0V5Y%v`b(3id50NiDONfK>be$g>xcyydZzaMeL ziQn>faP7f$1W}B^eBskrv*DZpd#B~V#fjo`IALEP19ZfG?;AX!MhIWw?M>V&&wU6w z%uKtF8OHJUTi`e{M;IDbyYB3?1rE9Z7AJ15ufVukZNiKCvo*LD#v>`?eV`=&im z8~nbgU*+N0Mq#8CC7{^Kp4hEvxNP~#L-tK>P#LWYXaU_NP&E-|cM(;OB?m9BVA{RtH-AUS~~ddc0jE*p33v?uDx(}f@pJ|no%}_oQ@9PH{Cy{sR^b<%h#Y<& zS~9I!8pA!#2?6Q&U6K@65O2?AO5#eTRYAjc&ZyEK0>J^4G5s%zL?2+}jYOgw@K7X? z;Qs6BBZq*iEV%bSW^BDa50v)uK_-e{VluG z44h3l0q?^JnG3KA=ea8ZAI6DlD_|)O*E#_^0KKVhYa4mLPV&Rx z{}FtyD3ki5ibMfUkRrJDAfDH!^XbDi(g(`$&3_!Rws=IT%dj9*Ix1OCF=QrSNxlvu zNtwK6!FPgWfnNu{n@1e&qbGfDn_(BDNLxF&-?FUda!`UIRrKLT4x`*{x~>o^X6{eUOc8T|Qz z&&IzP{66qqjFU>NE_p1H|C?YUjn}DkDgvh>a4G_)B5*1Kry_7F0{@>Pp#PVo|A)l& z4-@|@#iVim7m5jQOJowOXv5I|i3wjM$@;$``u|V(ZKFt7CW~~og8F|@Tn{p7{zqRV z8j1I-wHbfd&E&uV9TN_)L>f|joTQ5+*2T!_|MW~!bp9|pJ?SN1^g2o95|*h+W%NEm z6=&%G#>8>L&7|p*6t4XqkZePd4P8E7Rg3z7EktqTCh#t$i0ziZwI5g(3w)L0<9)xt zwco0k|8=1MKb~DMUuQFwD|mx~wF=&@;3fqhQ1GV;KB3_A3cjS^UlsgV!PB_mMEa6~ zUsv#Q10@qQwk%l=I=#jBtKutK_ARP=j)R*5zmWMJT2f%<4~>x7F{c04NN3yoi@0a%=)AQ&Iyuro%)Q%5TWCxh-xp~+maihrM)ki_{1xTT;M z{IlwehmoHO8CL_f}(Gg1B)TfVnB}yx)8~@oy=KZ2dRD4&N_gd>x=F^ByJlzop{XzWsIouH5SeSq6M^(EB? zPM2}7_2H-+(Cw~osjI1;Ww;kCzqYJm;e1dq<+x4DUB0BO!gN~;mKg497F{>5Y?1rA z^75r-rMt3h-Xha2{@d?L{)Zm_r{{+PQiM6f|InXg;?MQsV**J6|Bg?W+<`{-Djz;5 z@b|uDz)uupXz~*T83gggfozJGmfaq|-*boI_KGuXeCHq~HOG)25lB(s6hAlMQ(r5{ zWMqBnAjw44#1|5h1lCP|Eg_RAzle}QLkv^+9Dal$g~E>f+Cc`%?PgWvXA_Loo|fij zpQpjy(1;ft`pXF!^5U}z8I-JVL-3mo?&`({d_$s6y$3-V&5iCg_*er!C9&{2lvd+w zaJMvjYYg$l1vlSWu;JK%@=Z#!`mRG}QC@uS0TB&k6;Pw!hNy2hWGcB=H8-mYitj@3 zdlI6=de5z1w|vKdhQbFWJoPZZ*AW>8wGU(9fu*Dmw)o&h2H8_nqZ&(o?IMF|lpvM?&nm!xU&1vy*U%X7maJ}QDQWVf z!v4S=MoE&is>O#-?D%So5`3b=>u)lI;2KZ!8l$AqiT?*VI5)W6G_vc?&NIcvee&^%M$y zokuaAdS5ksXoO|lNbFdLGw=GGsWV>GE@ZM@-AB=})7^Lgeros!{9rtMWC}t>}U#lVcO!S{J+JDlR_@a?*qV@H@TEhVfA?fn9zOH`|JnGM*5R%@f zYpD12)aTMWTmJ{3F(&j+Bt7pdsLwAnJG=jIf0M57RC*eUcZ*sXFw4C0V3xjK-)R`v z2P(>j*4HMv?n*CT?;|wS=QCP9+y6(EzK(zP_vzwU9VWYc?$;=y_4WQz!yoE`70fRG z-?Q{L&y<21y0l@XuiH)MJ+XZjb(MTXuOG*YFMK zVwaHA*XLS&b3sJXauQ47n$GH7K{Agc7ENlls2dK%_IIbC1x>-t?%Ui+!dXuTv3Wzw|&dc7ZUNr`NI zrz9uug{u7NNs7#9{p{zLzA~l5tS%-6$|RVs0?%y`&-S$cdi)_x`z|%)efl*L{yK}P Y%hj?xcFGbFtT(?UCG #include #include -#include "../WAV/wav.h" +#include "../wav/wav.h" #include "../files/files.h" +#include "../plot/plot_constellation.h" #include +#include #define A 10000 @@ -73,7 +75,7 @@ void bits_to_symbols (qam_system* qam, uint8_t* bits, int nb_bits, double comple } } -// Modulation qam +// Modulation QAM void modulate (qam_system* qam, double complex* symbols, int nb_symbols, double complex* s) { for (int k = 0; k < nb_symbols; k++) { double complex iq = symbols[k]; @@ -83,8 +85,8 @@ void modulate (qam_system* qam, double complex* symbols, int nb_symbols, double } } -// Demodulation qam -void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bits_hat, double sigma) { +// Demodulation QAM +void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bits_hat) { for (int k = 0; k < nb_symbols; k++) { double complex r = 0; for (int n = 0; n < qam->N; n++) { @@ -128,8 +130,21 @@ void demodulate(qam_system* qam, double complex* s, int nb_symbols, uint8_t* bit } } +double complex* demodulate_points(qam_system* qam, double complex* s, int nb_symbols) { + double complex* points = malloc(sizeof(double complex) * nb_symbols); + for (int k = 0; k < nb_symbols; k++) { + double complex r = 0; + for (int n = 0; n < qam->N; n++) { + r += s[k * qam->N + n] * cexp(-2 * I * M_PI * qam->Fc * ((double)n / qam->Fs)); + } + r /= qam->N; + points[k] = r; + } + return points; +} + // Libération de la mémoire -void free_constellation(qam_system *qam) { +void free_constellation(qam_system* qam) { int sm = (int)sqrt(qam->M); for (int i = 0; i < sm; i++) free(qam->constellation[i]); @@ -143,50 +158,46 @@ int main (int argc, char *argv[]) { } qam_system qam; - qam.M = 256; + qam.M = 64; qam.k = (int)log2((double)(qam.M)); qam.Fs = 44100; - qam.Ts = 0.003; + qam.Ts = 0.0003; qam.N = (int)qam.Fs * qam.Ts; qam.Fc = 2000; init_constellation(&qam); - // Nombre de bit multiple de k sinon remplir de zero jusqu'a ce que ce le soit - //int bits[16] = {1,0,1,1, 0,1,1,0, 1,1,0,0, 0,0,0,1}; - //int nb_bits = 16; - //int nb_symbols = 16 / qam.k; - - printf("Lecture du fichier\n"); + printf("Lecture du fichier...\n"); // Lecture du fichier et conversion en bits const char *input_filename = argv[1]; bit_array input_bits = file_to_bits(input_filename); size_t nb_symbols = input_bits.nb_bits / qam.k; - printf("Mise en forme des symboles\n"); + printf("Mise en forme des symboles...\n"); // Mise en forme des symboles double complex *symbols = malloc(sizeof(double complex) * nb_symbols); bits_to_symbols(&qam, input_bits.bits, input_bits.nb_bits, symbols); - printf("Modulation\n"); + printf("Modulation...\n"); // Modulation QAM int total_samples = qam.N * nb_symbols; double complex* s = (double complex*)malloc(sizeof(double complex) * total_samples); modulate(&qam, symbols, nb_symbols, s); + // Ajout du bruit double signal_power = (2.0/3.0)*(qam.M-1); // puissance moyenne avant échelle double snr_dB = -27; // Signal to noise ratio double snr_lin = pow(10.0, snr_dB / 10.0); double sigma = sqrt(signal_power / snr_lin); - printf("Ajout du bruit \n puissance du signal : %f\n SNR db : %f\n sigma : %f\n", signal_power, snr_dB, sigma); - add_noise(s, total_samples, sigma); + printf("Ajout du bruit... \n puissance du signal : %f\n SNR db : %f\n sigma : %f\n", signal_power, snr_dB, sigma); + add_noise(s, total_samples, 1875); - printf("Demodulation\n"); + printf("Demodulation...\n"); // Demodulation QAM bit_array output_bits; output_bits.nb_bits = input_bits.nb_bits; output_bits.bits = (uint8_t*)malloc(output_bits.nb_bits); - demodulate(&qam, s, nb_symbols, output_bits.bits, 0.0); + demodulate(&qam, s, nb_symbols, output_bits.bits); printf("Ecriture...\n"); // Ecriture du fichier de Demodulation @@ -199,9 +210,18 @@ int main (int argc, char *argv[]) { for (int i = 0; i < total_samples; i++) { si[i] = cimag(s[i]); } - write_wav("s.wav", si, total_samples); + write_wav("output.wav", si, total_samples); + + // Plot + printf("Ploting..."); + plot_t plot; + plot_init(&plot, 1400, 1400, 0.04); + plot_draw_constellation(&plot, qam.constellation, qam.M); + SDL_Color red = {255, 0, 0, 255}; + plot_draw_points_animated(&plot, demodulate_points(&qam, s, nb_symbols), nb_symbols, red, 5); // Libération mémoire + plot_close(&plot); free_bit_array(&input_bits); free_bit_array(&output_bits); free(symbols); diff --git a/plot/plot_constellation.c b/plot/plot_constellation.c new file mode 100644 index 0000000..3b10cfd --- /dev/null +++ b/plot/plot_constellation.c @@ -0,0 +1,113 @@ +#include "plot_constellation.h" +#include +#include +#include + +// Fonction utilitaire pour dessiner un cercle plein +static void draw_filled_circle(SDL_Renderer* renderer, int cx, int cy, int radius) { + for (int w = -radius; w <= radius; w++) { + for (int h = -radius; h <= radius; h++) { + if (w*w + h*h <= radius*radius) { + SDL_RenderDrawPoint(renderer, cx + w, cy + h); + } + } + } +} + +// Initialisation SDL +void plot_init(plot_t *plot, int width, int height, double scale) { + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + fprintf(stderr, "Erreur SDL_Init: %s\n", SDL_GetError()); + exit(1); + } + + plot->width = width; + plot->height = height; + plot->scale = scale; + plot->offset_x = width / 2.0; + plot->offset_y = height / 2.0; + + plot->window = SDL_CreateWindow("Constellation QAM", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + width, height, SDL_WINDOW_SHOWN); + if (!plot->window) { fprintf(stderr, "Erreur SDL_CreateWindow: %s\n", SDL_GetError()); exit(1); } + + plot->renderer = SDL_CreateRenderer(plot->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (!plot->renderer) { fprintf(stderr, "Erreur SDL_CreateRenderer: %s\n", SDL_GetError()); exit(1); } + + SDL_SetRenderDrawColor(plot->renderer, 0, 0, 0, 255); // fond noir + SDL_RenderClear(plot->renderer); + SDL_RenderPresent(plot->renderer); +} + +// Dessiner la constellation (grille verte) +void plot_draw_constellation(plot_t *plot, double complex **constellation, int M) { + int sm = (int)sqrt(M); + SDL_SetRenderDrawColor(plot->renderer, 0, 255, 0, 255); // vert + + int radius = 8; // gros cercle pour la grille + for (int i = 0; i < sm; i++) { + for (int j = 0; j < sm; j++) { + int x = (int)(creal(constellation[i][j]) * plot->scale + plot->offset_x); + int y = (int)(cimag(constellation[i][j]) * plot->scale + plot->offset_y); + draw_filled_circle(plot->renderer, x, y, radius); + } + } + SDL_RenderPresent(plot->renderer); +} + +// Dessiner un tableau de points complexes (rouges) +void plot_draw_points(plot_t *plot, double complex *points, int nb_points, SDL_Color color) { + int radius = 4; // plus petit que la grille verte + SDL_SetRenderDrawColor(plot->renderer, color.r, color.g, color.b, color.a); + + for (int k = 0; k < nb_points; k++) { + int x = (int)(creal(points[k]) * plot->scale + plot->offset_x); + int y = (int)(cimag(points[k]) * plot->scale + plot->offset_y); + draw_filled_circle(plot->renderer, x, y, radius); + } + SDL_RenderPresent(plot->renderer); +} + +// Dessiner les points progressivement avec animation +void plot_draw_points_animated(plot_t *plot, double complex *points, int nb_points, SDL_Color color, int delay_ms) { + int radius = 4; + int k; + + for (k = 0; k < nb_points; k++) { + SDL_SetRenderDrawColor(plot->renderer, color.r, color.g, color.b, color.a); + int x = (int)(creal(points[k]) * plot->scale + plot->offset_x); + int y = (int)(cimag(points[k]) * plot->scale + plot->offset_y); + draw_filled_circle(plot->renderer, x, y, radius); + SDL_RenderPresent(plot->renderer); + + // Gestion événements pour stopper animation + SDL_Event event; + int stop = 0; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) return; + if (event.type == SDL_KEYDOWN) { stop = 1; break; } + } + if (stop) break; + + SDL_Delay(delay_ms); + } + + // Après animation ou keypress, attendre fermeture ou keypress + int running = 1; + SDL_Event event; + while (running) { + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) running = 0; + if (event.type == SDL_KEYDOWN) running = 0; + } + SDL_Delay(10); + } +} + +// Fermer SDL +void plot_close(plot_t *plot) { + SDL_DestroyRenderer(plot->renderer); + SDL_DestroyWindow(plot->window); + SDL_Quit(); +} + diff --git a/plot/plot_constellation.h b/plot/plot_constellation.h new file mode 100644 index 0000000..a6aeaf1 --- /dev/null +++ b/plot/plot_constellation.h @@ -0,0 +1,35 @@ +#ifndef PLOT_CONSTELLATION_H +#define PLOT_CONSTELLATION_H + +#include +#include + +typedef struct { + SDL_Window *window; + SDL_Renderer *renderer; + int width; + int height; + double scale; + double offset_x; + double offset_y; +} plot_t; + +// Initialiser SDL et la fenêtre +void plot_init(plot_t *plot, int width, int height, double scale); + +// Dessiner la constellation (grille de départ) +void plot_draw_constellation(plot_t *plot, double complex **constellation, int M); + +// Dessiner un tableau de points complexes +void plot_draw_points(plot_t *plot, double complex *points, int nb_points, SDL_Color color); + +// Dessiner les points progressivement avec animation +// delay_ms = délai entre chaque point en millisecondes +// Keypress pendant animation coupe l’animation +void plot_draw_points_animated(plot_t *plot, double complex *points, int nb_points, SDL_Color color, int delay_ms); + +// Fermer SDL proprement +void plot_close(plot_t *plot); + +#endif + diff --git a/WAV/wav.c b/wav/wav.c similarity index 100% rename from WAV/wav.c rename to wav/wav.c diff --git a/WAV/wav.h b/wav/wav.h similarity index 100% rename from WAV/wav.h rename to wav/wav.h