From c0c6ddd40954f9d5439e48b2b8d0118111812fb6 Mon Sep 17 00:00:00 2001 From: Michael du Breuil Date: Mon, 22 Jan 2024 10:45:27 -0700 Subject: [PATCH 1/3] AP_Periph: fix can mirroring --- Tools/AP_Periph/can.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/AP_Periph/can.cpp b/Tools/AP_Periph/can.cpp index 94aba74057f49..80ae6fbc4fc9c 100644 --- a/Tools/AP_Periph/can.cpp +++ b/Tools/AP_Periph/can.cpp @@ -1292,7 +1292,7 @@ void AP_Periph_FW::processRx(void) if (other_instance.mirror_queue == nullptr) { // we aren't mirroring here, or failed on memory continue; } - if (other_instance.index == ins.index) { // don't self add + if (other_instance.index == instance.index) { // don't self add continue; } other_instance.mirror_queue->push(rxmsg); From 52f787b635eb4812dae4879f35fc3c5a26a86df8 Mon Sep 17 00:00:00 2001 From: Michael du Breuil Date: Fri, 29 Mar 2024 09:42:32 -0700 Subject: [PATCH 2/3] AP_HAL_ChibiOS: add sw-boom-f407 and supporting scripts --- .../hwdef/sw-boom-f407/defaults.parm | 22 ++++ .../hwdef/sw-boom-f407/hwdef-bl.dat | 39 ++++++ .../hwdef/sw-boom-f407/hwdef.dat | 119 ++++++++++++++++++ .../hwdef/sw-boom-f407/scripts/params.lua | 28 +++++ 4 files changed, 208 insertions(+) create mode 100644 libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/defaults.parm create mode 100644 libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/hwdef-bl.dat create mode 100644 libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/hwdef.dat create mode 100644 libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/scripts/params.lua diff --git a/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/defaults.parm b/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/defaults.parm new file mode 100644 index 0000000000000..fcf2d3b163c47 --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/defaults.parm @@ -0,0 +1,22 @@ +BATT_CAPACITY 6000 +BATT_VOLT_PIN 2 +CAN_MIRROR_PORTS 3 +ESC_NUM_POLES 42 +ESC_NUM_POLES2 42 +ESC_PWM_TYPE 1 +OUT1_MAX 2000 +OUT1_MIN 1000 +OUT2_MAX 2000 +OUT2_MIN 1000 +RELAY1_DEFAULT 1 +RELAY2_DEFAULT 0 +SCR_ENABLE 1 +TEMP1_TYPE 5 +TEMP1_PIN 14 +TEMP1_SRC 3 +TEMP1_SRC_ID 1 +TEMP1_A0 -49.504657745 +TEMP1_A1 75.849555969 +TEMP1_A2 -22.5933513 +TEMP1_A3 -0.18553680181 +TEMP1_A4 1.5855249629 diff --git a/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/hwdef-bl.dat b/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/hwdef-bl.dat new file mode 100644 index 0000000000000..59c858c831a72 --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/hwdef-bl.dat @@ -0,0 +1,39 @@ +# MCU class and specific type +MCU STM32F4xx STM32F407xx + +FLASH_RESERVE_START_KB 0 +FLASH_BOOTLOADER_LOAD_KB 64 +FLASH_SIZE_KB 512 + +# board ID for firmware load +APJ_BOARD_ID 6001 + +env AP_PERIPH 1 + +define CAN_APP_NODE_NAME "sw-boom-f407-bl" + +# crystal frequency +OSCILLATOR_HZ 8000000 + +# activity led +PC8 LED_BOOTLOADER OUTPUT LOW +define HAL_LED_ON 1 + +PA13 JTMS-SWDIO SWD +PA14 JTCK-SWCLK SWD + +PD0 CAN1_RX CAN1 +PD1 CAN1_TX CAN1 +PD5 GPIO_CAN1_SILENT OUTPUT PUSHPULL SPEED_LOW LOW + +# can2 is the tail boom section, disable it +#PB5 CAN2_RX CAN2 +#PB6 CAN2_TX CAN2 +PC14 GPIO_CAN2_SILENT OUTPUT PUSHPULL SPEED_LOW HIGH + +# setup important outputs +PA5 SAGETECH_MAINT OUTPUT GPIO(0) HIGH # force sagetech to maintenance mode +PD15 CHARGER_EN OUTPUT GPIO(3) LOW # disable the charger +PB10 BAT_HEATER OUTPUT PUSHPULL SPEED_LOW LOW # disable the battery heater + +define HAL_USE_SERIAL FALSE diff --git a/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/hwdef.dat b/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/hwdef.dat new file mode 100644 index 0000000000000..544340b49f7b9 --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/hwdef.dat @@ -0,0 +1,119 @@ +# MCU class and specific type +MCU STM32F4xx STM32F407xx + +FLASH_RESERVE_START_KB 64 +FLASH_SIZE_KB 512 + +define HAL_STORAGE_SIZE 15360 +STORAGE_FLASH_PAGE 2 + +# board ID for firmware load +APJ_BOARD_ID 6001 + +env AP_PERIPH 1 + +define STM32_ST_USE_TIMER 5 + +define CAN_APP_NODE_NAME "sw-boom-f407" + +# crystal frequency +OSCILLATOR_HZ 8000000 + +# activity led +PC8 LED OUTPUT LOW +define HAL_LED_ON 1 + +# JTAG +PA13 JTMS-SWDIO SWD +PA14 JTCK-SWCLK SWD + +PD0 CAN1_RX CAN1 +PD1 CAN1_TX CAN1 +PD2 GPIO_CAN1_SILENT OUTPUT PUSHPULL SPEED_LOW LOW + +PB5 CAN2_RX CAN2 +PB6 CAN2_TX CAN2 +PB7 GPIO_CAN2_SILENT OUTPUT PUSHPULL SPEED_LOW LOW + +# we want to be able to mirror CAN onto both buses +define HAL_PERIPH_CAN_MIRROR 1 + +# UARTs +# | nav light | esc front | esc rear | transponder | +SERIAL_ORDER USART6 USART2 USART3 UART4 + +# USART6 nav light +PC6 USART6_TX USART6 SPEED_HIGH DMA + +# USART2 front esc +PD6 USART2_RX USART2 SPEED_HIGH DMA + +# USART3 rear esc +PD9 USART3_RX USART3 SPEED_HIGH DMA + +# USART4 transponder +PA0 UART4_TX UART4 SPEED_HIGH DMA +PA1 UART4_RX UART4 SPEED_HIGH DMA + +# APD telem +define HAL_PERIPH_ENABLE_ESC_APD 1 +define APD_ESC_INSTANCES 2 +define APD_ESC_SERIAL_0 1 +define APD_ESC_SERIAL_1 2 + +# pwm +define HAL_PERIPH_ENABLE_RC_OUT +PE9 TIM1_CH1 TIM1 PWM(1) GPIO(51) # esc front +PE11 TIM1_CH2 TIM1 PWM(2) GPIO(52) # esc rear +PB11 TIM2_CH4 TIM2 PWM(4) GPIO(54) # aux 3 + +# gpio +PA5 SAGETECH_MAINT OUTPUT GPIO(0) LOW +PB3 POWER_GOOD2 INPUT GPIO(1) # 7.4v secondary +PD7 POWER_GOOD1 INPUT GPIO(2) # 28v primary +PD15 CHARGER_EN OUTPUT GPIO(3) low # charger +PE4 ID_PIN INPUT GPIO(4) # high on left, low on right +PB10 HEAT_PIN OUTPUT GPIO(5) LOW # heater control, low is heater off, high is heater on +PB12 AUX3 OUTPUT GPIO(6) # aux 3 + +define HAL_PERIPH_ENABLE_RELAY 1 +define AP_RELAY_ENABLED 1 +define RELAY1_PIN_DEFAULT 3 +define RELAY2_PIN_DEFAULT 5 + + +# battery +define HAL_PERIPH_ENABLE_BATTERY +define HAL_PERIPH_BATTERY_SKIP_NAME +define HAL_USE_ADC TRUE +define STM32_ADC_USE_ADC1 TRUE +define AP_BATT_MONITOR_MAX_INSTANCES 4 +define HAL_BATT_MONITOR_DEFAULT 4 + +# vtol voltage +PA2 BATT_VOLTAGE_SENS ADC1 SCALE(1) # pin 2 +# vtol current +PA3 BATT_CURRENT_SENS ADC1 SCALE(1) # pin 3 +# servo voltage +PA4 SERVO_VOLTAGE_SENS ADC1 SCALE(1) # pin 4 +# 5V voltage +PA6 SUPPLY_VOLTAGE_SENS ADC1 SCALE(1) # pin 6 +# 28V voltage +PB1 BATT_28V_SENS ADC1 SCALE(1) # pin 9 +# 5v backup voltage +PC0 BATT_5V_SEC_SENS ADC1 SCALE(1) # pin 10 +# 5v primary +PC2 BATT_5V_PRIM_SENS ADC1 SCALE(1) # pin 12 +# battery temperature +PC4 BATT_TEMP_SENS ADC1 SCALE(1) # pin 14 + +# temperature +define AP_TEMPERATURE_SENSOR_ENABLED 1 +define AP_TEMPERATURE_SENSOR_MAX_INSTANCES 1 + +# Scripting +define AP_SCRIPTING_ENABLED 1 +define AP_FILESYSTEM_ROMFS_ENABLED 1 + +# don't build on firmware.ardupilot.org +AUTOBUILD_TARGETS None diff --git a/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/scripts/params.lua b/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/scripts/params.lua new file mode 100644 index 0000000000000..f037fffdf1110 --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/sw-boom-f407/scripts/params.lua @@ -0,0 +1,28 @@ +-- load default parameters depending upon if the board is a left or a right + +defaults = {} + +forced = {{"BATT_SERIAL_NUM", 2, 3}, + {"CAN_NODE", 109, 110}, + {"ESC_NUMBER", 2, 0}, + {"ESC_NUMBER2", 1, 3}, + {"RELAY1_FUNCTION", 17, 18}, + {"RELAY2_FUNCTION", 19, 20}, + {"OUT1_FUNCTION", 35, 33}, + {"OUT2_FUNCTION", 34, 36}} + +local index +if gpio:read (4) then -- id pin is pin 4, high if it's a left + index = 2 +else + index = 3 +end + +function set_table(fn, table) + for _,values in ipairs (table) do + assert(fn(param, values[1], values[index]), "not set the parameter: " .. values[index]) + end +end + +set_table(param.set_default, defaults) +set_table(param.set_and_save, forced) From 0b4f08d1237b15121de885e087f56492adecadb6 Mon Sep 17 00:00:00 2001 From: Michael du Breuil Date: Fri, 29 Mar 2024 12:59:11 -0700 Subject: [PATCH 3/3] Tools: add sw-boom-f407 bootloader --- Tools/bootloaders/sw-boom-f407_bl.bin | Bin 0 -> 18440 bytes Tools/bootloaders/sw-boom-f407_bl.hex | 1155 +++++++++++++++++++++++++ 2 files changed, 1155 insertions(+) create mode 100755 Tools/bootloaders/sw-boom-f407_bl.bin create mode 100644 Tools/bootloaders/sw-boom-f407_bl.hex diff --git a/Tools/bootloaders/sw-boom-f407_bl.bin b/Tools/bootloaders/sw-boom-f407_bl.bin new file mode 100755 index 0000000000000000000000000000000000000000..1422c7473360a56dad078388fe2d08316d686d04 GIT binary patch literal 18440 zcmdtKdstM}{y4nW-gDVA3@`{P45*tK)R93OMUB!^!!T?REG+GOP5XY&2GjOv=BRZJ zY3U$X@zI+8{MzgBUTZGY~To!fhjQKEypxetlRy^SAly>;65B?TDEI z;SLB7LwFIwzqk4Ke47a|N|<-_$lRa&FMams{ojvs{kT*AAGW`~@Bbgt&GCpq*ZooL zNJP?bVBNbn7P@e=wCf#2El7~a;6(B}|tzdCd6m)!_6ytk+1NpH`ZCrQnTZV_s# z@Az#^iHOiQKkK!(U!6PBN5#5(lB!8BTKr*%7R!fA#Jj8$=A{6P0mLT%rVTBghOz!KoHT#*ZEx7=i;E;hYIQ+>0Eu=fVg9J! zl+ofFEeOsvGC@FyVSYmG2tyjmstW)gQ0^WH3vNSfJDl_Ht_xE;#FD8$>9>6#>3pYz z{ankB`fV*zxdvL~V1%pE8|EG_o-4+m)R(SCG!IDnAkL1Mu$Evkpq94-ESNXeZz zI;Hpp`z#;MCcl%5CyO#wYtQyejYzy@a2jXt)<1~ETL+m2lrf3J;{5)?BQy(j63NeM zNQ2(Aj~2~CBu{4ib}+61i4F;gy9Ozdmz3P;W+a{+Ea~0gqQ%DkP+%H|GR_AS9G>J4 zsJPtj>X}~z;5Yj@yTS{t9>kN*1}HI4%1b?H|E3Lz< z`;pObZ^{FP6)6wgegBes?|xv(ilq;%d$&YvH(Aq9Nz85MJJ5^@*opmIC7fV=!D(2- zHJA__TNZ*WNB0@!P&Q3bqA;)9iJomt)uAxXPUKa^$%3PMLFtx8q{CqfCG+k^S3xqY zDJilpl&&`_I3%_X(Z%#*~YZVlrQIMU5y^75v8beeW`DkwYKJ z1>Iv4C(JWdsb5owdMVyiCC!)~+kMHXJ{%j&(2eKlFIVL2`8)V*jtVl=Rlilx^9|KU z9!#{nCE^<7v0F zVy>k3FJ)wH^I)Cs^`|9idPy&WSeISWYlE1bIfIK0K93ba4MJkZ&?Lux={f74)|uAD zGt*bDibk!S^Uqf)Vu`!(^slN|j4?VzMVf6+nRs0y|MR;?yfGkrr$ zp*n(5N?bm0z^?ili_Z?9k=juXx3*qvVYzUi{A%_KHJ^U5lfd?JHev~G$K5vm_VFc; z)tg}@4-L@V;v*>Iiw@fHrj%r(Htv*?*k=WsK<%Ypr%$E|m!(DSJQ3wlHCViVcuPud z5YcEabtngDMN*Us6s{SwDoi*8ar|N9(|l8c*<((x=L zejk2W%DU?vDNBjOkHX~*(bU;6<_epm>GNTTXW?vUH>)#{19y?&R`1akYl{p#(3FKW z63^b;{MG8L268%$G7FUW&``@2y^StJqQOhnujdfMLO(*|pR7l3D>)tD;U5w*&-0r$ zQI=Hyx7)BK*^kBgAr&Wwz8Rw7ynpPvES=tRBrJBT`o{c`3hT4S3{>{OZMS~ADZBX~ zP(Fie?u{)R;S%a#1}5`=HHgf;eswSj$)UduJtIxBK^hx5b#OAG#aD-r`JevyET(mD zahj_YMmpFxW<444V&EAmLr?a0yL3MA?KZQ;;?uWci^-?7eC{V4xq99c#h(gPZ+lr{ z-e(aWjl4qvtEI(Xb^AA)W^CAPZ}Rh-rgO-+Tl#9jRyz`3apM_^Ox(9^ZJ+=3KsslJ zl|47~%1DYHJ`iY>eq6ATR|aWKN$0Z=o}m2WK4D(#`hecgb#W+tF|6p0up;;~&g7;$ zNG>P5QAljYK)b&mcv?COH@#~>!C9NF>yW4l6AZKsG_?OsIuCn7>fe>JCT_9gRyjn= zq%_m9*Up^1R)ek4y1rqT@P~mXy6=Ym>0ze%4EJ#RI)Svxbgbh^KV=uC`A|B)3yDVt zD)KewppJ!dglC}C#~=-LNS+$siZW&bBp(bANcIjO@wuVj6(?6P&2s4A;2Cam;3$mR zhO}Y2EG(RrzSD1!u2^xOyY!^gZaoQkIdox24w;6b6^mz3B27I8sdocFWj1KTRG%`~ ziKjcr=-&)VJTh+buvpv;G^U;X+fQi2<)6}5x(zAj9B&G1yV^8km)-2u zb4@?rw?X~$F0J%)V8eYs{{>nluMGS=X~Q7oKZIT|tMw@VzOY_^xq4@$?2)eM?`|M) zZnt0IZtb1?HcAJG^#HB@47XlT71e2hvsE1Z0eSbsIY%J#DA0hC+z~?Gzxe#~->q1& z;?@IDhk?ht3Xpdnlv_O@!7Z{B8--f?)_OI_8&to7V~?T?mQ&VSTP7BlJvy<_;4(c* zuOrm{#0a%N0n{E%B=r6S(EIW8PDtM^_{6BOf}8*tZ#PZ>yxcT^GcE;^i;{0kydNmp z`ow!*Up)pS0iWOU0G_kS@_B1gk@{17xDt3_GDoK)ao^yo)s=RDh(7MmT)oYXy@!`8 zi!&cExM;7oxO26EPvaT`wQoAk5ZKAu#voWL@OZQW*%ss;s9y}R9_nuN7;Z!2OM{eY z)!O7@b47}fT!@WWEFA#)Rx_q}%sf;xrf@9qW%r#}d~0}gaY}hY!>B?m`i8OC7*@ay z`8EtUe|>$pr<)2V(u%$@F8x5Is4Gt9X>qy4G{l=M6*S<8;Fruv=u4j(G0#Do(A<6o zF$7M6b3$*X{zPq$@6MUh)`6a=oL^HP^VSPLZQ3q}f`b($mnHK{$fT`#Q<`awsaekh z4q}#aJAXpk@x<8RI7$t4f2WkTV5c;$9*b}E@0Zf7$YO(=%>qBzG^_$1o$q&*U~y4+ zjp3izgtx#d+`n0cc4QSf{ECuiBvk)dP_I22MDa=9Y|g^{VPM-p+-o}}vsDf~ z5`I6ZiZ^>pM3pw~Fx?e{?*y(s1@8Hre(hnpCfP*QXoHx#tN1MNNwiS0hvnu+_yZOn z8NS7Z#rSYZQORwI!YRX%z73nFozwGJREH@ph9fXjK%cRgKCC}t*-&shvLtzF6J=Vz z7K=Rtac_gXv>qD)_u@^QmAAra(hZOqe^*Q-8(a5XiNHBssK(9}M@GvVwrr?rz~Y4g zG)WB@){gU}AV`r7^d4${F7U;V%*Frd*QLhJ`{ z_FNuH{KJsucFk>8H_9*z+0~VHri~IyhAe`@fwSM~bKh#=yU)3RmnK1`8gwb z)x6zOhBdnZnV6LokYbE-=nF4~5s>#sGN+mHQsgGCt1TsEWPKxL;`L>E4>Hw&PW1Ub zrx)Su{s741h~_BHXBgFwQ_++GzpH?9&|Hn3^3f7b9SFDzrglhq6K+f5o{}{B>)7S^u5qiB!C&&rq1`ev|J~2DTUOFtTj)yrUwv}uaVY!DkJy$gQYB`?0kTE{ zM=S?AMfxt_zP9d%N6Dc>vWa6s7B<5@2o9UZQAReB?iyY;jy4)2>F=yK=!)b#kYk}` zeI)l55Tx z?u10^StH(s#lm5{FN#wv+94gqDHi8KI*L;)&W7|goMQ2YVKqzD>svw|#b%I9xvYlD zZKEty8)j*c>X9jhQybCKWVQboT%U$&KY3j$N1Chbd%eJi*|UMe+b$ty&L!rEi^=#Q5QZ_*Ik+bg zEFB(XX5t$!2UtTg+?Hd3>*4zJH*le+qdoQjT<4n^BdST@OmNPy_{5+-V}1F@mMg8; zw66RQX?V{64oTaukgNwtz7O=ITo1_#fMgE$j}b^tfxY9}c^(6JuK;M}kbM}|K60A3 z4Sm?WEKO~U;-YdWe$w84Y`w1>S(?0?Co8(tu-EhR8NYfq!|KCoKDyh?q^`ihv}^k- z3`O_1GeC4Fa(BpFUqHng{*ZN2lElP+3@7Vj*3F^GP5E%9 zu&Pzn^)Vtdi52EaKLzlO-=;*dmOb>-uehBFdw!&E%jREq{b_8{kIeLK_^Ze+Yhai4 zk-090Q!>_9AL(;%4!}OItNuUja}>LJ*yr_bJz#gvxa+a|UikWbJ{7QfG`DFTyX~>Q z1PRYsY-3Ee9;Co?vTTW>OjmU-Kv(_01gtG=Wz$a~kl*BN&=pTWXh&TY*uYiW(|ijg zMKRus-&SOdmGIInoysz1;-%yl@J?^5hihg*${*9DQmfH+$afLdHaizn6iUnX~=ciP_iHPM>!} zq_!YZJI_ZukMyeye{<5#^wQ_u%dJo6g-c#{|^zd4n9Pl4o#0 z2ZHy4rA`h#DjyVHuut)S3$hI3MH4gHqa#gj&D|ayhxLz*jH8EflF#YqB)~ZPVH{r0 zR*w+9(VCGinsT=8e zR<5#JxxL=i0-7j?K9lj>EC&m{5z6uCI3aH5gtPfk6k*Km5PI@Z)b_kaMd!CqN;G-jna=RE>(R z4^?R5J9dq)Okf43ONr%>YH*pr%pB+F2~6Q~pyj8snNvh;8&U+n@lfWt4#T$q1Xixv zdp|&)16a-B*#;|@1-a=m>yQ9n>pe+uI>^eWjjSB+`l2*A6!YM>O&jkceT2kp3M?SR@#Lg8w(%;$*Nk zgH!|oenH!D6~vKzpL@YB3Fujm4MoaHzTfw2`h@hko=8|Bk4|WjSXUBgc`kqKMrP{j zR_nyAU_H%uz9sw->(0L+WMBq6RAMJ1iOw0FFm zs8Ib;nJ?-1I3a$ZYH*C`E=l$(yL96rq>cCfLvojLBBlBg;<$~UOI4-HF2(3S3umMq zrMJUxb?H}<`;L4OD?f)Abvef5b_>dB4rP~Pw9@e**q)eKaU2fnbibDrUHK4JdU%o;qnedBaV^Rq(4uFMI5>#emjhJBD*>Q}))(L|C3*lui}3FD z)pBUz@C38A4L{qy8sxpu$>9Sa@hrA4&LzAafqceztP#sT!RZNT9}l)jV(DkdT{lwv zmI^z+g?ANz{0SWY1VD*Q3XZNI_xl&vGeQ$Y*h|u1$HA^x6GcV*sUA0Gya`-s&lXw{ ztWvq5T-n7XK2e|gaI1RSg$+ki)Kkw3a01TBu>M54uW}(BOjgsc>$8)EyM-icl-7cz>zEq8GoGt0`cv*i#czXkpSMW6dF&<+-Y zPOLf8k$BS?snCs0KQCAGJ-%4cSM~cd(xP2krNv~jhTu_vML@w7r5Rju z=%vUmr-80R@QJ1@@J%VsEO{>+?0eR}!>ctVm==%sgnI_*aN5Gtjg|(=Omls$L<0~X z*9GO-@AkRZgwCGsIvp1mr0J5*Z#AcSKB8alq8UvPYeCn2=nn(cq9&}oYYEtMJz=TO z(^tCr18-bV&L%C}4JR7!Nn0>b)vF6DdfyB8_P%KUs~^v~)EIC1tQF^+XjGd&Y6Y*w z+A;3ku5&KTeh^?dFYvWn!S3t+hnph2B@XoB4G*qzE){4I(?{%TALKz#e`*lV?eVjm zs|5phK*;K`J8PVYqAPxk51C@-*Ob!1DhhSkM3AOq{u5*!OTCkH(csN&7 z;Dog}o3?cMtu2FqzxAGRT%L0bS1X)VD>%)CS^=j&%b)DAQE+ybqjWhW3@>xm3Vvk_ z)WOcKjno=REe5ZN99kTyKTD6)Pmk2wNj(**FC2z5vGAPqInp=KLaK9L0qEXv%3L-% zbigZtKEOHAly!bpP^Zoj+-jFk)rCjr2p6P!tcSZvVuSYtV-u0h7JHx+@*kv$RD7D( zCc14T{|<&82}q1bRiGF8r6$b&iTolhAB}YfqH$b1#K&-z#6qiMP+ujbM^m~g$w*QO znz$;-q|ZseiB|+?A|jb6f*DHib*{2OI0PqLQ;prHJG3Su`>Yxb&wdiC~z)BYoM6N2y8<- zoN_(1cX@$cd6VHRiymt_@uOXq3QwTE$~&0pC<7>!5_RQ|p7!vc)N$vps&p6p9q5nG z*q_f;pXHqQNExp8_-PLlJ}_-9o=IonAdA2ANAJG~ z+ZWUa+y4;HrTe6YC_Pg4RW8!cM3Yp(Dq7idx@Z@Q9pf@3w&~XXQBr+ws;(_}o!3q0bc8eJ0xF$AC ziO6Pe%dCsY2U9zma&_EjZUP6IgIM1m!=;x~oTk}azMz4~M$2V6^rSq8%jD7_cU~q^ zQBwtx-K>)y16+;;|D|0->kRiARz~77!%8E`mqlSBTxoBFLty0?|DgubhfYrfi}9EJ zbb1oRpF%tu;t%^tyF9q5RS*-7?E?G~TW5p@0Zpu~e@gOMu|)y29dx7a3U@`xe@P}* z+gu=-(BCC=0DN-pNe{jc`uDxQXj_*rdc$6oqqr|~CJH8zq7!+NBC{p(%baNPA4(sG z8KZ5#0bd0YpK@OTZc#Cy=&QW@eNGc(G{klxaKoW|nR-nQtsMM9NxtnKLHuT%GRzfpOuwN%3CRogaT_iZXA1v;0=HWfU9nykMOj8`?vyU$g zA`G&mpl^r)7^i_(jIm*HWz$Go7Ua;8GQNrNV92+Q!^NOpVf@Gm{e zN?csG3f?_GZo|e8j%- zvJOpY^6t^?1uNvt2>r3P?6oWXAN06gAQP^yv|sh_wP!`_Kf#DDmcMdzb8Z>Yu8QF< z@&%`Qws9q$=Qcs>@-dwzRgU)-?hUZcFAQNu3*=Il>_&*5D{4F5&o9Xs~DWBL3wz>i9LH_zK^$9^KkC`7dy%C-NMe+!r6{XO>~;4UHc z&!9WTao;dZ*M+#;dlIF%6V0|M1FBH^fHo*M?&!q0U_cwX$p$GM4Ye~Jvm6%!?oP}y zrrhpy3OCvin&NJxLC$INE{NDSdclet)oXVqzhX!JoR%c8<;tP&AwYXwb82SE=Z2|_Xi76QDQ zfqu}oO%EXnLNWvvg4Mjk8_yC=O#?v-AqD~&BNjqL7S2=eP~V{7#<%%8sD0o|yDG0g z6J%Ad1X(a;18f7Tt7h<9PS3-6pEM@Jtz9NFvusmouFL<8^JXHm=ECS^54#fHo8K+MMQcevL>WB3}dTWPS($m*>m*Hyep` zo}aI8({?emaa|Mib^J(yJc>~xO2%Lb_|8Oj?;64cC=U-?e z@Le2cnpytsNFAC)>fVjuC+eq5<0|WyI`JN&Hz5lWYu%iQ6_kk-D=CMR&|ir zIo=yq!YW~nN@7*I=1EEd&Nv)u4jXrT<0Lkj;n0g=b_ce)8|Bas!*b~3VVvV`WUH{% z{NOUDaYt%-rh^tI(96VI=|bQ!iR*GWCqD(C{ACDF^aoH-M+3$*%+LCpOGLN!cJ4MV z8D8DVp+5~*0+&1Pi_Yi{qiHw$aou6i%P3<^kcpcxuw_sO4?K^7FE4!uysK&bv)uxo zsDl8-*5NYesB)Y`i4&+lgO#mBv}x^~^G2l(xPwKVlone77JG%n9M~@D(PzL3?~Yhu zUKuj&z_X6nr#3zzVhzBhZSrppAmfLDZ=6s3cbr7&@$7dS@r)CJHK6IQ3rL>PpnF&W zCkl|OhC@@ss=8&orw>g~*S*Tm^sdyv8D4j=?3uC4JjeRemR)sLUgre%vs{eGhA-QIM<@{S2_VJlpD{mTEI_%W<&U zcLxYxdQ;L{~d^T``7*3Y6!m}P!B{_KxnJz*$%MBa$|vd66nVR^#3)mUz%@SGJc_b zVeU@Q^a=cAEeVme6h_vP1Z!CdYgrUo%M_4;U^RavcElLMcad!+YEW2R1$iqCg1wA# z!fTxonne6_Vy;hO-6^*x0k(3%TCZs)koh|((@TcsT{Qi){ZH^a{w%$6yFC^>ZaaqP zm8k+&S_d`ownl$GP|axsxJO=h)p($RV#)UU zSng|S!LB5(j!60--=QuGLXX^}#8oCblrRFaI1hA9!-3+(stpJ%V(T7d% z0N(ERFEX-V!3 zsXGKM=LXoU_*UlGW#iKa=$?ye<*y^^@|e9$-6zl{GhoZI_`pZMymb8OU^?}3FrA(> zfP+eaVIuTO$Vat`x%E_J)o=PJQ)MJ|)Tc0Q0>2KKXq)6c*`u0-CZWt& zZVTt`4pod2Pt3E4Jr$abXbKX4sQ^ou&s2WIZWDj3IN76ErmE4yD~ZjtvWEB`lyy@a zC7qRpg`HXmobY8i$md`OVoW`nO0KXIUINtI=Tp|98j8D5SjaJlSgr~5Hza;sF?nT4 zb1v8=2^XfqYHkXIeRjpIr8gH1>o_oWOkE zQ>A;Oi$Ngo0G(_CYa5GR>(bE^1}caD-a(}|c@c0Kb5#|U!R}ir|OWU+=tESUzH0|^JPgqxi{YhZN{9t zv3>H&$pEVk!OIh%9t2(wz}p*WEZk)$<6xjHVt|Y=;8WMdTgHAh@aPfHcxj3jAE6WT z!Vg6?O?7zH#-o3v>gF_uA3fDmMd2A`J&)1hhkSvR8;@?PwO@)rG0S&ELs@13)JJ(m zU6?15LhNfpp_MXSr>#-c#nf2F>1r$+-;{2tCl7FRl;wcb+42KRNi)= z5_C=S-esqh>pm!GVJG$#MCPTz_6M>{9Tnd4QXu^3hds7Yja}y^*u;J}Kt<=}+r&XP zRcqP!t_Ee^=^G~kEgRn&M*|EqxSK|H_EoU<=q^Ur`{cmC z&!-H)U937>J*N`5_xev@{|*IN$~>S6DnN3^c^PoO6Y`R|PeATE-A`;5%|Tl{&2{*j zwq$OkZ$8^N9ZvEm{ozNOwp`3R*>hr4S==&f+S6#PDbGFyob)bK)5%uWU4;w+2e%q&H zaeJCIn;S2nX#;+Zff+Y#T(SdqX>`Yesqye4vuA&6t-Y>o40xmw1h89cegVlrgX)0( zY0*CTjX_VrZ!FpaZxG3QW5R3Kh;e8el*XgSe*haorE*@;DkE4!ik1o4mGI?B)G7v2 z+%Krz8u1pCy{jvZEou|ed)rGj3XM*icac9Q4YHbfc6beR3Q}5u*i*DTYrOcUO0cm) z?}!}&(F00&f8VYj@#n-9FBKAd(Xu385aec}4lD{I4G0_ig5ol+s@T{=g9zMH7pm{s5=NJEHUF-FAjE5QV(8N4STa-S9CDvzYj(VcD zJK>Enyb6@FD@*0jmohSS2f#8rBavUi_kipM=i93+ZWEY?k_AdI@C$itq#kPJ2SfXg zo53Dr_2`Pf7K+mz2MI6UXW=wOpd*W!{X~xaRz@IWkbGAEYfd%r7CF==_XkM7owE?5 zfcIaQgk3@%_~N7QR$K+7jw#lA(u7tp3q|KMKJ*nYhyE;MkN}CTc`&pjGIx$gJzqVK zDa0l;(d1grBXJD8%QU%&O%wc`-d*z%y9j(Qkug2%-UU0=awL8TH~5h-75TPgI06f4 zheSPaG|I#PPh&vmuM`e~Zz4}h%A%Zkk|WCwzqTw*QJ$2MbyCQalCvlyE$Oll{KjM{ zpj@AI5a$b=2;2A=em#_4J_U)@VI)2nR;0cHp7w{*romg6o`80mqK$YoFs%9bQLz1j4LhkgmTLoVj2`Fm z+RPN^79K`2V!n`1E`2RI33l+Vuy!&MZx53%d{mt3+#_jb7=LkiGB=Cs4rp&6V@i=R z_Z|g%cVvB%hj_%1m>rHUO5_$w`pqxcRsKxyN?VDQ0kCq?>vtX%9EPkEvp0)72(JK% zZdxZB;bjUmj{f_Z=8Doo|o+3 zwIw)63k^uZ3%$|xfUHt*Svuxsz%P<@J4nq7ka%XGRZ6qHF3_p)omp#=;{rfIH0qC` zl)!QZEXYJ^KLYkHB)$*yE}{BD2R)tG{G$86%84wkJ|rF(Sm`{_rO*`RZ{cFkQm{L} z3?O5)FXO)htc1YT3y5E4l)>oe4vgy3XmY$oBbsH`uqQCm)|cc+H^BVp5FhQ)a~$Hw zk(c0*oVy&b;W`JDMQ1yhd^$BbB_C|KCp#ES?hL6XZvlu+70xmO41$J*5cxiUDmo`z zq6g2DGmhp`@K#h)oLasfUcQU6y4V0V46j#Jw1lUE)iajx2Eo|tE(6S=$4Ns>GiG}OqXaxd^eg6E1-ec8MBAssmj>nFt#QloMLni-{3&#) zF%P~|B6jk`(nM!ouRA*tPUi|}^D^KC#?-_2c>Unx0B!}ISEe4xRPfS$UsS) z-M=+?TG3PX|7x8EFI^L%>`q_SZE~ns?lE=oa_D!mts76KvqraOh*+^AdE$JV0ZPU; z*iBBu#6zfpH!~$q%ArJ= zhIdRIK4<}bEzozGjM(-7X>TeuL3>kaOtr-wZ9OF+J6zO9s{VtHq zeFQiHD#k?K%#*V*4|clT+>i=8-8GC&F)r|ySq6QC8Zuxh2_J{=1Ylnnk7}N(5Qz;E zsVV7oPX|s4_v%m+j3;AwHU(|C1fU{G#|XtrI0myo&H{0c=a-&@t^1q7Z%}o*hf!Ef z@X8ME7x0SVC=ZC{9v>#}IdWQBuH*pj-N$plukekWFh8LPJhh#i(Z=hVwf70)}_$pbs?0{6^HFXMCB&KFVbjoJCTdrm%oMU`Dq1Vyh=@O@=~!K5dPo7d@DEUnF*<-KU*z z65!mdH}RB%85zYI83p!gX`aL`h>QY0I^=@y5nwE}2fjKuL|(L=l<_{g9%y2iyjPV& z-SAdP>5JCly}-X^@*aiU;cG!%oZo#H+%gKjy0n3Hs+OOB^>aJqi!pp}1g)&db{h7E zhMSt&Ko=KXecedp4^l?zXyDt1X1eIC^q`rPpNN!GHh60tk)$3plQ9T=An(yA@D82m zvBCb6cBJg`NEsR_BXALVqb-gpj49e>k2x1pd@*g5;e+u;&`q|(ODXWNqz{FD*SrwE z&IR8#a66_DG2|QDYXOPACYU{M@k&<#iIH*fGD9h4ya@0`^CU&+8MIk8Lf<^8#dsN- zsNf!}U(9bUiv#R+43O8)r#lqcgm;|oP|Z5sfgG>!-@{w(zseSP6@D7DNbtAg*rJKc z-KL0~6UL@?URy*zg!Zfx@SaA2=*jA00qj+ZS#Z|FDzLsqP|1HLoZ@4gd8Nfpx@@~MuPg@SJOVr8nN&Qf(BQOn%L&>%pqfr& zue^>(y(Dc|1!c<&tKoO~_@dO+39y>K$y6{6qdqrK4dygpF4peD z!v<*YH9SBhZNmy(QR)LV5$|vf@M?G7LSt%zlI#1rYrt|Eb1Vbl#7{CS#On@a5r`pPVR#@0UZvW4 z-7Y1|&xwvV<3HLl*T#c(zF*so|BrV1YvZki@m5|N zPy1`TF`$dw<5cvPuUk@jP^Gw#SX2WoebADJoW3Y=74!q2a6064MKzG~LGGVQ#Rd2} z{C=pre_z2t$SI3zAm@WzR03!t{A~mWDI;?{Vh683v>j8FxEgw{-dA9P9LxwgALQB< ziVGk~KLB+P>??Q?axf$0e2^=H98;9I2I|&8Kghw1kn=$`DACu@$Xf_J0AvV|45}pZy5Qgd(X+H-dSZkT@Ekj zOAdm!J2_R~g00;VKl{OkPYh$ru>;<22IaXs?C|{=$dsCPWqFHT5yXl11`7Hw7 zVB(1kGaqm$hZOJA9IVa)UpQG%W=H=c#Z$;^{<*f68dzY6_LvAR)?uX>iQz>vf(h-vY;R2+;At4np zuaI&GhafaScoTvW%9|nH3jeR=6NuXkh*@SuXaVpRH|Qr3ecc9wULQbEgx&l#tS)sv zfSmWnp9wWJQo;p?gpj#NUo+DP5-zv{G#$n5C# zzeL7Fmp3Ey?7ylbsge26Z|93P`hQ!e9hrmvx4HgL*|lS@)sWo+l!5(hI1{6@3WQiV L8