From 7e96608fbed4c380ce843a89588da216223c92fb Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 12:24:51 +0100 Subject: [PATCH 01/12] fix spectrum auto adjust freq change step when entered spectrum for first time --- app/spectrum.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/spectrum.c b/app/spectrum.c index 7ca5123b7..3de7017e6 100644 --- a/app/spectrum.c +++ b/app/spectrum.c @@ -1481,8 +1481,6 @@ void APP_RunSpectrum() { BackupRegisters(); - AutoAdjustFreqChangeStep(); - ResetInterrupts(); // turn of GREEN LED if spectrum was started during active RX @@ -1504,6 +1502,8 @@ void APP_RunSpectrum() { BK4819_SetFilterBandwidth(settings.listenBw = BK4819_FILTER_BW_WIDE, false); #endif + AutoAdjustFreqChangeStep(); + RelaunchScan(); for (int i = 0; i < 128; ++i) { From 7dbd1d88ce18337bfeb2b40e39e8d839273fc73d Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 12:29:39 +0100 Subject: [PATCH 02/12] cleanup messenger deviation --- app/messenger.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/messenger.c b/app/messenger.c index 733d98b2e..d6961dcdb 100644 --- a/app/messenger.c +++ b/app/messenger.c @@ -81,14 +81,15 @@ void MSG_FSKSendData() { //UART_printf("\n BANDWIDTH : 0x%.4X", dev_val); { - uint16_t deviation = 850; + uint16_t deviation; switch (gEeprom.VfoInfo[gEeprom.TX_VFO].CHANNEL_BANDWIDTH) { case BK4819_FILTER_BW_WIDE: deviation = 1350; break; // 20k // measurements by kamilsss655 case BK4819_FILTER_BW_NARROW: deviation = 1200; break; // 10k - case BK4819_FILTER_BW_NARROWAVIATION: deviation = 850; break; // 5k - case BK4819_FILTER_BW_NARROWER: deviation = 850; break; // 5k - case BK4819_FILTER_BW_NARROWEST: deviation = 850; break; // 5k + // case BK4819_FILTER_BW_NARROWAVIATION: deviation = 850; break; // 5k + // case BK4819_FILTER_BW_NARROWER: deviation = 850; break; // 5k + // case BK4819_FILTER_BW_NARROWEST: deviation = 850; break; // 5k + default: deviation = 850; break; // 5k } //BK4819_WriteRegister(0x40, (3u << 12) | (deviation & 0xfff)); BK4819_WriteRegister(BK4819_REG_40, (dev_val & 0xf000) | (deviation & 0xfff)); From 955b2d5f2317be064a2e295870600c3e2300ef3b Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 13:41:03 +0100 Subject: [PATCH 03/12] fix #68 mic on during fsk tx --- app/messenger.c | 22 ++++++++-------------- driver/bk4819.c | 13 ++++++++++++- driver/bk4819.h | 3 ++- radio.c | 3 ++- radio.h | 3 +++ 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/app/messenger.c b/app/messenger.c index d6961dcdb..31761e823 100644 --- a/app/messenger.c +++ b/app/messenger.c @@ -75,10 +75,6 @@ void MSG_FSKSendData() { // set the FM deviation level const uint16_t dev_val = BK4819_ReadRegister(BK4819_REG_40); - // mute the mic - const uint16_t reg30 = BK4819_ReadRegister(BK4819_REG_30); - BK4819_WriteRegister(BK4819_REG_30, reg30 & ~(1u << 2)); - //UART_printf("\n BANDWIDTH : 0x%.4X", dev_val); { uint16_t deviation; @@ -309,9 +305,6 @@ void MSG_FSKSendData() { // restore FM deviation level BK4819_WriteRegister(BK4819_REG_40, dev_val); - //restore mic mute - BK4819_WriteRegister(BK4819_REG_30, reg30); - // restore TX/RX filtering BK4819_WriteRegister(BK4819_REG_2B, filt_val); @@ -588,18 +581,16 @@ void MSG_SendPacket(union DataPacket packet) { BK4819_DisableDTMF(); - RADIO_SetTxParameters(); + // mute the mic during TX + gMuteMic = true; + FUNCTION_Select(FUNCTION_TRANSMIT); - SYSTEM_DelayMs(500); - // BK4819_PlayRogerNormal(98); - // BK4819_PlayRogerMDC(); - SYSTEM_DelayMs(100); - BK4819_ExitTxMute(); + SYSTEM_DelayMs(50); MSG_FSKSendData(); - SYSTEM_DelayMs(100); + SYSTEM_DelayMs(50); APP_EndTransmission(false); // this must be run after end of TX, otherwise radio will still TX transmit without even RED LED on @@ -607,6 +598,9 @@ void MSG_SendPacket(union DataPacket packet) { RADIO_SetVfoState(VFO_STATE_NORMAL); + // disable mic mute after TX + gMuteMic = false; + BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false); MSG_EnableRX(true); diff --git a/driver/bk4819.c b/driver/bk4819.c index dc11f7045..d6b3708c1 100644 --- a/driver/bk4819.c +++ b/driver/bk4819.c @@ -1058,11 +1058,22 @@ void BK4819_ExitBypass(void) ); } -void BK4819_PrepareTransmit(void) +void BK4819_PrepareTransmit(bool muteMic) { BK4819_ExitBypass(); BK4819_ExitTxMute(); BK4819_TxOn_Beep(); + + if(muteMic) + { + BK4819_MuteMic(); + } +} + +void BK4819_MuteMic(void) +{ + const uint16_t reg30 = BK4819_ReadRegister(BK4819_REG_30); + BK4819_WriteRegister(BK4819_REG_30, reg30 & ~(1u << 2)); } void BK4819_TxOn_Beep(void) diff --git a/driver/bk4819.h b/driver/bk4819.h index a596ee2a0..ebb888556 100644 --- a/driver/bk4819.h +++ b/driver/bk4819.h @@ -120,7 +120,8 @@ void BK4819_TurnsOffTones_TurnsOnRX(void); void BK4819_ResetFSK(void); void BK4819_Idle(void); void BK4819_ExitBypass(void); -void BK4819_PrepareTransmit(void); +void BK4819_PrepareTransmit(bool muteMic); +void BK4819_MuteMic(void); void BK4819_TxOn_Beep(void); void BK4819_ExitSubAu(void); diff --git a/radio.c b/radio.c index 955383b0f..f1119e2e6 100644 --- a/radio.c +++ b/radio.c @@ -44,6 +44,7 @@ VFO_Info_t *gRxVfo; VFO_Info_t *gCurrentVfo; DCS_CodeType_t gCurrentCodeType; VfoState_t VfoState[2]; +bool gMuteMic; const char gModulationStr[][4] = { @@ -820,7 +821,7 @@ void RADIO_SetTxParameters(void) // TX compressor BK4819_SetCompander((gRxVfo->Modulation == MODULATION_FM && (gRxVfo->Compander == 1 || gRxVfo->Compander >= 3)) ? gRxVfo->Compander : 0); - BK4819_PrepareTransmit(); + BK4819_PrepareTransmit(gMuteMic); SYSTEM_DelayMs(10); diff --git a/radio.h b/radio.h index 27663351f..4bf096099 100644 --- a/radio.h +++ b/radio.h @@ -152,6 +152,9 @@ extern DCS_CodeType_t gCurrentCodeType; extern VfoState_t VfoState[2]; +// determines whether mic should be muted during TX (i.e during FSK modem TX) +extern bool gMuteMic; + bool RADIO_CheckValidChannel(uint16_t ChNum, bool bCheckScanList, uint8_t RadioNum); uint8_t RADIO_FindNextChannel(uint8_t ChNum, int8_t Direction, bool bCheckScanList, uint8_t RadioNum); void RADIO_InitInfo(VFO_Info_t *pInfo, const uint8_t ChannelSave, const uint32_t Frequency); From 0631933ceb0c0448081c864cb979eabc6c7967c1 Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 13:54:41 +0100 Subject: [PATCH 04/12] RP STE menu item removed --- app/app.c | 27 ++------------------------- app/generic.c | 8 ++------ app/menu.c | 13 ------------- board.c | 2 +- docs/UV K5 EEPROM.xlsx | Bin 68514 -> 68493 bytes misc.c | 1 - misc.h | 1 - radio.c | 1 - settings.c | 2 +- settings.h | 1 - ui/menu.c | 8 -------- ui/menu.h | 1 - 12 files changed, 6 insertions(+), 59 deletions(-) diff --git a/app/app.c b/app/app.c index 70ddb3855..fc154a75e 100644 --- a/app/app.c +++ b/app/app.c @@ -786,14 +786,7 @@ void APP_EndTransmission(bool playRoger) else { APP_EndTransmission(true); - - if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0) - { - //if (gCurrentFunction != FUNCTION_FOREGROUND) - FUNCTION_Select(FUNCTION_FOREGROUND); - } - else - gRTTECountdown = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10; + FUNCTION_Select(FUNCTION_FOREGROUND); } gUpdateStatus = true; @@ -1239,19 +1232,6 @@ void APP_TimeSlice10ms(void) } } #endif - - // repeater tail tone elimination - if (gRTTECountdown > 0) - { - if (--gRTTECountdown == 0) - { - //if (gCurrentFunction != FUNCTION_FOREGROUND) - FUNCTION_Select(FUNCTION_FOREGROUND); - - gUpdateStatus = true; - gUpdateDisplay = true; - } - } } #ifdef ENABLE_FMRADIO @@ -1865,10 +1845,7 @@ static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { ALARM_Off(); - if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0) - FUNCTION_Select(FUNCTION_FOREGROUND); - else - gRTTECountdown = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10; + FUNCTION_Select(FUNCTION_FOREGROUND); if (Key == KEY_PTT) gPttWasPressed = true; diff --git a/app/generic.c b/app/generic.c index c68e369ad..d32ff7a6c 100644 --- a/app/generic.c +++ b/app/generic.c @@ -108,11 +108,7 @@ void GENERIC_Key_PTT(bool bKeyPressed) else { APP_EndTransmission(true); - - if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0) - FUNCTION_Select(FUNCTION_FOREGROUND); - else - gRTTECountdown = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10; + FUNCTION_Select(FUNCTION_FOREGROUND); } gFlagEndTransmission = false; @@ -165,7 +161,7 @@ void GENERIC_Key_PTT(bool bKeyPressed) goto start_tx; // listening to the FM radio .. start TX'ing #endif - if (gCurrentFunction == FUNCTION_TRANSMIT && gRTTECountdown == 0) + if (gCurrentFunction == FUNCTION_TRANSMIT) { // already transmitting gInputBoxIndex = 0; return; diff --git a/app/menu.c b/app/menu.c index 521f69ca6..7355c51d7 100644 --- a/app/menu.c +++ b/app/menu.c @@ -273,11 +273,6 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) case MENU_VOX: case MENU_VOX_DELAY: #endif - case MENU_RP_STE: - *pMin = 0; - *pMax = 10; - break; - case MENU_MEM_CH: case MENU_1_CALL: case MENU_DEL_CH: @@ -630,10 +625,6 @@ void MENU_AcceptSetting(void) gFlagResetVfos = true; return; - case MENU_RP_STE: - gEeprom.REPEATER_TAIL_TONE_ELIMINATION = gSubMenuSelection; - break; - case MENU_MIC: gEeprom.MIC_SENSITIVITY = gSubMenuSelection; BOARD_EEPROM_LoadCalibration(); @@ -1019,10 +1010,6 @@ void MENU_ShowCurrentSetting(void) gSubMenuSelection = gTxVfo->SCANLIST2_PARTICIPATION; break; - case MENU_RP_STE: - gSubMenuSelection = gEeprom.REPEATER_TAIL_TONE_ELIMINATION; - break; - case MENU_MIC: gSubMenuSelection = gEeprom.MIC_SENSITIVITY; break; diff --git a/board.c b/board.c index 572aa26c2..1037dfa2b 100644 --- a/board.c +++ b/board.c @@ -600,7 +600,7 @@ void BOARD_EEPROM_Init(void) gEeprom.ALARM_MODE = (Data[0] < 2) ? Data[0] : true; #endif gEeprom.ROGER = (Data[1] < 3) ? Data[1] : ROGER_MODE_OFF; - gEeprom.REPEATER_TAIL_TONE_ELIMINATION = (Data[2] < 11) ? Data[2] : 0; + // Data[2] empty slot gEeprom.TX_VFO = (Data[3] < 2) ? Data[3] : 0; gEeprom.BATTERY_TYPE = (Data[4] < BATTERY_TYPE_UNKNOWN) ? Data[4] : BATTERY_TYPE_1600_MAH; gEeprom.SQL_TONE = (Data[5] < ARRAY_SIZE(CTCSS_Options)) ? Data[5] : 50; diff --git a/docs/UV K5 EEPROM.xlsx b/docs/UV K5 EEPROM.xlsx index 9e1ecf34e6d00961585d675a1a436bb06998f0fb..6d6b5dac22a2fb9aaf31857c64a951e2919618b7 100644 GIT binary patch literal 68493 zcmdSC2|Uzm`#(+!iD3@p)N|sTnZD-yp5Oob`aiF8#<)J8>%NxzeP7pgU-#`iXVfS*?HSe@c;+IbFLy-v%3R+7srBk-mo~I z{0+Xj)KA0a`Y~G-j(r~TqP=Yja7s66ISa6 zcAZh9qQ3K3?C}I}LgOYfvNJ^8L=WC@vleu_*-k!=-q5~IyJnPmza<^^E(UOa01_^mmX8Ihm9y!+aeDBPA(Be5y z23(%*J+qtlO{P?Y)k3)q?NsG?vI}Z3n%kMij!72+UJBuSlj^j8ylh^6MR|wqF8PP> zZyl;)kFp-6g-v}s_G3DIx&C@`ynT!)d|nm(d|D)d@n>6t~Ig3P4mL?7P8s;JKFZd*pcA2qj5_03JIMBzJYDr zPb|`e7!7v>RAxq6Jn_g(ki-D9CbzQVPnZ{KAHIacM|UGiQ%p>=RACQ zBCwWoLFlus<}4Gn|I99L-BX;_QY?pI!?*W;^>Yb92n=4cJAQyCqG~^NB_mVgQggCQ zj&{W33HS$u!Y=h3tdE7KCVx1-mf2!a)Q~G$Co~3+APc#`QT8Lb%gs$ zq*MPHra3ifEF+ya_u`oefxHgKj91Qua)bL@@5g9;=tOW0Eq=U!*#tr7!tUueSaLEl z7m7bYhwdkI9G%>)uR21&8P`7>8Y{`*gD}43hB$fhk^e50FWUW1g6Et&Re9nkD##UH zuC%;x%~*ySbWy<9v#Z;oWnvIIT0&$s6h^lGg*+Rt*O zx)S47vf?};{pQqBg$JUg_KSrs#{BSm*NZZiswho|pHjatD%{Ka93`8hDN%T8ew)#i zbXh5;gApUzyNwLD2ES%KesDg$oWtYbfqKIlYlCdni!!_@kxWacLrNUj+6TgMMfbNy zO{t$<#&&8;xzknnTyBM6wami961n@Ul#B_;`maaK6$oYt@`WRN>&) z2BU4s6oXH>opM50i%%qvcJQ|n^N7`|H zQug{5yHpmfRqyh^&3lA;6DlD~>aa%ZC9`WwL#~E44kEW{8W}Jb_`mOKW-W;y=EqfT zueqvzL*N|ii9ou22Xk)HMMXr7{J2SeK-$4Ixg{gIg%-HzwtTC z!;Q&o#g~6P$2=K3u4c>nu1e!W9!< zuWZikxIN~gy^7t(wjasg>IDKD<|4kG!ilovz`R={m%C(rcE-tsqWWDk7q`lVqu*$Z zP`z$o=jmAV?A6O^Z*a^sU-l|B&eLUiS?JV|U}P1#(#w7jJzQrkz1Ye5xNEud^cA==x0dxGMjxR-j-jG{78Evt1wkX3=TCuy^=IJtnVr{Wo}ZaI zT;n=EQ)Bj=UaVH3G7Xk23qFy9St74F+xzLAc*NH?I3Iz%1~ga4K1F_Noh?_M9}x=~ zx%*CmmhxHh<~tSDF4SeWFcafFEaw}NySgn8hQ8$3`Mh-3x0_5Vg8I3$k{1O`D#K(9 zQ$MI`X10DP_8mVfSU01Bj3aN@qmyMok!O44Oo?M9?xkrf-FD*?&qSeGx~&Zk?BSx# z+My=hM+8Nv=4_Vx<@#X<*uHUn%<)as7I)qH#n_yE(qo(5){d+*K4Yugvoi%Tidi{b zonH8msx`Ij(E{u~_{VI#`&US{yy9@xOvlN=%GLrOS>xl49Xo0ws!@wNPv$0$)RQq^ zwv}=rUp38CzZa-n=VD`%>2{FYJWE}gyZ;>uyUD0Zjn}|nuvLrqAeG!MmqcV-4d>L% zym2B&M9#P^qRZAt>IP0(E5gOGpv>6L2iO0j(_tl9T4f>N%Ye`P%g#JRoY(b5o*ZM$ z`#KCZ%qhxt0Z^p(m9NguIl&h*F{SM|Q*>IV6Ry8td}4Ow6Q&4_al&0~&7N3HY+smK z?)jWyC5b83x6_O$8SfkT#2-uL8X;@@6)u~f(qp`5`p1_#%*vO#$!!=%+*Rk+ER`}Zs$iuPZ@FwrC*FKn zhi*adao{o68}Y&NS>mw^oI9T91dZEUzcMTN#{Qmhv@|Hb=i33P;%`#-`9+=u8Fqg= zKv(jO{5@k)N43BW>+mVVF`D;`=aPfiq+CzknY`U9Ti96dPt}?!)m!0gd*9tYK5iHL zC5yoaR8hmjv?2nt$Qx{~A}83G9C$=O-#ExrfTSAKp1A5So!xI_{VW?` zXk>A?)iFo(!Dvw{%g6ceqqO}V0uIIWjq|cd@Vjgz%Scgzg@}S&>#Vx@QwcBOsC9%v zkAx4j^Ou@LW0Dd^i?z5>VA0`Y5`v$=g1A@B}312}Jw^=?mU3 zN}!5Kl4_mZFDf?Z!EWY1aH+|+{!`qjI}qV0$K;$xZ_Aue2fY_1qTrZ4n1+9t2@OH) zqv%4Z;neL>_k*H&-5y3CX!#2h^h6Z4We+~A|MX9CRp*(Qq%Ezps^*pz^Os7KA!m*N zzp^{~JIIAfD-JD#ns!f>nJx6bqOiQkDcw2=mdcWXA$Z`KUlj%ah6ChNogf zB@?0$d2a|r*2I&);K|4M_~lQ>Kd1C=?L3`!0_9wC*6NdMr=2eAoT0?NbAZgI^bnBi z&Rzv%M_m>`W`oFvcyb4x?20F|L*#foc@$6f#FIH7a;MV6>db7%FF+gIQ<0$(+v9=I z(8|q#u!R@MTHLP)6g!k^38dWF4K(ctO9o;&w1Mijr=XYP@h|VezkC3C*&P3J2>#{p z`AdvQl zkG@jWfVCH78zd)lj2qmSW6ZSAv%9$Ceez@QYbgJ<<>vCMS!_Y7Kl%EU(2ve}9euXc zTt5HpcvaISZI10SY?GYwzDxUhx80>@Fh1$EWqL=ip{n2$78kMV`vc#axn&+-rE2*u zO6esi<(S94FKeq(P$e>XDtaOBuq;1~7XFt9=mhh2q`K$h;b3#=l$gfj>7FAulRjQN z9dsZ?F}yjs*7B@b-eD2_-7Nfpag2(ZK?gGCnr@&nVj8W|9Ul+JnM+f}Ok`3V^0$!U z54_E&cp@nIiQ?H$$%m&3PU!F6@{=}f{7Iea@$hj`Hp_I11}8Fzqo&7#JaLER+0FX9 zZ!szYo|fdpR%ajN9ah!feJ~BKB5K&%x4*#&{A^Lz+mDoUep{B18_1}r7?hl>c(ytD zspVPSyu*C5+<>(?`R)U3xVdzTy3*reWl=V(bgq57Ztjh-2xnA$m%=44Q(2X=TPsvs zR$g^_^>8&s>Tazt?Pr?=s(q7oYx!%(Iaa-87>o<1^<=+guwZC^iQTKbmMYk+a;c97 ze7C>L6R6zIQgrr4G#-56iH&zKq3ed}j zI=Ss1u01vLe$T4FG4Q*UliTN^sTa*XS5m5wrvu)HY;W4j#x5x>d&9}>$2Xm=->gfz z3uULgT6)OSxORQy(CeOg>#G#N6S_T=oh?C5TGq?SZ3URu+_RigMWGzP6Lvp%KQK?r z9dDkVwCqbKGm~Y=D{c(KQ`{|)DrSk&m=AKhFcqA;FhyH-VJwiln$-s)&dSBAe5%fw zJe1oU<7e0ywR6J3s8t1HE2YJlvZ7u5!v@VCV>5|0*o3NwaR;(ayR*pzT@07Al z9#ZAzIM(247lrp-Ofg=dbX~A{t_~?ATo5q<%T%o>$52t zFL8udO0wLxiTUoJ=Ah9JA)CjKIWC;PeZPrGFL$M{+UrF)<{H|fL~S7IL(~@^+@OoA zprJE{GX}TNQ7%`ztOvLMY&BEpeZlIEGo~lsN3;bC8?Eleta^B%vBheiY;x`~>DAp? zm~Jw1O3cVlS&qGzo{(dVF!C8vZpB2_E{)IhJ$%$wom01*MmfHV+e56YfZnyE$>z1> z*wtkvSI+AsWgTCWOF?uxYXlvq|A-$4?D<#FPg3;No=&Hre(bl-Eg~aZIlyl1i zpD=G)%8L!(lr)Vh%(!5l^q>#yv~&0pHCWKsUp=>Q2^ml@nA7L1;l&yCY15(q26y+(OEe!a;k8l^7&94>eF(qwn% zj$N0J-O#U>?eM4Sn3@q^Y0`)L&FRWgX$dH`a^yT3?9{tA;Tg8iP*z&2Wbz!>_}(+; zQ`N@JK1be2p8lF~?bFHAE_>rGGrFsXipwp{BMo+-;4l4AV?0qu&ibOaEHy328QjD< zz)ZI>ckORr6e@Lo!2gz`dFQuH{smuNZCUcw=gYs@!>?pbUe%|soqxOkA+y<*D1G+W z#`7;_rQ@?MyO#MJjr!2DGn5+Ykj_jJfuXj0a0g!`{35x-7H`-^hVWOIzT^tTIR!wMyM#*t^_+jP@xk>sheR+eJ zB=E9-^Ufb);CG@QeNHuKh0Ae`ZgA>gB+DfItsByP7)~Kgi&EI;n&IHZfVYzI(^v-P z4ACx*O>16;)O!$y^pBD|5nws;Lmq@I<_~p<4w;w9bWGI9&a69 zv;6An&6zeYh0}sND!NToS&DosY9ENWQ29pQyZG^v(1n;M8Aq8*)j#Pn(wZL{;@d_k zu`BQ47T@@-D<5ws86P*jC^WZi=;$_oAM&iL6`us36dYw<*&-ITMFDYh;`QYrrcXwU zw3tmRb*e#=4_}ptftQ7j&|x;|*QbSp*`t42>a*ALBIi@;Lrwjx2GYlk#)$hIGp{!15@s9gM+)C#yc^ zht-&mWkW8(KP<;T6owuSsY5*aNQkEkPnN=yH6e04o{Y__0Yjb05(aOdxemA;7aES zrS6KmA1q6xUQBGC(b4Hte$dU+{6&epIQ(h3RJK*`$DAaWM;tSiOh{$&#{jL#(uU0j8N<2cT^wuPA znm=<^)8pw=Iyv1R?(}=4IusPK^Jg&E@2zNlVdwk0WI6v5+iL54!A{~s5`19F$nb>s z!>*ECtJh1%Fimp^vhTu$7E{3$j+BDTvO;bjy7%}h?df8=dDuvST=F~_^#qHo=~P_B zHcEP0BN4ai?z49mx9rbPO(K&$LbiF4HbK~}v3rXz6{R3csmavSO7tcMgeC2kuveRo z+c$Ny_zuz<3AtUKil{h38Om2GNH#s%cZN)g7%Tl21@hf5$QZthy47?``7+V6Gnbl8 z1y-ccOl~_aJJR`5=PjMgmhVJ=z_#3_T1p~&mlLHxzQ53mhM9(}qF?9j88T{t#7+J{ zrRCj1yU8TC+%=8a$XiwU8+hxf-MCrC%_K60OY&Q2x7_TW;k|sAY;%+r`Clr;ZF*O+ zbcU?AweEj-tAnjIsM=iwY-JnC+~}vJ-cj9k{Xq8}RyD}LVdj;{H|?Sm*(CtG)Y1wo*RnH2@oELh-p8mD!vq!W(z0T;BYjT=dE5$z!`DQj;z9t&oPMa>i=4)T( zp2;u?DRrCeIDaHd(@Z`P#PV_D$*eH#7Oye0954UDB>`Gm}o}4SBlw z+s~BI?PNN8FJGfjx9J9B>PbAWO6v3;z3)Mrz3d3DJcbz8DjZ0}Y;9eA3F~={IOlD# z+OX=Y_9(F!0kh$l_|i19e6C$-WtDF{(%a|Z0yzw!ijGS(PV@fWl+zN2Y08OUL+i}j zPULP8Lt=BEzY|pIJeQdntgXY6mM)^|&N9zY;4wMZw#lJ7Ej>_8V^7pfpr_BnOQ(4S zQ?PyK;gbdBYK-IN2>BO?Z2EXHRzW1+yj_%4+DbuPo<64Is{X6{E-27sQxE|~sce31 z$wcLNqJDlpeQ09GkA`by;ZuDcslMpck@L7r+xf)xKiHf6H5buU&*2nMtMzpB;Vyd6 zFHB}2|HJX#4$x3Evok&8U}x_rXlmzh6*{M}(Kgho+P~X-QBSP2;K3VV|2)HFb1ebk zHpUP;YF9S>!{qt4IHPvkFV$t8vlT_(w^gq`eLO_=^~3q7yWG5i$7jzg8%9~?8oi@G z?2uqp@%X&LJ=c}H+`iyxd`Q#ZxoWr*If_%OyV}@(w z_YJJPE-W85+CeU%-im&iNaIv`k?zsG5ebygU{p^?{?2!Oyk_6K8)Ki0)GJ=uEWO<; zyz6zw;QXd@xlWJX^WGDEeTb#O@o@%+H*)l5Qtln!F@&n(Owygixnge*%}0EghFv9eHjUnM?%f*|tAg8S zSo5sfw_3?KSr+iA8P+}!Jjlz3^C1`OmQ5UM{R%p-qbkqG$mEr;vx>dn^6@Qohg$CS zPZsD$f@c{INXY4ZJ??v-;nQQePxN+dONTkl?p;3VyC7V=hx5ePiP@Vv9jT3%%LarW z`Y4SFDU;`%4`x;8zIyia=5*@x0C`uv{lyG=0ZYb~cGbh>FKt2vrkQO{$W(I)soGjy z=hDmi{Px*_;nqNTnT*tK;fs~xGaXfEcdCosG=lb09m=Abovp7YM&6IvK2d|M-n^U2 zXD*nc>usd%Kra(sz?9Rrx|NBykpj+oP{N>15c1n~+vLqFz$>x9cf`-BcdhlCsk5V# zoekb~jjw1bg?58tErYtPLzgPNB`-))Mt3o+E1%rau2v(++mq||#Qgvcc}=7oM&SiR z+m35Rf=77C`02Lu@Y`Y1BvmRtbYEuod(uyNw8W+L64#cyAIO7_?!PXTvHM!ux5jR| zC@E6`E=4=-gd5so_Zur?#(K#krFFlYZM(B;`GA+y^7P0tjM{cH)Z|i^9jB*FijPGH z6J%G-&bNLwn{ z{o;4-;?z0(*pVVlfworJ8S#hycDC) zvp>-C{&5^Rww-#L*n<+o?$Ah$`l50NSKFjfu`@9NIQ4o7b!9zo!{D z+8-B}%idXIxSD-g*M0wfGj+zMk{y$j#he}C)t`^eGGi}>X&h16lN&9 zm2=f8#b5QodQ;dIvHP%AbJ@v^OSuI--t_XfyeH&2$YBNTg;SyzBs<@^PTbYh*uQC1 z5jW%-cxz?sGXqMR%IBH5fmBX^+YEn$*7VuakBvQ6wnCHCD^oyk27vc@%bzBR8BF1? zOA?NjSFbub3gUkVLo-#{sTR4fHRjL|W|bypLFc6TrQED%HI(&J=(3g^nfz1EA0F>K z#{K-6rw`^PgP}4kH01>ovOJRAt5$h)7sbGIYgH2rYmDn_Lg5Bb2=sIY3^Nr4Ul~Wj zyq3o8%F%U`@TICm>O=?33#$RgVqKd!IB*jj-49^(%~zkTBCYsFtqWC2N=Htw=}0@h)8rr^^T%^`X`Mi zhwEF>vtW!qdSLMTL|o4zY<0QSt^w9xH)$jeZ-n8n@czB%*#a1L5sn_kEe~(Q%_BJ` z5ZGZf46_P@!9x+4LHO!wbu0&b_C3rSH|q*}1Y7MvqUtyh7;MI*Jf__kfw4nj>Re%q zaLno`41xLNb$dPvzSx9YDlvx7!f<^Y*tuc;)&3le1k7jgJ@7jYGiUrLgPtS7hh;@p zbal7{w=~>|!!~H)R;u8q63eUMXlzH~*PJDmJ`UVmK(7{jc_I?K+K0ddcGBaf8|YCy ziCsZjJs!Aib*_nBd3$_Tk#KaY7Rqe8lLL-LN3AY*;8p}t-nh<5ICg@55^jvKgTZmb zir9WQb{T=4!k`duIm*#}1-J!F6T)j-qR~VEhaPTG3pEYqS`bm1f`YF^z*gs@qLv0q zCc$L$cw^@Tumg(-^^8QL9uMre9TvsmvowoX#db`>%5)ODd|h#fmDMdLG5vD<<(Nd+ zYR90&K&vt4s^V%Zcyki*Nziz)N)WD-h}(xKeGkVhM17eZU7YSfd7)Ksm=c6HYVeBwH3^$rFIljzcThKA= zRcwgG+Ip{)sFb7o<8gC!QShaHCM-$|&U*y2(mGXz>YD5=f#W97T8N(6#knr|GH{3) zhUoC3Lii};0BDYbnF@uizPFRdJe2kJD8Y?qB*K?wQT|x$&dKsya14?IJJo57#U6q0 z#c7qNG@%+Z5LJ^1%%~RPhgkz|67F7xLnF6g=j!UP6M9Qa5^mTBeqgq>5^J!KJNhQE z7~~=rZOl`Cqt{AidgR@#OK;CRE14ZqH@Y<6XsM zlWu+tcNhY~{KEXh?t}%L@jK&x=FXXbPkx{LKgC!6Z4ieQ)n|=L86#ux1Yg`fZ`sIa zgWWJCR2(FXnv;feJLgtTI?ipJ^hwl7v`I8c+mp5?(Iv?QWYYBT`^o!p`U(5-`bqiq z16>S(F4ekQUz%PDM_WAaw7Y=L^wrXmqyui-?w9R$zBeCeT3LAE#3alECPm_XSu>U-gvRl;dMgm2;vr^yVbv)%89Ax^IAsPuseHi^5nE8RLva-efp z>twh@suHEysY7O`A1%J7``*JelUN!7-@ZtxW%Lmi5bMj6-OokOebR*cgf_Q=L+WwW z)RWgzPw1z5_O{5+_|Mhe46gO7ubr8DqqeFQVB80vIe?4N@YP#xvSux;4<)SfbL`($ zuES{=;b6H|FUcfxt)7q{XIJ)nr+hnA+5d;~tq00?J}dj?DKDPly!qSLvff$DZqlVJ zZm(GZ%genG-##LIdh7W_0iT%L>thg~IK(GGgfC=0pC;hba(jKI@TJwuv*6>2HW9w6 z^?X)t@}*X8`BsH~vHljZ{%VC*ZrgM65eEpmHQnlXR~S1>*p8SmmWy3=;`RX&bWJje zwAA2-I9-%Ia!MU}lb~B;(#hQwJj{-tHalr<=8n}zPI;|1;Kb>eCa?uoh4yH~A`VSX z1|#oQB3q@s$+2llhs=leZ4>#@2{PE$ZYA>7qc=Gyr;ubm``$KDEZri5?dVq8w5ooS zgJw#H-1s_c0=*q;f(@%cPkK*Vde2T<)`Y6(<2khy_rjP}!ghZM+s7NWGc%0UDvWVB z!HPBPZ@AK^%GIbk_FYW2L+nzOMwO@r#mw;o+^2VPD~fO{(WIW@OFhk+s#t9CnDPhR za5yUVfB%D*Lp-Fix#PJ;ae;Ot{L zCGS_8!LZDHAW`9m?_IB*;h_g+E}oJPuFcr7EO{VN=?BF#>|DNZ zAW`jy?>#S(@X$jm`pEy-51<6>X9xC+(Gi3qME@NhhXJ65r|{ZaKpwXs>hV*^HH#Pu z?Az^FHO1*%#p&=L|1YJ*m46kB`@a%5RheFq-gAfOYFRfq4v;%Rgp%wKD+Lh>EK?An zBm?w1jKc|Kt$0Ff+kNoCEqkPWzLncn2|8#E6H1rs*Y@h0^d2v_zj$K(L2R=p8W&}d zV*BlsLuqU8s@Db|oxHlYu<9>Wf9mb%_69>Z%dHQLf*o(!;Iy|js*qIMPrkh7w(|BY zb;6zQE7S@8-8ZNc0=jQeC*180r%t%nokX1w*!_w+A*j28Iw82bnK~h)yN5dAe)lwW zLTESn)`YOBH`&05R{Q+xV4U)b*FD1&d#T!qm=EZ`LtB|Om#bTceZCD~Y^*2-j0RLI zL>K}6H{%S#Tyuiz)| zOVp*x>yw1jhrrzSHEY(h?exS{SI=u#p&NzXg%@OH?`#Rl+f*D1dsCwn7q=3prnOSqOgxwuAcu;zbkpJW$sq1TGb^Lpjw*88Gg&20;o zFvjjItO=Fwf*rMNUGkS)+NtheDId$D-}lZd$(xA2-s|<{5C|xskBVQY5Pj_0PNij) zz7al9Cpi3MyG0QvC^Jr>Bx!8P5k_eF8Up(7)Lhrv9#GdaUUfCYyW457P80ohxsj=z zFeD)QZ%E9%S?F+uAe2YeIj6`g%e!#jPwzC|fxHt(>%C#` zWCJr>;}>pmrQ`rJElwL(9ho8wqU=2Szk_I@rx@sIIp++l{XBGJoNx&O(f`U^4j6s3 zyUXfPIz_4{)M{icy;Ce zg}QxsbqAGa6Um0t(z2E z0HO&1qD3$(DQT0CnQADakqDskpOL5>=vg@D4Xkw<2K)qTXo&tBL^uE<7y!{E0Fj_K z3Rr8r!cG)K83aHCsY{U#smr7OFVua9S2y@ys4Ie3_v*h;*A%brpgJ&@U^)YlV@)JN z0}!DBh#K?DaN;s785 z<86;E2a^*g4#X1%(Yi^Q03b5jZpUE+l?kyvP$IQkIas<0N4PjymqdS67^P5cA&G&q zZ|~eTA}C^7XK4TR@hT|eL%BX2DF{JV6XB=VO}N-E`y{`<>@KS62#5kOQphj{YHP;( zY|VK~q>}-1`tM5YS1uIHr*Ddr#+aa|>NAmoU|kUE9vH0)3{g36=mo)AThH3FXNmA` z7aH{Ueh*(eF7#9{^u*|77+Z5BNI9<%t5P8U{k7U=p!%kN>i=h~!&N==RfAF7PCb++ z@$KmX-%ohOtay&42JBXO^*}lEfl86Ca+^S>>| z-lgv4qte1W!T&YWhPA4pIx5rEDm6ar0Pmxnybncqqi8Z8@MS(?&3st=P~0l@MVNbE~#9VKr51K}~`xtW`GerQc|n7EUgS%nO9^FWOvh zvd@I@lZsYW>v~W#@z|;$>sk$Fi zFY%>nKTFlWmU@2Ve0yqmpu$Mn3Dz`~$7xp;PO#GFNXsM4qE9y#8fA!E{RkTs)R}Bi z?&MU|K6+4_@2a-I9&O%p+Wg0~k2oK(X;DUV&bRCjY2j{Yd7ZRBB%ok_qH%;+aZuav z2}#^a-RBaq7C+_i-D>w9sKz`{yQ8c6P**MFvudYmteAGNa+#QNikM1np7mknzMd@~ zfTu$yOkDVO-mk$z=04yiVy@Gn_2#Rd`TIXbao4qq4Wv+EpAWOn_+|C-%T z;vrh^U4^w|3~4j$b96eyUI)3;?7gcuOwh+=T3mC7)(ZZ`O6By6^>xrKb|QXq5k9jP z7G6xVdB|#emqh?6u9E1Cm$%#=lE(Vt-?R1tRuwKKA9##M)aerD!x1LD;o7{B4w+%9 znGx4A!}T)_tRlgKr%{wv4-Q#9dPKLyO13=6y?xk3lGY2XzGlNf`jhqzF9uF9jm2|D`}TATTvN@;wCJ6hm6V-~|tUgE!yG zOCGqV3%Dl|(l*?%-tpVrcx&We3Vib~1qzRiem)cuSB1SgV#qpf z@?UZVo`p2}Bd}*rB(oSDXvrW^09vHEvo_(BpQC~byqi=XgU;v5=C(%Enf(}U_ zk{Wjs-q!``TPrYN#zY~P`acWZojUzXX7>LmlTb*&%Uu2?bGJA{P79ID)+|7|HnW9J znrK2Xw*nuq_pL$!8^jI50sEf;1qm>8Vw&_RjdLkxZVWR9nb?WRlvEFuu7X)fDPb;Q z9wL|>Y+5XtDE^impvV_FNO~Z``&AX8Y12}hIR}*tz<-2GhINkZ5K91_Z3Lbj{PHs; zNfD0;T^Tz(BL5btp~ZQ20dnk^Nu!JKrwz|0Bs1gt|0q)&n&p4WoUIfXC`DG6z6|<< zzJz#l4eN&~N}~VzK|)f3cznTZMkA?Qg-J5iML2^Vid~u<-$_bmQXSQC@`XXKf~36d zNrRs?ljBM^h%*yyaP(2D3G&*0M9+c`f4Eaoxs3OqD$K&@$`_! z-Y*cJ}>N?<`UF)o~j}ybaP#t~{t{!bun)p%sV(C}JfEMcF`GfI#PrAgNbDMIf&eET;%g<_4t_ z0?~S@{v=gYqrgq(OpcwyCXHhz*`&l2NNSs5J>Vx1L&acDI;#PANrb}xioj~Tg*P_3 zNgpm;5;3_57XbKy3}a48#^0b+g78}>m60gu z3Bk`60O6rwy-h|?(d(e1Hc~(jr0Tf}1O6|hE$$A0I%jBcUm`IK{ci}Az+2d`Q42vb zTLj4r4NNp;azqWA*p8V@T%nleBU~IWTKRRQ{#B9xERM^O)!za9T#KXkmPD73lFK$K zb^ShofK*SSpeG1Fuu*b#5ncqKZxk4?B?a`5t@vo-N?Kx>0I2K4FK*Y3F7DrE{(mj7 zv=GXpfg$$_))yDP9P)$$54o%QS_@|bQBv$k8ppJ(XLDf9|b3={4_SEU+svg67 zsJq%DU=CVE!r!Z*J~nF_!9K{GK*-y2J5iNy68P6FfgkY zaT=d8a!Z(tnF+UbLF=4}YwgB8z*YD^t#hb0|5U9^tn@5qUf0Ph4O(7}NNt89A=nc5 z3!Em_rD~~O-*AT@L5ppW`(b=q0X-6m`MUj z{kUK9KyU$7I`LK&p%nEWc_2Q44I=5y?>Nxx1mZ1#xujIt2|(V@{m&R_Ekw|70)_c( zLFTOaN5lFq-6_$bQ7rUn3g=tedZ0a##^?53*NjS?&`3;XHwxzj=etnWhSh!PF$;b# z6I{r+y;%M|k){iM4bJB_ISLW&@Wjq|nx<=`Uo#uD-#oqjyD{=oH&pOhf=l4DspBP~ zqn{V(;O3bV8u1sNdFog^8tM9cC#_h*`6?iFLL^s+v`x*~f=||;3zg_$0v^ca>Mo{h z9{p05DXQjdH&UtH8C(1skZg~hGmu@oW3SMbE3fu!x0-f44UPr8t2%KL>UXp*_;mhH z)D1pz z4;VOK50sXE1(a@t>;MMZjeLacfJhS%iRsZuqwdm)Y8Qy%8g5&e%3sZ9%M#th&`EgW zI9$+&aS{^N_%O0F)3H$3HAA3ByEDGnU(MNdgi+v2XQn4aG^zw5_jLItjBCl=fgVX+ zdRC&7VV^mn8DEuFEaSX2YGmT`F^E_I5j(5WR;;DAuMv6p!n5~LeNB)0qNXU{fLR-$ zqqh@WF(=8G3xN;NI$Drz_<4rh;0#T@;e}^iQe=MHX1dN%&v`5M~aaq#WL z=Xl6*V76mua@tQ58_H8h4}wexG`a;Cz3io~YkKAL{08jjU67Y!(nf6dd|G>gn&z=; zv!|)+{Ee+S?LL<>^6i#lAm%HOY8L?nC7|)v%1$RicG=+O^)P9AFZd-_?V;l|SQvX7 zi`>vUO^{3QxNWzB2T(=*j-E{rCX)x!1&{i75P+bCAOO94L~VXd zn{Iebw+dh%>mO%fS6k$#X9LUD>5y3cHI}q9T~53FLPi3#zBVizEbO(y=WP%EZKYvt z(<~;>7q6^7x0sYF0zW!=C(gIW_u8iY^`$Ix>Y2@JSaqjriO%<|Jefa#@zeo_wYKr? zN6$^3UmrgZ2E%P753_sDb>IWY;2IHs$y)y<7C>eI{b!+bW1Xsh2S%rAQ&*M~@E0B! zlCDR_HNZp|FJ=@PSh)t4JaqZT7oYgz(h`35wP)W)w@%WmHGum*;>b{2$?fc(gNwj` zDA&ck!{>;k(;@e$ZNCeK{AL+UhHFtAwg-#zoYCz1;Xrpi4h%7GIP-+)!7lr{gI#yr zu*P1TLByck-qx3_tA(025lk(_j@CZRvTt5btBtEF%BR+8YDz=SS8Y4M(_orTM(pMyw<~i>w~{LVs>t^G1w`Yhc~(5}ixw-{N~k zswZ|w@dBT!zmloG8i>@dE{~m2IOl0xN9f%gor1+6`$-AykMUzo>&_iVXO^(5W^f-m zyX#B9K$N{|Q75lzQCa58SMV{dvmeJb|M@RQ+SwCloD=r(p*U`y=0Eo(p1&Jm{ax-= z@GWaSAI0&*B-$<+R~a0U2g?fK#Pp%-L6DgRU+J6PSFrvAZLtpFV;V)u3+b1*J#_?j za+KYmv&*UlN3I6k^1Yj$Eg)pG7!j}VC(*gKW8q1^H{~y4ad}Eu)N5OpYi9RtptGEw z+l!5#`AehvoZ*4nx)7S)%X;Dwy$>fQCHPvqQBArZ7Z6)*oxaESo>nT)allE;yhk2x=KM&xSC;FM%3{VfrUXisXUkn|?W){+1DKJ~@Bqg<%{xT& zROIx|-@KqBZO5%89#JrLJ{y4VP)JYKC6pI*;GTGUJK&}dCO6w3 zp8P9GAEq9fPHdGoc+};USJ}o>Hd}yg06QA;d6mgCKX2FMqqF=a3d0aW~gMdTN~XJT{{%*XGb#`!1{OLzySoh}!iuU_iODSP*%V*!kwEra*=@ zb3b<<=QP@Oe`=tI%0ewOHh?3ps+ef>64Ng|@!KQHebXG>vK^(Jva8*tNN)F~iizE! zQyuZWJA6uXWGn4l1C^G>HK(Z&oxJQluKCrz>u+tquZypVMa!^qbD7D{);;f20DfcP zAyuJD-m_OnIuSKrt$%s=@AsF$gSGoUuLhT{%(hDUZ{8s5Tg@4pUKjrhA%DAoWZ6Ku z4!^C|gYl2~SMLr0{KlSUpO{(%r@V77uMoL!62$jgb8vbfRsOViZ1=gI052#pi?vW( z0<9Aw8DJ7gy|y$0KFs=jHRIuoPEu6-GoIDWC<*)->UkQ%+tp?onl+Qh8k+M&KxWT_ z#MY9rIq4py=jHf~^7%7F9JZjb-eD-Gw&B=H`a!(I%$OXvb|ex>JK)6l%lZ>zJvqF> zZi9H2xd_7(J)&yDh+PcIhpm^4c5JhPSJG3%p{W8V+-RbA0BqpDFCIXhxP`&jNUR@+ zFb-q_aKB>U8mj`4TnkFW)hSN}Y=lQC3ZiVgxn zlGH09m%x5*>I5%Xn`fP=jrR20Eb#NRh>DcY(T-O zOE8s&p=&WS{o`WdG6|h@1DU(zm&W>j-VC`;T1Ob1hxMe){>NBSkJ5UonD9%m7&N;! z)aC-$9=-6#V3ipsp_-7?+ZNzZ%dcq<24Jy;Szd1ris#VX3L;taAD1q`#2oSxf%ZhP zp!Y-K{HQNk_mKw0e5+D66#jf_YWN!-i*424D=B+79INohJ<}>(1prVy?kG~4FyFy( zMo(@xn4XM=-G4eABh-Zf$4lR<-ed650>r6pMDINky4fO867A_G{q9$sk|3q!if1ja z{TK6N3yw9WE<7Y{e(<-)@Q!-L2c}1ZwMs$wXGjNkG6~<|{l{fZ$K0TzfcMY5{sox9 zfiOM&!1B+)y1|QUma#Qxa8<5TV1S){d=3Ow=t`lS_5R=6i1pW<m!45N_n|9Dy*OXh)&#HCW;b+zQk87gCxW4hm2rh}&cRIHZ2g)t;QLeD7 zC;%o*%(XV>Gwyl z-tjaU;rs(gMv8S;qJOooz0L}SxsP;OfADmdY1P1Ww?X|eH zpMBjmZk}Id4AT~*Wza1~D{v(|YWpzl;m0*-gL;eP>USJ*ON-8Yai4ixx%_bSX#?6k<>z@SB~Ho~$D75vP$u%b_zz+C*CTRt zdc=yWznMH)dz(=6R{}$pF4;*PW>80<(pr!X{av9X?5%m-XKrr-g z3YYH$3QG>+6@Fdq)kcEGIj4fAMeibZ^4B!&#|CbDr?Bp({I4cIVL++oF~fY9fZnUL zy*Y))Wm7loCLr`4ta=6SCTn5i4f;u=@0XjJPT(Lnr5FVBQ<9=?v|d5{*#X8#OJTbWPw0OX?fP!AlYgLr zzlN0ca!|iM)<8YEy0mDc$P)??gm-qCU@;Nurlr-FGAgZt3!(w!QDW=<{NOJu=Q_kx zVJ&N;gJ;n4qMAs^G@~O};KE=inR&1eFj@OI6KjxQCHzn38srkYop5XBWmZ%l{{TV< zp~1y}dd(f&HLE6^k!$U$DJY1BBe;>w5Vt++{{r(6G`W+u!gxy(19%s#>;#ggjnJor3^~?IVU*g5a?cHiqNnm1BY8_esfu?)lYT zm}!9V8ApU_i5<)$&uN>RTg8Lo6^- z4lgj_y9p^PB$t0+^aDWM?EH_7TG%62{vBmv1j+&}YheJO9G?8>D3U-_3LKO0?e`EH ztHSU}`(U$4LYs*Zh(j^_0|x~d=!vC-bp_mim9?4#1eJmelnX6U*^-SG3-~fM3RFQZ zK`MFC7NphH5thP&_-xX<(b>e;(~v)_`42UNt6(IdM-5a#g;16a+9+D@AeTJgLGBuP z(MiraY^-n?xY|Z{_ ztZzuDYjZ$08G*7%4r$rs7?{RRsIL7&QZ|7+N@87$hblCQju2EONQ3HQe8CQE9M~vS zLEr&}PZzK(gnxj)*`({6Nf&8_&m$nyTG$Q<1rg7jgn$kSjsGdM?GHi;<*xr4D=A^! z04$P{pXDzpTQGOEyl7Ya7R;5T!Uyu`e~M;O_KIK<w z1clEcD10slxohP`)8|Jol9sbT;X`Fm?+FSY5Pe7~d?2A_c%fQ<5=y9B@!w)~C8al$ zU@4r4&mqGbU6}YB(zOfpouC{d-$_yqfjn9SK{aZlIRxJ=gC+QuuaNdQ$6 zYjn-N_n@!A1&Z`IzZygE_AQM!e;b3E6EzCj60;yu0ooh9I zAh#Id8rdSp+#u$3Xdf5AKX7ar>L^g?sqm?|@ zw%BC5P^R)@!Z=#i=k)<61`?$${PAGiUU;#W}BWA)km9Qr3S=J zBZ=)Vm16%U)J)!51V{ULH25r#IU#zUxX6#|MV=d|;scI~L&E=1Z0%g&`R(O&5#6>o&5!u)`h_M+!iUXOin!H#ouu?Vh zvn&$#h_reUO2Q;n~DDqS@W8REY|uI@3pNx_Q^@n#7z0wG5N?5(WVK}1>z2FTH{~< zK<@$3FBS=%7TVqeZQeEV#9HB@3oL6|;b6fud8Mz^2cgxUHI)`NeX}6aR32!SU)xj; zU0lTb^G2e|d<@ef3z}FLT(;d}P1Am08Y@2=Ga@QDAqs5ll{ZZ!3Ow{0;PuG*bb|lX zG_dTB_rQ@a7DnGJ%6s{UEbE~~_jSD=yv&C{=9s845Lziedv#+{n?XRp3w`)gXxkrz zf>^Rv;r}k{m?)9n&#YzQ+QW(WXmq_En8xC!)Rp?@=wMQoi0XWd-eL?`A>C*dT_u$1C+V zhW-Ca_Wva_exXjtDSC@P4t7|7MXuS|EA=tQ!;60?VdCe%6eHKm-Ym{3*2U4?+nAqW>BzDS=4mS(6uj zQZh&iMD8FEX+eQ#*@>h;1bMU{!j3U%fe1`uIX)28kraqzK_H5PFz&VCKqML31d`?; zu*@XUU2{H0a3N-}P?gB(Y32>jzH+ECfN=WGWFo8ME8{-?*XZ1 ziv%o?exH;Q$X#W4{5GWGbe+nDskB&=?W<8Hl9EolbcpWt?Es|k69RG5V4KNKk6u1o|SrJBwk&)4WmK~s-z$% zc{n7h07vs|w3eb7obCt3RK$>|me!c4Ampld^0PbjHeORN#zaAK0Uq#z7h;%5sp29) zc?#r$Wmo?vu@wXg!2cGj2?^oT2!ziz??d3<;R|si9eh>(g@lCy2|e;t=<7cSJuCFjy~=-$6>LigUkf1+!&>oWF_=-kjV{hW z{HEjah-ePJz8E1XctIX*@E*Xid7=@pnu0mPN8E>_C&Gk)lwGSQSXDRt$?q(PD4`E!s#`f(o*RU@fJVBAbY)5QQM(79zMp z68DIxkxf7(LD|=^gzU+E6PA+n56b<2&(HcE@DV2W&T{5A=bSln=G?h;tw+iwKK!2o z(St{lJWZ|~t>mZSw{guW8Eu_)Y-w%F!=am+p*djWy=kFUagkl^DC^oc6kiB3{-Adq1t=fJsjX1yPHp4(ZsTs;;XeYv-3>+2yA=pu@7nfNbiJ z3;9T8WcxeWhKvI(wpqe$5G>>)YbyzlVD>Oa;?!jO4QP+9F|>okT-8D17vSg%9p8i{l;*-wlf!KE*8t$I83?WEajpy$je8fpLlrH@DY^=ZR>Dz~ zz~W2qu`+KDce&eRPY8ONnqU&65`iSIqzihY=zM}iA}K<=3hxMXlg3V+@#)sBr5q2r@1 z93F=oeKs^p%hXjTHv@wVdB;jfm`MbOhYcR|TAmfCg#2@My{x3#@<&_xd3}TXwnHvS4X4l;RuwYAN7czy}f# z+qqCyJ;!81kl{Q>Y;v#A<-6U>`Etq$F~fuLY$lZ5$GPKXOkQNPM~;#Zw4Z&Y1W~F# zu}6Jf!Ve`7 z7xN#0J3)2e4$T|fal5sm&a&?TGWy(`;ER$0VC_RhN}Ou4>V;h~5dG*%&W@0k%f)3H z3OeJgkJ<1a>N)5|pj@vC?^8__J+M^V2~*s8qG+XhVxn5#6NjRdD#e$9;KH^Svgz%X zF=`~)`D{opf}R(=VUu_Of~iEOb@Ffzi~<~-qH0Y=)$xj|A1SJ?pO|Q=T(zZY)l0f8 zV=PIsl5U_%2yvp4xs4v~ug?}!g*s8V!7#}4z$;qvQ?#Vv_jsP>-=XY^F9TXiF^*SB zN9IYsg7k|S6pw=M5~I*g`Vqv4+G;IkvSK`0ii&g;6`3hWj#QAWJQ`2)`<^}vUgsVD zG=G2>!~DSM7`f8;$N4O|0~ylOWaNSWJZiddVp^0f({C=J#fZM5(Sy>V=U@;N!CfmZ z3knV|WFp^Mg8`q;Im@F`gcAvgd4J==;eMgKBcvd{#y!KSZSyF|Z=Tec$t@Sl?+*bl z;2Z^iAQk)vpnE_~5N;3SFP-{&)&W${ndjiy0=;hqD+VU~%CnLK(8jkDA}#i<0U_NA z+<)BF2$&b(u~C7?3=+2q^m|;dtt9q< zUs$HWM#<~_k7$ZGr3w)`Fuu{lCOsPYXs|?{$G$%=L*9SYYZo&8*SyIGmGwRht>8q_ z=}{^Y1T6`pJUB4kV&AM@!UNXKBJ`D1O~e9XH_P5kW0{hpI!-SagG4Z>Oi4CL>q7^E zkZ!LKpwippLHkDLHAHu&+dV*VJCP}8Ky8kl@oXL9wO!(Px$G@v#%e|(q~EnM`kZ^C z{4K?3HT_$2S`wuNYJbwObRvDf^uAf@jHRL{fO;>XR85Kc%A1hrFy%p)hQ+>B3hL#W z-?TMwh>I0r%^vK8ngvjZy?z(BH=!4CcyD*O2k`6Lfcx~?X-$8Jf>+Unmz3)z+=5&| zy;)-{_HF7xg+uGBkn7laLSPi|R01j?*y}~i@B&pTTH;3F<9;6qMZRf)+=x(;9rrfk zl`6B2Eq5afsFL`x9E*?#USg%1^tL$Txwjjdb&2c24sjsG3W^ND3#nhWT7l2654dFqb^8?}FlDA!>21IbQ zpthA#LDCTl9QV5m|A=nJ@(5Afe1oG81+`ktx023qj}C(9K2=BuIzQOGkoi^!CQS!zoDgvx{pk~$#uk)YPfTmaZBg_|=lE=m|=cRp{+U7nDmOhb#3|wNx<>0hbA~k6e>-zO62k4J5E^>mN=Fd^?Q_Kf7AlH2p zv}lEreNvvon2t<4xm|j*4a^AJ-sQiMO&DO6UBG{X$7IMKaXW4w9i62!^fIAk+kkFZ z36=>OK@Pr|!pPA;)_yIIXdK+k1ymk1R;AL?_TlO(eBjpBSvhomNe-jc<{>H^ z+AKak_~M|@LRqowdfvu0#dNT;q2u(lL2c+Po}&ujS(1te>!n@Ij5Pe+333>H&}4P6&cNuy=6eUEU3D<};MM*Wv_~||KBRzQ z_!4ws6`U@pvG|CFVUMzgO@;cIVUK`*`yQ>(VGnT7oh)0#@cC!>goClY#n8wtgGKpI zuqcm!MY#nm$VUkOhcY;wRVoR(a}gHg6nK!og2gMpz~Yq=!c}JvAf7ouJj-E0{xdAd zPr>39JUm_*AzXE?KAj~1;+X>raxOf`;Y~tbuy|#J@PCS@5>pP!d{cW=KStg4;l38(D!@mg)9uCD7 zgc<}PRCg!7|Fh4BGOypmWxBO6=|weeBy-OhD*qxh)^=vGAUCcWWL!kDR|)XYCeQ6Z zdawTkjY6Z!ake4+KrP{SBI$J7Wy;51jCVfPf7W#0lkRI8W7~eyM+MO|q^E-Af9cOu zdaJ3)5IP}>L}RPVS0jmbTG2|U5XKFu6naP}p;9%_N-t}*ACdtnf>2@{i&UVlvPC#^ zW&e@u{qE^w=8bC_Irzwny8e>@`@Mc?j<+WVN?W@1+wq+u%fL{jSEnZZ@4#M2k_9p}q*pamLraFPJVZ;l zQ!7;E0E?jsm+80X>myX%P(y+uv8_t5MX2t{4hgs*=#B*(ZQ>4R_FxQiVggLaQ4ayu zwn{wL&?FPI7r`sgESrv(y-=fM(glQfL^45kv)8*uft*Ky>M9iLjXNj zR!#yu4Qqx(!Qp8l9G;c~+j{s&Q{f=(0S9R&9F~rP!_prFXdcc07%p0Hq-7+tUg3b1 z^U={*E6!qoA!NXkEI2w$4*Yn-m#k}WBx^Su$tr~-Srj;uSmWhjRyFXaR?nMlvgF(vOY?(4<^o(7>`YM>0=r>|0R&8=wO=DGMyhU>RW} znZteh7Ww}M=#EKSni-`E=L8R@8X`U7SNWiRl@IIA;^7#;$^D7BDS#tu#2?gi5O|Nn z6L{W2fJ5lha#H|TCzzS=aO^S;96S6I^9KRXTRq@uSd-qzcT@E2kd63*z_I!YV+&Y0 zOfXg7hqE9a$*gSUd~`I9$y>N!2tP45MUPK=#2*A+6`^ndg7qQ`OfBhfTumdHmDh_O z9SxvKOMw`|+VLC7tgJ~tIvPNeDz*|~ZHJ9yUa_=qqyFCj9k5Bez$QJcO}UZGvy%E^ zR{jmp8KER{t|I8;TUp{T1E&7J#H)N*zY3G}0mFpA^hf~~4lK{SJFLYsoGt#3AGY#I z`h$Sy4eTv`Vs46Fq(4O1$|va$0-m=3;CX{J>HS|0Tlp0ILBPuC08@1)oB)ZD%*s~I zM@J(KC6Rz390^GYh=P&q zeNSV5$aWg9T{(eQgt>B=TJw}xvRCXN9<^hi#qW9Ux2~=cw1^3J%mivPN!roNoqzb# zew?Y%PV(su(GJclFW67WF!CiQFO0S;{Nbd%rl-+fjir@Y%>p&bYmLxg=VjyVzce*A zA|E>zv)}pqukEK~7+aB#7smt^F4MK2>}foo9G|V%;LmC+<*K*ADB;7p!qIqrOA8?) zhib>pc6M?=o0`t4CI7l1_G{*fIiM5n!) zso_fUiDS{u&UR1iM`sxRNIqE{y~%l1lfAm9;c9YXcC<_3!81j+IUxq#^+-fb+$d-C zpXddqv(m_a9g7?9Y<~f5l`-oY`Dk(6m_qbPw58{)%jDK&=|Kl&$g1ZA#AB1u`;5c7-kieK#YGE63rV;08zT)2FbeZ`?(V3Q<>Xv}!@EYsN!$-f6hh@iJS5Imy@0NsG!yO5~HuYsl)0tu9KeXc} zIXgT-FUgo0PyTa5oUXHD6WZ2uW+eH@!nmo04zDKq+{S(Afq0W#NiyeX*wAY_l4FL; zAU>?#BBJE&2Fr#GR;?tInP9`QY*9xKd(49k+J&+8LBA6a!$vHDtFG_f8O+MmnmO!& z?}C~ ztd?#GA|Gz2YvFc!Kip2kojWq&@*Wm0@6ChDd&lAO-iI6pW>6iNk{846^jB~@eH3n| znQ(cp8ZPhcgUNeUaP^)yT;BVj!@#!WiV2~xVI3(j40G_`1?y2ki^8UT1XF_UM8cHO z&>3*Gz;|% z-nSg?NTzLJX!*mnEvv%d4uuX}esY5=cO#v6pWgt8b~6y|jj)FTwrImO+pFT?^3zBs z-Y?pflo8+9Fujz1aAo4(<)plC3tncIVDVW9bdq`M+zATy4E8*hjJ0SvI}Jgv%99`25)Sals=g9;QBJ^GU{3?nu?|V zK;1xfqHdusr#e#|sGF#ER2S+RsvGrt>N=`D)s?!E`XjY<7sLH7By6p}aRYxh9B&}! zClGT9vc_jbNo@j$AJoNSNv?JB8OhKyhD6M-4#Bi&U5+QcX=w|8>DeZG5qOdlvI~C_ z1-(G-mUpg@q==feS})cK3|{5b)is981Q^=|k|XOde6793n7#a{y~V7(d@ZkHj2A!3 ztC;1**TNTL@cbxzF$>REo8~*}XM;oQaN7javA$ytk`Dcd+gAIXThgIQ+_sYGWrQ&< z?@Zn#j9HU(r~+42JYA7w$o9)hdQwUk|1;??`P{~L3>&GANjh|cb!R=Us@1Zchf=T6 zQu~j~#nY8?-`z{PyE z&LgvGzl`FRRL?Q!zGXA2GwIi0!y4-eqCXz{ecc%o!}Y0|W5_YhTjfA6ij6uEoNjEe zBtt-sIkPZuovyt@>UU|>sLYr3vt2!TR~Ak>ZfD^*$J3K{ec_}8JBs6+08bu$;iMCG z7EW`Hc=8@CoRnxsahj9p$$P$V(n&ju)z$h?-dWblpNbl;c^ZBf$v$QGYf-~PPs1gV z?9+BBMGYmMhSrhnB)fY>4Yi(zwvp^)ySGIR-JXW1NH*zFkd%1>sbjx3^}F*iW32+i zbo17x`kjyY!Yc5HuKl{y8|P!DSp`Pw=B-N=oR67l6&Ryy@0|KwM$BBR!1$9D)u{E| zx6mhaX-<*kjDm_{^l4q%n#h`r0!cCYj4o|$q~V2v86{}4F3mY|$Atpx67+dp+J;E- zg@Vl`HYmBe8!4jZLP1aoI#ZX1jWoPiaH<5ItxMY!x#MC%P6_&^E^SLB`C>su2|8Do z<`!9Vu|QISzN1Uq_AI};;CH0X5p3$lOEG_01u}KVxuzyuiaBN#n6G=pHMR6o%xSAY zmhQMssXCWq$X0x*dM=oPE1_x28ym@h4mJ6zacslstwK&TqySuYw%q60IT$}uaTMbFQWn4Cu zHT4yLR}vrP8zwLBY2{tn2G2k;i1>!498eQq)I#e#bBR9Ck4q#Mu z{Cd|KKh4H%fq%W;VW#64E^TMK|FdPJ{OXm5{n!irbAM@no--yYVFEj#qN?NeU2E

p1YLhmjokOnP2T| z3|MejE&T^olqek@MGT~DlV!hj$72t zTh#r&%X^E8D=Lh;c-K4lj0gfoma{lIYb`3GX5LHIq$Q5sSx(RQ%PvJ{IioJtTzbjU zRp>_OKm}yZ$2V~vs_NUF`;Rx{!cNC4lr68OG(*N7^M1umKNXDZPR?^ZPx`yKs}b&6 z$jisB7fG#*=Qxq?FT~$J8?++2q}r{9X)CvpM4=`UB^B-=GI3+q4RI-+L=Tp?=8!nZ zU@1?O&XEg^?~>>tVr;NjdJYZoTPYl(M2rzVzi;7=lCct49HjIugCOVgyIJ^I(l!R0 z9wOoS>9;Wcaz{ydE+Im3QMybM>f~3;vutG)9d4~xGStmT-~xMGBAEBJ35PEII)qqx zQC#Z|1Ij6EN+}a?)qjtLAAbMtpYZtI=Kg#4 z{Il?di0C#sD41e`Kul06{1dne3Lo$Z*t7G%U_~+QqQF8>#0U_qt5WooMo-aRnw480 zlzzJtbJ<$jfP^p9036Cc*T(jeuxtDNojcb1?DzD-4N8fJL+&eQ(ANk+$(PC%Ajaq+ z5IgW5Yxm>54_J8M_wO96BfGs)J`;mtr$7~7s1#4oS1P{U+k3FmZ(bro6F{jB@Hbhd zG|ND#w1@8jAN=0IDtK#sLu&_Ux_IS5~z0gIl03wmoAJw}mvJopU-zzN0z8W8^jw2^bk literal 68514 zcmdSC2|SeT_dlMLB+_CjiIkEGiIR0%g)D_OYuRNPS;sn+P)TS*Le_aGsgT`-kdS4_ zzGdH+!5Cv^e%C$qc^c1S`kMZq-|zeSKd&11ocliaIoCPw>zs3)>(X=XEaNJU70k@c zD->OiUS2`<-#Tz@Xm4umASMcZCO;}rFFMHTJMMmeAMSA5G3Mxm995+p0ZG1(g0|bz z@5O%do|-+ic@t~E`=W<8ypSZL_;yv>1MLU*oHe+2;mW<0d3%gKQJ>05H(bSzRK|Ff zY&?2K6Mk}^eV~TQbVb+kFLCaUK`JZ*Shce?4E@FmW|eo0KUu$( z^`Mg4#t?zNvCmwXjE4fmC*^~op_{X_`t0qDrkN^pH{CgC?&z+z%Tq~pEQ)ixgrSPR zPUJ#)-{x~?*D(7$mwY}3jPP~kiWTQ*nu#4efv^^Hf!kXd!Qob-2pj7Ftrq*{gBv`@ zFCnJa=i3P%3}roxcof#YC$22jI_2H{1FmtqkI4{mZ%kh#U=*eq;_?PYn%cU1E3=-p zOKjPncK^yz*3dQk8hp+XLOtD;)=2bS=}GF;+<&)e^?{r#dAgBl(k43ma&9Ts75hG! zbrFuFyzF!SYuh;v;q*l5N0zhsHmnnc7gt<93uC#RXy_1q+3)Q^vUha3X3yIi{5vL} z?ROck=EA3do#rf&o zg!R&zXY^G1IC%wLtm#(hWoHg}qHOxPNrrFri;;1JmCPqyn@|21Klh4C>3j)|mNs~` z@jM3}y)(!89J^d<9(F-cJ6c0LmQ%mIRby;kkma?-EliDdE5Y{o$o>aS2VR`1I2qZN z;eEeJ@TGbDK`#A`euasT&0o4DpJv0uW$a~#H8iqrWrtil`}Awh?R~NlJA5L2IKu=> z%mnsc9lQToVD@00tvZ&Q*>`HQr}ilUYw4|fVS~4Ke7oZufEMk)4nMY2=uy!Q=0Yy+ zuX8mqvMHL6o{u5Rl#|4PI!&TL|=t6VH4%E7xoGI*MIzYEu!4 z7%N~n`I=|jR+QTO@NmJMW8d0aDxJq4ah+RLF&B=X+p=w!kXQQtMC?}o=XM|Lgv2}= z3Jы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 Date: Wed, 31 Jan 2024 14:04:48 +0100 Subject: [PATCH 05/12] fix #114 backlight switched to high if u scroll down through settings --- ui/menu.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui/menu.c b/ui/menu.c index dbf203264..c18f1a083 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -620,7 +620,6 @@ void UI_DisplayMenu(void) case MENU_ABR: strcpy(String, gSubMenu_BACKLIGHT[gSubMenuSelection]); - BACKLIGHT_SetBrightness(-1); break; case MENU_ABR_MIN: @@ -628,8 +627,6 @@ void UI_DisplayMenu(void) sprintf(String, "%d", gSubMenuSelection); if(gIsInSubMenu) BACKLIGHT_SetBrightness(gSubMenuSelection); - else - BACKLIGHT_SetBrightness(-1); break; case MENU_AM: From 80de2154a42b706578048b73cec75f2bb7017aaf Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 15:05:14 +0100 Subject: [PATCH 06/12] MSG_ClearPacketBuffer implementation --- app/messenger.c | 14 +++++++++----- app/messenger.h | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/messenger.c b/app/messenger.c index 31761e823..62dc3e8b2 100644 --- a/app/messenger.c +++ b/app/messenger.c @@ -273,8 +273,7 @@ void MSG_FSKSendData() { } } - // clear dataPacket - memset(dataPacket.serializedArray, 0, sizeof(dataPacket.serializedArray));; + MSG_ClearPacketBuffer(); // enable FSK TX BK4819_WriteRegister(BK4819_REG_59, (1u << 11) | fsk_reg59); @@ -554,7 +553,7 @@ void MSG_SendPacket(union DataPacket packet) { BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); - memset(dataPacket.serializedArray, 0, sizeof(dataPacket.serializedArray)); + MSG_ClearPacketBuffer(); // later refactor to not use global state but pass dataPacket type everywhere dataPacket = packet; @@ -640,7 +639,7 @@ void MSG_StorePacket(const uint16_t interrupt_bits) { if (rx_sync) { gFSKWriteIndex = 0; - memset(dataPacket.serializedArray, 0, sizeof(dataPacket.serializedArray)); + MSG_ClearPacketBuffer(); msgStatus = RECEIVING; } @@ -838,7 +837,7 @@ void MSG_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { break;*/ case KEY_MENU: // Send message - memset(dataPacket.serializedArray,0,sizeof(dataPacket.serializedArray)); + MSG_ClearPacketBuffer(); #ifdef ENABLE_ENCRYPTION dataPacket.data.header=ENCRYPTED_MESSAGE_PACKET; #else @@ -871,5 +870,10 @@ void MSG_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { } +void MSG_ClearPacketBuffer() +{ + memset(dataPacket.serializedArray, 0, sizeof(dataPacket.serializedArray)); +} + #endif \ No newline at end of file diff --git a/app/messenger.h b/app/messenger.h index bc496e1f5..025fce271 100644 --- a/app/messenger.h +++ b/app/messenger.h @@ -60,6 +60,7 @@ void MSG_Init(); void MSG_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld); void MSG_SendPacket(union DataPacket packet); void MSG_FSKSendData(); +void MSG_ClearPacketBuffer(); #endif From 2e47deb0c14666c3f7ad189363e635355f8a3d2b Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 16:33:11 +0100 Subject: [PATCH 07/12] refactor --- Makefile | 2 +- app/messenger.c | 58 +++++++++++++++++++++++++------------------------ app/messenger.h | 2 +- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index 1fdd29c59..4599ba2ff 100644 --- a/Makefile +++ b/Makefile @@ -225,7 +225,7 @@ endif CFLAGS = ifeq ($(ENABLE_CLANG),0) # Highest optimization settings (possible breaking changes): - CFLAGS += -Oz -mcpu=cortex-m0 -fno-delete-null-pointer-checks -std=c11 -MMD + CFLAGS += -Oz -Wall -Werror -mcpu=cortex-m0 -fno-delete-null-pointer-checks -std=c11 -MMD # Standard settings: #CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c11 -MMD #CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c99 -MMD diff --git a/app/messenger.c b/app/messenger.c index 62dc3e8b2..ee829bb25 100644 --- a/app/messenger.c +++ b/app/messenger.c @@ -273,8 +273,6 @@ void MSG_FSKSendData() { } } - MSG_ClearPacketBuffer(); - // enable FSK TX BK4819_WriteRegister(BK4819_REG_59, (1u << 11) | fsk_reg59); @@ -541,11 +539,11 @@ void moveUP(char (*rxMessages)[PAYLOAD_LENGTH + 2]) { memset(rxMessages[3], 0, sizeof(rxMessages[3])); } -void MSG_SendPacket(union DataPacket packet) { +void MSG_SendPacket() { if ( msgStatus != READY ) return; - if ( strlen(packet.data.payload) > 0 && (TX_freq_check(gCurrentVfo->pTX->Frequency) == 0) ) { + if ( strlen((char *)dataPacket.data.payload) > 0 && (TX_freq_check(gCurrentVfo->pTX->Frequency) == 0) ) { msgStatus = SENDING; @@ -553,28 +551,31 @@ void MSG_SendPacket(union DataPacket packet) { BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); - MSG_ClearPacketBuffer(); + // display sent message (before encryption) + if (dataPacket.data.header != ACK_PACKET) { + moveUP(rxMessage); + sprintf(rxMessage[3], "> %s", dataPacket.data.payload); + memset(lastcMessage, 0, sizeof(lastcMessage)); + memcpy(lastcMessage, dataPacket.data.payload, PAYLOAD_LENGTH); + cIndex = 0; + prevKey = 0; + prevLetter = 0; + memset(cMessage, 0, sizeof(cMessage)); + } - // later refactor to not use global state but pass dataPacket type everywhere - dataPacket = packet; #ifdef ENABLE_ENCRYPTION - if(packet.data.header == ENCRYPTED_MESSAGE_PACKET){ - char nonce[NONCE_LENGTH]; + if(dataPacket.data.header == ENCRYPTED_MESSAGE_PACKET){ - CRYPTO_Random(nonce, NONCE_LENGTH); - // this is wat happens when we have global state - memcpy(packet.data.nonce, nonce, NONCE_LENGTH); + CRYPTO_Random(dataPacket.data.nonce, NONCE_LENGTH); CRYPTO_Crypt( - packet.data.payload, + dataPacket.data.payload, PAYLOAD_LENGTH, dataPacket.data.payload, - &packet.data.nonce, + &dataPacket.data.nonce, gEncryptionKey, 256 ); - - memcpy(dataPacket.data.nonce, nonce, sizeof(dataPacket.data.nonce)); } #endif @@ -603,16 +604,10 @@ void MSG_SendPacket(union DataPacket packet) { BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false); MSG_EnableRX(true); - if (packet.data.header != ACK_PACKET) { - moveUP(rxMessage); - sprintf(rxMessage[3], "> %s", packet.data.payload); - memset(lastcMessage, 0, sizeof(lastcMessage)); - memcpy(lastcMessage, packet.data.payload, PAYLOAD_LENGTH); - cIndex = 0; - prevKey = 0; - prevLetter = 0; - memset(cMessage, 0, sizeof(cMessage)); - } + + // clear packet buffer + MSG_ClearPacketBuffer(); + msgStatus = READY; } else { @@ -721,8 +716,15 @@ void MSG_StorePacket(const uint16_t interrupt_bits) { gFSKWriteIndex = 0; // Transmit a message to the sender that we have received the message (Unless it's a service message) if (dataPacket.data.header!=ACK_PACKET) { + // in the future we might reply with received payload and then the sending radio + // could compare it and determine if the messegage was read correctly (kamilsss655) + MSG_ClearPacketBuffer(); dataPacket.data.header=ACK_PACKET; - MSG_SendPacket(dataPacket); + // sending only empty header seems to not work, so set few bytes of payload to increase reliability (kamilsss655) + memset(dataPacket.data.payload, 255, 5); + // wait so the correspondent radio can properly receive it + SYSTEM_DelayMs(700); + MSG_SendPacket(); } } } @@ -844,7 +846,7 @@ void MSG_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { dataPacket.data.header=MESSAGE_PACKET; #endif memcpy(dataPacket.data.payload, cMessage, sizeof(dataPacket.data.payload)); - MSG_SendPacket(dataPacket); + MSG_SendPacket(); break; case KEY_EXIT: gRequestDisplayScreen = DISPLAY_MAIN; diff --git a/app/messenger.h b/app/messenger.h index 025fce271..e9f517ce5 100644 --- a/app/messenger.h +++ b/app/messenger.h @@ -58,7 +58,7 @@ void MSG_EnableRX(const bool enable); void MSG_StorePacket(const uint16_t interrupt_bits); void MSG_Init(); void MSG_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld); -void MSG_SendPacket(union DataPacket packet); +void MSG_SendPacket(); void MSG_FSKSendData(); void MSG_ClearPacketBuffer(); From 89bcc17aff4a464f46e2fa61decb5564d392b19c Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 16:55:38 +0100 Subject: [PATCH 08/12] refactor --- app/messenger.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/messenger.c b/app/messenger.c index ee829bb25..e803a6e2d 100644 --- a/app/messenger.c +++ b/app/messenger.c @@ -624,6 +624,9 @@ uint8_t validate_char( uint8_t rchar ) { void MSG_StorePacket(const uint16_t interrupt_bits) { + // prevent listening to fsk data and squelch (kamilsss655) + AUDIO_AudioPathOff(); + //const uint16_t rx_sync_flags = BK4819_ReadRegister(BK4819_REG_0B); const bool rx_sync = (interrupt_bits & BK4819_REG_02_FSK_RX_SYNC) ? true : false; @@ -654,6 +657,8 @@ void MSG_StorePacket(const uint16_t interrupt_bits) { } if (rx_finished) { + // turn off green LED + BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, 0); const uint16_t fsk_reg59 = BK4819_ReadRegister(BK4819_REG_59) & ~((1u << 15) | (1u << 14) | (1u << 12) | (1u << 11)); From 76fb5adaf349196e63102c052142adef1b79c5bc Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 17:00:27 +0100 Subject: [PATCH 09/12] refactor --- app/messenger.c | 18 +++++++++++------- app/messenger.h | 1 + 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/app/messenger.c b/app/messenger.c index e803a6e2d..85c498e90 100644 --- a/app/messenger.c +++ b/app/messenger.c @@ -721,15 +721,9 @@ void MSG_StorePacket(const uint16_t interrupt_bits) { gFSKWriteIndex = 0; // Transmit a message to the sender that we have received the message (Unless it's a service message) if (dataPacket.data.header!=ACK_PACKET) { - // in the future we might reply with received payload and then the sending radio - // could compare it and determine if the messegage was read correctly (kamilsss655) - MSG_ClearPacketBuffer(); - dataPacket.data.header=ACK_PACKET; - // sending only empty header seems to not work, so set few bytes of payload to increase reliability (kamilsss655) - memset(dataPacket.data.payload, 255, 5); // wait so the correspondent radio can properly receive it SYSTEM_DelayMs(700); - MSG_SendPacket(); + MSG_SendAck(); } } } @@ -745,6 +739,16 @@ void MSG_Init() { cIndex = 0; } +void MSG_SendAck() { + // in the future we might reply with received payload and then the sending radio + // could compare it and determine if the messegage was read correctly (kamilsss655) + MSG_ClearPacketBuffer(); + dataPacket.data.header = ACK_PACKET; + // sending only empty header seems to not work, so set few bytes of payload to increase reliability (kamilsss655) + memset(dataPacket.data.payload, 255, 5); + MSG_SendPacket(); +} + // --------------------------------------------------------------------------------- void insertCharInMessage(uint8_t key) { diff --git a/app/messenger.h b/app/messenger.h index e9f517ce5..4bf99dd92 100644 --- a/app/messenger.h +++ b/app/messenger.h @@ -61,6 +61,7 @@ void MSG_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld); void MSG_SendPacket(); void MSG_FSKSendData(); void MSG_ClearPacketBuffer(); +void MSG_SendAck(); #endif From 6c3793ef74ea09e4372dcb19e3d9fce320653ec6 Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 17:05:23 +0100 Subject: [PATCH 10/12] fix: only ack message and enc message packets --- app/messenger.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/messenger.c b/app/messenger.c index 85c498e90..c60eaff9e 100644 --- a/app/messenger.c +++ b/app/messenger.c @@ -719,8 +719,10 @@ void MSG_StorePacket(const uint16_t interrupt_bits) { } gFSKWriteIndex = 0; - // Transmit a message to the sender that we have received the message (Unless it's a service message) - if (dataPacket.data.header!=ACK_PACKET) { + // Transmit a message to the sender that we have received the message + if (dataPacket.data.header == MESSAGE_PACKET || + dataPacket.data.header == ENCRYPTED_MESSAGE_PACKET) + { // wait so the correspondent radio can properly receive it SYSTEM_DelayMs(700); MSG_SendAck(); From fd032926691a8c518e591295d431d4722526993e Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 17:15:52 +0100 Subject: [PATCH 11/12] refactor --- app/messenger.c | 119 +++++++++++++++++++++++++----------------------- app/messenger.h | 1 + 2 files changed, 62 insertions(+), 58 deletions(-) diff --git a/app/messenger.c b/app/messenger.c index c60eaff9e..69bdbae27 100644 --- a/app/messenger.c +++ b/app/messenger.c @@ -667,66 +667,9 @@ void MSG_StorePacket(const uint16_t interrupt_bits) { msgStatus = READY; if (gFSKWriteIndex > 2) { - - if (dataPacket.data.header == ACK_PACKET) { - #ifdef ENABLE_MESSENGER_DELIVERY_NOTIFICATION - #ifdef ENABLE_MESSENGER_UART - UART_printf("SVC= INVALID_PACKET) { - snprintf(rxMessage[3], PAYLOAD_LENGTH + 2, "ERROR: INVALID PACKET."); - } - else - { - #ifdef ENABLE_ENCRYPTION - if(dataPacket.data.header == ENCRYPTED_MESSAGE_PACKET) - { - CRYPTO_Crypt(dataPacket.data.payload, - PAYLOAD_LENGTH, - dataPacket.data.payload, - &dataPacket.data.nonce, - gEncryptionKey, - 256); - } - snprintf(rxMessage[3], PAYLOAD_LENGTH + 2, "< %s", dataPacket.data.payload); - #else - snprintf(rxMessage[3], PAYLOAD_LENGTH + 2, "< %s", dataPacket.data.payload); - #endif - } - - #ifdef ENABLE_MESSENGER_UART - UART_printf("SMS<%s\r\n", dencryptedTxMessage); - #endif - - if ( gScreenToDisplay != DISPLAY_MSG ) { - hasNewMessage = 1; - gUpdateStatus = true; - gUpdateDisplay = true; - #ifdef ENABLE_MESSENGER_NOTIFICATION - gPlayMSGRing = true; - #endif - } - else { - gUpdateDisplay = true; - } - } + MSG_HandleReceive(); } - gFSKWriteIndex = 0; - // Transmit a message to the sender that we have received the message - if (dataPacket.data.header == MESSAGE_PACKET || - dataPacket.data.header == ENCRYPTED_MESSAGE_PACKET) - { - // wait so the correspondent radio can properly receive it - SYSTEM_DelayMs(700); - MSG_SendAck(); - } } } @@ -751,6 +694,66 @@ void MSG_SendAck() { MSG_SendPacket(); } +void MSG_HandleReceive(){ + if (dataPacket.data.header == ACK_PACKET) { + #ifdef ENABLE_MESSENGER_DELIVERY_NOTIFICATION + #ifdef ENABLE_MESSENGER_UART + UART_printf("SVC= INVALID_PACKET) { + snprintf(rxMessage[3], PAYLOAD_LENGTH + 2, "ERROR: INVALID PACKET."); + } + else + { + #ifdef ENABLE_ENCRYPTION + if(dataPacket.data.header == ENCRYPTED_MESSAGE_PACKET) + { + CRYPTO_Crypt(dataPacket.data.payload, + PAYLOAD_LENGTH, + dataPacket.data.payload, + &dataPacket.data.nonce, + gEncryptionKey, + 256); + } + snprintf(rxMessage[3], PAYLOAD_LENGTH + 2, "< %s", dataPacket.data.payload); + #else + snprintf(rxMessage[3], PAYLOAD_LENGTH + 2, "< %s", dataPacket.data.payload); + #endif + } + + #ifdef ENABLE_MESSENGER_UART + UART_printf("SMS<%s\r\n", dencryptedTxMessage); + #endif + + if ( gScreenToDisplay != DISPLAY_MSG ) { + hasNewMessage = 1; + gUpdateStatus = true; + gUpdateDisplay = true; + #ifdef ENABLE_MESSENGER_NOTIFICATION + gPlayMSGRing = true; + #endif + } + else { + gUpdateDisplay = true; + } + } + + // Transmit a message to the sender that we have received the message + if (dataPacket.data.header == MESSAGE_PACKET || + dataPacket.data.header == ENCRYPTED_MESSAGE_PACKET) + { + // wait so the correspondent radio can properly receive it + SYSTEM_DelayMs(700); + MSG_SendAck(); + } +} + // --------------------------------------------------------------------------------- void insertCharInMessage(uint8_t key) { diff --git a/app/messenger.h b/app/messenger.h index 4bf99dd92..08e0c1b82 100644 --- a/app/messenger.h +++ b/app/messenger.h @@ -62,6 +62,7 @@ void MSG_SendPacket(); void MSG_FSKSendData(); void MSG_ClearPacketBuffer(); void MSG_SendAck(); +void MSG_HandleReceive(); #endif From 229806da0f99fa187115d7a30de85def60ef5999 Mon Sep 17 00:00:00 2001 From: Nunu Date: Wed, 31 Jan 2024 18:11:44 +0100 Subject: [PATCH 12/12] fix enc key initialization after boot --- app/app.c | 10 ++++++++++ app/messenger.c | 3 +++ helper/crypto.c | 2 ++ helper/crypto.h | 6 +++--- settings.c | 3 +-- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/app/app.c b/app/app.c index fc154a75e..2dfc01bf3 100644 --- a/app/app.c +++ b/app/app.c @@ -65,6 +65,9 @@ #ifdef ENABLE_MESSENGER #include "app/messenger.h" #endif +#ifdef ENABLE_ENCRYPTION + #include "helper/crypto.h" +#endif #ifdef ENABLE_MESSENGER_NOTIFICATION bool gPlayMSGRing = false; @@ -1309,6 +1312,13 @@ void APP_TimeSlice500ms(void) } else if (hasNewMessage == 2) { hasNewMessage = 1; } + } + #endif + + #ifdef ENABLE_ENCRYPTION + if(gRecalculateEncKey){ + CRYPTO_Generate256BitKey(gEeprom.ENC_KEY, gEncryptionKey, sizeof(gEeprom.ENC_KEY)); + gRecalculateEncKey = false; } #endif diff --git a/app/messenger.c b/app/messenger.c index 69bdbae27..b17416c13 100644 --- a/app/messenger.c +++ b/app/messenger.c @@ -682,6 +682,9 @@ void MSG_Init() { prevKey = 0; prevLetter = 0; cIndex = 0; + #ifdef ENABLE_ENCRYPTION + gRecalculateEncKey = true; + #endif } void MSG_SendAck() { diff --git a/helper/crypto.c b/helper/crypto.c index ddf905798..3eeea30fa 100644 --- a/helper/crypto.c +++ b/helper/crypto.c @@ -19,6 +19,8 @@ #include "driver/bk4819.h" #include "driver/systick.h" +bool gRecalculateEncKey; + u_int8_t gEncryptionKey[32]; // salt used for hashing encryption key from eeprom used for sending packets diff --git a/helper/crypto.h b/helper/crypto.h index 55f8d6c82..c7de28174 100644 --- a/helper/crypto.h +++ b/helper/crypto.h @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#include #include - -extern uint8_t gEncryptionKey[32]; +extern bool gRecalculateEncKey; +extern uint8_t gEncryptionKey[32]; static const uint8_t encryptionSalt[4][8]; static const uint8_t displaySalt[32]; diff --git a/settings.c b/settings.c index 01470c13c..6ffca7354 100644 --- a/settings.c +++ b/settings.c @@ -277,8 +277,7 @@ void SETTINGS_SaveEncryptionKey() { EEPROM_WriteBuffer(0x0F30, gEeprom.ENC_KEY, true); EEPROM_WriteBuffer(0x0F38, gEeprom.ENC_KEY + 8, true); - - CRYPTO_Generate256BitKey(gEeprom.ENC_KEY, gEncryptionKey, sizeof(gEeprom.ENC_KEY)); + gRecalculateEncKey = true; } #endif