From b47fe883ffdaa537cdc47e838e06dc50c2461231 Mon Sep 17 00:00:00 2001 From: Razvalyaev Date: Wed, 25 Dec 2024 09:41:14 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A4=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20?= =?UTF-8?q?=D1=81=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA=D0=B0=D0=BC=D0=B8=20?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=B8=D0=BE=D0=B4=D0=B0=D0=BC=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D1=8B=20=D0=B2?= =?UTF-8?q?=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C=20gpio=5Fgeneral?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- diode_tester/Core/MyLibs/general_gpio.c | 128 ++++++++++++++++++ diode_tester/Core/MyLibs/general_gpio.h | 72 ++++++++++ diode_tester/Core/MyLibs/mylibs_include.h | 1 + .../Core/Tester_main/tester_interface_func.c | 89 ++---------- .../Core/Tester_main/tester_interface_func.h | 50 +------ diode_tester/Core/Tester_main/tester_main.c | 16 +-- diode_tester/Core/Tester_main/tester_main.h | 2 +- diode_tester/MDK-ARM/diode_tester.uvoptx | 78 +++++++---- diode_tester/MDK-ARM/diode_tester.uvprojx | 10 ++ docs/mb_adr.xlsx | Bin 15924 -> 15922 bytes 10 files changed, 286 insertions(+), 160 deletions(-) create mode 100644 diode_tester/Core/MyLibs/general_gpio.c create mode 100644 diode_tester/Core/MyLibs/general_gpio.h diff --git a/diode_tester/Core/MyLibs/general_gpio.c b/diode_tester/Core/MyLibs/general_gpio.c new file mode 100644 index 0000000..f5799cd --- /dev/null +++ b/diode_tester/Core/MyLibs/general_gpio.c @@ -0,0 +1,128 @@ +/** + ************************************************************************** + * @file general_gpio.c + * @brief Модуль для инициализации портов. + ************************************************************************** + @verbatim + //-------------------Функции-------------------// + Functions: users + - GPIO_Clock_Enable Инициализация тактирования порта + @endverbatim +***************************************************************************/ +#include "general_gpio.h" + +//------------------------------------------------------------------- +//------------------------GPIO INIT FUNCTIONS------------------------ + +HAL_StatusTypeDef GPIO_Clock_Enable(GPIO_TypeDef *GPIOx) +{ + HAL_StatusTypeDef status = HAL_OK; + // choose port for enable clock + if (GPIOx==GPIOA) + __HAL_RCC_GPIOA_CLK_ENABLE(); + else if (GPIOx==GPIOB) + __HAL_RCC_GPIOB_CLK_ENABLE(); + else if (GPIOx==GPIOC) + __HAL_RCC_GPIOC_CLK_ENABLE(); +#ifdef GPIOD + else if (GPIOx==GPIOD) + __HAL_RCC_GPIOD_CLK_ENABLE(); +#endif +#ifdef GPIOE + else if (GPIOx==GPIOE) + __HAL_RCC_GPIOE_CLK_ENABLE(); +#endif + else + status = HAL_ERROR; + + return status; +} + +//------------------------GPIO INIT FUNCTIONS------------------------ +//------------------------------------------------------------------- + + +//------------------------------------------------------------------- +//------------------------GPIO LED FUNCTIONS------------------------- + +/** + * @brief Включить светодиод + */ +void GPIO_LED_On(GPIO_LEDTypeDef *led) +{ + led->state = LED_IS_ON; + HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, LED_ON); +} +/** + * @brief Выключить светодиод + */ +void GPIO_LED_Off(GPIO_LEDTypeDef *led) +{ + led->state = LED_IS_OFF; + HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, LED_OFF); +} + +/** + * @brief Активировать моргание светодиодом + */ +void GPIO_LED_Blink_Start(GPIO_LEDTypeDef *led, uint32_t period) +{ + led->state = LED_IS_BLINKING; + led->LED_Period = period; +} + +/** + * @brief Моргание светодиодом + */ +void GPIO_LED_Blink_Handle(GPIO_LEDTypeDef *led) +{ + if(led->state == LED_IS_BLINKING) + { + uint32_t tickcurrent = HAL_GetTick(); + if((tickcurrent - led->tickprev) > led->LED_Period) + { + HAL_GPIO_TogglePin(led->LED_Port, led->LED_Pin); + led->tickprev = tickcurrent; + } + } +} +//------------------------GPIO LED FUNCTIONS------------------------- +//------------------------------------------------------------------- + +//------------------------------------------------------------------- +//------------------------GPIO SW FUNCTIONS------------------------- + +/** + * @brief Считать состоянии кнопки запуска + */ +uint8_t GPIO_Read_Swich(GPIO_SwitchTypeDef *sw) +{ + + if(HAL_GPIO_ReadPin(sw->Sw_Port, sw->Sw_Pin) == SW_ON) + { + sw->Sw_PrevState = 1; + + if(sw->tickprev == 0) + sw->tickprev = HAL_GetTick(); + + if((HAL_GetTick() - sw->tickprev) > sw->Sw_FilterDelay) + { + if(HAL_GPIO_ReadPin(sw->Sw_Port, sw->Sw_Pin) == SW_ON) + { + return 1; + } + else + { + sw->tickprev = 0; + return 0; + } + } + } + else + { + sw->Sw_PrevState = 0; + } + return 0; +} +//------------------------GPIO SW FUNCTIONS------------------------- +//------------------------------------------------------------------- \ No newline at end of file diff --git a/diode_tester/Core/MyLibs/general_gpio.h b/diode_tester/Core/MyLibs/general_gpio.h new file mode 100644 index 0000000..e579fea --- /dev/null +++ b/diode_tester/Core/MyLibs/general_gpio.h @@ -0,0 +1,72 @@ +/** + ************************************************************************** + * @file general_gpio.h + * @brief Заголовочный файл для модуля инициализации портов. + *************************************************************************/ +#ifndef __GPIO_GENERAL_H_ +#define __GPIO_GENERAL_H_ + +#include "mylibs_defs.h" + + +#define SPI_Alternate_Mapping(INSTANCE) ((((INSTANCE) == TIM1) || ((INSTANCE) == TIM2))? GPIO_AF1_TIM1: \ + (((INSTANCE) == TIM3) || ((INSTANCE) == TIM4) || ((INSTANCE) == TIM5))? GPIO_AF2_TIM3: \ + (((INSTANCE) == TIM8) || ((INSTANCE) == TIM9) || ((INSTANCE) == TIM10) || ((INSTANCE) == TIM11))? GPIO_AF3_TIM8: \ + (((INSTANCE) == TIM12) || ((INSTANCE) == TIM13) || ((INSTANCE) == TIM14))? GPIO_AF9_TIM12: \ + (0)) + + +#define TIM_Alternate_Mapping(INSTANCE) ((((INSTANCE) == TIM1) || ((INSTANCE) == TIM2))? GPIO_AF1_TIM1: \ + (((INSTANCE) == TIM3) || ((INSTANCE) == TIM4) || ((INSTANCE) == TIM5))? GPIO_AF2_TIM3: \ + (((INSTANCE) == TIM8) || ((INSTANCE) == TIM9) || ((INSTANCE) == TIM10) || ((INSTANCE) == TIM11))? GPIO_AF3_TIM8: \ + (((INSTANCE) == TIM12) || ((INSTANCE) == TIM13) || ((INSTANCE) == TIM14))? GPIO_AF9_TIM12: \ + (0)) + + +typedef enum +{ + LED_IS_OFF = 0, + LED_IS_ON = 1, + LED_IS_BLINKING = 2, + LED_IS_FADING = 3, +}GPIO_LEDStateTypeDef; + +typedef struct +{ + GPIO_LEDStateTypeDef state; + + GPIO_TypeDef *LED_Port; + uint32_t LED_Pin; + + uint32_t LED_Period; + uint32_t tickprev; +}GPIO_LEDTypeDef; + +typedef struct +{ + GPIO_TypeDef *Sw_Port; + uint32_t Sw_Pin; + + uint32_t Sw_PrevState; + uint32_t Sw_FilterDelay; + uint32_t tickprev; +}GPIO_SwitchTypeDef; + +///////////////////////////////////////////////////////////////////// +///////////////////////////---FUNCTIONS---/////////////////////////// +HAL_StatusTypeDef GPIO_Clock_Enable(GPIO_TypeDef *GPIOx); + +/* Считать состоянии кнопки запуска */ +uint8_t GPIO_Read_Swich(GPIO_SwitchTypeDef *swstart); +/* Включить светодиод */ +void GPIO_LED_On(GPIO_LEDTypeDef *led); +/* Выключить светодиод */ +void GPIO_LED_Off(GPIO_LEDTypeDef *led); +/* Активировать моргание светодиодом */ +void GPIO_LED_Blink_Start(GPIO_LEDTypeDef *led, uint32_t period); +/* Моргание светодиодом */ +void GPIO_LED_Blink_Handle(GPIO_LEDTypeDef *led); +///////////////////////////---FUNCTIONS---/////////////////////////// + + +#endif // __GPIO_GENERAL_H_ diff --git a/diode_tester/Core/MyLibs/mylibs_include.h b/diode_tester/Core/MyLibs/mylibs_include.h index 4404540..4785078 100644 --- a/diode_tester/Core/MyLibs/mylibs_include.h +++ b/diode_tester/Core/MyLibs/mylibs_include.h @@ -64,6 +64,7 @@ #include "main.h" #include "modbus_data.h" +#include "general_gpio.h" /** @brief Struct for trackers for Measure */ /** @brief Struct for trackers for RS */ diff --git a/diode_tester/Core/Tester_main/tester_interface_func.c b/diode_tester/Core/Tester_main/tester_interface_func.c index da63284..2666d64 100644 --- a/diode_tester/Core/Tester_main/tester_interface_func.c +++ b/diode_tester/Core/Tester_main/tester_interface_func.c @@ -4,108 +4,37 @@ /** * @brief Инициализация структур интерфейса */ -void TESTER_InterfaceInit(TESTER_SwitchStartTypeDef *swstart, TESTER_LEDsTypeDef *leds) +void TESTER_InterfaceInit(GPIO_SwitchTypeDef *swstart, TESTER_LEDsTypeDef *leds) { } /** * @brief Включить индикацию таймаута старта при активации теста */ -void TESTER_LED_TimeoutForStartTest(TESTER_LEDTypeDef *led) +void TESTER_LED_TimeoutForStartTest(GPIO_LEDTypeDef *led) { - TESTER_LED_Off(led); + GPIO_LED_Off(led); } /** * @brief Включить индикацию прямого подключения диода */ -void TESTER_LED_TestingDiodeForward(TESTER_LEDTypeDef *led) +void TESTER_LED_TestingDiodeForward(GPIO_LEDTypeDef *led) { - led->state = LED_IS_BLINKING; - led->period = LED_FORWARD_DIODE_PERIOD; + GPIO_LED_Blink_Start(led, LED_FORWARD_DIODE_PERIOD); } /** * @brief Включить индикацию обратного подключения диода */ -void TESTER_LED_TestingDiodeReverse(TESTER_LEDTypeDef *led) +void TESTER_LED_TestingDiodeReverse(GPIO_LEDTypeDef *led) { - led->state = LED_IS_BLINKING; - led->period = LED_REVERSE_DIODE_PERIOD; + GPIO_LED_Blink_Start(led, LED_REVERSE_DIODE_PERIOD); } /** * @brief Выключить индикацию ожидания комманды * @details Сделано через моргание, чтобы понимать, что системные тики работают */ -void TESTER_LED_WaitForAction(TESTER_LEDTypeDef *led) +void TESTER_LED_WaitForAction(GPIO_LEDTypeDef *led) { - led->state = LED_IS_BLINKING; - led->period = LED_BLINK_AS_ON; -} - - -/** - * @brief Считать состоянии кнопки запуска - */ -uint8_t TESTER_ReadSwichStart(TESTER_SwitchStartTypeDef *swstart) -{ - - if(HAL_GPIO_ReadPin(swstart->Sw_Port, swstart->Sw_Pin) == SW_ON) - { - if(swstart->tickprev == 0) - swstart->tickprev = HAL_GetTick(); - - if((HAL_GetTick() - swstart->tickprev) > swstart->Sw_FilterDelay) - { - if(HAL_GPIO_ReadPin(swstart->Sw_Port, swstart->Sw_Pin) == SW_ON) - { - return 1; - } - else - { - swstart->tickprev = 0; - return 0; - } - } - } - return 0; -} -/** - * @brief Включить светодиод - */ -void TESTER_LED_On(TESTER_LEDTypeDef *led) -{ - led->state = LED_IS_ON; - HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, LED_ON); -} -/** - * @brief Выключить светодиод - */ -void TESTER_LED_Off(TESTER_LEDTypeDef *led) -{ - led->state = LED_IS_OFF; - HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, LED_OFF); -} - -/** - * @brief Активировать моргание светодиодом - */ -void TESTER_LED_Blink_Start(TESTER_LEDTypeDef *led) -{ - led->state = LED_IS_BLINKING; -} - -/** - * @brief Моргание светодиодом - */ -void TESTER_LEDBlink_Handle(TESTER_LEDTypeDef *led) -{ - if(led->state == LED_IS_BLINKING) - { - uint32_t tickcurrent = HAL_GetTick(); - if((tickcurrent - led->tickprev) > led->period) - { - HAL_GPIO_TogglePin(led->LED_Port, led->LED_Pin); - led->tickprev = tickcurrent; - } - } + GPIO_LED_Blink_Start(led, LED_BLINK_AS_ON); } diff --git a/diode_tester/Core/Tester_main/tester_interface_func.h b/diode_tester/Core/Tester_main/tester_interface_func.h index 37cfd72..1e70b8e 100644 --- a/diode_tester/Core/Tester_main/tester_interface_func.h +++ b/diode_tester/Core/Tester_main/tester_interface_func.h @@ -14,64 +14,26 @@ #include "mylibs_include.h" #include "rs_message.h" -typedef enum -{ - LED_IS_OFF = 0, - LED_IS_ON = 1, - LED_IS_BLINKING = 2, -}TESTER_LEDStateTypeDef; - -typedef struct -{ - TESTER_LEDStateTypeDef state; - - GPIO_TypeDef *LED_Port; - uint32_t LED_Pin; - - uint32_t tickprev; - uint32_t period; -}TESTER_LEDTypeDef; typedef struct { - TESTER_LEDTypeDef LED1; + GPIO_LEDTypeDef LED1; }TESTER_LEDsTypeDef; -typedef struct -{ - GPIO_TypeDef *Sw_Port; - uint32_t Sw_Pin; - - uint32_t Sw_PrevState; - uint32_t Sw_FilterDelay; - uint32_t tickprev; -}TESTER_SwitchStartTypeDef; - - /* Инициализация структур интерфейса */ -void TESTER_InterfaceInit(TESTER_SwitchStartTypeDef *swstart, TESTER_LEDsTypeDef *leds); +void TESTER_InterfaceInit(GPIO_SwitchTypeDef *swstart, TESTER_LEDsTypeDef *leds); /* Включить индикацию таймаута старта при активации теста */ -void TESTER_LED_TimeoutForStartTest(TESTER_LEDTypeDef *led); +void TESTER_LED_TimeoutForStartTest(GPIO_LEDTypeDef *led); /* Включить индикацию прямого подключения диода */ -void TESTER_LED_TestingDiodeForward(TESTER_LEDTypeDef *led); +void TESTER_LED_TestingDiodeForward(GPIO_LEDTypeDef *led); /* Включить индикацию обратного подключения диода */ -void TESTER_LED_TestingDiodeReverse(TESTER_LEDTypeDef *led); +void TESTER_LED_TestingDiodeReverse(GPIO_LEDTypeDef *led); /* Выключить индикацию активного теста диодов */ -void TESTER_LED_WaitForAction(TESTER_LEDTypeDef *led); +void TESTER_LED_WaitForAction(GPIO_LEDTypeDef *led); -/* Считать состоянии кнопки запуска */ -uint8_t TESTER_ReadSwichStart(TESTER_SwitchStartTypeDef *swstart); -/* Включить светодиод */ -void TESTER_LED_On(TESTER_LEDTypeDef *led); -/* Выключить светодиод */ -void TESTER_LED_Off(TESTER_LEDTypeDef *led); -/* Активировать моргание светодиодом */ -void TESTER_LED_Blink_Start(TESTER_LEDTypeDef *led); -/* Моргание светодиодом */ -void TESTER_LEDBlink_Handle(TESTER_LEDTypeDef *led); #endif //_TESTER_INTERFACE_FUNC_H_ diff --git a/diode_tester/Core/Tester_main/tester_main.c b/diode_tester/Core/Tester_main/tester_main.c index 407bba3..c9d857c 100644 --- a/diode_tester/Core/Tester_main/tester_main.c +++ b/diode_tester/Core/Tester_main/tester_main.c @@ -10,7 +10,7 @@ TESTER_ProjectTypeDef TESTER = {0}; void TESTER_Init(TESTER_ProjectTypeDef *tester) { TESTER_InterfaceInit(&tester->SwStart, &tester->leds); - tester->leds.LED1.period = 100; + GPIO_LED_Blink_Start(&tester->leds.LED1, 100); tester->delay = 250; tester->delay_en = 0; @@ -34,9 +34,11 @@ void TESTER_pre_while(TESTER_ProjectTypeDef *tester) TESTER_UpdateSettings(tester->htest, tester->mbdata); RS_Receive_IT(tester->hmodbus, &MODBUS_MSG); - tester->leds.LED1.period = LED_BLINK_AS_ON; - tester->f.flag_init_done = 1; HAL_TIM_Base_Start(&hmcstim); + + + tester->f.flag_init_done = 1; + GPIO_LED_Blink_Start(&tester->leds.LED1, LED_BLINK_AS_ON); } @@ -123,7 +125,7 @@ void TESTER_InterfaceHandle(TESTER_ProjectTypeDef *tester) tester->mode = *((TESTER_TestModeTypeDef *)&tester->mbdata->Coils) & 0x3; /* если кнопка нажата или пришла соответствующая комманда модбас */ - if(TESTER_ReadSwichStart(&tester->SwStart) || tester->mbdata->Coils.StartTest) + if(GPIO_Read_Swich(&tester->SwStart) || tester->mbdata->Coils.StartTest) { tester->mbdata->Coils.StartTest = 0; /* Обновление настроек тестера */ @@ -148,7 +150,7 @@ void TESTER_InterfaceHandle(TESTER_ProjectTypeDef *tester) } - TESTER_LEDBlink_Handle(&tester->leds.LED1); + GPIO_LED_Blink_Handle(&tester->leds.LED1); } @@ -199,9 +201,7 @@ void TESTER_Set_Default_Settings(TESTER_ProjectTypeDef *tester) /* Настройка пинов для светодиода*/ tester->leds.LED1.LED_Port = LED1_Port; - tester->leds.LED1.LED_Pin = LED1_Pin; - tester->leds.LED1.period = LED_BLINK_AS_ON; - + tester->leds.LED1.LED_Pin = LED1_Pin; /* Настройка таймингов по умолчанию для тестирования */ tester->mbdata->HoldRegs.TimeForForward = DEF_MS_TIME_FOR_POSITIVE; diff --git a/diode_tester/Core/Tester_main/tester_main.h b/diode_tester/Core/Tester_main/tester_main.h index 9aa0bea..79528ef 100644 --- a/diode_tester/Core/Tester_main/tester_main.h +++ b/diode_tester/Core/Tester_main/tester_main.h @@ -59,7 +59,7 @@ typedef struct MB_DataStructureTypeDef *mbdata; - TESTER_SwitchStartTypeDef SwStart; ///< структура кнопки старта + GPIO_SwitchTypeDef SwStart; ///< структура кнопки старта TESTER_LEDsTypeDef leds; ///< структура светодиодов diff --git a/diode_tester/MDK-ARM/diode_tester.uvoptx b/diode_tester/MDK-ARM/diode_tester.uvoptx index bff4e9a..31a4b0e 100644 --- a/diode_tester/MDK-ARM/diode_tester.uvoptx +++ b/diode_tester/MDK-ARM/diode_tester.uvoptx @@ -576,7 +576,7 @@ MyLibs - 0 + 1 0 0 0 @@ -628,6 +628,30 @@ 0 0 + + 4 + 24 + 1 + 0 + 0 + 0 + ..\Core\MyLibs\general_gpio.c + general_gpio.c + 0 + 0 + + + 4 + 25 + 5 + 0 + 0 + 0 + ..\Core\MyLibs\general_gpio.h + general_gpio.h + 0 + 0 + @@ -638,7 +662,7 @@ 0 5 - 24 + 26 2 0 0 @@ -658,7 +682,7 @@ 0 6 - 25 + 27 1 0 0 @@ -670,7 +694,7 @@ 6 - 26 + 28 1 0 0 @@ -682,7 +706,7 @@ 6 - 27 + 29 1 0 0 @@ -694,7 +718,7 @@ 6 - 28 + 30 1 0 0 @@ -706,7 +730,7 @@ 6 - 29 + 31 1 0 0 @@ -718,7 +742,7 @@ 6 - 30 + 32 1 0 0 @@ -730,7 +754,7 @@ 6 - 31 + 33 1 0 0 @@ -742,7 +766,7 @@ 6 - 32 + 34 1 0 0 @@ -762,7 +786,7 @@ 0 7 - 33 + 35 1 0 0 @@ -774,7 +798,7 @@ 7 - 34 + 36 1 0 0 @@ -786,7 +810,7 @@ 7 - 35 + 37 1 0 0 @@ -798,7 +822,7 @@ 7 - 36 + 38 1 0 0 @@ -810,7 +834,7 @@ 7 - 37 + 39 1 0 0 @@ -822,7 +846,7 @@ 7 - 38 + 40 1 0 0 @@ -834,7 +858,7 @@ 7 - 39 + 41 1 0 0 @@ -846,7 +870,7 @@ 7 - 40 + 42 1 0 0 @@ -858,7 +882,7 @@ 7 - 41 + 43 1 0 0 @@ -870,7 +894,7 @@ 7 - 42 + 44 1 0 0 @@ -882,7 +906,7 @@ 7 - 43 + 45 1 0 0 @@ -894,7 +918,7 @@ 7 - 44 + 46 1 0 0 @@ -906,7 +930,7 @@ 7 - 45 + 47 1 0 0 @@ -918,7 +942,7 @@ 7 - 46 + 48 1 0 0 @@ -930,7 +954,7 @@ 7 - 47 + 49 1 0 0 @@ -942,7 +966,7 @@ 7 - 48 + 50 1 0 0 @@ -962,7 +986,7 @@ 0 8 - 49 + 51 1 0 0 diff --git a/diode_tester/MDK-ARM/diode_tester.uvprojx b/diode_tester/MDK-ARM/diode_tester.uvprojx index 0d49905..21f3185 100644 --- a/diode_tester/MDK-ARM/diode_tester.uvprojx +++ b/diode_tester/MDK-ARM/diode_tester.uvprojx @@ -515,6 +515,16 @@ 5 ..\Core\MyLibs\trackers.h + + general_gpio.c + 1 + ..\Core\MyLibs\general_gpio.c + + + general_gpio.h + 5 + ..\Core\MyLibs\general_gpio.h + diff --git a/docs/mb_adr.xlsx b/docs/mb_adr.xlsx index 926cf96d3221e9388da5d8da20b22c63bf59a254..2fc0eecf277507ebbca468d3e8f9ead00d055b5e 100644 GIT binary patch delta 2215 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 delta 2189 zcmV;82y*wbe6)P95fci=ejKya1^@u{8j~9nA%Ak>IPktz`wuRkb`OKG!6ZKF5mUyIy1vbxF2!@~6kL)T%4 zwA^He-NOCr&xa59uG8@3uu1arz!vT|*0>*+KmRm;E$ioI&lq=r!=YKYd(Nww=QZh` z6@N)HC@Xe=lWkcS35T!s&TFcgB^yapVt8J`2Q001bgZA+kA^zlY$RG^dJZY*R;%m1^ji2On(Fu z*f9C3E}L!me&J3A{&+Y6Wao)B{2>zzT_=5Mcv<|TP<&*hSOmxdK3~;&IJghP@#OyQ zdM2Q~ya#+DlaW6N?}j7)hMSC$349`x$#ih%52qt>ldcM$GKREsobY5hugg~lLL3xs zszf{(e+HDwr~|=-@3ZuIRVt&LF@Li39C87JyqgQSNL=KT;IVMWQ;@uH8wj7{aum$H zBZNeXI4gw{4y9KFRiq#Re6&nfDcltj$1MwB~4(B!1GXDSH+LOnBrr24k9f(VoyOD7O>u7B`QLPvc+b-d6aIkVQyl-Z>z8#R?}h4LG{D&9g?FdwDlV+86YO>)o!m zAZqm{u3O=urMEP}KB?KpRcUh-&Q_pelgSL&S|!w0q49uBp{lhZ6VQNAIJQ+t=&cb) zStYz=l*xOHB8Xa}&d$y-o3w(1iS5Qx*Gx^N1~bK{G} zLqB>!)T&P0BHgSi(CHnR@nEP&XG8=9OZr+3p@Jut%E4|Kc} z#*t=hb#t^aLnJ%mX|JP^?mPXPyiq64uk2lQikD2F?G*FMaY>w~l!jAq&*dZ^h?{k2 zBjhZa`cp$o93LZ62u17^_M}{_HPTcy#TR=XaPkcut;81o6n~?V=%rU3NYsJECd3X) z(sA{KrD|AA;S>^ysD$7=;lw7y7EU^w9^tBGFojb{f$CQ^;`)<}Ae5gkF!@u7(tal&h+QemLm zyHZJYaW2)TJ+&-=S_X?PS<6O7EeqOOMkiOz*i_8#SO~Wa;M_Kmk2@y9{e|jZPPM=e zV6vAGE1CX|J;2R^n%U{>s!!jX)8sjJo(B;?*0$cre zZ7js?E>EfY^cwZ)n5t>bPR6Ih8X}2|aPmHF@(`&)c6p+& zL+{g3RnuC*PX{_gvehRcvPL9S|5EVZRLBEsH$mrAeR{rm*QaL7?bC%6B8^R?F>(GH zkw7uA%6~SOZ!*vP?^=Z0f{A=JH1t$1gDweEyxPanJp?-Ufovn?{eaeNQM)!!@+Veo zcWi*Gi0R1&YN@Z5%>}D>a{b>pY55|S^e{%uTPXhIATqO{@4$y}Agio*VziuB$&US& z)Vu7^I62z_)8PQFQLCQ@^Boq{UDmkq6^;ow({PM$~=N%5fZrift`U{8`e7`XM zQaM#pvHDB)9e!|u=U>(t{JtQ6+F7_&S@Sx{IIPS8{=I~QJg&q#0CtkD_z8<=sRgQM z*=FI^j~h8Ad+iTa%O8^wH5IcO8c7`l8oA3&vu8In0e_?$Lqpqv%AOnuRutbta@Q4` zG$he(|K7CSY6nBeOYS-MyC;`q>w{{dAF!@&b&hC4Py|}Eves3O-pWmUha%^>mb_^- z_Kst1cwgduCymCU#0dE*{@6ah4o{71-S0{ODl#dUu)uw5iww^%VQ~$2ej9eY zt3f^-gMOtZ#SnLdfQ&)_HpV?G?~BK$a)XL~hb=L=kLju;gbnAjA9>N=2O10NH27a) zx{PTWr^}L3wjhkIX2dgK%zgO@ieCV;#yRo<3dVjMv(*Lw0QDM^!aG(04wD%?KmzO_ zlOGcmlW;sQ0b`S(JV5~_lj1x*0UDDaJyZdplOR1MlbSs*0Vb2mJtG7fxywzH@jVs+ PSCa@nBnHko00000+BPhq