From 34f7fb77c7e460466494e37c0903c02029f54cb4 Mon Sep 17 00:00:00 2001 From: heclak <46121009+heclak@users.noreply.github.com> Date: Thu, 12 Dec 2024 22:13:16 +0800 Subject: [PATCH 1/9] feat(a380x/fcu): add correct QFE label using baro preselect (#9637) * feat(a380x/fcu): add correct QFE label using baro preselect * add QFE label using baro preselect * add characters q,f,e and test q to FCU font * clean up old QFE label * adjust the alignment and size of elements in the baro window * docs: update changelog * fix(a380x/fcu): redo 7 segment fonts in FCU font to follow the correct font baseline * edited all 7-segment fonts in the FCU font to follow the correct font baseline non-7segment characters are untouched) * adjusted all FCU digits to the new FCU font --------- Co-authored-by: Michael Corcoran --- .github/CHANGELOG.md | 1 + .../html_ui/Fonts/fbw-a380x/A380X_FCU.ttf | Bin 10628 -> 13332 bytes fbw-a380x/src/fonts/A380X_FCU.sfd | 4136 +++++++++++------ .../src/FCU/Components/Altitude.tsx | 2 +- .../instruments/src/FCU/Components/Baro.tsx | 28 +- .../src/FCU/Components/Heading.tsx | 4 +- .../instruments/src/FCU/Components/Speed.tsx | 2 +- .../src/FCU/Components/VerticalSpeed.tsx | 2 +- .../systems/instruments/src/FCU/style.scss | 5 +- 9 files changed, 2654 insertions(+), 1526 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index affacd06b5f..6fb2d237026 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -87,6 +87,7 @@ 1. [A380X/SD] Add brake temperature color change to amber when brakes are hot - @heclak (Heclak) 1. [A380X/FCU] Fix display of values on FCU during light test - @heclak (Heclak) 1. [A380X/FMS] Fix VLS computation error for CONF 1, might have lead to FMS crashes during climb out - @flogross89 (floridude) +1. [A380X/FCU] Add correct QFE label using the baro preselect display - @heclak (Heclak) ## 0.12.0 diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/html_ui/Fonts/fbw-a380x/A380X_FCU.ttf b/fbw-a380x/src/base/flybywire-aircraft-a380-842/html_ui/Fonts/fbw-a380x/A380X_FCU.ttf index 6469170783c808ebb0d01203311953d6713143fd..7d477945dd79f2f1f378244e0646c0178906f95a 100644 GIT binary patch literal 13332 zcmeG@TW}lKb?5FAi#HY^01^bbz=8ltfG+?fNQ$DU2O)~ogCZpnR47XnNmH`*U?oMB zl9A%aSXN<6u`^TGV|!|k+d6GCmR3oeXyUZvHnpv|ldAS4%GjO6X*_k))b2-I&$OM0 z=(!6}vJ(On^@!w77udb;d(OG%+;h*Kdlv`**zv&uq|=+$J?nVV1(5hJ%&lC#sy7X1 z;m~EV%~Qq4j)q3H(41#_!*WP@1B|7 zYx`!?SF!UxtTQz|esCt20~Y%`kL8BxJxA|89&GvnfY<|2w|3Xm_+;Q4_6YW6#`3mZ zm?6BwdNI8U)1h5^4;`8Oz(mV`f$2ZpvwvdzjkP~Q%!Lmyy=m|Gkr~oYcr4$AX=UH| z-l^AKY<~ry8S!Jz&+I>Vh*j8E5kBqj(9D6U8SPh5q*u@|-3W9n@P3BfaeTY2>tisn z6b}5;%Rlzf@V(<7zn;60Tg5)kR$|fs49&$0+pwWr4{T+Bf#t8UkLx|<%ks}UJ*SQk zkn{`&(+s%vruiBi^C#pnK-`%u^D<^Vnh(jl&_WOn13Zpf;kp{bjKRBmC*eL&Kx36$ zJK_+6S1_B>0^}&`z(4^){uAPQ&N}StKK)*c;Un}0$X!56M=*|g_N!UM^n|m+!PVQ}_5XUt4 zV(u?;M+!XySg}PL-ucUkfeXs?gd041=!J5q&|^CP5eq-2svrm|g!KFx9Alv{*qA{% zbww)l3N$lMQa;J?AczLZXfj)@HoF7oiheo4g`nLC)?1Dc5nQDo0e$kSRswU$po-8D zG(ea>a6&9})h<-wM$0vbY2X~t>IXAg|KU*$)MZ{xh-Q|K>UqaTl^<%v+30Q1NKAQ0 zGe;XVCN?mX=~YJq4H_HU?Nzj%!AwBw8Ew$G7;PF*17FDe#P@?yAJ)rU_I)_&Qv(_w z&1mVvqk6&UDE7z4EMr?6G$D2_NKPVj<>c6yPXp{mjGYVVSv^;>3^CcEbTl<+QcO8U zf&3lzuV`$|8dcG_aK8qFne0?{T%nP6Um!5*%j&72e2M}z=CQN;>;VK~iYagDvR9^ii-{&lF8y z8>?S zmKoJtQJnM3fNDXRE!QR7g>xK#R_n%ckDFEyf{{iN2`4cNtEL1sh=0ASWNR1G znxy?DXczb^bNPv@OsGLXOGz??WmrN%i3rPzAZSZxSjQm|@WkB-Y;*-Mp$Q!+go-sO zSRKS15O*R@ux%b=+OD3ohyjXBBVoHqDh~@$xB{zH$D@r*b9}GB@+O`Tw!*_%Ss^6y zyzrdOp&3|nxxh%WLy*o|t@Z|q5R(vn4(sx&m9^2D9A^=PUg0%^jTl+kYzqm5uaJ3@ zAehZo!NAN$S;k=Hc}d{;E|ZZMq*heHqA2(oPUH-ZGJ*(kjKJ{>SIe7UHwx>>S&kvZ zU@#l4*bB#mu&HXdI9MaG&2C}W3C7pWd>za1oInKY?0=Uz4A_;QF&iX<*eaod@8&qs z$njPKL*5kxNj4aaLTe==(QOnZQ8G43oYg0~C5MdbfsePEMAr9!(P5B)|#(YL&XT->26PxT}m=6SABn%^(e(CoT$-r|8Q*}Y$ z5wf1VP2NB|0Gvgq;+sXql>E&+T*iKL7qIV6I7l@{IN26=yM$nSurU~HROutA!yd_{ z(bALwEfW$?bdp3oApp*)C~1RKo6NlLk67ESlJQHku`XM?ZSz{uaec48j$?Qv)ku4DN@g;M-K=d=?c2Q-7z<@u%c+HkA;-4L^S3P9wvs_H;GVtA*CLjqI!*h1@SQ>K3lJ1llO;Gk0)KtRm3Mq z-JD_>8mah;C*ryzR(Dv^e0+h#AFYPYO!`CLDp^XpNNY0h{7kix6OswR@JuL}=^LnZ zZd^A!5(DEfFHI(^2;K|gz!^YV-pFF;CLoC9H zj@GWRG%JhtwvNq`Y9OR9n?BbAYYasZu^lh)X|JTogGv> z^g$PeG8g_RqH~OC(XmU>;m4s5MkxylzOh0@Y@xGKn4>DsuyEv4%z7*lR7TQk>niSv z^f$M0W>%?ckH*Sm5~=A*bl8VhBr9B`qWrHr)>nVAI^v?d80jBI7qNpgiPe7OaD5Fi zxVpNwtU{s%duzuQW2{d_E=%@sZ7SBpFh-ZH+ZIw*FX^lM`I^Kr__49 z)Kj5{wtYn2*XPbe0Y2_GIum-gZ74!Gad0wQ88OU6FkS$M&?Zi|ksayk*!SC7FEq-v z&DQu|)w|YMPP6jhMD4S+?c|=`s)mcHk=btzn9BXqFlp^|4Op8xygR%dO>;1_2=fV~ z88<s^oRKBFeGq^_>qsIQu`W{P5*}d06g~6_4H-$^9H< ztQ-46O~g{^mp!O)sFXVjGG7=pfzj0w(nBRqFRSu+@2dY^GWorF`!ZXTXfuY5L0|n- zl|H4auKLM3f4#ZM#LC07_fJogFAe`XIXoTyqnceq8)tu<>LTF{k34YZX{vu1Scdfc zGvW}2rASc#mCM{5%nRxj-J)I{$kZIYx*}@Tr=l8cSw>D1vNY9QS8L(~bEqL5Pcg*r zcl0{i>Q0?Xu19VXQdwSUk&Lz~PX%G+3V(ZRkH=eCxum7b?{)-&4+SRsaB%u?Wvg;| zyk*sPbHShX|L>U4Ma^5v}j z$G?7yZKP{m6zhJBb@61$+}uH#moZ+Da3)$-B?YAlXXMMiW1GZN&EIYERfamg$jT>X zU1Q`7QJ%ki!+nDrwcxJBr+j@oh}UDMmGDt7dW-LR4D<#3+>6|e z(|t_jr&oMTyWvDBeu=m&UdJBr&31+_-nn!$JmHI)wTtwDQ@?8b6MWcvE4WZx$Ef@i!+X&y8jZ_TlU;v-2Wiu;ytitgws z?NMH&ZZN>w+$v_ft{am09&`jAhi}0}z*CdOceP2pI{&tiw^EvjZb;*akwn~iEgNc| zCC87!W!{E|KLmysOj1lVj@Y?Mfw!22@`~xAyLESw*GFPuL%8)1=*~C9=HpBAD)4i;4R$b{l6xERGhF z=M3Y4=kgFf6ZCD_3TN;wCV%;%s}LvnK6A1VXArNmg*c0r7WIZ`tbr{B>8SfT^q2P&|dtn^*z!dhJ(togW|IEJHBUXGL=dJ3_}vqupLjbC(!fLtjE%ryAt<~w_`86@#NSH_Bf8vVK|xI zzC6*|ynT6kc;(>s$=wHM_Kaix5CWXWt!7&704ArVKfh-jBWXl?A0kV`16X59N4F8d zC^$TLq<;~>^DSDiMT36Nkqznn`wpe|ADEs};*HHpr!qg1SkRJeNH)*`xJguRL3$40 z@a)#9RFJA>WCNv+{$R`0frGpE?^BwaTN<02F=H{*79DDO>L0J%OY|)8JXam&(eFK2 zoG(`Vg24gwR3H7?fPQI^|H{CJUl)YXM-;(t7@~-96QY|yuWbsyb6Ab%h1VcMhhY<1 z!(+(M2WgM^%>(_81b}`mQ;YQ(oCWmj2!j6J06taR=Oox;1fLw%p?K2z^e#N#z4Z4u K^q>C5<$nPP80Fsp literal 10628 zcmeHN32a=)d7hbf?(W;`?Zs=!y|~Mp%RPCCq$G=?C`zJ4iBtt0rb&vDB})V)2NqJ> zQH{v0YROKT#HowMg`766Yr6{4*sATOhK&{~S|D(cHt_``Hfp4(TcmXZIEA&_Z{9wN zl*B`lLw7w*2;GVNofG$r&)hxqAMX&thEVqW^!TxvVi6;e`a0CB(}z#& zf3)oflZ1%FgoOX{z|{C;_>rpbq3&&j+yNBG|0u}l>qS0x;GX06O&+&7kiUTZ*A5?@ z7=QAaKRtr}BJxA`jNdmyW+=v|?Z}6YjNdc$ch9!JLP#9-?83~^W5?N-gnB~iUPk?4 z!qn1^u5IHY|itT_QMqWWNro!ih;6@Z8l>RqK86}$lYsd)WY$qA!fso>hSm_wb z$Au89F2&?=Ge#LNUzjfzk+&m^2-`>iaRy-m;WS`)4{QU2UU!Io;cd0CLBol)0pG(yp)5%`|}qw@L7!s=B7Y%ik>FKXazu&FbAcD z3MC+}o-AtslB2JQ%BUjRERvM8i@K<^sIqK-RrkNG$j*?(TJBM_w>&Osz1^$CeLuE(s3!Vdo+d>O`(>x9xa|(Bjj~J6i-J{`WlfdjA-iU^tpz(C6zo=2qr4Pk@s`e|VoR*j@ zsZ^ov!V48Xt7H*t1#A?X)w0%R)$Bv4)MQz=3iS6BMR!^JmSLZw*f!ZMKC8dYCb=V4 zfLEcb7NK5oIaM)yPV-xRmcdFz(T413U#ZCV+9RVUv`&BnbljwyIbp*-0stWYs$Bui)HzIA*|@A|YX@o7-cMGVE--lD&tU*M9|Gso7~Zp7~_&ZhK`O?F*F zWE>djW37xb4e4epwuPi(HE{B)8p%bY0Am|f&S@=fwQ zmp1%ycHQH>xBW(Cth%_By&?!Weg_QtCs#Nmloh3Yo1are69X>2S(d_n#i`0V z7rKl|5@TF~>ayxoXbYrkv+fFrnuo50s+N_66oJ+?caBC$4;dpfhO4Q!;#Rm`GTqd{jl*@!3vYVXz zw3Jeo)hneH1xnfwD2uCcOYNIS1aUF#j;&czhr2nvhnLp1npYNC3uIOWX(wCB7s#W) z_MB+BR;O4Vm7k4@PHhlPi!lBYD85>Oo|jlRxgU-!CYF}L`>oP(u@x5RN%Qo1_O_$Y z3O`YwFa4JK0s6eiy6mrufOCq=zH-REZZdvdl8-K>BwWuywDfs%>76By{$)1Oic*X| zbeqH#fy}iWQ@|$I8dfebibF0PRQrqaJl)7Jo^jvnE zEs(1v9izlg*Y*E-dvVik%P%Vmf<@KHUjt(hRxHAXQ2`r9l(a&Em{tsK0@MTCkO2c? z1C7G&7>P!rIX$1rc?>foj2$hE-euRNfNWFkNi}paueE6X_N;yE{Fs(?^muEl`u;s7 zv3n8ldBaR<8a@FmZw9j_e_>;#t7tccvDL7&=5zFv z#fE7l7K`j0*jVS^p^GfBG2PAtwxusuRYqYzTb=1rnOj?x$y8J39rb&vI<^mPV^kDH zr&y_vZ{5FXzhdn*BnN9&s*4|5{PlT#RkWmla*M68 zw5Z43NxQf$H=kQYGi@1TrIF}JW7mav?by1Zc#TERcJA1))fp_?6XaCS^f=*RE-@S8SOLZc!r>wDVh{JapH36C-RTb3wl$dwFRdv5LC5BrFV-ZyoEBq)BTN?E zqD`p@g2D~8RP}aukKTbr%dTw4sI_Sz3MyM%@w$9dD`Qr#v&R_=t?%lrDQ7gD=xR<` zY@$OH)$)n5P`#_iS#GB+78_l^sV)M8tux!cebbn}L0{9DsNFR%5DNlF8PM-T;3x~~ z8P-5^m7t`FgH+n<@^Q|L&LhQagd$hQ)~YoGrw{zFb?*KXak<;nb?>2d_+GmXf$EY58sR@Z48?O3t{76Gdq|PX9=Xu=`h>G*&MyIzozN$ zbJ>e6dR@|y`s)Vo2K!k-AD*atvaX%py{@|XhxxI>^BZmDLCXluuJdkmw04x;S=P}y zH|J^0`3yMp~C+N`oow0j6j{&gE{C=S`%^%n(Od59c_et~yY*x8b!+=CuY_ud`Kg zTI1G8Wy2Fym7(hTns3$z8?;uNppO(zPEXSZM?T4nOvfLuJ+N(S;V1cS8sGA}zxCW7 z0EO6ty;#rB07IOt!ivHWE^~XZ#Hb*h3Cuhq^K^7g*4-MxbN;ZOr{s}x};~WJ3bVtF!k?2NtTKliF zJw2;e3;MS{`H|4V+cu)@FVWUNzkk5@I`)#u<*d?hkZTad)7h-7jL~pntWb!DxZg?`mFHN?Bi{ zQJd1GS~IESD!Zmnhz`jf_m@`|ergrf#A0@i;gyU?H}0GhOEjY=;J@l6J7IHL&f@eL zl7l)HH!R&+oG-d9KLfPFZn_tH;S}~l1bCgo%@yK-YQa6~hE6i)Qx^^OBN~ZE7eI24nsSxkIreB*(4vB`b*kpGMwN8CgO9w1OEL>axOh* z&nb5MddcN^OH(}MR!hh!sc-uW`xki9%B9zjUG~thDSG)jPk!FYoQs> z;Lgx2IY_3-0o)%7kvcL#>Jg_%5}^%qgvcN{1Y6c&@Z==P8!uUVbmqkD!RZ6XLv<7N zp;R)}))X2%G=6w$GM~>AGD0$>pX`HgI1SA*X{7p5x)#3geHi5+Ifj`JW7HF9oax`U zI-O1KTirjhc6i_9!DBOr$5Flw6Hdca#GB0`J2idp;c+DT0rn99%i~$Jm@>d^!89SD z2Uo9dVDeIrHuPvV!rZb+|Is7I`;X2}PlZw~$xvr#aUfCAmTAs3a|GO?RgYplvp~;5 zW0fJSDhV?1)$x~%PR$-Wc=SjpnQUuGCQ)!Bt6dV+=54Lw_xYWpMV?xeQD~Y1Za6w{ zQ_M~H4FY~UjNc3^-3qJ3ZLk=0&;)LtH3HyPfSbl&VIKF>)`OU1@CA*Nhxkaip~ejE s){v`1I|l9-5Gej5Yw!)@rTD*(;wz#JhmV?}lp^o`^FILPSKdMVU%7Fb+yDRo diff --git a/fbw-a380x/src/fonts/A380X_FCU.sfd b/fbw-a380x/src/fonts/A380X_FCU.sfd index 2a39043f653..7e8922de6e5 100644 --- a/fbw-a380x/src/fonts/A380X_FCU.sfd +++ b/fbw-a380x/src/fonts/A380X_FCU.sfd @@ -22,7 +22,7 @@ OS2Version: 4 OS2_WeightWidthSlopeOnly: 0 OS2_UseTypoMetrics: 1 CreationTime: 1603675803 -ModificationTime: 1732268502 +ModificationTime: 1733903687 PfmFamily: 17 TTFWeight: 400 TTFWidth: 5 @@ -59,6 +59,673 @@ OS2CodePages: 00000001.00000000 OS2UnicodeRanges: 00000003.00000000.00000000.00000000 MarkAttachClasses: 1 DEI: 91125 +TtTable: prep +PUSHW_1 + 511 +SCANCTRL +PUSHB_1 + 1 +SCANTYPE +SVTCA[y-axis] +MPPEM +PUSHB_1 + 8 +LT +IF +PUSHB_2 + 1 + 1 +INSTCTRL +EIF +PUSHB_2 + 70 + 6 +CALL +IF +POP +PUSHB_1 + 16 +EIF +MPPEM +PUSHB_1 + 20 +GT +IF +POP +PUSHB_1 + 128 +EIF +SCVTCI +PUSHB_1 + 6 +CALL +NOT +IF +EIF +PUSHB_1 + 20 +CALL +EndTTInstrs +TtTable: fpgm +PUSHB_1 + 0 +FDEF +PUSHB_1 + 0 +SZP0 +MPPEM +PUSHB_1 + 42 +LT +IF +PUSHB_1 + 74 +SROUND +EIF +PUSHB_1 + 0 +SWAP +MIAP[rnd] +RTG +PUSHB_1 + 6 +CALL +IF +RTDG +EIF +MPPEM +PUSHB_1 + 42 +LT +IF +RDTG +EIF +DUP +MDRP[rp0,rnd,grey] +PUSHB_1 + 1 +SZP0 +MDAP[no-rnd] +RTG +ENDF +PUSHB_1 + 1 +FDEF +DUP +MDRP[rp0,min,white] +PUSHB_1 + 12 +CALL +ENDF +PUSHB_1 + 2 +FDEF +MPPEM +GT +IF +RCVT +SWAP +EIF +POP +ENDF +PUSHB_1 + 3 +FDEF +ROUND[Black] +RTG +DUP +PUSHB_1 + 64 +LT +IF +POP +PUSHB_1 + 64 +EIF +ENDF +PUSHB_1 + 4 +FDEF +PUSHB_1 + 6 +CALL +IF +POP +SWAP +POP +ROFF +IF +MDRP[rp0,min,rnd,black] +ELSE +MDRP[min,rnd,black] +EIF +ELSE +MPPEM +GT +IF +IF +MIRP[rp0,min,rnd,black] +ELSE +MIRP[min,rnd,black] +EIF +ELSE +SWAP +POP +PUSHB_1 + 5 +CALL +IF +PUSHB_1 + 70 +SROUND +EIF +IF +MDRP[rp0,min,rnd,black] +ELSE +MDRP[min,rnd,black] +EIF +EIF +EIF +RTG +ENDF +PUSHB_1 + 5 +FDEF +GFV +NOT +AND +ENDF +PUSHB_1 + 6 +FDEF +PUSHB_2 + 34 + 1 +GETINFO +LT +IF +PUSHB_1 + 32 +GETINFO +NOT +NOT +ELSE +PUSHB_1 + 0 +EIF +ENDF +PUSHB_1 + 7 +FDEF +PUSHB_2 + 36 + 1 +GETINFO +LT +IF +PUSHB_1 + 64 +GETINFO +NOT +NOT +ELSE +PUSHB_1 + 0 +EIF +ENDF +PUSHB_1 + 8 +FDEF +SRP2 +SRP1 +DUP +IP +MDAP[rnd] +ENDF +PUSHB_1 + 9 +FDEF +DUP +RDTG +PUSHB_1 + 6 +CALL +IF +MDRP[rnd,grey] +ELSE +MDRP[min,rnd,black] +EIF +DUP +PUSHB_1 + 3 +CINDEX +MD[grid] +SWAP +DUP +PUSHB_1 + 4 +MINDEX +MD[orig] +PUSHB_1 + 0 +LT +IF +ROLL +NEG +ROLL +SUB +DUP +PUSHB_1 + 0 +LT +IF +SHPIX +ELSE +POP +POP +EIF +ELSE +ROLL +ROLL +SUB +DUP +PUSHB_1 + 0 +GT +IF +SHPIX +ELSE +POP +POP +EIF +EIF +RTG +ENDF +PUSHB_1 + 10 +FDEF +PUSHB_1 + 6 +CALL +IF +POP +SRP0 +ELSE +SRP0 +POP +EIF +ENDF +PUSHB_1 + 11 +FDEF +DUP +MDRP[rp0,white] +PUSHB_1 + 12 +CALL +ENDF +PUSHB_1 + 12 +FDEF +DUP +MDAP[rnd] +PUSHB_1 + 7 +CALL +NOT +IF +DUP +DUP +GC[orig] +SWAP +GC[cur] +SUB +ROUND[White] +DUP +IF +DUP +ABS +DIV +SHPIX +ELSE +POP +POP +EIF +ELSE +POP +EIF +ENDF +PUSHB_1 + 13 +FDEF +SRP2 +SRP1 +DUP +DUP +IP +MDAP[rnd] +DUP +ROLL +DUP +GC[orig] +ROLL +GC[cur] +SUB +SWAP +ROLL +DUP +ROLL +SWAP +MD[orig] +PUSHB_1 + 0 +LT +IF +SWAP +PUSHB_1 + 0 +GT +IF +PUSHB_1 + 64 +SHPIX +ELSE +POP +EIF +ELSE +SWAP +PUSHB_1 + 0 +LT +IF +PUSHB_1 + 64 +NEG +SHPIX +ELSE +POP +EIF +EIF +ENDF +PUSHB_1 + 14 +FDEF +PUSHB_1 + 6 +CALL +IF +RTDG +MDRP[rp0,rnd,white] +RTG +POP +POP +ELSE +DUP +MDRP[rp0,rnd,white] +ROLL +MPPEM +GT +IF +DUP +ROLL +SWAP +MD[grid] +DUP +PUSHB_1 + 0 +NEQ +IF +SHPIX +ELSE +POP +POP +EIF +ELSE +POP +POP +EIF +EIF +ENDF +PUSHB_1 + 15 +FDEF +SWAP +DUP +MDRP[rp0,rnd,white] +DUP +MDAP[rnd] +PUSHB_1 + 7 +CALL +NOT +IF +SWAP +DUP +IF +MPPEM +GTEQ +ELSE +POP +PUSHB_1 + 1 +EIF +IF +ROLL +PUSHB_1 + 4 +MINDEX +MD[grid] +SWAP +ROLL +SWAP +DUP +ROLL +MD[grid] +ROLL +SWAP +SUB +SHPIX +ELSE +POP +POP +POP +POP +EIF +ELSE +POP +POP +POP +POP +POP +EIF +ENDF +PUSHB_1 + 16 +FDEF +DUP +MDRP[rp0,min,white] +PUSHB_1 + 18 +CALL +ENDF +PUSHB_1 + 17 +FDEF +DUP +MDRP[rp0,white] +PUSHB_1 + 18 +CALL +ENDF +PUSHB_1 + 18 +FDEF +DUP +MDAP[rnd] +PUSHB_1 + 7 +CALL +NOT +IF +DUP +DUP +GC[orig] +SWAP +GC[cur] +SUB +ROUND[White] +ROLL +DUP +GC[orig] +SWAP +GC[cur] +SWAP +SUB +ROUND[White] +ADD +DUP +IF +DUP +ABS +DIV +SHPIX +ELSE +POP +POP +EIF +ELSE +POP +POP +EIF +ENDF +PUSHB_1 + 19 +FDEF +DUP +ROLL +DUP +ROLL +SDPVTL[orthog] +DUP +PUSHB_1 + 3 +CINDEX +MD[orig] +ABS +SWAP +ROLL +SPVTL[orthog] +PUSHB_1 + 32 +LT +IF +ALIGNRP +ELSE +MDRP[grey] +EIF +ENDF +PUSHB_1 + 20 +FDEF +PUSHB_4 + 0 + 64 + 1 + 64 +WS +WS +SVTCA[x-axis] +MPPEM +PUSHW_1 + 4096 +MUL +SVTCA[y-axis] +MPPEM +PUSHW_1 + 4096 +MUL +DUP +ROLL +DUP +ROLL +NEQ +IF +DUP +ROLL +DUP +ROLL +GT +IF +SWAP +DIV +DUP +PUSHB_1 + 0 +SWAP +WS +ELSE +DIV +DUP +PUSHB_1 + 1 +SWAP +WS +EIF +DUP +PUSHB_1 + 64 +GT +IF +PUSHB_3 + 0 + 32 + 0 +RS +MUL +WS +PUSHB_3 + 1 + 32 + 1 +RS +MUL +WS +PUSHB_1 + 32 +MUL +PUSHB_1 + 25 +NEG +JMPR +POP +EIF +ELSE +POP +POP +EIF +ENDF +PUSHB_1 + 21 +FDEF +PUSHB_1 + 1 +RS +MUL +SWAP +PUSHB_1 + 0 +RS +MUL +SWAP +ENDF +EndTTInstrs +ShortTable: cvt 5 + -193 + 0 + 377 + 786 + 793 +EndShort ShortTable: maxp 16 1 0 @@ -68,11 +735,11 @@ ShortTable: maxp 16 0 0 2 - 0 - 1 1 + 2 + 22 0 - 64 + 256 0 0 0 @@ -86,7 +753,7 @@ DisplaySize: -48 AntiAlias: 1 FitToEm: 0 WinInfo: 0 29 11 -BeginChars: 65539 37 +BeginChars: 65539 41 StartChar: .notdef Encoding: 65536 -1 0 @@ -132,86 +799,86 @@ EndChar StartChar: plus Encoding: 43 43 3 -Width: 600 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -354 403 m 0,0,1 - 350 396 350 396 343 396 c 2,2,-1 - 257 396 l 2,3,4 - 250 396 250 396 246 403 c 0,5,6 - 235 421 235 421 226 437 c 0,7,8 - 221 446 221 446 221 457 c 128,-1,9 - 221 468 221 468 226 477 c 0,10,11 - 274 557 274 557 287 578 c 0,12,13 - 291 585 291 585 300 585 c 128,-1,14 - 309 585 309 585 313 578 c 0,15,16 - 320 567 320 567 343 528.5 c 128,-1,17 - 366 490 366 490 374 477 c 0,18,19 - 380 468 380 468 380 457.5 c 128,-1,20 - 380 447 380 447 374 437 c 0,21,22 - 361 415 361 415 354 403 c 0,0,1 -167 366 m 0,23,24 - 185 377 185 377 207 377 c 2,25,-1 - 427 377 l 2,26,27 - 434 377 434 377 440 372 c 0,28,29 - 455 355 455 355 487 321 c 0,30,31 - 496 311 496 311 496 298 c 0,32,33 - 496 284 496 284 486 274 c 0,34,35 - 461 248 461 248 442 230 c 0,36,37 - 435 222 435 222 423 222 c 2,38,-1 - 204 222 l 2,39,40 - 185 222 185 222 169 231 c 0,41,42 - 164 234 164 234 93 275 c 0,43,44 - 80 282 80 282 80 298 c 0,45,46 - 80 313 80 313 93 321 c 0,47,48 - 100 325 100 325 127 341.5 c 128,-1,49 - 154 358 154 358 167 366 c 0,23,24 -354 196 m 0,50,51 - 361 184 361 184 374 162 c 0,52,53 - 380 152 380 152 380 141.5 c 128,-1,54 - 380 131 380 131 374 122 c 0,55,56 - 330 48 330 48 313 21 c 0,57,58 - 309 14 309 14 300 14 c 128,-1,59 - 291 14 291 14 287 21 c 0,60,61 - 280 33 280 33 257 71 c 128,-1,62 - 234 109 234 109 226 122 c 0,63,64 - 221 131 221 131 221 142 c 128,-1,65 - 221 153 221 153 226 162 c 0,66,67 - 242 189 242 189 246 196 c 0,68,69 - 250 202 250 202 257 202 c 2,70,-1 - 343 202 l 2,71,72 - 350 202 350 202 354 196 c 0,50,51 +359 479 m 0,0,1 + 355 473 355 473 350 473 c 2,2,-1 + 281 473 l 2,3,4 + 275 473 275 473 272 479 c 0,5,6 + 267 488 267 488 256 506 c 0,7,8 + 251 514 251 514 252 522 c 0,9,10 + 253 532 253 532 256 538 c 0,11,12 + 282 591 282 591 305 619 c 0,13,14 + 309 624 309 624 316 624 c 128,-1,15 + 323 624 323 624 326 619 c 0,16,17 + 332 610 332 610 350 579 c 128,-1,18 + 368 548 368 548 375 538 c 0,19,20 + 380 531 380 531 380 522 c 0,21,22 + 380 515 380 515 375 506 c 0,23,24 + 369 496 369 496 359 479 c 0,0,1 +209 449 m 0,25,26 + 224 458 224 458 241 458 c 2,27,-1 + 417 458 l 2,28,29 + 425 458 425 458 428 454 c 0,30,31 + 440 440 440 440 465 413 c 0,32,33 + 471 406 471 406 472 395 c 128,-1,34 + 473 384 473 384 464 375 c 0,35,36 + 446 358 446 358 429 340 c 0,37,38 + 423 334 423 334 414 334 c 2,39,-1 + 239 334 l 2,40,41 + 225 334 225 334 211 341 c 0,42,43 + 195 349 195 349 150 376 c 0,44,45 + 141 381 141 381 140 395 c 0,46,47 + 139 406 139 406 150 413 c 0,48,49 + 156 416 156 416 177.5 429.5 c 128,-1,50 + 199 443 199 443 209 449 c 0,25,26 +359 313 m 0,51,52 + 364 303 364 303 375 286 c 0,53,54 + 380 278 380 278 380 269 c 128,-1,55 + 380 260 380 260 375 254 c 0,56,57 + 340 195 340 195 326 173 c 0,58,59 + 323 167 323 167 315.5 167 c 128,-1,60 + 308 167 308 167 305 173 c 0,61,62 + 299 183 299 183 281 213 c 128,-1,63 + 263 243 263 243 256 254 c 0,64,65 + 252 261 252 261 252 270 c 128,-1,66 + 252 279 252 279 256 286 c 0,67,68 + 269 308 269 308 272 313 c 128,-1,69 + 275 318 275 318 281 318 c 2,70,-1 + 350 318 l 2,71,72 + 356 318 356 318 359 313 c 0,51,52 EndSplineSet Validated: 1 EndChar StartChar: hyphen Encoding: 45 45 4 -Width: 600 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -167 363 m 0,0,1 - 185 374 185 374 207 374 c 2,2,-1 - 427 374 l 2,3,4 - 434 374 434 374 440 368 c 0,5,6 - 455 352 455 352 487 318 c 0,7,8 - 496 308 496 308 496 295 c 0,9,10 - 496 281 496 281 486 271 c 0,11,12 - 461 245 461 245 442 227 c 0,13,14 - 435 219 435 219 423 219 c 2,15,-1 - 204 219 l 2,16,17 - 185 219 185 219 169 228 c 0,18,19 - 164 231 164 231 93 272 c 0,20,21 - 80 279 80 279 80 295 c 0,22,23 - 80 310 80 310 93 318 c 0,24,25 - 100 322 100 322 127 338.5 c 128,-1,26 - 154 355 154 355 167 363 c 0,0,1 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 EndSplineSet Validated: 1 EndChar @@ -224,15 +891,15 @@ Flags: W LayerCount: 2 Fore SplineSet --70 -100 m 128,-1,1 - -70 -71 -70 -71 -49 -50 c 128,-1,2 - -28 -29 -28 -29 1 -29 c 128,-1,3 - 30 -29 30 -29 51 -50 c 128,-1,4 - 72 -71 72 -71 72 -100 c 128,-1,5 - 72 -129 72 -129 51 -150 c 128,-1,6 - 30 -171 30 -171 1 -171 c 128,-1,7 - -28 -171 -28 -171 -49 -150 c 128,-1,0 - -70 -129 -70 -129 -70 -100 c 128,-1,1 +-56 58 m 132,-1,1 + -56 81 -56 81 -39 98 c 132,-1,2 + -22 115 -22 115 1 115 c 132,-1,3 + 24 115 24 115 41 98 c 132,-1,4 + 58 81 58 81 58 58 c 132,-1,5 + 58 35 58 35 41 18 c 132,-1,6 + 24 1 24 1 1 1 c 132,-1,7 + -22 1 -22 1 -39 18 c 132,-1,0 + -56 35 -56 35 -56 58 c 132,-1,1 EndSplineSet Validated: 1 EndChar @@ -265,1018 +932,1026 @@ EndChar StartChar: zero Encoding: 48 48 7 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -695 319 m 0,0,1 - 685 308 685 308 666 307 c 0,2,3 - 665 307 665 307 659 306.5 c 128,-1,4 - 653 306 653 306 649 306 c 0,5,6 - 627 306 627 306 611 317 c 0,7,8 - 592 329 592 329 548 382 c 0,9,10 - 541 390 541 390 541 401 c 0,11,12 - 541 430 541 430 541 453 c 0,13,14 - 541 481 541 481 541 502.5 c 128,-1,15 - 541 524 541 524 541 551.5 c 128,-1,16 - 541 579 541 579 541 612 c 0,17,18 - 541 625 541 625 547 637 c 0,19,20 - 580 710 580 710 602 758 c 0,21,22 - 608 771 608 771 623 771 c 0,23,24 - 631 771 631 771 638 767 c 0,25,26 - 655 753 655 753 668 735 c 0,27,28 - 682 716 682 716 692 694 c 0,29,30 - 703 669 703 669 703 641 c 2,31,-1 - 703 346 l 2,32,33 - 703 339 703 339 702 332 c 0,34,35 - 700 324 700 324 695 319 c 0,0,1 -114 325 m 0,36,37 - 110 327 110 327 107 330 c 0,38,39 - 97 339 97 339 97 352 c 2,40,-1 - 97 645 l 2,41,42 - 97 681 97 681 115 711 c 0,43,44 - 115 712 115 712 121 723 c 0,45,46 - 127 733 127 733 139 733 c 0,47,48 - 147 733 147 733 152 727 c 0,49,50 - 158 722 158 722 196 684 c 128,-1,51 - 234 646 234 646 247 633 c 0,52,53 - 259 621 259 621 259 605 c 2,54,-1 - 259 388 l 2,55,56 - 259 377 259 377 249 372 c 0,57,58 - 238 365 238 365 204.5 346 c 128,-1,59 - 171 327 171 327 162 322 c 0,60,61 - 152 317 152 317 141 317 c 0,62,63 - 132 317 132 317 124 320 c 0,64,65 - 117 323 117 323 114 325 c 0,36,37 -153 743 m 0,66,67 - 151 751 151 751 153 754.5 c 128,-1,68 - 155 758 155 758 164 767 c 0,69,70 - 169 772 169 772 179 778 c 0,71,72 - 200 793 200 793 226 793 c 2,73,-1 - 555 793 l 1,74,-1 - 572 792 l 2,75,76 - 573 792 573 792 576 791.5 c 128,-1,77 - 579 791 579 791 581 791 c 0,78,79 - 589 790 589 790 594 785 c 0,80,81 - 600 779 600 779 598 771 c 0,82,83 - 593 761 593 761 542 647 c 0,84,85 - 536 633 536 633 521 633 c 2,86,-1 - 272 633 l 2,87,88 - 260 633 260 633 252 642 c 0,89,90 - 157 735 157 735 153 743 c 0,66,67 -695 278 m 0,91,92 - 700 273 700 273 702 265 c 0,93,94 - 703 258 703 258 703 251 c 2,95,-1 - 703 -45 l 2,96,97 - 703 -72 703 -72 692 -97 c 0,98,99 - 682 -119 682 -119 668 -138 c 0,100,101 - 655 -156 655 -156 638 -170 c 0,102,103 - 631 -175 631 -175 623 -175 c 0,104,105 - 608 -175 608 -175 602 -161 c 0,106,107 - 600 -157 600 -157 577.5 -107.5 c 128,-1,108 - 555 -58 555 -58 547 -40 c 0,109,110 - 541 -28 541 -28 541 -15 c 0,111,112 - 541 18 541 18 541 45.5 c 128,-1,113 - 541 73 541 73 541 94.5 c 128,-1,114 - 541 116 541 116 541 144 c 0,115,116 - 541 167 541 167 541 196 c 0,117,118 - 541 206 541 206 548 214 c 0,119,120 - 592 268 592 268 611 280 c 0,121,122 - 627 291 627 291 649 291 c 0,123,124 - 653 291 653 291 659 290.5 c 128,-1,125 - 665 290 665 290 666 290 c 0,126,127 - 685 289 685 289 695 278 c 0,91,92 -153 -143 m 0,128,129 - 157 -135 157 -135 252 -42 c 0,130,131 - 260 -34 260 -34 272 -34 c 2,132,-1 - 521 -34 l 2,133,134 - 536 -34 536 -34 542 -47 c 0,135,136 - 593 -161 593 -161 598 -172 c 0,137,138 - 600 -179 600 -179 594 -185 c 0,139,140 - 589 -190 589 -190 581 -191 c 0,141,142 - 580 -191 580 -191 576.5 -191.5 c 128,-1,143 - 573 -192 573 -192 572 -192 c 2,144,-1 - 555 -193 l 1,145,-1 - 226 -193 l 2,146,147 - 200 -193 200 -193 179 -178 c 0,148,149 - 169 -172 169 -172 164 -167 c 0,150,151 - 155 -158 155 -158 153 -154.5 c 128,-1,152 - 151 -151 151 -151 153 -143 c 0,128,129 -114 275 m 0,153,154 - 117 277 117 277 124 280 c 0,155,156 - 132 283 132 283 141 283 c 0,157,158 - 152 283 152 283 162 278 c 0,159,160 - 171 273 171 273 204.5 254 c 128,-1,161 - 238 235 238 235 249 228 c 0,162,163 - 259 223 259 223 259 212 c 2,164,-1 - 259 -6 l 2,165,166 - 259 -22 259 -22 247 -33 c 0,167,168 - 234 -46 234 -46 196 -84 c 128,-1,169 - 158 -122 158 -122 152 -127 c 0,170,171 - 147 -133 147 -133 139 -133 c 0,172,173 - 127 -133 127 -133 121 -123 c 256,174,175 - 115 -113 115 -113 115 -112 c 0,176,177 - 97 -81 97 -81 97 -45 c 2,178,-1 - 97 247 l 2,179,180 - 97 261 97 261 107 269 c 0,181,182 - 110 272 110 272 114 275 c 0,153,154 +554 411 m 0,0,1 + 546 402 546 402 531 402 c 0,2,3 + 530 402 530 402 525 401.5 c 128,-1,4 + 520 401 520 401 517 401 c 0,5,6 + 499 401 499 401 487 410 c 0,7,8 + 472 420 472 420 436 462 c 0,9,10 + 430 468 430 468 431 477 c 0,11,12 + 431 500 431 500 431 519 c 0,13,14 + 431 541 431 541 431 558 c 128,-1,15 + 431 575 431 575 431 597 c 128,-1,16 + 431 619 431 619 431 646 c 0,17,18 + 431 656 431 656 436 666 c 0,19,20 + 462 724 462 724 480 763 c 0,21,22 + 485 773 485 773 496 773 c 0,23,24 + 502 773 502 773 508 770 c 0,25,26 + 520 761 520 761 532 744 c 0,27,28 + 546 726 546 726 552 711 c 0,29,30 + 560 693 560 693 560 673 c 0,31,32 + 560 671 560 671 560 669 c 2,33,-1 + 560 433 l 2,34,35 + 560 427 560 427 560 422 c 0,36,37 + 558 415 558 415 554 411 c 0,0,1 +89 416 m 0,38,39 + 86 418 86 418 84 420 c 0,40,41 + 76 427 76 427 76 438 c 2,42,-1 + 76 672 l 2,43,44 + 76 701 76 701 90 725 c 0,45,46 + 90 726 90 726 95 735 c 0,47,48 + 100 743 100 743 109 743 c 0,49,50 + 115 743 115 743 120 738 c 0,51,52 + 125 734 125 734 155 703.5 c 128,-1,53 + 185 673 185 673 196 663 c 0,54,55 + 206 653 206 653 205 640 c 2,56,-1 + 205 467 l 2,57,58 + 205 458 205 458 197 454 c 0,59,60 + 188 448 188 448 161.5 433 c 128,-1,61 + 135 418 135 418 128 414 c 0,62,63 + 120 410 120 410 111 410 c 0,64,65 + 104 410 104 410 97 412 c 0,66,67 + 91 414 91 414 89 416 c 0,38,39 +120 751 m 0,68,69 + 118 757 118 757 120 760 c 128,-1,70 + 122 763 122 763 129 770 c 0,71,72 + 133 774 133 774 141 779 c 0,73,74 + 158 791 158 791 179 791 c 2,75,-1 + 442 791 l 1,76,-1 + 456 790 l 2,77,78 + 457 790 457 790 459 789.5 c 128,-1,79 + 461 789 461 789 463 789 c 0,80,81 + 469 788 469 788 473 784 c 0,82,83 + 478 779 478 779 476 773 c 0,84,85 + 472 765 472 765 432 674 c 0,86,87 + 427 663 427 663 415 663 c 2,88,-1 + 216 663 l 2,89,90 + 206 663 206 663 200 670 c 0,91,92 + 123 745 123 745 120 751 c 0,68,69 +554 379 m 0,93,94 + 558 375 558 375 560 368 c 0,95,96 + 561 362 561 362 560 357 c 2,97,-1 + 560 120 l 2,98,99 + 560 98 560 98 552 79 c 0,100,101 + 544 61 544 61 532 46 c 0,102,103 + 522 32 522 32 508 20 c 0,104,105 + 502 16 502 16 496 16 c 0,106,107 + 484 16 484 16 480 27 c 0,108,109 + 478 30 478 30 460 70 c 128,-1,110 + 442 110 442 110 436 124 c 0,111,112 + 431 134 431 134 431 144 c 0,113,114 + 431 170 431 170 431 192.5 c 128,-1,115 + 431 215 431 215 431 232 c 128,-1,116 + 431 249 431 249 431 271 c 0,117,118 + 431 289 431 289 431 313 c 0,119,120 + 431 321 431 321 436 327 c 0,121,122 + 471 370 471 370 487 380 c 0,123,124 + 500 389 500 389 517 389 c 0,125,126 + 520 389 520 389 525 388.5 c 128,-1,127 + 530 388 530 388 531 388 c 0,128,129 + 546 388 546 388 554 379 c 0,93,94 +120 42 m 0,130,131 + 123 48 123 48 200 123 c 0,132,133 + 206 129 206 129 216 129 c 2,134,-1 + 415 129 l 2,135,136 + 427 129 427 129 432 119 c 0,137,138 + 473 28 473 28 476 19 c 0,139,140 + 478 13 478 13 473 8 c 0,141,142 + 469 4 469 4 463 3 c 0,143,144 + 462 3 462 3 459 3 c 128,-1,145 + 456 3 456 3 456 3 c 2,146,-1 + 442 2 l 1,147,-1 + 179 2 l 2,148,149 + 158 2 158 2 141 14 c 0,150,151 + 133 19 133 19 129 23 c 0,152,153 + 122 30 122 30 120 33 c 128,-1,154 + 118 36 118 36 120 42 c 0,130,131 +89 376 m 0,155,156 + 91 378 91 378 97 380 c 128,-1,157 + 103 382 103 382 111 383 c 0,158,159 + 120 383 120 383 128 379 c 0,160,161 + 135 375 135 375 161.5 359.5 c 128,-1,162 + 188 344 188 344 197 339 c 0,163,164 + 205 335 205 335 205 326 c 2,165,-1 + 205 151 l 2,166,167 + 205 138 205 138 196 130 c 0,168,169 + 186 120 186 120 155 89.5 c 128,-1,170 + 124 59 124 59 120 55 c 0,171,172 + 116 50 116 50 109 50 c 0,173,174 + 99 50 99 50 95 58 c 256,175,176 + 90 66 90 66 90 67 c 0,177,178 + 76 92 76 92 76 120 c 2,179,-1 + 76 354 l 2,180,181 + 76 365 76 365 84 371 c 0,182,183 + 86 374 86 374 89 376 c 0,155,156 EndSplineSet Validated: 1 EndChar StartChar: one Encoding: 49 49 8 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -695 319 m 0,0,1 - 685 308 685 308 666 307 c 2,2,3 - 666 307 666 307 660 306.5 c 128,-1,4 - 654 306 654 306 650 306 c 0,5,6 - 627 306 627 306 611 317 c 0,7,8 - 593 329 593 329 548 382 c 0,9,10 - 542 390 542 390 542 401 c 0,11,12 - 542 430 542 430 542 453 c 0,13,14 - 542 481 542 481 542 502.5 c 128,-1,15 - 542 524 542 524 542 551.5 c 128,-1,16 - 542 579 542 579 542 612 c 0,17,18 - 542 625 542 625 547 637 c 0,19,20 - 580 710 580 710 602 758 c 0,21,22 - 609 771 609 771 624 771 c 0,23,24 - 632 771 632 771 638 767 c 0,25,26 - 656 753 656 753 669 735 c 0,27,28 - 683 716 683 716 693 694 c 0,29,30 - 704 669 704 669 704 641 c 2,31,-1 - 704 346 l 2,32,33 - 704 339 704 339 702 332 c 0,34,35 - 700 324 700 324 695 319 c 0,0,1 -695 278 m 0,36,37 - 700 273 700 273 702 265 c 0,38,39 - 704 258 704 258 704 251 c 2,40,-1 - 704 -45 l 2,41,42 - 704 -72 704 -72 693 -97 c 0,43,44 - 683 -119 683 -119 669 -138 c 0,45,46 - 656 -156 656 -156 638 -170 c 0,47,48 - 632 -175 632 -175 624 -175 c 0,49,50 - 609 -175 609 -175 602 -161 c 0,51,52 - 601 -157 601 -157 578 -107.5 c 128,-1,53 - 555 -58 555 -58 547 -40 c 0,54,55 - 542 -28 542 -28 542 -15 c 0,56,57 - 542 18 542 18 542 45.5 c 128,-1,58 - 542 73 542 73 542 94.5 c 128,-1,59 - 542 116 542 116 542 144 c 0,60,61 - 542 167 542 167 542 196 c 0,62,63 - 542 206 542 206 548 214 c 0,64,65 - 593 268 593 268 611 280 c 0,66,67 - 627 291 627 291 650 291 c 0,68,69 - 654 291 654 291 660 290.5 c 128,-1,70 - 666 290 666 290 666 290 c 2,71,72 - 685 289 685 289 695 278 c 0,36,37 +554 411 m 0,0,1 + 546 402 546 402 531 402 c 0,2,3 + 530 402 530 402 525 401.5 c 128,-1,4 + 520 401 520 401 517 401 c 0,5,6 + 499 401 499 401 487 410 c 0,7,8 + 472 420 472 420 436 462 c 0,9,10 + 430 468 430 468 431 477 c 0,11,12 + 431 500 431 500 431 519 c 0,13,14 + 431 541 431 541 431 558 c 128,-1,15 + 431 575 431 575 431 597 c 128,-1,16 + 431 619 431 619 431 646 c 0,17,18 + 431 656 431 656 436 666 c 0,19,20 + 462 724 462 724 480 763 c 0,21,22 + 485 773 485 773 496 773 c 0,23,24 + 502 773 502 773 508 770 c 0,25,26 + 520 761 520 761 532 744 c 0,27,28 + 546 726 546 726 552 711 c 0,29,30 + 560 693 560 693 560 673 c 0,31,32 + 560 671 560 671 560 669 c 2,33,-1 + 560 433 l 2,34,35 + 560 427 560 427 560 422 c 0,36,37 + 558 415 558 415 554 411 c 0,0,1 +554 379 m 0,38,39 + 558 375 558 375 560 368 c 0,40,41 + 561 362 561 362 560 357 c 2,42,-1 + 560 120 l 2,43,44 + 560 98 560 98 552 79 c 0,45,46 + 544 61 544 61 532 46 c 0,47,48 + 522 32 522 32 508 20 c 0,49,50 + 502 16 502 16 496 16 c 0,51,52 + 484 16 484 16 480 27 c 0,53,54 + 478 30 478 30 460 70 c 128,-1,55 + 442 110 442 110 436 124 c 0,56,57 + 431 134 431 134 431 144 c 0,58,59 + 431 170 431 170 431 192.5 c 128,-1,60 + 431 215 431 215 431 232 c 128,-1,61 + 431 249 431 249 431 271 c 0,62,63 + 431 289 431 289 431 313 c 0,64,65 + 431 321 431 321 436 327 c 0,66,67 + 471 370 471 370 487 380 c 0,68,69 + 500 389 500 389 517 389 c 0,70,71 + 520 389 520 389 525 388.5 c 128,-1,72 + 530 388 530 388 531 388 c 0,73,74 + 546 388 546 388 554 379 c 0,38,39 EndSplineSet Validated: 1 EndChar StartChar: two Encoding: 50 50 9 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -695 319 m 0,0,1 - 685 308 685 308 666 307 c 0,2,3 - 665 307 665 307 659 306.5 c 128,-1,4 - 653 306 653 306 649 306 c 0,5,6 - 627 306 627 306 611 317 c 0,7,8 - 592 329 592 329 548 382 c 0,9,10 - 541 390 541 390 541 401 c 0,11,12 - 541 430 541 430 541 453 c 0,13,14 - 541 481 541 481 541 502.5 c 128,-1,15 - 541 524 541 524 541 551.5 c 128,-1,16 - 541 579 541 579 541 612 c 0,17,18 - 541 625 541 625 547 637 c 0,19,20 - 580 710 580 710 602 758 c 0,21,22 - 608 771 608 771 623 771 c 0,23,24 - 631 771 631 771 638 767 c 0,25,26 - 655 753 655 753 668 735 c 0,27,28 - 682 716 682 716 692 694 c 0,29,30 - 703 669 703 669 703 641 c 2,31,-1 - 703 346 l 2,32,33 - 703 339 703 339 702 332 c 0,34,35 - 700 324 700 324 695 319 c 0,0,1 -267 366 m 0,36,37 - 285 377 285 377 307 377 c 2,38,-1 - 527 377 l 2,39,40 - 534 377 534 377 540 372 c 0,41,42 - 555 355 555 355 587 321 c 0,43,44 - 596 311 596 311 596 298 c 0,45,46 - 596 284 596 284 586 274 c 0,47,48 - 561 248 561 248 542 230 c 0,49,50 - 535 222 535 222 523 222 c 2,51,-1 - 304 222 l 2,52,53 - 285 222 285 222 269 231 c 0,54,55 - 264 234 264 234 193 275 c 0,56,57 - 180 282 180 282 180 298 c 0,58,59 - 180 313 180 313 193 321 c 0,60,61 - 200 325 200 325 227 341.5 c 128,-1,62 - 254 358 254 358 267 366 c 0,36,37 -153 743 m 0,63,64 - 151 751 151 751 153 754.5 c 128,-1,65 - 155 758 155 758 164 767 c 0,66,67 - 169 772 169 772 179 778 c 0,68,69 - 200 793 200 793 226 793 c 2,70,-1 - 555 793 l 1,71,-1 - 572 792 l 2,72,73 - 573 792 573 792 576 791.5 c 128,-1,74 - 579 791 579 791 581 791 c 0,75,76 - 589 790 589 790 594 785 c 0,77,78 - 601 779 601 779 598 771 c 0,79,80 - 593 761 593 761 542 647 c 0,81,82 - 536 633 536 633 521 633 c 2,83,-1 - 272 633 l 2,84,85 - 260 633 260 633 252 642 c 0,86,87 - 157 735 157 735 153 743 c 0,63,64 -153 -143 m 0,88,89 - 157 -135 157 -135 252 -42 c 0,90,91 - 260 -34 260 -34 272 -34 c 2,92,-1 - 521 -34 l 2,93,94 - 536 -34 536 -34 542 -47 c 0,95,96 - 593 -161 593 -161 598 -172 c 0,97,98 - 601 -179 601 -179 594 -185 c 0,99,100 - 589 -190 589 -190 581 -191 c 0,101,102 - 580 -191 580 -191 576.5 -191.5 c 128,-1,103 - 573 -192 573 -192 572 -192 c 2,104,-1 - 555 -193 l 1,105,-1 - 226 -193 l 2,106,107 - 200 -193 200 -193 179 -178 c 0,108,109 - 169 -172 169 -172 164 -167 c 0,110,111 - 155 -158 155 -158 153 -154.5 c 128,-1,112 - 151 -151 151 -151 153 -143 c 0,88,89 -114 275 m 0,113,114 - 117 277 117 277 124 280 c 0,115,116 - 132 283 132 283 141 283 c 0,117,118 - 152 283 152 283 162 278 c 0,119,120 - 171 273 171 273 204.5 254 c 128,-1,121 - 238 235 238 235 249 228 c 0,122,123 - 259 223 259 223 259 212 c 2,124,-1 - 259 -6 l 2,125,126 - 259 -22 259 -22 247 -33 c 0,127,128 - 234 -46 234 -46 196 -84 c 128,-1,129 - 158 -122 158 -122 152 -127 c 0,130,131 - 147 -133 147 -133 139 -133 c 0,132,133 - 127 -133 127 -133 121 -123 c 256,134,135 - 115 -113 115 -113 115 -112 c 0,136,137 - 97 -81 97 -81 97 -45 c 2,138,-1 - 97 247 l 2,139,140 - 97 261 97 261 107 269 c 0,141,142 - 110 272 110 272 114 275 c 0,113,114 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +554 411 m 0,26,27 + 546 402 546 402 531 402 c 0,28,29 + 530 402 530 402 525 401.5 c 128,-1,30 + 520 401 520 401 517 401 c 0,31,32 + 499 401 499 401 487 410 c 0,33,34 + 472 420 472 420 436 462 c 0,35,36 + 430 468 430 468 431 477 c 0,37,38 + 431 500 431 500 431 519 c 0,39,40 + 431 541 431 541 431 558 c 128,-1,41 + 431 575 431 575 431 597 c 128,-1,42 + 431 619 431 619 431 646 c 0,43,44 + 431 656 431 656 436 666 c 0,45,46 + 462 724 462 724 480 763 c 0,47,48 + 485 773 485 773 496 773 c 0,49,50 + 502 773 502 773 508 770 c 0,51,52 + 520 761 520 761 532 744 c 0,53,54 + 546 726 546 726 552 711 c 0,55,56 + 560 693 560 693 560 673 c 0,57,58 + 560 671 560 671 560 669 c 2,59,-1 + 560 433 l 2,60,61 + 560 427 560 427 560 422 c 0,62,63 + 558 415 558 415 554 411 c 0,26,27 +120 751 m 0,64,65 + 118 757 118 757 120 760 c 128,-1,66 + 122 763 122 763 129 770 c 0,67,68 + 133 774 133 774 141 779 c 0,69,70 + 158 791 158 791 179 791 c 2,71,-1 + 442 791 l 1,72,-1 + 456 790 l 2,73,74 + 457 790 457 790 459 789.5 c 128,-1,75 + 461 789 461 789 463 789 c 0,76,77 + 469 788 469 788 473 784 c 0,78,79 + 478 779 478 779 476 773 c 0,80,81 + 472 765 472 765 432 674 c 0,82,83 + 427 663 427 663 415 663 c 2,84,-1 + 216 663 l 2,85,86 + 206 663 206 663 200 670 c 0,87,88 + 123 745 123 745 120 751 c 0,64,65 +120 42 m 0,89,90 + 123 48 123 48 200 123 c 0,91,92 + 206 129 206 129 216 129 c 2,93,-1 + 415 129 l 2,94,95 + 427 129 427 129 432 119 c 0,96,97 + 473 28 473 28 476 19 c 0,98,99 + 478 13 478 13 473 8 c 0,100,101 + 469 4 469 4 463 3 c 0,102,103 + 462 3 462 3 459 3 c 128,-1,104 + 456 3 456 3 456 3 c 2,105,-1 + 442 2 l 1,106,-1 + 179 2 l 2,107,108 + 158 2 158 2 141 14 c 0,109,110 + 133 19 133 19 129 23 c 0,111,112 + 122 30 122 30 120 33 c 128,-1,113 + 118 36 118 36 120 42 c 0,89,90 +89 376 m 0,114,115 + 91 378 91 378 97 380 c 128,-1,116 + 103 382 103 382 111 383 c 0,117,118 + 120 383 120 383 128 379 c 0,119,120 + 135 375 135 375 161.5 359.5 c 128,-1,121 + 188 344 188 344 197 339 c 0,122,123 + 205 335 205 335 205 326 c 2,124,-1 + 205 151 l 2,125,126 + 205 138 205 138 196 130 c 0,127,128 + 186 120 186 120 155 89.5 c 128,-1,129 + 124 59 124 59 120 55 c 0,130,131 + 116 50 116 50 109 50 c 0,132,133 + 99 50 99 50 95 58 c 256,134,135 + 90 66 90 66 90 67 c 0,136,137 + 76 92 76 92 76 120 c 2,138,-1 + 76 354 l 2,139,140 + 76 365 76 365 84 371 c 0,141,142 + 86 374 86 374 89 376 c 0,114,115 EndSplineSet Validated: 1 EndChar StartChar: three Encoding: 51 51 10 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -695 319 m 0,0,1 - 685 308 685 308 666 307 c 0,2,3 - 665 307 665 307 659 306.5 c 128,-1,4 - 653 306 653 306 649 306 c 0,5,6 - 627 306 627 306 611 317 c 0,7,8 - 592 329 592 329 548 382 c 0,9,10 - 541 390 541 390 541 401 c 0,11,12 - 541 430 541 430 541 453 c 0,13,14 - 541 481 541 481 541 502.5 c 128,-1,15 - 541 524 541 524 541 551.5 c 128,-1,16 - 541 579 541 579 541 612 c 0,17,18 - 541 625 541 625 547 637 c 0,19,20 - 580 710 580 710 602 758 c 0,21,22 - 608 771 608 771 623 771 c 0,23,24 - 631 771 631 771 638 767 c 0,25,26 - 655 753 655 753 668 735 c 0,27,28 - 682 716 682 716 692 694 c 0,29,30 - 703 669 703 669 703 641 c 2,31,-1 - 703 346 l 2,32,33 - 703 339 703 339 702 332 c 0,34,35 - 700 324 700 324 695 319 c 0,0,1 -267 366 m 0,36,37 - 285 377 285 377 307 377 c 2,38,-1 - 527 377 l 2,39,40 - 535 377 535 377 540 372 c 0,41,42 - 555 355 555 355 587 321 c 0,43,44 - 596 311 596 311 596 298 c 0,45,46 - 596 284 596 284 586 274 c 0,47,48 - 561 248 561 248 542 230 c 0,49,50 - 535 222 535 222 523 222 c 2,51,-1 - 304 222 l 2,52,53 - 285 222 285 222 269 231 c 0,54,55 - 264 234 264 234 193 275 c 0,56,57 - 180 282 180 282 180 298 c 0,58,59 - 180 313 180 313 193 321 c 0,60,61 - 200 325 200 325 227 341.5 c 128,-1,62 - 254 358 254 358 267 366 c 0,36,37 -153 743 m 0,63,64 - 151 751 151 751 153 754.5 c 128,-1,65 - 155 758 155 758 164 767 c 0,66,67 - 169 772 169 772 179 778 c 0,68,69 - 200 793 200 793 226 793 c 2,70,-1 - 555 793 l 1,71,-1 - 572 792 l 2,72,73 - 573 792 573 792 576 791.5 c 128,-1,74 - 579 791 579 791 581 791 c 0,75,76 - 589 790 589 790 594 785 c 0,77,78 - 601 779 601 779 598 771 c 0,79,80 - 593 761 593 761 542 647 c 0,81,82 - 536 633 536 633 521 633 c 2,83,-1 - 272 633 l 2,84,85 - 260 633 260 633 252 642 c 0,86,87 - 157 735 157 735 153 743 c 0,63,64 -695 278 m 0,88,89 - 700 273 700 273 702 265 c 0,90,91 - 703 258 703 258 703 251 c 2,92,-1 - 703 -45 l 2,93,94 - 703 -72 703 -72 692 -97 c 0,95,96 - 682 -119 682 -119 668 -138 c 0,97,98 - 655 -156 655 -156 638 -170 c 0,99,100 - 631 -175 631 -175 623 -175 c 0,101,102 - 608 -175 608 -175 602 -161 c 0,103,104 - 600 -157 600 -157 577.5 -107.5 c 128,-1,105 - 555 -58 555 -58 547 -40 c 0,106,107 - 541 -28 541 -28 541 -15 c 0,108,109 - 541 18 541 18 541 45.5 c 128,-1,110 - 541 73 541 73 541 94.5 c 128,-1,111 - 541 116 541 116 541 144 c 0,112,113 - 541 167 541 167 541 196 c 0,114,115 - 541 206 541 206 548 214 c 0,116,117 - 592 268 592 268 611 280 c 0,118,119 - 627 291 627 291 649 291 c 0,120,121 - 653 291 653 291 659 290.5 c 128,-1,122 - 665 290 665 290 666 290 c 0,123,124 - 685 289 685 289 695 278 c 0,88,89 -153 -143 m 0,125,126 - 157 -135 157 -135 252 -42 c 0,127,128 - 260 -34 260 -34 272 -34 c 2,129,-1 - 521 -34 l 2,130,131 - 536 -34 536 -34 542 -47 c 0,132,133 - 593 -161 593 -161 598 -172 c 0,134,135 - 601 -179 601 -179 594 -185 c 0,136,137 - 589 -190 589 -190 581 -191 c 0,138,139 - 580 -191 580 -191 576.5 -191.5 c 128,-1,140 - 573 -192 573 -192 572 -192 c 2,141,-1 - 555 -193 l 1,142,-1 - 226 -193 l 2,143,144 - 200 -193 200 -193 179 -178 c 0,145,146 - 169 -172 169 -172 164 -167 c 0,147,148 - 155 -158 155 -158 153 -154.5 c 128,-1,149 - 151 -151 151 -151 153 -143 c 0,125,126 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +554 411 m 0,26,27 + 546 402 546 402 531 402 c 0,28,29 + 530 402 530 402 525 401.5 c 128,-1,30 + 520 401 520 401 517 401 c 0,31,32 + 499 401 499 401 487 410 c 0,33,34 + 472 420 472 420 436 462 c 0,35,36 + 430 468 430 468 431 477 c 0,37,38 + 431 500 431 500 431 519 c 0,39,40 + 431 541 431 541 431 558 c 128,-1,41 + 431 575 431 575 431 597 c 128,-1,42 + 431 619 431 619 431 646 c 0,43,44 + 431 656 431 656 436 666 c 0,45,46 + 462 724 462 724 480 763 c 0,47,48 + 485 773 485 773 496 773 c 0,49,50 + 502 773 502 773 508 770 c 0,51,52 + 520 761 520 761 532 744 c 0,53,54 + 546 726 546 726 552 711 c 0,55,56 + 560 693 560 693 560 673 c 0,57,58 + 560 671 560 671 560 669 c 2,59,-1 + 560 433 l 2,60,61 + 560 427 560 427 560 422 c 0,62,63 + 558 415 558 415 554 411 c 0,26,27 +120 751 m 0,64,65 + 118 757 118 757 120 760 c 128,-1,66 + 122 763 122 763 129 770 c 0,67,68 + 133 774 133 774 141 779 c 0,69,70 + 158 791 158 791 179 791 c 2,71,-1 + 442 791 l 1,72,-1 + 456 790 l 2,73,74 + 457 790 457 790 459 789.5 c 128,-1,75 + 461 789 461 789 463 789 c 0,76,77 + 469 788 469 788 473 784 c 0,78,79 + 478 779 478 779 476 773 c 0,80,81 + 472 765 472 765 432 674 c 0,82,83 + 427 663 427 663 415 663 c 2,84,-1 + 216 663 l 2,85,86 + 206 663 206 663 200 670 c 0,87,88 + 123 745 123 745 120 751 c 0,64,65 +554 379 m 0,89,90 + 558 375 558 375 560 368 c 0,91,92 + 561 362 561 362 560 357 c 2,93,-1 + 560 120 l 2,94,95 + 560 98 560 98 552 79 c 0,96,97 + 544 61 544 61 532 46 c 0,98,99 + 522 32 522 32 508 20 c 0,100,101 + 502 16 502 16 496 16 c 0,102,103 + 484 16 484 16 480 27 c 0,104,105 + 478 30 478 30 460 70 c 128,-1,106 + 442 110 442 110 436 124 c 0,107,108 + 431 134 431 134 431 144 c 0,109,110 + 431 170 431 170 431 192.5 c 128,-1,111 + 431 215 431 215 431 232 c 128,-1,112 + 431 249 431 249 431 271 c 0,113,114 + 431 289 431 289 431 313 c 0,115,116 + 431 321 431 321 436 327 c 0,117,118 + 471 370 471 370 487 380 c 0,119,120 + 500 389 500 389 517 389 c 0,121,122 + 520 389 520 389 525 388.5 c 128,-1,123 + 530 388 530 388 531 388 c 0,124,125 + 546 388 546 388 554 379 c 0,89,90 +120 42 m 0,126,127 + 123 48 123 48 200 123 c 0,128,129 + 206 129 206 129 216 129 c 2,130,-1 + 415 129 l 2,131,132 + 427 129 427 129 432 119 c 0,133,134 + 473 28 473 28 476 19 c 0,135,136 + 478 13 478 13 473 8 c 0,137,138 + 469 4 469 4 463 3 c 0,139,140 + 462 3 462 3 459 3 c 128,-1,141 + 456 3 456 3 456 3 c 2,142,-1 + 442 2 l 1,143,-1 + 179 2 l 2,144,145 + 158 2 158 2 141 14 c 0,146,147 + 133 19 133 19 129 23 c 0,148,149 + 122 30 122 30 120 33 c 128,-1,150 + 118 36 118 36 120 42 c 0,126,127 EndSplineSet Validated: 1 EndChar StartChar: four Encoding: 52 52 11 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -695 319 m 0,0,1 - 685 308 685 308 666 307 c 0,2,3 - 665 307 665 307 659 306.5 c 128,-1,4 - 653 306 653 306 649 306 c 0,5,6 - 627 306 627 306 611 317 c 0,7,8 - 592 329 592 329 548 382 c 0,9,10 - 541 390 541 390 541 401 c 0,11,12 - 541 430 541 430 541 453 c 0,13,14 - 541 481 541 481 541 502.5 c 128,-1,15 - 541 524 541 524 541 551.5 c 128,-1,16 - 541 579 541 579 541 612 c 0,17,18 - 541 625 541 625 547 637 c 0,19,20 - 580 710 580 710 602 758 c 0,21,22 - 608 771 608 771 623 771 c 0,23,24 - 631 771 631 771 638 767 c 0,25,26 - 655 753 655 753 668 735 c 0,27,28 - 682 716 682 716 692 694 c 0,29,30 - 703 669 703 669 703 641 c 2,31,-1 - 703 346 l 2,32,33 - 703 339 703 339 702 332 c 0,34,35 - 700 324 700 324 695 319 c 0,0,1 -267 366 m 0,36,37 - 285 377 285 377 307 377 c 2,38,-1 - 527 377 l 2,39,40 - 534 377 534 377 540 372 c 0,41,42 - 555 355 555 355 587 321 c 0,43,44 - 596 311 596 311 596 298 c 0,45,46 - 596 284 596 284 586 274 c 0,47,48 - 561 248 561 248 542 230 c 0,49,50 - 535 222 535 222 523 222 c 2,51,-1 - 304 222 l 2,52,53 - 285 222 285 222 269 231 c 0,54,55 - 264 234 264 234 193 275 c 0,56,57 - 180 282 180 282 180 298 c 0,58,59 - 180 313 180 313 193 321 c 0,60,61 - 200 325 200 325 227 341.5 c 128,-1,62 - 254 358 254 358 267 366 c 0,36,37 -114 325 m 256,63,64 - 111 327 111 327 107 330 c 0,65,66 - 97 339 97 339 97 352 c 2,67,-1 - 97 645 l 2,68,69 - 97 681 97 681 115 711 c 0,70,71 - 115 712 115 712 121 723 c 0,72,73 - 127 733 127 733 139 733 c 0,74,75 - 147 733 147 733 152 727 c 0,76,77 - 158 722 158 722 196 684 c 128,-1,78 - 234 646 234 646 247 633 c 0,79,80 - 259 621 259 621 259 605 c 2,81,-1 - 259 388 l 2,82,83 - 259 377 259 377 249 372 c 0,84,85 - 238 365 238 365 204.5 346 c 128,-1,86 - 171 327 171 327 162 322 c 0,87,88 - 152 317 152 317 141 317 c 0,89,90 - 132 317 132 317 124 320 c 0,91,92 - 117 323 117 323 114 325 c 256,63,64 -695 278 m 0,93,94 - 700 273 700 273 702 265 c 0,95,96 - 703 258 703 258 703 251 c 2,97,-1 - 703 -45 l 2,98,99 - 703 -72 703 -72 692 -97 c 0,100,101 - 682 -119 682 -119 668 -138 c 0,102,103 - 655 -156 655 -156 638 -170 c 0,104,105 - 631 -175 631 -175 623 -175 c 0,106,107 - 608 -175 608 -175 602 -161 c 0,108,109 - 600 -157 600 -157 577.5 -107.5 c 128,-1,110 - 555 -58 555 -58 547 -40 c 0,111,112 - 541 -28 541 -28 541 -15 c 0,113,114 - 541 18 541 18 541 45.5 c 128,-1,115 - 541 73 541 73 541 94.5 c 128,-1,116 - 541 116 541 116 541 144 c 0,117,118 - 541 167 541 167 541 196 c 0,119,120 - 541 206 541 206 548 214 c 0,121,122 - 592 268 592 268 611 280 c 0,123,124 - 627 291 627 291 649 291 c 0,125,126 - 653 291 653 291 659 290.5 c 128,-1,127 - 665 290 665 290 666 290 c 0,128,129 - 685 289 685 289 695 278 c 0,93,94 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +554 411 m 0,26,27 + 546 402 546 402 531 402 c 0,28,29 + 530 402 530 402 525 401.5 c 128,-1,30 + 520 401 520 401 517 401 c 0,31,32 + 499 401 499 401 487 410 c 0,33,34 + 472 420 472 420 436 462 c 0,35,36 + 430 468 430 468 431 477 c 0,37,38 + 431 500 431 500 431 519 c 0,39,40 + 431 541 431 541 431 558 c 128,-1,41 + 431 575 431 575 431 597 c 128,-1,42 + 431 619 431 619 431 646 c 0,43,44 + 431 656 431 656 436 666 c 0,45,46 + 462 724 462 724 480 763 c 0,47,48 + 485 773 485 773 496 773 c 0,49,50 + 502 773 502 773 508 770 c 0,51,52 + 520 761 520 761 532 744 c 0,53,54 + 546 726 546 726 552 711 c 0,55,56 + 560 693 560 693 560 673 c 0,57,58 + 560 671 560 671 560 669 c 2,59,-1 + 560 433 l 2,60,61 + 560 427 560 427 560 422 c 0,62,63 + 558 415 558 415 554 411 c 0,26,27 +89 416 m 0,64,65 + 86 418 86 418 84 420 c 0,66,67 + 76 427 76 427 76 438 c 2,68,-1 + 76 672 l 2,69,70 + 76 701 76 701 90 725 c 0,71,72 + 90 726 90 726 95 735 c 0,73,74 + 100 743 100 743 109 743 c 0,75,76 + 115 743 115 743 120 738 c 0,77,78 + 125 734 125 734 155 703.5 c 128,-1,79 + 185 673 185 673 196 663 c 0,80,81 + 206 653 206 653 205 640 c 2,82,-1 + 205 467 l 2,83,84 + 205 458 205 458 197 454 c 0,85,86 + 188 448 188 448 161.5 433 c 128,-1,87 + 135 418 135 418 128 414 c 0,88,89 + 120 410 120 410 111 410 c 0,90,91 + 104 410 104 410 97 412 c 0,92,93 + 91 414 91 414 89 416 c 0,64,65 +554 379 m 0,94,95 + 558 375 558 375 560 368 c 0,96,97 + 561 362 561 362 560 357 c 2,98,-1 + 560 120 l 2,99,100 + 560 98 560 98 552 79 c 0,101,102 + 544 61 544 61 532 46 c 0,103,104 + 522 32 522 32 508 20 c 0,105,106 + 502 16 502 16 496 16 c 0,107,108 + 484 16 484 16 480 27 c 0,109,110 + 478 30 478 30 460 70 c 128,-1,111 + 442 110 442 110 436 124 c 0,112,113 + 431 134 431 134 431 144 c 0,114,115 + 431 170 431 170 431 192.5 c 128,-1,116 + 431 215 431 215 431 232 c 128,-1,117 + 431 249 431 249 431 271 c 0,118,119 + 431 289 431 289 431 313 c 0,120,121 + 431 321 431 321 436 327 c 0,122,123 + 471 370 471 370 487 380 c 0,124,125 + 500 389 500 389 517 389 c 0,126,127 + 520 389 520 389 525 388.5 c 128,-1,128 + 530 388 530 388 531 388 c 0,129,130 + 546 388 546 388 554 379 c 0,94,95 EndSplineSet Validated: 1 EndChar StartChar: five Encoding: 53 53 12 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -267 366 m 0,0,1 - 285 377 285 377 307 377 c 2,2,-1 - 527 377 l 2,3,4 - 535 377 535 377 540 372 c 0,5,6 - 555 355 555 355 587 321 c 0,7,8 - 596 311 596 311 596 298 c 0,9,10 - 596 284 596 284 586 274 c 0,11,12 - 561 248 561 248 542 230 c 0,13,14 - 535 222 535 222 523 222 c 2,15,-1 - 304 222 l 2,16,17 - 285 222 285 222 269 231 c 0,18,19 - 264 234 264 234 193 275 c 0,20,21 - 180 282 180 282 180 298 c 0,22,23 - 180 313 180 313 193 321 c 0,24,25 - 200 325 200 325 227 341.5 c 128,-1,26 - 254 358 254 358 267 366 c 0,0,1 -114 325 m 256,27,28 - 111 327 111 327 107 330 c 0,29,30 - 97 339 97 339 97 352 c 2,31,-1 - 97 645 l 2,32,33 - 97 681 97 681 115 711 c 0,34,35 - 115 712 115 712 121 723 c 0,36,37 - 127 733 127 733 139 733 c 0,38,39 - 147 733 147 733 152 727 c 0,40,41 - 158 722 158 722 196 684 c 128,-1,42 - 234 646 234 646 247 633 c 0,43,44 - 259 621 259 621 259 605 c 2,45,-1 - 259 388 l 2,46,47 - 259 377 259 377 249 372 c 0,48,49 - 238 365 238 365 204.5 346 c 128,-1,50 - 171 327 171 327 162 322 c 0,51,52 - 152 317 152 317 141 317 c 0,53,54 - 132 317 132 317 124 320 c 0,55,56 - 117 323 117 323 114 325 c 256,27,28 -153 743 m 0,57,58 - 151 751 151 751 153 754.5 c 128,-1,59 - 155 758 155 758 164 767 c 0,60,61 - 169 772 169 772 179 778 c 0,62,63 - 200 793 200 793 226 793 c 2,64,-1 - 555 793 l 1,65,-1 - 572 792 l 2,66,67 - 573 792 573 792 576 791.5 c 128,-1,68 - 579 791 579 791 581 791 c 0,69,70 - 589 790 589 790 594 785 c 0,71,72 - 601 779 601 779 598 771 c 0,73,74 - 593 761 593 761 542 647 c 0,75,76 - 536 633 536 633 521 633 c 2,77,-1 - 272 633 l 2,78,79 - 260 633 260 633 252 642 c 0,80,81 - 157 735 157 735 153 743 c 0,57,58 -695 278 m 0,82,83 - 700 273 700 273 702 265 c 0,84,85 - 703 258 703 258 703 251 c 2,86,-1 - 703 -45 l 2,87,88 - 703 -72 703 -72 692 -97 c 0,89,90 - 682 -119 682 -119 668 -138 c 0,91,92 - 655 -156 655 -156 638 -170 c 0,93,94 - 631 -175 631 -175 623 -175 c 0,95,96 - 608 -175 608 -175 602 -161 c 0,97,98 - 600 -157 600 -157 577.5 -107.5 c 128,-1,99 - 555 -58 555 -58 547 -40 c 0,100,101 - 541 -28 541 -28 541 -15 c 0,102,103 - 541 18 541 18 541 45.5 c 128,-1,104 - 541 73 541 73 541 94.5 c 128,-1,105 - 541 116 541 116 541 144 c 0,106,107 - 541 167 541 167 541 196 c 0,108,109 - 541 206 541 206 548 214 c 0,110,111 - 592 268 592 268 611 280 c 0,112,113 - 627 291 627 291 649 291 c 0,114,115 - 653 291 653 291 659 290.5 c 128,-1,116 - 665 290 665 290 666 290 c 0,117,118 - 685 289 685 289 695 278 c 0,82,83 -153 -143 m 0,119,120 - 157 -135 157 -135 252 -42 c 0,121,122 - 260 -34 260 -34 272 -34 c 2,123,-1 - 521 -34 l 2,124,125 - 536 -34 536 -34 542 -47 c 0,126,127 - 593 -161 593 -161 598 -172 c 0,128,129 - 601 -179 601 -179 594 -185 c 0,130,131 - 589 -190 589 -190 581 -191 c 0,132,133 - 580 -191 580 -191 576.5 -191.5 c 128,-1,134 - 573 -192 573 -192 572 -192 c 2,135,-1 - 555 -193 l 1,136,-1 - 226 -193 l 2,137,138 - 200 -193 200 -193 179 -178 c 0,139,140 - 169 -172 169 -172 164 -167 c 0,141,142 - 155 -158 155 -158 153 -154.5 c 128,-1,143 - 151 -151 151 -151 153 -143 c 0,119,120 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +89 416 m 0,26,27 + 86 418 86 418 84 420 c 0,28,29 + 76 427 76 427 76 438 c 2,30,-1 + 76 672 l 2,31,32 + 76 701 76 701 90 725 c 0,33,34 + 90 726 90 726 95 735 c 0,35,36 + 100 743 100 743 109 743 c 0,37,38 + 115 743 115 743 120 738 c 0,39,40 + 125 734 125 734 155 703.5 c 128,-1,41 + 185 673 185 673 196 663 c 0,42,43 + 206 653 206 653 205 640 c 2,44,-1 + 205 467 l 2,45,46 + 205 458 205 458 197 454 c 0,47,48 + 188 448 188 448 161.5 433 c 128,-1,49 + 135 418 135 418 128 414 c 0,50,51 + 120 410 120 410 111 410 c 0,52,53 + 104 410 104 410 97 412 c 0,54,55 + 91 414 91 414 89 416 c 0,26,27 +120 751 m 0,56,57 + 118 757 118 757 120 760 c 128,-1,58 + 122 763 122 763 129 770 c 0,59,60 + 133 774 133 774 141 779 c 0,61,62 + 158 791 158 791 179 791 c 2,63,-1 + 442 791 l 1,64,-1 + 456 790 l 2,65,66 + 457 790 457 790 459 789.5 c 128,-1,67 + 461 789 461 789 463 789 c 0,68,69 + 469 788 469 788 473 784 c 0,70,71 + 478 779 478 779 476 773 c 0,72,73 + 472 765 472 765 432 674 c 0,74,75 + 427 663 427 663 415 663 c 2,76,-1 + 216 663 l 2,77,78 + 206 663 206 663 200 670 c 0,79,80 + 123 745 123 745 120 751 c 0,56,57 +554 379 m 0,81,82 + 558 375 558 375 560 368 c 0,83,84 + 561 362 561 362 560 357 c 2,85,-1 + 560 120 l 2,86,87 + 560 98 560 98 552 79 c 0,88,89 + 544 61 544 61 532 46 c 0,90,91 + 522 32 522 32 508 20 c 0,92,93 + 502 16 502 16 496 16 c 0,94,95 + 484 16 484 16 480 27 c 0,96,97 + 478 30 478 30 460 70 c 128,-1,98 + 442 110 442 110 436 124 c 0,99,100 + 431 134 431 134 431 144 c 0,101,102 + 431 170 431 170 431 192.5 c 128,-1,103 + 431 215 431 215 431 232 c 128,-1,104 + 431 249 431 249 431 271 c 0,105,106 + 431 289 431 289 431 313 c 0,107,108 + 431 321 431 321 436 327 c 0,109,110 + 471 370 471 370 487 380 c 0,111,112 + 500 389 500 389 517 389 c 0,113,114 + 520 389 520 389 525 388.5 c 128,-1,115 + 530 388 530 388 531 388 c 0,116,117 + 546 388 546 388 554 379 c 0,81,82 +120 42 m 0,118,119 + 123 48 123 48 200 123 c 0,120,121 + 206 129 206 129 216 129 c 2,122,-1 + 415 129 l 2,123,124 + 427 129 427 129 432 119 c 0,125,126 + 473 28 473 28 476 19 c 0,127,128 + 478 13 478 13 473 8 c 0,129,130 + 469 4 469 4 463 3 c 0,131,132 + 462 3 462 3 459 3 c 128,-1,133 + 456 3 456 3 456 3 c 2,134,-1 + 442 2 l 1,135,-1 + 179 2 l 2,136,137 + 158 2 158 2 141 14 c 0,138,139 + 133 19 133 19 129 23 c 0,140,141 + 122 30 122 30 120 33 c 128,-1,142 + 118 36 118 36 120 42 c 0,118,119 EndSplineSet Validated: 1 EndChar StartChar: six Encoding: 54 54 13 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -267 366 m 0,0,1 - 285 377 285 377 307 377 c 2,2,-1 - 527 377 l 2,3,4 - 535 377 535 377 540 372 c 0,5,6 - 555 355 555 355 587 321 c 0,7,8 - 596 311 596 311 596 298 c 0,9,10 - 596 284 596 284 586 274 c 0,11,12 - 561 248 561 248 542 230 c 0,13,14 - 535 222 535 222 523 222 c 2,15,-1 - 304 222 l 2,16,17 - 285 222 285 222 269 231 c 0,18,19 - 264 234 264 234 193 275 c 0,20,21 - 180 282 180 282 180 298 c 0,22,23 - 180 313 180 313 193 321 c 0,24,25 - 200 325 200 325 227 341.5 c 128,-1,26 - 254 358 254 358 267 366 c 0,0,1 -114 325 m 256,27,28 - 111 327 111 327 107 330 c 0,29,30 - 97 339 97 339 97 352 c 2,31,-1 - 97 645 l 2,32,33 - 97 681 97 681 115 711 c 0,34,35 - 115 712 115 712 121 723 c 0,36,37 - 127 733 127 733 139 733 c 0,38,39 - 147 733 147 733 152 727 c 0,40,41 - 158 722 158 722 196 684 c 128,-1,42 - 234 646 234 646 247 633 c 0,43,44 - 259 621 259 621 259 605 c 2,45,-1 - 259 388 l 2,46,47 - 259 377 259 377 249 372 c 0,48,49 - 238 365 238 365 204.5 346 c 128,-1,50 - 171 327 171 327 162 322 c 0,51,52 - 152 317 152 317 141 317 c 0,53,54 - 132 317 132 317 124 320 c 0,55,56 - 117 323 117 323 114 325 c 256,27,28 -153 743 m 0,57,58 - 151 751 151 751 153 754.5 c 128,-1,59 - 155 758 155 758 164 767 c 0,60,61 - 169 772 169 772 179 778 c 0,62,63 - 200 793 200 793 226 793 c 2,64,-1 - 555 793 l 1,65,-1 - 572 792 l 2,66,67 - 573 792 573 792 576 791.5 c 128,-1,68 - 579 791 579 791 581 791 c 0,69,70 - 589 790 589 790 594 785 c 0,71,72 - 601 779 601 779 598 771 c 0,73,74 - 593 761 593 761 542 647 c 0,75,76 - 536 633 536 633 521 633 c 2,77,-1 - 272 633 l 2,78,79 - 260 633 260 633 252 642 c 0,80,81 - 157 735 157 735 153 743 c 0,57,58 -695 278 m 0,82,83 - 700 273 700 273 702 265 c 0,84,85 - 703 258 703 258 703 251 c 2,86,-1 - 703 -45 l 2,87,88 - 703 -72 703 -72 692 -97 c 0,89,90 - 682 -119 682 -119 668 -138 c 0,91,92 - 655 -156 655 -156 638 -170 c 0,93,94 - 631 -175 631 -175 623 -175 c 0,95,96 - 608 -175 608 -175 602 -161 c 0,97,98 - 600 -157 600 -157 577.5 -107.5 c 128,-1,99 - 555 -58 555 -58 547 -40 c 0,100,101 - 541 -28 541 -28 541 -15 c 0,102,103 - 541 18 541 18 541 45.5 c 128,-1,104 - 541 73 541 73 541 94.5 c 128,-1,105 - 541 116 541 116 541 144 c 0,106,107 - 541 167 541 167 541 196 c 0,108,109 - 541 206 541 206 548 214 c 0,110,111 - 592 268 592 268 611 280 c 0,112,113 - 627 291 627 291 649 291 c 0,114,115 - 653 291 653 291 659 290.5 c 128,-1,116 - 665 290 665 290 666 290 c 0,117,118 - 685 289 685 289 695 278 c 0,82,83 -153 -143 m 0,119,120 - 157 -135 157 -135 252 -42 c 0,121,122 - 260 -34 260 -34 272 -34 c 2,123,-1 - 521 -34 l 2,124,125 - 536 -34 536 -34 542 -47 c 0,126,127 - 593 -161 593 -161 598 -172 c 0,128,129 - 601 -179 601 -179 594 -185 c 0,130,131 - 589 -190 589 -190 581 -191 c 0,132,133 - 580 -191 580 -191 576.5 -191.5 c 128,-1,134 - 573 -192 573 -192 572 -192 c 2,135,-1 - 555 -193 l 1,136,-1 - 226 -193 l 2,137,138 - 200 -193 200 -193 179 -178 c 0,139,140 - 169 -172 169 -172 164 -167 c 0,141,142 - 155 -158 155 -158 153 -154.5 c 128,-1,143 - 151 -151 151 -151 153 -143 c 0,119,120 -114 275 m 0,144,145 - 117 277 117 277 124 280 c 0,146,147 - 132 283 132 283 141 283 c 0,148,149 - 152 283 152 283 162 278 c 0,150,151 - 171 273 171 273 204.5 254 c 128,-1,152 - 238 235 238 235 249 228 c 0,153,154 - 259 223 259 223 259 212 c 2,155,-1 - 259 -6 l 2,156,157 - 259 -22 259 -22 247 -33 c 0,158,159 - 234 -46 234 -46 196 -84 c 128,-1,160 - 158 -122 158 -122 152 -127 c 0,161,162 - 147 -133 147 -133 139 -133 c 0,163,164 - 127 -133 127 -133 121 -123 c 256,165,166 - 115 -113 115 -113 115 -112 c 0,167,168 - 97 -81 97 -81 97 -45 c 2,169,-1 - 97 247 l 2,170,171 - 97 261 97 261 107 269 c 0,172,173 - 110 272 110 272 114 275 c 0,144,145 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +89 416 m 0,26,27 + 86 418 86 418 84 420 c 0,28,29 + 76 427 76 427 76 438 c 2,30,-1 + 76 672 l 2,31,32 + 76 701 76 701 90 725 c 0,33,34 + 90 726 90 726 95 735 c 0,35,36 + 100 743 100 743 109 743 c 0,37,38 + 115 743 115 743 120 738 c 0,39,40 + 125 734 125 734 155 703.5 c 128,-1,41 + 185 673 185 673 196 663 c 0,42,43 + 206 653 206 653 205 640 c 2,44,-1 + 205 467 l 2,45,46 + 205 458 205 458 197 454 c 0,47,48 + 188 448 188 448 161.5 433 c 128,-1,49 + 135 418 135 418 128 414 c 0,50,51 + 120 410 120 410 111 410 c 0,52,53 + 104 410 104 410 97 412 c 0,54,55 + 91 414 91 414 89 416 c 0,26,27 +120 751 m 0,56,57 + 118 757 118 757 120 760 c 128,-1,58 + 122 763 122 763 129 770 c 0,59,60 + 133 774 133 774 141 779 c 0,61,62 + 158 791 158 791 179 791 c 2,63,-1 + 442 791 l 1,64,-1 + 456 790 l 2,65,66 + 457 790 457 790 459 789.5 c 128,-1,67 + 461 789 461 789 463 789 c 0,68,69 + 469 788 469 788 473 784 c 0,70,71 + 478 779 478 779 476 773 c 0,72,73 + 472 765 472 765 432 674 c 0,74,75 + 427 663 427 663 415 663 c 2,76,-1 + 216 663 l 2,77,78 + 206 663 206 663 200 670 c 0,79,80 + 123 745 123 745 120 751 c 0,56,57 +554 379 m 0,81,82 + 558 375 558 375 560 368 c 0,83,84 + 561 362 561 362 560 357 c 2,85,-1 + 560 120 l 2,86,87 + 560 98 560 98 552 79 c 0,88,89 + 544 61 544 61 532 46 c 0,90,91 + 522 32 522 32 508 20 c 0,92,93 + 502 16 502 16 496 16 c 0,94,95 + 484 16 484 16 480 27 c 0,96,97 + 478 30 478 30 460 70 c 128,-1,98 + 442 110 442 110 436 124 c 0,99,100 + 431 134 431 134 431 144 c 0,101,102 + 431 170 431 170 431 192.5 c 128,-1,103 + 431 215 431 215 431 232 c 128,-1,104 + 431 249 431 249 431 271 c 0,105,106 + 431 289 431 289 431 313 c 0,107,108 + 431 321 431 321 436 327 c 0,109,110 + 471 370 471 370 487 380 c 0,111,112 + 500 389 500 389 517 389 c 0,113,114 + 520 389 520 389 525 388.5 c 128,-1,115 + 530 388 530 388 531 388 c 0,116,117 + 546 388 546 388 554 379 c 0,81,82 +120 42 m 0,118,119 + 123 48 123 48 200 123 c 0,120,121 + 206 129 206 129 216 129 c 2,122,-1 + 415 129 l 2,123,124 + 427 129 427 129 432 119 c 0,125,126 + 473 28 473 28 476 19 c 0,127,128 + 478 13 478 13 473 8 c 0,129,130 + 469 4 469 4 463 3 c 0,131,132 + 462 3 462 3 459 3 c 128,-1,133 + 456 3 456 3 456 3 c 2,134,-1 + 442 2 l 1,135,-1 + 179 2 l 2,136,137 + 158 2 158 2 141 14 c 0,138,139 + 133 19 133 19 129 23 c 0,140,141 + 122 30 122 30 120 33 c 128,-1,142 + 118 36 118 36 120 42 c 0,118,119 +89 376 m 0,143,144 + 91 378 91 378 97 380 c 128,-1,145 + 103 382 103 382 111 383 c 0,146,147 + 120 383 120 383 128 379 c 0,148,149 + 135 375 135 375 161.5 359.5 c 128,-1,150 + 188 344 188 344 197 339 c 0,151,152 + 205 335 205 335 205 326 c 2,153,-1 + 205 151 l 2,154,155 + 205 138 205 138 196 130 c 0,156,157 + 186 120 186 120 155 89.5 c 128,-1,158 + 124 59 124 59 120 55 c 0,159,160 + 116 50 116 50 109 50 c 0,161,162 + 99 50 99 50 95 58 c 256,163,164 + 90 66 90 66 90 67 c 0,165,166 + 76 92 76 92 76 120 c 2,167,-1 + 76 354 l 2,168,169 + 76 365 76 365 84 371 c 0,170,171 + 86 374 86 374 89 376 c 0,143,144 EndSplineSet Validated: 1 EndChar StartChar: seven Encoding: 55 55 14 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -695 319 m 0,0,1 - 685 308 685 308 666 307 c 0,2,3 - 665 307 665 307 659 306.5 c 128,-1,4 - 653 306 653 306 649 306 c 0,5,6 - 627 306 627 306 611 317 c 0,7,8 - 592 329 592 329 548 382 c 0,9,10 - 541 390 541 390 541 401 c 0,11,12 - 541 430 541 430 541 453 c 0,13,14 - 541 481 541 481 541 502.5 c 128,-1,15 - 541 524 541 524 541 551.5 c 128,-1,16 - 541 579 541 579 541 612 c 0,17,18 - 541 625 541 625 547 637 c 0,19,20 - 580 710 580 710 602 758 c 0,21,22 - 608 771 608 771 623 771 c 0,23,24 - 631 771 631 771 638 767 c 0,25,26 - 655 753 655 753 668 735 c 0,27,28 - 682 716 682 716 692 694 c 0,29,30 - 703 669 703 669 703 641 c 2,31,-1 - 703 346 l 2,32,33 - 703 339 703 339 702 332 c 0,34,35 - 700 324 700 324 695 319 c 0,0,1 -153 743 m 0,36,37 - 151 751 151 751 153 754.5 c 128,-1,38 - 155 758 155 758 164 767 c 0,39,40 - 169 772 169 772 179 778 c 0,41,42 - 200 793 200 793 226 793 c 2,43,-1 - 555 793 l 1,44,-1 - 572 792 l 2,45,46 - 573 792 573 792 576 791.5 c 128,-1,47 - 579 791 579 791 581 791 c 0,48,49 - 589 790 589 790 594 785 c 0,50,51 - 601 779 601 779 598 771 c 0,52,53 - 593 761 593 761 542 647 c 0,54,55 - 536 633 536 633 521 633 c 2,56,-1 - 272 633 l 2,57,58 - 260 633 260 633 252 642 c 0,59,60 - 157 735 157 735 153 743 c 0,36,37 -695 278 m 0,61,62 - 700 273 700 273 702 265 c 0,63,64 - 703 258 703 258 703 251 c 2,65,-1 - 703 -45 l 2,66,67 - 703 -72 703 -72 692 -97 c 0,68,69 - 682 -119 682 -119 668 -138 c 0,70,71 - 655 -156 655 -156 638 -170 c 0,72,73 - 631 -175 631 -175 623 -175 c 0,74,75 - 608 -175 608 -175 602 -161 c 0,76,77 - 600 -157 600 -157 577.5 -107.5 c 128,-1,78 - 555 -58 555 -58 547 -40 c 0,79,80 - 541 -28 541 -28 541 -15 c 0,81,82 - 541 18 541 18 541 45.5 c 128,-1,83 - 541 73 541 73 541 94.5 c 128,-1,84 - 541 116 541 116 541 144 c 0,85,86 - 541 167 541 167 541 196 c 0,87,88 - 541 206 541 206 548 214 c 0,89,90 - 592 268 592 268 611 280 c 0,91,92 - 627 291 627 291 649 291 c 0,93,94 - 653 291 653 291 659 290.5 c 128,-1,95 - 665 290 665 290 666 290 c 0,96,97 - 685 289 685 289 695 278 c 0,61,62 +554 411 m 0,0,1 + 546 402 546 402 531 402 c 0,2,3 + 530 402 530 402 525 401.5 c 128,-1,4 + 520 401 520 401 517 401 c 0,5,6 + 499 401 499 401 487 410 c 0,7,8 + 472 420 472 420 436 462 c 0,9,10 + 430 468 430 468 431 477 c 0,11,12 + 431 500 431 500 431 519 c 0,13,14 + 431 541 431 541 431 558 c 128,-1,15 + 431 575 431 575 431 597 c 128,-1,16 + 431 619 431 619 431 646 c 0,17,18 + 431 656 431 656 436 666 c 0,19,20 + 462 724 462 724 480 763 c 0,21,22 + 485 773 485 773 496 773 c 0,23,24 + 502 773 502 773 508 770 c 0,25,26 + 520 761 520 761 532 744 c 0,27,28 + 546 726 546 726 552 711 c 0,29,30 + 560 693 560 693 560 673 c 0,31,32 + 560 671 560 671 560 669 c 2,33,-1 + 560 433 l 2,34,35 + 560 427 560 427 560 422 c 0,36,37 + 558 415 558 415 554 411 c 0,0,1 +120 751 m 0,38,39 + 118 757 118 757 120 760 c 128,-1,40 + 122 763 122 763 129 770 c 0,41,42 + 133 774 133 774 141 779 c 0,43,44 + 158 791 158 791 179 791 c 2,45,-1 + 442 791 l 1,46,-1 + 456 790 l 2,47,48 + 457 790 457 790 459 789.5 c 128,-1,49 + 461 789 461 789 463 789 c 0,50,51 + 469 788 469 788 473 784 c 0,52,53 + 478 779 478 779 476 773 c 0,54,55 + 472 765 472 765 432 674 c 0,56,57 + 427 663 427 663 415 663 c 2,58,-1 + 216 663 l 2,59,60 + 206 663 206 663 200 670 c 0,61,62 + 123 745 123 745 120 751 c 0,38,39 +554 379 m 0,63,64 + 558 375 558 375 560 368 c 0,65,66 + 561 362 561 362 560 357 c 2,67,-1 + 560 120 l 2,68,69 + 560 98 560 98 552 79 c 0,70,71 + 544 61 544 61 532 46 c 0,72,73 + 522 32 522 32 508 20 c 0,74,75 + 502 16 502 16 496 16 c 0,76,77 + 484 16 484 16 480 27 c 0,78,79 + 478 30 478 30 460 70 c 128,-1,80 + 442 110 442 110 436 124 c 0,81,82 + 431 134 431 134 431 144 c 0,83,84 + 431 170 431 170 431 192.5 c 128,-1,85 + 431 215 431 215 431 232 c 128,-1,86 + 431 249 431 249 431 271 c 0,87,88 + 431 289 431 289 431 313 c 0,89,90 + 431 321 431 321 436 327 c 0,91,92 + 471 370 471 370 487 380 c 0,93,94 + 500 389 500 389 517 389 c 0,95,96 + 520 389 520 389 525 388.5 c 128,-1,97 + 530 388 530 388 531 388 c 0,98,99 + 546 388 546 388 554 379 c 0,63,64 EndSplineSet Validated: 1 EndChar StartChar: eight Encoding: 56 56 15 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -695 319 m 0,0,1 - 685 308 685 308 666 307 c 0,2,3 - 665 307 665 307 659 306.5 c 128,-1,4 - 653 306 653 306 649 306 c 0,5,6 - 627 306 627 306 611 317 c 0,7,8 - 592 329 592 329 548 382 c 0,9,10 - 541 390 541 390 541 401 c 0,11,12 - 541 430 541 430 541 453 c 0,13,14 - 541 481 541 481 541 502.5 c 128,-1,15 - 541 524 541 524 541 551.5 c 128,-1,16 - 541 579 541 579 541 612 c 0,17,18 - 541 625 541 625 547 637 c 0,19,20 - 580 710 580 710 602 758 c 0,21,22 - 608 771 608 771 623 771 c 0,23,24 - 631 771 631 771 638 767 c 0,25,26 - 655 753 655 753 668 735 c 0,27,28 - 682 716 682 716 692 694 c 0,29,30 - 703 669 703 669 703 641 c 2,31,-1 - 703 346 l 2,32,33 - 703 339 703 339 702 332 c 0,34,35 - 700 324 700 324 695 319 c 0,0,1 -267 366 m 0,36,37 - 285 377 285 377 307 377 c 2,38,-1 - 527 377 l 2,39,40 - 534 377 534 377 540 372 c 0,41,42 - 555 355 555 355 587 321 c 0,43,44 - 596 311 596 311 596 298 c 0,45,46 - 596 284 596 284 586 274 c 0,47,48 - 561 248 561 248 542 230 c 0,49,50 - 535 222 535 222 523 222 c 2,51,-1 - 304 222 l 2,52,53 - 285 222 285 222 269 231 c 0,54,55 - 264 234 264 234 193 275 c 0,56,57 - 180 282 180 282 180 298 c 0,58,59 - 180 313 180 313 193 321 c 0,60,61 - 200 325 200 325 227 341.5 c 128,-1,62 - 254 358 254 358 267 366 c 0,36,37 -114 325 m 256,63,64 - 111 327 111 327 107 330 c 0,65,66 - 97 339 97 339 97 352 c 2,67,-1 - 97 645 l 2,68,69 - 97 681 97 681 115 711 c 0,70,71 - 115 712 115 712 121 723 c 0,72,73 - 127 733 127 733 139 733 c 0,74,75 - 147 733 147 733 152 727 c 0,76,77 - 158 722 158 722 196 684 c 128,-1,78 - 234 646 234 646 247 633 c 0,79,80 - 259 621 259 621 259 605 c 2,81,-1 - 259 388 l 2,82,83 - 259 377 259 377 249 372 c 0,84,85 - 238 365 238 365 204.5 346 c 128,-1,86 - 171 327 171 327 162 322 c 0,87,88 - 152 317 152 317 141 317 c 0,89,90 - 132 317 132 317 124 320 c 0,91,92 - 117 323 117 323 114 325 c 256,63,64 -153 743 m 0,93,94 - 151 751 151 751 153 754.5 c 128,-1,95 - 155 758 155 758 164 767 c 0,96,97 - 169 772 169 772 179 778 c 0,98,99 - 200 793 200 793 226 793 c 2,100,-1 - 555 793 l 1,101,-1 - 572 792 l 2,102,103 - 573 792 573 792 576 791.5 c 128,-1,104 - 579 791 579 791 581 791 c 0,105,106 - 589 790 589 790 594 785 c 0,107,108 - 601 779 601 779 598 771 c 0,109,110 - 593 761 593 761 542 647 c 0,111,112 - 536 633 536 633 521 633 c 2,113,-1 - 272 633 l 2,114,115 - 260 633 260 633 252 642 c 0,116,117 - 157 735 157 735 153 743 c 0,93,94 -695 278 m 0,118,119 - 700 273 700 273 702 265 c 0,120,121 - 703 258 703 258 703 251 c 2,122,-1 - 703 -45 l 2,123,124 - 703 -72 703 -72 692 -97 c 0,125,126 - 682 -119 682 -119 668 -138 c 0,127,128 - 655 -156 655 -156 638 -170 c 0,129,130 - 631 -175 631 -175 623 -175 c 0,131,132 - 608 -175 608 -175 602 -161 c 0,133,134 - 600 -157 600 -157 577.5 -107.5 c 128,-1,135 - 555 -58 555 -58 547 -40 c 0,136,137 - 541 -28 541 -28 541 -15 c 0,138,139 - 541 18 541 18 541 45.5 c 128,-1,140 - 541 73 541 73 541 94.5 c 128,-1,141 - 541 116 541 116 541 144 c 0,142,143 - 541 167 541 167 541 196 c 0,144,145 - 541 206 541 206 548 214 c 0,146,147 - 592 268 592 268 611 280 c 0,148,149 - 627 291 627 291 649 291 c 0,150,151 - 653 291 653 291 659 290.5 c 128,-1,152 - 665 290 665 290 666 290 c 0,153,154 - 685 289 685 289 695 278 c 0,118,119 -153 -143 m 0,155,156 - 157 -135 157 -135 252 -42 c 0,157,158 - 260 -34 260 -34 272 -34 c 2,159,-1 - 521 -34 l 2,160,161 - 536 -34 536 -34 542 -47 c 0,162,163 - 593 -161 593 -161 598 -172 c 0,164,165 - 601 -179 601 -179 594 -185 c 0,166,167 - 589 -190 589 -190 581 -191 c 0,168,169 - 580 -191 580 -191 576.5 -191.5 c 128,-1,170 - 573 -192 573 -192 572 -192 c 2,171,-1 - 555 -193 l 1,172,-1 - 226 -193 l 2,173,174 - 200 -193 200 -193 179 -178 c 0,175,176 - 169 -172 169 -172 164 -167 c 0,177,178 - 155 -158 155 -158 153 -154.5 c 128,-1,179 - 151 -151 151 -151 153 -143 c 0,155,156 -114 275 m 0,180,181 - 117 277 117 277 124 280 c 0,182,183 - 132 283 132 283 141 283 c 0,184,185 - 152 283 152 283 162 278 c 0,186,187 - 171 273 171 273 204.5 254 c 128,-1,188 - 238 235 238 235 249 228 c 0,189,190 - 259 223 259 223 259 212 c 2,191,-1 - 259 -6 l 2,192,193 - 259 -22 259 -22 247 -33 c 0,194,195 - 234 -46 234 -46 196 -84 c 128,-1,196 - 158 -122 158 -122 152 -127 c 0,197,198 - 147 -133 147 -133 139 -133 c 0,199,200 - 127 -133 127 -133 121 -123 c 256,201,202 - 115 -113 115 -113 115 -112 c 0,203,204 - 97 -81 97 -81 97 -45 c 2,205,-1 - 97 247 l 2,206,207 - 97 261 97 261 107 269 c 0,208,209 - 110 272 110 272 114 275 c 0,180,181 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +554 411 m 0,26,27 + 546 402 546 402 531 402 c 0,28,29 + 530 402 530 402 525 401.5 c 128,-1,30 + 520 401 520 401 517 401 c 0,31,32 + 499 401 499 401 487 410 c 0,33,34 + 472 420 472 420 436 462 c 0,35,36 + 430 468 430 468 431 477 c 0,37,38 + 431 500 431 500 431 519 c 0,39,40 + 431 541 431 541 431 558 c 128,-1,41 + 431 575 431 575 431 597 c 128,-1,42 + 431 619 431 619 431 646 c 0,43,44 + 431 656 431 656 436 666 c 0,45,46 + 462 724 462 724 480 763 c 0,47,48 + 485 773 485 773 496 773 c 0,49,50 + 502 773 502 773 508 770 c 0,51,52 + 520 761 520 761 532 744 c 0,53,54 + 546 726 546 726 552 711 c 0,55,56 + 560 693 560 693 560 673 c 0,57,58 + 560 671 560 671 560 669 c 2,59,-1 + 560 433 l 2,60,61 + 560 427 560 427 560 422 c 0,62,63 + 558 415 558 415 554 411 c 0,26,27 +89 416 m 0,64,65 + 86 418 86 418 84 420 c 0,66,67 + 76 427 76 427 76 438 c 2,68,-1 + 76 672 l 2,69,70 + 76 701 76 701 90 725 c 0,71,72 + 90 726 90 726 95 735 c 0,73,74 + 100 743 100 743 109 743 c 0,75,76 + 115 743 115 743 120 738 c 0,77,78 + 125 734 125 734 155 703.5 c 128,-1,79 + 185 673 185 673 196 663 c 0,80,81 + 206 653 206 653 205 640 c 2,82,-1 + 205 467 l 2,83,84 + 205 458 205 458 197 454 c 0,85,86 + 188 448 188 448 161.5 433 c 128,-1,87 + 135 418 135 418 128 414 c 0,88,89 + 120 410 120 410 111 410 c 0,90,91 + 104 410 104 410 97 412 c 0,92,93 + 91 414 91 414 89 416 c 0,64,65 +120 751 m 0,94,95 + 118 757 118 757 120 760 c 128,-1,96 + 122 763 122 763 129 770 c 0,97,98 + 133 774 133 774 141 779 c 0,99,100 + 158 791 158 791 179 791 c 2,101,-1 + 442 791 l 1,102,-1 + 456 790 l 2,103,104 + 457 790 457 790 459 789.5 c 128,-1,105 + 461 789 461 789 463 789 c 0,106,107 + 469 788 469 788 473 784 c 0,108,109 + 478 779 478 779 476 773 c 0,110,111 + 472 765 472 765 432 674 c 0,112,113 + 427 663 427 663 415 663 c 2,114,-1 + 216 663 l 2,115,116 + 206 663 206 663 200 670 c 0,117,118 + 123 745 123 745 120 751 c 0,94,95 +554 379 m 0,119,120 + 558 375 558 375 560 368 c 0,121,122 + 561 362 561 362 560 357 c 2,123,-1 + 560 120 l 2,124,125 + 560 98 560 98 552 79 c 0,126,127 + 544 61 544 61 532 46 c 0,128,129 + 522 32 522 32 508 20 c 0,130,131 + 502 16 502 16 496 16 c 0,132,133 + 484 16 484 16 480 27 c 0,134,135 + 478 30 478 30 460 70 c 128,-1,136 + 442 110 442 110 436 124 c 0,137,138 + 431 134 431 134 431 144 c 0,139,140 + 431 170 431 170 431 192.5 c 128,-1,141 + 431 215 431 215 431 232 c 128,-1,142 + 431 249 431 249 431 271 c 0,143,144 + 431 289 431 289 431 313 c 0,145,146 + 431 321 431 321 436 327 c 0,147,148 + 471 370 471 370 487 380 c 0,149,150 + 500 389 500 389 517 389 c 0,151,152 + 520 389 520 389 525 388.5 c 128,-1,153 + 530 388 530 388 531 388 c 0,154,155 + 546 388 546 388 554 379 c 0,119,120 +120 42 m 0,156,157 + 123 48 123 48 200 123 c 0,158,159 + 206 129 206 129 216 129 c 2,160,-1 + 415 129 l 2,161,162 + 427 129 427 129 432 119 c 0,163,164 + 473 28 473 28 476 19 c 0,165,166 + 478 13 478 13 473 8 c 0,167,168 + 469 4 469 4 463 3 c 0,169,170 + 462 3 462 3 459 3 c 128,-1,171 + 456 3 456 3 456 3 c 2,172,-1 + 442 2 l 1,173,-1 + 179 2 l 2,174,175 + 158 2 158 2 141 14 c 0,176,177 + 133 19 133 19 129 23 c 0,178,179 + 122 30 122 30 120 33 c 128,-1,180 + 118 36 118 36 120 42 c 0,156,157 +89 376 m 0,181,182 + 91 378 91 378 97 380 c 128,-1,183 + 103 382 103 382 111 383 c 0,184,185 + 120 383 120 383 128 379 c 0,186,187 + 135 375 135 375 161.5 359.5 c 128,-1,188 + 188 344 188 344 197 339 c 0,189,190 + 205 335 205 335 205 326 c 2,191,-1 + 205 151 l 2,192,193 + 205 138 205 138 196 130 c 0,194,195 + 186 120 186 120 155 89.5 c 128,-1,196 + 124 59 124 59 120 55 c 0,197,198 + 116 50 116 50 109 50 c 0,199,200 + 99 50 99 50 95 58 c 256,201,202 + 90 66 90 66 90 67 c 0,203,204 + 76 92 76 92 76 120 c 2,205,-1 + 76 354 l 2,206,207 + 76 365 76 365 84 371 c 0,208,209 + 86 374 86 374 89 376 c 0,181,182 EndSplineSet Validated: 1 EndChar StartChar: nine Encoding: 57 57 16 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -695 319 m 0,0,1 - 685 308 685 308 666 307 c 0,2,3 - 665 307 665 307 659 306.5 c 128,-1,4 - 653 306 653 306 649 306 c 0,5,6 - 627 306 627 306 611 317 c 0,7,8 - 592 329 592 329 548 382 c 0,9,10 - 541 390 541 390 541 401 c 0,11,12 - 541 430 541 430 541 453 c 0,13,14 - 541 481 541 481 541 502.5 c 128,-1,15 - 541 524 541 524 541 551.5 c 128,-1,16 - 541 579 541 579 541 612 c 0,17,18 - 541 625 541 625 547 637 c 0,19,20 - 580 710 580 710 602 758 c 0,21,22 - 608 771 608 771 623 771 c 0,23,24 - 631 771 631 771 638 767 c 0,25,26 - 655 753 655 753 668 735 c 0,27,28 - 682 716 682 716 692 694 c 0,29,30 - 703 669 703 669 703 641 c 2,31,-1 - 703 346 l 2,32,33 - 703 339 703 339 702 332 c 0,34,35 - 700 324 700 324 695 319 c 0,0,1 -267 366 m 0,36,37 - 285 377 285 377 307 377 c 2,38,-1 - 527 377 l 2,39,40 - 534 377 534 377 540 372 c 0,41,42 - 555 355 555 355 587 321 c 0,43,44 - 596 311 596 311 596 298 c 0,45,46 - 596 284 596 284 586 274 c 0,47,48 - 561 248 561 248 542 230 c 0,49,50 - 535 222 535 222 523 222 c 2,51,-1 - 304 222 l 2,52,53 - 285 222 285 222 269 231 c 0,54,55 - 264 234 264 234 193 275 c 0,56,57 - 180 282 180 282 180 298 c 0,58,59 - 180 313 180 313 193 321 c 0,60,61 - 200 325 200 325 227 341.5 c 128,-1,62 - 254 358 254 358 267 366 c 0,36,37 -114 325 m 256,63,64 - 111 327 111 327 107 330 c 0,65,66 - 97 339 97 339 97 352 c 2,67,-1 - 97 645 l 2,68,69 - 97 681 97 681 115 711 c 0,70,71 - 115 712 115 712 121 723 c 0,72,73 - 127 733 127 733 139 733 c 0,74,75 - 147 733 147 733 152 727 c 0,76,77 - 158 722 158 722 196 684 c 128,-1,78 - 234 646 234 646 247 633 c 0,79,80 - 259 621 259 621 259 605 c 2,81,-1 - 259 388 l 2,82,83 - 259 377 259 377 249 372 c 0,84,85 - 238 365 238 365 204.5 346 c 128,-1,86 - 171 327 171 327 162 322 c 0,87,88 - 152 317 152 317 141 317 c 0,89,90 - 132 317 132 317 124 320 c 0,91,92 - 117 323 117 323 114 325 c 256,63,64 -153 743 m 0,93,94 - 151 751 151 751 153 754.5 c 128,-1,95 - 155 758 155 758 164 767 c 0,96,97 - 169 772 169 772 179 778 c 0,98,99 - 200 793 200 793 226 793 c 2,100,-1 - 555 793 l 1,101,-1 - 572 792 l 2,102,103 - 573 792 573 792 576 791.5 c 128,-1,104 - 579 791 579 791 581 791 c 0,105,106 - 589 790 589 790 594 785 c 0,107,108 - 601 779 601 779 598 771 c 0,109,110 - 593 761 593 761 542 647 c 0,111,112 - 536 633 536 633 521 633 c 2,113,-1 - 272 633 l 2,114,115 - 260 633 260 633 252 642 c 0,116,117 - 157 735 157 735 153 743 c 0,93,94 -695 278 m 0,118,119 - 700 273 700 273 702 265 c 0,120,121 - 703 258 703 258 703 251 c 2,122,-1 - 703 -45 l 2,123,124 - 703 -72 703 -72 692 -97 c 0,125,126 - 682 -119 682 -119 668 -138 c 0,127,128 - 655 -156 655 -156 638 -170 c 0,129,130 - 631 -175 631 -175 623 -175 c 0,131,132 - 608 -175 608 -175 602 -161 c 0,133,134 - 600 -157 600 -157 577.5 -107.5 c 128,-1,135 - 555 -58 555 -58 547 -40 c 0,136,137 - 541 -28 541 -28 541 -15 c 0,138,139 - 541 18 541 18 541 45.5 c 128,-1,140 - 541 73 541 73 541 94.5 c 128,-1,141 - 541 116 541 116 541 144 c 0,142,143 - 541 167 541 167 541 196 c 0,144,145 - 541 206 541 206 548 214 c 0,146,147 - 592 268 592 268 611 280 c 0,148,149 - 627 291 627 291 649 291 c 0,150,151 - 653 291 653 291 659 290.5 c 128,-1,152 - 665 290 665 290 666 290 c 0,153,154 - 685 289 685 289 695 278 c 0,118,119 -153 -143 m 0,155,156 - 157 -135 157 -135 252 -42 c 0,157,158 - 260 -34 260 -34 272 -34 c 2,159,-1 - 521 -34 l 2,160,161 - 536 -34 536 -34 542 -47 c 0,162,163 - 593 -161 593 -161 598 -172 c 0,164,165 - 601 -179 601 -179 594 -185 c 0,166,167 - 589 -190 589 -190 581 -191 c 0,168,169 - 580 -191 580 -191 576.5 -191.5 c 128,-1,170 - 573 -192 573 -192 572 -192 c 2,171,-1 - 555 -193 l 1,172,-1 - 226 -193 l 2,173,174 - 200 -193 200 -193 179 -178 c 0,175,176 - 169 -172 169 -172 164 -167 c 0,177,178 - 155 -158 155 -158 153 -154.5 c 128,-1,179 - 151 -151 151 -151 153 -143 c 0,155,156 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +554 411 m 0,26,27 + 546 402 546 402 531 402 c 0,28,29 + 530 402 530 402 525 401.5 c 128,-1,30 + 520 401 520 401 517 401 c 0,31,32 + 499 401 499 401 487 410 c 0,33,34 + 472 420 472 420 436 462 c 0,35,36 + 430 468 430 468 431 477 c 0,37,38 + 431 500 431 500 431 519 c 0,39,40 + 431 541 431 541 431 558 c 128,-1,41 + 431 575 431 575 431 597 c 128,-1,42 + 431 619 431 619 431 646 c 0,43,44 + 431 656 431 656 436 666 c 0,45,46 + 462 724 462 724 480 763 c 0,47,48 + 485 773 485 773 496 773 c 0,49,50 + 502 773 502 773 508 770 c 0,51,52 + 520 761 520 761 532 744 c 0,53,54 + 546 726 546 726 552 711 c 0,55,56 + 560 693 560 693 560 673 c 0,57,58 + 560 671 560 671 560 669 c 2,59,-1 + 560 433 l 2,60,61 + 560 427 560 427 560 422 c 0,62,63 + 558 415 558 415 554 411 c 0,26,27 +89 416 m 0,64,65 + 86 418 86 418 84 420 c 0,66,67 + 76 427 76 427 76 438 c 2,68,-1 + 76 672 l 2,69,70 + 76 701 76 701 90 725 c 0,71,72 + 90 726 90 726 95 735 c 0,73,74 + 100 743 100 743 109 743 c 0,75,76 + 115 743 115 743 120 738 c 0,77,78 + 125 734 125 734 155 703.5 c 128,-1,79 + 185 673 185 673 196 663 c 0,80,81 + 206 653 206 653 205 640 c 2,82,-1 + 205 467 l 2,83,84 + 205 458 205 458 197 454 c 0,85,86 + 188 448 188 448 161.5 433 c 128,-1,87 + 135 418 135 418 128 414 c 0,88,89 + 120 410 120 410 111 410 c 0,90,91 + 104 410 104 410 97 412 c 0,92,93 + 91 414 91 414 89 416 c 0,64,65 +120 751 m 0,94,95 + 118 757 118 757 120 760 c 128,-1,96 + 122 763 122 763 129 770 c 0,97,98 + 133 774 133 774 141 779 c 0,99,100 + 158 791 158 791 179 791 c 2,101,-1 + 442 791 l 1,102,-1 + 456 790 l 2,103,104 + 457 790 457 790 459 789.5 c 128,-1,105 + 461 789 461 789 463 789 c 0,106,107 + 469 788 469 788 473 784 c 0,108,109 + 478 779 478 779 476 773 c 0,110,111 + 472 765 472 765 432 674 c 0,112,113 + 427 663 427 663 415 663 c 2,114,-1 + 216 663 l 2,115,116 + 206 663 206 663 200 670 c 0,117,118 + 123 745 123 745 120 751 c 0,94,95 +554 379 m 0,119,120 + 558 375 558 375 560 368 c 0,121,122 + 561 362 561 362 560 357 c 2,123,-1 + 560 120 l 2,124,125 + 560 98 560 98 552 79 c 0,126,127 + 544 61 544 61 532 46 c 0,128,129 + 522 32 522 32 508 20 c 0,130,131 + 502 16 502 16 496 16 c 0,132,133 + 484 16 484 16 480 27 c 0,134,135 + 478 30 478 30 460 70 c 128,-1,136 + 442 110 442 110 436 124 c 0,137,138 + 431 134 431 134 431 144 c 0,139,140 + 431 170 431 170 431 192.5 c 128,-1,141 + 431 215 431 215 431 232 c 128,-1,142 + 431 249 431 249 431 271 c 0,143,144 + 431 289 431 289 431 313 c 0,145,146 + 431 321 431 321 436 327 c 0,147,148 + 471 370 471 370 487 380 c 0,149,150 + 500 389 500 389 517 389 c 0,151,152 + 520 389 520 389 525 388.5 c 128,-1,153 + 530 388 530 388 531 388 c 0,154,155 + 546 388 546 388 554 379 c 0,119,120 +120 42 m 0,156,157 + 123 48 123 48 200 123 c 0,158,159 + 206 129 206 129 216 129 c 2,160,-1 + 415 129 l 2,161,162 + 427 129 427 129 432 119 c 0,163,164 + 473 28 473 28 476 19 c 0,165,166 + 478 13 478 13 473 8 c 0,167,168 + 469 4 469 4 463 3 c 0,169,170 + 462 3 462 3 459 3 c 128,-1,171 + 456 3 456 3 456 3 c 2,172,-1 + 442 2 l 1,173,-1 + 179 2 l 2,174,175 + 158 2 158 2 141 14 c 0,176,177 + 133 19 133 19 129 23 c 0,178,179 + 122 30 122 30 120 33 c 128,-1,180 + 118 36 118 36 120 42 c 0,156,157 EndSplineSet Validated: 1 EndChar @@ -1715,100 +2390,100 @@ EndChar StartChar: S Encoding: 83 83 26 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -267 366 m 0,0,1 - 285 377 285 377 307 377 c 2,2,-1 - 527 377 l 2,3,4 - 535 377 535 377 540 372 c 0,5,6 - 555 355 555 355 587 321 c 0,7,8 - 596 311 596 311 596 298 c 0,9,10 - 596 284 596 284 586 274 c 0,11,12 - 561 248 561 248 542 230 c 0,13,14 - 535 222 535 222 523 222 c 2,15,-1 - 304 222 l 2,16,17 - 285 222 285 222 269 231 c 0,18,19 - 264 234 264 234 193 275 c 0,20,21 - 180 282 180 282 180 298 c 0,22,23 - 180 313 180 313 193 321 c 0,24,25 - 200 325 200 325 227 341.5 c 128,-1,26 - 254 358 254 358 267 366 c 0,0,1 -114 325 m 256,27,28 - 111 327 111 327 107 330 c 0,29,30 - 97 339 97 339 97 352 c 2,31,-1 - 97 645 l 2,32,33 - 97 681 97 681 115 711 c 0,34,35 - 115 712 115 712 121 723 c 0,36,37 - 127 733 127 733 139 733 c 0,38,39 - 147 733 147 733 152 727 c 0,40,41 - 158 722 158 722 196 684 c 128,-1,42 - 234 646 234 646 247 633 c 0,43,44 - 259 621 259 621 259 605 c 2,45,-1 - 259 388 l 2,46,47 - 259 377 259 377 249 372 c 0,48,49 - 238 365 238 365 204.5 346 c 128,-1,50 - 171 327 171 327 162 322 c 0,51,52 - 152 317 152 317 141 317 c 0,53,54 - 132 317 132 317 124 320 c 0,55,56 - 117 323 117 323 114 325 c 256,27,28 -153 743 m 0,57,58 - 151 751 151 751 153 754.5 c 128,-1,59 - 155 758 155 758 164 767 c 0,60,61 - 169 772 169 772 179 778 c 0,62,63 - 200 793 200 793 226 793 c 2,64,-1 - 555 793 l 1,65,-1 - 572 792 l 2,66,67 - 573 792 573 792 576 791.5 c 128,-1,68 - 579 791 579 791 581 791 c 0,69,70 - 589 790 589 790 594 785 c 0,71,72 - 601 779 601 779 598 771 c 0,73,74 - 593 761 593 761 542 647 c 0,75,76 - 536 633 536 633 521 633 c 2,77,-1 - 272 633 l 2,78,79 - 260 633 260 633 252 642 c 0,80,81 - 157 735 157 735 153 743 c 0,57,58 -695 278 m 0,82,83 - 700 273 700 273 702 265 c 0,84,85 - 703 258 703 258 703 251 c 2,86,-1 - 703 -45 l 2,87,88 - 703 -72 703 -72 692 -97 c 0,89,90 - 682 -119 682 -119 668 -138 c 0,91,92 - 655 -156 655 -156 638 -170 c 0,93,94 - 631 -175 631 -175 623 -175 c 0,95,96 - 608 -175 608 -175 602 -161 c 0,97,98 - 600 -157 600 -157 577.5 -107.5 c 128,-1,99 - 555 -58 555 -58 547 -40 c 0,100,101 - 541 -28 541 -28 541 -15 c 0,102,103 - 541 18 541 18 541 45.5 c 128,-1,104 - 541 73 541 73 541 94.5 c 128,-1,105 - 541 116 541 116 541 144 c 0,106,107 - 541 167 541 167 541 196 c 0,108,109 - 541 206 541 206 548 214 c 0,110,111 - 592 268 592 268 611 280 c 0,112,113 - 627 291 627 291 649 291 c 0,114,115 - 653 291 653 291 659 290.5 c 128,-1,116 - 665 290 665 290 666 290 c 0,117,118 - 685 289 685 289 695 278 c 0,82,83 -153 -143 m 0,119,120 - 157 -135 157 -135 252 -42 c 0,121,122 - 260 -34 260 -34 272 -34 c 2,123,-1 - 521 -34 l 2,124,125 - 536 -34 536 -34 542 -47 c 0,126,127 - 593 -161 593 -161 598 -172 c 0,128,129 - 601 -179 601 -179 594 -185 c 0,130,131 - 589 -190 589 -190 581 -191 c 0,132,133 - 580 -191 580 -191 576.5 -191.5 c 128,-1,134 - 573 -192 573 -192 572 -192 c 2,135,-1 - 555 -193 l 1,136,-1 - 226 -193 l 2,137,138 - 200 -193 200 -193 179 -178 c 0,139,140 - 169 -172 169 -172 164 -167 c 0,141,142 - 155 -158 155 -158 153 -154.5 c 128,-1,143 - 151 -151 151 -151 153 -143 c 0,119,120 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +89 416 m 0,26,27 + 86 418 86 418 84 420 c 0,28,29 + 76 427 76 427 76 438 c 2,30,-1 + 76 672 l 2,31,32 + 76 701 76 701 90 725 c 0,33,34 + 90 726 90 726 95 735 c 0,35,36 + 100 743 100 743 109 743 c 0,37,38 + 115 743 115 743 120 738 c 0,39,40 + 125 734 125 734 155 703.5 c 128,-1,41 + 185 673 185 673 196 663 c 0,42,43 + 206 653 206 653 205 640 c 2,44,-1 + 205 467 l 2,45,46 + 205 458 205 458 197 454 c 0,47,48 + 188 448 188 448 161.5 433 c 128,-1,49 + 135 418 135 418 128 414 c 0,50,51 + 120 410 120 410 111 410 c 0,52,53 + 104 410 104 410 97 412 c 0,54,55 + 91 414 91 414 89 416 c 0,26,27 +120 751 m 0,56,57 + 118 757 118 757 120 760 c 128,-1,58 + 122 763 122 763 129 770 c 0,59,60 + 133 774 133 774 141 779 c 0,61,62 + 158 791 158 791 179 791 c 2,63,-1 + 442 791 l 1,64,-1 + 456 790 l 2,65,66 + 457 790 457 790 459 789.5 c 128,-1,67 + 461 789 461 789 463 789 c 0,68,69 + 469 788 469 788 473 784 c 0,70,71 + 478 779 478 779 476 773 c 0,72,73 + 472 765 472 765 432 674 c 0,74,75 + 427 663 427 663 415 663 c 2,76,-1 + 216 663 l 2,77,78 + 206 663 206 663 200 670 c 0,79,80 + 123 745 123 745 120 751 c 0,56,57 +554 379 m 0,81,82 + 558 375 558 375 560 368 c 0,83,84 + 561 362 561 362 560 357 c 2,85,-1 + 560 120 l 2,86,87 + 560 98 560 98 552 79 c 0,88,89 + 544 61 544 61 532 46 c 0,90,91 + 522 32 522 32 508 20 c 0,92,93 + 502 16 502 16 496 16 c 0,94,95 + 484 16 484 16 480 27 c 0,96,97 + 478 30 478 30 460 70 c 128,-1,98 + 442 110 442 110 436 124 c 0,99,100 + 431 134 431 134 431 144 c 0,101,102 + 431 170 431 170 431 192.5 c 128,-1,103 + 431 215 431 215 431 232 c 128,-1,104 + 431 249 431 249 431 271 c 0,105,106 + 431 289 431 289 431 313 c 0,107,108 + 431 321 431 321 436 327 c 0,109,110 + 471 370 471 370 487 380 c 0,111,112 + 500 389 500 389 517 389 c 0,113,114 + 520 389 520 389 525 388.5 c 128,-1,115 + 530 388 530 388 531 388 c 0,116,117 + 546 388 546 388 554 379 c 0,81,82 +120 42 m 0,118,119 + 123 48 123 48 200 123 c 0,120,121 + 206 129 206 129 216 129 c 2,122,-1 + 415 129 l 2,123,124 + 427 129 427 129 432 119 c 0,125,126 + 473 28 473 28 476 19 c 0,127,128 + 478 13 478 13 473 8 c 0,129,130 + 469 4 469 4 463 3 c 0,131,132 + 462 3 462 3 459 3 c 128,-1,133 + 456 3 456 3 456 3 c 2,134,-1 + 442 2 l 1,135,-1 + 179 2 l 2,136,137 + 158 2 158 2 141 14 c 0,138,139 + 133 19 133 19 129 23 c 0,140,141 + 122 30 122 30 120 33 c 128,-1,142 + 118 36 118 36 120 42 c 0,118,119 EndSplineSet Validated: 1 EndChar @@ -1863,84 +2538,84 @@ EndChar StartChar: o Encoding: 111 111 29 -Width: 800 +Width: 640 GlyphClass: 1 Flags: W LayerCount: 2 Fore SplineSet -270 366 m 0,0,1 - 288 377 288 377 310 377 c 2,2,-1 - 530 377 l 2,3,4 - 538 377 538 377 543 372 c 0,5,6 - 558 355 558 355 590 321 c 0,7,8 - 599 311 599 311 599 298 c 0,9,10 - 599 284 599 284 589 274 c 0,11,12 - 564 248 564 248 545 230 c 0,13,14 - 538 222 538 222 526 222 c 2,15,-1 - 307 222 l 2,16,17 - 288 222 288 222 272 231 c 0,18,19 - 267 234 267 234 196 275 c 0,20,21 - 183 282 183 282 183 298 c 0,22,23 - 183 313 183 313 196 321 c 0,24,25 - 203 325 203 325 230 341.5 c 128,-1,26 - 257 358 257 358 270 366 c 0,0,1 -698 278 m 0,27,28 - 703 273 703 273 705 265 c 0,29,30 - 706 258 706 258 706 251 c 2,31,-1 - 706 -45 l 2,32,33 - 706 -72 706 -72 695 -97 c 0,34,35 - 685 -119 685 -119 671 -138 c 0,36,37 - 658 -156 658 -156 641 -170 c 0,38,39 - 634 -175 634 -175 626 -175 c 0,40,41 - 611 -175 611 -175 605 -161 c 0,42,43 - 603 -157 603 -157 580.5 -107.5 c 128,-1,44 - 558 -58 558 -58 550 -40 c 0,45,46 - 544 -28 544 -28 544 -15 c 0,47,48 - 544 18 544 18 544 45.5 c 128,-1,49 - 544 73 544 73 544 94.5 c 128,-1,50 - 544 116 544 116 544 144 c 0,51,52 - 544 167 544 167 544 196 c 0,53,54 - 544 206 544 206 551 214 c 0,55,56 - 595 268 595 268 614 280 c 0,57,58 - 630 291 630 291 652 291 c 0,59,60 - 656 291 656 291 662 290.5 c 128,-1,61 - 668 290 668 290 669 290 c 0,62,63 - 688 289 688 289 698 278 c 0,27,28 -156 -143 m 0,64,65 - 160 -135 160 -135 255 -42 c 0,66,67 - 263 -34 263 -34 275 -34 c 2,68,-1 - 524 -34 l 2,69,70 - 539 -34 539 -34 545 -47 c 0,71,72 - 596 -161 596 -161 601 -172 c 0,73,74 - 604 -179 604 -179 597 -185 c 0,75,76 - 592 -190 592 -190 584 -191 c 0,77,78 - 583 -191 583 -191 579.5 -191.5 c 128,-1,79 - 576 -192 576 -192 575 -192 c 2,80,-1 - 558 -193 l 1,81,-1 - 229 -193 l 2,82,83 - 203 -193 203 -193 182 -178 c 0,84,85 - 172 -172 172 -172 167 -167 c 0,86,87 - 158 -158 158 -158 156 -154.5 c 128,-1,88 - 154 -151 154 -151 156 -143 c 0,64,65 -117 275 m 0,89,90 - 120 277 120 277 127 280 c 0,91,92 - 135 283 135 283 144 283 c 0,93,94 - 155 283 155 283 165 278 c 0,95,96 - 174 273 174 273 207.5 254 c 128,-1,97 - 241 235 241 235 252 228 c 0,98,99 - 262 223 262 223 262 212 c 2,100,-1 - 262 -6 l 2,101,102 - 262 -22 262 -22 250 -33 c 0,103,104 - 237 -46 237 -46 199 -84 c 128,-1,105 - 161 -122 161 -122 155 -127 c 0,106,107 - 150 -133 150 -133 142 -133 c 0,108,109 - 130 -133 130 -133 124 -123 c 256,110,111 - 118 -113 118 -113 118 -112 c 0,112,113 - 100 -81 100 -81 100 -45 c 2,114,-1 - 100 247 l 2,115,116 - 100 261 100 261 110 269 c 0,117,118 - 113 272 113 272 117 275 c 0,89,90 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +554 379 m 0,26,27 + 558 375 558 375 560 368 c 0,28,29 + 561 362 561 362 560 357 c 2,30,-1 + 560 120 l 2,31,32 + 560 98 560 98 552 79 c 0,33,34 + 544 61 544 61 532 46 c 0,35,36 + 522 32 522 32 508 20 c 0,37,38 + 502 16 502 16 496 16 c 0,39,40 + 484 16 484 16 480 27 c 0,41,42 + 478 30 478 30 460 70 c 128,-1,43 + 442 110 442 110 436 124 c 0,44,45 + 431 134 431 134 431 144 c 0,46,47 + 431 170 431 170 431 192.5 c 128,-1,48 + 431 215 431 215 431 232 c 128,-1,49 + 431 249 431 249 431 271 c 0,50,51 + 431 289 431 289 431 313 c 0,52,53 + 431 321 431 321 436 327 c 0,54,55 + 471 370 471 370 487 380 c 0,56,57 + 500 389 500 389 517 389 c 0,58,59 + 520 389 520 389 525 388.5 c 128,-1,60 + 530 388 530 388 531 388 c 0,61,62 + 546 388 546 388 554 379 c 0,26,27 +120 42 m 0,63,64 + 123 48 123 48 200 123 c 0,65,66 + 206 129 206 129 216 129 c 2,67,-1 + 415 129 l 2,68,69 + 427 129 427 129 432 119 c 0,70,71 + 473 28 473 28 476 19 c 0,72,73 + 478 13 478 13 473 8 c 0,74,75 + 469 4 469 4 463 3 c 0,76,77 + 462 3 462 3 459 3 c 128,-1,78 + 456 3 456 3 456 3 c 2,79,-1 + 442 2 l 1,80,-1 + 179 2 l 2,81,82 + 158 2 158 2 141 14 c 0,83,84 + 133 19 133 19 129 23 c 0,85,86 + 122 30 122 30 120 33 c 128,-1,87 + 118 36 118 36 120 42 c 0,63,64 +89 376 m 0,88,89 + 91 378 91 378 97 380 c 128,-1,90 + 103 382 103 382 111 383 c 0,91,92 + 120 383 120 383 128 379 c 0,93,94 + 135 375 135 375 161.5 359.5 c 128,-1,95 + 188 344 188 344 197 339 c 0,96,97 + 205 335 205 335 205 326 c 2,98,-1 + 205 151 l 2,99,100 + 205 138 205 138 196 130 c 0,101,102 + 186 120 186 120 155 89.5 c 128,-1,103 + 124 59 124 59 120 55 c 0,104,105 + 116 50 116 50 109 50 c 0,106,107 + 99 50 99 50 95 58 c 256,108,109 + 90 66 90 66 90 67 c 0,110,111 + 76 92 76 92 76 120 c 2,112,-1 + 76 354 l 2,113,114 + 76 365 76 365 84 371 c 0,115,116 + 86 374 86 374 89 376 c 0,88,89 EndSplineSet Validated: 1 EndChar @@ -1974,225 +2649,215 @@ Flags: W LayerCount: 2 Fore SplineSet -172 689 m 128,-1,1 - 172 713 172 713 155 730 c 128,-1,2 - 138 747 138 747 114 747 c 128,-1,3 - 90 747 90 747 73 730 c 128,-1,4 - 56 713 56 713 56 689 c 128,-1,5 - 56 665 56 665 73 648 c 128,-1,6 - 90 631 90 631 114 631 c 128,-1,7 - 138 631 138 631 155 648 c 128,-1,0 - 172 665 172 665 172 689 c 128,-1,1 -223 689 m 128,-1,9 - 223 644 223 644 191 612 c 128,-1,10 - 159 580 159 580 114 580 c 128,-1,11 - 69 580 69 580 37 612 c 128,-1,12 - 5 644 5 644 5 689 c 128,-1,13 - 5 734 5 734 37 766 c 128,-1,14 - 69 798 69 798 114 798 c 128,-1,15 - 159 798 159 798 191 766 c 128,-1,8 - 223 734 223 734 223 689 c 128,-1,9 +160 709 m 0,0,1 + 160 730 160 730 147 742 c 0,2,3 + 133 755 133 755 114 755 c 0,4,5 + 93 755 93 755 81 742 c 0,6,7 + 68 728 68 728 68 709 c 0,8,9 + 68 688 68 688 81 676 c 0,10,11 + 95 663 95 663 114 663 c 128,-1,12 + 133 663 133 663 146.5 676.5 c 128,-1,13 + 160 690 160 690 160 709 c 0,0,1 +201 709 m 0,14,15 + 201 671 201 671 176 647 c 0,16,17 + 150 622 150 622 114 622 c 128,-1,18 + 78 622 78 622 52 648 c 0,19,20 + 27 673 27 673 27 709 c 0,21,22 + 27 747 27 747 52 771 c 0,23,24 + 78 796 78 796 114 796 c 128,-1,25 + 150 796 150 796 175.5 770.5 c 128,-1,26 + 201 745 201 745 201 709 c 0,14,15 EndSplineSet Validated: 1 EndChar StartChar: d Encoding: 100 100 32 -Width: 800 +Width: 640 Flags: W -HStem: -193 159<243.48 548.143> 222 155<252.811 557.993> -VStem: 100 162<-42.5625 234.938> 544 162<-74.7422 231.322 368.678 404 615 674.742> LayerCount: 2 Fore SplineSet -698 322 m 0,0,1 - 687 310 687 310 669 310 c 0,2,3 - 666 310 666 310 662 310 c 0,4,5 - 656 309 656 309 652 309 c 0,6,7 - 630 309 630 309 614 320 c 0,8,9 - 602 327 602 327 551 386 c 0,10,11 - 544 394 544 394 544 404 c 2,12,13 - 544 404 544 404 544 456 c 1,14,-1 - 544 506 l 1,15,-1 - 544 554 l 1,16,-1 - 544 615 l 2,17,18 - 544 628 544 628 550 640 c 0,19,20 - 558 658 558 658 580.5 707.5 c 128,-1,21 - 603 757 603 757 605 761 c 0,22,23 - 611 775 611 775 626 775 c 0,24,25 - 634 775 634 775 641 770 c 0,26,27 - 657 757 657 757 671 738 c 128,-1,28 - 685 719 685 719 695 697 c 0,29,30 - 706 672 706 672 706 645 c 2,31,32 - 706 645 706 645 706 349 c 2,33,34 - 706 339 706 339 705 335 c 0,35,36 - 703 327 703 327 698 322 c 0,0,1 -270 366 m 0,37,38 - 288 377 288 377 310 377 c 2,39,-1 - 530 377 l 2,40,41 - 538 377 538 377 543 372 c 0,42,43 - 558 355 558 355 590 321 c 0,44,45 - 599 311 599 311 599 298 c 0,46,47 - 599 284 599 284 589 274 c 0,48,49 - 564 248 564 248 545 230 c 0,50,51 - 538 222 538 222 526 222 c 2,52,-1 - 307 222 l 2,53,54 - 288 222 288 222 272 231 c 0,55,56 - 267 234 267 234 196 275 c 0,57,58 - 183 282 183 282 183 298 c 0,59,60 - 183 313 183 313 196 321 c 0,61,62 - 203 325 203 325 230 341.5 c 128,-1,63 - 257 358 257 358 270 366 c 0,37,38 -698 278 m 0,64,65 - 703 273 703 273 705 265 c 0,66,67 - 706 258 706 258 706 251 c 2,68,-1 - 706 -45 l 2,69,70 - 706 -72 706 -72 695 -97 c 0,71,72 - 685 -119 685 -119 671 -138 c 0,73,74 - 658 -156 658 -156 641 -170 c 0,75,76 - 634 -175 634 -175 626 -175 c 0,77,78 - 611 -175 611 -175 605 -161 c 0,79,80 - 603 -157 603 -157 580.5 -107.5 c 128,-1,81 - 558 -58 558 -58 550 -40 c 0,82,83 - 544 -28 544 -28 544 -15 c 0,84,85 - 544 18 544 18 544 45.5 c 128,-1,86 - 544 73 544 73 544 94.5 c 128,-1,87 - 544 116 544 116 544 144 c 0,88,89 - 544 167 544 167 544 196 c 0,90,91 - 544 206 544 206 551 214 c 0,92,93 - 595 268 595 268 614 280 c 0,94,95 - 630 291 630 291 652 291 c 0,96,97 - 656 291 656 291 662 290.5 c 128,-1,98 - 668 290 668 290 669 290 c 0,99,100 - 688 289 688 289 698 278 c 0,64,65 -156 -143 m 0,101,102 - 160 -135 160 -135 255 -42 c 0,103,104 - 263 -34 263 -34 275 -34 c 2,105,-1 - 524 -34 l 2,106,107 - 539 -34 539 -34 545 -47 c 0,108,109 - 596 -161 596 -161 601 -172 c 0,110,111 - 604 -179 604 -179 597 -185 c 0,112,113 - 592 -190 592 -190 584 -191 c 0,114,115 - 583 -191 583 -191 579.5 -191.5 c 128,-1,116 - 576 -192 576 -192 575 -192 c 2,117,-1 - 558 -193 l 1,118,-1 - 229 -193 l 2,119,120 - 203 -193 203 -193 182 -178 c 0,121,122 - 172 -172 172 -172 167 -167 c 0,123,124 - 158 -158 158 -158 156 -154.5 c 128,-1,125 - 154 -151 154 -151 156 -143 c 0,101,102 -117 275 m 0,126,127 - 120 277 120 277 127 280 c 0,128,129 - 135 283 135 283 144 283 c 0,130,131 - 155 283 155 283 165 278 c 0,132,133 - 174 273 174 273 207.5 254 c 128,-1,134 - 241 235 241 235 252 228 c 0,135,136 - 262 223 262 223 262 212 c 2,137,-1 - 262 -6 l 2,138,139 - 262 -22 262 -22 250 -33 c 0,140,141 - 237 -46 237 -46 199 -84 c 128,-1,142 - 161 -122 161 -122 155 -127 c 0,143,144 - 150 -133 150 -133 142 -133 c 0,145,146 - 130 -133 130 -133 124 -123 c 256,147,148 - 118 -113 118 -113 118 -112 c 0,149,150 - 100 -81 100 -81 100 -45 c 2,151,-1 - 100 247 l 2,152,153 - 100 261 100 261 110 269 c 0,154,155 - 113 272 113 272 117 275 c 0,126,127 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +554 411 m 0,26,27 + 546 402 546 402 531 402 c 0,28,29 + 530 402 530 402 525 401.5 c 128,-1,30 + 520 401 520 401 517 401 c 0,31,32 + 499 401 499 401 487 410 c 0,33,34 + 472 420 472 420 436 462 c 0,35,36 + 430 468 430 468 431 477 c 0,37,38 + 431 500 431 500 431 519 c 0,39,40 + 431 541 431 541 431 558 c 128,-1,41 + 431 575 431 575 431 597 c 128,-1,42 + 431 619 431 619 431 646 c 0,43,44 + 431 656 431 656 436 666 c 0,45,46 + 462 724 462 724 480 763 c 0,47,48 + 485 773 485 773 496 773 c 0,49,50 + 502 773 502 773 508 770 c 0,51,52 + 520 761 520 761 532 744 c 0,53,54 + 546 726 546 726 552 711 c 0,55,56 + 560 693 560 693 560 673 c 0,57,58 + 560 671 560 671 560 669 c 2,59,-1 + 560 433 l 2,60,61 + 560 427 560 427 560 422 c 0,62,63 + 558 415 558 415 554 411 c 0,26,27 +554 379 m 0,64,65 + 558 375 558 375 560 368 c 0,66,67 + 561 362 561 362 560 357 c 2,68,-1 + 560 120 l 2,69,70 + 560 98 560 98 552 79 c 0,71,72 + 544 61 544 61 532 46 c 0,73,74 + 522 32 522 32 508 20 c 0,75,76 + 502 16 502 16 496 16 c 0,77,78 + 484 16 484 16 480 27 c 0,79,80 + 478 30 478 30 460 70 c 128,-1,81 + 442 110 442 110 436 124 c 0,82,83 + 431 134 431 134 431 144 c 0,84,85 + 431 170 431 170 431 192.5 c 128,-1,86 + 431 215 431 215 431 232 c 128,-1,87 + 431 249 431 249 431 271 c 0,88,89 + 431 289 431 289 431 313 c 0,90,91 + 431 321 431 321 436 327 c 0,92,93 + 471 370 471 370 487 380 c 0,94,95 + 500 389 500 389 517 389 c 0,96,97 + 520 389 520 389 525 388.5 c 128,-1,98 + 530 388 530 388 531 388 c 0,99,100 + 546 388 546 388 554 379 c 0,64,65 +120 42 m 0,101,102 + 123 48 123 48 200 123 c 0,103,104 + 206 129 206 129 216 129 c 2,105,-1 + 415 129 l 2,106,107 + 427 129 427 129 432 119 c 0,108,109 + 473 28 473 28 476 19 c 0,110,111 + 478 13 478 13 473 8 c 0,112,113 + 469 4 469 4 463 3 c 0,114,115 + 462 3 462 3 459 3 c 128,-1,116 + 456 3 456 3 456 3 c 2,117,-1 + 442 2 l 1,118,-1 + 179 2 l 2,119,120 + 158 2 158 2 141 14 c 0,121,122 + 133 19 133 19 129 23 c 0,123,124 + 122 30 122 30 120 33 c 128,-1,125 + 118 36 118 36 120 42 c 0,101,102 +89 376 m 0,126,127 + 91 378 91 378 97 380 c 128,-1,128 + 103 382 103 382 111 383 c 0,129,130 + 120 383 120 383 128 379 c 0,131,132 + 135 375 135 375 161.5 359.5 c 128,-1,133 + 188 344 188 344 197 339 c 0,134,135 + 205 335 205 335 205 326 c 2,136,-1 + 205 151 l 2,137,138 + 205 138 205 138 196 130 c 0,139,140 + 186 120 186 120 155 89.5 c 128,-1,141 + 124 59 124 59 120 55 c 0,142,143 + 116 50 116 50 109 50 c 0,144,145 + 99 50 99 50 95 58 c 256,146,147 + 90 66 90 66 90 67 c 0,148,149 + 76 92 76 92 76 120 c 2,150,-1 + 76 354 l 2,151,152 + 76 365 76 365 84 371 c 0,153,154 + 86 374 86 374 89 376 c 0,126,127 EndSplineSet Validated: 1 EndChar StartChar: t Encoding: 116 116 33 -Width: 800 +Width: 640 Flags: W LayerCount: 2 Fore SplineSet -102 322 m 0,0,1 - 97 327 97 327 95 335 c 0,2,3 - 94 342 94 342 94 349 c 2,4,-1 - 94 645 l 2,5,6 - 94 672 94 672 105 697 c 0,7,8 - 115 719 115 719 129 738 c 0,9,10 - 142 756 142 756 159 770 c 0,11,12 - 166 775 166 775 174 775 c 0,13,14 - 189 775 189 775 195 761 c 0,15,16 - 197 757 197 757 219.5 707.5 c 128,-1,17 - 242 658 242 658 250 640 c 0,18,19 - 256 628 256 628 256 615 c 2,20,-1 - 256 554 l 1,21,-1 - 256 506 l 1,22,-1 - 256 456 l 1,23,-1 - 256 404 l 2,24,25 - 256 394 256 394 249 386 c 0,26,27 - 205 332 205 332 186 320 c 0,28,29 - 170 309 170 309 148 309 c 0,30,31 - 144 309 144 309 138 309.5 c 128,-1,32 - 132 310 132 310 131 310 c 0,33,34 - 112 311 112 311 102 322 c 0,0,1 -530 366 m 0,35,36 - 543 358 543 358 570 341.5 c 128,-1,37 - 597 325 597 325 604 321 c 0,38,39 - 617 313 617 313 617 298 c 0,40,41 - 617 282 617 282 604 275 c 0,42,43 - 533 234 533 234 528 231 c 0,44,45 - 512 222 512 222 493 222 c 2,46,47 - 493 222 493 222 274 222 c 2,48,49 - 262 222 262 222 255 230 c 0,50,51 - 236 248 236 248 211 274 c 0,52,53 - 201 284 201 284 201 298 c 0,54,55 - 201 311 201 311 210 321 c 0,56,57 - 242 355 242 355 257 372 c 0,58,59 - 262 377 262 377 270 377 c 2,60,61 - 270 377 270 377 490 377 c 2,62,63 - 512 377 512 377 530 366 c 0,35,36 -102 278 m 0,64,65 - 112 289 112 289 131 290 c 0,66,67 - 132 290 132 290 138 290.5 c 128,-1,68 - 144 291 144 291 148 291 c 0,69,70 - 170 291 170 291 186 280 c 0,71,72 - 205 268 205 268 249 214 c 0,73,74 - 256 206 256 206 256 196 c 0,75,76 - 256 167 256 167 256 144 c 0,77,78 - 256 116 256 116 256 94.5 c 128,-1,79 - 256 73 256 73 256 45.5 c 128,-1,80 - 256 18 256 18 256 -15 c 0,81,82 - 256 -28 256 -28 250 -40 c 0,83,84 - 242 -58 242 -58 219.5 -107.5 c 128,-1,85 - 197 -157 197 -157 195 -161 c 0,86,87 - 189 -175 189 -175 174 -175 c 0,88,89 - 166 -175 166 -175 159 -170 c 0,90,91 - 142 -156 142 -156 129 -138 c 0,92,93 - 115 -119 115 -119 105 -97 c 0,94,95 - 94 -72 94 -72 94 -45 c 2,96,97 - 94 -45 94 -45 94 251 c 2,98,99 - 94 258 94 258 95 265 c 0,100,101 - 97 273 97 273 102 278 c 0,64,65 -644 -143 m 0,102,103 - 646 -151 646 -151 644 -154.5 c 128,-1,104 - 642 -158 642 -158 633 -167 c 0,105,106 - 628 -172 628 -172 618 -178 c 0,107,108 - 597 -193 597 -193 571 -193 c 2,109,110 - 571 -193 571 -193 242 -193 c 1,111,-1 - 225 -192 l 2,112,113 - 224 -192 224 -192 220.5 -191.5 c 128,-1,114 - 217 -191 217 -191 216 -191 c 0,115,116 - 208 -190 208 -190 203 -185 c 0,117,118 - 196 -179 196 -179 199 -172 c 0,119,120 - 204 -161 204 -161 255 -47 c 0,121,122 - 261 -34 261 -34 276 -34 c 2,123,124 - 276 -34 276 -34 525 -34 c 2,125,126 - 537 -34 537 -34 545 -42 c 0,127,128 - 640 -135 640 -135 644 -143 c 0,102,103 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +89 416 m 0,26,27 + 86 418 86 418 84 420 c 0,28,29 + 76 427 76 427 76 438 c 2,30,-1 + 76 672 l 2,31,32 + 76 701 76 701 90 725 c 0,33,34 + 90 726 90 726 95 735 c 0,35,36 + 100 743 100 743 109 743 c 0,37,38 + 115 743 115 743 120 738 c 0,39,40 + 125 734 125 734 155 703.5 c 128,-1,41 + 185 673 185 673 196 663 c 0,42,43 + 206 653 206 653 205 640 c 2,44,-1 + 205 467 l 2,45,46 + 205 458 205 458 197 454 c 0,47,48 + 188 448 188 448 161.5 433 c 128,-1,49 + 135 418 135 418 128 414 c 0,50,51 + 120 410 120 410 111 410 c 0,52,53 + 104 410 104 410 97 412 c 0,54,55 + 91 414 91 414 89 416 c 0,26,27 +120 42 m 0,56,57 + 123 48 123 48 200 123 c 0,58,59 + 206 129 206 129 216 129 c 2,60,-1 + 415 129 l 2,61,62 + 427 129 427 129 432 119 c 0,63,64 + 473 28 473 28 476 19 c 0,65,66 + 478 13 478 13 473 8 c 0,67,68 + 469 4 469 4 463 3 c 0,69,70 + 462 3 462 3 459 3 c 128,-1,71 + 456 3 456 3 456 3 c 2,72,-1 + 442 2 l 1,73,-1 + 179 2 l 2,74,75 + 158 2 158 2 141 14 c 0,76,77 + 133 19 133 19 129 23 c 0,78,79 + 122 30 122 30 120 33 c 128,-1,80 + 118 36 118 36 120 42 c 0,56,57 +89 376 m 0,81,82 + 91 378 91 378 97 380 c 128,-1,83 + 103 382 103 382 111 383 c 0,84,85 + 120 383 120 383 128 379 c 0,86,87 + 135 375 135 375 161.5 359.5 c 128,-1,88 + 188 344 188 344 197 339 c 0,89,90 + 205 335 205 335 205 326 c 2,91,-1 + 205 151 l 2,92,93 + 205 138 205 138 196 130 c 0,94,95 + 186 120 186 120 155 89.5 c 128,-1,96 + 124 59 124 59 120 55 c 0,97,98 + 116 50 116 50 109 50 c 0,99,100 + 99 50 99 50 95 58 c 256,101,102 + 90 66 90 66 90 67 c 0,103,104 + 76 92 76 92 76 120 c 2,105,-1 + 76 354 l 2,106,107 + 76 365 76 365 84 371 c 0,108,109 + 86 374 86 374 89 376 c 0,81,82 EndSplineSet Validated: 1 EndChar StartChar: asciitilde Encoding: 126 126 34 -Width: 600 +Width: 640 Flags: W HStem: -193 159<515.48 820.143> 222 155<524.811 829.993> VStem: 372 162<-42.5625 234.938> 816 162<-74.7422 231.322 368.678 404 615 674.742> @@ -2203,8 +2868,10 @@ EndChar StartChar: space Encoding: 32 32 35 -Width: 800 +Width: 640 Flags: W +HStem: -193 159<515.48 820.143> 222 155<524.811 829.993> +VStem: 372 162<-42.5625 234.938> 816 162<-74.7422 231.322 368.678 404 615 674.742> LayerCount: 2 Fore Validated: 1 @@ -2212,168 +2879,637 @@ EndChar StartChar: asterisk Encoding: 42 42 36 -Width: 800 +Width: 640 +Flags: W +LayerCount: 2 +Fore +SplineSet +359 479 m 4,0,1 + 355 473 355 473 350 473 c 6,2,-1 + 281 473 l 6,3,4 + 275 473 275 473 272 479 c 4,5,6 + 267 488 267 488 256 506 c 4,7,8 + 251 514 251 514 252 522 c 4,9,10 + 253 532 253 532 256 538 c 4,11,12 + 282 591 282 591 305 619 c 4,13,14 + 309 624 309 624 316 624 c 132,-1,15 + 323 624 323 624 326 619 c 4,16,17 + 332 610 332 610 350 579 c 132,-1,18 + 368 548 368 548 375 538 c 4,19,20 + 380 531 380 531 380 522 c 4,21,22 + 380 515 380 515 375 506 c 4,23,24 + 369 496 369 496 359 479 c 4,0,1 +209 449 m 4,25,26 + 224 458 224 458 241 458 c 6,27,-1 + 417 458 l 6,28,29 + 425 458 425 458 428 454 c 4,30,31 + 440 440 440 440 465 413 c 4,32,33 + 471 406 471 406 472 395 c 132,-1,34 + 473 384 473 384 464 375 c 4,35,36 + 446 358 446 358 429 340 c 4,37,38 + 423 334 423 334 414 334 c 6,39,-1 + 239 334 l 6,40,41 + 225 334 225 334 211 341 c 4,42,43 + 195 349 195 349 150 376 c 4,44,45 + 141 381 141 381 140 395 c 4,46,47 + 139 406 139 406 150 413 c 4,48,49 + 156 416 156 416 177.5 429.5 c 132,-1,50 + 199 443 199 443 209 449 c 4,25,26 +359 313 m 4,51,52 + 364 303 364 303 375 286 c 4,53,54 + 380 278 380 278 380 269 c 132,-1,55 + 380 260 380 260 375 254 c 4,56,57 + 340 195 340 195 326 173 c 4,58,59 + 323 167 323 167 315.5 167 c 132,-1,60 + 308 167 308 167 305 173 c 4,61,62 + 299 183 299 183 281 213 c 132,-1,63 + 263 243 263 243 256 254 c 4,64,65 + 252 261 252 261 252 270 c 132,-1,66 + 252 279 252 279 256 286 c 4,67,68 + 269 308 269 308 272 313 c 132,-1,69 + 275 318 275 318 281 318 c 6,70,-1 + 350 318 l 6,71,72 + 356 318 356 318 359 313 c 4,51,52 +554 411 m 4,73,74 + 546 402 546 402 531 402 c 4,75,76 + 530 402 530 402 525 401.5 c 132,-1,77 + 520 401 520 401 517 401 c 4,78,79 + 499 401 499 401 487 410 c 4,80,81 + 472 420 472 420 436 462 c 4,82,83 + 430 468 430 468 431 477 c 4,84,85 + 431 500 431 500 431 519 c 4,86,87 + 431 541 431 541 431 558 c 132,-1,88 + 431 575 431 575 431 597 c 132,-1,89 + 431 619 431 619 431 646 c 4,90,91 + 431 656 431 656 436 666 c 4,92,93 + 462 724 462 724 480 763 c 4,94,95 + 485 773 485 773 496 773 c 4,96,97 + 502 773 502 773 508 770 c 4,98,99 + 520 761 520 761 532 744 c 4,100,101 + 546 726 546 726 552 711 c 4,102,103 + 560 693 560 693 560 673 c 4,104,105 + 560 671 560 671 560 669 c 6,106,-1 + 560 433 l 6,107,108 + 560 427 560 427 560 422 c 4,109,110 + 558 415 558 415 554 411 c 4,73,74 +89 416 m 4,111,112 + 86 418 86 418 84 420 c 4,113,114 + 76 427 76 427 76 438 c 6,115,-1 + 76 672 l 6,116,117 + 76 701 76 701 90 725 c 4,118,119 + 90 726 90 726 95 735 c 4,120,121 + 100 743 100 743 109 743 c 4,122,123 + 115 743 115 743 120 738 c 4,124,125 + 125 734 125 734 155 703.5 c 132,-1,126 + 185 673 185 673 196 663 c 4,127,128 + 206 653 206 653 205 640 c 6,129,-1 + 205 467 l 6,130,131 + 205 458 205 458 197 454 c 4,132,133 + 188 448 188 448 161.5 433 c 132,-1,134 + 135 418 135 418 128 414 c 4,135,136 + 120 410 120 410 111 410 c 4,137,138 + 104 410 104 410 97 412 c 4,139,140 + 91 414 91 414 89 416 c 4,111,112 +120 751 m 4,141,142 + 118 757 118 757 120 760 c 132,-1,143 + 122 763 122 763 129 770 c 4,144,145 + 133 774 133 774 141 779 c 4,146,147 + 158 791 158 791 179 791 c 6,148,-1 + 442 791 l 5,149,-1 + 456 790 l 6,150,151 + 457 790 457 790 459 789.5 c 132,-1,152 + 461 789 461 789 463 789 c 4,153,154 + 469 788 469 788 473 784 c 4,155,156 + 478 779 478 779 476 773 c 4,157,158 + 472 765 472 765 432 674 c 4,159,160 + 427 663 427 663 415 663 c 6,161,-1 + 216 663 l 6,162,163 + 206 663 206 663 200 670 c 4,164,165 + 123 745 123 745 120 751 c 4,141,142 +554 379 m 4,166,167 + 558 375 558 375 560 368 c 4,168,169 + 561 362 561 362 560 357 c 6,170,-1 + 560 120 l 6,171,172 + 560 98 560 98 552 79 c 4,173,174 + 544 61 544 61 532 46 c 4,175,176 + 522 32 522 32 508 20 c 4,177,178 + 502 16 502 16 496 16 c 4,179,180 + 484 16 484 16 480 27 c 4,181,182 + 478 30 478 30 460 70 c 132,-1,183 + 442 110 442 110 436 124 c 4,184,185 + 431 134 431 134 431 144 c 4,186,187 + 431 170 431 170 431 192.5 c 132,-1,188 + 431 215 431 215 431 232 c 132,-1,189 + 431 249 431 249 431 271 c 4,190,191 + 431 289 431 289 431 313 c 4,192,193 + 431 321 431 321 436 327 c 4,194,195 + 471 370 471 370 487 380 c 4,196,197 + 500 389 500 389 517 389 c 4,198,199 + 520 389 520 389 525 388.5 c 132,-1,200 + 530 388 530 388 531 388 c 4,201,202 + 546 388 546 388 554 379 c 4,166,167 +120 42 m 4,203,204 + 123 48 123 48 200 123 c 4,205,206 + 206 129 206 129 216 129 c 6,207,-1 + 415 129 l 6,208,209 + 427 129 427 129 432 119 c 4,210,211 + 473 28 473 28 476 19 c 4,212,213 + 478 13 478 13 473 8 c 4,214,215 + 469 4 469 4 463 3 c 4,216,217 + 462 3 462 3 459 3 c 132,-1,218 + 456 3 456 3 456 3 c 6,219,-1 + 442 2 l 5,220,-1 + 179 2 l 6,221,222 + 158 2 158 2 141 14 c 4,223,224 + 133 19 133 19 129 23 c 4,225,226 + 122 30 122 30 120 33 c 132,-1,227 + 118 36 118 36 120 42 c 4,203,204 +89 376 m 4,228,229 + 91 378 91 378 97 380 c 132,-1,230 + 103 382 103 382 111 383 c 4,231,232 + 120 383 120 383 128 379 c 4,233,234 + 135 375 135 375 161.5 359.5 c 132,-1,235 + 188 344 188 344 197 339 c 4,236,237 + 205 335 205 335 205 326 c 6,238,-1 + 205 151 l 6,239,240 + 205 138 205 138 196 130 c 4,241,242 + 186 120 186 120 155 89.5 c 132,-1,243 + 124 59 124 59 120 55 c 4,244,245 + 116 50 116 50 109 50 c 4,246,247 + 99 50 99 50 95 58 c 260,248,249 + 90 66 90 66 90 67 c 4,250,251 + 76 92 76 92 76 120 c 6,252,-1 + 76 354 l 6,253,254 + 76 365 76 365 84 371 c 4,255,256 + 86 374 86 374 89 376 c 4,228,229 +EndSplineSet +Validated: 2049 +EndChar + +StartChar: f +Encoding: 102 102 37 +Width: 640 +Flags: W +LayerCount: 2 +Fore +SplineSet +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +89 416 m 0,26,27 + 86 418 86 418 84 420 c 0,28,29 + 76 427 76 427 76 438 c 2,30,-1 + 76 672 l 2,31,32 + 76 701 76 701 90 725 c 0,33,34 + 90 726 90 726 95 735 c 0,35,36 + 100 743 100 743 109 743 c 0,37,38 + 115 743 115 743 120 738 c 0,39,40 + 125 734 125 734 155 703.5 c 128,-1,41 + 185 673 185 673 196 663 c 0,42,43 + 206 653 206 653 205 640 c 2,44,-1 + 205 467 l 2,45,46 + 205 458 205 458 197 454 c 0,47,48 + 188 448 188 448 161.5 433 c 128,-1,49 + 135 418 135 418 128 414 c 0,50,51 + 120 410 120 410 111 410 c 0,52,53 + 104 410 104 410 97 412 c 0,54,55 + 91 414 91 414 89 416 c 0,26,27 +120 751 m 0,56,57 + 118 757 118 757 120 760 c 128,-1,58 + 122 763 122 763 129 770 c 0,59,60 + 133 774 133 774 141 779 c 0,61,62 + 158 791 158 791 179 791 c 2,63,-1 + 442 791 l 1,64,-1 + 456 790 l 2,65,66 + 457 790 457 790 459 789.5 c 128,-1,67 + 461 789 461 789 463 789 c 0,68,69 + 469 788 469 788 473 784 c 0,70,71 + 478 779 478 779 476 773 c 0,72,73 + 472 765 472 765 432 674 c 0,74,75 + 427 663 427 663 415 663 c 2,76,-1 + 216 663 l 2,77,78 + 206 663 206 663 200 670 c 0,79,80 + 123 745 123 745 120 751 c 0,56,57 +89 376 m 0,81,82 + 91 378 91 378 97 380 c 128,-1,83 + 103 382 103 382 111 383 c 0,84,85 + 120 383 120 383 128 379 c 0,86,87 + 135 375 135 375 161.5 359.5 c 128,-1,88 + 188 344 188 344 197 339 c 0,89,90 + 205 335 205 335 205 326 c 2,91,-1 + 205 151 l 2,92,93 + 205 138 205 138 196 130 c 0,94,95 + 186 120 186 120 155 89.5 c 128,-1,96 + 124 59 124 59 120 55 c 0,97,98 + 116 50 116 50 109 50 c 0,99,100 + 99 50 99 50 95 58 c 256,101,102 + 90 66 90 66 90 67 c 0,103,104 + 76 92 76 92 76 120 c 2,105,-1 + 76 354 l 2,106,107 + 76 365 76 365 84 371 c 0,108,109 + 86 374 86 374 89 376 c 0,81,82 +EndSplineSet +Validated: 1 +EndChar + +StartChar: e +Encoding: 101 101 38 +Width: 640 +Flags: W +LayerCount: 2 +Fore +SplineSet +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +89 416 m 0,26,27 + 86 418 86 418 84 420 c 0,28,29 + 76 427 76 427 76 438 c 2,30,-1 + 76 672 l 2,31,32 + 76 701 76 701 90 725 c 0,33,34 + 90 726 90 726 95 735 c 0,35,36 + 100 743 100 743 109 743 c 0,37,38 + 115 743 115 743 120 738 c 0,39,40 + 125 734 125 734 155 703.5 c 128,-1,41 + 185 673 185 673 196 663 c 0,42,43 + 206 653 206 653 205 640 c 2,44,-1 + 205 467 l 2,45,46 + 205 458 205 458 197 454 c 0,47,48 + 188 448 188 448 161.5 433 c 128,-1,49 + 135 418 135 418 128 414 c 0,50,51 + 120 410 120 410 111 410 c 0,52,53 + 104 410 104 410 97 412 c 0,54,55 + 91 414 91 414 89 416 c 0,26,27 +120 751 m 0,56,57 + 118 757 118 757 120 760 c 128,-1,58 + 122 763 122 763 129 770 c 0,59,60 + 133 774 133 774 141 779 c 0,61,62 + 158 791 158 791 179 791 c 2,63,-1 + 442 791 l 1,64,-1 + 456 790 l 2,65,66 + 457 790 457 790 459 789.5 c 128,-1,67 + 461 789 461 789 463 789 c 0,68,69 + 469 788 469 788 473 784 c 0,70,71 + 478 779 478 779 476 773 c 0,72,73 + 472 765 472 765 432 674 c 0,74,75 + 427 663 427 663 415 663 c 2,76,-1 + 216 663 l 2,77,78 + 206 663 206 663 200 670 c 0,79,80 + 123 745 123 745 120 751 c 0,56,57 +120 42 m 0,81,82 + 123 48 123 48 200 123 c 0,83,84 + 206 129 206 129 216 129 c 2,85,-1 + 415 129 l 2,86,87 + 427 129 427 129 432 119 c 0,88,89 + 473 28 473 28 476 19 c 0,90,91 + 478 13 478 13 473 8 c 0,92,93 + 469 4 469 4 463 3 c 0,94,95 + 462 3 462 3 459 3 c 128,-1,96 + 456 3 456 3 456 3 c 2,97,-1 + 442 2 l 1,98,-1 + 179 2 l 2,99,100 + 158 2 158 2 141 14 c 0,101,102 + 133 19 133 19 129 23 c 0,103,104 + 122 30 122 30 120 33 c 128,-1,105 + 118 36 118 36 120 42 c 0,81,82 +89 376 m 0,106,107 + 91 378 91 378 97 380 c 128,-1,108 + 103 382 103 382 111 383 c 0,109,110 + 120 383 120 383 128 379 c 0,111,112 + 135 375 135 375 161.5 359.5 c 128,-1,113 + 188 344 188 344 197 339 c 0,114,115 + 205 335 205 335 205 326 c 2,116,-1 + 205 151 l 2,117,118 + 205 138 205 138 196 130 c 0,119,120 + 186 120 186 120 155 89.5 c 128,-1,121 + 124 59 124 59 120 55 c 0,122,123 + 116 50 116 50 109 50 c 0,124,125 + 99 50 99 50 95 58 c 256,126,127 + 90 66 90 66 90 67 c 0,128,129 + 76 92 76 92 76 120 c 2,130,-1 + 76 354 l 2,131,132 + 76 365 76 365 84 371 c 0,133,134 + 86 374 86 374 89 376 c 0,106,107 +EndSplineSet +Validated: 1 +EndChar + +StartChar: q +Encoding: 113 113 39 +Width: 640 +Flags: W +LayerCount: 2 +Fore +SplineSet +463 -4 m 0,0,1 + 483 -4 483 -4 495 -13 c 2,2,-1 + 588 -82 l 2,3,4 + 593 -86 593 -86 595 -91 c 0,5,6 + 599 -109 599 -109 605 -145 c 0,7,8 + 607 -156 607 -156 602 -165 c 0,9,10 + 596 -173 596 -173 585 -177 c 0,11,12 + 576 -180 576 -180 532 -187 c 0,13,14 + 525 -188 525 -188 515 -181 c 2,15,-1 + 428 -118 l 2,16,17 + 412 -106 412 -106 408 -97 c 0,18,19 + 380 -46 380 -46 374 -35 c 0,20,21 + 369 -24 369 -24 375.5 -14 c 128,-1,22 + 382 -4 382 -4 394 -4 c 0,23,24 + 400 -4 400 -4 425 -4 c 0,25,26 + 451 -4 451 -4 463 -4 c 0,0,1 +554 411 m 0,27,28 + 546 402 546 402 531 402 c 0,29,30 + 530 402 530 402 525 401.5 c 128,-1,31 + 520 401 520 401 517 401 c 0,32,33 + 499 401 499 401 487 410 c 0,34,35 + 472 420 472 420 436 462 c 0,36,37 + 430 468 430 468 431 477 c 0,38,39 + 431 500 431 500 431 519 c 0,40,41 + 431 541 431 541 431 558 c 128,-1,42 + 431 575 431 575 431 597 c 128,-1,43 + 431 619 431 619 431 646 c 0,44,45 + 431 656 431 656 436 666 c 0,46,47 + 462 724 462 724 480 763 c 0,48,49 + 485 773 485 773 496 773 c 0,50,51 + 502 773 502 773 508 770 c 0,52,53 + 520 761 520 761 532 744 c 0,54,55 + 546 726 546 726 552 711 c 0,56,57 + 560 693 560 693 560 673 c 0,58,59 + 560 671 560 671 560 669 c 2,60,-1 + 560 433 l 2,61,62 + 560 427 560 427 560 422 c 0,63,64 + 558 415 558 415 554 411 c 0,27,28 +89 416 m 0,65,66 + 86 418 86 418 84 420 c 0,67,68 + 76 427 76 427 76 438 c 2,69,-1 + 76 672 l 2,70,71 + 76 701 76 701 90 725 c 0,72,73 + 90 726 90 726 95 735 c 0,74,75 + 100 743 100 743 109 743 c 0,76,77 + 115 743 115 743 120 738 c 0,78,79 + 125 734 125 734 155 703.5 c 128,-1,80 + 185 673 185 673 196 663 c 0,81,82 + 206 653 206 653 205 640 c 2,83,-1 + 205 467 l 2,84,85 + 205 458 205 458 197 454 c 0,86,87 + 188 448 188 448 161.5 433 c 128,-1,88 + 135 418 135 418 128 414 c 0,89,90 + 120 410 120 410 111 410 c 0,91,92 + 104 410 104 410 97 412 c 0,93,94 + 91 414 91 414 89 416 c 0,65,66 +120 751 m 0,95,96 + 118 757 118 757 120 760 c 128,-1,97 + 122 763 122 763 129 770 c 0,98,99 + 133 774 133 774 141 779 c 0,100,101 + 158 791 158 791 179 791 c 2,102,-1 + 442 791 l 1,103,-1 + 456 790 l 2,104,105 + 457 790 457 790 459 789.5 c 128,-1,106 + 461 789 461 789 463 789 c 0,107,108 + 469 788 469 788 473 784 c 0,109,110 + 478 779 478 779 476 773 c 0,111,112 + 472 765 472 765 432 674 c 0,113,114 + 427 663 427 663 415 663 c 2,115,-1 + 216 663 l 2,116,117 + 206 663 206 663 200 670 c 0,118,119 + 123 745 123 745 120 751 c 0,95,96 +554 379 m 0,120,121 + 558 375 558 375 560 368 c 0,122,123 + 561 362 561 362 560 357 c 2,124,-1 + 560 120 l 2,125,126 + 560 98 560 98 552 79 c 0,127,128 + 544 61 544 61 532 46 c 0,129,130 + 522 32 522 32 508 20 c 0,131,132 + 502 16 502 16 496 16 c 0,133,134 + 484 16 484 16 480 27 c 0,135,136 + 478 30 478 30 460 70 c 128,-1,137 + 442 110 442 110 436 124 c 0,138,139 + 431 134 431 134 431 144 c 0,140,141 + 431 170 431 170 431 192.5 c 128,-1,142 + 431 215 431 215 431 232 c 128,-1,143 + 431 249 431 249 431 271 c 0,144,145 + 431 289 431 289 431 313 c 0,146,147 + 431 321 431 321 436 327 c 0,148,149 + 471 370 471 370 487 380 c 0,150,151 + 500 389 500 389 517 389 c 0,152,153 + 520 389 520 389 525 388.5 c 128,-1,154 + 530 388 530 388 531 388 c 0,155,156 + 546 388 546 388 554 379 c 0,120,121 +120 42 m 0,157,158 + 123 48 123 48 200 123 c 0,159,160 + 206 129 206 129 216 129 c 2,161,-1 + 415 129 l 2,162,163 + 427 129 427 129 432 119 c 0,164,165 + 473 28 473 28 476 19 c 0,166,167 + 478 13 478 13 473 8 c 0,168,169 + 469 4 469 4 463 3 c 0,170,171 + 462 3 462 3 459 3 c 128,-1,172 + 456 3 456 3 456 3 c 2,173,-1 + 442 2 l 1,174,-1 + 179 2 l 2,175,176 + 158 2 158 2 141 14 c 0,177,178 + 133 19 133 19 129 23 c 0,179,180 + 122 30 122 30 120 33 c 128,-1,181 + 118 36 118 36 120 42 c 0,157,158 +89 376 m 0,182,183 + 91 378 91 378 97 380 c 128,-1,184 + 103 382 103 382 111 383 c 0,185,186 + 120 383 120 383 128 379 c 0,187,188 + 135 375 135 375 161.5 359.5 c 128,-1,189 + 188 344 188 344 197 339 c 0,190,191 + 205 335 205 335 205 326 c 2,192,-1 + 205 151 l 2,193,194 + 205 138 205 138 196 130 c 0,195,196 + 186 120 186 120 155 89.5 c 128,-1,197 + 124 59 124 59 120 55 c 0,198,199 + 116 50 116 50 109 50 c 0,200,201 + 99 50 99 50 95 58 c 256,202,203 + 90 66 90 66 90 67 c 0,204,205 + 76 92 76 92 76 120 c 2,206,-1 + 76 354 l 2,207,208 + 76 365 76 365 84 371 c 0,209,210 + 86 374 86 374 89 376 c 0,182,183 +EndSplineSet +Validated: 1 +EndChar + +StartChar: p +Encoding: 112 112 40 +Width: 640 Flags: W LayerCount: 2 Fore SplineSet -451 403 m 4,0,1 - 447 396 447 396 440 396 c 6,2,-1 - 354 396 l 6,3,4 - 347 396 347 396 343 403 c 4,5,6 - 332 421 332 421 323 437 c 4,7,8 - 318 446 318 446 318 457 c 132,-1,9 - 318 468 318 468 323 477 c 4,10,11 - 371 557 371 557 384 578 c 4,12,13 - 388 585 388 585 397 585 c 132,-1,14 - 406 585 406 585 410 578 c 4,15,16 - 417 567 417 567 440 528.5 c 132,-1,17 - 463 490 463 490 471 477 c 4,18,19 - 477 468 477 468 477 457.5 c 132,-1,20 - 477 447 477 447 471 437 c 4,21,22 - 458 415 458 415 451 403 c 4,0,1 -264 366 m 4,23,24 - 282 377 282 377 304 377 c 6,25,-1 - 524 377 l 6,26,27 - 531 377 531 377 537 372 c 4,28,29 - 552 355 552 355 584 321 c 4,30,31 - 593 311 593 311 593 298 c 4,32,33 - 593 284 593 284 583 274 c 4,34,35 - 558 248 558 248 539 230 c 4,36,37 - 532 222 532 222 520 222 c 6,38,-1 - 301 222 l 6,39,40 - 282 222 282 222 266 231 c 4,41,42 - 261 234 261 234 190 275 c 4,43,44 - 177 282 177 282 177 298 c 4,45,46 - 177 313 177 313 190 321 c 4,47,48 - 197 325 197 325 224 341.5 c 132,-1,49 - 251 358 251 358 264 366 c 4,23,24 -451 196 m 4,50,51 - 458 184 458 184 471 162 c 4,52,53 - 477 152 477 152 477 141.5 c 132,-1,54 - 477 131 477 131 471 122 c 4,55,56 - 427 48 427 48 410 21 c 4,57,58 - 406 14 406 14 397 14 c 132,-1,59 - 388 14 388 14 384 21 c 4,60,61 - 377 33 377 33 354 71 c 132,-1,62 - 331 109 331 109 323 122 c 4,63,64 - 318 131 318 131 318 142 c 132,-1,65 - 318 153 318 153 323 162 c 4,66,67 - 339 189 339 189 343 196 c 4,68,69 - 347 202 347 202 354 202 c 6,70,-1 - 440 202 l 6,71,72 - 447 202 447 202 451 196 c 4,50,51 -695 319 m 0,73,74 - 685 308 685 308 666 307 c 0,75,76 - 665 307 665 307 659 306.5 c 128,-1,77 - 653 306 653 306 649 306 c 0,78,79 - 627 306 627 306 611 317 c 0,80,81 - 592 329 592 329 548 382 c 0,82,83 - 541 390 541 390 541 401 c 0,84,85 - 541 430 541 430 541 453 c 0,86,87 - 541 481 541 481 541 502.5 c 128,-1,88 - 541 524 541 524 541 551.5 c 128,-1,89 - 541 579 541 579 541 612 c 0,90,91 - 541 625 541 625 547 637 c 0,92,93 - 580 710 580 710 602 758 c 0,94,95 - 608 771 608 771 623 771 c 0,96,97 - 631 771 631 771 638 767 c 0,98,99 - 655 753 655 753 668 735 c 0,100,101 - 682 716 682 716 692 694 c 0,102,103 - 703 669 703 669 703 641 c 2,104,-1 - 703 346 l 2,105,106 - 703 339 703 339 702 332 c 0,107,108 - 700 324 700 324 695 319 c 0,73,74 -114 325 m 0,109,110 - 110 327 110 327 107 330 c 0,111,112 - 97 339 97 339 97 352 c 2,113,-1 - 97 645 l 2,114,115 - 97 681 97 681 115 711 c 0,116,117 - 115 712 115 712 121 723 c 0,118,119 - 127 733 127 733 139 733 c 0,120,121 - 147 733 147 733 152 727 c 0,122,123 - 158 722 158 722 196 684 c 128,-1,124 - 234 646 234 646 247 633 c 0,125,126 - 259 621 259 621 259 605 c 2,127,-1 - 259 388 l 2,128,129 - 259 377 259 377 249 372 c 0,130,131 - 238 365 238 365 204.5 346 c 128,-1,132 - 171 327 171 327 162 322 c 0,133,134 - 152 317 152 317 141 317 c 0,135,136 - 132 317 132 317 124 320 c 0,137,138 - 117 323 117 323 114 325 c 0,109,110 -153 743 m 0,139,140 - 151 751 151 751 153 754.5 c 128,-1,141 - 155 758 155 758 164 767 c 0,142,143 - 169 772 169 772 179 778 c 0,144,145 - 200 793 200 793 226 793 c 2,146,-1 - 555 793 l 1,147,-1 - 572 792 l 2,148,149 - 573 792 573 792 576 791.5 c 128,-1,150 - 579 791 579 791 581 791 c 0,151,152 - 589 790 589 790 594 785 c 0,153,154 - 600 779 600 779 598 771 c 0,155,156 - 593 761 593 761 542 647 c 0,157,158 - 536 633 536 633 521 633 c 2,159,-1 - 272 633 l 2,160,161 - 260 633 260 633 252 642 c 0,162,163 - 157 735 157 735 153 743 c 0,139,140 -695 278 m 0,164,165 - 700 273 700 273 702 265 c 0,166,167 - 703 258 703 258 703 251 c 2,168,-1 - 703 -45 l 2,169,170 - 703 -72 703 -72 692 -97 c 0,171,172 - 682 -119 682 -119 668 -138 c 0,173,174 - 655 -156 655 -156 638 -170 c 0,175,176 - 631 -175 631 -175 623 -175 c 0,177,178 - 608 -175 608 -175 602 -161 c 0,179,180 - 600 -157 600 -157 577.5 -107.5 c 128,-1,181 - 555 -58 555 -58 547 -40 c 0,182,183 - 541 -28 541 -28 541 -15 c 0,184,185 - 541 18 541 18 541 45.5 c 128,-1,186 - 541 73 541 73 541 94.5 c 128,-1,187 - 541 116 541 116 541 144 c 0,188,189 - 541 167 541 167 541 196 c 0,190,191 - 541 206 541 206 548 214 c 0,192,193 - 592 268 592 268 611 280 c 0,194,195 - 627 291 627 291 649 291 c 0,196,197 - 653 291 653 291 659 290.5 c 128,-1,198 - 665 290 665 290 666 290 c 0,199,200 - 685 289 685 289 695 278 c 0,164,165 -153 -143 m 0,201,202 - 157 -135 157 -135 252 -42 c 0,203,204 - 260 -34 260 -34 272 -34 c 2,205,-1 - 521 -34 l 2,206,207 - 536 -34 536 -34 542 -47 c 0,208,209 - 593 -161 593 -161 598 -172 c 0,210,211 - 600 -179 600 -179 594 -185 c 0,212,213 - 589 -190 589 -190 581 -191 c 0,214,215 - 580 -191 580 -191 576.5 -191.5 c 128,-1,216 - 573 -192 573 -192 572 -192 c 2,217,-1 - 555 -193 l 1,218,-1 - 226 -193 l 2,219,220 - 200 -193 200 -193 179 -178 c 0,221,222 - 169 -172 169 -172 164 -167 c 0,223,224 - 155 -158 155 -158 153 -154.5 c 128,-1,225 - 151 -151 151 -151 153 -143 c 0,201,202 -114 275 m 0,226,227 - 117 277 117 277 124 280 c 0,228,229 - 132 283 132 283 141 283 c 0,230,231 - 152 283 152 283 162 278 c 0,232,233 - 171 273 171 273 204.5 254 c 128,-1,234 - 238 235 238 235 249 228 c 0,235,236 - 259 223 259 223 259 212 c 2,237,-1 - 259 -6 l 2,238,239 - 259 -22 259 -22 247 -33 c 0,240,241 - 234 -46 234 -46 196 -84 c 128,-1,242 - 158 -122 158 -122 152 -127 c 0,243,244 - 147 -133 147 -133 139 -133 c 0,245,246 - 127 -133 127 -133 121 -123 c 256,247,248 - 115 -113 115 -113 115 -112 c 0,249,250 - 97 -81 97 -81 97 -45 c 2,251,-1 - 97 247 l 2,252,253 - 97 261 97 261 107 269 c 0,254,255 - 110 272 110 272 114 275 c 0,226,227 +209 449 m 0,0,1 + 224 458 224 458 241 458 c 2,2,-1 + 417 458 l 2,3,4 + 425 458 425 458 428 454 c 0,5,6 + 440 440 440 440 465 413 c 0,7,8 + 471 406 471 406 472 395 c 128,-1,9 + 473 384 473 384 464 375 c 0,10,11 + 446 358 446 358 429 340 c 0,12,13 + 423 334 423 334 414 334 c 2,14,-1 + 239 334 l 2,15,16 + 225 334 225 334 211 341 c 0,17,18 + 195 349 195 349 150 376 c 0,19,20 + 141 381 141 381 140 395 c 0,21,22 + 139 406 139 406 150 413 c 0,23,24 + 156 416 156 416 177.5 429.5 c 128,-1,25 + 199 443 199 443 209 449 c 0,0,1 +463 -4 m 0,26,27 + 483 -4 483 -4 495 -13 c 2,28,-1 + 588 -82 l 2,29,30 + 593 -86 593 -86 595 -91 c 0,31,32 + 599 -109 599 -109 605 -145 c 0,33,34 + 607 -156 607 -156 602 -165 c 0,35,36 + 596 -173 596 -173 585 -177 c 0,37,38 + 576 -180 576 -180 532 -187 c 0,39,40 + 525 -188 525 -188 515 -181 c 2,41,-1 + 428 -118 l 2,42,43 + 412 -106 412 -106 408 -97 c 0,44,45 + 380 -46 380 -46 374 -35 c 0,46,47 + 369 -24 369 -24 375.5 -14 c 128,-1,48 + 382 -4 382 -4 394 -4 c 0,49,50 + 400 -4 400 -4 425 -4 c 0,51,52 + 451 -4 451 -4 463 -4 c 0,26,27 +554 411 m 0,53,54 + 546 402 546 402 531 402 c 0,55,56 + 530 402 530 402 525 401.5 c 128,-1,57 + 520 401 520 401 517 401 c 0,58,59 + 499 401 499 401 487 410 c 0,60,61 + 472 420 472 420 436 462 c 0,62,63 + 430 468 430 468 431 477 c 0,64,65 + 431 500 431 500 431 519 c 0,66,67 + 431 541 431 541 431 558 c 128,-1,68 + 431 575 431 575 431 597 c 128,-1,69 + 431 619 431 619 431 646 c 0,70,71 + 431 656 431 656 436 666 c 0,72,73 + 462 724 462 724 480 763 c 0,74,75 + 485 773 485 773 496 773 c 0,76,77 + 502 773 502 773 508 770 c 0,78,79 + 520 761 520 761 532 744 c 0,80,81 + 546 726 546 726 552 711 c 0,82,83 + 560 693 560 693 560 673 c 0,84,85 + 560 671 560 671 560 669 c 2,86,-1 + 560 433 l 2,87,88 + 560 427 560 427 560 422 c 0,89,90 + 558 415 558 415 554 411 c 0,53,54 +89 416 m 0,91,92 + 86 418 86 418 84 420 c 0,93,94 + 76 427 76 427 76 438 c 2,95,-1 + 76 672 l 2,96,97 + 76 701 76 701 90 725 c 0,98,99 + 90 726 90 726 95 735 c 0,100,101 + 100 743 100 743 109 743 c 0,102,103 + 115 743 115 743 120 738 c 0,104,105 + 125 734 125 734 155 703.5 c 128,-1,106 + 185 673 185 673 196 663 c 0,107,108 + 206 653 206 653 205 640 c 2,109,-1 + 205 467 l 2,110,111 + 205 458 205 458 197 454 c 0,112,113 + 188 448 188 448 161.5 433 c 128,-1,114 + 135 418 135 418 128 414 c 0,115,116 + 120 410 120 410 111 410 c 0,117,118 + 104 410 104 410 97 412 c 0,119,120 + 91 414 91 414 89 416 c 0,91,92 +120 751 m 0,121,122 + 118 757 118 757 120 760 c 128,-1,123 + 122 763 122 763 129 770 c 0,124,125 + 133 774 133 774 141 779 c 0,126,127 + 158 791 158 791 179 791 c 2,128,-1 + 442 791 l 1,129,-1 + 456 790 l 2,130,131 + 457 790 457 790 459 789.5 c 128,-1,132 + 461 789 461 789 463 789 c 0,133,134 + 469 788 469 788 473 784 c 0,135,136 + 478 779 478 779 476 773 c 0,137,138 + 472 765 472 765 432 674 c 0,139,140 + 427 663 427 663 415 663 c 2,141,-1 + 216 663 l 2,142,143 + 206 663 206 663 200 670 c 0,144,145 + 123 745 123 745 120 751 c 0,121,122 +554 379 m 0,146,147 + 558 375 558 375 560 368 c 0,148,149 + 561 362 561 362 560 357 c 2,150,-1 + 560 120 l 2,151,152 + 560 98 560 98 552 79 c 0,153,154 + 544 61 544 61 532 46 c 0,155,156 + 522 32 522 32 508 20 c 0,157,158 + 502 16 502 16 496 16 c 0,159,160 + 484 16 484 16 480 27 c 0,161,162 + 478 30 478 30 460 70 c 128,-1,163 + 442 110 442 110 436 124 c 0,164,165 + 431 134 431 134 431 144 c 0,166,167 + 431 170 431 170 431 192.5 c 128,-1,168 + 431 215 431 215 431 232 c 128,-1,169 + 431 249 431 249 431 271 c 0,170,171 + 431 289 431 289 431 313 c 0,172,173 + 431 321 431 321 436 327 c 0,174,175 + 471 370 471 370 487 380 c 0,176,177 + 500 389 500 389 517 389 c 0,178,179 + 520 389 520 389 525 388.5 c 128,-1,180 + 530 388 530 388 531 388 c 0,181,182 + 546 388 546 388 554 379 c 0,146,147 +120 42 m 0,183,184 + 123 48 123 48 200 123 c 0,185,186 + 206 129 206 129 216 129 c 2,187,-1 + 415 129 l 2,188,189 + 427 129 427 129 432 119 c 0,190,191 + 473 28 473 28 476 19 c 0,192,193 + 478 13 478 13 473 8 c 0,194,195 + 469 4 469 4 463 3 c 0,196,197 + 462 3 462 3 459 3 c 128,-1,198 + 456 3 456 3 456 3 c 2,199,-1 + 442 2 l 1,200,-1 + 179 2 l 2,201,202 + 158 2 158 2 141 14 c 0,203,204 + 133 19 133 19 129 23 c 0,205,206 + 122 30 122 30 120 33 c 128,-1,207 + 118 36 118 36 120 42 c 0,183,184 +89 376 m 0,208,209 + 91 378 91 378 97 380 c 128,-1,210 + 103 382 103 382 111 383 c 0,211,212 + 120 383 120 383 128 379 c 0,213,214 + 135 375 135 375 161.5 359.5 c 128,-1,215 + 188 344 188 344 197 339 c 0,216,217 + 205 335 205 335 205 326 c 2,218,-1 + 205 151 l 2,219,220 + 205 138 205 138 196 130 c 0,221,222 + 186 120 186 120 155 89.5 c 128,-1,223 + 124 59 124 59 120 55 c 0,224,225 + 116 50 116 50 109 50 c 0,226,227 + 99 50 99 50 95 58 c 256,228,229 + 90 66 90 66 90 67 c 0,230,231 + 76 92 76 92 76 120 c 2,232,-1 + 76 354 l 2,233,234 + 76 365 76 365 84 371 c 0,235,236 + 86 374 86 374 89 376 c 0,208,209 EndSplineSet Validated: 2049 EndChar diff --git a/fbw-a380x/src/systems/instruments/src/FCU/Components/Altitude.tsx b/fbw-a380x/src/systems/instruments/src/FCU/Components/Altitude.tsx index 35829716f51..dc0371d74f4 100644 --- a/fbw-a380x/src/systems/instruments/src/FCU/Components/Altitude.tsx +++ b/fbw-a380x/src/systems/instruments/src/FCU/Components/Altitude.tsx @@ -35,7 +35,7 @@ export class Altitude extends DisplayComponent { ALT - + {this.altText} diff --git a/fbw-a380x/src/systems/instruments/src/FCU/Components/Baro.tsx b/fbw-a380x/src/systems/instruments/src/FCU/Components/Baro.tsx index 363526576cd..787aa02fc86 100644 --- a/fbw-a380x/src/systems/instruments/src/FCU/Components/Baro.tsx +++ b/fbw-a380x/src/systems/instruments/src/FCU/Components/Baro.tsx @@ -66,9 +66,11 @@ export class Baro extends DisplayComponent { ); private readonly preSelBaroText = MappedSubject.create( - ([correction, isVisible, isLightTest]) => { + ([correction, isVisible, isLightTest, mode]) => { if (isLightTest) { - return '8.8.8.8'; + return '8p88'; // p is used as a standin character for the Q test character + } else if (mode === 'QFE') { + return 'qfe'; } else if (isVisible) { return correction < 100 ? correction.toFixed(2) : correction.toFixed(0).padStart(4, '0'); } else { @@ -78,6 +80,7 @@ export class Baro extends DisplayComponent { this.correction, this.isPreSelVisible, this.isLightTestActive, + this.mode, ); onAfterRender(_node: VNode): void { @@ -95,8 +98,8 @@ export class Baro extends DisplayComponent { { > QNH - {/* Removed QFE label as QFE systems are INOP */} - {/* - QFE - */} - + {this.preSelBaroText} - + {this.baroText} diff --git a/fbw-a380x/src/systems/instruments/src/FCU/Components/Heading.tsx b/fbw-a380x/src/systems/instruments/src/FCU/Components/Heading.tsx index 68476f1c811..955d1172902 100644 --- a/fbw-a380x/src/systems/instruments/src/FCU/Components/Heading.tsx +++ b/fbw-a380x/src/systems/instruments/src/FCU/Components/Heading.tsx @@ -19,10 +19,10 @@ export class Heading extends DisplayComponent { TRK - + --- - + ° diff --git a/fbw-a380x/src/systems/instruments/src/FCU/Components/Speed.tsx b/fbw-a380x/src/systems/instruments/src/FCU/Components/Speed.tsx index dcc76a8afe5..6f1872b087e 100644 --- a/fbw-a380x/src/systems/instruments/src/FCU/Components/Speed.tsx +++ b/fbw-a380x/src/systems/instruments/src/FCU/Components/Speed.tsx @@ -16,7 +16,7 @@ export class Speed extends DisplayComponent { SPD - + --- diff --git a/fbw-a380x/src/systems/instruments/src/FCU/Components/VerticalSpeed.tsx b/fbw-a380x/src/systems/instruments/src/FCU/Components/VerticalSpeed.tsx index 402d2e5e74f..8b2e4ae9667 100644 --- a/fbw-a380x/src/systems/instruments/src/FCU/Components/VerticalSpeed.tsx +++ b/fbw-a380x/src/systems/instruments/src/FCU/Components/VerticalSpeed.tsx @@ -16,7 +16,7 @@ export class VerticalSpeed extends DisplayComponent { V/S - + ----- diff --git a/fbw-a380x/src/systems/instruments/src/FCU/style.scss b/fbw-a380x/src/systems/instruments/src/FCU/style.scss index e3b7acb317d..7c2d2e43061 100644 --- a/fbw-a380x/src/systems/instruments/src/FCU/style.scss +++ b/fbw-a380x/src/systems/instruments/src/FCU/style.scss @@ -83,20 +83,21 @@ text.Label.Visible { :root text.Value { font-family: Digital; - font-size:440px; + font-size:550px; text-anchor: start; fill: $display-colour; letter-spacing: 0px; } :root .Baro text.Value { - font-size: 400px; + font-size: 512px; } :root #PreSelBaroValue { font-family: Digital; text-anchor: end; letter-spacing: 0px; + font-size: 275px; } :root line { From 37615961120d948f7eae0508e59b7bc84ab5ac46 Mon Sep 17 00:00:00 2001 From: BBK <22713769+BlueberryKing@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:12:34 +0100 Subject: [PATCH 2/9] fix(fms): move speed limit to performance data (#9033) * Start moving speed limit to performance data * Show alternate speed limit on alternate plan * Include alternate speed limit on main flight plan * Make Coherent happy * Update CHANGELOG.md * Remove useless setters * Update CHANGELOG.md --------- Co-authored-by: 2hwk <15316958+2hwk@users.noreply.github.com> Co-authored-by: Benjamin Dupont <4503241+Benjozork@users.noreply.github.com> --- .github/CHANGELOG.md | 1 + .../CDU/A320_Neo_CDU_VerticalRevisionPage.js | 60 +++--- .../FMC/A32NX_FMCMainDisplay.js | 79 ++++++-- .../src/flightplanning/plans/FlightPlan.ts | 25 +++ .../performance/FlightPlanPerformanceData.ts | 174 ++++++++++++++++++ 5 files changed, 292 insertions(+), 47 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 6fb2d237026..cf513ecea1d 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -88,6 +88,7 @@ 1. [A380X/FCU] Fix display of values on FCU during light test - @heclak (Heclak) 1. [A380X/FMS] Fix VLS computation error for CONF 1, might have lead to FMS crashes during climb out - @flogross89 (floridude) 1. [A380X/FCU] Add correct QFE label using the baro preselect display - @heclak (Heclak) +1. [FMS] Move the speed limit data to performance data, so that it is flight-plan-specific - @BlueberryKing (BlueberryKing) ## 0.12.0 diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_VerticalRevisionPage.js b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_VerticalRevisionPage.js index 31bbb2a0c90..9c0ea557b9a 100644 --- a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_VerticalRevisionPage.js +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_VerticalRevisionPage.js @@ -24,8 +24,9 @@ class CDUVerticalRevisionPage { /** @type {BaseFlightPlan} */ const targetPlan = mcdu.flightPlan(forPlan, inAlternate); - // Use performance data of primary for waypoints in alternaten - const performanceData = mcdu.flightPlan(forPlan, false).performanceData; + const mainTargetPlan = mcdu.flightPlan(forPlan, false); + // Use performance data of primary for waypoints in alternate + const performanceData = mainTargetPlan.performanceData; const confirmConstraint = Number.isFinite(confirmSpeed) || Number.isFinite(confirmAlt); const constraintType = CDUVerticalRevisionPage.constraintType(mcdu, wpIndex, forPlan, inAlternate); @@ -41,11 +42,6 @@ class CDUVerticalRevisionPage { } } - let coordinates = "---"; - if (waypoint.isXF()) { - coordinates = CDUPilotsWaypoint.formatLatLong(waypoint.terminationWaypoint().location); - } - const showSpeedLim = mcdu._fuelPredDone || isOrigin || isDestination || constraintType !== WaypointConstraintType.Unknown; // the conditions other than isDestination are a workaround for no ToC const showDesSpeedLim = showSpeedLim && (isDestination || @@ -53,19 +49,27 @@ class CDUVerticalRevisionPage { (mcdu.flightPhaseManager.phase > FmgcFlightPhases.CRUISE && mcdu.flightPhaseManager.phase < FmgcFlightPhases.GOAROUND)); + const climbSpeedLimitSpeed = inAlternate ? performanceData.alternateClimbSpeedLimitSpeed : performanceData.climbSpeedLimitSpeed; + const climbSpeedLimitAltitude = inAlternate ? performanceData.alternateClimbSpeedLimitAltitude : performanceData.climbSpeedLimitAltitude; + const isClimbSpeedLimitPilotEntered = inAlternate ? performanceData.isAlternateClimbSpeedLimitPilotEntered : performanceData.isClimbSpeedLimitPilotEntered; + + const descentSpeedLimitSpeed = inAlternate ? performanceData.alternateDescentSpeedLimitSpeed : performanceData.descentSpeedLimitSpeed; + const descentSpeedLimitAltitude = inAlternate ? performanceData.alternateDescentSpeedLimitAltitude : performanceData.descentSpeedLimitAltitude; + const isDescentSpeedLimitPilotEntered = inAlternate ? performanceData.isAlternateDescentSpeedLimitPilotEntered : performanceData.isDescentSpeedLimitPilotEntered; + let speedLimitTitle = ""; let speedLimitCell = ""; if (showDesSpeedLim) { speedLimitTitle = "\xa0DES SPD LIM"; - if (mcdu.descentSpeedLimit !== undefined) { - speedLimitCell = `{magenta}{${mcdu.descentSpeedLimitPilot ? 'big' : 'small'}}${mcdu.descentSpeedLimit.toFixed(0).padStart(3, "0")}/${this.formatFl(mcdu.descentSpeedLimitAlt, performanceData.transitionLevel * 100)}{end}{end}`; + if (descentSpeedLimitSpeed !== null) { + speedLimitCell = `{magenta}{${isDescentSpeedLimitPilotEntered ? 'big' : 'small'}}${descentSpeedLimitSpeed.toFixed(0).padStart(3, "0")}/${this.formatFl(descentSpeedLimitAltitude, performanceData.transitionLevel * 100)}{end}{end}`; } else { speedLimitCell = "{cyan}*[ ]/[ ]{end}"; } } else if (showSpeedLim) { speedLimitTitle = "\xa0CLB SPD LIM"; - if (mcdu.climbSpeedLimit !== undefined) { - speedLimitCell = `{magenta}{${mcdu.climbSpeedLimitPilot ? 'big' : 'small'}}${mcdu.climbSpeedLimit.toFixed(0).padStart(3, "0")}/${this.formatFl(mcdu.climbSpeedLimitAlt, performanceData.transitionAltitude)}{end}{end}`; + if (climbSpeedLimitSpeed !== null) { + speedLimitCell = `{magenta}{${isClimbSpeedLimitPilotEntered ? 'big' : 'small'}}${climbSpeedLimitSpeed.toFixed(0).padStart(3, "0")}/${this.formatFl(climbSpeedLimitAltitude, performanceData.transitionAltitude)}{end}{end}`; } else { speedLimitCell = "{cyan}*[ ]/[ ]{end}"; } @@ -162,23 +166,13 @@ class CDUVerticalRevisionPage { if (value === FMCMainDisplay.clrValue) { if (showDesSpeedLim) { - if (mcdu.descentSpeedLimitPilot) { - mcdu.descentSpeedLimit = 250; - mcdu.descentSpeedLimitAlt = 10000; - } else { - mcdu.descentSpeedLimit = undefined; - mcdu.descentSpeedLimitAlt = undefined; - } - mcdu.descentSpeedLimitPilot = false; + mainTargetPlan.setPerformanceData(inAlternate ? 'alternateDescentSpeedLimitSpeed' : 'descentSpeedLimitSpeed', null); + mainTargetPlan.setPerformanceData(inAlternate ? 'alternateDescentSpeedLimitAltitude' : 'descentSpeedLimitAltitude', null); + mainTargetPlan.setPerformanceData(inAlternate ? 'isAlternateDescentSpeedLimitPilotEntered' : 'isDescentSpeedLimitPilotEntered', false); } else { - if (mcdu.climbSpeedLimitPilot) { - mcdu.climbSpeedLimit = 250; - mcdu.climbSpeedLimitAlt = 10000; - } else { - mcdu.climbSpeedLimit = undefined; - mcdu.climbSpeedLimitAlt = undefined; - } - mcdu.climbSpeedLimitPilot = false; + mainTargetPlan.setPerformanceData(inAlternate ? 'alternateClimbSpeedLimitSpeed' : 'climbSpeedLimitSpeed', null); + mainTargetPlan.setPerformanceData(inAlternate ? 'alternateClimbSpeedLimitAltitude' : 'climbSpeedLimitAltitude', null); + mainTargetPlan.setPerformanceData(inAlternate ? 'isAlternateClimbSpeedLimitPilotEntered' : 'isClimbSpeedLimitPilotEntered', false); } CDUVerticalRevisionPage.ShowPage(mcdu, waypoint, wpIndex, verticalWaypoint, undefined, undefined, undefined, forPlan, inAlternate); return; @@ -203,13 +197,13 @@ class CDUVerticalRevisionPage { alt = Math.round(alt / 10) * 10; if (showDesSpeedLim) { - mcdu.descentSpeedLimit = speed; - mcdu.descentSpeedLimitAlt = alt; - mcdu.descentSpeedLimitPilot = true; + mainTargetPlan.setPerformanceData(inAlternate ? 'alternateDescentSpeedLimitSpeed' : 'descentSpeedLimitSpeed', speed); + mainTargetPlan.setPerformanceData(inAlternate ? 'alternateDescentSpeedLimitAltitude' : 'descentSpeedLimitAltitude', alt); + mainTargetPlan.setPerformanceData(inAlternate ? 'isAlternateDescentSpeedLimitPilotEntered' : 'isDescentSpeedLimitPilotEntered', true); } else { - mcdu.climbSpeedLimit = speed; - mcdu.climbSpeedLimitAlt = alt; - mcdu.climbSpeedLimitPilot = true; + mainTargetPlan.setPerformanceData(inAlternate ? 'alternateClimbSpeedLimitSpeed' : 'climbSpeedLimitSpeed', speed); + mainTargetPlan.setPerformanceData(inAlternate ? 'alternateClimbSpeedLimitAltitude' : 'climbSpeedLimitAltitude', alt); + mainTargetPlan.setPerformanceData(inAlternate ? 'isAlternateClimbSpeedLimitPilotEntered' : 'isClimbSpeedLimitPilotEntered', true); } CDUVerticalRevisionPage.ShowPage(mcdu, waypoint, wpIndex, verticalWaypoint, undefined, undefined, undefined, forPlan, inAlternate); diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/FMC/A32NX_FMCMainDisplay.js b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/FMC/A32NX_FMCMainDisplay.js index 3ef6b69e973..53476dddb0f 100644 --- a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/FMC/A32NX_FMCMainDisplay.js +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/FMC/A32NX_FMCMainDisplay.js @@ -100,12 +100,6 @@ class FMCMainDisplay extends BaseAirliners { this.preSelectedCrzSpeed = undefined; this.managedSpeedTarget = undefined; this.managedSpeedTargetIsMach = undefined; - this.climbSpeedLimit = undefined; - this.climbSpeedLimitAlt = undefined; - this.climbSpeedLimitPilot = undefined; - this.descentSpeedLimit = undefined; - this.descentSpeedLimitAlt = undefined; - this.descentSpeedLimitPilot = undefined; this.managedSpeedClimb = undefined; this.managedSpeedClimbIsPilotEntered = undefined; this.managedSpeedClimbMach = undefined; @@ -450,12 +444,6 @@ class FMCMainDisplay extends BaseAirliners { this.preSelectedCrzSpeed = undefined; this.managedSpeedTarget = NaN; this.managedSpeedTargetIsMach = false; - this.climbSpeedLimit = 250; - this.climbSpeedLimitAlt = 10000; - this.climbSpeedLimitPilot = false; - this.descentSpeedLimit = 250; - this.descentSpeedLimitAlt = 10000; - this.descentSpeedLimitPilot = false; this.managedSpeedClimb = 290; this.managedSpeedClimbIsPilotEntered = false; this.managedSpeedClimbMach = 0.78; @@ -947,11 +935,11 @@ class FMCMainDisplay extends BaseAirliners { // apply speed limit/alt if (this.flightPhaseManager.phase <= FmgcFlightPhases.CRUISE) { - if (this.climbSpeedLimit !== undefined && alt <= this.climbSpeedLimitAlt) { + if (this.climbSpeedLimit !== null && alt <= this.climbSpeedLimitAlt) { kcas = Math.min(this.climbSpeedLimit, kcas); } } else if (this.flightPhaseManager.phase < FmgcFlightPhases.GOAROUND) { - if (this.descentSpeedLimit !== undefined && alt <= this.descentSpeedLimitAlt) { + if (this.descentSpeedLimit !== null && alt <= this.descentSpeedLimitAlt) { kcas = Math.min(this.descentSpeedLimit, kcas); } } @@ -4762,6 +4750,62 @@ class FMCMainDisplay extends BaseAirliners { } } + /** + * The maximum speed imposed by the climb speed limit in the active flight plan or null if it is not set. + * @returns {number | null} + */ + get climbSpeedLimit() { + const plan = this.currFlightPlanService.active; + + // The plane follows 250 below 10'000 even without a flight plan + return plan ? plan.performanceData.climbSpeedLimitSpeed : DefaultPerformanceData.ClimbSpeedLimitSpeed; + } + + /** + * The altitude below which the climb speed limit of the active flight plan applies or null if not set. + * @returns {number | null} + */ + get climbSpeedLimitAlt() { + const plan = this.currFlightPlanService.active; + + // The plane follows 250 below 10'000 even without a flight plan + return plan ? plan.performanceData.climbSpeedLimitAltitude : DefaultPerformanceData.ClimbSpeedLimitAltitude; + } + + get climbSpeedLimitPilot() { + const plan = this.currFlightPlanService.active; + + return plan ? plan.performanceData.isClimbSpeedLimitPilotEntered : false; + } + + /** + * The maximum speed imposed by the descent speed limit in the active flight plan or null if it is not set. + * @returns {number | null} + */ + get descentSpeedLimit() { + const plan = this.currFlightPlanService.active; + + // The plane follows 250 below 10'000 even without a flight plan + return plan ? plan.performanceData.descentSpeedLimitSpeed : DefaultPerformanceData.DescentSpeedLimitSpeed; + } + + /** + * The altitude below which the descent speed limit of the active flight plan applies or null if not set. + * @returns {number | null} + */ + get descentSpeedLimitAlt() { + const plan = this.currFlightPlanService.active; + + // The plane follows 250 below 10'000 even without a flight plan + return plan ? plan.performanceData.descentSpeedLimitAltitude : DefaultPerformanceData.DescentSpeedLimitAltitude; + } + + get descentSpeedLimitPilot() { + const plan = this.currFlightPlanService.active; + + return plan ? plan.performanceData.isDescentSpeedLimitPilotEntered : false; + } + getFlightPhase() { return this.flightPhaseManager.phase; } @@ -5078,6 +5122,13 @@ const FlightPlans = Object.freeze({ Temporary: 1, }); +const DefaultPerformanceData = Object.freeze({ + ClimbSpeedLimitSpeed: 250, + ClimbSpeedLimitAltitude: 10000, + DescentSpeedLimitSpeed: 250, + DescentSpeedLimitAltitude: 10000, +}); + class FmArinc429OutputWord extends Arinc429Word { constructor(name, value = 0) { super(0); diff --git a/fbw-a32nx/src/systems/fmgc/src/flightplanning/plans/FlightPlan.ts b/fbw-a32nx/src/systems/fmgc/src/flightplanning/plans/FlightPlan.ts index 25b49d99231..2bfe23e6fc8 100644 --- a/fbw-a32nx/src/systems/fmgc/src/flightplanning/plans/FlightPlan.ts +++ b/fbw-a32nx/src/systems/fmgc/src/flightplanning/plans/FlightPlan.ts @@ -15,6 +15,7 @@ import { FlightArea } from '@fmgc/navigation/FlightArea'; import { CopyOptions } from '@fmgc/flightplanning/plans/CloningOptions'; import { ImportedPerformanceData } from '@fmgc/flightplanning/uplink/SimBriefUplinkAdapter'; import { + DefaultPerformanceData, FlightPlanPerformanceData, FlightPlanPerformanceDataProperties, } from '@fmgc/flightplanning/plans/performance/FlightPlanPerformanceData'; @@ -129,9 +130,20 @@ export class FlightPlan

= this.firstMissedApproachLegIndex) { throw new Error('[FPM] Cannot direct to a leg in the missed approach segment'); @@ -301,8 +313,21 @@ export class FlightPlan

Date: Sun, 15 Dec 2024 00:23:52 +1300 Subject: [PATCH 3/9] feat(fwc): fcu faults (#9655) * feat(fwc): fcu faults * refactor(fcu): use proper bits in existing DW for FCU healthy * refactor(fcu): also revert other FlyByWireInterface changes --------- Co-authored-by: Lukas Michels --- .github/CHANGELOG.md | 1 + fbw-a32nx/docs/a320-simvars.md | 4 +- .../instruments/src/Common/EWDMessages.tsx | 6 + .../systems/instruments/src/EWD/PseudoFWC.ts | 54 +++- .../instruments/src/EWD/instrument.tsx | 5 + .../src/publishers/A32NXFcuBusPublisher.ts | 277 ++++++++++++++++++ fbw-a32nx/src/wasm/fbw_a320/src/fcu/Fcu.cpp | 3 + 7 files changed, 347 insertions(+), 3 deletions(-) create mode 100644 fbw-a32nx/src/systems/shared/src/publishers/A32NXFcuBusPublisher.ts diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index cf513ecea1d..9ccb38a218b 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -89,6 +89,7 @@ 1. [A380X/FMS] Fix VLS computation error for CONF 1, might have lead to FMS crashes during climb out - @flogross89 (floridude) 1. [A380X/FCU] Add correct QFE label using the baro preselect display - @heclak (Heclak) 1. [FMS] Move the speed limit data to performance data, so that it is flight-plan-specific - @BlueberryKing (BlueberryKing) +1. [A32NX/FWC] Add FCU faults - @tracernz (Mike) ## 0.12.0 diff --git a/fbw-a32nx/docs/a320-simvars.md b/fbw-a32nx/docs/a320-simvars.md index 49e0e482316..82b14691494 100644 --- a/fbw-a32nx/docs/a320-simvars.md +++ b/fbw-a32nx/docs/a320-simvars.md @@ -3332,7 +3332,9 @@ In the variables below, {number} should be replaced with one item in the set: { |15-19| Spare | | 20 | FMGC 1 selected (has priority) | | 21 | FMGC 2 selected (has priority) | - |22-25| Spare | + |22-23| Spare | + | 24 | FCU 1 Healthy | + | 25 | FCU 2 Healthy | | 26 | FD 1 Button off | | 27 | FD 2 Button off | |28-29| Spare | diff --git a/fbw-a32nx/src/systems/instruments/src/Common/EWDMessages.tsx b/fbw-a32nx/src/systems/instruments/src/Common/EWDMessages.tsx index e79a55e4a8c..0af0ff516e0 100644 --- a/fbw-a32nx/src/systems/instruments/src/Common/EWDMessages.tsx +++ b/fbw-a32nx/src/systems/instruments/src/Common/EWDMessages.tsx @@ -192,6 +192,12 @@ const EWDMessages = { '216330503': '\x1b<4m -FWD CAB TRIM VALVE', '216330504': '\x1b<4m -AFT CAB TRIM VALVE', '216330505': '\x1b<4m -TRIM AIR HI PR', + '220020201': '\x1b<4m\x1b4mAUTO FLT\x1bm FCU 1+2 FAULT', + '220020202': '\x1b<5m -PFD BARO REF: STD ONLY', + '220021001': '\x1b<4m\x1b4mAUTO FLT\x1bm FCU 1 FAULT', + '220021002': '\x1b<5m -BARO REF.........CHECK', + '220021501': '\x1b<4m\x1b4mAUTO FLT\x1bm FCU 2 FAULT', + '220021502': '\x1b<5m -BARO REF.........CHECK', '221070001': '\x1b<4m\x1b4mT.O\x1bm SPEEDS TOO LOW', '221070002': '\x1b<5m -TOW AND T.O DATA.CHECK', '221071001': '\x1b<4m\x1b4mT.O\x1bm V1/VR/V2 DISAGREE', diff --git a/fbw-a32nx/src/systems/instruments/src/EWD/PseudoFWC.ts b/fbw-a32nx/src/systems/instruments/src/EWD/PseudoFWC.ts index 88e4ab2b2e8..228279f0ca1 100644 --- a/fbw-a32nx/src/systems/instruments/src/EWD/PseudoFWC.ts +++ b/fbw-a32nx/src/systems/instruments/src/EWD/PseudoFWC.ts @@ -16,6 +16,7 @@ import { } from '@microsoft/msfs-sdk'; import { + Arinc429LocalVarConsumerSubject, Arinc429Register, Arinc429RegisterSubject, Arinc429SignStatusMatrix, @@ -30,6 +31,7 @@ import { import { VerticalMode } from '@shared/autopilot'; import { EwdSimvars } from 'instruments/src/EWD/shared/EwdSimvarPublisher'; import { FuelSystemEvents } from '../MsfsAvionicsCommon/providers/FuelSystemPublisher'; +import { A32NXFcuBusEvents } from '../../../shared/src/publishers/A32NXFcuBusPublisher'; export function xor(a: boolean, b: boolean): boolean { return !!((a ? 1 : 0) ^ (b ? 1 : 0)); @@ -71,7 +73,8 @@ enum FwcAuralWarning { } export class PseudoFWC { - private readonly sub = this.bus.getSubscriber(); + private readonly sub = this.bus.getSubscriber(); + /** Time to inhibit master warnings and cautions during startup in ms */ private static readonly FWC_STARTUP_TIME = 5000; @@ -289,6 +292,13 @@ export class PseudoFWC { private toV2VRV2DisagreeWarning = Subject.create(false); + private readonly fcu1DiscreteWord2 = Arinc429LocalVarConsumerSubject.create(this.sub.on('a32nx_fcu_discrete_word_2')); + private readonly fcu2DiscreteWord2 = Arinc429LocalVarConsumerSubject.create(this.sub.on('a32nx_fcu_discrete_word_2')); + + private readonly fcu12Fault = Subject.create(false); + private readonly fcu1Fault = Subject.create(false); + private readonly fcu2Fault = Subject.create(false); + /* 24 - ELECTRICAL */ private readonly ac1BusPowered = Subject.create(false); @@ -1088,7 +1098,6 @@ export class PseudoFWC { const deltaTime = this.instrument.deltaTime; // Inputs update - this.flightPhaseEndedPulseNode.write(false, deltaTime); this.fwcFlightPhase.set(SimVar.GetSimVarValue('L:A32NX_FWC_FLIGHT_PHASE', 'Enum')); @@ -1379,6 +1388,14 @@ export class PseudoFWC { overspeedWarning ||= adr1Discrete1.bitValueOr(9, false) || adr2Discrete1.bitValueOr(9, false); this.overspeedWarning.set(overspeedWarning); + // In reality FWC1 takes 1B, and FWC2 2B. + const fcu1Healthy = this.fcu1DiscreteWord2.get().bitValueOr(24, false); + const fcu2Healthy = this.fcu1DiscreteWord2.get().bitValueOr(25, false); + + this.fcu12Fault.set(!fcu1Healthy && !fcu2Healthy && this.dcESSBusPowered.get() && this.dc2BusPowered.get()); + this.fcu1Fault.set(!fcu1Healthy && fcu2Healthy && this.dcESSBusPowered.get()); + this.fcu2Fault.set(fcu1Healthy && !fcu2Healthy && this.dc2BusPowered.get()); + // TO SPEEDS NOT INSERTED const fmToSpeedsNotInserted = fm1DiscreteWord3.bitValueOr(18, false) && fm2DiscreteWord3.bitValueOr(18, false); @@ -2525,6 +2542,39 @@ export class PseudoFWC { ewdMessageFailures: EWDMessageDict = { // 22 - AUTOFLIGHT + 2200202: { + // FCU 1+2 FAULT + flightPhaseInhib: [3, 4, 5, 7, 8], + simVarIsActive: this.fcu12Fault, + whichCodeToReturn: () => [0, 1], + codesToReturn: ['220020201', '220020202'], + memoInhibit: () => false, + failure: 2, + sysPage: -1, + side: 'LEFT', + }, + 2200210: { + // FCU 1 FAULT + flightPhaseInhib: [3, 4, 5, 7, 8], + simVarIsActive: this.fcu1Fault, + whichCodeToReturn: () => [0, 1], + codesToReturn: ['220021001', '220021002'], + memoInhibit: () => false, + failure: 1, + sysPage: -1, + side: 'LEFT', + }, + 2200215: { + // FCU 2 FAULT + flightPhaseInhib: [3, 4, 5, 7, 8], + simVarIsActive: this.fcu2Fault, + whichCodeToReturn: () => [0, 1], + codesToReturn: ['220021501', '220021502'], + memoInhibit: () => false, + failure: 1, + sysPage: -1, + side: 'LEFT', + }, 2210700: { // TO SPEEDS TOO LOW flightPhaseInhib: [1, 4, 5, 6, 7, 8, 9, 10], diff --git a/fbw-a32nx/src/systems/instruments/src/EWD/instrument.tsx b/fbw-a32nx/src/systems/instruments/src/EWD/instrument.tsx index b00d8b5b1c2..ae54d48dd36 100644 --- a/fbw-a32nx/src/systems/instruments/src/EWD/instrument.tsx +++ b/fbw-a32nx/src/systems/instruments/src/EWD/instrument.tsx @@ -14,6 +14,7 @@ import { FuelSystemPublisher } from 'instruments/src/MsfsAvionicsCommon/provider import { ArincValueProvider } from './shared/ArincValueProvider'; import { EwdComponent } from './EWD'; import { EwdSimvarPublisher } from './shared/EwdSimvarPublisher'; +import { A32NXFcuBusPublisher } from '@shared/publishers/A32NXFcuBusPublisher'; import { PseudoFWC } from './PseudoFWC'; import './style.scss'; @@ -35,6 +36,8 @@ class A32NX_EWD extends BaseInstrument { private readonly stallWarningPublisher = new StallWarningPublisher(this.bus, 0.9); + private readonly a32nxFcuBusPublisher = new A32NXFcuBusPublisher(this.bus); + private readonly pseudoFwc = new PseudoFWC(this.bus, this); constructor() { @@ -45,6 +48,8 @@ class A32NX_EWD extends BaseInstrument { this.backplane.addPublisher('FuelSystem', this.fuelSystemPublisher); this.backplane.addPublisher('adc', this.adcPublisher); this.backplane.addPublisher('stallWarning', this.stallWarningPublisher); + this.backplane.addPublisher('A32NXFcuBus', this.a32nxFcuBusPublisher); + this.backplane.addInstrument('Fwc', this.pseudoFwc); } diff --git a/fbw-a32nx/src/systems/shared/src/publishers/A32NXFcuBusPublisher.ts b/fbw-a32nx/src/systems/shared/src/publishers/A32NXFcuBusPublisher.ts new file mode 100644 index 00000000000..a4a07570d08 --- /dev/null +++ b/fbw-a32nx/src/systems/shared/src/publishers/A32NXFcuBusPublisher.ts @@ -0,0 +1,277 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +import { + EventBus, + IndexedEventType, + PublishPacer, + SimVarPublisher, + SimVarPublisherEntry, + SimVarValueType, +} from '@microsoft/msfs-sdk'; + +interface A32NXFcuBusBaseEvents { + /** The FCU selected heading. NCD if dashes or TRK/FPA mode. Raw ARINC word. */ + a32nx_fcu_selected_heading: number; + /** The FCU selected altitude. Raw ARINC word. */ + a32nx_fcu_selected_altitude: number; + /** The FCU selected CAS. NCD if dashes. Raw ARINC word. */ + a32nx_fcu_selected_airspeed: number; + /** The FCU selected V/S. NCD if dashes or TRK/FPA mode. Raw ARINC word. */ + a32nx_fcu_selected_vertical_speed: number; + /** The FCU selected track. NCD if dashes or HDG/VS mode. Raw ARINC word. */ + a32nx_fcu_selected_track: number; + /** The FCU selected FPA. NCD if dashes or HDG/VS mode. Raw ARINC word. */ + a32nx_fcu_selected_fpa: number; + /** + * FCU Autothrust System discrete word. Retransmitted from FMGC that has priority. + * Raw ARINC word. + * | Bit | Description | + * |:---:|:---------------------------------:| + * | 13 | A/THR Engaged | + * | 14 | A/THR Active | + * | 17 | A/THR Instinctive Disconnect | + * | 18 | A/THR SPD MACH mode | + * | 19 | FCU Mach Selection | + * | 20 | RETARD Mode Active | + * | 21 | THRUST N1 Mode Active | + * | 22 | THRUST EPR Mode Active | + * | 23 | A/THR ALPHA FLOOR | + * | 24 | A/THR Inop | + * | 25 | A/THR Limited | + */ + a32nx_fcu_ats_discrete_word: number; + /** + * FCU Autothrust System FMA discrete word. Retransmitted from FMGC that has priority. + * Raw ARINC word. + * | Bit | Description | + * |:---:|:---------------------------------:| + * | 11 | TO/GA Display | + * | 12 | MCT Display | + * | 13 | FLX Display | + * | 14 | CLB Display | + * | 15 | THR Display | + * | 16 | IDLE Display | + * | 17 | A.FLOOR Display | + * | 18 | TO/GA LK Display | + * | 19 | SPEED Display | + * | 20 | MACH Display | + * | 21 | ASYM Display | + * | 22 | CLB Demand Display | + * | 23 | MCT Demand Display | + */ + a32nx_fcu_ats_fma_discrete_word: number; + + /** + * Discrete word 1 for EIS left, raw ARINC word. + * | Bit | Description | + * |:---:|:---------------------------------:| + * | 11 | Baro is inHG | + * |12-24| Spare | + * | 25 | EFIS Range 10 | + * | 26 | EFIS Range 20 | + * | 27 | EFIS Range 40 | + * | 28 | EFIS Range 80 | + * | 29 | EFIS Range 160 | + * | | EFIS Range 320 if 25-29 false | + */ + a32nx_fcu_eis_discrete_word_1_left: number; + /** + * Discrete word 1 for EIS right, raw ARINC word. + * | Bit | Description | + * |:---:|:---------------------------------:| + * | 11 | Baro is inHG | + * |12-24| Spare | + * | 25 | EFIS Range 10 | + * | 26 | EFIS Range 20 | + * | 27 | EFIS Range 40 | + * | 28 | EFIS Range 80 | + * | 29 | EFIS Range 160 | + * | | EFIS Range 320 if 25-29 false | + */ + a32nx_fcu_eis_discrete_word_1_right: number; + /** + * Discrete word 2 for EIS left, raw ARINC word. + * | Bit | Description | + * |:---:|:---------------------------------:| + * | 11 | EFIS mode PLAN | + * | 12 | EFIS mode ARC | + * | 13 | EFIS mode ROSE NAV | + * | 14 | EFIS mode ROSE VOR | + * | 15 | EFIS mode ROSE ILS | + * | 16 | Spare | + * | 17 | EFIS Filter CSTR | + * | 18 | EFIS Filter WPT | + * | 19 | EFIS Filter VORD | + * | 20 | EFIS Filter NDB | + * | 21 | EFIS Filter ARPT | + * | 22 | LS Button On | + * | 23 | FD Button Off | + * | 24 | NAVAID 1 ADF | + * | 25 | NAVAID 2 ADF | + * | 26 | NAVAID 1 VOR | + * | 27 | NAVAID 2 VOR | + * | 28 | Baro on STD | + * | 29 | Baro on QNH | + */ + a32nx_fcu_eis_discrete_word_2_left: number; + /** + * Discrete word 2 for EIS right, raw ARINC word. + * | Bit | Description | + * |:---:|:---------------------------------:| + * | 11 | EFIS mode PLAN | + * | 12 | EFIS mode ARC | + * | 13 | EFIS mode ROSE NAV | + * | 14 | EFIS mode ROSE VOR | + * | 15 | EFIS mode ROSE ILS | + * | 16 | Spare | + * | 17 | EFIS Filter CSTR | + * | 18 | EFIS Filter WPT | + * | 19 | EFIS Filter VORD | + * | 20 | EFIS Filter NDB | + * | 21 | EFIS Filter ARPT | + * | 22 | LS Button On | + * | 23 | FD Button Off | + * | 24 | NAVAID 1 ADF | + * | 25 | NAVAID 2 ADF | + * | 26 | NAVAID 1 VOR | + * | 27 | NAVAID 2 VOR | + * | 28 | Baro on STD | + * | 29 | Baro on QNH | + */ + a32nx_fcu_eis_discrete_word_2_right: number; + /** + * FCU EIS Baro correction in inHg. Remains at previous value if in STD, and + * is at the inHG value corresponding to the selected hPa value if in hPa. + * Raw ARINC word. + */ + a32nx_fcu_eis_baro_left: number; + /** + * FCU EIS Baro correction in inHg. Remains at previous value if in STD, and + * is at the inHG value corresponding to the selected hPa value if in hPa. + * Raw ARINC word. + */ + a32nx_fcu_eis_baro_right: number; + /** + * FCU EIS Baro correction in hPa. Remains at previous value if in STD, and + * is at the hPa value corresponding to the selected inHG value if in inHG. + * Raw ARINC word. + */ + a32nx_fcu_eis_baro_hpa_left: number; + /** + * FCU EIS Baro correction in hPa. Remains at previous value if in STD, and + * is at the hPa value corresponding to the selected inHG value if in inHG. + * Raw ARINC word. + */ + a32nx_fcu_eis_baro_hpa_right: number; + /** + * FCU Discrete word 1. All pull/push bits are MTRIG processed for 0.1s to enabled + * async processing in other devices (FGMC, FWC etc.). + * Value changed bits are MTRIG processed for 0.5s. + * Raw ARINC word. + * | Bit | Description | + * |:---:|:---------------------------------:| + * | 11 | SPD/MACH Pushed | + * | 12 | SPD/MACH Pulled | + * | 13 | ALT Value changed | + * | 14 | VS/FPA Value changed | + * | 15 | SPD/MACH Value changed | + * | 16 | VS/FPA Pushed | + * | 17 | ALT Pushed | + * | 18 | ALT Pulled | + * | 19 | VS/FPA pulled | + * | 20 | Metric alt active | + * | 21 | SPD/MACH Switching button pushed | + * | 22 | EXPED Pushed | + * | 23 | APPR Pushed | + * | 24 | HDG/VS Active | + * | 25 | TRK/FPA Active | + * |26-29| Spare | + */ + a32nx_fcu_discrete_word_1: number; + /** + * FCU Discrete word 2. All pull/push bits are MTRIG processed for 0.1s to enabled + * async processing in other devices (FGMC, FWC etc.). + * Value changed bits are MTRIG processed for 0.5s. + * Raw ARINC word. + * | Bit | Description | + * |:---:|:---------------------------------:| + * | 11 | HDG/TRK Pushed | + * | 12 | HDG/TRK Pulled | + * | 13 | LOC Pushed | + * | 14 | HDG/TRK Value changed | + * |15-19| Spare | + * | 20 | FMGC 1 selected (has priority) | + * | 21 | FMGC 2 selected (has priority) | + * |22-23| Spare | + * | 24 | FCU 1 Healthy | + * | 25 | FCU 2 Healthy | + * | 26 | FD 1 Button off | + * | 27 | FD 2 Button off | + * |28-29| Spare | + */ + a32nx_fcu_discrete_word_2: number; +} + +type IndexedTopics = null; + +type A32NXFcuBusIndexedEvents = { + [P in keyof Pick as IndexedEventType

]: A32NXFcuBusBaseEvents[P]; +}; + +interface A32NXFcuBusPublisherEvents extends A32NXFcuBusBaseEvents, A32NXFcuBusIndexedEvents {} + +/** + * Events for A32NX FCU bus local vars. + */ +export interface A32NXFcuBusEvents extends Omit, A32NXFcuBusIndexedEvents {} + +/** + * Publisher for A32NX FCU bus local vars. + */ +export class A32NXFcuBusPublisher extends SimVarPublisher { + /** + * Create a publisher. + * @param bus The EventBus to publish to + * @param pacer An optional pacer to use to control the rate of publishing + */ + public constructor(bus: EventBus, pacer?: PublishPacer) { + const simvars = new Map>([ + ['a32nx_fcu_selected_heading', { name: 'L:A32NX_FCU_SELECTED_HEADING', type: SimVarValueType.Enum }], + ['a32nx_fcu_selected_altitude', { name: 'L:A32NX_FCU_SELECTED_ALTITUDE', type: SimVarValueType.Enum }], + ['a32nx_fcu_selected_airspeed', { name: 'L:A32NX_FCU_SELECTED_AIRSPEED', type: SimVarValueType.Enum }], + [ + 'a32nx_fcu_selected_vertical_speed', + { name: 'L:A32NX_FCU_SELECTED_VERTICAL_SPEED', type: SimVarValueType.Enum }, + ], + ['a32nx_fcu_selected_track', { name: 'L:A32NX_FCU_SELECTED_TRACK', type: SimVarValueType.Enum }], + ['a32nx_fcu_selected_fpa', { name: 'L:A32NX_FCU_SELECTED_FPA', type: SimVarValueType.Enum }], + ['a32nx_fcu_ats_discrete_word', { name: 'L:A32NX_FCU_ATS_DISCRETE_WORD', type: SimVarValueType.Enum }], + ['a32nx_fcu_ats_fma_discrete_word', { name: 'L:A32NX_FCU_ATS_FMA_DISCRETE_WORD', type: SimVarValueType.Enum }], + [ + 'a32nx_fcu_eis_discrete_word_1_left', + { name: 'L:A32NX_FCU_LEFT_EIS_DISCRETE_WORD_1', type: SimVarValueType.Enum }, + ], + [ + 'a32nx_fcu_eis_discrete_word_1_right', + { name: 'L:A32NX_FCU_RIGHT_EIS_DISCRETE_WORD_1', type: SimVarValueType.Enum }, + ], + [ + 'a32nx_fcu_eis_discrete_word_2_left', + { name: 'L:A32NX_FCU_LEFT_EIS_DISCRETE_WORD_2', type: SimVarValueType.Enum }, + ], + [ + 'a32nx_fcu_eis_discrete_word_2_right', + { name: 'L:A32NX_FCU_RIGHT_EIS_DISCRETE_WORD_2', type: SimVarValueType.Enum }, + ], + ['a32nx_fcu_eis_baro_left', { name: 'L:A32NX_FCU_LEFT_EIS_BARO', type: SimVarValueType.Enum }], + ['a32nx_fcu_eis_baro_right', { name: 'L:A32NX_FCU_RIGHT_EIS_BARO', type: SimVarValueType.Enum }], + ['a32nx_fcu_eis_baro_hpa_left', { name: 'L:A32NX_FCU_LEFT_EIS_BARO_HPA', type: SimVarValueType.Enum }], + ['a32nx_fcu_eis_baro_hpa_right', { name: 'L:A32NX_FCU_RIGHT_EIS_BARO_HPA', type: SimVarValueType.Enum }], + ['a32nx_fcu_discrete_word_1', { name: 'L:A32NX_FCU_DISCRETE_WORD_1', type: SimVarValueType.Enum }], + ['a32nx_fcu_discrete_word_2', { name: 'L:A32NX_FCU_DISCRETE_WORD_2', type: SimVarValueType.Enum }], + ]); + + super(simvars, bus, pacer); + } +} diff --git a/fbw-a32nx/src/wasm/fbw_a320/src/fcu/Fcu.cpp b/fbw-a32nx/src/wasm/fbw_a320/src/fcu/Fcu.cpp index a0712c2f84a..03e33cb0e79 100644 --- a/fbw-a32nx/src/wasm/fbw_a320/src/fcu/Fcu.cpp +++ b/fbw-a32nx/src/wasm/fbw_a320/src/fcu/Fcu.cpp @@ -71,6 +71,9 @@ base_fcu_bus Fcu::getBusOutputs() { return {}; } + Arinc429Utils::setBit(modelOutputs.bus_outputs.fcu_discrete_word_2, 24, monitoringHealthy[0]); + Arinc429Utils::setBit(modelOutputs.bus_outputs.fcu_discrete_word_2, 25, monitoringHealthy[1]); + return modelOutputs.bus_outputs; } From 94dc90aadf2cc0286569de29be7e5963f4e278e8 Mon Sep 17 00:00:00 2001 From: Michel Zehnder Date: Sat, 14 Dec 2024 13:35:22 +0100 Subject: [PATCH 4/9] fix(a380x/pfd): Fix PFD DU / ND DU brightness knobs (#9650) * Fix PFD DU / ND DU brightness knobs * Use getDisplayIndex for consistency * Remove file added by accident --------- Co-authored-by: Benjamin Dupont <4503241+Benjozork@users.noreply.github.com> Co-authored-by: BravoMike99 <119708186+BravoMike99@users.noreply.github.com> --- .github/CHANGELOG.md | 1 + fbw-a380x/src/systems/instruments/src/ND/instrument.tsx | 2 +- fbw-a380x/src/systems/instruments/src/PFD/PFD.tsx | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 9ccb38a218b..8ae8b112323 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -87,6 +87,7 @@ 1. [A380X/SD] Add brake temperature color change to amber when brakes are hot - @heclak (Heclak) 1. [A380X/FCU] Fix display of values on FCU during light test - @heclak (Heclak) 1. [A380X/FMS] Fix VLS computation error for CONF 1, might have lead to FMS crashes during climb out - @flogross89 (floridude) +1. [A380X/PFD] Fix PFD DU / ND DU brightness knobs - @MichelZ 1. [A380X/FCU] Add correct QFE label using the baro preselect display - @heclak (Heclak) 1. [FMS] Move the speed limit data to performance data, so that it is flight-plan-specific - @BlueberryKing (BlueberryKing) 1. [A32NX/FWC] Add FCU faults - @tracernz (Mike) diff --git a/fbw-a380x/src/systems/instruments/src/ND/instrument.tsx b/fbw-a380x/src/systems/instruments/src/ND/instrument.tsx index 286a01720a1..e3534d83a36 100644 --- a/fbw-a380x/src/systems/instruments/src/ND/instrument.tsx +++ b/fbw-a380x/src/systems/instruments/src/ND/instrument.tsx @@ -244,7 +244,7 @@ class NDInstrument implements FsInstrument {

diff --git a/fbw-a380x/src/systems/instruments/src/PFD/PFD.tsx b/fbw-a380x/src/systems/instruments/src/PFD/PFD.tsx index 945922d2174..385b8be4864 100644 --- a/fbw-a380x/src/systems/instruments/src/PFD/PFD.tsx +++ b/fbw-a380x/src/systems/instruments/src/PFD/PFD.tsx @@ -175,7 +175,7 @@ export class PFDComponent extends DisplayComponent { return ( From e8e1f6b5e61bec1a0c26d050040d5f5006b5053b Mon Sep 17 00:00:00 2001 From: lukecologne Date: Sat, 14 Dec 2024 21:07:10 +0100 Subject: [PATCH 5/9] feat(a32nx): sync flashing across the whole PFD (#9569) * feat: add clock and flashing utils * feat(pfd): convert flashing elements to synced utils * feat: make visible parameter optional, fix bug with infite flashing * fix: reset clock after publishing for better flashing evenness * refactor: generalize flashing util to subscribable classnames * feat(fma): add synced flashing to FMA feat(fma): use flashing component for BC3 and V/S * feat(fma): also sync A FLOOR/TOGA LK amber box * chore: add changelog * fix(pfd): remove invalid prop on V/S flashing * fix: apply review comments Co-authored-by: Michael Corcoran * refactor: don't pub oneHertzClock each frame * refactor: make new subjects readonly * chore: fix changelog * fix: FlashOneHertz now also works with tspan * fix(pfd): fix altimeter settting visibility * refactor(pfd): don't use refs in altimeter setting indicator --------- Co-authored-by: Michael Corcoran --- .github/CHANGELOG.md | 1 + .../FlashingElementUtils.tsx | 83 ++++++++ .../providers/ExtendedClockProvider.ts | 58 ++++++ .../instruments/src/PFD/AltitudeIndicator.tsx | 139 +++++++------ .../src/PFD/AttitudeIndicatorFixed.tsx | 128 ++++++------ .../src/PFD/AttitudeIndicatorHorizon.tsx | 71 +++---- .../src/systems/instruments/src/PFD/FMA.tsx | 183 ++++++++++-------- .../src/PFD/FlightPathDirector.tsx | 52 ++--- .../instruments/src/PFD/FlightPathVector.tsx | 26 ++- .../instruments/src/PFD/HeadingIndicator.tsx | 13 +- .../instruments/src/PFD/SpeedIndicator.tsx | 80 ++++---- .../src/PFD/VerticalSpeedIndicator.tsx | 17 +- .../instruments/src/PFD/instrument.tsx | 4 + .../systems/instruments/src/PFD/style.scss | 8 + 14 files changed, 545 insertions(+), 318 deletions(-) create mode 100644 fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/FlashingElementUtils.tsx create mode 100644 fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/ExtendedClockProvider.ts diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 8ae8b112323..83239d20889 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -82,6 +82,7 @@ 1. [A380X/COND] Fix wasm crash during rapid decompression - @mjuhe (Miquel Juhe) 1. [A32NX/EWD] Corrected fuel flow step to 20kg/40lbs per hour - @BravoMike99 (bruno_pt99) 1. [A380X] Fix EWD avail. thrust fill area & PFD rudder trim visibility on ground - @flogross89 (floridude) +1. [A32NX/PFD] Synchronize flashing/pulsing components across PFD - @lukecologne (luke) 1. [A380X/LIGHTS] Fix function of FCU brightness knobs - @heclak (Heclak) 1. [A380X/FWS] Fix "NO ZFW OR ZFWCG DATA" ECAM alert after landing - @flogross89 (floridude) 1. [A380X/SD] Add brake temperature color change to amber when brakes are hot - @heclak (Heclak) diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/FlashingElementUtils.tsx b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/FlashingElementUtils.tsx new file mode 100644 index 00000000000..b68efa5224e --- /dev/null +++ b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/FlashingElementUtils.tsx @@ -0,0 +1,83 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +import { + FSComponent, + DisplayComponent, + VNode, + Subscribable, + MappedSubject, + ComponentProps, + EventBus, + ConsumerSubject, + Subject, + SubscribableUtils, +} from '@microsoft/msfs-sdk'; +import { ExtendedClockEvents } from './providers/ExtendedClockProvider'; +import { NXLogicTriggeredMonostableNode } from '@flybywiresim/fbw-sdk'; + +export interface FlashProps extends ComponentProps { + bus: EventBus; + className1?: Subscribable | string; + className2?: Subscribable | string; + visible?: Subscribable; + flashing?: Subscribable; + flashDuration: number; +} + +export class FlashOneHertz extends DisplayComponent { + private readonly oneHertzClock = ConsumerSubject.create(null, false); + + private readonly flashingMtrig = new NXLogicTriggeredMonostableNode(this.props.flashDuration, true); + + private readonly flashingMtrigResult = Subject.create(false); + + private readonly visible = MappedSubject.create( + ([visible, oneHertzClock, flashingMtrig]) => visible && !(flashingMtrig && oneHertzClock), + this.props.visible ?? Subject.create(true), + this.oneHertzClock, + this.flashingMtrigResult, + ); + + private readonly class = MappedSubject.create( + ([visible, class1, class2]) => (visible ? class1 : class2), + this.visible, + SubscribableUtils.toSubscribable(this.props.className1 ?? '', true), + SubscribableUtils.toSubscribable(this.props.className2 ?? 'HiddenElement', true), + ); + + private prevClass = ''; + + onAfterRender(node: VNode): void { + super.onAfterRender(node); + + const sub = this.props.bus.getSubscriber(); + + this.oneHertzClock.setConsumer(sub.on('oneHertzClock')); + + sub.on('deltaTime').handle((dt) => { + const visible = this.props.visible?.get() ?? true; + const shouldFlash = this.props.flashing?.get() ?? true; + this.flashingMtrigResult.set( + this.props.flashDuration === Infinity + ? visible && shouldFlash + : this.flashingMtrig.write(visible && shouldFlash, dt), + ); + }); + + this.class.sub((value) => { + this.props.children.forEach((child) => { + const classList = ((child as VNode).instance as HTMLElement).classList; + + classList.remove(...FSComponent.parseCssClassesFromString(this.prevClass)); + classList.add(...FSComponent.parseCssClassesFromString(value)); + }); + + this.prevClass = value; + }, true); + } + + render(): VNode { + return <>{this.props.children}; + } +} diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/ExtendedClockProvider.ts b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/ExtendedClockProvider.ts new file mode 100644 index 00000000000..e7db8155139 --- /dev/null +++ b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/ExtendedClockProvider.ts @@ -0,0 +1,58 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { ClockEvents, EventBus, Instrument, Subject } from '@microsoft/msfs-sdk'; + +export interface ExtendedClockEvents { + monotonicTime: number; + deltaTime: number; + oneHertzClock: boolean; +} + +export class ExtendedClockEventProvider implements Instrument { + private prevSimTime = 0; + + private deltaTime = 0; + + private monotonicTime = 0; + + private oneHertzClockTime = 0; + + private readonly oneHertzClock = Subject.create(false); + + constructor(private readonly bus: EventBus) {} + + /** @inheritdoc */ + public init(): void { + const publisher = this.bus.getPublisher(); + const subscriber = this.bus.getSubscriber(); + + subscriber.on('simTime').handle((time) => { + this.deltaTime = time - this.prevSimTime; + + this.monotonicTime += this.deltaTime; + + this.oneHertzClockTime += this.deltaTime; + + this.oneHertzClock.set(this.oneHertzClockTime > 500); + + publisher.pub('deltaTime', this.deltaTime); + publisher.pub('monotonicTime', this.monotonicTime); + + if (this.oneHertzClockTime > 1000) { + this.oneHertzClockTime = 0; + } + this.prevSimTime = time; + }); + + this.oneHertzClock.sub((oneHertzClock) => { + publisher.pub('oneHertzClock', oneHertzClock); + }); + } + + /** @inheritdoc */ + public onUpdate(): void { + // noop + } +} diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/AltitudeIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/AltitudeIndicator.tsx index c4f0bc38767..84c6a9d27ee 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/AltitudeIndicator.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/AltitudeIndicator.tsx @@ -2,7 +2,15 @@ // // SPDX-License-Identifier: GPL-3.0 -import { ClockEvents, DisplayComponent, FSComponent, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; +import { + ClockEvents, + ConsumerSubject, + DisplayComponent, + FSComponent, + Subject, + Subscribable, + VNode, +} from '@microsoft/msfs-sdk'; import { ArincEventBus, Arinc429Register, @@ -17,6 +25,7 @@ import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { DigitalAltitudeReadout } from './DigitalAltitudeReadout'; import { VerticalTape } from './VerticalTape'; import { Arinc429Values } from './shared/ArincValueProvider'; +import { FlashOneHertz } from 'instruments/src/MsfsAvionicsCommon/FlashingElementUtils'; const DisplayRange = 570; const ValueSpacing = 100; @@ -294,7 +303,9 @@ enum TargetAltitudeColor { export class AltitudeIndicatorOfftape extends DisplayComponent { private abnormal = FSComponent.createRef(); - private tcasFailed = FSComponent.createRef(); + private readonly altFlagVisible = Subject.create(false); + + private readonly tcasFailed = ConsumerSubject.create(null, false); private normal = FSComponent.createRef(); @@ -326,18 +337,10 @@ export class AltitudeIndicatorOfftape extends DisplayComponent { - if (tcasFailed) { - this.tcasFailed.instance.style.display = 'inline'; - } else { - this.tcasFailed.instance.style.display = 'none'; - } - }); + this.tcasFailed.setConsumer(sub.on('tcasFail')); sub .on('fmgcDiscreteWord1') @@ -378,24 +381,27 @@ export class AltitudeIndicatorOfftape extends DisplayComponent - - ALT - + + + ALT + + - - + + T - + C - + A - + S - + + { private selectedAltUpperGroupRef = FSComponent.createRef(); - private selectedAltFailText = FSComponent.createRef(); + private readonly selectedAltFailed = Subject.create(false); private targetGroupRef = FSComponent.createRef(); @@ -559,22 +565,22 @@ class SelectedAltIndicator extends DisplayComponent { this.selectedAltUpperGroupRef.instance.style.display = 'none'; this.selectedAltLowerGroupRef.instance.style.display = 'none'; this.targetGroupRef.instance.style.display = 'none'; - this.selectedAltFailText.instance.style.display = 'block'; + this.selectedAltFailed.set(true); } else if (this.altitude.value - this.shownTargetAltitude.value > DisplayRange) { this.selectedAltLowerGroupRef.instance.style.display = 'block'; this.selectedAltUpperGroupRef.instance.style.display = 'none'; this.targetGroupRef.instance.style.display = 'none'; - this.selectedAltFailText.instance.style.display = 'none'; + this.selectedAltFailed.set(false); } else if (this.altitude.value - this.shownTargetAltitude.value < -DisplayRange) { this.targetGroupRef.instance.style.display = 'none'; this.selectedAltUpperGroupRef.instance.style.display = 'block'; this.selectedAltLowerGroupRef.instance.style.display = 'none'; - this.selectedAltFailText.instance.style.display = 'none'; + this.selectedAltFailed.set(false); } else { this.selectedAltUpperGroupRef.instance.style.display = 'none'; this.selectedAltLowerGroupRef.instance.style.display = 'none'; this.targetGroupRef.instance.style.display = 'inline'; - this.selectedAltFailText.instance.style.display = 'none'; + this.selectedAltFailed.set(false); } } @@ -661,15 +667,11 @@ class SelectedAltIndicator extends DisplayComponent { {this.textSub} - - ALT SEL - + + + ALT SEL + + ); } @@ -685,6 +687,8 @@ class AltimeterIndicator extends DisplayComponent { private text = Subject.create(''); + private readonly shouldFlash = Subject.create(false); + private baroInhg = new Arinc429Word(0); private baroHpa = new Arinc429Word(0); @@ -701,11 +705,11 @@ class AltimeterIndicator extends DisplayComponent { private flightPhase = 0; - private stdGroup = FSComponent.createRef(); + private stdVisible = Subject.create(false); - private qfeGroup = FSComponent.createRef(); + private altiSettingVisible = Subject.create(false); - private qfeBorder = FSComponent.createRef(); + private qfeBorderHidden = Subject.create(true); onAfterRender(node: VNode): void { super.onAfterRender(node); @@ -788,39 +792,34 @@ class AltimeterIndicator extends DisplayComponent { this.transLvlAr.isNormalOperation() && 100 * this.transLvlAr.value > this.props.altitude.get() ) { - this.stdGroup.instance.classList.add('BlinkInfinite'); + this.shouldFlash.set(true); } else { - this.stdGroup.instance.classList.remove('BlinkInfinite'); + this.shouldFlash.set(false); } } else if ( this.flightPhase <= 3 && this.transAltAr.isNormalOperation() && this.transAltAr.value < this.props.altitude.get() ) { - this.qfeGroup.instance.classList.add('BlinkInfinite'); + this.shouldFlash.set(true); } else { - this.qfeGroup.instance.classList.remove('BlinkInfinite'); + this.shouldFlash.set(false); } } private getText() { if (this.baroInStd) { this.mode.set('STD'); - this.stdGroup.instance.classList.remove('HiddenElement'); - this.qfeGroup.instance.classList.add('HiddenElement'); - this.qfeBorder.instance.classList.add('HiddenElement'); } else if (this.baroInQnh) { this.mode.set('QNH'); - this.stdGroup.instance.classList.add('HiddenElement'); - this.qfeGroup.instance.classList.remove('HiddenElement'); - this.qfeBorder.instance.classList.add('HiddenElement'); } else { this.mode.set('QFE'); - this.stdGroup.instance.classList.add('HiddenElement'); - this.qfeGroup.instance.classList.remove('HiddenElement'); - this.qfeBorder.instance.classList.remove('HiddenElement'); } + this.stdVisible.set(this.baroInStd); + this.altiSettingVisible.set(!this.baroInStd); + this.qfeBorderHidden.set(this.baroInStd || this.baroInQnh); + if (!this.baroInInhg) { this.text.set(Math.round(this.baroHpa.value).toString()); } else { @@ -831,17 +830,33 @@ class AltimeterIndicator extends DisplayComponent { render(): VNode { return ( <> - - - - STD - - - - + + + + + STD + + + + + + @@ -851,7 +866,7 @@ class AltimeterIndicator extends DisplayComponent { {this.text} - + ); } diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorFixed.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorFixed.tsx index fc003adaf1b..00f3d3e4223 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorFixed.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorFixed.tsx @@ -6,6 +6,7 @@ import { DisplayComponent, FSComponent, Subject, Subscribable, VNode } from '@mi import { ArincEventBus, Arinc429Register, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; import { FgBus } from 'instruments/src/PFD/shared/FgBusProvider'; import { FcuBus } from 'instruments/src/PFD/shared/FcuBusProvider'; +import { FlashOneHertz } from 'instruments/src/MsfsAvionicsCommon/FlashingElementUtils'; import { FlightPathDirector } from './FlightPathDirector'; import { FlightPathVector } from './FlightPathVector'; @@ -99,7 +100,7 @@ export class AttitudeIndicatorFixedCenter extends DisplayComponent - - ATT - + + + ATT + + + @@ -283,7 +281,15 @@ class FlightDirector extends DisplayComponent<{ bus: ArincEventBus }> { private verticalRef2 = FSComponent.createRef(); - private fdFlagVisibleSub = Subject.create('hidden'); + private readonly fdFlagVisibleSub = Subject.create(false); + + private readonly lateralShouldFlash = Subject.create(false); + + private readonly longitudinalShouldFlash = Subject.create(false); + + private readonly lateralVisible = Subject.create(false); + + private readonly longitudinalVisible = Subject.create(false); private handleFdState() { const fdOff = this.fcuEisDiscreteWord2.bitValueOr(23, false); @@ -297,14 +303,12 @@ class FlightDirector extends DisplayComponent<{ bus: ArincEventBus }> { if (showRoll) { const FDRollOffset = Math.min(Math.max(this.fdRollCommand.value, -45), 45) * 0.44; - this.lateralRef1.instance.setAttribute('visibility', 'visible'); + this.lateralVisible.set(true); this.lateralRef1.instance.style.transform = `translate3d(${FDRollOffset}px, 0px, 0px)`; - this.lateralRef2.instance.setAttribute('visibility', 'visible'); this.lateralRef2.instance.style.transform = `translate3d(${FDRollOffset}px, 0px, 0px)`; } else { - this.lateralRef1.instance.setAttribute('visibility', 'hidden'); - this.lateralRef2.instance.setAttribute('visibility', 'hidden'); + this.lateralVisible.set(false); } const showPitch = @@ -313,14 +317,12 @@ class FlightDirector extends DisplayComponent<{ bus: ArincEventBus }> { if (showPitch) { const FDPitchOffset = Math.min(Math.max(this.fdPitchCommand.value, -22.5), 22.5) * 0.89; - this.verticalRef1.instance.setAttribute('visibility', 'visible'); + this.longitudinalVisible.set(true); this.verticalRef1.instance.style.transform = `translate3d(0px, ${FDPitchOffset}px, 0px)`; - this.verticalRef2.instance.setAttribute('visibility', 'visible'); this.verticalRef2.instance.style.transform = `translate3d(0px, ${FDPitchOffset}px, 0px)`; } else { - this.verticalRef1.instance.setAttribute('visibility', 'hidden'); - this.verticalRef2.instance.setAttribute('visibility', 'hidden'); + this.longitudinalVisible.set(false); } const onGround = this.leftMainGearCompressed || this.rightMainGearCompressed; @@ -331,9 +333,9 @@ class FlightDirector extends DisplayComponent<{ bus: ArincEventBus }> { this.fdPitchCommand.isFailureWarning() || (this.fdYawCommand.isFailureWarning() && onGround)) ) { - this.fdFlagVisibleSub.set('block'); + this.fdFlagVisibleSub.set(true); } else { - this.fdFlagVisibleSub.set('none'); + this.fdFlagVisibleSub.set(false); } } @@ -341,21 +343,8 @@ class FlightDirector extends DisplayComponent<{ bus: ArincEventBus }> { const fdRollBarFlashing = this.fmgcDiscreteWord2.bitValueOr(28, false); const fdPitchBarFlashing = this.fmgcDiscreteWord5.bitValueOr(24, false); - if (fdRollBarFlashing) { - this.lateralRef1.instance.classList.add('BlinkInfinite'); - this.lateralRef2.instance.classList.add('BlinkInfinite'); - } else { - this.lateralRef1.instance.classList.remove('BlinkInfinite'); - this.lateralRef2.instance.classList.remove('BlinkInfinite'); - } - - if (fdPitchBarFlashing) { - this.verticalRef1.instance.classList.add('BlinkInfinite'); - this.verticalRef2.instance.classList.add('BlinkInfinite'); - } else { - this.verticalRef1.instance.classList.remove('BlinkInfinite'); - this.verticalRef2.instance.classList.remove('BlinkInfinite'); - } + this.lateralShouldFlash.set(fdRollBarFlashing); + this.longitudinalShouldFlash.set(fdPitchBarFlashing); } onAfterRender(node: VNode): void { @@ -455,25 +444,48 @@ class FlightDirector extends DisplayComponent<{ bus: ArincEventBus }> { render(): VNode | null { return ( - - - - - - - - - - - + + + + + + + + + + + + - FD - + + + + + + FD + + ); } diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorHorizon.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorHorizon.tsx index 67926919755..139dda64364 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorHorizon.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorHorizon.tsx @@ -23,6 +23,7 @@ import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { Arinc429Values } from './shared/ArincValueProvider'; import { HorizontalTape } from './HorizontalTape'; import { getDisplayIndex } from './PFD'; +import { FlashOneHertz } from 'instruments/src/MsfsAvionicsCommon/FlashingElementUtils'; const DisplayRange = 35; const DistanceSpacing = 15; @@ -443,11 +444,13 @@ class RadioAltAndDH extends DisplayComponent<{ private altitude = new Arinc429Word(0); - private attDhText = FSComponent.createRef(); + private readonly attDhTextVisible = Subject.create(false); private radioAltText = Subject.create('0'); - private radioAlt = FSComponent.createRef(); + private readonly radioAltVisible = Subject.create(true); + + private readonly raFlagFlashing = Subject.create(false); private classSub = Subject.create(''); @@ -488,7 +491,7 @@ class RadioAltAndDH extends DisplayComponent<{ sub.on('chosenRa').handle((ra) => { if (!this.props.attExcessive.get()) { this.radioAltitude = ra; - const raFailed = !this.radioAltitude.isFailureWarning(); + const raNotFailed = !this.radioAltitude.isFailureWarning(); const raHasData = !this.radioAltitude.isNoComputedData(); const raValue = this.filteredRadioAltitude; const verticalOffset = calculateVerticalOffsetFromRoll(this.roll.value); @@ -506,7 +509,7 @@ class RadioAltAndDH extends DisplayComponent<{ let color = 'Amber'; if (raHasData) { - if (raFailed) { + if (raNotFailed) { if (raValue < 2500) { if (raValue > 400 || (raValue > dh.value + 100 && DHValid)) { color = 'Green'; @@ -523,16 +526,18 @@ class RadioAltAndDH extends DisplayComponent<{ } } } else { - color = belowTransitionAltitude ? 'Red Blink9Seconds' : 'Red'; + color = 'Red'; text = 'RA'; } } + this.raFlagFlashing.set(!raNotFailed && belowTransitionAltitude); + this.daRaGroup.instance.style.transform = `translate3d(0px, ${-verticalOffset}px, 0px)`; - if (raFailed && DHValid && raValue <= dh.value) { - this.attDhText.instance.style.visibility = 'visible'; + if (raNotFailed && DHValid && raValue <= dh.value) { + this.attDhTextVisible.set(true); } else { - this.attDhText.instance.style.visibility = 'hidden'; + this.attDhTextVisible.set(false); } this.radioAltText.set(text); this.classSub.set(`${size} ${color} MiddleAlign TextOutline`); @@ -545,9 +550,9 @@ class RadioAltAndDH extends DisplayComponent<{ this.props.attExcessive.sub((ae) => { if (ae) { - this.radioAlt.instance.style.visibility = 'hidden'; + this.radioAltVisible.set(false); } else { - this.radioAlt.instance.style.visibility = 'visible'; + this.radioAltVisible.set(true); } }); @@ -557,18 +562,22 @@ class RadioAltAndDH extends DisplayComponent<{ render(): VNode { return ( - + + DH + + + + - DH - - - {this.radioAltText} - + + {this.radioAltText} + + ); } @@ -590,7 +599,7 @@ class SideslipIndicator extends DisplayComponent { private slideSlip = FSComponent.createRef(); - private siFailFlag = FSComponent.createRef(); + private readonly siFlagVisible = Subject.create(false); private onGround = true; @@ -684,10 +693,10 @@ class SideslipIndicator extends DisplayComponent { (!this.onGround && this.latAcc.isFailureWarning() && this.beta.isFailureWarning()) ) { this.slideSlip.instance.style.visibility = 'hidden'; - this.siFailFlag.instance.style.display = 'block'; + this.siFlagVisible.set(true); } else { this.slideSlip.instance.style.visibility = 'visible'; - this.siFailFlag.instance.style.display = 'none'; + this.siFlagVisible.set(false); } if ( @@ -720,15 +729,11 @@ class SideslipIndicator extends DisplayComponent { class={this.classNameSub} d="m73.974 47.208-1.4983-2.2175h-7.0828l-1.4983 2.2175z" /> - - SI - + + + SI + + ); } diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/FMA.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/FMA.tsx index aeadd848398..924004e988a 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/FMA.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/FMA.tsx @@ -18,6 +18,8 @@ import { FgBus } from 'instruments/src/PFD/shared/FgBusProvider'; import { FcuBus } from 'instruments/src/PFD/shared/FcuBusProvider'; import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; +import { FlashOneHertz } from 'instruments/src/MsfsAvionicsCommon/FlashingElementUtils'; +import { ExtendedClockEvents } from 'instruments/src/MsfsAvionicsCommon/providers/ExtendedClockProvider'; /* eslint-disable no-constant-condition,no-dupe-else-if -- for keeping the FMA code while it's not active yet */ @@ -393,7 +395,7 @@ class A2Cell extends DisplayComponent<{ bus: ArincEventBus }> { } handleMessage(): void { - const [_isShown, isTwoLine, _text] = getA1A2CellText( + const [_isShown, isTwoLine, _text, _amberFlashingBox] = getA1A2CellText( this.fcuAtsDiscreteWord, this.fcuAtsFmaDiscreteWord, 0, @@ -464,7 +466,7 @@ class Row3 extends DisplayComponent<{ - + ); @@ -477,13 +479,14 @@ function getA1A2CellText( flexTemp: number, autoBrakeMode: number, autoBrakeActive: boolean, -): [boolean, boolean, string] { +): [boolean, boolean, string, boolean] { const atEngaged = fcuAtsDiscreteWord.bitValueOr(13, false); const atActive = fcuAtsDiscreteWord.bitValueOr(14, false); let text = ''; let isShown = true; let isTwoLine = false; + let amberFlashingBox = false; if (fcuAtsFmaDiscreteWord.bitValueOr(11, false)) { isShown = false; @@ -540,16 +543,12 @@ function getA1A2CellText( `; } else if (fcuAtsFmaDiscreteWord.bitValueOr(17, false)) { isShown = false; - text = ` - - A.FLOOR - `; + amberFlashingBox = true; + text = 'A.FLOOR'; } else if (fcuAtsFmaDiscreteWord.bitValueOr(18, false)) { isShown = false; - text = ` - - TOGA LK - `; + amberFlashingBox = true; + text = 'TOGA LK'; } else if (fcuAtsFmaDiscreteWord.bitValueOr(19, false)) { text = 'SPEED'; } else if (fcuAtsFmaDiscreteWord.bitValueOr(20, false)) { @@ -582,7 +581,7 @@ function getA1A2CellText( isShown = false; } - return [isShown, isTwoLine, text]; + return [isShown, isTwoLine, text, amberFlashingBox]; } interface CellProps extends ComponentProps { @@ -596,6 +595,8 @@ class A1A2Cell extends ShowForSecondsComponent { private cellRef = FSComponent.createRef(); + private readonly amberFlashingBox = Subject.create(false); + private flexTemp = 0; private autoBrakeActive = false; @@ -607,7 +608,7 @@ class A1A2Cell extends ShowForSecondsComponent { } private setText() { - const [isShown, _isTwoLine, text] = getA1A2CellText( + const [isShown, _isTwoLine, text, amberFlashingBox] = getA1A2CellText( this.fcuAtsDiscreteWord, this.fcuAtsFmaDiscreteWord, this.flexTemp, @@ -624,6 +625,8 @@ class A1A2Cell extends ShowForSecondsComponent { } this.cellRef.instance.innerHTML = text; + + this.amberFlashingBox.set(amberFlashingBox); } onAfterRender(node: VNode): void { @@ -681,6 +684,9 @@ class A1A2Cell extends ShowForSecondsComponent { d="m3.3 1.8143h27.127v6.0476h-27.127z" /> + + + ); } @@ -700,18 +706,23 @@ const getA3Message = ( let text: string; let className: string; + let flashingClassName = null; if (thrLocked) { text = 'THR LK'; - className = 'Amber BlinkInfinite'; + className = 'Amber'; + flashingClassName = ''; } else if (false) { text = 'LVR TOGA'; - className = 'White BlinkInfinite'; + className = 'White'; + flashingClassName = ''; } else if (clbDemand) { text = 'LVR CLB'; - className = 'White BlinkInfinite'; + className = 'White'; + flashingClassName = ''; } else if (mctDemand) { text = 'LVR MCT'; - className = 'White BlinkInfinite'; + className = 'White'; + flashingClassName = ''; } else if (assymThrust) { text = 'LVR ASYM'; className = 'Amber'; @@ -719,10 +730,10 @@ const getA3Message = ( text = 'BRK MAX'; className = 'FontMediumSmaller MiddleAlign Cyan'; } else { - return [null, null]; + return [null, null, null]; } - return [text, className]; + return [text, className, flashingClassName]; }; interface A3CellProps extends CellProps { @@ -734,12 +745,15 @@ class A3Cell extends DisplayComponent { private textSub = Subject.create(''); + private readonly shouldFlash = Subject.create(false); + private updateMessage() { const className = this.props.A3Message.get()[1]; const text = this.props.A3Message.get()[0]; this.textSub.set(text); this.classSub.set(`FontMedium MiddleAlign ${className}`); + this.shouldFlash.set(this.props.A3Message.get()[2] !== null); } onAfterRender(node: VNode): void { @@ -750,9 +764,11 @@ class A3Cell extends DisplayComponent { render(): VNode { return ( - - {this.textSub} - + + + {this.textSub} + + ); } } @@ -821,9 +837,7 @@ class B1Cell extends ShowForSecondsComponent { private readonly inSpeedProtection = Subject.create(false); - private speedProtectionPathRef = FSComponent.createRef(); - - private inModeReversionPathRef = FSComponent.createRef(); + private readonly inModeReversion = Subject.create(false); private fmaTextRef = FSComponent.createRef(); @@ -961,17 +975,7 @@ class B1Cell extends ShowForSecondsComponent { this.boxClassSub.set('NormalStroke White'); } - if (longitudinalModeReversion) { - this.inModeReversionPathRef.instance.setAttribute('visibility', 'visible'); - } else { - this.inModeReversionPathRef.instance.setAttribute('visibility', 'hidden'); - } - - if (inSpeedProtection) { - this.speedProtectionPathRef.instance.setAttribute('visibility', 'visible'); - } else { - this.speedProtectionPathRef.instance.setAttribute('visibility', 'hidden'); - } + this.inModeReversion.set(longitudinalModeReversion); const bigBoxDisplayed = tcasMode && this.fmgcDiscreteWord7.bitValueOr(18, false); const boxPathString = @@ -995,7 +999,7 @@ class B1Cell extends ShowForSecondsComponent { onAfterRender(node: VNode): void { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub .on('fmgcDiscreteWord1') @@ -1067,16 +1071,13 @@ class B1Cell extends ShowForSecondsComponent { - - + + + + + + + { y="7.1040988" > {this.verticalText} - - {this.additionalText} - + {this.additionalText} + ); @@ -1482,6 +1483,8 @@ const getBC3Message = ( let text: string; let className: string; + let flashingClassName1 = ''; + let flashingClassName2 = ''; // All currently unused message are set to false if ( !fcdcWord1.bitValue(11) && @@ -1492,69 +1495,85 @@ const getBC3Message = ( flightPhaseForWarning ) { text = 'MAN PITCH TRIM ONLY'; - className = 'FontSmall Red Blink9Seconds'; + className = 'FontSmall'; + flashingClassName1 = 'Red Fill'; + flashingClassName2 = 'HiddenElement'; } else if (fcdcWord1.bitValue(15) && !fcdcWord1.isFailureWarning() && flightPhaseForWarning) { text = 'USE MAN PITCH TRIM'; - className = 'FontSmall PulseAmber9Seconds Amber'; + className = 'FontSmall'; + flashingClassName1 = 'Amber Fill'; + flashingClassName2 = 'DimmedAmber Fill'; } else if (false) { text = 'FOR GA: SET TOGA'; - className = 'FontMedium PulseAmber9Seconds Amber'; + className = 'FontMedium'; + flashingClassName1 = 'Amber Fill'; + flashingClassName2 = 'DimmedAmber Fill'; } else if (TCASArmed && !isAttExcessive) { text = 'TCAS '; className = 'FontMediumSmaller Cyan'; } else if (false) { text = 'DISCONNECT AP FOR LDG'; - className = 'FontMedium PulseAmber9Seconds Amber'; + className = 'FontMedium'; + flashingClassName1 = 'Amber Fill'; + flashingClassName2 = 'DimmedAmber Fill'; } else if (tcasRaInhibited && !isAttExcessive) { text = 'TCAS RA INHIBITED'; - className = 'FontMedium White'; + className = 'FontMedium White Fill'; } else if (trkFpaDeselectedTCAS && !isAttExcessive) { text = 'TRK FPA DESELECTED'; - className = 'FontMedium White'; + className = 'FontMedium White Fill'; } else if (false) { text = 'SET GREEN DOT SPEED'; - className = 'FontMedium White'; + className = 'FontMedium White Fill'; } else if (tdReached) { text = 'T/D REACHED'; - className = 'FontMedium White'; + className = 'FontMedium White Fill'; } else if (false) { text = 'MORE DRAG'; className = 'FontMedium White'; } else if (checkSpeedMode && !isAttExcessive) { text = 'CHECK SPEED MODE'; - className = 'FontMedium White'; + className = 'FontMedium White Fill'; } else if (false) { text = 'CHECK APPR SELECTION'; - className = 'FontMedium White'; + className = 'FontMedium White Fill'; } else if (false) { text = 'TURN AREA EXCEEDANCE'; - className = 'FontMedium White'; + className = 'FontMedium White Fill'; } else if (setHoldSpeed) { text = 'SET HOLD SPEED'; - className = 'FontMedium White'; + className = 'FontMedium White Fill'; } else if (false) { text = 'VERT DISCONT AHEAD'; - className = 'FontMedium Amber'; + className = 'FontMedium Amber Fill'; } else if (false) { text = 'FINAL APP SELECTED'; - className = 'FontSmall White'; + className = 'FontSmall White Fill'; } else { - return [null, null]; + return [null, null, flashingClassName1, flashingClassName2]; } - return [text, className]; + return [text, className, flashingClassName1, flashingClassName2]; }; -class BC3Cell extends DisplayComponent<{ BC3Message: Subscribable }> { +class BC3Cell extends DisplayComponent<{ BC3Message: Subscribable } & CellProps> { private bc3Cell = FSComponent.createRef(); - private classNameSub = Subject.create(''); + private readonly normalClassNames = Subject.create(''); + + private readonly flashingClassName1 = Subject.create(''); + + private readonly flashingClassName2 = Subject.create(''); + + private readonly isFlashing = Subject.create(false); private fillBC3Cell() { - const className = this.props.BC3Message.get()[1]; - const text = this.props.BC3Message.get()[0]; + this.normalClassNames.set(`${this.props.BC3Message.get()[1]} MiddleAlign`); + this.flashingClassName1.set(this.props.BC3Message.get()[2]); + this.flashingClassName2.set(this.props.BC3Message.get()[3]); + this.isFlashing.set(this.props.BC3Message.get()[2] !== ''); - this.classNameSub.set(`MiddleAlign ${className}`); + const text = this.props.BC3Message.get()[0]; if (text !== null) { this.bc3Cell.instance.innerHTML = text; } else { @@ -1571,7 +1590,17 @@ class BC3Cell extends DisplayComponent<{ BC3Message: Subscribable }> { } render(): VNode { - return ; + return ( + + + + ); } } diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathDirector.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathDirector.tsx index 23514a7a5e9..fccc7062251 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathDirector.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathDirector.tsx @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0 -import { ClockEvents, DisplayComponent, FSComponent, Subscribable, VNode } from '@microsoft/msfs-sdk'; +import { ClockEvents, DisplayComponent, FSComponent, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; import { ArincEventBus, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; import { FcuBus } from 'instruments/src/PFD/shared/FcuBusProvider'; import { FgBus } from 'instruments/src/PFD/shared/FgBusProvider'; @@ -10,6 +10,7 @@ import { FgBus } from 'instruments/src/PFD/shared/FgBusProvider'; import { calculateHorizonOffsetFromPitch } from './PFDUtils'; import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; +import { FlashOneHertz } from 'instruments/src/MsfsAvionicsCommon/FlashingElementUtils'; const DistanceSpacing = 15; const ValueSpacing = 10; @@ -48,12 +49,14 @@ export class FlightPathDirector extends DisplayComponent<{ private needsUpdate = false; - private isVisible = false; + private readonly isVisible = Subject.create(false); private birdPath = FSComponent.createRef(); private birdPathWings = FSComponent.createRef(); + private readonly shouldFlash = Subject.create(false); + onAfterRender(node: VNode): void { super.onAfterRender(node); @@ -133,7 +136,7 @@ export class FlightPathDirector extends DisplayComponent<{ sub.on('realTime').handle((_t) => { this.handlePath(); - if (this.needsUpdate && this.isVisible) { + if (this.needsUpdate && this.isVisible.get()) { this.moveBird(); } }); @@ -159,15 +162,15 @@ export class FlightPathDirector extends DisplayComponent<{ this.props.isAttExcessive.get() ) { this.birdPath.instance.style.visibility = 'hidden'; - this.isVisible = false; + this.isVisible.set(false); } else { this.birdPath.instance.style.visibility = 'visible'; - this.isVisible = true; + this.isVisible.set(true); } } private moveBird() { - if (this.isVisible) { + if (this.isVisible.get()) { const FDRollOrder = this.data.rollFdCommand.value; const FDRollOrderLim = Math.max(Math.min(FDRollOrder, 45), -45); const FDPitchOrder = this.data.pitchFdCommand.value; @@ -196,11 +199,7 @@ export class FlightPathDirector extends DisplayComponent<{ const fdRollBarFlashing = this.fmgcDiscreteWord2.bitValueOr(28, false); const fdPitchBarFlashing = this.fmgcDiscreteWord5.bitValueOr(24, false); - if (fdRollBarFlashing || fdPitchBarFlashing) { - this.birdPathWings.instance.classList.add('BlinkInfinite'); - } else { - this.birdPathWings.instance.classList.remove('BlinkInfinite'); - } + this.shouldFlash.set(fdRollBarFlashing || fdPitchBarFlashing); } render(): VNode { @@ -215,18 +214,25 @@ export class FlightPathDirector extends DisplayComponent<{ viewBox="0 0 31 31" xmlns="http://www.w3.org/2000/svg" > - - - - + + + + + + ); diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathVector.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathVector.tsx index f7b7e9a4f8c..d13e7af9b2c 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathVector.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathVector.tsx @@ -2,13 +2,14 @@ // // SPDX-License-Identifier: GPL-3.0 -import { ClockEvents, DisplayComponent, FSComponent, VNode } from '@microsoft/msfs-sdk'; +import { ClockEvents, DisplayComponent, FSComponent, Subject, VNode } from '@microsoft/msfs-sdk'; import { ArincEventBus, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; import { FcuBus } from 'instruments/src/PFD/shared/FcuBusProvider'; import { calculateHorizonOffsetFromPitch } from './PFDUtils'; import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; +import { FlashOneHertz } from 'instruments/src/MsfsAvionicsCommon/FlashingElementUtils'; const DistanceSpacing = 15; const ValueSpacing = 10; @@ -23,7 +24,7 @@ interface FlightPathVectorData { export class FlightPathVector extends DisplayComponent<{ bus: ArincEventBus }> { private bird = FSComponent.createRef(); - private fpvFlag = FSComponent.createRef(); + private readonly fpvFlagVisible = Subject.create(false); private fcuDiscreteWord1 = new Arinc429Word(0); @@ -76,14 +77,14 @@ export class FlightPathVector extends DisplayComponent<{ bus: ArincEventBus }> { const trkFpaActive = this.fcuDiscreteWord1.bitValueOr(25, true); const daAndFpaValid = this.data.fpa.isNormalOperation() && this.data.da.isNormalOperation(); if (trkFpaActive && daAndFpaValid) { - this.fpvFlag.instance.style.visibility = 'hidden'; + this.fpvFlagVisible.set(false); this.bird.instance.classList.remove('HiddenElement'); this.moveBird(); } else if (!trkFpaActive) { - this.fpvFlag.instance.style.visibility = 'hidden'; + this.fpvFlagVisible.set(false); this.bird.instance.classList.add('HiddenElement'); } else if (trkFpaActive && this.data.pitch.isNormalOperation() && this.data.roll.isNormalOperation()) { - this.fpvFlag.instance.style.visibility = 'visible'; + this.fpvFlagVisible.set(true); this.bird.instance.classList.add('HiddenElement'); } } @@ -132,16 +133,11 @@ export class FlightPathVector extends DisplayComponent<{ bus: ArincEventBus }> { - + + + ); } diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/HeadingIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/HeadingIndicator.tsx index 91da4573f05..f0133c4110f 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/HeadingIndicator.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/HeadingIndicator.tsx @@ -11,6 +11,7 @@ import { HorizontalTape } from './HorizontalTape'; import { getSmallestAngle } from './PFDUtils'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { Arinc429Values } from './shared/ArincValueProvider'; +import { FlashOneHertz } from 'instruments/src/MsfsAvionicsCommon/FlashingElementUtils'; const DisplayRange = 24; const DistanceSpacing = 7.555; @@ -57,6 +58,8 @@ export class HeadingOfftape extends DisplayComponent<{ bus: ArincEventBus; faile private abnormalRef = FSComponent.createRef(); + private readonly hdgFlagVisible = Subject.create(false); + private heading = Subject.create(0); private ILSCourse = Subject.create(0); @@ -77,9 +80,11 @@ export class HeadingOfftape extends DisplayComponent<{ bus: ArincEventBus; faile if (word.isNormalOperation()) { this.normalRef.instance.style.visibility = 'visible'; this.abnormalRef.instance.style.visibility = 'hidden'; + this.hdgFlagVisible.set(false); } else { this.normalRef.instance.style.visibility = 'hidden'; this.abnormalRef.instance.style.visibility = 'visible'; + this.hdgFlagVisible.set(true); } }); @@ -104,9 +109,11 @@ export class HeadingOfftape extends DisplayComponent<{ bus: ArincEventBus; faile - - HDG - + + + HDG + + diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/SpeedIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/SpeedIndicator.tsx index 750a4e4825e..721e248e001 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/SpeedIndicator.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/SpeedIndicator.tsx @@ -19,6 +19,7 @@ import { FcuBus } from 'instruments/src/PFD/shared/FcuBusProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { VerticalTape } from './VerticalTape'; import { Arinc429Values } from './shared/ArincValueProvider'; +import { FlashOneHertz } from 'instruments/src/MsfsAvionicsCommon/FlashingElementUtils'; const ValueSpacing = 10; const DistanceSpacing = 10; @@ -153,6 +154,8 @@ export class AirspeedIndicator extends DisplayComponent private failedGroup: NodeReference = FSComponent.createRef(); + private readonly spdFlagVisible = Subject.create(false); + private showBarsRef = FSComponent.createRef(); private vfeNext = FSComponent.createRef(); @@ -183,9 +186,11 @@ export class AirspeedIndicator extends DisplayComponent if (Number.isNaN(airspeedValue)) { this.speedTapeElements.instance.classList.add('HiddenElement'); this.failedGroup.instance.classList.remove('HiddenElement'); + this.spdFlagVisible.set(true); } else { this.speedTapeElements.instance.classList.remove('HiddenElement'); this.failedGroup.instance.classList.add('HiddenElement'); + this.spdFlagVisible.set(false); } const length = @@ -252,9 +257,12 @@ export class AirspeedIndicator extends DisplayComponent <> - - SPD - + + + SPD + + + @@ -381,7 +389,7 @@ export class AirspeedIndicatorOfftape extends DisplayComponent<{ bus: ArincEvent private decelRef = FSComponent.createRef(); - private spdLimFlagRef = FSComponent.createRef(); + private readonly spdLimFlagVisible = Subject.create(false); private onGround = true; @@ -465,9 +473,9 @@ export class AirspeedIndicatorOfftape extends DisplayComponent<{ bus: ArincEvent .whenChanged() .handle((a) => { if (a === 0) { - this.spdLimFlagRef.instance.style.visibility = 'visible'; + this.spdLimFlagVisible.set(true); } else { - this.spdLimFlagRef.instance.style.visibility = 'hidden'; + this.spdLimFlagVisible.set(false); } }); } @@ -491,14 +499,14 @@ export class AirspeedIndicatorOfftape extends DisplayComponent<{ bus: ArincEvent /> - - + + SPD - + LIM - + ); @@ -992,7 +1000,7 @@ interface SpeedStateInfo { } class SpeedTarget extends DisplayComponent<{ bus: ArincEventBus }> { - private spdSelFlagRef = FSComponent.createRef(); + private readonly spdSelFlagVisible = Subject.create(false); private upperBoundRef = FSComponent.createRef(); @@ -1110,36 +1118,36 @@ class SpeedTarget extends DisplayComponent<{ bus: ArincEventBus }> { this.lowerBoundRef.instance.style.visibility = 'hidden'; this.upperBoundRef.instance.style.visibility = 'hidden'; this.speedTargetRef.instance.style.visibility = 'hidden'; - this.spdSelFlagRef.instance.style.display = 'block'; + this.spdSelFlagVisible.set(true); } else if (spdSelNcd) { this.lowerBoundRef.instance.style.visibility = 'hidden'; this.upperBoundRef.instance.style.visibility = 'hidden'; this.speedTargetRef.instance.style.visibility = 'hidden'; - this.spdSelFlagRef.instance.style.display = 'none'; + this.spdSelFlagVisible.set(false); } else if (this.speedState.speed.value - currentTargetSpeed < -DisplayRange) { this.upperBoundRef.instance.style.visibility = 'visible'; this.lowerBoundRef.instance.style.visibility = 'hidden'; this.speedTargetRef.instance.style.visibility = 'hidden'; - this.spdSelFlagRef.instance.style.display = 'none'; + this.spdSelFlagVisible.set(false); this.currentVisible = this.upperBoundRef; } else if (this.speedState.speed.value - currentTargetSpeed > DisplayRange && !this.decelActive) { this.lowerBoundRef.instance.style.visibility = 'visible'; this.upperBoundRef.instance.style.visibility = 'hidden'; this.speedTargetRef.instance.style.visibility = 'hidden'; - this.spdSelFlagRef.instance.style.display = 'none'; + this.spdSelFlagVisible.set(false); this.currentVisible = this.lowerBoundRef; } else if (Math.abs(this.speedState.speed.value - currentTargetSpeed) < DisplayRange) { this.lowerBoundRef.instance.style.visibility = 'hidden'; this.upperBoundRef.instance.style.visibility = 'hidden'; this.speedTargetRef.instance.style.visibility = 'visible'; - this.spdSelFlagRef.instance.style.display = 'none'; + this.spdSelFlagVisible.set(false); this.currentVisible = this.speedTargetRef; inRange = true; } else { this.lowerBoundRef.instance.style.visibility = 'hidden'; this.upperBoundRef.instance.style.visibility = 'hidden'; this.speedTargetRef.instance.style.visibility = 'hidden'; - this.spdSelFlagRef.instance.style.display = 'none'; + this.spdSelFlagVisible.set(false); } return inRange; } @@ -1165,15 +1173,12 @@ class SpeedTarget extends DisplayComponent<{ bus: ArincEventBus }> { > {this.textSub} - - SPD SEL - + + + SPD SEL + + + { export class MachNumber extends DisplayComponent<{ bus: ArincEventBus }> { private machTextSub = Subject.create(''); - private failedRef = FSComponent.createRef(); + private readonly machFlagVisible = Subject.create(false); private machHysteresis = false; @@ -1306,13 +1311,13 @@ export class MachNumber extends DisplayComponent<{ bus: ArincEventBus }> { lsDisplay; if (hideMachDisplay) { - this.failedRef.instance.style.visibility = 'hidden'; + this.machFlagVisible.set(false); this.machTextSub.set(''); } else if (!this.mach.isNormalOperation()) { - this.failedRef.instance.style.visibility = 'visible'; + this.machFlagVisible.set(true); this.machTextSub.set(''); } else { - this.failedRef.instance.style.visibility = 'hidden'; + this.machFlagVisible.set(false); const machPermille = Math.round(this.mach.value * 1000); this.machTextSub.set(`.${machPermille}`); } @@ -1361,15 +1366,12 @@ export class MachNumber extends DisplayComponent<{ bus: ArincEventBus }> { render(): VNode { return ( <> - - MACH - + + + MACH + + + {this.machTextSub} diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/VerticalSpeedIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/VerticalSpeedIndicator.tsx index 4a204a920d6..296004fc29c 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/VerticalSpeedIndicator.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/VerticalSpeedIndicator.tsx @@ -16,6 +16,7 @@ import { ArincEventBus, Arinc429Word } from '@flybywiresim/fbw-sdk'; import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { LagFilter } from './PFDUtils'; +import { FlashOneHertz } from 'instruments/src/MsfsAvionicsCommon/FlashingElementUtils'; interface VerticalSpeedIndicatorProps { bus: ArincEventBus; @@ -39,7 +40,7 @@ export class VerticalSpeedIndicator extends DisplayComponent(); + private readonly vsFlagVisible = Subject.create(false); private vsNormal = FSComponent.createRef(); @@ -127,10 +128,10 @@ export class VerticalSpeedIndicator extends DisplayComponent - - + + V - + / - + S - + diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/instrument.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/instrument.tsx index 1acc0f43d98..b122e76883c 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/instrument.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/instrument.tsx @@ -8,6 +8,7 @@ import { FwcPublisher, RopRowOansPublisher } from '@flybywiresim/msfs-avionics-c import { FmsDataPublisher } from '../MsfsAvionicsCommon/providers/FmsDataPublisher'; import { DmcPublisher } from '../MsfsAvionicsCommon/providers/DmcPublisher'; +import { ExtendedClockEventProvider } from '../MsfsAvionicsCommon/providers/ExtendedClockProvider'; import { FcuBusProvider } from 'instruments/src/PFD/shared/FcuBusProvider'; import { FgBusProvider } from 'instruments/src/PFD/shared/FgBusProvider'; import { getDisplayIndex, PFDComponent } from './PFD'; @@ -48,6 +49,8 @@ class A32NX_PFD extends BaseInstrument { private readonly fwcPublisher = new FwcPublisher(this.bus); + private readonly extendedClockProvider = new ExtendedClockEventProvider(this.bus); + /** * "mainmenu" = 0 * "loading" = 1 @@ -68,6 +71,7 @@ class A32NX_PFD extends BaseInstrument { this.backplane.addPublisher('Dmc', this.dmcPublisher); this.backplane.addPublisher('RopRowOans', this.ropRowOansPublisher); this.backplane.addPublisher('Fwc', this.fwcPublisher); + this.backplane.addInstrument('ExtendedClock', this.extendedClockProvider); } get templateID(): string { diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/style.scss b/fbw-a32nx/src/systems/instruments/src/PFD/style.scss index 82fac194310..382a9892734 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/style.scss +++ b/fbw-a32nx/src/systems/instruments/src/PFD/style.scss @@ -157,6 +157,10 @@ tspan.Cyan { fill: $display-cyan; stroke: none; } +.DimmedCyan.Fill { + fill: scale-color($display-cyan, $lightness: -30%); + stroke: none; +} .None { fill: none; @@ -203,6 +207,10 @@ text.Amber { fill: $display-amber; stroke: none; } +.DimmedAmber.Fill { + fill: scale-color($display-amber, $lightness: -30%); + stroke: none; +} .Yellow { stroke: $display-yellow; From 8389e6861e83402cdd82ccbfc8d1e898f199252b Mon Sep 17 00:00:00 2001 From: heclak <46121009+heclak@users.noreply.github.com> Date: Tue, 17 Dec 2024 09:44:31 +0800 Subject: [PATCH 6/9] fix(a380x): lowered height of pilot and copilot cameras (#9557) * fix(a380x): lowered height of pilot and copilot cameras to match airbus recommendations * lowered height of pilot and copilot cameras to match Airbus guides * cleaned whitespace and newline issue * docs: update changelog --------- Co-authored-by: Saschl <19493808+Saschl@users.noreply.github.com> --- .github/CHANGELOG.md | 1 + .../AirPlanes/FlyByWire_A380_842/cameras.cfg | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 83239d20889..923d6832ac0 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -92,6 +92,7 @@ 1. [A380X/FCU] Add correct QFE label using the baro preselect display - @heclak (Heclak) 1. [FMS] Move the speed limit data to performance data, so that it is flight-plan-specific - @BlueberryKing (BlueberryKing) 1. [A32NX/FWC] Add FCU faults - @tracernz (Mike) +1. [A380X] Improve pilot and copilot camera positions - @heclak (Heclak) ## 0.12.0 diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/cameras.cfg b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/cameras.cfg index 3f46840e6ab..e786fca7f18 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/cameras.cfg +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/cameras.cfg @@ -38,8 +38,8 @@ SubCategory ="Pilot" SubCategoryItem ="DefaultPilot" PitchPanRate =20 HeadingPanRate =60 -InitialXyz= 0, 1.956999, 18.6 -InitialPbh= -11.397058, -0.007368, 0.244131 +InitialXyz= 0, 1.893, 18.6 +InitialPbh= -9.244958, -0.004128, 0.244043 NodesToHide ="" ClipMode ="Normal" BoundingBoxRadius =0.1 @@ -165,8 +165,8 @@ SnapPbhReturn=1 InstancedBased=0 NoSortTitle=0 Transition=0 -InitialXyz= 0.92399, 1.957001, 18.596704 -InitialPbh= -11.397008, 0.000366, 0.136788 +InitialXyz= 1.043988, 1.893, 18.596704 +InitialPbh= -9.244958, -0.004128, 0.244043 Category ="Cockpit" SubCategory ="Pilot" SubCategoryItem ="CoPilot" @@ -1464,7 +1464,7 @@ XYZRate =0.25 XYZAcceleratorTime =0 [CAMERADEFINITION.36] -Title ="FixedOnPlane_WindowView01" +Title ="FixedOnPlane_WindowView01" UITitle ="TT:GAME.PANEL_CAMERA_FIXEDONPLANE_16" Guid ="{D985C44F-5EC7-489D-A4CA-E9BB5AE4B7C2}" Description="" @@ -1684,4 +1684,4 @@ NoSortTitle = 0 Transition = 0 PanAcceleratorTime = 5 XYZRate = 0.25 -XYZAcceleratorTime = 0 \ No newline at end of file +XYZAcceleratorTime = 0 From 2e43f0b435b97ded79b5990ec6fd1219fac4b4b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20St=C3=B6rzbach?= Date: Wed, 18 Dec 2024 09:00:40 +0000 Subject: [PATCH 7/9] fix(elec): exchange execute_calculator_code for trigger_key_event to switch bus connectivity (#9640) * fix(elec): exchange execute_calculator_code for trigger_key_event to switch bus connectivity * fix: only start publishing elect events once in cockpit * fix: ac ground bus not being updated * fix lint * fix lint again * remove camera state from publisher * revert change regarding ground bus * chore: add changelog --------- Co-authored-by: Saschl Co-authored-by: Saschl <19493808+Saschl@users.noreply.github.com> Co-authored-by: Benjamin Dupont <4503241+Benjozork@users.noreply.github.com> --- .github/CHANGELOG.md | 1 + Cargo.lock | 447 ++++++++---------- .../Cargo.toml | 4 +- .../src/wasm/systems/a320_systems/Cargo.toml | 6 +- .../src/wasm/systems/a380_systems/Cargo.toml | 10 +- .../src/systems/shared/src/GPUManagement.ts | 14 +- .../src/wasm/systems/systems/Cargo.toml | 10 +- .../systems/systems_wasm/src/electrical.rs | 31 +- .../src/wasm/systems/systems_wasm/src/lib.rs | 2 +- .../src/wasm/systems/systems_wasm/src/msfs.rs | 10 + 10 files changed, 260 insertions(+), 275 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 923d6832ac0..1d5e8f2bd1d 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -92,6 +92,7 @@ 1. [A380X/FCU] Add correct QFE label using the baro preselect display - @heclak (Heclak) 1. [FMS] Move the speed limit data to performance data, so that it is flight-plan-specific - @BlueberryKing (BlueberryKing) 1. [A32NX/FWC] Add FCU faults - @tracernz (Mike) +1. [ELEC] Improved elec system startup behaviour - @Gurgel100 (Pascal) - @saschl 1. [A380X] Improve pilot and copilot camera positions - @heclak (Heclak) ## 0.12.0 diff --git a/Cargo.lock b/Cargo.lock index 18d75b50940..97347df3021 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,9 +71,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] @@ -110,9 +110,9 @@ dependencies = [ [[package]] name = "approx" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" dependencies = [ "num-traits", ] @@ -146,24 +146,24 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bindgen" -version = "0.66.1" +version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", + "itertools", "lazy_static", "lazycell", "log", - "peeking_take_while", "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", - "syn 2.0.79", + "syn 2.0.90", "which", ] @@ -191,6 +191,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytemuck" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" + [[package]] name = "byteorder" version = "1.5.0" @@ -199,9 +205,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.22" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "shlex", ] @@ -272,7 +278,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -283,7 +289,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -311,7 +317,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -322,12 +328,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -360,9 +366,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -375,9 +381,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -385,15 +391,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -402,38 +408,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -456,16 +462,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -479,9 +475,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -497,9 +493,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "hex" @@ -513,7 +509,7 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -558,27 +554,37 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", "serde", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -596,15 +602,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets", @@ -612,9 +618,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "linux-raw-sys" @@ -662,7 +668,7 @@ dependencies = [ [[package]] name = "msfs" version = "0.1.0" -source = "git+https://github.com/flybywiresim/msfs-rs?branch=main#b438d3e66a31bf6a739c45b3c035483c276af9e6" +source = "git+https://github.com/flybywiresim/msfs-rs?branch=main#4319d5c75222f41147ac5e73e954f17f416d9258" dependencies = [ "bindgen", "cc", @@ -675,7 +681,7 @@ dependencies = [ [[package]] name = "msfs_derive" version = "0.2.0" -source = "git+https://github.com/flybywiresim/msfs-rs?branch=main#b438d3e66a31bf6a739c45b3c035483c276af9e6" +source = "git+https://github.com/flybywiresim/msfs-rs?branch=main#4319d5c75222f41147ac5e73e954f17f416d9258" dependencies = [ "quote", "syn 1.0.109", @@ -684,25 +690,35 @@ dependencies = [ [[package]] name = "msfs_sdk" version = "0.1.0" -source = "git+https://github.com/flybywiresim/msfs-rs?branch=main#b438d3e66a31bf6a739c45b3c035483c276af9e6" +source = "git+https://github.com/flybywiresim/msfs-rs?branch=main#4319d5c75222f41147ac5e73e954f17f416d9258" [[package]] name = "nalgebra" -version = "0.25.4" +version = "0.33.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c70c9e8c5f213c8e93fc8c112ade4edd3ee62062fb897776c23dcebac7932900" +checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" dependencies = [ "approx", - "generic-array", "matrixmultiply", + "nalgebra-macros", "num-complex", "num-rational", "num-traits", - "serde", "simba", "typenum", ] +[[package]] +name = "nalgebra-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "nom" version = "7.1.3" @@ -715,26 +731,19 @@ dependencies = [ [[package]] name = "ntest" -version = "0.7.5" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c544e496c816f0a59645c0bb69097e453df203954ae2ed4b3ac4251fad69d44" +checksum = "fb183f0a1da7a937f672e5ee7b7edb727bf52b8a52d531374ba8ebb9345c0330" dependencies = [ - "ntest_proc_macro_helper", "ntest_test_cases", "ntest_timeout", ] -[[package]] -name = "ntest_proc_macro_helper" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f52e34b414605b77efc95c3f0ecef01df0c324bcc7f68d9a9cb7a7552777e52" - [[package]] name = "ntest_test_cases" -version = "0.7.5" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99a81eb400abc87063f829560bc5c5c835177703b83d1cd991960db0b2a00abe" +checksum = "16d0d3f2a488592e5368ebbe996e7f1d44aa13156efad201f5b4d84e150eaa93" dependencies = [ "proc-macro2", "quote", @@ -743,22 +752,31 @@ dependencies = [ [[package]] name = "ntest_timeout" -version = "0.7.5" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b10db009e117aca57cbfb70ac332348f9a89d09ff7204497c283c0f7a0c96323" +checksum = "fcc7c92f190c97f79b4a332f5e81dcf68c8420af2045c936c9be0bc9de6f63b5" dependencies = [ - "ntest_proc_macro_helper", "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-complex" -version = "0.3.1" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -771,13 +789,13 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-derive" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] @@ -791,11 +809,11 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.3.2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", + "num-bigint", "num-integer", "num-traits", ] @@ -812,21 +830,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.20.1" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" -dependencies = [ - "portable-atomic", -] +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "paste" @@ -834,28 +849,11 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "pest" -version = "2.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -873,12 +871,6 @@ dependencies = [ "svg", ] -[[package]] -name = "portable-atomic" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" - [[package]] name = "powerfmt" version = "0.2.0" @@ -896,29 +888,28 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -989,9 +980,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -1001,9 +992,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1018,9 +1009,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rstest" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "041bb0202c14f6a158bbbf086afb03d0c6e975c2dec7d4912f8061ed44f290af" +checksum = "d912f35156a3f99a66ee3e11ac2e0b3f34ac85a07e05263d05a7e2c8810d616f" dependencies = [ "cfg-if", "proc-macro2", @@ -1043,24 +1034,24 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1076,48 +1067,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] -name = "semver" -version = "0.11.0" +name = "safe_arch" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" dependencies = [ - "semver-parser", + "bytemuck", ] [[package]] -name = "semver-parser" -version = "0.10.2" +name = "semver" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -1136,15 +1124,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.5.0", + "indexmap 2.7.0", "serde", "serde_derive", "serde_json", @@ -1154,14 +1142,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1172,14 +1160,15 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simba" -version = "0.4.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5132a955559188f3d13c9ba831e77c802ddc8782783f050ed0c52f5988b95f4c" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" dependencies = [ "approx", "num-complex", "num-traits", "paste", + "wide", ] [[package]] @@ -1216,9 +1205,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -1266,31 +1255,11 @@ dependencies = [ "uom", ] -[[package]] -name = "thiserror" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.79", -] - [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -1309,9 +1278,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -1326,7 +1295,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.22", + "toml_edit", ] [[package]] @@ -1338,28 +1307,17 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.5.0", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.20", + "winnow", ] [[package]] @@ -1368,17 +1326,11 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-xid" @@ -1396,12 +1348,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1410,9 +1356,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -1421,24 +1367,23 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1446,22 +1391,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "which" @@ -1475,6 +1420,16 @@ dependencies = [ "rustix", ] +[[package]] +name = "wide" +version = "0.7.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58e6db2670d2be78525979e9a5f9c69d296fd7d670549fe9ebf70f8708cb5019" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -1493,6 +1448,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -1557,15 +1521,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - [[package]] name = "winnow" version = "0.6.20" @@ -1593,5 +1548,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] diff --git a/fbw-a32nx/src/wasm/systems/a320_hydraulic_simulation_graphs/Cargo.toml b/fbw-a32nx/src/wasm/systems/a320_hydraulic_simulation_graphs/Cargo.toml index 6dcc005da03..318ac01f5cf 100644 --- a/fbw-a32nx/src/wasm/systems/a320_hydraulic_simulation_graphs/Cargo.toml +++ b/fbw-a32nx/src/wasm/systems/a320_hydraulic_simulation_graphs/Cargo.toml @@ -13,8 +13,8 @@ systems = { path = "../../../../../fbw-common/src/wasm/systems/systems" } a320_systems = { path = "../a320_systems" } uom = "0.36.0" rand = "0.8.0" -ntest = "0.7.2" -num-derive = "0.3.3" +ntest = "0.9.3" +num-derive = "0.4.2" num-traits = "0.2.14" plotlib = "0.5.1" rustplotlib = "0.0.4" diff --git a/fbw-a32nx/src/wasm/systems/a320_systems/Cargo.toml b/fbw-a32nx/src/wasm/systems/a320_systems/Cargo.toml index 73db92ea2aa..aec30911938 100644 --- a/fbw-a32nx/src/wasm/systems/a320_systems/Cargo.toml +++ b/fbw-a32nx/src/wasm/systems/a320_systems/Cargo.toml @@ -6,11 +6,11 @@ edition = "2021" [dependencies] uom = "0.36.0" -nalgebra = "0.25.0" -ntest = "0.7.2" +nalgebra = "0.33.0" +ntest = "0.9.0" systems = { path = "../../../../../fbw-common/src/wasm/systems/systems" } [dev-dependencies] -rstest = "0.10.0" +rstest = "0.12.0" rand = "0.8.0" rand_pcg = "0.3.1" diff --git a/fbw-a380x/src/wasm/systems/a380_systems/Cargo.toml b/fbw-a380x/src/wasm/systems/a380_systems/Cargo.toml index c46d3dd2567..b60a90b5af0 100644 --- a/fbw-a380x/src/wasm/systems/a380_systems/Cargo.toml +++ b/fbw-a380x/src/wasm/systems/a380_systems/Cargo.toml @@ -6,15 +6,15 @@ edition = "2021" [dependencies] uom = "0.36.0" -nalgebra = "0.25.0" -ntest = "0.7.2" +nalgebra = "0.33.0" +ntest = "0.9.3" fxhash = "0.2.1" rand = "0.8.0" -serde = { version = "1.0.210", features = ["derive"] } -serde_with = { version = "3.9.0", features = ["std"] } +serde = { version = "1.0.215", features = ["derive"] } +serde_with = { version = "3.11.0", features = ["std"] } toml = { version = "0.8.19", features = ["parse"] } systems = { path = "../../../../../fbw-common/src/wasm/systems/systems" } [dev-dependencies] -rstest = "0.10.0" +rstest = "0.12.0" rand_pcg = "0.3.1" diff --git a/fbw-common/src/systems/shared/src/GPUManagement.ts b/fbw-common/src/systems/shared/src/GPUManagement.ts index 121ec976fb5..7478cf2993f 100644 --- a/fbw-common/src/systems/shared/src/GPUManagement.ts +++ b/fbw-common/src/systems/shared/src/GPUManagement.ts @@ -8,6 +8,7 @@ import { Instrument, MappedSubject, SimVarValueType, + Subject, Wait, } from '@microsoft/msfs-sdk'; import { GroundSupportEvents, MsfsElectricsEvents, MsfsFlightModelEvents, MsfsMiscEvents } from '@flybywiresim/fbw-sdk'; @@ -28,10 +29,19 @@ export class GPUManagement implements Instrument { private readonly groundVelocity = ConsumerSubject.create(this.sub.on('msfs_ground_velocity'), 0); + private readonly cameraState = Subject.create(-1); + private readonly msfsExtPowerAvailStates = new Map>(); private readonly ExtPowerAvailStates = new Map>(); + // state 2 is cockpit, state 3 is external + private readonly isIngame = MappedSubject.create( + ([gameState, cameraState]) => gameState === GameState.ingame && (cameraState === 2 || cameraState === 3), + GameStateProvider.get(), + this.cameraState, + ); + private initialIngameFrame: boolean; constructor( private readonly bus: EventBus, @@ -50,7 +60,7 @@ export class GPUManagement implements Instrument { } public init(): void { - Wait.awaitSubscribable(GameStateProvider.get(), (state) => state === GameState.ingame, true).then(() => { + Wait.awaitSubscribable(this.isIngame, (state) => state, true).then(() => { this.sub.on('gpu_toggle').handle(this.toggleGPU.bind(this)); this.gpuHookedUp.sub((v) => this.setEXTpower(v)); this.groundVelocity.sub((v) => { @@ -69,6 +79,8 @@ export class GPUManagement implements Instrument { this.setEXTpower(true); } this.initialIngameFrame = false; + } else { + this.cameraState.set(SimVar.GetSimVarValue('CAMERA STATE', 'enum')); } } diff --git a/fbw-common/src/wasm/systems/systems/Cargo.toml b/fbw-common/src/wasm/systems/systems/Cargo.toml index 8cef5e3b790..cbf6fe68a0a 100644 --- a/fbw-common/src/wasm/systems/systems/Cargo.toml +++ b/fbw-common/src/wasm/systems/systems/Cargo.toml @@ -9,13 +9,13 @@ uom = "0.36.0" rand = { version = "0.8.0", features = ["small_rng"] } rand_distr = "0.4.3" rand_pcg = "0.3.1" -ntest = "0.7.2" -num-derive = "0.3.3" -num-traits = "0.2.14" -nalgebra = "0.25.0" +ntest = "0.9.3" +num-derive = "0.4.2" +num-traits = "0.2.19" +nalgebra = "0.33.0" bounded-vec-deque = "0.1.1" fxhash = "0.2.1" bitflags = "1.3.2" [dev-dependencies] -rstest = "0.10.0" +rstest = "0.12.0" diff --git a/fbw-common/src/wasm/systems/systems_wasm/src/electrical.rs b/fbw-common/src/wasm/systems/systems_wasm/src/electrical.rs index ab9e677cdc9..4e6ac67c301 100644 --- a/fbw-common/src/wasm/systems/systems_wasm/src/electrical.rs +++ b/fbw-common/src/wasm/systems/systems_wasm/src/electrical.rs @@ -1,35 +1,42 @@ #[cfg(not(target_arch = "wasm32"))] -use crate::msfs::{legacy::execute_calculator_code, legacy::trigger_key_event}; +use crate::msfs::{legacy::trigger_key_event, legacy::trigger_key_event_ex1}; #[cfg(target_arch = "wasm32")] -use msfs::{legacy::execute_calculator_code, legacy::trigger_key_event}; +use msfs::{legacy::trigger_key_event, legacy::trigger_key_event_ex1}; use crate::{ExecuteOn, MsfsAspectBuilder, Variable}; use msfs::sys::{ - KEY_APU_BLEED_AIR_SOURCE_SET, KEY_APU_OFF_SWITCH, KEY_APU_STARTER, KEY_FUELSYSTEM_PUMP_OFF, - KEY_FUELSYSTEM_PUMP_ON, KEY_FUELSYSTEM_VALVE_CLOSE, KEY_FUELSYSTEM_VALVE_OPEN, + KEY_APU_BLEED_AIR_SOURCE_SET, KEY_APU_OFF_SWITCH, KEY_APU_STARTER, + KEY_ELECTRICAL_BUS_TO_BUS_CONNECTION_TOGGLE, KEY_FUELSYSTEM_PUMP_OFF, KEY_FUELSYSTEM_PUMP_ON, + KEY_FUELSYSTEM_VALVE_CLOSE, KEY_FUELSYSTEM_VALVE_OPEN, KEY_WING_FOLD_SET, }; use std::error::Error; use systems::shared::{to_bool, ElectricalBusType}; pub(super) fn electrical_buses( - buses: [(ElectricalBusType, usize); N], + buses: [(ElectricalBusType, u32); N], ) -> impl FnOnce(&mut MsfsAspectBuilder) -> Result<(), Box> { move |builder: &mut MsfsAspectBuilder| { + // dummy event to work around bug in MSFS, first event sent does seem to be ignored + trigger_key_event_ex1(KEY_WING_FOLD_SET, 0, 0, 0, 0, 0); for bus in buses { - const INFINITELY_POWERED_BUS_IDENTIFIER: usize = 1; - let toggle_code = format!( - "{} {} (>K:2:ELECTRICAL_BUS_TO_BUS_CONNECTION_TOGGLE)", - INFINITELY_POWERED_BUS_IDENTIFIER, bus.1 - ); + const INFINITELY_POWERED_BUS_IDENTIFIER: u32 = 1; let variable = Variable::named(&format!("ELEC_{}_BUS_IS_POWERED", bus.0)); - // MSFS' starting state has all buses connected. + builder.init_variable(variable.clone(), 1.); + builder.on_change( ExecuteOn::PostTick, vec![variable], Box::new(move |_, _| { - execute_calculator_code::<()>(&toggle_code); + trigger_key_event_ex1( + KEY_ELECTRICAL_BUS_TO_BUS_CONNECTION_TOGGLE, + INFINITELY_POWERED_BUS_IDENTIFIER, + bus.1, + 0, + 0, + 0, + ); }), ); } diff --git a/fbw-common/src/wasm/systems/systems_wasm/src/lib.rs b/fbw-common/src/wasm/systems/systems_wasm/src/lib.rs index 6e5e1982efb..56872764bea 100644 --- a/fbw-common/src/wasm/systems/systems_wasm/src/lib.rs +++ b/fbw-common/src/wasm/systems/systems_wasm/src/lib.rs @@ -93,7 +93,7 @@ impl<'a, 'b> MsfsSimulationBuilder<'a, 'b> { /// as a power source for the other buses which will all be connected to it. pub fn with_electrical_buses( self, - buses: [(ElectricalBusType, usize); N], + buses: [(ElectricalBusType, u32); N], ) -> Result> { self.with_aspect(electrical_buses(buses)) } diff --git a/fbw-common/src/wasm/systems/systems_wasm/src/msfs.rs b/fbw-common/src/wasm/systems/systems_wasm/src/msfs.rs index bdf607718e7..62a4b14a6a7 100644 --- a/fbw-common/src/wasm/systems/systems_wasm/src/msfs.rs +++ b/fbw-common/src/wasm/systems/systems_wasm/src/msfs.rs @@ -11,6 +11,16 @@ pub(crate) mod legacy { pub fn trigger_key_event(_event_id: ID32, _value: UINT32) {} + pub fn trigger_key_event_ex1( + _event_id: ID32, + _value0: UINT32, + _value1: UINT32, + _value2: UINT32, + _value3: UINT32, + _value4: UINT32, + ) { + } + #[derive(Debug)] pub struct AircraftVariable {} From cb7b806cde949d67d41abbdcfd479ffc0330ffbe Mon Sep 17 00:00:00 2001 From: BravoMike99 <119708186+BravoMike99@users.noreply.github.com> Date: Wed, 18 Dec 2024 22:29:53 +0000 Subject: [PATCH 8/9] fix(a380x/efis): illuminate range & mode selector during light test (#9639) fix(efis): illuminate range & mode selector during lt test --- .github/CHANGELOG.md | 1 + .../AirPlanes/FlyByWire_A380_842/model/behaviour/efis-cp.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 1d5e8f2bd1d..c76d696710d 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -94,6 +94,7 @@ 1. [A32NX/FWC] Add FCU faults - @tracernz (Mike) 1. [ELEC] Improved elec system startup behaviour - @Gurgel100 (Pascal) - @saschl 1. [A380X] Improve pilot and copilot camera positions - @heclak (Heclak) +1. [A380X/EFIS] Illuminate ND range and mode selectors during light test - @BravoMike99 (bruno_pt99) ## 0.12.0 diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/efis-cp.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/efis-cp.xml index f692bf6dd37..7bef6b09f52 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/efis-cp.xml +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/efis-cp.xml @@ -20,7 +20,7 @@ - (#SIMVAR_NAME#, Enum) #SIMVAR_VALUE# == #INDICATOR_POWERED# and + (#SIMVAR_NAME#, Enum) #SIMVAR_VALUE# == (L:A32NX_OVHD_INTLT_ANN) 0 == or #INDICATOR_POWERED# and From 22b58541a8e2e37364a5a1fb757e79fdfa3b1871 Mon Sep 17 00:00:00 2001 From: floridude <63071941+flogross89@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:21:04 +0100 Subject: [PATCH 9/9] fix(fws): Sound scheduling for FWS, triple click on capability downgrade (#9555) * Implement FwsSoundManager * add altitude callouts * a380x fixes * move PseudoFWC to systems-host; Implement AP + A/THR disconnect logic * fix triple clicks * fix a320/a380 differences * review fixes * BravoMike's review findings * fix AUTO_THROTTLE_DISCONNECT * single chime for A/THR OFF memo * another event forward * update a32nx sounds * change single chime back to a32nx variant * consider land armed for CAT 2 -> CAT 1 downgrades * don't break before event emission :) * Revert "update a32nx sounds" This reverts commit 48337044fe172df97dafad92c6e703b814af52be. * replace exec calculator code with simconnect call * add athr disconnect event, improve sendEvent call (no this) * first cavcharge fix * remove sound elec bus dependency * keep showing AP OFF alert unless AP re-engaged or flight is restarted * listen to ATS discrete word * pause before triple click * timing update * use FMGC discrete for AP engagement * add THR LEVERS ... MOVE * Don't instantly interrupt when continuous, only when higher prio * ECAM warning: Separate sound from AP OFF fault line * A380X: adapt timing, play first cav charge for at least 0.3s * fix alt c chord * a380x: fix short c-chord --- .github/CHANGELOG.md | 3 + .../FlyByWire_A320_NEO/sound/sound.xml | 25 +- .../instruments/src/Common/EWDMessages.tsx | 6 + .../instruments/src/EWD/instrument.tsx | 21 +- .../providers/PseudoFwcPublisher.tsx | 33 + fbw-a32nx/src/systems/systems-host/index.ts | 69 +- .../systems/FWC/FwsSoundManager.ts | 428 +++++++++++ .../systems/FWC}/PseudoFWC.ts | 570 ++++++++++++-- .../src/systems/systems-host/systems/atsu.ts | 13 +- .../systems-host/systems/powersupply.ts | 17 +- .../src/interface/SimConnectInterface.cpp | 8 + .../src/interface/SimConnectInterface.h | 2 + .../providers/PseudoFwcPublisher.tsx | 183 ----- .../src/PFD/shared/PFDSimvarPublisher.tsx | 2 +- fbw-a380x/src/systems/systems-host/index.ts | 16 +- .../FlightWarningSystem/FwsAbnormalSensed.ts | 2 +- .../systems/FlightWarningSystem/FwsCore.ts | 281 +++---- .../FlightWarningSystem/FwsFlightPhases.ts | 534 +++++++++++++ .../systems/FlightWarningSystem/FwsMemos.ts | 4 +- .../FlightWarningSystem/FwsSoundManager.ts | 453 +++++++++++ .../systems/systems-host/systems/LegacyFwc.ts | 727 ------------------ .../systems-host/systems/LegacyGpws.ts | 65 +- .../systems/LegacySoundManager.ts | 88 --- .../wasm/fbw_a380/src/FlyByWireInterface.cpp | 2 +- .../src/interface/SimConnectInterface.cpp | 6 +- .../src/interface/SimConnectInterface.h | 2 + 26 files changed, 2262 insertions(+), 1298 deletions(-) create mode 100644 fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher.tsx create mode 100644 fbw-a32nx/src/systems/systems-host/systems/FWC/FwsSoundManager.ts rename fbw-a32nx/src/systems/{instruments/src/EWD => systems-host/systems/FWC}/PseudoFWC.ts (88%) create mode 100644 fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsFlightPhases.ts create mode 100644 fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsSoundManager.ts delete mode 100644 fbw-a380x/src/systems/systems-host/systems/LegacyFwc.ts diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index c76d696710d..27d3ea96b20 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -73,6 +73,9 @@ 1. [FMS] Fix Pause at T/D not working in selected speed - @BlueberryKing (BlueberryKing) 1. [MISC] Replaced brake temperature simulation with physics based model of brakes - @Gurgel100 (Pascal) 1. [A32NX/MCDU] Suppress TMPY FPLN when no modifications made in airways page - @robertxing2004 (robeet) +1. [A380X/FWS] No "auto brake off" callout when double pressing A/THR instinctive disconnect - @flogross89 (floridude) +1. [A380X/FWS] Improve landing capability downgrade triple click logic (#9008) - @flogross89 (floridude) +1. [A32NX/FWS] Add "auto brake off" callout, improve AP/ATHR disconnect aural alert logic - @flogross89 (floridude) 1. [A32NX/FCU] The FCU LCD is now still visible with ambient light when the backlight is off @tracernz (Mike) 1. [A380X/FMC] Fix reset of perf data on done phase or database swap - @tracernz (Mike) 1. [A32NX/ATC] Fixed ATC/TCAS power supply - @tracernz (Mike) diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/sound/sound.xml b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/sound/sound.xml index 1b5aced6220..cd1656bc82e 100644 --- a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/sound/sound.xml +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/sound/sound.xml @@ -596,10 +596,6 @@ - - - - @@ -2150,7 +2146,7 @@ - + @@ -2274,54 +2270,55 @@ + - + - + - - - - - - - + + + + + + + diff --git a/fbw-a32nx/src/systems/instruments/src/Common/EWDMessages.tsx b/fbw-a32nx/src/systems/instruments/src/Common/EWDMessages.tsx index 0af0ff516e0..fae8018fc37 100644 --- a/fbw-a32nx/src/systems/instruments/src/Common/EWDMessages.tsx +++ b/fbw-a32nx/src/systems/instruments/src/Common/EWDMessages.tsx @@ -27,6 +27,7 @@ const EWDMessages = { '000002010': ' \x1b<3mFLAPS FULL', '000002011': ' \x1b<3mFLAPS\x1b<5m.....CONF 3', '000002012': ' \x1b<3mFLAPS CONF 3', + '320000001': '\x1b<4mAUTO BRK OFF', '000002201': '\x1b<3mAUTO BRK LO', '000002202': '\x1b<3mAUTO BRK MED', '000002203': '\x1b<3mAUTO BRK MAX', @@ -192,6 +193,11 @@ const EWDMessages = { '216330503': '\x1b<4m -FWD CAB TRIM VALVE', '216330504': '\x1b<4m -AFT CAB TRIM VALVE', '216330505': '\x1b<4m -TRIM AIR HI PR', + '220000001': '\x1b<2mAP OFF', + '220000002': '\x1b<4mA/THR OFF', + '220800001': '\x1b<2m\x1b4mAUTO FLT\x1bm AP OFF', + '220800004': '\x1b<4m\x1b4mAUTO FLT\x1bm A/THR OFF', + '220800005': '\x1b<5m -THR LEVERS........MOVE', '220020201': '\x1b<4m\x1b4mAUTO FLT\x1bm FCU 1+2 FAULT', '220020202': '\x1b<5m -PFD BARO REF: STD ONLY', '220021001': '\x1b<4m\x1b4mAUTO FLT\x1bm FCU 1 FAULT', diff --git a/fbw-a32nx/src/systems/instruments/src/EWD/instrument.tsx b/fbw-a32nx/src/systems/instruments/src/EWD/instrument.tsx index ae54d48dd36..5fcb9206740 100644 --- a/fbw-a32nx/src/systems/instruments/src/EWD/instrument.tsx +++ b/fbw-a32nx/src/systems/instruments/src/EWD/instrument.tsx @@ -2,20 +2,11 @@ // // SPDX-License-Identifier: GPL-3.0 -import { - AdcPublisher, - Clock, - EventBus, - FSComponent, - InstrumentBackplane, - StallWarningPublisher, -} from '@microsoft/msfs-sdk'; +import { AdcPublisher, Clock, EventBus, FSComponent, InstrumentBackplane } from '@microsoft/msfs-sdk'; import { FuelSystemPublisher } from 'instruments/src/MsfsAvionicsCommon/providers/FuelSystemPublisher'; import { ArincValueProvider } from './shared/ArincValueProvider'; import { EwdComponent } from './EWD'; import { EwdSimvarPublisher } from './shared/EwdSimvarPublisher'; -import { A32NXFcuBusPublisher } from '@shared/publishers/A32NXFcuBusPublisher'; -import { PseudoFWC } from './PseudoFWC'; import './style.scss'; @@ -34,12 +25,6 @@ class A32NX_EWD extends BaseInstrument { private readonly adcPublisher = new AdcPublisher(this.bus); - private readonly stallWarningPublisher = new StallWarningPublisher(this.bus, 0.9); - - private readonly a32nxFcuBusPublisher = new A32NXFcuBusPublisher(this.bus); - - private readonly pseudoFwc = new PseudoFWC(this.bus, this); - constructor() { super(); @@ -47,10 +32,6 @@ class A32NX_EWD extends BaseInstrument { this.backplane.addPublisher('SimVars', this.simVarPublisher); this.backplane.addPublisher('FuelSystem', this.fuelSystemPublisher); this.backplane.addPublisher('adc', this.adcPublisher); - this.backplane.addPublisher('stallWarning', this.stallWarningPublisher); - this.backplane.addPublisher('A32NXFcuBus', this.a32nxFcuBusPublisher); - - this.backplane.addInstrument('Fwc', this.pseudoFwc); } get templateID(): string { diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher.tsx b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher.tsx new file mode 100644 index 00000000000..2a7c0695682 --- /dev/null +++ b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher.tsx @@ -0,0 +1,33 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { EventBus, SimVarDefinition, SimVarValueType, SimVarPublisher } from '@microsoft/msfs-sdk'; + +export type PseudoFwcSimvars = { + engine1Master: number; + engine2Master: number; + engine3Master: number; + engine4Master: number; + fmgc1DiscreteWord3: number; + fmgc2DiscreteWord3: number; + fmgc1DiscreteWord4: number; + fmgc2DiscreteWord4: number; +}; + +export class PseudoFwcSimvarPublisher extends SimVarPublisher { + private static simvars = new Map([ + ['engine1Master', { name: 'A:FUELSYSTEM VALVE SWITCH:1', type: SimVarValueType.Bool }], + ['engine2Master', { name: 'A:FUELSYSTEM VALVE SWITCH:2', type: SimVarValueType.Bool }], + ['engine3Master', { name: 'A:FUELSYSTEM VALVE SWITCH:3', type: SimVarValueType.Bool }], + ['engine4Master', { name: 'A:FUELSYSTEM VALVE SWITCH:4', type: SimVarValueType.Bool }], + ['fmgc1DiscreteWord3', { name: 'L:A32NX_FMGC_1_DISCRETE_WORD_3', type: SimVarValueType.Number }], + ['fmgc2DiscreteWord3', { name: 'L:A32NX_FMGC_2_DISCRETE_WORD_3', type: SimVarValueType.Number }], + ['fmgc1DiscreteWord4', { name: 'L:A32NX_FMGC_1_DISCRETE_WORD_4', type: SimVarValueType.Number }], + ['fmgc2DiscreteWord4', { name: 'L:A32NX_FMGC_2_DISCRETE_WORD_4', type: SimVarValueType.Number }], + ]); + + public constructor(bus: EventBus) { + super(PseudoFwcSimvarPublisher.simvars, bus); + } +} diff --git a/fbw-a32nx/src/systems/systems-host/index.ts b/fbw-a32nx/src/systems/systems-host/index.ts index 38afa459c5c..33210e739cf 100644 --- a/fbw-a32nx/src/systems/systems-host/index.ts +++ b/fbw-a32nx/src/systems/systems-host/index.ts @@ -2,18 +2,43 @@ // // SPDX-License-Identifier: GPL-3.0 -import { EventBus, HEventPublisher } from '@microsoft/msfs-sdk'; +import { + Clock, + ClockEvents, + EventBus, + HEventPublisher, + InstrumentBackplane, + StallWarningPublisher, +} from '@microsoft/msfs-sdk'; import { AtsuSystem } from './systems/atsu'; import { PowerSupplyBusses } from './systems/powersupply'; +import { PseudoFWC } from 'systems-host/systems/FWC/PseudoFWC'; +import { FuelSystemPublisher } from 'instruments/src/MsfsAvionicsCommon/providers/FuelSystemPublisher'; +import { A32NXFcuBusPublisher } from '@shared/publishers/A32NXFcuBusPublisher'; +import { PseudoFwcSimvarPublisher } from 'instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher'; class SystemsHost extends BaseInstrument { - private readonly bus: EventBus; + private readonly bus = new EventBus(); - private readonly hEventPublisher: HEventPublisher; + private readonly backplane = new InstrumentBackplane(); - private readonly powerSupply: PowerSupplyBusses; + private readonly clock = new Clock(this.bus); - private readonly atsu: AtsuSystem; + private readonly hEventPublisher = new HEventPublisher(this.bus); + + private readonly powerSupply = new PowerSupplyBusses(this.bus); + + private readonly atsu = new AtsuSystem(this.bus); + + private readonly fuelSystemPublisher = new FuelSystemPublisher(this.bus); + + private readonly stallWarningPublisher = new StallWarningPublisher(this.bus, 0.9); + + private readonly a32nxFcuBusPublisher = new A32NXFcuBusPublisher(this.bus); + + private readonly pseudoFwcPublisher = new PseudoFwcSimvarPublisher(this.bus); + + private readonly pseudoFwc = new PseudoFWC(this.bus, this); /** * "mainmenu" = 0 @@ -26,10 +51,26 @@ class SystemsHost extends BaseInstrument { constructor() { super(); - this.bus = new EventBus(); - this.hEventPublisher = new HEventPublisher(this.bus); - this.powerSupply = new PowerSupplyBusses(this.bus); - this.atsu = new AtsuSystem(this.bus); + this.backplane.addInstrument('Clock', this.clock); + this.backplane.addInstrument('AtsuSystem', this.atsu); + this.backplane.addPublisher('FuelSystem', this.fuelSystemPublisher); + this.backplane.addPublisher('PowerPublisher', this.powerSupply); + this.backplane.addPublisher('stallWarning', this.stallWarningPublisher); + this.backplane.addPublisher('a32nxFcuBusPublisher', this.a32nxFcuBusPublisher); + this.backplane.addPublisher('PseudoFwcPublisher', this.pseudoFwcPublisher); + + this.pseudoFwc.init(); + let lastUpdateTime: number; + this.bus + .getSubscriber() + .on('simTimeHiFreq') + .atFrequency(50) + .handle((now) => { + const dt = lastUpdateTime === undefined ? 0 : now - lastUpdateTime; + lastUpdateTime = now; + + this.pseudoFwc.update(dt); + }); } get templateID(): string { @@ -47,9 +88,6 @@ class SystemsHost extends BaseInstrument { public connectedCallback(): void { super.connectedCallback(); - this.powerSupply.connectedCallback(); - this.atsu.connectedCallback(); - // Needed to fetch METARs from the sim RegisterViewListener( 'JS_LISTENER_FACILITY', @@ -58,6 +96,8 @@ class SystemsHost extends BaseInstrument { }, true, ); + + this.backplane.init(); } public Update(): void { @@ -67,14 +107,11 @@ class SystemsHost extends BaseInstrument { const gamestate = this.getGameState(); if (gamestate === 3) { this.hEventPublisher.startPublish(); - this.powerSupply.startPublish(); - this.atsu.startPublish(); } this.gameState = gamestate; } - this.powerSupply.update(); - this.atsu.update(); + this.backplane.onUpdate(); } } diff --git a/fbw-a32nx/src/systems/systems-host/systems/FWC/FwsSoundManager.ts b/fbw-a32nx/src/systems/systems-host/systems/FWC/FwsSoundManager.ts new file mode 100644 index 00000000000..1010f16b25a --- /dev/null +++ b/fbw-a32nx/src/systems/systems-host/systems/FWC/FwsSoundManager.ts @@ -0,0 +1,428 @@ +// Copyright (c) 2021-2024 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { EventBus, SimVarValueType, Subscribable } from '@microsoft/msfs-sdk'; + +export interface FwsSoundManagerControlEvents { + enqueueSound: string; + dequeueSound: string; +} + +// Synthetic voice has priority over everything, SC is least important +enum FwsAuralWarningType { + SingleChime, + AuralWarning, + SyntheticVoice, +} + +export enum FwsAuralVolume { + Full, // 0 dB + Attenuated, // -6dB + Silent, // -200 dB +} + +interface FwsAural { + /** The LocalVar which triggers the playback. Not prefixed by L: here. Either localVarName or wwiseEventName has to be defined. */ + localVarName?: string; + /** The Wwise event which triggers the playback. Either localVarName or wwiseEventName has to be defined. */ + wwiseEventName?: string; + /** Sounds are queued based on type and priority (highest priority = gets queued first within same type) */ + priority: number; + type: FwsAuralWarningType; + /** Length of audio in seconds, if non-repetitive */ + length?: number; + /** If this is set, this sound is repeated periodically with the specified pause in seconds */ + periodicWithPause?: number; + continuous?: boolean; +} + +export const FwsAuralsList: Record = { + continuousRepetitiveChime: { + localVarName: 'A32NX_FWC_CRC', + priority: 5, + type: FwsAuralWarningType.AuralWarning, + continuous: true, + }, + singleChime: { + localVarName: 'A32NX_FWC_SC', + length: 0.54, + priority: 0, + type: FwsAuralWarningType.SingleChime, + continuous: false, + }, + cavalryChargeOnce: { + localVarName: 'A32NX_FWC_CAVALRY_CHARGE', + length: 0.9, + priority: 4, + type: FwsAuralWarningType.AuralWarning, + continuous: false, + }, + cavalryChargeCont: { + localVarName: 'A32NX_FWC_CAVALRY_CHARGE', + priority: 4, + type: FwsAuralWarningType.AuralWarning, + continuous: true, + }, + tripleClick: { + localVarName: 'A32NX_FMA_TRIPLE_CLICK', + length: 0.62, + priority: 3, + type: FwsAuralWarningType.AuralWarning, + continuous: false, + }, + pause0p8s: { + localVarName: 'A32NX_AUDIO_PAUSE', + length: 0.8, + priority: 4, + type: FwsAuralWarningType.AuralWarning, + continuous: false, + }, + autoBrakeOff: { + localVarName: 'A32NX_AUDIO_AUTOBRAKE_OFF', + length: 1.5, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + continuous: false, + }, + runwayTooShort: { + localVarName: 'A32NX_AUDIO_ROW_RWY_TOO_SHORT', + length: 1.6, + priority: 4, + type: FwsAuralWarningType.SyntheticVoice, + continuous: true, + }, + keepMaxReverse: { + localVarName: 'A32NX_AUDIO_ROP_KEEP_MAX_REVERSE', + length: 1.4, + priority: 4, + type: FwsAuralWarningType.SyntheticVoice, + continuous: false, + }, + setMaxReverse: { + localVarName: 'A32NX_AUDIO_ROW_SET_MAX_REVERSE', + length: 1.62, + priority: 4, + type: FwsAuralWarningType.SyntheticVoice, + continuous: false, + }, + brakeMaxBraking: { + localVarName: 'A32NX_AUDIO_ROP_MAX_BRAKING', + length: 3.1, + priority: 4, + type: FwsAuralWarningType.SyntheticVoice, + continuous: true, + }, + stall: { + localVarName: 'A32NX_AUDIO_ROP_MAX_BRAKING', + length: 3.0, + priority: 5, + type: FwsAuralWarningType.SyntheticVoice, + continuous: true, + }, + cChordOnce: { + localVarName: 'A32NX_ALT_DEVIATION', + length: 1.0, + priority: 3, + type: FwsAuralWarningType.AuralWarning, + continuous: false, + }, + cChordCont: { + localVarName: 'A32NX_ALT_DEVIATION', + priority: 3, + type: FwsAuralWarningType.AuralWarning, + continuous: true, + }, + // Altitude callouts + minimums: { + wwiseEventName: 'aural_minimumnew', + length: 0.67, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + hundred_above: { + wwiseEventName: 'aural_100above', + length: 0.72, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + retard: { + wwiseEventName: 'new_retard', + length: 0.9, + periodicWithPause: 0.2, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_2500: { + wwiseEventName: 'new_2500', + length: 1.1, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_2500b: { + wwiseEventName: 'new_2_500', + length: 1.047, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_2000: { + wwiseEventName: 'new_2000', + length: 0.72, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_1000: { + wwiseEventName: 'new_1000', + length: 0.9, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_500: { + wwiseEventName: 'new_500', + length: 0.6, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_400: { + wwiseEventName: 'new_400', + length: 0.6, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_300: { + wwiseEventName: 'new_300', + length: 0.6, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_200: { + wwiseEventName: 'new_200', + length: 0.6, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_100: { + wwiseEventName: 'new_100', + length: 0.6, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_50: { + wwiseEventName: 'new_50', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_40: { + wwiseEventName: 'new_40', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_30: { + wwiseEventName: 'new_30', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_20: { + wwiseEventName: 'new_20', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_10: { + wwiseEventName: 'new_10', + length: 0.3, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_5: { + wwiseEventName: 'new_5', + length: 0.3, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, +}; + +// FIXME Not all sounds are added to this yet (e.g. CIDS chimes), consider adding them in the future +// Also, single chimes are not filtered (in RL only once every two seconds) +export class FwsSoundManager { + private readonly soundQueue = new Set(); + + private singleChimesPending = 0; + + private currentSoundPlaying: keyof typeof FwsAuralsList | null = null; + + /** in seconds */ + private currentSoundPlayTimeRemaining = 0; + + constructor( + private bus: EventBus, + private startupCompleted: Subscribable, + ) { + // Stop all sounds + Object.values(FwsAuralsList).forEach((a) => { + if (a.localVarName) { + SimVar.SetSimVarValue(`L:${a.localVarName}`, SimVarValueType.Bool, false); + } + }); + + const sub = this.bus.getSubscriber(); + sub.on('enqueueSound').handle((s) => this.enqueueSound(s)); + sub.on('dequeueSound').handle((s) => this.dequeueSound(s)); + } + + /** Add sound to queue. Don't add if already playing */ + enqueueSound(soundKey: keyof typeof FwsAuralsList) { + const sound = FwsAuralsList[soundKey]; + if (!sound || this.currentSoundPlaying === soundKey) { + return; + } + + if (sound.type === FwsAuralWarningType.SyntheticVoice || sound.type === FwsAuralWarningType.AuralWarning) { + this.soundQueue.add(soundKey); + } else if (sound.type === FwsAuralWarningType.SingleChime) { + this.singleChimesPending++; + } + } + + /** Remove sound from queue, e.g. when condition doesn't apply anymore. If sound is currently playing, stops sound immediately */ + dequeueSound(soundKey: keyof typeof FwsAuralsList) { + // Check if this sound is currently playing + if (this.currentSoundPlaying === soundKey && FwsAuralsList[this.currentSoundPlaying]?.continuous) { + this.stopCurrentSound(); + } + this.soundQueue.delete(soundKey); + } + + private stopCurrentSound() { + // Only LVar sounds which are continuous can be stopped + if ( + this.currentSoundPlaying && + FwsAuralsList[this.currentSoundPlaying].localVarName && + FwsAuralsList[this.currentSoundPlaying]?.continuous + ) { + SimVar.SetSimVarValue(`L:${FwsAuralsList[this.currentSoundPlaying].localVarName}`, SimVarValueType.Bool, false); + this.currentSoundPlaying = null; + this.currentSoundPlayTimeRemaining = 0; + } + } + + /** + * Convenience function for FWS: If condition true and sound not already playing, add to queue. If not, dequeue sound + * */ + handleSoundCondition(soundKey: keyof typeof FwsAuralsList, condition: boolean) { + if (condition && this.currentSoundPlaying !== soundKey) { + this.enqueueSound(soundKey); + } else if (!condition) { + this.dequeueSound(soundKey); + } + } + + /** This only has an effect on sounds defining WwiseRTPC behavior/var for volume */ + setVolume(volume: FwsAuralVolume) { + SimVar.SetSimVarValue('L:A32NX_FWS_AUDIO_VOLUME', SimVarValueType.Enum, volume); + } + + /** Play now, not to be called from the outside */ + private playSound(soundKey: keyof typeof FwsAuralsList) { + const sound = FwsAuralsList[soundKey]; + if (!sound) { + return; + } + + if (sound.localVarName) { + SimVar.SetSimVarValue(`L:${sound.localVarName}`, SimVarValueType.Bool, true); + } else if (sound.wwiseEventName) { + Coherent.call('PLAY_INSTRUMENT_SOUND', sound.wwiseEventName); + } + this.currentSoundPlaying = soundKey; + this.currentSoundPlayTimeRemaining = sound.continuous ? Infinity : sound.length; + this.soundQueue.delete(soundKey); + } + /** Find most important sound from soundQueue and play */ + private selectAndPlayMostImportantSound(): keyof typeof FwsAuralsList | null { + if (!this.startupCompleted.get()) { + return; + } + + // Logic for scheduling new sounds: Take sound from soundQueue of most important type + // (SyntheticVoice > AuralWarning > SingleChime) with highest priority, and play it + let selectedSoundKey: keyof typeof FwsAuralsList | null = null; + this.soundQueue.forEach((sk) => { + const s = FwsAuralsList[sk]; + if ( + selectedSoundKey === null || + s.type > FwsAuralsList[selectedSoundKey].type || + (s.type === FwsAuralsList[selectedSoundKey].type && s.priority > FwsAuralsList[selectedSoundKey].priority) + ) { + selectedSoundKey = sk; + } + }); + + if (selectedSoundKey) { + this.playSound(selectedSoundKey); + return selectedSoundKey; + } + + // See if single chimes are left + if (this.singleChimesPending) { + this.playSound('singleChime'); + this.singleChimesPending--; + return 'singleChime'; + } + + // Ok, nothing to play + return null; + } + + onUpdate(deltaTime: number) { + // Either wait for the current sound to finish, or schedule the next sound + if (this.currentSoundPlaying && this.currentSoundPlayTimeRemaining > 0) { + if (this.currentSoundPlayTimeRemaining - deltaTime / 1_000 > 0) { + // Wait for sound to be finished + this.currentSoundPlayTimeRemaining -= deltaTime / 1_000; + } else { + // Sound finishes in this cycle + if (FwsAuralsList[this.currentSoundPlaying].localVarName) { + SimVar.SetSimVarValue( + `L:${FwsAuralsList[this.currentSoundPlaying].localVarName}`, + SimVarValueType.Bool, + false, + ); + } + this.currentSoundPlaying = null; + this.currentSoundPlayTimeRemaining = 0; + } + + // Interrupt if sound with higher category is present in queue and current sound is continuous + let shouldInterrupt = false; + let rescheduleSound: keyof typeof FwsAuralsList | null = null; + this.soundQueue.forEach((sk) => { + const s = FwsAuralsList[sk]; + if ( + s && + this.currentSoundPlaying && + FwsAuralsList[this.currentSoundPlaying]?.continuous && + s.type > FwsAuralsList[this.currentSoundPlaying].type + ) { + shouldInterrupt = true; + } + }); + + if (shouldInterrupt) { + if (this.currentSoundPlaying && FwsAuralsList[this.currentSoundPlaying]?.continuous) { + rescheduleSound = this.currentSoundPlaying; + this.stopCurrentSound(); + if (rescheduleSound) { + this.enqueueSound(rescheduleSound); + } + } + } + } else { + // Play next sound + this.selectAndPlayMostImportantSound(); + } + } +} diff --git a/fbw-a32nx/src/systems/instruments/src/EWD/PseudoFWC.ts b/fbw-a32nx/src/systems/systems-host/systems/FWC/PseudoFWC.ts similarity index 88% rename from fbw-a32nx/src/systems/instruments/src/EWD/PseudoFWC.ts rename to fbw-a32nx/src/systems/systems-host/systems/FWC/PseudoFWC.ts index 228279f0ca1..4266ca34ee1 100644 --- a/fbw-a32nx/src/systems/instruments/src/EWD/PseudoFWC.ts +++ b/fbw-a32nx/src/systems/systems-host/systems/FWC/PseudoFWC.ts @@ -13,6 +13,10 @@ import { SimVarValueType, SubscribableMapFunctions, StallWarningEvents, + KeyEventManager, + GameStateProvider, + Wait, + KeyEvents, } from '@microsoft/msfs-sdk'; import { @@ -21,17 +25,20 @@ import { Arinc429RegisterSubject, Arinc429SignStatusMatrix, Arinc429Word, + Arinc429WordData, NXDataStore, NXLogicClockNode, NXLogicConfirmNode, NXLogicMemoryNode, NXLogicPulseNode, NXLogicTriggeredMonostableNode, + UpdateThrottler, } from '@flybywiresim/fbw-sdk'; import { VerticalMode } from '@shared/autopilot'; -import { EwdSimvars } from 'instruments/src/EWD/shared/EwdSimvarPublisher'; -import { FuelSystemEvents } from '../MsfsAvionicsCommon/providers/FuelSystemPublisher'; +import { FuelSystemEvents } from '../../../instruments/src/MsfsAvionicsCommon/providers/FuelSystemPublisher'; import { A32NXFcuBusEvents } from '../../../shared/src/publishers/A32NXFcuBusPublisher'; +import { FwsSoundManager } from 'systems-host/systems/FWC/FwsSoundManager'; +import { PseudoFwcSimvars } from 'instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher'; export function xor(a: boolean, b: boolean): boolean { return !!((a ? 1 : 0) ^ (b ? 1 : 0)); @@ -70,10 +77,21 @@ enum FwcAuralWarning { None, SingleChime, Crc, + CavalryCharge, } export class PseudoFWC { - private readonly sub = this.bus.getSubscriber(); + private readonly sub = this.bus.getSubscriber< + PseudoFwcSimvars & StallWarningEvents & KeyEvents & A32NXFcuBusEvents + >(); + + private readonly fwsUpdateThrottler = new UpdateThrottler(125); // has to be > 100 due to pulse nodes + + private keyEventManager: KeyEventManager; + + private readonly startupCompleted = Subject.create(false); + + public readonly soundManager = new FwsSoundManager(this.bus, this.startupCompleted); /** Time to inhibit master warnings and cautions during startup in ms */ private static readonly FWC_STARTUP_TIME = 5000; @@ -81,9 +99,6 @@ export class PseudoFWC { /** Time to inhibit SCs after one is trigger in ms */ private static readonly AURAL_SC_INHIBIT_TIME = 2000; - /** The time to play the single chime sound in ms */ - private static readonly AURAL_SC_PLAY_TIME = 500; - private static readonly EWD_MESSAGE_LINES = 7; private static readonly ewdMessageSimVarsLeft = Array.from( @@ -104,11 +119,16 @@ export class PseudoFWC { Subject.create(''), ); + // Input buffering + public readonly toConfigInputBuffer = new NXLogicMemoryNode(false); + public readonly clearButtonInputBuffer = new NXLogicMemoryNode(false); + public readonly recallButtonInputBuffer = new NXLogicMemoryNode(false); + public readonly aThrDiscInputBuffer = new NXLogicMemoryNode(false); + public readonly apDiscInputBuffer = new NXLogicMemoryNode(false); + /* PSEUDO FWC VARIABLES */ private readonly startupTimer = new DebounceTimer(); - private readonly startupCompleted = Subject.create(false); - private readonly allCurrentFailures: string[] = []; private readonly failuresLeft: string[] = []; @@ -117,6 +137,15 @@ export class PseudoFWC { private recallFailures: string[] = []; + private requestMasterCautionFromFaults = false; + private requestMasterCautionFromABrkOff = false; + private requestMasterCautionFromAThrOff = false; + + private requestSingleChimeFromAThrOff = false; + + private requestMasterWarningFromFaults = false; + private requestMasterWarningFromApOff = false; + private auralCrcKeys: string[] = []; private auralScKeys: string[] = []; @@ -127,8 +156,6 @@ export class PseudoFWC { private readonly auralSingleChimeInhibitTimer = new DebounceTimer(); - private readonly auralSingleChimePlayingTimer = new DebounceTimer(); - private readonly masterWarning = Subject.create(false); private readonly masterCaution = Subject.create(false); @@ -285,6 +312,76 @@ export class PseudoFWC { private toSpeedsNotInsertedWarning = Subject.create(false); + /** If multiple AP discs are triggered between FWS cycles, memorize the amount */ + public autoPilotInstinctiveDiscCountSinceLastFwsCycle = 0; + + public readonly autoPilotDisengagedInstantPulse = new NXLogicPulseNode(false); + + /** 1.8s according to references, but was raised to 1.9s to allow for triple click to finish */ + public readonly autoPilotInstinctiveDiscPressedInLast1p5Sec = new NXLogicTriggeredMonostableNode(1.5, true); + + /** 1.8s according to references, but was raised to 1.9s to allow for triple click to finish */ + public readonly autoPilotInstinctiveDiscPressedTwiceInLast1p5Sec = new NXLogicTriggeredMonostableNode(1.5, true); + + public readonly autoPilotInstinctiveDiscPressedPulse = new NXLogicPulseNode(true); + + /** Stay in first warning stage for 1.8s. Raised to 1.9s to allow for triple click to finish */ + public readonly autoPilotOffVoluntaryEndAfter1p5s = new NXLogicTriggeredMonostableNode(1.5, true); + + public readonly autoPilotOffVoluntaryFirstCavalryChargeActive = new NXLogicTriggeredMonostableNode(0.8, true); + + public readonly autoPilotOffVoluntaryFirstCavalryChargeActivePulse = new NXLogicPulseNode(false); + + public readonly autoPilotOffVoluntaryDiscPulse = new NXLogicPulseNode(true); + + public readonly autoPilotOffVoluntaryMemory = new NXLogicMemoryNode(true); + + public readonly autoPilotOffInvoluntaryMemory = new NXLogicMemoryNode(false); + + public readonly autoPilotOffAlertShown = Subject.create(false); + + public readonly autoPilotOffInvoluntary = Subject.create(false); + + public readonly autoPilotOffAlertShownMemory = new NXLogicMemoryNode(false); + + public readonly autoPilotOffUnacknowledged = new NXLogicMemoryNode(false); + + public readonly autoPilotOffShowMemo = Subject.create(false); + + public readonly fmgc1DiscreteWord3 = Arinc429LocalVarConsumerSubject.create(this.sub.on('fmgc1DiscreteWord3')); + + public readonly fmgc2DiscreteWord3 = Arinc429LocalVarConsumerSubject.create(this.sub.on('fmgc2DiscreteWord3')); + + public readonly fmgc1DiscreteWord4 = Arinc429LocalVarConsumerSubject.create(this.sub.on('fmgc1DiscreteWord4')); + + public readonly fmgc2DiscreteWord4 = Arinc429LocalVarConsumerSubject.create(this.sub.on('fmgc2DiscreteWord4')); + + public readonly fmgcApproachCapability = Subject.create(0); + + public readonly approachCapabilityDowngradeDebounce = new NXLogicTriggeredMonostableNode(0.5, true); + + public readonly approachCapabilityDowngradeSuppress = new NXLogicTriggeredMonostableNode(3, true); + + public readonly approachCapabilityDowngradeDebouncePulse = new NXLogicPulseNode(false); + + public readonly autoThrustDisengagedInstantPulse = new NXLogicPulseNode(false); + + public readonly autoThrustInstinctiveDiscPressed = new NXLogicTriggeredMonostableNode(1.5, true); // Save event for 1.5 sec + + public readonly autoThrustOffVoluntaryMemoNode = new NXLogicTriggeredMonostableNode(9, false); // Emit memo for max. 9 sec + + public readonly autoThrustOffVoluntaryCautionNode = new NXLogicTriggeredMonostableNode(3, false); // Emit master caution for max. 3 sec + + public readonly autoThrustOffInvoluntaryNode = new NXLogicMemoryNode(false); + + public autoThrustInhibitCaution = false; // Inhibit for 10 sec + + public readonly autoThrustOffVoluntary = Subject.create(false); + + public readonly autoThrustOffInvoluntary = Subject.create(false); + + public autoThrustOffVoluntaryMemoInhibited = false; + /** TO CONF pressed in phase 2 or 3 SR */ private toConfigCheckedInPhase2Or3 = false; @@ -678,6 +775,14 @@ export class PseudoFWC { private onGroundImmediate = false; + public readonly autoBrakeDeactivatedNode = new NXLogicTriggeredMonostableNode(9, false); // When ABRK deactivated, emit this for 9 sec + + public readonly autoBrakeOffAuralConfirmNode = new NXLogicConfirmNode(1, true); + + public readonly autoBrakeOff = Subject.create(false); + + public autoBrakeOffAuralTriggered = false; + /* NAVIGATION */ private readonly adirsRemainingAlignTime = Subject.create(0); @@ -798,12 +903,22 @@ export class PseudoFWC { private readonly throttle2Position = Subject.create(0); + public readonly allThrottleIdle = Subject.create(false); + private readonly engine1ValueSwitch = ConsumerValue.create(null, false); private readonly engine2ValueSwitch = ConsumerValue.create(null, false); private readonly autoThrustStatus = Subject.create(0); + private readonly atsDiscreteWord = Arinc429Register.empty(); + + private readonly ecu1MaintenanceWord6 = Arinc429Register.empty(); + + private readonly ecu2MaintenanceWord6 = Arinc429Register.empty(); + + private readonly thrLocked = Subject.create(false); + private readonly autothrustLeverWarningFlex = Subject.create(false); private readonly autothrustLeverWarningToga = Subject.create(false); @@ -946,10 +1061,34 @@ export class PseudoFWC { } init(): void { + Promise.all([ + KeyEventManager.getManager(this.bus), + Wait.awaitSubscribable(GameStateProvider.get(), (state) => state === GameState.ingame, true), + ]).then(([keyEventManager]) => { + this.keyEventManager = keyEventManager; + this.registerKeyEvents(); + }); + + this.sub + .on('key_intercept') + .atFrequency(50) + .handle((keyData) => { + switch (keyData.key) { + case 'A32NX.AUTO_THROTTLE_DISCONNECT': + this.autoThrottleInstinctiveDisconnect(); + break; + case 'A32NX.FCU_AP_DISCONNECT_PUSH': + case 'A32NX.AUTOPILOT_DISENGAGE': + case 'AUTOPILOT_OFF': + this.autoPilotInstinctiveDisconnect(); + break; + } + }); + this.toConfigNormal.sub((normal) => SimVar.SetSimVarValue('L:A32NX_TO_CONFIG_NORMAL', 'bool', normal)); this.fwcFlightPhase.sub(() => this.flightPhaseEndedPulseNode.write(true, 0)); - this.auralCrcOutput.sub((crc) => SimVar.SetSimVarValue('L:A32NX_FWC_CRC', 'bool', crc)); + this.auralCrcOutput.sub((crc) => this.soundManager.handleSoundCondition('continuousRepetitiveChime', crc), true); this.masterCaution.sub((caution) => { // Inhibit master warning/cautions until FWC startup has been completed @@ -1017,6 +1156,14 @@ export class PseudoFWC { }); } + private registerKeyEvents() { + this.keyEventManager.interceptKey('A32NX.AUTO_THROTTLE_DISCONNECT', true); + this.keyEventManager.interceptKey('A32NX.FCU_AP_DISCONNECT_PUSH', true); + this.keyEventManager.interceptKey('A32NX.AUTOPILOT_DISENGAGE', false); // internal event, for FWS only + this.keyEventManager.interceptKey('AUTOPILOT_OFF', true); + this.keyEventManager.interceptKey('AUTO_THROTTLE_ARM', true); + } + mapOrder(array, order): [] { array.sort((a, b) => { if (order.indexOf(a) > order.indexOf(b)) { @@ -1094,8 +1241,43 @@ export class PseudoFWC { /** * Periodic update */ - onUpdate() { - const deltaTime = this.instrument.deltaTime; + update(_deltaTime: number) { + const deltaTime = this.fwsUpdateThrottler.canUpdate(_deltaTime); + + // Acquire discrete inputs at a higher frequency, buffer them until the next FWS cycle. + // T.O CONFIG button + if (SimVar.GetSimVarValue('L:A32NX_BTN_TOCONFIG', 'bool')) { + this.toConfigInputBuffer.write(true, false); + } + + // CLR buttons + const clearButtonLeft = SimVar.GetSimVarValue('L:A32NX_BTN_CLR', 'bool'); + const clearButtonRight = SimVar.GetSimVarValue('L:A32NX_BTN_CLR2', 'bool'); + if (clearButtonLeft || clearButtonRight) { + this.clearButtonInputBuffer.write(true, false); + } + + // RCL button + const recallButton = SimVar.GetSimVarValue('L:A32NX_BTN_RCL', 'bool'); + if (recallButton) { + this.recallButtonInputBuffer.write(true, false); + } + + // Enforce cycle time for the logic computation (otherwise pulse nodes would be broken) + if (deltaTime === -1 || _deltaTime === 0) { + return; + } + + // Play sounds + this.soundManager.onUpdate(deltaTime); + + // Write pulse nodes for buffered inputs + this.toConfigPulseNode.write(this.toConfigInputBuffer.read(), deltaTime); + this.clr1PulseNode.write(this.clearButtonInputBuffer.read(), deltaTime); + this.clr2PulseNode.write(this.clearButtonInputBuffer.read(), deltaTime); + this.rclUpPulseNode.write(this.recallButtonInputBuffer.read(), deltaTime); + this.autoThrustInstinctiveDiscPressed.write(this.aThrDiscInputBuffer.read(), deltaTime); + this.autoPilotInstinctiveDiscPressedPulse.write(this.apDiscInputBuffer.read(), deltaTime); // Inputs update this.flightPhaseEndedPulseNode.write(false, deltaTime); @@ -1111,10 +1293,11 @@ export class PseudoFWC { this.flightPhase67.set([6, 7].includes(this.fwcFlightPhase.get())); this.flightPhase78.set([7, 8].includes(this.fwcFlightPhase.get())); const flightPhase567 = [5, 6, 7].includes(this.fwcFlightPhase.get()); + const flightPhase167 = [1, 6, 7].includes(this.fwcFlightPhase.get()); // TO CONFIG button this.toConfigTestRaw = SimVar.GetSimVarValue('L:A32NX_BTN_TOCONFIG', 'bool') > 0; - this.toConfigPulseNode.write(this.toConfigTestRaw, deltaTime); + this.toConfigPulseNode.write(this.toConfigTestRaw, _deltaTime); const toConfigTest = this.toConfigTriggerNode.write(this.toConfigPulseNode.read(), deltaTime); if (toConfigTest !== this.toConfigTest) { // temporary var for the old FWC stuff @@ -1126,17 +1309,11 @@ export class PseudoFWC { ); // CLR buttons - const clearButtonLeft = SimVar.GetSimVarValue('L:A32NX_BTN_CLR', 'bool'); - const clearButtonRight = SimVar.GetSimVarValue('L:A32NX_BTN_CLR2', 'bool'); - this.clr1PulseNode.write(clearButtonLeft, deltaTime); - this.clr2PulseNode.write(clearButtonRight, deltaTime); const previousClrPulseUpTrigger = this.clrPulseUpTrigger.read(); this.clrPulseUpTrigger.write(this.clr1PulseNode.read() || this.clr2PulseNode.read(), deltaTime); this.clrTriggerRisingEdge = !previousClrPulseUpTrigger && this.clrPulseUpTrigger.read(); // RCL button - const recallButton = SimVar.GetSimVarValue('L:A32NX_BTN_RCL', 'bool'); - this.rclUpPulseNode.write(recallButton, deltaTime); const previousRclUpTriggerNode = this.rclUpTriggerNode.read(); this.rclUpTriggerNode.write(recallButton, deltaTime); @@ -1208,8 +1385,17 @@ export class PseudoFWC { this.throttle1Position.set(SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:1', 'number')); this.throttle2Position.set(SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:2', 'number')); this.autoThrustStatus.set(SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_STATUS', 'enum')); + this.atsDiscreteWord.setFromSimVar('L:A32NX_FCU_ATS_DISCRETE_WORD'); + this.ecu1MaintenanceWord6.setFromSimVar('L:A32NX_ECU_1_MAINTENANCE_WORD_6'); + this.ecu2MaintenanceWord6.setFromSimVar('L:A32NX_ECU_2_MAINTENANCE_WORD_6'); this.autothrustLeverWarningFlex.set(SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_THRUST_LEVER_WARNING_FLEX', 'bool')); this.autothrustLeverWarningToga.set(SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_THRUST_LEVER_WARNING_TOGA', 'bool')); + this.allThrottleIdle.set(this.throttle1Position.get() < 1 && this.throttle2Position.get() < 1); + + const masterCautionButtonLeft = SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERCAUT_L', 'bool'); + const masterCautionButtonRight = SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERCAUT_R', 'bool'); + const masterWarningButtonLeft = SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERAWARN_L', 'bool'); + const masterWarningButtonRight = SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERAWARN_R', 'bool'); /* HYDRAULICS acquisition */ @@ -1341,6 +1527,201 @@ export class PseudoFWC { (onGroundCount > 1 && raInvalid); this.aircraftOnGround.set(this.onGroundConf.write(this.onGroundImmediate, deltaTime)); + // AP OFF + const apEngaged: boolean = + SimVar.GetSimVarValue('L:A32NX_FMGC_1_AP_ENGAGED', SimVarValueType.Bool) || + SimVar.GetSimVarValue('L:A32NX_FMGC_2_AP_ENGAGED', SimVarValueType.Bool); + this.autoPilotDisengagedInstantPulse.write(apEngaged, deltaTime); + + const apDiscPressedInLast1p8SecBeforeThisCycle = this.autoPilotInstinctiveDiscPressedInLast1p5Sec.read(); + this.autoPilotInstinctiveDiscPressedInLast1p5Sec.write(this.autoPilotInstinctiveDiscPressedPulse.read(), deltaTime); + + const voluntaryApDisc = + this.autoPilotDisengagedInstantPulse.read() && this.autoPilotInstinctiveDiscPressedInLast1p5Sec.read(); + this.autoPilotOffVoluntaryEndAfter1p5s.write(voluntaryApDisc, deltaTime); + this.autoPilotOffVoluntaryDiscPulse.write(voluntaryApDisc, deltaTime); + + this.autoPilotOffVoluntaryFirstCavalryChargeActive.write(this.autoPilotOffVoluntaryDiscPulse.read(), deltaTime); + this.autoPilotOffVoluntaryFirstCavalryChargeActivePulse.write( + this.autoPilotOffVoluntaryFirstCavalryChargeActive.read(), + deltaTime, + ); + + this.autoPilotInstinctiveDiscPressedTwiceInLast1p5Sec.write( + this.autoPilotInstinctiveDiscPressedPulse.read() && + (this.autoPilotInstinctiveDiscCountSinceLastFwsCycle > 1 || apDiscPressedInLast1p8SecBeforeThisCycle), + deltaTime, + ); + + this.autoPilotOffVoluntaryMemory.write( + this.autoPilotOffVoluntaryDiscPulse.read(), + apEngaged || + this.autoPilotInstinctiveDiscPressedTwiceInLast1p5Sec.read() || + !this.autoPilotOffVoluntaryEndAfter1p5s.read(), + ); + + const discPbPressedAfterDisconnection = + !this.autoPilotDisengagedInstantPulse.read() && + (this.autoPilotInstinctiveDiscPressedPulse.read() || masterWarningButtonLeft || masterWarningButtonRight); + + this.autoPilotOffUnacknowledged.write( + this.autoPilotDisengagedInstantPulse.read(), + apEngaged || this.autoPilotInstinctiveDiscPressedTwiceInLast1p5Sec.read() || discPbPressedAfterDisconnection, + ); + + this.autoPilotOffInvoluntaryMemory.write( + !apEngaged && !this.autoPilotOffVoluntaryMemory.read() && this.autoPilotOffUnacknowledged.read(), + !this.autoPilotOffUnacknowledged.read(), + ); + + this.autoPilotOffAlertShownMemory.write( + this.autoPilotOffInvoluntaryMemory.read(), + this.fwcFlightPhase.get() === 1 || apEngaged, + ); + this.autoPilotOffAlertShown.set(this.autoPilotOffAlertShownMemory.read()); + this.autoPilotOffInvoluntary.set(this.autoPilotOffInvoluntaryMemory.read()); + this.autoPilotOffShowMemo.set(this.autoPilotOffVoluntaryMemory.read() || this.autoPilotOffInvoluntaryMemory.read()); + + if (this.autoPilotDisengagedInstantPulse.read()) { + // Request quiet CRC one time + this.requestMasterWarningFromApOff = true; + this.soundManager.enqueueSound('cavalryChargeOnce'); // On the A320, play first cav charge completely no matter what + } + if (this.autoPilotOffVoluntaryFirstCavalryChargeActivePulse.read()) { + this.soundManager.dequeueSound('cavalryChargeOnce'); + } + if (!this.autoPilotOffVoluntaryMemory.read() && !this.autoPilotOffInvoluntaryMemory.read()) { + this.requestMasterWarningFromApOff = false; + this.soundManager.dequeueSound('cavalryChargeOnce'); + this.soundManager.dequeueSound('cavalryChargeCont'); + } + + this.autoPilotInstinctiveDiscPressedPulse.write(false, deltaTime); + + // approach capability downgrade. Debounce first, then suppress for a certain amount of time + // (to avoid multiple triple clicks, and a delay which is too long) + let fmgcApproachCapability = 0; + const getApproachCapability = (dw3: Arinc429WordData, dw4: Arinc429WordData): number => { + let appCap = 0; + const landModeActive = dw4.bitValueOr(14, false); + const landModeArmed = dw3.bitValueOr(20, false); + const land2Capacity = dw4.bitValueOr(23, false); + const land3FailPassiveCapacity = dw4.bitValueOr(24, false); + const land3FailOperationalCapacity = dw4.bitValueOr(25, false); + + if (land2Capacity) { + appCap = 2; + } else if (land3FailPassiveCapacity) { + appCap = 3; + } else if (land3FailOperationalCapacity) { + appCap = 4; + } else if (landModeActive || landModeArmed) { + appCap = 1; + } else { + appCap = 0; + } + return appCap; + }; + + if (this.fmgc1DiscreteWord3.get().isNormalOperation() && this.fmgc1DiscreteWord4.get().isNormalOperation()) { + fmgcApproachCapability = getApproachCapability(this.fmgc1DiscreteWord3.get(), this.fmgc1DiscreteWord4.get()); + } else if (this.fmgc2DiscreteWord3.get().isNormalOperation() && this.fmgc2DiscreteWord4.get().isNormalOperation()) { + fmgcApproachCapability = getApproachCapability(this.fmgc2DiscreteWord3.get(), this.fmgc2DiscreteWord4.get()); + } + + const capabilityDowngrade = + fmgcApproachCapability < this.fmgcApproachCapability.get() && fmgcApproachCapability > 0; + this.approachCapabilityDowngradeDebounce.write( + capabilityDowngrade && flightPhase167 && !this.approachCapabilityDowngradeSuppress.read(), + deltaTime, + ); + this.approachCapabilityDowngradeDebouncePulse.write(this.approachCapabilityDowngradeDebounce.read(), deltaTime); + this.approachCapabilityDowngradeSuppress.write(this.approachCapabilityDowngradeDebouncePulse.read(), deltaTime); + // Capability downgrade after debounce --> triple click + if (this.approachCapabilityDowngradeDebouncePulse.read()) { + this.soundManager.enqueueSound('pause0p8s'); + this.soundManager.enqueueSound('tripleClick'); + } + this.fmgcApproachCapability.set(fmgcApproachCapability); + + // A/THR OFF + const aThrEngaged = this.atsDiscreteWord.bitValueOr(13, false); + this.autoThrustDisengagedInstantPulse.write(aThrEngaged, deltaTime); + this.autoThrustInstinctiveDiscPressed.write(false, deltaTime); + + const below50ft = this.radioHeight1.valueOr(2500) < 50 && this.radioHeight2.valueOr(2500) < 50; + + if (below50ft && this.allThrottleIdle.get()) { + this.autoThrustInhibitCaution = true; + } + + const voluntaryAThrDisc = + !this.aircraftOnGround.get() && + this.autoThrustDisengagedInstantPulse.read() && + (this.autoThrustInstinctiveDiscPressed.read() || this.allThrottleIdle.get()) && + !this.autoThrustInhibitCaution; + + // Voluntary A/THR disconnect + this.autoThrustOffVoluntaryMemoNode.write(voluntaryAThrDisc && !aThrEngaged, deltaTime); + this.autoThrustOffVoluntaryCautionNode.write(voluntaryAThrDisc && !aThrEngaged, deltaTime); + this.thrLocked.set( + this.ecu1MaintenanceWord6.bitValueOr(12, false) || this.ecu2MaintenanceWord6.bitValueOr(12, false), + ); + + if (!this.autoThrustOffVoluntaryMemoNode.read()) { + this.autoThrustInhibitCaution = false; + } + + if ( + this.autoThrustOffVoluntaryCautionNode.read() && + !this.autoThrustOffVoluntary.get() && + !this.autoThrustInhibitCaution + ) { + // First triggered in this cycle, request master caution + this.requestMasterCautionFromAThrOff = true; + this.requestSingleChimeFromAThrOff = true; + } else if (!this.autoThrustOffVoluntaryCautionNode.read() || this.autoThrustInhibitCaution) { + this.requestMasterCautionFromAThrOff = false; + this.requestSingleChimeFromAThrOff = false; + } + this.autoThrustOffVoluntary.set( + this.autoThrustOffVoluntaryMemoNode.read() && !this.autoThrustInhibitCaution && !aThrEngaged, + ); + + // Involuntary A/THR disconnect + const involuntaryAThrDisc = + !this.aircraftOnGround.get() && + this.autoThrustDisengagedInstantPulse.read() && + !(this.autoThrustInstinctiveDiscPressed.read() || (below50ft && this.allThrottleIdle.get())); + + this.autoThrustOffInvoluntaryNode.write(involuntaryAThrDisc, aThrEngaged || voluntaryAThrDisc); + this.autoThrustOffInvoluntary.set(this.autoThrustOffInvoluntaryNode.read()); + + // AUTO BRAKE OFF + this.autoBrakeDeactivatedNode.write(!!SimVar.GetSimVarValue('L:A32NX_AUTOBRAKES_ACTIVE', 'boolean'), deltaTime); + + if (!this.autoBrakeDeactivatedNode.read()) { + this.requestMasterCautionFromABrkOff = false; + this.autoBrakeOffAuralTriggered = false; + } + + this.autoBrakeOffAuralConfirmNode.write(this.autoBrakeDeactivatedNode.read(), deltaTime); + + const autoBrakeOffShouldTrigger = + this.aircraftOnGround.get() && this.computedAirSpeedToNearest2.get() > 33 && this.autoBrakeDeactivatedNode.read(); + + if (autoBrakeOffShouldTrigger && !this.autoBrakeOff.get()) { + // Triggered in this cycle -> request master caution + this.requestMasterCautionFromABrkOff = true; + } + + // FIXME double callout if ABRK fails + this.autoBrakeOff.set(autoBrakeOffShouldTrigger); + if (autoBrakeOffShouldTrigger && this.autoBrakeOffAuralConfirmNode.read() && !this.autoBrakeOffAuralTriggered) { + this.soundManager.enqueueSound('autoBrakeOff'); + this.autoBrakeOffAuralTriggered = true; + } + // Engine Logic this.thrustLeverNotSet.set(this.autothrustLeverWarningFlex.get() || this.autothrustLeverWarningToga.get()); // FIXME ECU doesn't have the necessary output words so we go purely on TLA @@ -2178,18 +2559,17 @@ export class PseudoFWC { } /* MASTER CAUT/WARN BUTTONS */ - - const masterCautionButtonLeft = SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERCAUT_L', 'bool'); - const masterCautionButtonRight = SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERCAUT_R', 'bool'); - const masterWarningButtonLeft = SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERAWARN_L', 'bool'); - const masterWarningButtonRight = SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERAWARN_R', 'bool'); if (masterCautionButtonLeft || masterCautionButtonRight) { - this.masterCaution.set(false); this.auralSingleChimePending = false; + this.requestMasterCautionFromFaults = false; + this.requestMasterCautionFromABrkOff = false; + this.requestMasterCautionFromAThrOff = false; + this.autoThrustInhibitCaution = true; } if ((masterWarningButtonLeft || masterWarningButtonRight) && this.nonCancellableWarningCount === 0) { - this.masterWarning.set(false); - this.auralCrcActive.set(false); + this.requestMasterWarningFromFaults = this.nonCancellableWarningCount > 0; + this.requestMasterWarningFromApOff = false; + this.auralCrcActive.set(this.nonCancellableWarningCount > 0); } /* T.O. CONFIG CHECK */ @@ -2309,10 +2689,10 @@ export class PseudoFWC { } if (value.failure === 3) { - this.masterWarning.set(true); + this.requestMasterWarningFromFaults = true; } if (value.failure === 2) { - this.masterCaution.set(true); + this.requestMasterCautionFromFaults = true; } } @@ -2378,6 +2758,10 @@ export class PseudoFWC { } auralScKeys.push(key); } + + if (value.auralWarning?.get() === FwcAuralWarning.CavalryCharge) { + this.soundManager.enqueueSound('cavalryChargeCont'); + } } this.auralCrcKeys = auralCrcKeys; @@ -2465,13 +2849,21 @@ export class PseudoFWC { this.ewdMessageLinesLeft.forEach((l, i) => l.set(orderedMemoArrayLeft[i])); if (orderedFailureArrayRight.length === 0) { - this.masterCaution.set(false); + this.requestMasterCautionFromFaults = false; if (this.nonCancellableWarningCount === 0) { - this.masterWarning.set(false); + this.requestMasterWarningFromFaults = false; } } } + this.masterCaution.set( + this.requestMasterCautionFromFaults || + this.requestMasterCautionFromABrkOff || + this.requestMasterCautionFromAThrOff, + ); + + this.masterWarning.set(this.requestMasterWarningFromFaults || this.requestMasterWarningFromApOff); + if (leftFailureSystemCount + rightFailureSystemCount === 0) { SimVar.SetSimVarValue('L:A32NX_ECAM_SFAIL', 'number', -1); } @@ -2491,30 +2883,35 @@ export class PseudoFWC { this.ewdMessageLinesRight.forEach((l, i) => l.set(orderedMemoArrayRight[i])); - // This does not consider interrupting c-chord, priority of synthetic voice etc. - // We shall wait for the rust FWC for those nice things! - if (this.auralSingleChimePending && !this.auralCrcActive.get() && !this.auralSingleChimeInhibitTimer.isPending()) { + const chimeRequested = + (this.auralSingleChimePending || this.requestSingleChimeFromAThrOff) && !this.auralCrcActive.get(); + if (chimeRequested && !this.auralSingleChimeInhibitTimer.isPending()) { this.auralSingleChimePending = false; - SimVar.SetSimVarValue('L:A32NX_FWC_SC', 'bool', true); + this.requestSingleChimeFromAThrOff = false; + this.soundManager.enqueueSound('singleChime'); // there can only be one SC per 2 seconds, non-cumulative, so clear any pending ones at the end of that inhibit period this.auralSingleChimeInhibitTimer.schedule( () => (this.auralSingleChimePending = false), PseudoFWC.AURAL_SC_INHIBIT_TIME, ); - this.auralSingleChimePlayingTimer.schedule( - () => SimVar.SetSimVarValue('L:A32NX_FWC_SC', 'bool', false), - PseudoFWC.AURAL_SC_PLAY_TIME, - ); } this.updateRowRopWarnings(); + + // Reset all buffered inputs + this.toConfigInputBuffer.write(false, true); + this.clearButtonInputBuffer.write(false, true); + this.recallButtonInputBuffer.write(false, true); + this.aThrDiscInputBuffer.write(false, true); + this.apDiscInputBuffer.write(false, true); + this.autoPilotInstinctiveDiscCountSinceLastFwsCycle = 0; } updateRowRopWarnings() { const w = Arinc429Word.fromSimVarValue('L:A32NX_ROW_ROP_WORD_1'); // ROW - SimVar.SetSimVarValue('L:A32NX_AUDIO_ROW_RWY_TOO_SHORT', 'bool', w.bitValueOr(15, false)); + this.soundManager.handleSoundCondition('runwayTooShort', w.bitValueOr(15, false)); // ROP // MAX BRAKING, only for manual braking, if maximum pedal braking is not applied @@ -2522,25 +2919,71 @@ export class PseudoFWC { SimVar.GetSimVarValue('L:A32NX_LEFT_BRAKE_PEDAL_INPUT', 'number') > 90 || SimVar.GetSimVarValue('L:A32NX_RIGHT_BRAKE_PEDAL_INPUT', 'number') > 90; const maxBraking = w.bitValueOr(13, false) && !maxBrakingSet; - SimVar.SetSimVarValue('L:A32NX_AUDIO_ROP_MAX_BRAKING', 'bool', maxBraking); + this.soundManager.handleSoundCondition('brakeMaxBraking', maxBraking); // SET MAX REVERSE, if not already max. reverse set and !MAX_BRAKING const maxReverseSet = SimVar.GetSimVarValue('L:XMLVAR_Throttle1Position', 'number') < 0.1 && SimVar.GetSimVarValue('L:XMLVAR_Throttle2Position', 'number') < 0.1; const maxReverse = (w.bitValueOr(12, false) || w.bitValueOr(13, false)) && !maxReverseSet; - SimVar.SetSimVarValue('L:A32NX_AUDIO_ROW_SET_MAX_REVERSE', 'bool', !maxBraking && maxReverse); + this.soundManager.handleSoundCondition('setMaxReverse', !maxBraking && maxReverse); // At 80kt, KEEP MAX REVERSE once, if max. reversers deployed const ias = SimVar.GetSimVarValue('AIRSPEED INDICATED', 'knots'); - SimVar.SetSimVarValue( - 'L:A32NX_AUDIO_ROP_KEEP_MAX_REVERSE', - 'bool', + this.soundManager.handleSoundCondition( + 'keepMaxReverse', ias <= 80 && ias > 4 && (w.bitValueOr(12, false) || w.bitValueOr(13, false)), ); } + autoThrottleInstinctiveDisconnect() { + // When instinctive A/THR disc. p/b is pressed after ABRK deactivation, inhibit audio+memo, don't request master caution + // Unclear refs, whether this has to happen within the audio confirm node time (1s) + if (this.autoBrakeDeactivatedNode.read()) { + this.requestMasterCautionFromABrkOff = false; + } + + this.aThrDiscInputBuffer.write(true, false); + + if (this.autoThrustOffVoluntary.get()) { + // Pressed a second time -> silence + this.autoThrustInhibitCaution = true; + this.requestMasterCautionFromAThrOff = false; + } + } + + autoPilotInstinctiveDisconnect() { + this.apDiscInputBuffer.write(true, false); + if (this.apDiscInputBuffer.read()) { + this.autoPilotInstinctiveDiscCountSinceLastFwsCycle++; + } + } + ewdMessageFailures: EWDMessageDict = { + // 22 - FLIGHT GUIDANCE + 220800001: { + // AP OFF involuntary + flightPhaseInhib: [], + simVarIsActive: this.autoPilotOffAlertShown, + auralWarning: this.autoPilotOffInvoluntary.map((a) => (a ? FwcAuralWarning.CavalryCharge : FwcAuralWarning.None)), + whichCodeToReturn: () => [0], + codesToReturn: ['220800001'], + memoInhibit: () => false, + failure: 3, + sysPage: -1, + side: 'LEFT', + }, + 220800004: { + // A/THR OFF involuntary + flightPhaseInhib: [3, 4, 8], + simVarIsActive: this.autoThrustOffInvoluntary, + whichCodeToReturn: () => [0, this.thrLocked.get() ? 1 : null], + codesToReturn: ['220800004', '220800005'], + memoInhibit: () => false, + failure: 2, + sysPage: -1, + side: 'LEFT', + }, // 22 - AUTOFLIGHT 2200202: { // FCU 1+2 FAULT @@ -4332,6 +4775,18 @@ export class PseudoFWC { sysPage: -1, side: 'RIGHT', }, + // 32 LANDING GEAR + 320000001: { + // AUTO BRK OFF + flightPhaseInhib: [1, 2, 3, 4, 5, 6, 7, 10], + simVarIsActive: this.autoBrakeOff, + whichCodeToReturn: () => [0], + codesToReturn: ['320000001'], + memoInhibit: () => false, + failure: 0, + sysPage: -1, + side: 'RIGHT', + }, '0000040': { // NW STRG DISC flightPhaseInhib: [], @@ -4630,5 +5085,28 @@ export class PseudoFWC { sysPage: -1, side: 'RIGHT', }, + // 22 - Flight guidance + 220000001: { + // A/THR OFF + flightPhaseInhib: [], + simVarIsActive: this.autoPilotOffShowMemo, + whichCodeToReturn: () => [0], + codesToReturn: ['220000001'], + memoInhibit: () => false, + failure: 0, + sysPage: -1, + side: 'RIGHT', + }, + 220000002: { + // A/THR OFF + flightPhaseInhib: [], + simVarIsActive: this.autoThrustOffVoluntary, + whichCodeToReturn: () => [0], + codesToReturn: ['220000002'], + memoInhibit: () => false, + failure: 0, + sysPage: -1, + side: 'RIGHT', + }, }; } diff --git a/fbw-a32nx/src/systems/systems-host/systems/atsu.ts b/fbw-a32nx/src/systems/systems-host/systems/atsu.ts index 256c359a796..f129b08fe98 100644 --- a/fbw-a32nx/src/systems/systems-host/systems/atsu.ts +++ b/fbw-a32nx/src/systems/systems-host/systems/atsu.ts @@ -6,10 +6,10 @@ import { Atc } from '@datalink/atc'; import { Aoc } from '@datalink/aoc'; import { SimVarHandling } from '@datalink/common'; import { Router } from '@datalink/router'; -import { EventBus, EventSubscriber } from '@microsoft/msfs-sdk'; +import { EventBus, EventSubscriber, Instrument } from '@microsoft/msfs-sdk'; import { PowerSupplyBusTypes } from 'systems-host/systems/powersupply'; -export class AtsuSystem { +export class AtsuSystem implements Instrument { private readonly simVarHandling: SimVarHandling; private readonly powerSupply: EventSubscriber; @@ -40,18 +40,15 @@ export class AtsuSystem { }); } - public connectedCallback(): void { + public init(): void { this.simVarHandling.initialize(); + this.simVarHandling.startPublish(); this.router.initialize(); this.atc.initialize(); this.aoc.initialize(); } - public startPublish(): void { - this.simVarHandling.startPublish(); - } - - public update(): void { + public onUpdate(): void { this.simVarHandling.update(); this.router.update(); } diff --git a/fbw-a32nx/src/systems/systems-host/systems/powersupply.ts b/fbw-a32nx/src/systems/systems-host/systems/powersupply.ts index 0fc4ca65137..796f174d292 100644 --- a/fbw-a32nx/src/systems/systems-host/systems/powersupply.ts +++ b/fbw-a32nx/src/systems/systems-host/systems/powersupply.ts @@ -3,6 +3,7 @@ // SPDX-License-Identifier: GPL-3.0 import { + BackplanePublisher, EventBus, EventSubscriber, Publisher, @@ -53,7 +54,7 @@ export interface PowerSupplyBusTypes { dcBusEss: boolean; } -export class PowerSupplyBusses { +export class PowerSupplyBusses implements BackplanePublisher { private simVarPublisher: PowerSupplySimvarPublisher = null; private subscriber: EventSubscriber = null; @@ -94,22 +95,12 @@ export class PowerSupplyBusses { .handle((powered: number) => this.publisher.pub('dcBusEss', powered !== 0, false, false)); } - public connectedCallback(): void { - this.initialize(); - - this.simVarPublisher.subscribe('msfsAcBus1'); - this.simVarPublisher.subscribe('msfsAcBus2'); - this.simVarPublisher.subscribe('msfsAcBusEss'); - this.simVarPublisher.subscribe('msfsDcBus1'); - this.simVarPublisher.subscribe('msfsDcBus2'); - this.simVarPublisher.subscribe('msfsDcBusEss'); - } - public startPublish(): void { + this.initialize(); this.simVarPublisher.startPublish(); } - public update(): void { + public onUpdate(): void { this.simVarPublisher.onUpdate(); } } diff --git a/fbw-a32nx/src/wasm/fbw_a320/src/interface/SimConnectInterface.cpp b/fbw-a32nx/src/wasm/fbw_a320/src/interface/SimConnectInterface.cpp index 68c39bf1722..6789785aa13 100644 --- a/fbw-a32nx/src/wasm/fbw_a320/src/interface/SimConnectInterface.cpp +++ b/fbw-a32nx/src/wasm/fbw_a320/src/interface/SimConnectInterface.cpp @@ -291,6 +291,7 @@ bool SimConnectInterface::prepareSimInputSimConnectDataDefinitions() { result &= addInputDataDefinition(hSimConnect, 0, Events::AUTOPILOT_DISENGAGE_SET, "AUTOPILOT_DISENGAGE_SET", true); result &= addInputDataDefinition(hSimConnect, 0, Events::AUTOPILOT_DISENGAGE_TOGGLE, "AUTOPILOT_DISENGAGE_TOGGLE", true); result &= addInputDataDefinition(hSimConnect, 0, Events::TOGGLE_FLIGHT_DIRECTOR, "TOGGLE_FLIGHT_DIRECTOR", true); + result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_AUTOPILOT_DISENGAGE, "A32NX.AUTOPILOT_DISENGAGE", false); result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_FCU_AP_1_PUSH, "A32NX.FCU_AP_1_PUSH", false); result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_FCU_AP_2_PUSH, "A32NX.FCU_AP_2_PUSH", false); result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_FCU_AP_DISCONNECT_PUSH, "A32NX.FCU_AP_DISCONNECT_PUSH", false); @@ -397,6 +398,7 @@ bool SimConnectInterface::prepareSimInputSimConnectDataDefinitions() { result &= addInputDataDefinition(hSimConnect, 0, Events::AUTO_THROTTLE_ARM, "AUTO_THROTTLE_ARM", true); result &= addInputDataDefinition(hSimConnect, 0, Events::AUTO_THROTTLE_DISCONNECT, "AUTO_THROTTLE_DISCONNECT", true); + result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_AUTO_THROTTLE_DISCONNECT, "A32NX.AUTO_THROTTLE_DISCONNECT", false); result &= addInputDataDefinition(hSimConnect, 0, Events::AUTO_THROTTLE_TO_GA, "AUTO_THROTTLE_TO_GA", true); result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_ATHR_RESET_DISABLE, "A32NX.ATHR_RESET_DISABLE", false); @@ -1810,6 +1812,9 @@ void SimConnectInterface::processEvent(const DWORD eventId, const DWORD data0, c if (static_cast(data0) == 1) { simInputAutopilot.AP_disconnect = 1; std::cout << "WASM: event triggered: AUTOPILOT_DISENGAGE_SET" << std::endl; + + // Re emitting masked event for autopilot disconnection + sendEvent(SimConnectInterface::Events::A32NX_AUTOPILOT_DISENGAGE, 0, SIMCONNECT_GROUP_PRIORITY_STANDARD); } break; } @@ -2436,6 +2441,9 @@ void SimConnectInterface::processEvent(const DWORD eventId, const DWORD data0, c case Events::AUTO_THROTTLE_DISCONNECT: { simInputThrottles.ATHR_disconnect = 1; std::cout << "WASM: event triggered: AUTO_THROTTLE_DISCONNECT" << std::endl; + + // Re emitting masked event + sendEvent(Events::A32NX_AUTO_THROTTLE_DISCONNECT, 0, SIMCONNECT_GROUP_PRIORITY_STANDARD); break; } diff --git a/fbw-a32nx/src/wasm/fbw_a320/src/interface/SimConnectInterface.h b/fbw-a32nx/src/wasm/fbw_a320/src/interface/SimConnectInterface.h index fe4f980c487..f644c9cfef3 100644 --- a/fbw-a32nx/src/wasm/fbw_a320/src/interface/SimConnectInterface.h +++ b/fbw-a32nx/src/wasm/fbw_a320/src/interface/SimConnectInterface.h @@ -47,6 +47,7 @@ class SimConnectInterface { AUTOPILOT_DISENGAGE_SET, AUTOPILOT_DISENGAGE_TOGGLE, TOGGLE_FLIGHT_DIRECTOR, + A32NX_AUTOPILOT_DISENGAGE, A32NX_FCU_AP_1_PUSH, A32NX_FCU_AP_2_PUSH, A32NX_FCU_AP_DISCONNECT_PUSH, @@ -148,6 +149,7 @@ class SimConnectInterface { BAROMETRIC, AUTO_THROTTLE_ARM, AUTO_THROTTLE_DISCONNECT, + A32NX_AUTO_THROTTLE_DISCONNECT, AUTO_THROTTLE_TO_GA, A32NX_ATHR_RESET_DISABLE, A32NX_THROTTLE_MAPPING_SET_DEFAULTS, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher.tsx index 6d001810ac1..47527dc1641 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher.tsx @@ -5,201 +5,18 @@ import { EventBus, SimVarDefinition, SimVarValueType, SimVarPublisher } from '@microsoft/msfs-sdk'; export type PseudoFwcSimvars = { - acEssBus: boolean; - ewdPotentiometer: number; - autoThrustCommand1: number; - autoThrustCommand2: number; - autoThrustLimit: number; - autoThrustLimitToga: number; - thrustLimitType: number; - autoThrustMode: number; - autoThrustStatus: number; - autoThrustTLA1: number; - autoThrustTLA2: number; - autoThrustWarningToga: boolean; - packs1Supplying: boolean; - packs2Supplying: boolean; - engine1AntiIce: boolean; - engine1EGT: number; - engine1Fadec: boolean; - engine1FF: number; engine1Master: number; - engine1N1: number; - engine1N2: number; - engine1ReverserTransit: boolean; - engine1ReverserDeployed: boolean; - engine1State: number; - engine2AntiIce: boolean; - engine2EGT: number; - engine2Fadec: boolean; - engine2FF: number; engine2Master: number; - engine2N1: number; - engine2N2: number; - engine2ReverserTransit: boolean; - engine2ReverserDeployed: boolean; - engine2State: number; engine3Master: number; engine4Master: number; - wingAntiIce: boolean; - apuBleedPressure: number; - left1LandingGear: boolean; - right1LandingGear: boolean; - throttle1Position: number; - throttle2Position: number; - fwcFlightPhase: number; - idleN1: number; - flexTemp: number; - satRaw: number; - totalFuel: number; - slatsFlapsStatusRaw: number; - slatsPositionRaw: number; - flapsPositionRaw: number; - ewdLowerLeft1: number; - ewdLowerLeft2: number; - ewdLowerLeft3: number; - ewdLowerLeft4: number; - ewdLowerLeft5: number; - ewdLowerLeft6: number; - ewdLowerLeft7: number; - ewdLowerRight1: number; - ewdLowerRight2: number; - ewdLowerRight3: number; - ewdLowerRight4: number; - ewdLowerRight5: number; - ewdLowerRight6: number; - ewdLowerRight7: number; }; -export enum PseudoFwcVars { - acEssBus = 'L:A32NX_ELEC_AC_ESS_BUS_IS_POWERED', - ewdPotentiometer = 'LIGHT POTENTIOMETER:92', - autoThrustCommand1 = 'L:A32NX_AUTOTHRUST_N1_COMMANDED:1', - autoThrustCommand2 = 'L:A32NX_AUTOTHRUST_N1_COMMANDED:2', - autoThrustLimit = 'L:A32NX_AUTOTHRUST_THRUST_LIMIT', - autoThrustLimitToga = 'L:A32NX_AUTOTHRUST_THRUST_LIMIT_TOGA', - thrustLimitType = 'L:A32NX_AUTOTHRUST_THRUST_LIMIT_TYPE', - autoThrustMode = 'L:A32NX_AUTOTHRUST_MODE', - autoThrustStatus = 'L:A32NX_AUTOTHRUST_STATUS', - autoThrustTLA1 = 'L:A32NX_AUTOTHRUST_TLA_N1:1', - autoThrustTLA2 = 'L:A32NX_AUTOTHRUST_TLA_N1:2', - autoThrustWarningToga = 'L:A32NX_AUTOTHRUST_THRUST_LEVER_WARNING_TOGA', - packs1Supplying = 'L:A32NX_COND_PACK_FLOW_VALVE_1_IS_OPEN', - packs2Supplying = 'L:A32NX_COND_PACK_FLOW_VALVE_2_IS_OPEN', - engine1AntiIce = 'L:XMLVAR_Momentary_PUSH_OVHD_ANTIICE_ENG1_Pressed', - engine1EGT = 'L:A32NX_ENGINE_EGT:1', - engine1Fadec = 'L:A32NX_FADEC_POWERED_ENG1', - engine1FF = 'L:A32NX_ENGINE_FF:1', - engine1N1 = 'L:A32NX_ENGINE_N1:1', - engine1N2 = 'L:A32NX_ENGINE_N2:1', - engine1ReverserTransit = 'L:A32NX_REVERSER_1_DEPLOYING', - engine1ReverserDeployed = 'L:A32NX_REVERSER_1_DEPLOYED', - engine1State = 'L:A32NX_ENGINE_STATE:1', - engine2AntiIce = 'L:XMLVAR_Momentary_PUSH_OVHD_ANTIICE_ENG2_Pressed', - engine2EGT = 'L:A32NX_ENGINE_EGT:2', - engine2Fadec = 'L:A32NX_FADEC_POWERED_ENG2', - engine2FF = 'L:A32NX_ENGINE_FF:2', - engine2N1 = 'L:A32NX_ENGINE_N1:2', - engine2N2 = 'L:A32NX_ENGINE_N2:2', - engine2ReverserTransit = 'L:A32NX_REVERSER_2_DEPLOYING', - engine2ReverserDeployed = 'L:A32NX_REVERSER_2_DEPLOYED', - engine2State = 'L:A32NX_ENGINE_STATE:2', - wingAntiIce = 'L:A32NX_PNEU_WING_ANTI_ICE_SYSTEM_SELECTED', - apuBleedPressure = 'L:APU_BLEED_PRESSURE', - left1LandingGear = 'L:A32NX_LGCIU_1_LEFT_GEAR_COMPRESSED', - right1LandingGear = 'L:A32NX_LGCIU_1_RIGHT_GEAR_COMPRESSED', - throttle1Position = 'L:XMLVAR_Throttle1Position', - throttle2Position = 'L:XMLVAR_Throttle2Position', - fwcFlightPhase = 'L:A32NX_FWC_FLIGHT_PHASE', - idleN1 = 'L:A32NX_ENGINE_IDLE_N1', - flexTemp = 'L:AIRLINER_TO_FLEX_TEMP', - satRaw = 'L:A32NX_ADIRS_ADR_1_STATIC_AIR_TEMPERATURE', - totalFuel = 'FUEL TOTAL QUANTITY WEIGHT', - slatsFlapsStatusRaw = 'L:A32NX_SFCC_SLAT_FLAP_SYSTEM_STATUS_WORD', - slatsPositionRaw = 'L:A32NX_SFCC_SLAT_ACTUAL_POSITION_WORD', - flapsPositionRaw = 'L:A32NX_SFCC_FLAP_ACTUAL_POSITION_WORD', - ewdLowerLeft1 = 'L:A32NX_Ewd_LOWER_LEFT_LINE_1', - ewdLowerLeft2 = 'L:A32NX_Ewd_LOWER_LEFT_LINE_2', - ewdLowerLeft3 = 'L:A32NX_Ewd_LOWER_LEFT_LINE_3', - ewdLowerLeft4 = 'L:A32NX_Ewd_LOWER_LEFT_LINE_4', - ewdLowerLeft5 = 'L:A32NX_Ewd_LOWER_LEFT_LINE_5', - ewdLowerLeft6 = 'L:A32NX_Ewd_LOWER_LEFT_LINE_6', - ewdLowerLeft7 = 'L:A32NX_Ewd_LOWER_LEFT_LINE_7', - ewdLowerRight1 = 'L:A32NX_Ewd_LOWER_RIGHT_LINE_1', - ewdLowerRight2 = 'L:A32NX_Ewd_LOWER_RIGHT_LINE_2', - ewdLowerRight3 = 'L:A32NX_Ewd_LOWER_RIGHT_LINE_3', - ewdLowerRight4 = 'L:A32NX_Ewd_LOWER_RIGHT_LINE_4', - ewdLowerRight5 = 'L:A32NX_Ewd_LOWER_RIGHT_LINE_5', - ewdLowerRight6 = 'L:A32NX_Ewd_LOWER_RIGHT_LINE_6', - ewdLowerRight7 = 'L:A32NX_Ewd_LOWER_RIGHT_LINE_7', -} - export class PseudoFwcSimvarPublisher extends SimVarPublisher { private static simvars = new Map([ - ['acEssBus', { name: PseudoFwcVars.acEssBus, type: SimVarValueType.Bool }], - ['ewdPotentiometer', { name: PseudoFwcVars.ewdPotentiometer, type: SimVarValueType.Number }], - ['autoThrustCommand1', { name: PseudoFwcVars.autoThrustCommand1, type: SimVarValueType.Number }], - ['autoThrustCommand2', { name: PseudoFwcVars.autoThrustCommand2, type: SimVarValueType.Number }], - ['autoThrustLimit', { name: PseudoFwcVars.autoThrustLimit, type: SimVarValueType.Number }], - ['autoThrustLimitToga', { name: PseudoFwcVars.autoThrustLimitToga, type: SimVarValueType.Number }], - ['thrustLimitType', { name: PseudoFwcVars.thrustLimitType, type: SimVarValueType.Enum }], - ['autoThrustMode', { name: PseudoFwcVars.autoThrustMode, type: SimVarValueType.Enum }], - ['autoThrustStatus', { name: PseudoFwcVars.autoThrustStatus, type: SimVarValueType.Enum }], - ['autoThrustTLA1', { name: PseudoFwcVars.autoThrustTLA1, type: SimVarValueType.Number }], - ['autoThrustTLA2', { name: PseudoFwcVars.autoThrustTLA2, type: SimVarValueType.Number }], - ['autoThrustWarningToga', { name: PseudoFwcVars.autoThrustWarningToga, type: SimVarValueType.Bool }], - ['packs1Supplying', { name: PseudoFwcVars.packs1Supplying, type: SimVarValueType.Bool }], - ['packs2Supplying', { name: PseudoFwcVars.packs2Supplying, type: SimVarValueType.Bool }], - ['engine1AntiIce', { name: PseudoFwcVars.engine1AntiIce, type: SimVarValueType.Bool }], - ['engine1EGT', { name: PseudoFwcVars.engine1EGT, type: SimVarValueType.Number }], - ['engine1Fadec', { name: PseudoFwcVars.engine1Fadec, type: SimVarValueType.Bool }], ['engine1Master', { name: 'A:FUELSYSTEM VALVE SWITCH:1', type: SimVarValueType.Bool }], - ['engine1FF', { name: PseudoFwcVars.engine1FF, type: SimVarValueType.Number }], - ['engine1N1', { name: PseudoFwcVars.engine1N1, type: SimVarValueType.Number }], - ['engine1N2', { name: PseudoFwcVars.engine1N2, type: SimVarValueType.Number }], - ['engine1ReverserTransit', { name: PseudoFwcVars.engine1ReverserTransit, type: SimVarValueType.Bool }], - ['engine1ReverserDeployed', { name: PseudoFwcVars.engine1ReverserDeployed, type: SimVarValueType.Bool }], - ['engine1State', { name: PseudoFwcVars.engine1State, type: SimVarValueType.Enum }], - ['engine2AntiIce', { name: PseudoFwcVars.engine2AntiIce, type: SimVarValueType.Bool }], - ['engine2EGT', { name: PseudoFwcVars.engine2EGT, type: SimVarValueType.Number }], - ['engine2Fadec', { name: PseudoFwcVars.engine2Fadec, type: SimVarValueType.Bool }], - ['engine2FF', { name: PseudoFwcVars.engine2FF, type: SimVarValueType.Number }], ['engine2Master', { name: 'A:FUELSYSTEM VALVE SWITCH:2', type: SimVarValueType.Bool }], - ['engine2N1', { name: PseudoFwcVars.engine2N1, type: SimVarValueType.Number }], - ['engine2N2', { name: PseudoFwcVars.engine2N2, type: SimVarValueType.Number }], - ['engine2ReverserTransit', { name: PseudoFwcVars.engine2ReverserTransit, type: SimVarValueType.Bool }], - ['engine2ReverserDeployed', { name: PseudoFwcVars.engine2ReverserDeployed, type: SimVarValueType.Bool }], - ['engine2State', { name: PseudoFwcVars.engine2State, type: SimVarValueType.Enum }], ['engine3Master', { name: 'A:FUELSYSTEM VALVE SWITCH:3', type: SimVarValueType.Bool }], ['engine4Master', { name: 'A:FUELSYSTEM VALVE SWITCH:4', type: SimVarValueType.Bool }], - ['wingAntiIce', { name: PseudoFwcVars.wingAntiIce, type: SimVarValueType.Bool }], - ['apuBleedPressure', { name: PseudoFwcVars.apuBleedPressure, type: SimVarValueType.PSI }], - ['left1LandingGear', { name: PseudoFwcVars.left1LandingGear, type: SimVarValueType.Bool }], - ['right1LandingGear', { name: PseudoFwcVars.right1LandingGear, type: SimVarValueType.Bool }], - ['throttle1Position', { name: PseudoFwcVars.throttle1Position, type: SimVarValueType.Number }], - ['throttle2Position', { name: PseudoFwcVars.throttle2Position, type: SimVarValueType.Number }], - ['fwcFlightPhase', { name: PseudoFwcVars.fwcFlightPhase, type: SimVarValueType.Enum }], - ['idleN1', { name: PseudoFwcVars.idleN1, type: SimVarValueType.Number }], - ['flexTemp', { name: PseudoFwcVars.flexTemp, type: SimVarValueType.Number }], - ['satRaw', { name: PseudoFwcVars.satRaw, type: SimVarValueType.Number }], - ['totalFuel', { name: PseudoFwcVars.totalFuel, type: SimVarValueType.Number }], - ['slatsFlapsStatusRaw', { name: PseudoFwcVars.slatsFlapsStatusRaw, type: SimVarValueType.Number }], - ['slatsPositionRaw', { name: PseudoFwcVars.slatsPositionRaw, type: SimVarValueType.Number }], - ['flapsPositionRaw', { name: PseudoFwcVars.flapsPositionRaw, type: SimVarValueType.Number }], - ['ewdLowerLeft1', { name: PseudoFwcVars.ewdLowerLeft1, type: SimVarValueType.Number }], - ['ewdLowerLeft2', { name: PseudoFwcVars.ewdLowerLeft2, type: SimVarValueType.Number }], - ['ewdLowerLeft3', { name: PseudoFwcVars.ewdLowerLeft3, type: SimVarValueType.Number }], - ['ewdLowerLeft4', { name: PseudoFwcVars.ewdLowerLeft4, type: SimVarValueType.Number }], - ['ewdLowerLeft5', { name: PseudoFwcVars.ewdLowerLeft5, type: SimVarValueType.Number }], - ['ewdLowerLeft6', { name: PseudoFwcVars.ewdLowerLeft6, type: SimVarValueType.Number }], - ['ewdLowerLeft7', { name: PseudoFwcVars.ewdLowerLeft7, type: SimVarValueType.Number }], - ['ewdLowerRight1', { name: PseudoFwcVars.ewdLowerRight1, type: SimVarValueType.Number }], - ['ewdLowerRight2', { name: PseudoFwcVars.ewdLowerRight2, type: SimVarValueType.Number }], - ['ewdLowerRight3', { name: PseudoFwcVars.ewdLowerRight3, type: SimVarValueType.Number }], - ['ewdLowerRight4', { name: PseudoFwcVars.ewdLowerRight4, type: SimVarValueType.Number }], - ['ewdLowerRight5', { name: PseudoFwcVars.ewdLowerRight5, type: SimVarValueType.Number }], - ['ewdLowerRight6', { name: PseudoFwcVars.ewdLowerRight6, type: SimVarValueType.Number }], - ['ewdLowerRight7', { name: PseudoFwcVars.ewdLowerRight7, type: SimVarValueType.Number }], ]); public constructor(bus: EventBus) { diff --git a/fbw-a380x/src/systems/instruments/src/PFD/shared/PFDSimvarPublisher.tsx b/fbw-a380x/src/systems/instruments/src/PFD/shared/PFDSimvarPublisher.tsx index b289f68de72..de69cc28db8 100644 --- a/fbw-a380x/src/systems/instruments/src/PFD/shared/PFDSimvarPublisher.tsx +++ b/fbw-a380x/src/systems/instruments/src/PFD/shared/PFDSimvarPublisher.tsx @@ -194,7 +194,7 @@ export enum PFDVars { fmaSpeedProtection = 'L:A32NX_FMA_SPEED_PROTECTION_MODE', AThrMode = 'L:A32NX_AUTOTHRUST_MODE', apVsSelected = 'L:A32NX_AUTOPILOT_VS_SELECTED', - approachCapability = 'L:A32NX_ApproachCapability', + approachCapability = 'L:A32NX_APPROACH_CAPABILITY', ap1Active = 'L:A32NX_AUTOPILOT_1_ACTIVE', ap2Active = 'L:A32NX_AUTOPILOT_2_ACTIVE', fmaVerticalArmed = 'L:A32NX_FMA_VERTICAL_ARMED', diff --git a/fbw-a380x/src/systems/systems-host/index.ts b/fbw-a380x/src/systems/systems-host/index.ts index 1d93a2a0f3d..b8ebac5a4de 100644 --- a/fbw-a380x/src/systems/systems-host/index.ts +++ b/fbw-a380x/src/systems/systems-host/index.ts @@ -11,9 +11,9 @@ import { MappedSubject, SubscribableMapFunctions, WeightBalanceSimvarPublisher, + StallWarningPublisher, } from '@microsoft/msfs-sdk'; import { LegacyGpws } from 'systems-host/systems/LegacyGpws'; -import { LegacyFwc } from 'systems-host/systems/LegacyFwc'; import { LegacyFuel } from 'systems-host/systems/LegacyFuel'; import { LegacySoundManager } from 'systems-host/systems/LegacySoundManager'; import { LegacyTcasComputer } from 'systems-host/systems/tcas/components/LegacyTcasComputer'; @@ -34,6 +34,7 @@ import { AtsuSystem } from 'systems-host/systems/atsu'; import { FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; import { FuelSystemPublisher } from 'systems-host/systems/FuelSystemPublisher'; import { BrakeToVacateDistanceUpdater } from 'systems-host/systems/BrakeToVacateDistanceUpdater'; +import { PseudoFwcSimvarPublisher } from 'instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher'; class SystemsHost extends BaseInstrument { private readonly bus = new ArincEventBus(); @@ -49,9 +50,6 @@ class SystemsHost extends BaseInstrument { private readonly failuresConsumer = new FailuresConsumer('A32NX'); // TODO: Migrate PowerSupplyBusses, if needed - - private fwc: LegacyFwc; - private gpws: LegacyGpws; private soundManager: LegacySoundManager; @@ -97,6 +95,10 @@ class SystemsHost extends BaseInstrument { private readonly fuelSystemPublisher = new FuelSystemPublisher(this.bus); + private readonly stallWarningPublisher = new StallWarningPublisher(this.bus, 0.9); + + private readonly pseudoFwcPublisher = new PseudoFwcSimvarPublisher(this.bus); + private readonly fwsCore = new FwsCore(1, this.bus); //FIXME add some deltatime functionality to backplane instruments so we dont have to pass SystemHost @@ -129,12 +131,13 @@ class SystemsHost extends BaseInstrument { this.backplane.addPublisher('BtvPublisher', this.btvPublisher); this.backplane.addPublisher('Weightpublisher', this.weightAndBalancePublisher); this.backplane.addPublisher('FuelPublisher', this.fuelSystemPublisher); + this.backplane.addPublisher('StallWarning', this.stallWarningPublisher); + this.backplane.addPublisher('PseudoFwc', this.pseudoFwcPublisher); this.backplane.addInstrument('LegacyFuel', this.legacyFuel); this.hEventPublisher = new HEventPublisher(this.bus); - this.fwc = new LegacyFwc(); this.soundManager = new LegacySoundManager(); - this.gpws = new LegacyGpws(this.soundManager); + this.gpws = new LegacyGpws(this.bus, this.soundManager); this.gpws.init(); this.fwsCore.init(); @@ -149,7 +152,6 @@ class SystemsHost extends BaseInstrument { const dt = lastUpdateTime === undefined ? 0 : now - lastUpdateTime; lastUpdateTime = now; - this.fwc.update(dt); this.soundManager.update(dt); this.gpws.update(dt); this.fwsCore.update(dt); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 9e3583db849..f1b7f4b83ab 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -1456,7 +1456,7 @@ export class FwsAbnormalSensed { flightPhaseInhib: [3, 4, 5, 10], simVarIsActive: this.fws.autoThrustOffInvoluntary, notActiveWhenFaults: [], - whichItemsToShow: () => [true], + whichItemsToShow: () => [false], whichItemsChecked: () => [SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_MODE_MESSAGE', 'number') !== 1], failure: 2, sysPage: -1, diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 276c4089590..80e943068d8 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -49,6 +49,8 @@ import { EwdAbnormalItem, FwsAbnormalSensed } from 'systems-host/systems/FlightW import { FwsAbnormalNonSensed } from 'systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed'; import { MfdSurvEvents } from 'instruments/src/MsfsAvionicsCommon/providers/MfdSurvPublisher'; import { Mle, Mmo, VfeF1, VfeF1F, VfeF2, VfeF3, VfeFF, Vle, Vmo } from '@shared/PerformanceConstants'; +import { FwsAuralVolume, FwsSoundManager } from 'systems-host/systems/FlightWarningSystem/FwsSoundManager'; +import { FwcFlightPhase, FwsFlightPhases } from 'systems-host/systems/FlightWarningSystem/FwsFlightPhases'; export function xor(a: boolean, b: boolean): boolean { return !!((a ? 1 : 0) ^ (b ? 1 : 0)); @@ -70,30 +72,29 @@ export enum FwcAuralWarning { CavalryCharge, } -export enum FwcAuralVolume { - Full, // 0 dB - Attenuated, // -6dB - Silent, // -200 dB -} - export class FwsCore { public readonly sub = this.bus.getSubscriber< PseudoFwcSimvars & StallWarningEvents & MfdSurvEvents & FuelSystemEvents & KeyEvents >(); public readonly vhfSub = this.bus.getSubscriber(); - private fwsUpdateThrottler = new UpdateThrottler(125); // has to be > 100 due to pulse nodes + private readonly fwsUpdateThrottler = new UpdateThrottler(125); // has to be > 100 due to pulse nodes private keyEventManager: KeyEventManager; + private readonly startupTimer = new DebounceTimer(); + + private readonly startupCompleted = Subject.create(false); + + public readonly soundManager = new FwsSoundManager(this.bus, this.startupCompleted); + + private readonly flightPhases = new FwsFlightPhases(this); + /** Time to inhibit master warnings and cautions during startup in ms */ private static readonly FWC_STARTUP_TIME = 5000; /** Time to inhibit SCs after one is trigger in ms */ - private static readonly AURAL_SC_INHIBIT_TIME = 5000; - - /** The time to play the single chime sound in ms */ - private static readonly AURAL_SC_PLAY_TIME = 500; + private static readonly AURAL_SC_INHIBIT_TIME = 2000; private static readonly EWD_MESSAGE_LINES = 10; @@ -207,9 +208,6 @@ export class FwsCore { public readonly apDiscInputBuffer = new NXLogicMemoryNode(false); /* PSEUDO FWC VARIABLES */ - private readonly startupTimer = new DebounceTimer(); - - private readonly startupCompleted = Subject.create(false); /** Keys/IDs of all failures currently active, irrespective they are already cleared or not */ public readonly allCurrentFailures: string[] = []; @@ -243,8 +241,6 @@ export class FwsCore { public readonly auralSingleChimePlayingTimer = new DebounceTimer(); - public readonly auralCavalryChargeActive = Subject.create(false); - public readonly masterWarning = Subject.create(false); public readonly masterCaution = Subject.create(false); @@ -266,21 +262,6 @@ export class FwsCore { this.startupCompleted, ); - public readonly auralCrcOutput = MappedSubject.create( - ([auralCrc, startup]) => auralCrc && startup, - this.auralCrcActive, - this.startupCompleted, - ); - - public readonly auralCavalryChargeOutput = MappedSubject.create( - ([auralCavCharge, auralCrc, startup]) => auralCavCharge && !auralCrc && startup, - this.auralCavalryChargeActive, - this.auralCrcOutput, - this.startupCompleted, - ); - - public readonly fwsAuralVolume = Subject.create(FwcAuralVolume.Full); - public readonly ecamStsNormal = Subject.create(true); public readonly fwcOut126 = Arinc429RegisterSubject.createEmpty(); @@ -486,14 +467,17 @@ export class FwsCore { /** 1.8s according to references, but was raised to 1.9s to allow for triple click to finish */ public readonly autoPilotInstinctiveDiscPressedTwiceInLast1p9Sec = new NXLogicTriggeredMonostableNode(1.9, true); + /** Prohibits that CRC can be cancelled before even hearing it */ + public readonly autoPilotFirstCavalryStillWithinFirst0p3s = new NXLogicTriggeredMonostableNode(0.3, true); + public readonly autoPilotInstinctiveDiscPressedPulse = new NXLogicPulseNode(true); /** Stay in first warning stage for 1.8s. Raised to 1.9s to allow for triple click to finish */ public readonly autoPilotOffVoluntaryEndAfter1p9s = new NXLogicTriggeredMonostableNode(1.9, true); - public readonly autoPilotOffVoluntaryFirstCavalryChargeActive = new NXLogicTriggeredMonostableNode(0.8, true); + public readonly autoPilotOffVoluntaryFirstCavalryChargeActive = new NXLogicTriggeredMonostableNode(0.9, true); - public readonly autoPilotOffSendTripleClickAfterFirstCavalryCharge = new NXLogicPulseNode(false); + public readonly autoPilotOffVoluntaryFirstCavalryChargeActivePulse = new NXLogicPulseNode(false); public readonly autoPilotOffVoluntaryDiscPulse = new NXLogicPulseNode(true); @@ -507,6 +491,14 @@ export class FwsCore { public readonly autoPilotOffShowMemo = Subject.create(false); + public readonly approachCapability = Subject.create(0); + + public readonly approachCapabilityDowngradeDebounce = new NXLogicTriggeredMonostableNode(1, true); + + public readonly approachCapabilityDowngradeSuppress = new NXLogicTriggeredMonostableNode(3, true); + + public readonly approachCapabilityDowngradeDebouncePulse = new NXLogicPulseNode(false); + public readonly autoThrustDisengagedInstantPulse = new NXLogicPulseNode(false); public readonly autoThrustInstinctiveDiscPressed = new NXLogicTriggeredMonostableNode(1.5, true); // Save event for 1.5 sec @@ -1035,7 +1027,7 @@ export class FwsCore { /* 31 - FWS */ - public readonly fwcFlightPhase = Subject.create(-1); + public readonly flightPhase = Subject.create(null); public readonly flightPhase128 = Subject.create(false); @@ -1093,8 +1085,6 @@ export class FwsCore { /** If one of the ADR's CAS is above V1 - 4kts, confirm for 0.3s */ public readonly v1SpeedConfirmNode = new NXLogicConfirmNode(0.3); - public readonly v1CalloutOutput = Subject.create(false); - /* LANDING GEAR AND LIGHTS */ public readonly aircraftOnGround = Subject.create(false); @@ -1175,6 +1165,8 @@ export class FwsCore { public readonly autoBrakeOff = Subject.create(false); + public autoBrakeOffAuralTriggered = false; + public autoBrakeOffMemoInhibited = false; /* NAVIGATION */ @@ -1223,6 +1215,8 @@ export class FwsCore { this.fwsNumber === 2 ? this.airDataFoOn3 : this.airDataCaptOn3, ); + public readonly adrPressureAltitude = Subject.create(0); + public readonly ir1MaintWord = Arinc429Register.empty(); public readonly ir2MaintWord = Arinc429Register.empty(); public readonly ir3MaintWord = Arinc429Register.empty(); @@ -1579,22 +1573,14 @@ export class FwsCore { }); this.toConfigNormal.sub((normal) => SimVar.SetSimVarValue('L:A32NX_TO_CONFIG_NORMAL', 'bool', normal)); - this.fwcFlightPhase.sub(() => this.flightPhaseEndedPulseNode.write(true, 0)); + this.flightPhase.sub((fp) => { + SimVar.SetSimVarValue('L:A32NX_FWC_FLIGHT_PHASE', 'Enum', fp || 0); + if (fp !== null) { + this.flightPhaseEndedPulseNode.write(true, 0); + } + }); - this.auralCrcOutput.sub( - (crc) => SimVar.SetSimVarValue('L:A32NX_FWC_CRC', 'bool', this.startupCompleted.get() ? crc : false), - true, - ); - - this.auralCavalryChargeOutput.sub( - (cc) => - SimVar.SetSimVarValue( - 'L:A32NX_FWC_CAVALRY_CHARGE', - SimVarValueType.Bool, - this.startupCompleted.get() ? cc : false, - ), - true, - ); + this.auralCrcActive.sub((crc) => this.soundManager.handleSoundCondition('continuousRepetitiveChime', crc), true); this.masterCautionOutput.sub((caution) => { // Inhibit master warning/cautions until FWC startup has been completed @@ -1606,13 +1592,6 @@ export class FwsCore { SimVar.SetSimVarValue('L:A32NX_MASTER_WARNING', 'bool', warning); }, true); - this.fwsAuralVolume.sub((volume) => { - // Inhibit master warning/cautions until FWC startup has been completed - SimVar.SetSimVarValue('L:A32NX_FWS_AUDIO_VOLUME', SimVarValueType.Enum, volume); - }, true); - - this.v1CalloutOutput.sub((c) => SimVar.SetSimVarValue('L:A32NX_AUDIO_V1_CALLOUT', SimVarValueType.Bool, c), true); - // L/G lever red arrow sinking outputs this.lgLeverRedArrow.sub((on) => { // TODO FWCs need to be powered... @@ -1623,7 +1602,7 @@ export class FwsCore { this.stallWarning.sub((v) => { this.fwcOut126.setBitValue(17, v); // set the sound on/off - SimVar.SetSimVarValue('L:A32NX_AUDIO_STALL_WARNING', 'bool', v); + this.soundManager.handleSoundCondition('stall', v); }, true); this.aircraftOnGround.sub((v) => this.fwcOut126.setBitValue(28, v)); @@ -1832,6 +1811,12 @@ export class FwsCore { // A380X hack: Inject healthy messages for some systems which are not yet implemented this.healthInjector(); + // Update flight phases + this.flightPhases.update(deltaTime); + + // Play sounds + this.soundManager.onUpdate(deltaTime); + // Write pulse nodes for buffered inputs this.toConfigPulseNode.write(this.toConfigInputBuffer.read(), deltaTime); this.clrPulseNode.write(this.clearButtonInputBuffer.read(), deltaTime); @@ -1845,24 +1830,24 @@ export class FwsCore { // Inputs update this.flightPhaseEndedPulseNode.write(false, deltaTime); - this.fwcFlightPhase.set(SimVar.GetSimVarValue('L:A32NX_FWC_FLIGHT_PHASE', 'Enum')); - const phase3 = this.fwcFlightPhase.get() === 3; - const phase6 = this.fwcFlightPhase.get() === 6; + const phase3 = this.flightPhase.get() === 3; + const phase6 = this.flightPhase.get() === 6; this.flightPhase3PulseNode.write(phase3, deltaTime); // flight phase convenience vars - this.flightPhase128.set([1, 2, 8].includes(this.fwcFlightPhase.get())); - this.flightPhase23.set([2, 3].includes(this.fwcFlightPhase.get())); - this.flightPhase345.set([3, 4, 5].includes(this.fwcFlightPhase.get())); + this.flightPhase128.set([1, 2, 8].includes(this.flightPhase.get())); + this.flightPhase23.set([2, 3].includes(this.flightPhase.get())); + this.flightPhase345.set([3, 4, 5].includes(this.flightPhase.get())); this.flightPhase34567.set( - this.flightPhase345.get() || this.fwcFlightPhase.get() === 6 || this.fwcFlightPhase.get() === 7, + this.flightPhase345.get() || this.flightPhase.get() === 6 || this.flightPhase.get() === 7, ); - this.flightPhase1211.set([1, 2, 11].includes(this.fwcFlightPhase.get())); - this.flightPhase89.set([8, 9].includes(this.fwcFlightPhase.get())); - this.flightPhase910.set([9, 10].includes(this.fwcFlightPhase.get())); - const flightPhase6789 = [6, 7, 8, 9].includes(this.fwcFlightPhase.get()); - const flightPhase112 = [1, 12].includes(this.fwcFlightPhase.get()); + this.flightPhase1211.set([1, 2, 11].includes(this.flightPhase.get())); + this.flightPhase89.set([8, 9].includes(this.flightPhase.get())); + this.flightPhase910.set([9, 10].includes(this.flightPhase.get())); + const flightPhase6789 = [6, 7, 8, 9].includes(this.flightPhase.get()); + const flightPhase112 = [1, 12].includes(this.flightPhase.get()); + const flightPhase189 = [1, 8, 9].includes(this.flightPhase.get()); - this.phase815MinConfNode.write(this.fwcFlightPhase.get() === 8, deltaTime); + this.phase815MinConfNode.write(this.flightPhase.get() === 8, deltaTime); this.phase112.set(flightPhase112); // TO CONFIG button @@ -2011,12 +1996,12 @@ export class FwsCore { const yLoPressure = !yellowSysPressurised; this.eng1Or2RunningAndPhaseConfirmationNode.write( - this.engine1Running.get() || this.engine2Running.get() || ![1, 2, 11, 12].includes(this.fwcFlightPhase.get()), + this.engine1Running.get() || this.engine2Running.get() || ![1, 2, 11, 12].includes(this.flightPhase.get()), deltaTime, ); this.eng3Or4RunningAndPhaseConfirmationNode.write( - this.engine3Running.get() || this.engine4Running.get() || ![1, 2, 11, 12].includes(this.fwcFlightPhase.get()), + this.engine3Running.get() || this.engine4Running.get() || ![1, 2, 11, 12].includes(this.flightPhase.get()), deltaTime, ); @@ -2097,7 +2082,7 @@ export class FwsCore { !this.greenRsvLoAirPressure.get() && !this.greenRsvOverheat.get() && !this.greenAbnormLoPressure.get() && - this.fwcFlightPhase.get() === 2 && + this.flightPhase.get() === 2 && !this.eng1APumpAuto.get(), deltaTime, ); @@ -2114,7 +2099,7 @@ export class FwsCore { !this.greenRsvLoAirPressure.get() && !this.greenRsvOverheat.get() && !this.greenAbnormLoPressure.get() && - this.fwcFlightPhase.get() === 2 && + this.flightPhase.get() === 2 && !this.eng1BPumpAuto.get(), deltaTime, ); @@ -2135,7 +2120,7 @@ export class FwsCore { !this.greenRsvLoAirPressure.get() && !this.greenRsvOverheat.get() && !this.greenAbnormLoPressure.get() && - this.fwcFlightPhase.get() === 2 && + this.flightPhase.get() === 2 && !this.eng2APumpAuto.get(), deltaTime, ); @@ -2153,7 +2138,7 @@ export class FwsCore { !this.greenRsvLoAirPressure.get() && !this.greenRsvOverheat.get() && !this.greenAbnormLoPressure.get() && - this.fwcFlightPhase.get() === 2 && + this.flightPhase.get() === 2 && !this.eng2BPumpAuto.get(), deltaTime, ); @@ -2173,7 +2158,7 @@ export class FwsCore { !this.yellowRsvLoAirPressure.get() && !this.yellowRsvOverheat.get() && !this.yellowAbnormLoPressure.get() && - this.fwcFlightPhase.get() === 2 && + this.flightPhase.get() === 2 && !this.eng3APumpAuto.get(), deltaTime, ); @@ -2194,7 +2179,7 @@ export class FwsCore { !this.yellowRsvLoAirPressure.get() && !this.yellowRsvOverheat.get() && !this.yellowAbnormLoPressure.get() && - this.fwcFlightPhase.get() === 2 && + this.flightPhase.get() === 2 && !this.eng3BPumpAuto.get(), deltaTime, ); @@ -2216,7 +2201,7 @@ export class FwsCore { !this.yellowRsvLoAirPressure.get() && !this.yellowRsvOverheat.get() && !this.yellowAbnormLoPressure.get() && - this.fwcFlightPhase.get() === 2 && + this.flightPhase.get() === 2 && !this.eng4APumpAuto, deltaTime, ); @@ -2235,7 +2220,7 @@ export class FwsCore { !this.yellowRsvLoAirPressure.get() && !this.yellowRsvOverheat.get() && !this.yellowAbnormLoPressure.get() && - this.fwcFlightPhase.get() === 2 && + this.flightPhase.get() === 2 && !this.eng4BPumpAuto.get(), deltaTime, ); @@ -2284,8 +2269,9 @@ export class FwsCore { this.adirsRemainingAlignTime.set(SimVar.GetSimVarValue('L:A32NX_ADIRS_REMAINING_IR_ALIGNMENT_TIME', 'Seconds')); // TODO use GPS alt if ADRs not available - const pressureAltitude = - adr1PressureAltitude.valueOr(null) ?? adr2PressureAltitude.valueOr(null) ?? adr3PressureAltitude.valueOr(null); + this.adrPressureAltitude.set( + adr1PressureAltitude.valueOr(null) ?? adr2PressureAltitude.valueOr(null) ?? adr3PressureAltitude.valueOr(null), + ); this.ir1Align.set( this.ir1MaintWord.bitValueOr(16, false) || this.ir1MaintWord.bitValueOr(17, false) || @@ -2319,6 +2305,7 @@ export class FwsCore { /* V1 callout */ const v1 = SimVar.GetSimVarValue('L:AIRLINER_V1_SPEED', SimVarValueType.Knots); const v1Threshold = v1 - 4; + const v1ConfirmNodeStatus = this.v1SpeedConfirmNode.read(); this.v1SpeedConfirmNode.write( v1 && (this.adr1Cas.get().valueOr(0) > v1Threshold || @@ -2326,7 +2313,14 @@ export class FwsCore { this.adr3Cas.get().valueOr(0) > v1Threshold), deltaTime, ); - this.v1CalloutOutput.set(this.fwcFlightPhase.get() === 4 && this.v1SpeedConfirmNode.read()); + if ( + this.flightPhase.get() === 4 && + this.v1SpeedConfirmNode.read() && + !v1ConfirmNodeStatus && + this.v1SpeedConfirmNode.read() + ) { + this.soundManager.enqueueSound('v1'); + } /* LANDING GEAR AND LIGHTS acquisition */ @@ -2447,14 +2441,14 @@ export class FwsCore { this.autoPilotOffVoluntaryDiscPulse.write(voluntaryApDisc, deltaTime); this.autoPilotOffVoluntaryFirstCavalryChargeActive.write(this.autoPilotOffVoluntaryDiscPulse.read(), deltaTime); - this.autoPilotOffSendTripleClickAfterFirstCavalryCharge.write( + this.autoPilotOffVoluntaryFirstCavalryChargeActivePulse.write( this.autoPilotOffVoluntaryFirstCavalryChargeActive.read(), deltaTime, ); - SimVar.SetSimVarValue( - 'L:A32NX_FMA_TRIPLE_CLICK', - 'Bool', - this.autoPilotOffSendTripleClickAfterFirstCavalryCharge.read(), + + this.autoPilotFirstCavalryStillWithinFirst0p3s.write( + this.autoPilotOffVoluntaryFirstCavalryChargeActive.read(), + deltaTime, ); this.autoPilotInstinctiveDiscPressedTwiceInLast1p9Sec.write( @@ -2466,13 +2460,14 @@ export class FwsCore { this.autoPilotOffVoluntaryMemory.write( this.autoPilotOffVoluntaryDiscPulse.read(), apEngaged || - this.autoPilotInstinctiveDiscPressedTwiceInLast1p9Sec.read() || + (this.autoPilotInstinctiveDiscPressedTwiceInLast1p9Sec.read() && + !this.autoPilotFirstCavalryStillWithinFirst0p3s.read()) || !this.autoPilotOffVoluntaryEndAfter1p9s.read(), ); const discPbPressedAfterDisconnection = !this.autoPilotDisengagedInstantPulse.read() && - (this.autoPilotInstinctiveDiscPressedPulse.read() || masterWarningButtonLeft || masterCautionButtonRight); + (this.autoPilotInstinctiveDiscPressedPulse.read() || masterWarningButtonLeft || masterWarningButtonRight); this.autoPilotOffUnacknowledged.write( this.autoPilotDisengagedInstantPulse.read(), @@ -2489,21 +2484,37 @@ export class FwsCore { if (this.autoPilotDisengagedInstantPulse.read()) { // Request quiet CRC one time this.requestMasterWarningFromApOff = true; - this.auralCavalryChargeActive.set(true); - this.fwsAuralVolume.set(FwcAuralVolume.Attenuated); + this.soundManager.setVolume(FwsAuralVolume.Attenuated); + this.soundManager.enqueueSound('cavalryChargeCont'); // On the A380, first cav charge can be cancelled early } - if (!this.autoPilotOffVoluntaryFirstCavalryChargeActive.read()) { - this.auralCavalryChargeActive.set(false); - this.fwsAuralVolume.set(FwcAuralVolume.Full); + if (this.autoPilotOffVoluntaryFirstCavalryChargeActivePulse.read()) { + this.soundManager.dequeueSound('cavalryChargeCont'); + this.soundManager.setVolume(FwsAuralVolume.Full); } if (!this.autoPilotOffVoluntaryMemory.read() && !this.autoPilotOffInvoluntaryMemory.read()) { this.requestMasterWarningFromApOff = false; - this.auralCavalryChargeActive.set(false); - this.fwsAuralVolume.set(FwcAuralVolume.Full); + this.soundManager.dequeueSound('cavalryChargeCont'); + this.soundManager.setVolume(FwsAuralVolume.Full); } this.autoPilotInstinctiveDiscPressedPulse.write(false, deltaTime); + // approach capability downgrade. Debounce first, then suppress for a certain amount of time + // (to avoid multiple triple clicks, and a delay which is too long) + const newCapability = SimVar.GetSimVarValue('L:A32NX_APPROACH_CAPABILITY', SimVarValueType.Number); + const capabilityDowngrade = newCapability < this.approachCapability.get() && newCapability > 0; + this.approachCapabilityDowngradeDebounce.write( + capabilityDowngrade && flightPhase189 && !this.approachCapabilityDowngradeSuppress.read(), + deltaTime, + ); + this.approachCapabilityDowngradeDebouncePulse.write(this.approachCapabilityDowngradeDebounce.read(), deltaTime); + this.approachCapabilityDowngradeSuppress.write(this.approachCapabilityDowngradeDebouncePulse.read(), deltaTime); + // Capability downgrade after debounce --> triple click + if (this.approachCapabilityDowngradeDebouncePulse.read()) { + this.soundManager.enqueueSound('tripleClick'); + } + this.approachCapability.set(newCapability); + // A/THR OFF const aThrEngaged = this.autoThrustStatus.get() === 2 || this.autoThrustMode.get() !== 0; this.autoThrustDisengagedInstantPulse.write(aThrEngaged, deltaTime); @@ -2563,6 +2574,7 @@ export class FwsCore { if (!this.autoBrakeDeactivatedNode.read()) { this.autoBrakeOffMemoInhibited = false; this.requestMasterCautionFromABrkOff = false; + this.autoBrakeOffAuralTriggered = false; } this.autoBrakeOffAuralConfirmNode.write( @@ -2583,11 +2595,10 @@ export class FwsCore { // FIXME double callout if ABRK fails this.autoBrakeOff.set(autoBrakeOffShouldTrigger); - SimVar.SetSimVarValue( - 'L:A32NX_AUDIO_AUTOBRAKE_OFF', - SimVarValueType.Bool, - autoBrakeOffShouldTrigger && this.autoBrakeOffAuralConfirmNode.read(), - ); + if (autoBrakeOffShouldTrigger && this.autoBrakeOffAuralConfirmNode.read() && !this.autoBrakeOffAuralTriggered) { + this.soundManager.enqueueSound('autoBrakeOff'); + this.autoBrakeOffAuralTriggered = true; + } // Engine Logic this.thrustLeverNotSet.set(this.autothrustLeverWarningFlex.get() || this.autothrustLeverWarningToga.get()); @@ -2717,11 +2728,11 @@ export class FwsCore { /* 21 - AIR CONDITIONING AND PRESSURIZATION */ - this.flightLevel.set(Math.round(pressureAltitude / 100)); + this.flightLevel.set(Math.round(this.adrPressureAltitude.get() / 100)); - this.phase8ConfirmationNode60.write(this.fwcFlightPhase.get() === 8, deltaTime); + this.phase8ConfirmationNode60.write(this.flightPhase.get() === 8, deltaTime); - this.phase8ConfirmationNode180.write(this.fwcFlightPhase.get() === 8, deltaTime); + this.phase8ConfirmationNode180.write(this.flightPhase.get() === 8, deltaTime); this.fdac1Channel1Failure.set(SimVar.GetSimVarValue('L:A32NX_COND_FDAC_1_CHANNEL_1_FAILURE', 'bool')); this.fdac1Channel2Failure.set(SimVar.GetSimVarValue('L:A32NX_COND_FDAC_1_CHANNEL_2_FAILURE', 'bool')); @@ -3225,7 +3236,7 @@ export class FwsCore { const flapsNotInToPos = this.flapsSuperiorTo26Deg.get() || this.flapsInferiorTo8Deg.get(); this.flapConfigSr.write( this.flightPhase345.get() && flapsNotInToPos, - !flapsNotInToPos || phase6 || this.fwcFlightPhase.get() === 7, + !flapsNotInToPos || phase6 || this.flightPhase.get() === 7, ); this.flapsNotTo.set(this.flightPhase1211.get() && flapsNotInToPos); this.flapsNotToMemo.set(this.flapConfigSr.read() || this.flapsNotTo.get()); @@ -3240,7 +3251,7 @@ export class FwsCore { const slatsNotInToPos = this.slatsInferiorTo20Deg.get(); this.slatConfigSr.write( this.flightPhase345.get() && slatsNotInToPos, - !slatsNotInToPos || phase6 || this.fwcFlightPhase.get() === 7, + !slatsNotInToPos || phase6 || this.flightPhase.get() === 7, ); this.slatsNotTo.set(this.flightPhase1211.get() && slatsNotInToPos); this.slatConfigAural.set( @@ -3254,7 +3265,7 @@ export class FwsCore { const speedbrakesNotInToPos = fcdc1DiscreteWord4.bitValueOr(28, false) || fcdc2DiscreteWord4.bitValueOr(28, false); this.speedbrakesConfigSr.write( this.flightPhase345.get() && speedbrakesNotInToPos, - !speedbrakesNotInToPos || phase6 || this.fwcFlightPhase.get() === 7, + !speedbrakesNotInToPos || phase6 || this.flightPhase.get() === 7, ); this.speedbrakesNotTo.set(this.flightPhase1211.get() && speedbrakesNotInToPos); this.speedbrakesConfigAural.set( @@ -3283,7 +3294,7 @@ export class FwsCore { ); // taxi in flap 0 one minute check - this.taxiInFlap0Check.write(this.slatFlapSelectionS0F0 && this.fwcFlightPhase.get() == 11, deltaTime); + this.taxiInFlap0Check.write(this.slatFlapSelectionS0F0 && this.flightPhase.get() == 11, deltaTime); this.flapsMcduDisagree.set( (flapsMcduPos1Disagree || flapsMcduPos2Disagree || flapsMcduPos3Disagree) && @@ -3303,7 +3314,7 @@ export class FwsCore { const pitchConfigInPhase3or4or5 = this.flightPhase345.get() && pitchConfig; this.pitchConfigInPhase3or4or5Sr.write( pitchConfigInPhase3or4or5, - phase6 || this.fwcFlightPhase.get() === 7 || !pitchConfig, + phase6 || this.flightPhase.get() === 7 || !pitchConfig, ); this.pitchTrimNotToAudio.set(pitchConfigTestInPhase1211 || pitchConfigInPhase3or4or5); this.pitchTrimNotToWarning.set(pitchConfigTestInPhase1211 || this.pitchConfigInPhase3or4or5Sr.read()); @@ -3349,7 +3360,7 @@ export class FwsCore { (adr1PressureAltitude.valueOr(0) >= 22000 || adr2PressureAltitude.valueOr(0) >= 22000 || adr3PressureAltitude.valueOr(0) >= 22000) && - this.fwcFlightPhase.get() === 8 && + this.flightPhase.get() === 8 && !this.slatFlapSelectionS0F0, ); @@ -3361,13 +3372,13 @@ export class FwsCore { deltaTime, ); this.speedBrakeCaution1Confirm.write( - this.fwcFlightPhase.get() === 8 && + this.flightPhase.get() === 8 && this.speedBrakeCommand50sConfirm.read() && !this.engAboveIdleWithSpeedBrakeConfirm.read(), deltaTime, ); const speedBrakeCaution1 = this.speedBrakeCaution1Confirm.read(); - const speedBrakeCaution2 = this.fwcFlightPhase.get() === 9 && this.speedBrakeCommand5sConfirm.read(); + const speedBrakeCaution2 = this.flightPhase.get() === 9 && this.speedBrakeCommand5sConfirm.read(); // FIXME FCU does not provide the bit, so we synthesize it const apVerticalMode = SimVar.GetSimVarValue('L:A32NX_FMA_VERTICAL_MODE', 'number'); const apTcasRaNoseUp = @@ -3377,7 +3388,7 @@ export class FwsCore { this.apTcasRaNoseUpConfirm.write(apTcasRaNoseUp, deltaTime); this.speedBrakeCaution3Confirm.write( this.speedBrakeCommand.get() && - this.fwcFlightPhase.get() === 8 && + this.flightPhase.get() === 8 && oneEngineAboveMinPower && this.apTcasRaNoseUpConfirm.read(), deltaTime, @@ -3410,7 +3421,7 @@ export class FwsCore { const lgDown = this.lgciu1DiscreteWord1.bitValueOr(29, false) || (this.lgciu2DiscreteWord1.bitValueOr(29, false) && mainGearDownlocked); - this.phase104s5Trigger.write(this.fwcFlightPhase.get() === 10, deltaTime); + this.phase104s5Trigger.write(this.flightPhase.get() === 10, deltaTime); this.groundSpoiler5sDelayed.write( fcdc1DiscreteWord4.bitValueOr(27, false) || fcdc2DiscreteWord4.bitValueOr(27, false), deltaTime, @@ -3433,7 +3444,7 @@ export class FwsCore { ); // l/g gear not down - const fwcFlightPhase = this.fwcFlightPhase.get(); + const fwcFlightPhase = this.flightPhase.get(); const flightPhase4567 = fwcFlightPhase === 4 || fwcFlightPhase === 5 || fwcFlightPhase === 6 || fwcFlightPhase === 7; const flightPhase8 = fwcFlightPhase === 8; @@ -3444,7 +3455,7 @@ export class FwsCore { this.radioHeight3.valueOr(Infinity), ) < 750; const altInhibit = - (pressureAltitude ?? 0) > 18500 && + (this.adrPressureAltitude.get() ?? 0) > 18500 && !this.radioHeight1.isNoComputedData() && !this.radioHeight1.isNormalOperation() && !this.radioHeight2.isNoComputedData() && @@ -3753,7 +3764,7 @@ export class FwsCore { (this.engine1State.get() === 0 && this.engine2State.get() === 0)), ); - const flightPhase = this.fwcFlightPhase.get(); + const flightPhase = this.flightPhase.get(); let tempMemoArrayLeft: string[] = []; let tempMemoArrayRight: string[] = []; const allFailureKeys: string[] = []; @@ -3938,7 +3949,7 @@ export class FwsCore { } if (value.auralWarning?.get() === FwcAuralWarning.CavalryCharge) { - this.auralCavalryChargeActive.set(true); + this.soundManager.enqueueSound('cavalryChargeCont'); } } @@ -4083,26 +4094,17 @@ export class FwsCore { !ewdLimitationsApprLdgKeys.length, ); - // This does not consider interrupting c-chord, priority of synthetic voice etc. - const chimeRequested = this.auralSingleChimePending || this.requestSingleChimeFromAThrOff; - if ( - chimeRequested && - !this.auralCrcActive.get() && - !this.auralCavalryChargeActive.get() && - !this.auralSingleChimeInhibitTimer.isPending() - ) { + const chimeRequested = + (this.auralSingleChimePending || this.requestSingleChimeFromAThrOff) && !this.auralCrcActive.get(); + if (chimeRequested && !this.auralSingleChimeInhibitTimer.isPending()) { this.auralSingleChimePending = false; this.requestSingleChimeFromAThrOff = false; - SimVar.SetSimVarValue('L:A32NX_FWC_SC', 'bool', true); + this.soundManager.enqueueSound('singleChime'); // there can only be one SC per 2 seconds, non-cumulative, so clear any pending ones at the end of that inhibit period this.auralSingleChimeInhibitTimer.schedule( () => (this.auralSingleChimePending = false), FwsCore.AURAL_SC_INHIBIT_TIME, ); - this.auralSingleChimePlayingTimer.schedule( - () => SimVar.SetSimVarValue('L:A32NX_FWC_SC', 'bool', false), - FwsCore.AURAL_SC_PLAY_TIME, - ); } this.normalChecklists.update(); @@ -4126,7 +4128,7 @@ export class FwsCore { const w = Arinc429Word.fromSimVarValue('L:A32NX_ROW_ROP_WORD_1'); // ROW - SimVar.SetSimVarValue('L:A32NX_AUDIO_ROW_RWY_TOO_SHORT', 'bool', w.bitValueOr(15, false)); + this.soundManager.handleSoundCondition('runwayTooShort', w.bitValueOr(15, false)); // ROP // MAX BRAKING, only for manual braking, if maximum pedal braking is not applied @@ -4134,20 +4136,19 @@ export class FwsCore { SimVar.GetSimVarValue('L:A32NX_LEFT_BRAKE_PEDAL_INPUT', 'number') > 90 || SimVar.GetSimVarValue('L:A32NX_RIGHT_BRAKE_PEDAL_INPUT', 'number') > 90; const maxBraking = w.bitValueOr(13, false) && !maxBrakingSet; - SimVar.SetSimVarValue('L:A32NX_AUDIO_ROP_MAX_BRAKING', 'bool', maxBraking); + this.soundManager.handleSoundCondition('brakeMaxBraking', maxBraking); // SET MAX REVERSE, if not already max. reverse set and !MAX_BRAKING const maxReverseSet = SimVar.GetSimVarValue('L:XMLVAR_Throttle1Position', 'number') < 0.1 && SimVar.GetSimVarValue('L:XMLVAR_Throttle2Position', 'number') < 0.1; const maxReverse = (w.bitValueOr(12, false) || w.bitValueOr(13, false)) && !maxReverseSet; - SimVar.SetSimVarValue('L:A32NX_AUDIO_ROW_SET_MAX_REVERSE', 'bool', !maxBraking && maxReverse); + this.soundManager.handleSoundCondition('setMaxReverse', !maxBraking && maxReverse); // At 80kt, KEEP MAX REVERSE once, if max. reversers deployed const ias = SimVar.GetSimVarValue('AIRSPEED INDICATED', 'knots'); - SimVar.SetSimVarValue( - 'L:A32NX_AUDIO_ROP_KEEP_MAX_REVERSE', - 'bool', + this.soundManager.handleSoundCondition( + 'keepMaxReverse', ias <= 80 && ias > 4 && (w.bitValueOr(12, false) || w.bitValueOr(13, false)), ); } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsFlightPhases.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsFlightPhases.ts new file mode 100644 index 00000000000..ef8066cbcd8 --- /dev/null +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsFlightPhases.ts @@ -0,0 +1,534 @@ +/* eslint-disable no-underscore-dangle */ +/* eslint-disable camelcase */ +import { + Arinc429Register, + NXLogicConfirmNode, + NXLogicMemoryNode, + NXLogicTriggeredMonostableNode, +} from '@flybywiresim/fbw-sdk'; +import { FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; + +export enum FwcFlightPhase { + ElecPwr = 1, + FirstEngineStarted = 2, + SecondEngineTakeOffPower = 3, + AtOrAboveEightyKnots = 4, + AtOrAboveV1 = 5, + LiftOff = 6, + AtOrAbove400Feet = 7, + AtOrAbove1500FeetTo800Feet = 8, + AtOrBelow800Feet = 9, + TouchDown = 10, + AtOrBelowEightyKnots = 11, + EnginesShutdown = 12, +} + +// FIXME use subjects from FwsCore +/** + * This nearly a 1:1 port from the A32NX's FWC serves as temporary replacement, until a more sophisticated system simulation is in place. + */ +export class FwsFlightPhases { + toConfigTest: boolean; + + ldgMemo: boolean; + + toMemo: boolean; + + gndMemo: NXLogicConfirmNode; + + oneEngineRunningConf: NXLogicConfirmNode; + + speedAbove80KtsMemo: NXLogicMemoryNode; + + speedAboveV1Memo: NXLogicMemoryNode; + + mctMemo: NXLogicConfirmNode; + + firePBOutConf: NXLogicConfirmNode; + + firePBOutMemo: NXLogicTriggeredMonostableNode; + + firePBClear12: NXLogicMemoryNode; + + phase112Memo: NXLogicTriggeredMonostableNode; + + phase10GroundMemo: NXLogicTriggeredMonostableNode; + + ac80KtsMemo: NXLogicTriggeredMonostableNode; + + prevPhase11InvertMemo: NXLogicTriggeredMonostableNode; + + twoEnginesTOPowerInvertMemo: NXLogicTriggeredMonostableNode; + + phase9Nvm: NXLogicMemoryNode; + + prevPhase11: boolean; + + groundImmediateMemo: NXLogicTriggeredMonostableNode; + + phase6Memo: NXLogicTriggeredMonostableNode; + + phase7Memo: NXLogicTriggeredMonostableNode; + + phase89Memo: NXLogicTriggeredMonostableNode; + + memoTo_conf01: NXLogicConfirmNode; + + memoTo_memo: NXLogicMemoryNode; + + memoLdgMemo_conf01: NXLogicConfirmNode; + + memoLdgMemo_inhibit: NXLogicMemoryNode; + + memoLdgMemo_conf02: NXLogicConfirmNode; + + memoLdgMemo_below2000ft: NXLogicMemoryNode; + + memoToInhibit_conf01: NXLogicConfirmNode; + + memoLdgInhibit_conf01: NXLogicConfirmNode; + + previousTargetAltitude: number; + + _wasBelowThreshold: boolean; + + _wasAboveThreshold: boolean; + + _wasInRange: boolean; + + _wasReach200ft: boolean; + + _cChordShortWasTriggered: boolean; + + aircraft: Aircraft; + + private readonly adrAltitude = Arinc429Register.empty(); + + constructor(private fws: FwsCore) { + // momentary + this.toConfigTest = null; + + // persistent + this.ldgMemo = null; + this.toMemo = null; + + this.gndMemo = new NXLogicConfirmNode(1); + + this.oneEngineRunningConf = new NXLogicConfirmNode(30); + + this.speedAbove80KtsMemo = new NXLogicMemoryNode(true); + + this.speedAboveV1Memo = new NXLogicMemoryNode(); + + this.mctMemo = new NXLogicConfirmNode(60, false); + + this.firePBOutConf = new NXLogicConfirmNode(0.2); + this.firePBOutMemo = new NXLogicTriggeredMonostableNode(2); + this.firePBClear12 = new NXLogicMemoryNode(false); + this.phase112Memo = new NXLogicTriggeredMonostableNode(300); + this.phase10GroundMemo = new NXLogicTriggeredMonostableNode(2); + this.ac80KtsMemo = new NXLogicTriggeredMonostableNode(2); + this.prevPhase11InvertMemo = new NXLogicTriggeredMonostableNode(3, false); + this.twoEnginesTOPowerInvertMemo = new NXLogicTriggeredMonostableNode(1, false); + this.phase9Nvm = new NXLogicMemoryNode(true, true); + this.prevPhase11 = false; + + this.groundImmediateMemo = new NXLogicTriggeredMonostableNode(2); + this.phase6Memo = new NXLogicTriggeredMonostableNode(15); + this.phase7Memo = new NXLogicTriggeredMonostableNode(120); + this.phase89Memo = new NXLogicTriggeredMonostableNode(180); + + this.memoTo_conf01 = new NXLogicConfirmNode(120, true); + this.memoTo_memo = new NXLogicMemoryNode(false); + + this.memoLdgMemo_conf01 = new NXLogicConfirmNode(1, true); + this.memoLdgMemo_inhibit = new NXLogicMemoryNode(false); + this.memoLdgMemo_conf02 = new NXLogicConfirmNode(10, true); + this.memoLdgMemo_below2000ft = new NXLogicMemoryNode(true); + + this.memoToInhibit_conf01 = new NXLogicConfirmNode(3, true); + + this.memoLdgInhibit_conf01 = new NXLogicConfirmNode(3, true); + + // altitude warning + this.previousTargetAltitude = NaN; + this._wasBelowThreshold = false; + this._wasAboveThreshold = false; + this._wasInRange = false; + this._wasReach200ft = false; + } + + update(deltaTime: number) { + this._updateFlightPhase(deltaTime); + this._updateTakeoffMemo(deltaTime); + this._updateLandingMemo(deltaTime); + this._updateAltitudeWarning(); + } + + _updateFlightPhase(_deltaTime: number) { + const raHeight1Invalid = this.fws.radioHeight1.isFailureWarning() || this.fws.radioHeight1.isNoComputedData(); + const raHeight2Invalid = this.fws.radioHeight2.isFailureWarning() || this.fws.radioHeight2.isNoComputedData(); + let radioHeight; + if (raHeight1Invalid) { + if (raHeight2Invalid) { + radioHeight = this.fws.radioHeight3; + } else { + radioHeight = this.fws.radioHeight2; + } + } else { + radioHeight = this.fws.radioHeight1; + } + // TODO find a better source for the following value ("core speed at or above idle") + // Note that N1 starts below idle on spawn on the runway, so this should be below 16 to not jump back to phase 1 + const oneEngRunning = + this.fws.N1Eng1.get() > 15 || + this.fws.N1Eng2.get() > 15 || + this.fws.N1Eng3.get() > 15 || + this.fws.N1Eng4.get() > 15; + const oneEngineRunning = this.oneEngineRunningConf.write(oneEngRunning, _deltaTime); + const noEngineRunning = !oneEngineRunning; + const hFail = + this.fws.radioHeight1.isFailureWarning() && + this.fws.radioHeight2.isFailureWarning() && + this.fws.radioHeight3.isFailureWarning(); + const adcTestInhib = false; + + const groundImmediate = Simplane.getIsGrounded(); + const ground = this.gndMemo.write(groundImmediate, _deltaTime); + + const ias = this.fws.computedAirSpeedToNearest2.get(); + const acSpeedAbove80kts = this.speedAbove80KtsMemo.write(ias > 83, ias < 77); + + const v1 = SimVar.GetSimVarValue('L:AIRLINER_V1_SPEED', 'knots'); + let acAboveV1: boolean; + if (v1) { + acAboveV1 = this.speedAboveV1Memo.write(ias > v1 + 3, ias < v1 - 3); + } else { + acAboveV1 = false; + } + + const hAbv1500 = radioHeight.isNoComputedData() || radioHeight.value > 1500; + const hAbv800 = radioHeight.isNoComputedData() || radioHeight.value > 800; + const hAbv400 = radioHeight.isNoComputedData() || radioHeight.value > 400; + + const eng1TLA = SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:1', 'number'); + const eng1TLAFTO = SimVar.GetSimVarValue('L:A32NX_AIRLINER_TO_FLEX_TEMP', 'number') !== 0; // is a flex temp is set? + const eng1MCT = eng1TLA > 33.3 && eng1TLA < 36.7; + const eng1TLAFullPwr = eng1TLA > 43.3; + const eng1MCL = eng1TLA > 22.9; + const eng1SupMCT = !(eng1TLA < 36.7); + + const eng2TLA = SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:2', 'number'); + const eng2TLAFTO = eng1TLAFTO; // until we have proper FADECs + const eng2MCT = eng2TLA > 33.3 && eng2TLA < 36.7; + const eng2TLAFullPwr = eng2TLA > 43.3; + const eng2MCL = eng2TLA > 22.9; + const eng2SupMCT = !(eng2TLA < 36.7); + + const eng3TLA = SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:3', 'number'); + const eng3TLAFTO = eng1TLAFTO; // until we have proper FADECs + const eng3MCT = eng3TLA > 33.3 && eng3TLA < 36.7; + const eng3TLAFullPwr = eng3TLA > 43.3; + const eng3MCL = eng3TLA > 22.9; + const eng3SupMCT = !(eng3TLA < 36.7); + + const eng4TLA = SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:4', 'number'); + const eng4TLAFTO = eng1TLAFTO; // until we have proper FADECs + const eng4MCT = eng4TLA > 33.3 && eng4TLA < 36.7; + const eng4TLAFullPwr = eng3TLA > 43.3; + const eng4MCL = eng4TLA > 22.9; + const eng4SupMCT = !(eng4TLA < 36.7); + + const twoEnginesMcl = [eng1MCL, eng2MCL, eng3MCL, eng4MCL].filter(Boolean).length >= 2; + const eng1TOPowerSignal = (eng1TLAFTO && eng1MCT) || eng1TLAFullPwr || eng1SupMCT; + const eng2TOPowerSignal = (eng2TLAFTO && eng2MCT) || eng2TLAFullPwr || eng2SupMCT; + const eng3TOPowerSignal = (eng3TLAFTO && eng3MCT) || eng3TLAFullPwr || eng3SupMCT; + const eng4TOPowerSignal = (eng4TLAFTO && eng4MCT) || eng4TLAFullPwr || eng4SupMCT; + + const twoEnginesTOPowerSignal = + [eng1TOPowerSignal, eng2TOPowerSignal, eng3TOPowerSignal, eng4TOPowerSignal].filter(Boolean).length >= 2; + + const twoEnginesTOPower = + twoEnginesTOPowerSignal || + (this.mctMemo.write(twoEnginesTOPowerSignal, _deltaTime) && !hAbv1500 && twoEnginesMcl); + + const eng1FirePbMemo = this.firePBOutMemo.write( + this.firePBOutConf.write(this.fws.fireButtonEng1.get(), _deltaTime), + _deltaTime, + ); + const resetFirePbClear12 = eng1FirePbMemo && ground; + + const phase10 = + (this.phase10GroundMemo.write(groundImmediate, _deltaTime) || groundImmediate) && + !twoEnginesTOPower && + acSpeedAbove80kts; + + const phase345Cond = ground && twoEnginesTOPower; + const phase3 = !acSpeedAbove80kts && oneEngRunning && phase345Cond; + const phase4 = acSpeedAbove80kts && phase345Cond && !acAboveV1; + const phase5 = acSpeedAbove80kts && phase345Cond && acAboveV1; + + const setPhase11Nvm = phase3 || phase10; + const resetPhase11Nvm = + (!this.ac80KtsMemo.write(!acSpeedAbove80kts, _deltaTime) && + ((ground && this.prevPhase11InvertMemo.write(this.prevPhase11, _deltaTime)) || + resetFirePbClear12 || + (ground && this.twoEnginesTOPowerInvertMemo.write(twoEnginesTOPower, _deltaTime))) && + !this.prevPhase11) || + adcTestInhib; + const phase11Nvm = this.phase9Nvm.write(setPhase11Nvm, resetPhase11Nvm); // S* / R (NVM) + const phase211Cond = ground && !twoEnginesTOPower && !acSpeedAbove80kts; + const phase11 = oneEngRunning && phase11Nvm && phase211Cond; + const phase2 = phase211Cond && !phase11Nvm && oneEngRunning; + + const phase112MemoA = this.firePBClear12.write(phase11, resetFirePbClear12); // S / R* + const phase112Cond = !phase11 && noEngineRunning && groundImmediate; + const phase112Memo = this.phase112Memo.write(phase112MemoA && phase112Cond, _deltaTime); + const phase1 = phase112Cond && !phase112Memo; + const phase12 = phase112Cond && phase112Memo; + + this.prevPhase11 = phase11; + + const ground2sMemorized = this.groundImmediateMemo.write(groundImmediate, _deltaTime) || groundImmediate; + + const phase6Cond = !hAbv400 && twoEnginesTOPower && !hFail && !ground2sMemorized; + const phase6 = this.phase6Memo.write(phase6Cond, _deltaTime) && phase6Cond; + + const phase7Cond = !phase6 && !hAbv1500 && twoEnginesTOPower && !hFail && !ground2sMemorized; + const phase7 = this.phase7Memo.write(phase7Cond, _deltaTime) && phase7Cond; + + const phase89Cond = !ground2sMemorized && !hFail && !twoEnginesTOPower && !hAbv1500 && !hAbv800; + const phase89Memo = this.phase89Memo.write(phase89Cond, _deltaTime) && phase89Cond; + + const phase8 = !phase7 && !ground2sMemorized && !phase89Memo; + const phase9 = phase89Memo && !phase10; + + // consolidate into single variable (just to be safe) + const phases = [phase1, phase2, phase3, phase4, phase5, phase6, phase7, phase8, phase9, phase10, phase11, phase12]; + + if (this.fws.flightPhase.get() === null && phases.indexOf(true) !== -1) { + // if we aren't initialized, just grab the first one that is valid + this.fws.flightPhase.set(phases.indexOf(true) + 1); + console.log(`FWC flight phase: ${this.fws.flightPhase.get()}`); + return; + } + + const activePhases = phases + .map((x, i) => [x ? 1 : 0, i + 1]) + .filter((y) => y[0] === 1) + .map((z) => z[1]); + + // the usual and easy case: only one flight phase is valid + if (activePhases.length === 1) { + if (activePhases[0] !== this.fws.flightPhase.get()) { + console.log(`FWC flight phase: ${this.fws.flightPhase.get()} => ${activePhases[0]}`); + this.fws.flightPhase.set(activePhases[0]); + } + return; + } + + // the mixed case => warn + if (activePhases.length > 1) { + if (activePhases.indexOf(this.fws.flightPhase.get()) !== -1) { + // if the currently active one is present, keep it + return; + } + // pick the earliest one + this.fws.flightPhase.set(activePhases[0]); + return; + } + + // otherwise, no flight phase is valid => warn + if (this.fws.flightPhase.get() === null) { + this.fws.flightPhase.set(null); + } + } + + _updateTakeoffMemo(_deltaTime: number) { + const setFlightPhaseMemo = this.fws.flightPhase.get() === FwcFlightPhase.FirstEngineStarted && this.toConfigTest; + const resetFlightPhaseMemo = + this.fws.flightPhase.get() === FwcFlightPhase.EnginesShutdown || + this.fws.flightPhase.get() === FwcFlightPhase.SecondEngineTakeOffPower || + this.fws.flightPhase.get() === FwcFlightPhase.ElecPwr || + this.fws.flightPhase.get() === FwcFlightPhase.AtOrAbove1500FeetTo800Feet; + const flightPhaseMemo = this.memoTo_memo.write(setFlightPhaseMemo, resetFlightPhaseMemo); + + this.fws.engine1Running.get(); + const toTimerElapsed = this.memoTo_conf01.write( + this.fws.engine1Running.get() && + this.fws.engine2Running.get() && + this.fws.engine3Running.get() && + this.fws.engine4Running.get(), + _deltaTime, + ); + + this.toMemo = + flightPhaseMemo || (this.fws.flightPhase.get() === FwcFlightPhase.FirstEngineStarted && toTimerElapsed); + SimVar.SetSimVarValue('L:A32NX_FWC_TOMEMO', 'Bool', this.toMemo); + } + + _updateLandingMemo(_deltaTime: number) { + const radioHeight1Invalid = this.fws.radioHeight1.isFailureWarning() || this.fws.radioHeight1.isNoComputedData(); + const radioHeight2Invalid = this.fws.radioHeight2.isFailureWarning() || this.fws.radioHeight2.isNoComputedData(); + const radioHeight3Invalid = this.fws.radioHeight3.isFailureWarning() || this.fws.radioHeight3.isNoComputedData(); + const gearDownlocked = SimVar.GetSimVarValue('GEAR TOTAL PCT EXTENDED', 'percent') > 0.95; + + const setBelow2000ft = + (this.fws.radioHeight1.value < 2000 && !radioHeight1Invalid) || + (this.fws.radioHeight2.value < 2000 && !radioHeight2Invalid) || + (this.fws.radioHeight3.value < 2000 && !radioHeight3Invalid); + const resetBelow2000ft = + (this.fws.radioHeight1.value > 2200 || radioHeight1Invalid) && + (this.fws.radioHeight2.value > 2200 || radioHeight2Invalid) && + (this.fws.radioHeight3.value > 2200 || radioHeight3Invalid); + const memo2 = this.memoLdgMemo_below2000ft.write(setBelow2000ft, resetBelow2000ft); + + const setInhibitMemo = this.memoLdgMemo_conf01.write( + resetBelow2000ft && !radioHeight1Invalid && !radioHeight2Invalid && !radioHeight3Invalid, + _deltaTime, + ); + const resetInhibitMemo = !( + this.fws.flightPhase.get() === FwcFlightPhase.AtOrBelow800Feet || + this.fws.flightPhase.get() === FwcFlightPhase.TouchDown || + this.fws.flightPhase.get() === FwcFlightPhase.AtOrAbove1500FeetTo800Feet + ); + const memo1 = this.memoLdgMemo_inhibit.write(setInhibitMemo, resetInhibitMemo); + + const showInApproach = memo1 && memo2 && this.fws.flightPhase.get() === FwcFlightPhase.AtOrAbove1500FeetTo800Feet; + + const invalidRadioMemo = this.memoLdgMemo_conf02.write( + radioHeight1Invalid && + radioHeight2Invalid && + radioHeight3Invalid && + gearDownlocked && + this.fws.flightPhase.get() === FwcFlightPhase.AtOrAbove1500FeetTo800Feet, + _deltaTime, + ); + + this.ldgMemo = + showInApproach || + invalidRadioMemo || + this.fws.flightPhase.get() === FwcFlightPhase.TouchDown || + this.fws.flightPhase.get() === FwcFlightPhase.AtOrBelow800Feet; + SimVar.SetSimVarValue('L:A32NX_FWC_LDGMEMO', 'Bool', this.ldgMemo); + } + + _updateAltitudeWarning() { + const warningPressed = + !!SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERAWARN_L', 'Bool') || + !!SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERAWARN_R', 'Bool'); + if (warningPressed === true) { + this._wasBelowThreshold = false; + this._wasAboveThreshold = false; + this._wasInRange = false; + this._cChordShortWasTriggered = false; + this.fws.soundManager.dequeueSound('cChordOnce'); + this.fws.soundManager.dequeueSound('cChordCont'); + return; + } + + if (Simplane.getIsGrounded()) { + this.fws.soundManager.dequeueSound('cChordCont'); + } + + // Use FCU displayed value + const currentAltitudeConstraint = SimVar.GetSimVarValue('L:A32NX_FG_ALTITUDE_CONSTRAINT', 'feet'); + const currentFCUAltitude = SimVar.GetSimVarValue('AUTOPILOT ALTITUDE LOCK VAR:3', 'feet'); + const targetAltitude = + currentAltitudeConstraint && !this.hasAltitudeConstraint() ? currentAltitudeConstraint : currentFCUAltitude; + + // Exit when selected altitude is being changed + if (this.previousTargetAltitude !== targetAltitude) { + this.previousTargetAltitude = targetAltitude; + this._wasBelowThreshold = false; + this._wasAboveThreshold = false; + this._wasInRange = false; + this._wasReach200ft = false; + this._cChordShortWasTriggered = false; + this.fws.soundManager.dequeueSound('cChordOnce'); + this.fws.soundManager.dequeueSound('cChordCont'); + return; + } + + // Exit when: + // - Landing gear down & slats extended + // - Glide slope captured + // - Landing locked down + + const landingGearIsDown = + SimVar.GetSimVarValue('L:A32NX_FLAPS_HANDLE_INDEX', 'Enum') >= 1 && + SimVar.GetSimVarValue('L:A32NX_GEAR_HANDLE_POSITION', 'Percent over 100') > 0.5; + const verticalMode = SimVar.GetSimVarValue('L:A32NX_FMA_VERTICAL_MODE', 'Number'); + const glideSlopeCaptured = verticalMode >= 30 && verticalMode <= 34; + const landingGearIsLockedDown = SimVar.GetSimVarValue('GEAR POSITION:0', 'Enum') > 0.9; + const isTcasResolutionAdvisoryActive = SimVar.GetSimVarValue('L:A32NX_TCAS_STATE', 'Enum') > 1; + if (landingGearIsDown || glideSlopeCaptured || landingGearIsLockedDown || isTcasResolutionAdvisoryActive) { + this._wasBelowThreshold = false; + this._wasAboveThreshold = false; + this._wasInRange = false; + this._wasReach200ft = false; + this._cChordShortWasTriggered = false; + this.fws.soundManager.dequeueSound('cChordOnce'); + this.fws.soundManager.dequeueSound('cChordCont'); + return; + } + + // FIXME better altitude selection + this.adrAltitude.setFromSimVar(`L:A32NX_ADIRS_ADR_1_BARO_CORRECTED_ALTITUDE_${this.fws.fwsNumber}`); + if (!this.adrAltitude.isNormalOperation()) { + return; + } + const delta = Math.abs(this.adrAltitude.value - targetAltitude); + + if (delta < 200) { + this._wasBelowThreshold = true; + this._wasAboveThreshold = false; + this._wasReach200ft = true; + } + if (delta > 750) { + this._wasAboveThreshold = true; + this._wasBelowThreshold = false; + this._cChordShortWasTriggered = false; + } + if (delta >= 200 && delta <= 750) { + this._wasInRange = true; + } + + const apEngaged = + SimVar.GetSimVarValue('L:A32NX_AUTOPILOT_1_ACTIVE', 'Bool') || + SimVar.GetSimVarValue('L:A32NX_AUTOPILOT_2_ACTIVE', 'Bool'); + if (this._wasBelowThreshold && this._wasReach200ft) { + if (delta >= 200) { + this.fws.soundManager.enqueueSound('cChordCont'); + } else { + this.fws.soundManager.dequeueSound('cChordCont'); + } + } else if ( + this._wasAboveThreshold && + delta <= 750 && + !this._wasReach200ft && + !this._cChordShortWasTriggered && + !apEngaged + ) { + this._cChordShortWasTriggered = true; + this.fws.soundManager.dequeueSound('cChordCont'); + this.fws.soundManager.enqueueSound('cChordOnce'); + } else if (delta > 750 && this._wasInRange && !this._wasReach200ft) { + if (delta > 750) { + this.fws.soundManager.enqueueSound('cChordCont'); + } else { + this.fws.soundManager.dequeueSound('cChordCont'); + } + } + } + + hasAltitudeConstraint() { + if ( + Simplane.getAutoPilotAltitudeManaged() && + SimVar.GetSimVarValue('L:AP_CURRENT_TARGET_ALTITUDE_IS_CONSTRAINT', 'number') !== 0 + ) { + return false; + } + return true; + } +} diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsMemos.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsMemos.ts index c4e104543f1..815d4d2bd8e 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsMemos.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsMemos.ts @@ -55,7 +55,7 @@ export class FwsMemos { simVarIsActive: MappedSubject.create( ([speedBrakeCommand, fwcFlightPhase]) => speedBrakeCommand && ![1, 8, 9, 10].includes(fwcFlightPhase), this.fws.speedBrakeCommand, - this.fws.fwcFlightPhase, + this.fws.flightPhase, ), whichCodeToReturn: () => [this.fws.amberSpeedBrake.get() ? 1 : 0], codesToReturn: ['000006001', '000006002'], @@ -353,7 +353,7 @@ export class FwsMemos { // RAT OUT flightPhaseInhib: [], simVarIsActive: this.fws.ratDeployed.map((v) => v > 0), - whichCodeToReturn: () => [[1, 2].includes(this.fws.fwcFlightPhase.get()) ? 0 : 1], + whichCodeToReturn: () => [[1, 2].includes(this.fws.flightPhase.get()) ? 0 : 1], codesToReturn: ['242000001', '242000002'], memoInhibit: () => false, failure: 0, diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsSoundManager.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsSoundManager.ts new file mode 100644 index 00000000000..36696baec36 --- /dev/null +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsSoundManager.ts @@ -0,0 +1,453 @@ +// Copyright (c) 2021-2024 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { EventBus, SimVarValueType, Subscribable } from '@microsoft/msfs-sdk'; + +export interface FwsSoundManagerControlEvents { + enqueueSound: string; + dequeueSound: string; +} + +// Synthetic voice has priority over everything, SC is least important +enum FwsAuralWarningType { + SingleChime, + AuralWarning, + SyntheticVoice, +} + +export enum FwsAuralVolume { + Full, // 0 dB + Attenuated, // -6dB + Silent, // -200 dB +} + +interface FwsAural { + /** The LocalVar which triggers the playback. Not prefixed by L: here. Either localVarName or wwiseEventName has to be defined. */ + localVarName?: string; + /** The Wwise event which triggers the playback. Either localVarName or wwiseEventName has to be defined. */ + wwiseEventName?: string; + /** Sounds are queued based on type and priority (highest priority = gets queued first within same type) */ + priority: number; + type: FwsAuralWarningType; + /** Length of audio in seconds, if non-repetitive */ + length?: number; + /** If this is set, this sound is repeated periodically with the specified pause in seconds */ + periodicWithPause?: number; + continuous?: boolean; +} + +export const FwsAuralsList: Record = { + continuousRepetitiveChime: { + localVarName: 'A32NX_FWC_CRC', + priority: 5, + type: FwsAuralWarningType.AuralWarning, + continuous: true, + }, + singleChime: { + localVarName: 'A32NX_FWC_SC', + length: 0.54, + priority: 0, + type: FwsAuralWarningType.SingleChime, + continuous: false, + }, + cavalryChargeOnce: { + localVarName: 'A32NX_FWC_CAVALRY_CHARGE', + length: 0.9, + priority: 4, + type: FwsAuralWarningType.AuralWarning, + continuous: false, + }, + cavalryChargeCont: { + localVarName: 'A32NX_FWC_CAVALRY_CHARGE', + priority: 4, + type: FwsAuralWarningType.AuralWarning, + continuous: true, + }, + tripleClick: { + localVarName: 'A32NX_FMA_TRIPLE_CLICK', + length: 0.62, + priority: 3, + type: FwsAuralWarningType.AuralWarning, + continuous: false, + }, + v1: { + localVarName: 'A32NX_AUDIO_V1_CALLOUT', + length: 1.3, + priority: 1, + type: FwsAuralWarningType.SyntheticVoice, + continuous: false, + }, + autoBrakeOff: { + localVarName: 'A32NX_AUDIO_AUTOBRAKE_OFF', + length: 1.5, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + continuous: false, + }, + runwayTooShort: { + localVarName: 'A32NX_AUDIO_ROW_RWY_TOO_SHORT', + length: 1.6, + priority: 4, + type: FwsAuralWarningType.SyntheticVoice, + continuous: true, + }, + keepMaxReverse: { + localVarName: 'A32NX_AUDIO_ROP_KEEP_MAX_REVERSE', + length: 1.4, + priority: 4, + type: FwsAuralWarningType.SyntheticVoice, + continuous: false, + }, + setMaxReverse: { + localVarName: 'A32NX_AUDIO_ROW_SET_MAX_REVERSE', + length: 1.62, + priority: 4, + type: FwsAuralWarningType.SyntheticVoice, + continuous: false, + }, + brakeMaxBraking: { + localVarName: 'A32NX_AUDIO_ROP_MAX_BRAKING', + length: 3.1, + priority: 4, + type: FwsAuralWarningType.SyntheticVoice, + continuous: true, + }, + stall: { + localVarName: 'A32NX_AUDIO_ROP_MAX_BRAKING', + length: 3.0, + priority: 5, + type: FwsAuralWarningType.SyntheticVoice, + continuous: true, + }, + cChordOnce: { + localVarName: 'A32NX_ALT_DEVIATION', + length: 1.0, + priority: 3, + type: FwsAuralWarningType.AuralWarning, + continuous: false, + }, + cChordCont: { + localVarName: 'A32NX_ALT_DEVIATION', + priority: 3, + type: FwsAuralWarningType.AuralWarning, + continuous: true, + }, + // Altitude callouts + minimums: { + wwiseEventName: 'aural_minimumnew', + length: 0.67, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + hundred_above: { + wwiseEventName: 'aural_100above', + length: 0.72, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + retard: { + wwiseEventName: 'new_retard', + length: 0.9, + periodicWithPause: 0.2, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_2500: { + wwiseEventName: 'new_2500', + length: 1.1, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_2500b: { + wwiseEventName: 'new_2_500', + length: 1.047, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_2000: { + wwiseEventName: 'new_2000', + length: 0.72, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_1000: { + wwiseEventName: 'new_1000', + length: 0.9, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_500: { + wwiseEventName: 'new_500', + length: 0.6, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_400: { + wwiseEventName: 'new_400', + length: 0.6, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_300: { + wwiseEventName: 'new_300', + length: 0.6, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_200: { + wwiseEventName: 'new_200', + length: 0.6, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_100: { + wwiseEventName: 'new_100', + length: 0.6, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_90: { + wwiseEventName: '90_380', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_80: { + wwiseEventName: '80_380', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_70: { + wwiseEventName: '70_380', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_60: { + wwiseEventName: '60_380', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_50: { + wwiseEventName: '50_380', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_40: { + wwiseEventName: '40_380', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_30: { + wwiseEventName: '30_380', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_20: { + wwiseEventName: '20_380', + length: 0.4, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_10: { + wwiseEventName: '10_380', + length: 0.3, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, + alt_5: { + wwiseEventName: '5_380', + length: 0.3, + priority: 2, + type: FwsAuralWarningType.SyntheticVoice, + }, +}; + +// FIXME Not all sounds are added to this yet (e.g. CIDS chimes), consider adding them in the future +// Also, single chimes are not filtered (in RL only once every two seconds) +export class FwsSoundManager { + private readonly soundQueue = new Set(); + + private singleChimesPending = 0; + + private currentSoundPlaying: keyof typeof FwsAuralsList | null = null; + + /** in seconds */ + private currentSoundPlayTimeRemaining = 0; + + constructor( + private bus: EventBus, + private startupCompleted: Subscribable, + ) { + // Stop all sounds + Object.values(FwsAuralsList).forEach((a) => { + if (a.localVarName) { + SimVar.SetSimVarValue(`L:${a.localVarName}`, SimVarValueType.Bool, false); + } + }); + + const sub = this.bus.getSubscriber(); + sub.on('enqueueSound').handle((s) => this.enqueueSound(s)); + sub.on('dequeueSound').handle((s) => this.dequeueSound(s)); + } + + /** Add sound to queue. Don't add if already playing */ + enqueueSound(soundKey: keyof typeof FwsAuralsList) { + const sound = FwsAuralsList[soundKey]; + if (!sound || this.currentSoundPlaying === soundKey) { + return; + } + + if (sound.type === FwsAuralWarningType.SyntheticVoice || sound.type === FwsAuralWarningType.AuralWarning) { + this.soundQueue.add(soundKey); + } else if (sound.type === FwsAuralWarningType.SingleChime) { + this.singleChimesPending++; + } + } + + /** Remove sound from queue, e.g. when condition doesn't apply anymore. If sound is currently playing, stops sound immediately */ + dequeueSound(soundKey: keyof typeof FwsAuralsList) { + // Check if this sound is currently playing + if (this.currentSoundPlaying === soundKey && FwsAuralsList[this.currentSoundPlaying]?.continuous) { + this.stopCurrentSound(); + } + this.soundQueue.delete(soundKey); + } + + private stopCurrentSound() { + // Only LVar sounds which are continuous can be stopped + if ( + this.currentSoundPlaying && + FwsAuralsList[this.currentSoundPlaying].localVarName && + FwsAuralsList[this.currentSoundPlaying]?.continuous + ) { + SimVar.SetSimVarValue(`L:${FwsAuralsList[this.currentSoundPlaying].localVarName}`, SimVarValueType.Bool, false); + this.currentSoundPlaying = null; + this.currentSoundPlayTimeRemaining = 0; + } + } + + /** + * Convenience function for FWS: If condition true and sound not already playing, add to queue. If not, dequeue sound + * */ + handleSoundCondition(soundKey: keyof typeof FwsAuralsList, condition: boolean) { + if (condition && this.currentSoundPlaying !== soundKey) { + this.enqueueSound(soundKey); + } else if (!condition) { + this.dequeueSound(soundKey); + } + } + + /** This only has an effect on sounds defining WwiseRTPC behavior/var for volume */ + setVolume(volume: FwsAuralVolume) { + SimVar.SetSimVarValue('L:A32NX_FWS_AUDIO_VOLUME', SimVarValueType.Enum, volume); + } + + /** Play now, not to be called from the outside */ + private playSound(soundKey: keyof typeof FwsAuralsList) { + const sound = FwsAuralsList[soundKey]; + if (!sound) { + return; + } + + if (sound.localVarName) { + SimVar.SetSimVarValue(`L:${sound.localVarName}`, SimVarValueType.Bool, true); + } else if (sound.wwiseEventName) { + Coherent.call('PLAY_INSTRUMENT_SOUND', sound.wwiseEventName); + } + this.currentSoundPlaying = soundKey; + this.currentSoundPlayTimeRemaining = sound.continuous ? Infinity : sound.length; + this.soundQueue.delete(soundKey); + } + + /** Find most important sound from soundQueue and play */ + private selectAndPlayMostImportantSound(): keyof typeof FwsAuralsList | null { + if (!this.startupCompleted.get()) { + return; + } + + // Logic for scheduling new sounds: Take sound from soundQueue of most important type + // (SyntheticVoice > AuralWarning > SingleChime) with highest priority, and play it + let selectedSoundKey: keyof typeof FwsAuralsList | null = null; + this.soundQueue.forEach((sk) => { + const s = FwsAuralsList[sk]; + if ( + selectedSoundKey === null || + s.type > FwsAuralsList[selectedSoundKey].type || + (s.type === FwsAuralsList[selectedSoundKey].type && s.priority > FwsAuralsList[selectedSoundKey].priority) + ) { + selectedSoundKey = sk; + } + }); + + if (selectedSoundKey) { + this.playSound(selectedSoundKey); + return selectedSoundKey; + } + + // See if single chimes are left + if (this.singleChimesPending) { + this.playSound('singleChime'); + this.singleChimesPending--; + return 'singleChime'; + } + + // Ok, nothing to play + return null; + } + + onUpdate(deltaTime: number) { + // Either wait for the current sound to finish, or schedule the next sound + if (this.currentSoundPlaying && this.currentSoundPlayTimeRemaining > 0) { + if (this.currentSoundPlayTimeRemaining - deltaTime / 1_000 > 0) { + // Wait for sound to be finished + this.currentSoundPlayTimeRemaining -= deltaTime / 1_000; + } else { + // Sound finishes in this cycle + if (FwsAuralsList[this.currentSoundPlaying].localVarName) { + SimVar.SetSimVarValue( + `L:${FwsAuralsList[this.currentSoundPlaying].localVarName}`, + SimVarValueType.Bool, + false, + ); + } + this.currentSoundPlaying = null; + this.currentSoundPlayTimeRemaining = 0; + } + + // Interrupt if sound with higher category is present in queue and current sound is continuous + let shouldInterrupt = false; + let rescheduleSound: keyof typeof FwsAuralsList | null = null; + this.soundQueue.forEach((sk) => { + const s = FwsAuralsList[sk]; + if ( + s && + this.currentSoundPlaying && + FwsAuralsList[this.currentSoundPlaying]?.continuous && + s.type > FwsAuralsList[this.currentSoundPlaying].type + ) { + shouldInterrupt = true; + } + }); + + if (shouldInterrupt) { + if (this.currentSoundPlaying && FwsAuralsList[this.currentSoundPlaying]?.continuous) { + rescheduleSound = this.currentSoundPlaying; + this.stopCurrentSound(); + if (rescheduleSound) { + this.enqueueSound(rescheduleSound); + } + } + } + } else { + // Play next sound + this.selectAndPlayMostImportantSound(); + } + } +} diff --git a/fbw-a380x/src/systems/systems-host/systems/LegacyFwc.ts b/fbw-a380x/src/systems/systems-host/systems/LegacyFwc.ts deleted file mode 100644 index 9ee2596a8f5..00000000000 --- a/fbw-a380x/src/systems/systems-host/systems/LegacyFwc.ts +++ /dev/null @@ -1,727 +0,0 @@ -/* eslint-disable no-underscore-dangle */ -/* eslint-disable camelcase */ -// TODO remove this once Rust implementation is up and running -import { Arinc429Word, UpdateThrottler } from '@flybywiresim/fbw-sdk'; - -enum FwcFlightPhase { - ElecPwr = 1, - FirstEngineStarted = 2, - SecondEngineTakeOffPower = 3, - AtOrAboveEightyKnots = 4, - AtOrAboveV1 = 5, - LiftOff = 6, - AtOrAbove400Feet = 7, - AtOrAbove1500FeetTo800Feet = 8, - AtOrBelow800Feet = 9, - TouchDown = 10, - AtOrBelowEightyKnots = 11, - EnginesShutdown = 12, -} - -/** - * This 1:1 port from the A32NX's FWC serves as temporary replacement, until a more sophisticated system simulation is in place. - * After merge of PR #4872 (https://github.com/flybywiresim/aircraft/pull/4872) (intended for A32NX), the FWS architecture has to - * be ported to the A380X, then this class can be removed. - */ -export class LegacyFwc { - private updateThrottler = new UpdateThrottler(125); // has to be > 100 due to pulse nodes - - toConfigTest: boolean; - - flightPhase: FwcFlightPhase; - - ldgMemo: boolean; - - toMemo: boolean; - - gndMemo: NXLogic_ConfirmNode; - - oneEngineRunningConf: NXLogic_ConfirmNode; - - speedAbove80KtsMemo: NXLogic_MemoryNode; - - speedAboveV1Memo: NXLogic_MemoryNode; - - mctMemo: NXLogic_ConfirmNode; - - firePBOutConf: NXLogic_ConfirmNode; - - firePBOutMemo: NXLogic_TriggeredMonostableNode; - - firePBClear12: NXLogic_MemoryNode; - - phase112Memo: NXLogic_TriggeredMonostableNode; - - phase10GroundMemo: NXLogic_TriggeredMonostableNode; - - ac80KtsMemo: NXLogic_TriggeredMonostableNode; - - prevPhase11InvertMemo: NXLogic_TriggeredMonostableNode; - - twoEnginesTOPowerInvertMemo: NXLogic_TriggeredMonostableNode; - - phase9Nvm: NXLogic_MemoryNode; - - prevPhase11: boolean; - - groundImmediateMemo: NXLogic_TriggeredMonostableNode; - - phase6Memo: NXLogic_TriggeredMonostableNode; - - phase7Memo: NXLogic_TriggeredMonostableNode; - - phase89Memo: NXLogic_TriggeredMonostableNode; - - memoTo_conf01: NXLogic_ConfirmNode; - - memoTo_memo: NXLogic_MemoryNode; - - memoLdgMemo_conf01: NXLogic_ConfirmNode; - - memoLdgMemo_inhibit: NXLogic_MemoryNode; - - memoLdgMemo_conf02: NXLogic_ConfirmNode; - - memoLdgMemo_below2000ft: NXLogic_MemoryNode; - - memoToInhibit_conf01: NXLogic_ConfirmNode; - - memoLdgInhibit_conf01: NXLogic_ConfirmNode; - - previousTargetAltitude: number; - - _wasBellowThreshold: boolean; - - _wasAboveThreshold: boolean; - - _wasInRange: boolean; - - _wasReach200ft: boolean; - - aircraft: Aircraft; - - constructor() { - // momentary - this.toConfigTest = null; // WTOCT - - // persistent - this.flightPhase = null; - this.ldgMemo = null; - this.toMemo = null; - - // ESDL 1. 0. 60 - this.gndMemo = new NXLogic_ConfirmNode(1); // outptuts ZGND - - // ESDL 1. 0. 60 - this.oneEngineRunningConf = new NXLogic_ConfirmNode(30); - - // ESDL 1. 0. 73 - this.speedAbove80KtsMemo = new NXLogic_MemoryNode(true); - - this.speedAboveV1Memo = new NXLogic_MemoryNode(); - - // ESDL 1. 0. 79 / ESDL 1. 0. 80 - this.mctMemo = new NXLogic_ConfirmNode(60, false); - - // ESDL 1. 0.100 - this.firePBOutConf = new NXLogic_ConfirmNode(0.2); // CONF01 - this.firePBOutMemo = new NXLogic_TriggeredMonostableNode(2); // MTRIG 05 - this.firePBClear12 = new NXLogic_MemoryNode(false); - this.phase112Memo = new NXLogic_TriggeredMonostableNode(300); // MTRIG 03 - this.phase10GroundMemo = new NXLogic_TriggeredMonostableNode(2); // MTRIG 06 - this.ac80KtsMemo = new NXLogic_TriggeredMonostableNode(2); // MTRIG 04 - this.prevPhase11InvertMemo = new NXLogic_TriggeredMonostableNode(3, false); // MTRIG 02 - this.twoEnginesTOPowerInvertMemo = new NXLogic_TriggeredMonostableNode(1, false); // MTRIG 01 - this.phase9Nvm = new NXLogic_MemoryNode(true, true); - this.prevPhase11 = false; - - // ESDL 1. 0.110 - this.groundImmediateMemo = new NXLogic_TriggeredMonostableNode(2); // MTRIG 03 - this.phase6Memo = new NXLogic_TriggeredMonostableNode(15); - this.phase7Memo = new NXLogic_TriggeredMonostableNode(120); - this.phase89Memo = new NXLogic_TriggeredMonostableNode(180); // MTRIG 02 - - // ESDL 1. 0.180 - this.memoTo_conf01 = new NXLogic_ConfirmNode(120, true); // CONF 01 - this.memoTo_memo = new NXLogic_MemoryNode(false); - - // ESDL 1. 0.190 - this.memoLdgMemo_conf01 = new NXLogic_ConfirmNode(1, true); // CONF 01 - this.memoLdgMemo_inhibit = new NXLogic_MemoryNode(false); - this.memoLdgMemo_conf02 = new NXLogic_ConfirmNode(10, true); // CONF 01 - this.memoLdgMemo_below2000ft = new NXLogic_MemoryNode(true); - - // ESDL 1. 0.310 - this.memoToInhibit_conf01 = new NXLogic_ConfirmNode(3, true); // CONF 01 - - // ESDL 1. 0.320 - this.memoLdgInhibit_conf01 = new NXLogic_ConfirmNode(3, true); // CONF 01 - - // altitude warning - this.previousTargetAltitude = NaN; - this._wasBellowThreshold = false; - this._wasAboveThreshold = false; - this._wasInRange = false; - this._wasReach200ft = false; - } - - update(_deltaTime: number) { - const throttledT = this.updateThrottler.canUpdate(_deltaTime); - - if (throttledT > 0) { - this._updateFlightPhase(throttledT); - this._updateTakeoffMemo(throttledT); - this._updateLandingMemo(throttledT); - this._updateAltitudeWarning(); - } - } - - _updateFlightPhase(_deltaTime: number) { - const radioHeight1 = Arinc429Word.fromSimVarValue('L:A32NX_RA_1_RADIO_ALTITUDE'); - const radioHeight2 = Arinc429Word.fromSimVarValue('L:A32NX_RA_2_RADIO_ALTITUDE'); - const radioHeight3 = Arinc429Word.fromSimVarValue('L:A32NX_RA_3_RADIO_ALTITUDE'); - - const raHeight1InValid = radioHeight1.isFailureWarning() || radioHeight1.isNoComputedData(); - const raHeight2InValid = radioHeight2.isFailureWarning() || radioHeight2.isNoComputedData(); - let radioHeight; - if (raHeight1InValid) { - if (raHeight2InValid) { - radioHeight = radioHeight3; - } else { - radioHeight = radioHeight2; - } - } else { - radioHeight = radioHeight1; - } - const eng1N1 = SimVar.GetSimVarValue('ENG N1 RPM:1', 'Percent'); - const eng2N1 = SimVar.GetSimVarValue('ENG N1 RPM:2', 'Percent'); - const eng3N1 = SimVar.GetSimVarValue('ENG N1 RPM:3', 'Percent'); - const eng4N1 = SimVar.GetSimVarValue('ENG N1 RPM:4', 'Percent'); - // TODO find a better source for the following value ("core speed at or above idle") - // Note that N1 starts below idle on spawn on the runway, so this should be below 16 to not jump back to phase 1 - const oneEngRunning = eng1N1 > 15 || eng2N1 > 15 || eng3N1 > 15 || eng4N1 > 15; - const oneEngineRunning = this.oneEngineRunningConf.write(oneEngRunning, _deltaTime); - const noEngineRunning = !oneEngineRunning; - const hFail = radioHeight1.isFailureWarning() && radioHeight2.isFailureWarning() && radioHeight3.isFailureWarning(); - const adcTestInhib = false; - - // ESLD 1.0.60 - const groundImmediate = Simplane.getIsGrounded(); - const ground = this.gndMemo.write(groundImmediate, _deltaTime); - - // ESLD 1.0.73 - const ias = SimVar.GetSimVarValue('AIRSPEED INDICATED', 'knots'); - const acSpeedAbove80kts = this.speedAbove80KtsMemo.write(ias > 83, ias < 77); - - const v1 = SimVar.GetSimVarValue('L:AIRLINER_V1_SPEED', 'knots'); - let acAboveV1; - if (v1) { - acAboveV1 = this.speedAboveV1Memo.write(ias > v1 + 3, ias < v1 - 3); - } else { - acAboveV1 = false; - } - - // ESLD 1.0.90 - const hAbv1500 = radioHeight.isNoComputedData() || radioHeight.value > 1500; - const hAbv800 = radioHeight.isNoComputedData() || radioHeight.value > 800; - const hAbv400 = radioHeight.isNoComputedData() || radioHeight.value > 400; - - // ESLD 1.0.79 + 1.0.80 - const eng1TLA = SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:1', 'number'); - const eng1TLAFTO = SimVar.GetSimVarValue('L:A32NX_AIRLINER_TO_FLEX_TEMP', 'number') !== 0; // is a flex temp is set? - const eng1MCT = eng1TLA > 33.3 && eng1TLA < 36.7; - const eng1TLAFullPwr = eng1TLA > 43.3; - const eng1MCL = eng1TLA > 22.9; - const eng1SupMCT = !(eng1TLA < 36.7); - - const eng2TLA = SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:2', 'number'); - const eng2TLAFTO = eng1TLAFTO; // until we have proper FADECs - const eng2MCT = eng2TLA > 33.3 && eng2TLA < 36.7; - const eng2TLAFullPwr = eng2TLA > 43.3; - const eng2MCL = eng2TLA > 22.9; - const eng2SupMCT = !(eng2TLA < 36.7); - - const eng3TLA = SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:3', 'number'); - const eng3TLAFTO = eng1TLAFTO; // until we have proper FADECs - const eng3MCT = eng3TLA > 33.3 && eng3TLA < 36.7; - const eng3TLAFullPwr = eng3TLA > 43.3; - const eng3MCL = eng3TLA > 22.9; - const eng3SupMCT = !(eng3TLA < 36.7); - - const eng4TLA = SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:4', 'number'); - const eng4TLAFTO = eng1TLAFTO; // until we have proper FADECs - const eng4MCT = eng3TLA > 33.3 && eng3TLA < 36.7; - const eng4TLAFullPwr = eng3TLA > 43.3; - const eng4MCL = eng3TLA > 22.9; - const eng4SupMCT = !(eng4TLA < 36.7); - - const twoEnginesMcl = [eng1MCL, eng2MCL, eng3MCL, eng4MCL].filter(Boolean).length >= 2; - const eng1TOPowerSignal = (eng1TLAFTO && eng1MCT) || eng1TLAFullPwr || eng1SupMCT; - const eng2TOPowerSignal = (eng2TLAFTO && eng2MCT) || eng2TLAFullPwr || eng2SupMCT; - const eng3TOPowerSignal = (eng3TLAFTO && eng3MCT) || eng3TLAFullPwr || eng3SupMCT; - const eng4TOPowerSignal = (eng4TLAFTO && eng4MCT) || eng4TLAFullPwr || eng4SupMCT; - - const twoEnginesTOPowerSignal = - [eng1TOPowerSignal, eng2TOPowerSignal, eng3TOPowerSignal, eng4TOPowerSignal].filter(Boolean).length >= 2; - - const twoEnginesTOPower = - twoEnginesTOPowerSignal || - (this.mctMemo.write(twoEnginesTOPowerSignal, _deltaTime) && !hAbv1500 && twoEnginesMcl); - - // ESLD 1.0.100 - const eng1FirePbOut = SimVar.GetSimVarValue('L:A32NX_FIRE_BUTTON_ENG1', 'Bool'); - const eng1FirePbMemo = this.firePBOutMemo.write(this.firePBOutConf.write(eng1FirePbOut, _deltaTime), _deltaTime); - const resetFirePbClear12 = eng1FirePbMemo && ground; - - const phase10 = - (this.phase10GroundMemo.write(groundImmediate, _deltaTime) || groundImmediate) && - !twoEnginesTOPower && - acSpeedAbove80kts; - - const phase345Cond = ground && twoEnginesTOPower; - const phase3 = !acSpeedAbove80kts && oneEngRunning && phase345Cond; - const phase4 = acSpeedAbove80kts && phase345Cond && !acAboveV1; - const phase5 = acSpeedAbove80kts && phase345Cond && acAboveV1; - - const setPhase11Nvm = phase3 || phase10; - const resetPhase11Nvm = - (!this.ac80KtsMemo.write(!acSpeedAbove80kts, _deltaTime) && - ((ground && this.prevPhase11InvertMemo.write(this.prevPhase11, _deltaTime)) || - resetFirePbClear12 || - (ground && this.twoEnginesTOPowerInvertMemo.write(twoEnginesTOPower, _deltaTime))) && - !this.prevPhase11) || - adcTestInhib; - const phase11Nvm = this.phase9Nvm.write(setPhase11Nvm, resetPhase11Nvm); // S* / R (NVM) - const phase211Cond = ground && !twoEnginesTOPower && !acSpeedAbove80kts; - const phase11 = oneEngRunning && phase11Nvm && phase211Cond; - const phase2 = phase211Cond && !phase11Nvm && oneEngRunning; - - const phase112MemoA = this.firePBClear12.write(phase11, resetFirePbClear12); // S / R* - const phase112Cond = !phase11 && noEngineRunning && groundImmediate; - const phase112Memo = this.phase112Memo.write(phase112MemoA && phase112Cond, _deltaTime); // MTRIG 03 - const phase1 = phase112Cond && !phase112Memo; - const phase12 = phase112Cond && phase112Memo; - - this.prevPhase11 = phase11; - - // ESLD 1.0.110 - const ground2sMemorized = this.groundImmediateMemo.write(groundImmediate, _deltaTime) || groundImmediate; - - const phase6Cond = !hAbv400 && twoEnginesTOPower && !hFail && !ground2sMemorized; - const phase6 = this.phase6Memo.write(phase6Cond, _deltaTime) && phase6Cond; - - const phase7Cond = !phase6 && !hAbv1500 && twoEnginesTOPower && !hFail && !ground2sMemorized; - const phase7 = this.phase7Memo.write(phase7Cond, _deltaTime) && phase7Cond; - - const phase89Cond = !ground2sMemorized && !hFail && !twoEnginesTOPower && !hAbv1500 && !hAbv800; - const phase89Memo = this.phase89Memo.write(phase89Cond, _deltaTime) && phase89Cond; - - const phase8 = !phase7 && !ground2sMemorized && !phase89Memo; - const phase9 = phase89Memo && !phase10; - - /** * End of ESLD logic ** */ - - // consolidate into single variable (just to be safe) - const phases = [phase1, phase2, phase3, phase4, phase5, phase6, phase7, phase8, phase9, phase10, phase11, phase12]; - - if (this.flightPhase === null && phases.indexOf(true) !== -1) { - // if we aren't initialized, just grab the first one that is valid - this._setFlightPhase(phases.indexOf(true) + 1); - console.log(`FWC flight phase: ${this.flightPhase}`); - return; - } - - const activePhases = phases - .map((x, i) => [x ? 1 : 0, i + 1]) - .filter((y) => y[0] === 1) - .map((z) => z[1]); - - // the usual and easy case: only one flight phase is valid - if (activePhases.length === 1) { - if (activePhases[0] !== this.flightPhase) { - console.log(`FWC flight phase: ${this.flightPhase} => ${activePhases[0]}`); - this._setFlightPhase(activePhases[0]); - } - return; - } - - // the mixed case => warn - if (activePhases.length > 1) { - if (activePhases.indexOf(this.flightPhase) !== -1) { - // if the currently active one is present, keep it - return; - } - // pick the earliest one - this._setFlightPhase(activePhases[0]); - return; - } - - // otherwise, no flight phase is valid => warn - if (this.flightPhase === null) { - this._setFlightPhase(null); - } - } - - _setFlightPhase(flightPhase: FwcFlightPhase) { - if (flightPhase === this.flightPhase) { - return; - } - - // update flight phase - this.flightPhase = flightPhase; - SimVar.SetSimVarValue('L:A32NX_FWC_FLIGHT_PHASE', 'Enum', this.flightPhase || 0); - } - - _updateTakeoffMemo(_deltaTime: number) { - /// FWC ESLD 1.0.180 - const setFlightPhaseMemo = this.flightPhase === FwcFlightPhase.FirstEngineStarted && this.toConfigTest; - const resetFlightPhaseMemo = - this.flightPhase === FwcFlightPhase.EnginesShutdown || - this.flightPhase === FwcFlightPhase.SecondEngineTakeOffPower || - this.flightPhase === FwcFlightPhase.ElecPwr || - this.flightPhase === FwcFlightPhase.AtOrAbove1500FeetTo800Feet; - const flightPhaseMemo = this.memoTo_memo.write(setFlightPhaseMemo, resetFlightPhaseMemo); - - const eng1NotRunning = SimVar.GetSimVarValue('ENG N1 RPM:1', 'Percent') < 15; - const eng2NotRunning = SimVar.GetSimVarValue('ENG N1 RPM:2', 'Percent') < 15; - const eng3NotRunning = SimVar.GetSimVarValue('ENG N1 RPM:3', 'Percent') < 15; - const eng4NotRunning = SimVar.GetSimVarValue('ENG N1 RPM:4', 'Percent') < 15; - const toTimerElapsed = this.memoTo_conf01.write( - !eng1NotRunning && !eng2NotRunning && !eng3NotRunning && !eng4NotRunning, - _deltaTime, - ); - - this.toMemo = flightPhaseMemo || (this.flightPhase === FwcFlightPhase.FirstEngineStarted && toTimerElapsed); - SimVar.SetSimVarValue('L:A32NX_FWC_TOMEMO', 'Bool', this.toMemo); - } - - _updateLandingMemo(_deltaTime: number) { - const radioHeight1 = Arinc429Word.fromSimVarValue('L:A32NX_RA_1_RADIO_ALTITUDE'); - const radioHeight2 = Arinc429Word.fromSimVarValue('L:A32NX_RA_2_RADIO_ALTITUDE'); - const radioHeight3 = Arinc429Word.fromSimVarValue('L:A32NX_RA_3_RADIO_ALTITUDE'); - const radioHeight1Invalid = radioHeight1.isFailureWarning() || radioHeight1.isNoComputedData(); - const radioHeight2Invalid = radioHeight2.isFailureWarning() || radioHeight2.isNoComputedData(); - const radioHeight3Invalid = radioHeight3.isFailureWarning() || radioHeight3.isNoComputedData(); - const gearDownlocked = SimVar.GetSimVarValue('GEAR TOTAL PCT EXTENDED', 'percent') > 0.95; - - // FWC ESLD 1.0.190 - const setBelow2000ft = - (radioHeight1.value < 2000 && !radioHeight1Invalid) || - (radioHeight2.value < 2000 && !radioHeight2Invalid) || - (radioHeight3.value < 2000 && !radioHeight3Invalid); - const resetBelow2000ft = - (radioHeight1.value > 2200 || radioHeight1Invalid) && - (radioHeight2.value > 2200 || radioHeight2Invalid) && - (radioHeight3.value > 2200 || radioHeight3Invalid); - const memo2 = this.memoLdgMemo_below2000ft.write(setBelow2000ft, resetBelow2000ft); - - const setInhibitMemo = this.memoLdgMemo_conf01.write( - resetBelow2000ft && !radioHeight1Invalid && !radioHeight2Invalid && !radioHeight3Invalid, - _deltaTime, - ); - const resetInhibitMemo = !( - this.flightPhase === FwcFlightPhase.AtOrBelow800Feet || - this.flightPhase === FwcFlightPhase.TouchDown || - this.flightPhase === FwcFlightPhase.AtOrAbove1500FeetTo800Feet - ); - const memo1 = this.memoLdgMemo_inhibit.write(setInhibitMemo, resetInhibitMemo); - - const showInApproach = memo1 && memo2 && this.flightPhase === FwcFlightPhase.AtOrAbove1500FeetTo800Feet; - - const invalidRadioMemo = this.memoLdgMemo_conf02.write( - radioHeight1Invalid && - radioHeight2Invalid && - radioHeight3Invalid && - gearDownlocked && - this.flightPhase === FwcFlightPhase.AtOrAbove1500FeetTo800Feet, - _deltaTime, - ); - - this.ldgMemo = - showInApproach || - invalidRadioMemo || - this.flightPhase === FwcFlightPhase.TouchDown || - this.flightPhase === FwcFlightPhase.AtOrBelow800Feet; - SimVar.SetSimVarValue('L:A32NX_FWC_LDGMEMO', 'Bool', this.ldgMemo); - } - - _updateAltitudeWarning() { - const indicatedAltitude = Simplane.getAltitude(); - const shortAlert = SimVar.GetSimVarValue('L:A32NX_ALT_DEVIATION_SHORT', 'Bool'); - if (shortAlert === 1) { - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION_SHORT', 'Bool', false); - } - - const warningPressed = - !!SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERAWARN_L', 'Bool') || - !!SimVar.GetSimVarValue('L:PUSH_AUTOPILOT_MASTERAWARN_R', 'Bool'); - if (warningPressed === true) { - this._wasBellowThreshold = false; - this._wasAboveThreshold = false; - this._wasInRange = false; - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION', 'Bool', false); - return; - } - - if (Simplane.getIsGrounded()) { - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION', 'Bool', false); - } - - // Use FCU displayed value - const currentAltitudeConstraint = SimVar.GetSimVarValue('L:A32NX_FG_ALTITUDE_CONSTRAINT', 'feet'); - const currentFCUAltitude = SimVar.GetSimVarValue('AUTOPILOT ALTITUDE LOCK VAR:3', 'feet'); - const targetAltitude = - currentAltitudeConstraint && !this.hasAltitudeConstraint() ? currentAltitudeConstraint : currentFCUAltitude; - - // Exit when selected altitude is being changed - if (this.previousTargetAltitude !== targetAltitude) { - this.previousTargetAltitude = targetAltitude; - this._wasBellowThreshold = false; - this._wasAboveThreshold = false; - this._wasInRange = false; - this._wasReach200ft = false; - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION_SHORT', 'Bool', false); - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION', 'Bool', false); - return; - } - - // Exit when: - // - Landing gear down & slats extended - // - Glide slope captured - // - Landing locked down - - const landingGearIsDown = - SimVar.GetSimVarValue('L:A32NX_FLAPS_HANDLE_INDEX', 'Enum') >= 1 && - SimVar.GetSimVarValue('L:A32NX_GEAR_HANDLE_POSITION', 'Percent over 100') > 0.5; - const verticalMode = SimVar.GetSimVarValue('L:A32NX_FMA_VERTICAL_MODE', 'Number'); - const glideSlopeCaptured = verticalMode >= 30 && verticalMode <= 34; - const landingGearIsLockedDown = SimVar.GetSimVarValue('GEAR POSITION:0', 'Enum') > 0.9; - const isTcasResolutionAdvisoryActive = SimVar.GetSimVarValue('L:A32NX_TCAS_STATE', 'Enum') > 1; - if (landingGearIsDown || glideSlopeCaptured || landingGearIsLockedDown || isTcasResolutionAdvisoryActive) { - this._wasBellowThreshold = false; - this._wasAboveThreshold = false; - this._wasInRange = false; - this._wasReach200ft = false; - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION_SHORT', 'Bool', false); - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION', 'Bool', false); - return; - } - - const delta = Math.abs(indicatedAltitude - targetAltitude); - - if (delta < 200) { - this._wasBellowThreshold = true; - this._wasAboveThreshold = false; - this._wasReach200ft = true; - } - if (delta > 750) { - this._wasAboveThreshold = true; - this._wasBellowThreshold = false; - } - if (delta >= 200 && delta <= 750) { - this._wasInRange = true; - } - - if (this._wasBellowThreshold && this._wasReach200ft) { - if (delta >= 200) { - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION', 'Bool', true); - } else if (delta < 200) { - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION', 'Bool', false); - } - } else if (this._wasAboveThreshold && delta <= 750 && !this._wasReach200ft) { - if ( - !SimVar.GetSimVarValue('L:A32NX_AUTOPILOT_1_ACTIVE', 'Bool') && - !SimVar.GetSimVarValue('L:A32NX_AUTOPILOT_2_ACTIVE', 'Bool') - ) { - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION', 'Bool', false); - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION_SHORT', 'Bool', true); - } - } else if (delta > 750 && this._wasInRange && !this._wasReach200ft) { - if (delta > 750) { - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION', 'Bool', true); - } else if (delta >= 750) { - SimVar.SetSimVarValue('L:A32NX_ALT_DEVIATION', 'Bool', false); - } - } - } - - hasAltitudeConstraint() { - if ( - Simplane.getAutoPilotAltitudeManaged() && - SimVar.GetSimVarValue('L:AP_CURRENT_TARGET_ALTITUDE_IS_CONSTRAINT', 'number') !== 0 - ) { - return false; - } - return true; - } -} - -/* - * This file contains various nodes that can be used for logical processing. Systems like the FWC may use them to - * accurately implement their functionality. - */ - -/** - * The following class represents a monostable circuit. It is inspired by the MTRIG nodes as described in the ESLD and - * used by the FWC. - * When it detects either a rising or a falling edge (depending on it's type) it will emit a signal for a certain time t - * after the detection. It is not retriggerable, so a rising/falling edge within t will not reset the timer. - */ -class NXLogic_TriggeredMonostableNode { - t: number; - - risingEdge: boolean; - - _timer: number; - - _previousValue: boolean; - - constructor(t: number, risingEdge = true) { - this.t = t; - this.risingEdge = risingEdge; - this._timer = 0; - this._previousValue = null; - } - - write(value: boolean, _deltaTime: number) { - if (this._previousValue === null && SimVar.GetSimVarValue('L:A32NX_FWC_SKIP_STARTUP', 'Bool')) { - this._previousValue = value; - } - if (this.risingEdge) { - if (this._timer > 0) { - this._timer = Math.max(this._timer - _deltaTime / 1000, 0); - this._previousValue = value; - return true; - } - if (!this._previousValue && value) { - this._timer = this.t; - this._previousValue = value; - return true; - } - } else { - if (this._timer > 0) { - this._timer = Math.max(this._timer - _deltaTime / 1000, 0); - this._previousValue = value; - return true; - } - if (this._previousValue && !value) { - this._timer = this.t; - this._previousValue = value; - return true; - } - } - this._previousValue = value; - return false; - } -} - -/** - * The following class represents a "confirmation" circuit, which only passes a signal once it has been stable for a - * certain amount of time. It is inspired by the CONF nodes as described in the ESLD and used by the FWC. - * When it detects either a rising or falling edge (depending on it's type) it will wait for up to time t and emit the - * incoming signal if it was stable throughout t. If at any point the signal reverts during t the state is fully reset, - * and the original signal will be emitted again. - */ -class NXLogic_ConfirmNode { - t: number; - - risingEdge: boolean; - - _timer: number; - - _previousInput: boolean; - - _previousOutput: boolean; - - constructor(t: number, risingEdge = true) { - this.t = t; - this.risingEdge = risingEdge; - this._timer = 0; - this._previousInput = null; - this._previousOutput = null; - } - - write(value: boolean, _deltaTime: number) { - if (this._previousInput === null && SimVar.GetSimVarValue('L:A32NX_FWC_SKIP_STARTUP', 'Bool')) { - this._previousInput = value; - this._previousOutput = value; - } - if (this.risingEdge) { - if (!value) { - this._timer = 0; - } else if (this._timer > 0) { - this._timer = Math.max(this._timer - _deltaTime / 1000, 0); - this._previousInput = value; - this._previousOutput = !value; - return !value; - } else if (!this._previousInput && value) { - this._timer = this.t; - this._previousInput = value; - this._previousOutput = !value; - return !value; - } - } else if (value) { - this._timer = 0; - } else if (this._timer > 0) { - this._timer = Math.max(this._timer - _deltaTime / 1000, 0); - this._previousInput = value; - this._previousOutput = !value; - return !value; - } else if (this._previousInput && !value) { - this._timer = this.t; - this._previousInput = value; - this._previousOutput = !value; - return !value; - } - this._previousInput = value; - this._previousOutput = value; - return value; - } - - read() { - return this._previousOutput; - } -} - -/** - * The following class represents a flip-flop or memory circuit that can be used to store a single bit. It is inspired - * by the S+R nodes as described in the ESLD. - * It has two inputs: Set and Reset. At first it will always emit a falsy value, until it receives a signal on the set - * input, at which point it will start emitting a truthy value. This will continue until a signal is received on the - * reset input, at which point it reverts to the original falsy output. It a signal is sent on both set and reset at the - * same time, the input with a star will have precedence. - * The NVM flag is not implemented right now but can be used to indicate non-volatile memory storage, which means the - * value will persist even when power is lost and subsequently restored. - */ -class NXLogic_MemoryNode { - setStar: boolean; - - nvm: boolean; - - _value: boolean; - - /** - * @param setStar Whether set has precedence over reset if both are applied simultaneously. - * @param nvm Whether the is non-volatile and will be kept even when power is lost. - */ - constructor(setStar = true, nvm = false) { - this.setStar = setStar; - this.nvm = nvm; // TODO in future, reset non-nvm on power cycle - this._value = false; - } - - write(set, reset) { - if (set && reset) { - this._value = this.setStar; - } else if (set && !this._value) { - this._value = true; - } else if (reset && this._value) { - this._value = false; - } - return this._value; - } - - read() { - return this._value; - } -} diff --git a/fbw-a380x/src/systems/systems-host/systems/LegacyGpws.ts b/fbw-a380x/src/systems/systems-host/systems/LegacyGpws.ts index 88b61713dbc..becf5e19fc1 100644 --- a/fbw-a380x/src/systems/systems-host/systems/LegacyGpws.ts +++ b/fbw-a380x/src/systems/systems-host/systems/LegacyGpws.ts @@ -2,6 +2,8 @@ import { Arinc429SignStatusMatrix, Arinc429Word, NXDataStore, UpdateThrottler } import { FmgcFlightPhase } from '@shared/flightphase'; import { LegacySoundManager, soundList } from 'systems-host/systems/LegacySoundManager'; import { A380X_DEFAULT_RADIO_AUTO_CALL_OUTS, A380XRadioAutoCallOutFlags } from '../../shared/src/AutoCallOuts'; +import { EventBus } from '@microsoft/msfs-sdk'; +import { FwsSoundManagerControlEvents } from 'systems-host/systems/FlightWarningSystem/FwsSoundManager'; type ModesType = { current: number; @@ -12,12 +14,12 @@ type ModesType = { /** * This 1:1 port from the A32NX's GPWS+FWS serves as temporary replacement, until a more sophisticated system simulation is in place. - * After merge of PR #4872 (https://github.com/flybywiresim/aircraft/pull/4872) (intended for A32NX), the FWS architecture has to - * be ported to the A380X, then the FWS callout parts of this class can be removed. */ export class LegacyGpws { private updateThrottler = new UpdateThrottler(125); // has to be > 100 due to pulse nodes + private pub = this.bus.getPublisher(); + autoCallOutPins: number; minimumsState = 0; @@ -51,7 +53,10 @@ export class LegacyGpws { egpwsAlertDiscreteWord2 = Arinc429Word.empty(); // eslint-disable-next-line camelcase - constructor(private soundManager: LegacySoundManager) { + constructor( + private bus: EventBus, + private soundManager: LegacySoundManager, + ) { this.autoCallOutPins = A380X_DEFAULT_RADIO_AUTO_CALL_OUTS; this.minimumsState = 0; @@ -331,10 +336,10 @@ export class LegacyGpws { } else if (this.minimumsState === 1 && over100Above) { this.minimumsState = 2; } else if (this.minimumsState === 2 && !over100Above) { - this.soundManager.tryPlaySound(soundList.hundred_above); + this.pub.pub('enqueueSound', 'hundred_above'); this.minimumsState = 1; } else if (this.minimumsState === 1 && !overMinimums) { - this.soundManager.tryPlaySound(soundList.minimums); + this.pub.pub('enqueueSound', 'minimums'); this.minimumsState = 0; } } @@ -578,7 +583,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 6) { if (this.RetardState.value !== 'retardPlaying' && this.autoCallOutPins & A380XRadioAutoCallOutFlags.Five) { - this.soundManager.tryPlaySound(soundList.alt_5); + this.pub.pub('enqueueSound', 'alt_5'); } this.AltCallState.action('down'); } @@ -588,7 +593,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 12) { if (this.RetardState.value !== 'retardPlaying' && this.autoCallOutPins & A380XRadioAutoCallOutFlags.Ten) { - this.soundManager.tryPlaySound(soundList.alt_10); + this.pub.pub('enqueueSound', 'alt_10'); } this.AltCallState.action('down'); } @@ -598,7 +603,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 22) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.Twenty) { - this.soundManager.tryPlaySound(soundList.alt_20); + this.pub.pub('enqueueSound', 'alt_20'); } this.AltCallState.action('down'); } @@ -608,7 +613,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 32) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.Thirty) { - this.soundManager.tryPlaySound(soundList.alt_30); + this.pub.pub('enqueueSound', 'alt_30'); } this.AltCallState.action('down'); } @@ -618,7 +623,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 42) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.Forty) { - this.soundManager.tryPlaySound(soundList.alt_40); + this.pub.pub('enqueueSound', 'alt_40'); } this.AltCallState.action('down'); } @@ -628,7 +633,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 53) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.Fifty) { - this.soundManager.tryPlaySound(soundList.alt_50); + this.pub.pub('enqueueSound', 'alt_50'); } this.AltCallState.action('down'); } @@ -638,7 +643,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 63) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.Sixty) { - this.soundManager.tryPlaySound(soundList.alt_60); + this.pub.pub('enqueueSound', 'alt_60'); } this.AltCallState.action('down'); } @@ -648,7 +653,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 73) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.Seventy) { - this.soundManager.tryPlaySound(soundList.alt_70); + this.pub.pub('enqueueSound', 'alt_70'); } this.AltCallState.action('down'); } @@ -658,7 +663,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 83) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.Eighty) { - this.soundManager.tryPlaySound(soundList.alt_80); + this.pub.pub('enqueueSound', 'alt_80'); } this.AltCallState.action('down'); } @@ -668,7 +673,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 93) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.Ninety) { - this.soundManager.tryPlaySound(soundList.alt_90); + this.pub.pub('enqueueSound', 'alt_90'); } this.AltCallState.action('down'); } @@ -678,7 +683,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 110) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.OneHundred) { - this.soundManager.tryPlaySound(soundList.alt_100); + this.pub.pub('enqueueSound', 'alt_100'); } this.AltCallState.action('down'); } @@ -688,7 +693,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 210) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.TwoHundred) { - this.soundManager.tryPlaySound(soundList.alt_200); + this.pub.pub('enqueueSound', 'alt_200'); } this.AltCallState.action('down'); } @@ -698,7 +703,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 310) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.ThreeHundred) { - this.soundManager.tryPlaySound(soundList.alt_300); + this.pub.pub('enqueueSound', 'alt_300'); } this.AltCallState.action('down'); } @@ -708,7 +713,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 410) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.FourHundred) { - this.soundManager.tryPlaySound(soundList.alt_400); + this.pub.pub('enqueueSound', 'alt_400'); } this.AltCallState.action('down'); } @@ -718,7 +723,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 513) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.FiveHundred) { - this.soundManager.tryPlaySound(soundList.alt_500); + this.pub.pub('enqueueSound', 'alt_500'); } this.AltCallState.action('down'); } @@ -728,7 +733,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 1020) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.OneThousand) { - this.soundManager.tryPlaySound(soundList.alt_1000); + this.pub.pub('enqueueSound', 'alt_1000'); } this.AltCallState.action('down'); } @@ -738,7 +743,7 @@ export class LegacyGpws { this.AltCallState.action('up'); } else if (radioAlt <= 2020) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.TwoThousand) { - this.soundManager.tryPlaySound(soundList.alt_2000); + this.pub.pub('enqueueSound', 'alt_2000'); } this.AltCallState.action('down'); } @@ -746,9 +751,9 @@ export class LegacyGpws { case 'over2500': if (radioAlt <= 2530) { if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.TwoThousandFiveHundred) { - this.soundManager.tryPlaySound(soundList.alt_2500); + this.pub.pub('enqueueSound', 'alt_2500'); } else if (this.autoCallOutPins & A380XRadioAutoCallOutFlags.TwentyFiveHundred) { - this.soundManager.tryPlaySound(soundList.alt_2500b); + this.pub.pub('enqueueSound', 'alt_2500b'); } this.AltCallState.action('down'); } @@ -762,26 +767,28 @@ export class LegacyGpws { if (radioAlt < 20) { if (!SimVar.GetSimVarValue('L:A32NX_AUTOPILOT_ACTIVE', 'Bool')) { this.RetardState.action('play'); - this.soundManager.addPeriodicSound(soundList.retard, 1.1); + this.pub.pub('enqueueSound', 'retard'); } else if (radioAlt < 10) { this.RetardState.action('play'); - this.soundManager.addPeriodicSound(soundList.retard, 1.1); + this.pub.pub('enqueueSound', 'retard'); } } break; case 'retardPlaying': if ( SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:1', 'number') < 2.6 || - SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:2', 'number') < 2.6 + SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:2', 'number') < 2.6 || + SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:3', 'number') < 2.6 || + SimVar.GetSimVarValue('L:A32NX_AUTOTHRUST_TLA:4', 'number') < 2.6 ) { this.RetardState.action('land'); - this.soundManager.removePeriodicSound(soundList.retard); + this.pub.pub('dequeueSound', 'retard'); } else if ( SimVar.GetSimVarValue('L:A32NX_FMGC_FLIGHT_PHASE', 'Enum') === FmgcFlightPhase.GoAround || radioAlt > 20 ) { this.RetardState.action('go_around'); - this.soundManager.removePeriodicSound(soundList.retard); + this.pub.pub('dequeueSound', 'retard'); } break; case 'landed': diff --git a/fbw-a380x/src/systems/systems-host/systems/LegacySoundManager.ts b/fbw-a380x/src/systems/systems-host/systems/LegacySoundManager.ts index 8512cb125ad..25516bb3c9a 100644 --- a/fbw-a380x/src/systems/systems-host/systems/LegacySoundManager.ts +++ b/fbw-a380x/src/systems/systems-host/systems/LegacySoundManager.ts @@ -146,92 +146,4 @@ export const soundList: Record = { name: 'aural_too_low_terrain', length: 0.9, }, - minimums: { - name: 'aural_minimumnew', - length: 0.67, - }, - hundred_above: { - name: 'aural_100above', - length: 0.72, - }, - retard: { - name: 'new_retard', - length: 0.9, - }, - alt_2500: { - name: 'new_2500', - length: 1.1, - }, - alt_2500b: { - name: 'new_2_500', - length: 1.047, - }, - alt_2000: { - name: 'new_2000', - length: 0.72, - }, - alt_1000: { - name: 'new_1000', - length: 0.9, - }, - alt_500: { - name: 'new_500', - length: 0.6, - }, - alt_400: { - name: 'new_400', - length: 0.6, - }, - alt_300: { - name: 'new_300', - length: 0.6, - }, - alt_200: { - name: 'new_200', - length: 0.6, - }, - alt_100: { - name: 'new_100', - length: 0.6, - }, - alt_90: { - name: '90_380', - length: 0.4, - }, - alt_80: { - name: '80_380', - length: 0.4, - }, - alt_70: { - name: '70_380', - length: 0.4, - }, - alt_60: { - name: '60_380', - length: 0.4, - }, - alt_50: { - name: '50_380', - length: 0.4, - }, - alt_40: { - name: '40_380', - length: 0.4, - }, - alt_30: { - name: '30_380', - length: 0.4, - }, - alt_20: { - name: '20_380', - length: 0.4, - }, - alt_10: { - name: '10_380', - length: 0.3, - }, - alt_5: { - name: '5_380', - length: 0.3, - }, }; diff --git a/fbw-a380x/src/wasm/fbw_a380/src/FlyByWireInterface.cpp b/fbw-a380x/src/wasm/fbw_a380/src/FlyByWireInterface.cpp index 10c137cb3ce..5850fa32186 100644 --- a/fbw-a380x/src/wasm/fbw_a380/src/FlyByWireInterface.cpp +++ b/fbw-a380x/src/wasm/fbw_a380/src/FlyByWireInterface.cpp @@ -332,7 +332,7 @@ void FlyByWireInterface::setupLocalVariables() { idFmaSpeedProtectionActive = std::make_unique("A32NX_FMA_SPEED_PROTECTION_MODE"); idFmaSoftAltModeActive = std::make_unique("A32NX_FMA_SOFT_ALT_MODE"); idFmaCruiseAltModeActive = std::make_unique("A32NX_FMA_CRUISE_ALT_MODE"); - idFmaApproachCapability = std::make_unique("A32NX_ApproachCapability"); + idFmaApproachCapability = std::make_unique("A32NX_APPROACH_CAPABILITY"); idFmaTripleClick = std::make_unique("A32NX_FMA_TRIPLE_CLICK"); idFmaModeReversion = std::make_unique("A32NX_FMA_MODE_REVERSION"); diff --git a/fbw-a380x/src/wasm/fbw_a380/src/interface/SimConnectInterface.cpp b/fbw-a380x/src/wasm/fbw_a380/src/interface/SimConnectInterface.cpp index 0ea0c773bcd..18dd71601b0 100644 --- a/fbw-a380x/src/wasm/fbw_a380/src/interface/SimConnectInterface.cpp +++ b/fbw-a380x/src/wasm/fbw_a380/src/interface/SimConnectInterface.cpp @@ -622,6 +622,7 @@ bool SimConnectInterface::prepareSimInputSimConnectDataDefinitions() { result &= addInputDataDefinition(hSimConnect, 0, Events::AUTOPILOT_DISENGAGE_SET, "AUTOPILOT_DISENGAGE_SET", true); result &= addInputDataDefinition(hSimConnect, 0, Events::AUTOPILOT_DISENGAGE_TOGGLE, "AUTOPILOT_DISENGAGE_TOGGLE", true); result &= addInputDataDefinition(hSimConnect, 0, Events::TOGGLE_FLIGHT_DIRECTOR, "TOGGLE_FLIGHT_DIRECTOR", false); + result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_AUTOPILOT_DISENGAGE, "A32NX.AUTOPILOT_DISENGAGE", false); result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_FCU_AP_1_PUSH, "A32NX.FCU_AP_1_PUSH", false); result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_FCU_AP_2_PUSH, "A32NX.FCU_AP_2_PUSH", false); result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_FCU_AP_DISCONNECT_PUSH, "A32NX.FCU_AP_DISCONNECT_PUSH", false); @@ -693,6 +694,7 @@ bool SimConnectInterface::prepareSimInputSimConnectDataDefinitions() { result &= addInputDataDefinition(hSimConnect, 0, Events::AUTO_THROTTLE_ARM, "AUTO_THROTTLE_ARM", true); result &= addInputDataDefinition(hSimConnect, 0, Events::AUTO_THROTTLE_DISCONNECT, "AUTO_THROTTLE_DISCONNECT", true); + result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_AUTO_THROTTLE_DISCONNECT, "A32NX.AUTO_THROTTLE_DISCONNECT", false); result &= addInputDataDefinition(hSimConnect, 0, Events::AUTO_THROTTLE_TO_GA, "AUTO_THROTTLE_TO_GA", true); result &= addInputDataDefinition(hSimConnect, 0, Events::A32NX_ATHR_RESET_DISABLE, "A32NX.ATHR_RESET_DISABLE", false); @@ -2216,7 +2218,7 @@ void SimConnectInterface::processEventWithOneParam(const DWORD eventId, const DW std::cout << "WASM: event triggered: AUTOPILOT_DISENGAGE_SET" << std::endl; // Re emitting masked event for autopilot disconnection - execute_calculator_code("(>K:A32NX.AUTOPILOT_DISENGAGE)", nullptr, nullptr, nullptr); + sendEvent(SimConnectInterface::Events::A32NX_AUTOPILOT_DISENGAGE, 0, SIMCONNECT_GROUP_PRIORITY_STANDARD); } break; } @@ -2678,7 +2680,7 @@ void SimConnectInterface::processEventWithOneParam(const DWORD eventId, const DW std::cout << "WASM: event triggered: AUTO_THROTTLE_DISCONNECT" << std::endl; // Re emitting masked event for autobrake disconnection - execute_calculator_code("(>K:A32NX.AUTO_THROTTLE_DISCONNECT)", nullptr, nullptr, nullptr); + sendEvent(Events::A32NX_AUTO_THROTTLE_DISCONNECT, 0, SIMCONNECT_GROUP_PRIORITY_STANDARD); break; } diff --git a/fbw-a380x/src/wasm/fbw_a380/src/interface/SimConnectInterface.h b/fbw-a380x/src/wasm/fbw_a380/src/interface/SimConnectInterface.h index a97dd8195f0..b5c6093f39f 100644 --- a/fbw-a380x/src/wasm/fbw_a380/src/interface/SimConnectInterface.h +++ b/fbw-a380x/src/wasm/fbw_a380/src/interface/SimConnectInterface.h @@ -48,6 +48,7 @@ class SimConnectInterface { AUTOPILOT_DISENGAGE_SET, AUTOPILOT_DISENGAGE_TOGGLE, TOGGLE_FLIGHT_DIRECTOR, + A32NX_AUTOPILOT_DISENGAGE, A32NX_FCU_AP_1_PUSH, A32NX_FCU_AP_2_PUSH, A32NX_FCU_AP_DISCONNECT_PUSH, @@ -116,6 +117,7 @@ class SimConnectInterface { AP_MACH_HOLD, AUTO_THROTTLE_ARM, AUTO_THROTTLE_DISCONNECT, + A32NX_AUTO_THROTTLE_DISCONNECT, AUTO_THROTTLE_TO_GA, A32NX_ATHR_RESET_DISABLE, A32NX_THROTTLE_MAPPING_SET_DEFAULTS,