diff --git a/CMakeLists.txt b/CMakeLists.txt index 65b4ebd..5c197e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,15 +3,15 @@ cmake_minimum_required(VERSION 3.19) project(shmingo-HAL) set(PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(MCU_FAMILY "STM32L4xx" CACHE STRING "MCU family") -set(MCU_MODEL "STM32L432xx" CACHE STRING "MCU model") +set(MCU_FAMILY "STM32F0xx") +set(MCU_MODEL "STM32F072xB") set(CPU_PARAMETERS - -mcpu=cortex-m4 + -mcpu=cortex-m0 -mthumb) -set(STARTUP_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/MX/L432KC/startup_stm32l432kcux.s) -set(MCU_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/MX/L432KC/STM32L432KCUX_FLASH.ld) +set(STARTUP_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/MX/F072RB/startup_stm32f072rbtx.s) +set(MCU_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/MX/F072RB/STM32F072RBTX_FLASH.ld) set(EXECUTABLE ${CMAKE_PROJECT_NAME}) enable_language(C CXX ASM) @@ -23,87 +23,94 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS ON) set(MX_INCLUDE_DIRECTORIES - ${CMAKE_CURRENT_SOURCE_DIR}/Drivers/CMSIS/Device/ST/${MCU_FAMILY}/Include - ${CMAKE_CURRENT_SOURCE_DIR}/Drivers/CMSIS/Include + ${CMAKE_CURRENT_SOURCE_DIR}/Drivers/CMSIS/Device/ST/${MCU_FAMILY}/Include + ${CMAKE_CURRENT_SOURCE_DIR}/Drivers/CMSIS/Include ) set(PROJECT_INCLUDE_DIRECTORIES - ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + + #[[ +SHAL/Include/Peripheral/UART +SHAL/Include/Peripheral/UART/Reg +SHAL/Include/Peripheral/I2C +SHAL/Include/Peripheral/I2C/Reg +SHAL/Include/Peripheral/ADC +SHAL/Include/Peripheral/ADC/Reg +SHAL/Include/Peripheral/EXT +SHAL/Include/Peripheral/EXT/Reg +]]# SHAL/Include/Core/ - SHAL/Include/Peripheral/Timer - SHAL/Include/Peripheral/Timer/Reg SHAL/Include/Peripheral/GPIO SHAL/Include/Peripheral/GPIO/Reg - SHAL/Include/Peripheral/UART - SHAL/Include/Peripheral/UART/Reg - SHAL/Include/Peripheral/I2C - SHAL/Include/Peripheral/I2C/Reg - SHAL/Include/Peripheral/ADC - SHAL/Include/Peripheral/ADC/Reg - SHAL/Include/Peripheral/EXT/ - SHAL/Include/Peripheral/EXT/Reg + SHAL/Include/Peripheral/Timer + SHAL/Include/Peripheral/Timer/Reg ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Include ) file(GLOB_RECURSE PROJECT_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/${MCU_FAMILY}/*.c - ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/${MCU_FAMILY}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/Universal/*.c ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/Universal/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/Universal/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/${MCU_FAMILY}/*.c +#${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/${MCU_FAMILY}/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/main.cpp + + #Temporary manual method of including source files to avoid including broken code + ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/${MCU_FAMILY}/Peripheral/GPIO/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/${MCU_FAMILY}/Peripheral/Timer/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/SHAL/Src/${MCU_FAMILY}/Core/*.cpp ) add_executable(${EXECUTABLE} - ${PROJECT_SOURCES} - ${STARTUP_SCRIPT} +${PROJECT_SOURCES} +${STARTUP_SCRIPT} ) target_compile_definitions(${EXECUTABLE} PRIVATE - ${MCU_MODEL} +${MCU_MODEL} ) target_include_directories(${EXECUTABLE} PRIVATE - ${MX_INCLUDE_DIRECTORIES} - ${PROJECT_INCLUDE_DIRECTORIES} +${MX_INCLUDE_DIRECTORIES} +${PROJECT_INCLUDE_DIRECTORIES} ) target_compile_options(${EXECUTABLE} PRIVATE - ${CPU_PARAMETERS} - -Wall - -Wextra - -Wpedantic - -Wno-unused-parameter - -Wno-switch - -Wno-implicit-fallthrough - $<$: - -Wno-volatile - -Wsuggest-override> - - $<$:-Og -g3 -ggdb> - $<$:-Og -g0> +${CPU_PARAMETERS} +-Wall +-Wextra +-Wpedantic +-Wno-unused-parameter +$<$: +-Wno-volatile +-Wsuggest-override> + +$<$:-Og -g3 -ggdb> +$<$:-Og -g0> ) target_link_options(${EXECUTABLE} PRIVATE - -T${MCU_LINKER_SCRIPT} - ${CPU_PARAMETERS} - -Wl,-Map=${CMAKE_PROJECT_NAME}.map - --specs=nosys.specs - -Wl,--start-group - -lc - -lm - -lstdc++ - -lsupc++ - -Wl,--end-group - -Wl,--print-memory-usage +-T${MCU_LINKER_SCRIPT} +${CPU_PARAMETERS} +-Wl,-Map=${CMAKE_PROJECT_NAME}.map +--specs=nosys.specs +-Wl,--start-group +-lc +-lm +-lstdc++ +-lsupc++ +-Wl,--end-group +-Wl,--print-memory-usage ) add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${CMAKE_SIZE} $ +COMMAND ${CMAKE_SIZE} $ ) add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${CMAKE_OBJCOPY} -O ihex $ - ${EXECUTABLE}.hex - COMMAND ${CMAKE_OBJCOPY} -O binary $ - ${EXECUTABLE}.bin +COMMAND ${CMAKE_OBJCOPY} -O ihex $ +${EXECUTABLE}.hex +COMMAND ${CMAKE_OBJCOPY} -O binary $ +${EXECUTABLE}.bin ) \ No newline at end of file diff --git a/MX/F072RB/startup_stm32f072rbtx.s b/MX/F072RB/startup_stm32f072rbtx.s index ba7b08a..66a0308 100644 --- a/MX/F072RB/startup_stm32f072rbtx.s +++ b/MX/F072RB/startup_stm32f072rbtx.s @@ -1,4 +1,4 @@ -/** + /** ****************************************************************************** * @file startup_stm32f072xb.s * @author MCD Application Team diff --git a/Makefile b/Makefile index 4bbed9d..9328010 100644 --- a/Makefile +++ b/Makefile @@ -5,12 +5,9 @@ BUILD_DIR := build BUILD_TYPE ?= Debug TOOLCHAIN := gcc-arm-none-eabi.cmake -CFLAGS_DEBUG ?= -g3 -O0 -CXXFLAGS_DEBUG ?= -g3 -O0 - # MCU target (override on command line: make build MCU_MODEL=STM32F051x8) -MCU_MODEL ?= STM32L432xx -MCU_FAMILY ?= STM32L4xx +MCU_MODEL ?= STM32F072xB +MCU_FAMILY ?= STM32F0xx # --- Default target --- all: build @@ -23,8 +20,6 @@ ${BUILD_DIR}/build.ninja: -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN} \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" \ - -DCMAKE_CXX_FLAGS_DEBUG="${CXXFLAGS_DEBUG}" \ -DMCU_MODEL=$(MCU_MODEL) \ -DMCU_FAMILY=$(MCU_FAMILY) @@ -43,4 +38,4 @@ format: $(addsuffix .format,${SRCS}) # --- Clean --- clean: - rm -rf ${BUILD_DIR} compile_commands.json + rm -rf ${BUILD_DIR} compile_commands.json \ No newline at end of file diff --git a/README.md b/README.md index c4a0ac9..33cb4f1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ -# Shmingo-HAL +Instructions to run -A custom HAL for STM32F0 MCUs \ No newline at end of file +A binary is provided (Shmingo-HAL, formats are bin,hex,elf) + +Download STM32CubeProgrammer +point to the binary file +Program via SWD (on Nucleo devices, you can just plug into USB and connect via onboard USB to SWD adapter) + +You can also use an external ST-Link to program with the dedicated SWD pins \ No newline at end of file diff --git a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_F072xB.h b/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_F072xB.h index d128244..6325fdf 100644 --- a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_F072xB.h +++ b/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_F072xB.h @@ -8,6 +8,30 @@ #include "SHAL_CORE.h" #include "SHAL_ADC_TYPES.h" +enum class SHAL_ADC_Channel : uint32_t { //TODO remove unused or non existing channels? + CH0 = 0, + CH1, + CH2, + CH3, + CH4, + CH5, + CH6, + CH7, + CH8, + CH9, + CH10, + CH11, + CH12, + CH13, + CH14, + CH15, + CH16, + CHTemp, + CHRef, + CHBat, + NO_ADC_MAPPING +}; + #define SHAL_ADC1 SHAL_ADC(1) enum class ADC_Key : uint8_t{ diff --git a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_L432KC.h b/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_L432KC.h index 847d28c..206fe03 100644 --- a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_L432KC.h +++ b/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_L432KC.h @@ -57,7 +57,7 @@ static volatile ADC_TypeDef* ADC_TABLE[1] = { //Lookup table for ADCs }; static inline SHAL_ADC_Common_Control_Reg getADCCommonControl() { - return {&ADC1_COMMON->CCR ,ADC_CCR_VREFEN,ADC_CCR_TSEN,ADC_CCR_VBATEN}; + return {&ADC1_COMMON->CCR,ADC_CCR_VREFEN,ADC_CCR_TSEN,ADC_CCR_VBATEN}; } static inline SHAL_ADC_RCC_Enable_Reg getADCRCCEnableRegister(ADC_Key key){ diff --git a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_F072xB.h b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_F072xB.h index e46394e..fbc48e7 100644 --- a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_F072xB.h +++ b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_F072xB.h @@ -29,66 +29,29 @@ enum class GPIO_Key : uint8_t { INVALID }; +static volatile GPIO_TypeDef * GPIO_TABLE[3] = { //Lookup table for ADCs + GPIOA, + GPIOB, + GPIOC, +}; - -constexpr SHAL_GPIO_Peripheral getGPIORegister(const GPIO_Key g){ - switch(g) { - case GPIO_Key::A0: return {GPIOA,0}; - case GPIO_Key::A1: return {GPIOA,1}; - case GPIO_Key::A2: return {GPIOA,2}; - case GPIO_Key::A3: return {GPIOA,3}; - case GPIO_Key::A4: return {GPIOA,4}; - case GPIO_Key::A5: return {GPIOA,5}; - case GPIO_Key::A6: return {GPIOA,6}; - case GPIO_Key::A7: return {GPIOA,7}; - case GPIO_Key::A8: return {GPIOA,8}; - case GPIO_Key::A9: return {GPIOA,9}; - case GPIO_Key::A10: return {GPIOA,10}; - case GPIO_Key::A11: return {GPIOA,11}; - case GPIO_Key::A12: return {GPIOA,12}; - case GPIO_Key::A13: return {GPIOA,13}; - case GPIO_Key::A14: return {GPIOA,14}; - case GPIO_Key::A15: return {GPIOA,15}; - case GPIO_Key::B0: return {GPIOB,0}; - case GPIO_Key::B1: return {GPIOB,1}; - case GPIO_Key::B2: return {GPIOB,2}; - case GPIO_Key::B3: return {GPIOB,3}; - case GPIO_Key::B4: return {GPIOB,4}; - case GPIO_Key::B5: return {GPIOB,5}; - case GPIO_Key::B6: return {GPIOB,6}; - case GPIO_Key::B7: return {GPIOB,7}; - case GPIO_Key::B8: return {GPIOB,8}; - case GPIO_Key::B9: return {GPIOB,9}; - case GPIO_Key::B10: return {GPIOB,10}; - case GPIO_Key::B11: return {GPIOB,11}; - case GPIO_Key::B12: return {GPIOB,12}; - case GPIO_Key::B13: return {GPIOB,13}; - case GPIO_Key::B14: return {GPIOB,14}; - case GPIO_Key::B15: return {GPIOB,15}; - case GPIO_Key::C0: return {GPIOC,0}; - case GPIO_Key::C1: return {GPIOC,1}; - case GPIO_Key::C2: return {GPIOC,2}; - case GPIO_Key::C3: return {GPIOC,3}; - case GPIO_Key::C4: return {GPIOC,4}; - case GPIO_Key::C5: return {GPIOC,5}; - case GPIO_Key::C6: return {GPIOC,6}; - case GPIO_Key::C7: return {GPIOC,7}; - case GPIO_Key::C8: return {GPIOC,8}; - case GPIO_Key::C9: return {GPIOC,9}; - case GPIO_Key::C10: return {GPIOC,10}; - case GPIO_Key::C11: return {GPIOC,11}; - case GPIO_Key::C12: return {GPIOC,12}; - case GPIO_Key::C13: return {GPIOC,13}; - case GPIO_Key::C14: return {GPIOC,14}; - case GPIO_Key::C15: return {GPIOC,15}; - case GPIO_Key::INVALID: - case GPIO_Key::NUM_GPIO: - assert(false); - return SHAL_GPIO_Peripheral(nullptr,0); //Unreachable - } - __builtin_unreachable(); +constexpr uint8_t getGPIOPinNumber(GPIO_Key key){ + return static_cast(key) % 16; } +static inline uint32_t getGPIOPortNumber(const GPIO_Key g){ + return (static_cast(g) / 16); +} + +static inline SHAL_GPIO_RCC_Enable_Register getGPIORCCEnable(const GPIO_Key g){ + volatile uint32_t* reg = &RCC->AHBENR; //register + uint32_t mask; + mask = RCC_AHBENR_GPIOAEN << getGPIOPortNumber(g); //Should shift to get each port number + + return {reg,mask}; +} + + constexpr SHAL_GPIO_EXTI_Register getGPIOEXTICR(const GPIO_Key g){ switch(g) { case GPIO_Key::A0: return {&SYSCFG->EXTICR[0],SYSCFG_EXTICR1_EXTI0_PA,EXTI0_1_IRQn}; @@ -148,128 +111,55 @@ constexpr SHAL_GPIO_EXTI_Register getGPIOEXTICR(const GPIO_Key g){ __builtin_unreachable(); } -constexpr SHAL_Peripheral_Register getGPIORCCEnable(const GPIO_Key g){ - switch(g) { - case GPIO_Key::A0: - case GPIO_Key::A1: - case GPIO_Key::A2: - case GPIO_Key::A3: - case GPIO_Key::A4: - case GPIO_Key::A5: - case GPIO_Key::A6: - case GPIO_Key::A7: - case GPIO_Key::A8: - case GPIO_Key::A9: - case GPIO_Key::A10: - case GPIO_Key::A11: - case GPIO_Key::A12: - case GPIO_Key::A13: - case GPIO_Key::A14: - case GPIO_Key::A15: - return {&RCC->AHBENR, RCC_AHBENR_GPIOAEN_Pos}; - case GPIO_Key::B0: - case GPIO_Key::B1: - case GPIO_Key::B2: - case GPIO_Key::B3: - case GPIO_Key::B4: - case GPIO_Key::B5: - case GPIO_Key::B6: - case GPIO_Key::B7: - case GPIO_Key::B8: - case GPIO_Key::B9: - case GPIO_Key::B10: - case GPIO_Key::B11: - case GPIO_Key::B12: - case GPIO_Key::B13: - case GPIO_Key::B14: - case GPIO_Key::B15: - return {&RCC->AHBENR, RCC_AHBENR_GPIOBEN_Pos}; - case GPIO_Key::C0: - case GPIO_Key::C1: - case GPIO_Key::C2: - case GPIO_Key::C3: - case GPIO_Key::C4: - case GPIO_Key::C5: - case GPIO_Key::C6: - case GPIO_Key::C7: - case GPIO_Key::C8: - case GPIO_Key::C9: - case GPIO_Key::C10: - case GPIO_Key::C11: - case GPIO_Key::C12: - case GPIO_Key::C13: - case GPIO_Key::C14: - case GPIO_Key::C15: - return {&RCC->AHBENR, RCC_AHBENR_GPIOCEN_Pos}; - case GPIO_Key::INVALID: - case GPIO_Key::NUM_GPIO: - assert(false); - return SHAL_Peripheral_Register(nullptr,0); //Unreachable - } - __builtin_unreachable(); + + +static inline SHAL_GPIO_Mode_Register getGPIOModeRegister(const GPIO_Key key){ + volatile uint32_t* reg = &GPIO_TABLE[static_cast(key) / 16]->MODER; + uint32_t offset = 2 * (static_cast(key) % 16); + return {reg,offset}; } -constexpr uint32_t getGPIOPortNumber(const GPIO_Key g){ - switch(g) { - case GPIO_Key::A0: - case GPIO_Key::A1: - case GPIO_Key::A2: - case GPIO_Key::A3: - case GPIO_Key::A4: - case GPIO_Key::A5: - case GPIO_Key::A6: - case GPIO_Key::A7: - case GPIO_Key::A8: - case GPIO_Key::A9: - case GPIO_Key::A10: - case GPIO_Key::A11: - case GPIO_Key::A12: - case GPIO_Key::A13: - case GPIO_Key::A14: - case GPIO_Key::A15: - return 0; - case GPIO_Key::B0: - case GPIO_Key::B1: - case GPIO_Key::B2: - case GPIO_Key::B3: - case GPIO_Key::B4: - case GPIO_Key::B5: - case GPIO_Key::B6: - case GPIO_Key::B7: - case GPIO_Key::B8: - case GPIO_Key::B9: - case GPIO_Key::B10: - case GPIO_Key::B11: - case GPIO_Key::B12: - case GPIO_Key::B13: - case GPIO_Key::B14: - case GPIO_Key::B15: - return 1; - case GPIO_Key::C0: - case GPIO_Key::C1: - case GPIO_Key::C2: - case GPIO_Key::C3: - case GPIO_Key::C4: - case GPIO_Key::C5: - case GPIO_Key::C6: - case GPIO_Key::C7: - case GPIO_Key::C8: - case GPIO_Key::C9: - case GPIO_Key::C10: - case GPIO_Key::C11: - case GPIO_Key::C12: - case GPIO_Key::C13: - case GPIO_Key::C14: - case GPIO_Key::C15: - return 2; - case GPIO_Key::INVALID: - case GPIO_Key::NUM_GPIO: - assert(false); - return 0; - } - __builtin_unreachable(); +static inline SHAL_GPIO_Pullup_Pulldown_Register getGPIOPUPDRegister(const GPIO_Key key){ + volatile uint32_t* reg = &GPIO_TABLE[static_cast(key) / 16]->PUPDR; + uint32_t offset = 2 * static_cast(key) % 16; + return {reg,offset}; } +static inline SHAL_GPIO_Alternate_Function_Register getGPIOAlternateFunctionRegister(const GPIO_Key key){ + + uint32_t pinNumber = static_cast(key) % 16; //Number of pin (We need 0-7 to be AFR 1 and 8-15 to be AFR 2) + uint32_t afrIndex = pinNumber < 8 ? 0 : 1; + + volatile uint32_t* reg = &GPIO_TABLE[static_cast(key) / 16]->AFR[afrIndex]; + uint32_t offset = (pinNumber % 8) * 4; //Increment in groups of four + return {reg,offset}; +} + +static inline SHAL_GPIO_Output_Speed_Register getGPIOOutputSpeedRegister(const GPIO_Key key){ + volatile uint32_t* reg = &GPIO_TABLE[static_cast(key) / 16]->OSPEEDR; + uint32_t offset = 2 * static_cast(key) % 16; + return {reg,offset}; +} + +static inline SHAL_GPIO_Output_Type_Register getGPIOOutputTypeRegister(const GPIO_Key key){ + volatile uint32_t* reg = &GPIO_TABLE[static_cast(key) / 16]->OTYPER; + uint32_t offset = static_cast(key) % 16; + return {reg,offset}; +} + +static inline SHAL_GPIO_Output_Data_Register getGPIOOutputDataRegister(const GPIO_Key key){ + volatile uint32_t* reg = &GPIO_TABLE[static_cast(key) / 16]->ODR; + uint32_t offset = (static_cast(key) % 16); + return {reg,offset}; +} + +static inline SHAL_GPIO_Input_Data_Register getGPIOInputDataRegister(const GPIO_Key key){ + volatile uint32_t* reg = &GPIO_TABLE[static_cast(key) / 16]->IDR; + uint32_t offset = static_cast(key) % 16; + return {reg,offset}; +} + +/* TODO reimplement constexpr SHAL_GPIO_Port_Info getGPIOPortInfo(GPIO_Key key){ switch(key){ case GPIO_Key::A0: @@ -343,6 +233,6 @@ constexpr SHAL_GPIO_Port_Info getGPIOPortInfo(GPIO_Key key){ __builtin_unreachable(); } - +*/ #endif //SHMINGO_HAL_SHAL_GPIO_REG_F072XB_H diff --git a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_L432KC.h b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_L432KC.h index f27d994..73774a0 100644 --- a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_L432KC.h +++ b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_L432KC.h @@ -113,7 +113,8 @@ constexpr SHAL_GPIO_EXTI_Register getGPIOEXTICR(const GPIO_Key g){ static inline SHAL_GPIO_RCC_Enable_Register getGPIORCCEnable(const GPIO_Key g){ volatile uint32_t* reg = &RCC->AHB2ENR; //register uint32_t offset; - offset = (static_cast(g) / 16) == 0 ? RCC_AHB2ENR_GPIOAEN_Pos : RCC_AHB2ENR_GPIOBEN_Pos; + + offset = RCC_AHB2ENR_GPIOAEN << getGPIOPortNUmber(g); //Should shift to get each port number return {reg,offset}; } diff --git a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h index 2192f80..491e057 100644 --- a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h +++ b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO.h @@ -9,8 +9,8 @@ #include -#include "SHAL_EXTI_CALLBACK.h" -#include "SHAL_ADC.h" +//#include "SHAL_EXTI_CALLBACK.h" +//#include "SHAL_ADC.h" //Abstraction of SHAL_GPIO registers @@ -27,12 +27,12 @@ public: /// Uses the ADC to read an analog voltage value /// \param sampleTime The amount of clock cycles to use for the ADC /// \return ADC result - uint16_t analogRead(SHAL_ADC_SampleTime sampleTime = SHAL_ADC_SampleTime::C8); + //uint16_t analogRead(SHAL_ADC_SampleTime sampleTime = SHAL_ADC_SampleTime::C8); TODO Reimplement uint16_t digitalRead(); void setAlternateFunction(GPIO_Alternate_Function AF) volatile; - void setAlternateFunction(GPIO_Alternate_Function_Mapping AF) volatile; + //void setAlternateFunction(GPIO_Alternate_Function_Mapping AF) volatile; //TODO reimplement? void setOutputType(PinType type) volatile; @@ -40,7 +40,7 @@ public: void setInternalResistor(InternalResistorType type) volatile; - void useAsExternalInterrupt(TriggerMode mode, EXTICallback callback); + //void useAsExternalInterrupt(TriggerMode mode, EXTICallback callback); TODO reimplement SHAL_Result setPinMode(PinMode mode) volatile; @@ -65,7 +65,7 @@ private: #define GET_GPIO(key) GPIOManager::get(key) -#define SET_ANALOGREAD_ADC(x) GPIOManager::setGPIOADC(x) +//#define SET_ANALOGREAD_ADC(x) GPIOManager::setGPIOADC(x) TODO reimplement //Manages instances of SHAL_GPIO objects @@ -75,9 +75,9 @@ public: static SHAL_GPIO& get(GPIO_Key); - static SHAL_ADC getGPIOADC(){ return m_GPIO_ADC;} + //static SHAL_ADC getGPIOADC(){ return m_GPIO_ADC;} TODO Reimplement - static void setGPIOADC(SHAL_ADC adc){m_GPIO_ADC = adc;} + //static void setGPIOADC(SHAL_ADC adc){m_GPIO_ADC = adc;} TODO Reimplement GPIOManager() = delete; @@ -85,7 +85,7 @@ private: inline static SHAL_GPIO m_gpios[AVAILABLE_PORTS][PINS_PER_PORT] = {{}}; - inline static SHAL_ADC m_GPIO_ADC = SHAL_ADC(1); + //inline static SHAL_ADC m_GPIO_ADC = SHAL_ADC(1); TODO Reimplement }; diff --git a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO_TYPES.h b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO_TYPES.h index 10dfef1..e0b17b3 100644 --- a/SHAL/Include/Peripheral/GPIO/SHAL_GPIO_TYPES.h +++ b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO_TYPES.h @@ -6,8 +6,8 @@ #define SHAL_GPIO_TYPES_H #include "SHAL_CORE.h" -#include "SHAL_ADC.h" -#include "SHAL_ADC_TYPES.h" +//#include "SHAL_ADC.h" +//#include "SHAL_ADC_TYPES.h" struct SHAL_GPIO_EXTI_Register{ volatile uint32_t* EXT_ICR; //4 32 bit registers which say which GPIO a line is connected to @@ -17,7 +17,7 @@ struct SHAL_GPIO_EXTI_Register{ struct SHAL_GPIO_RCC_Enable_Register{ volatile uint32_t* reg; - uint32_t offset; + uint32_t mask; }; struct SHAL_GPIO_Mode_Register { @@ -55,11 +55,12 @@ struct SHAL_GPIO_Input_Data_Register { uint32_t offset; }; +/* TODO reimplement and uncomment ADC references (Here and on GPIO.h) struct SHAL_GPIO_Port_Info{ uint8_t number; SHAL_ADC_Channel ADCChannel; }; - +*/ enum class PinMode : uint8_t{ INPUT_MODE = 0x00, OUTPUT_MODE = 0x01, diff --git a/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h b/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h index 113d7bb..ad680bc 100644 --- a/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h +++ b/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG_F072xB.h @@ -16,9 +16,9 @@ #include "SHAL_TIM_TYPES.h" enum class Timer_Key : uint8_t { //For STM32F072 - S_TIM1, - S_TIM2, - S_TIM3, + S_TIM1 = 0, + S_TIM2 = 1, + S_TIM3 = 2, S_TIM6, S_TIM7, S_TIM14, @@ -39,20 +39,40 @@ enum class Timer_Key : uint8_t { //For STM32F072 #define SHAL_TIM16 TimerManager::get(Timer_Key::S_TIM16) #define SHAL_TIM17 TimerManager::get(Timer_Key::S_TIM17) +static SHAL_TIM_Info TIM_INFO_TABLE[9] = { + {TIM1,TIM1_BRK_UP_TRG_COM_IRQn,4}, + {TIM2,TIM2_IRQn,4}, + {TIM3,TIM3_IRQn,4}, + {TIM6,TIM6_DAC_IRQn,0}, + {TIM7,TIM7_IRQn,0}, + {TIM14,TIM14_IRQn,1}, + {TIM15,TIM15_IRQn,2}, + {TIM16,TIM16_IRQn,1}, + {TIM17,TIM17_IRQn,1}, +}; + +//Get actual register value based on enum +static volatile TIM_TypeDef* getTimerRegister(Timer_Key t) { + return TIM_INFO_TABLE[static_cast(t)].timer; +} + +static IRQn_Type getIRQn(Timer_Key t) { + return TIM_INFO_TABLE[static_cast(t)].IRQn; +} //Get TIMER_KEY peripheral struct including bus register, enable mask, TIMER_KEY mask -constexpr TIM_RCC_Enable getTimerRCC(Timer_Key t) { +static SHAL_TIM_RCC_Register getTimerRCC(Timer_Key t) { switch(t) { - case Timer_Key::S_TIM1: return {&RCC->APB2ENR, RCC_APB2ENR_TIM1EN_Pos}; - case Timer_Key::S_TIM2: return {&RCC->APB1ENR, RCC_APB1ENR_TIM2EN_Pos}; - case Timer_Key::S_TIM3: return {&RCC->APB1ENR, RCC_APB1ENR_TIM3EN_Pos}; - case Timer_Key::S_TIM6: return {&RCC->APB1ENR, RCC_APB1ENR_TIM6EN_Pos}; - case Timer_Key::S_TIM7: return {&RCC->APB1ENR, RCC_APB1ENR_TIM7EN_Pos}; - case Timer_Key::S_TIM14: return {&RCC->APB1ENR, RCC_APB1ENR_TIM14EN_Pos}; - case Timer_Key::S_TIM15: return {&RCC->APB2ENR, RCC_APB2ENR_TIM15EN_Pos}; - case Timer_Key::S_TIM16: return {&RCC->APB2ENR, RCC_APB2ENR_TIM16EN_Pos}; - case Timer_Key::S_TIM17: return {&RCC->APB2ENR, RCC_APB2ENR_TIM17EN_Pos}; + case Timer_Key::S_TIM1: return {&RCC->APB2ENR, RCC_APB2ENR_TIM1EN}; + case Timer_Key::S_TIM2: return {&RCC->APB1ENR, RCC_APB1ENR_TIM2EN}; + case Timer_Key::S_TIM3: return {&RCC->APB1ENR, RCC_APB1ENR_TIM3EN}; + case Timer_Key::S_TIM6: return {&RCC->APB1ENR, RCC_APB1ENR_TIM6EN}; + case Timer_Key::S_TIM7: return {&RCC->APB1ENR, RCC_APB1ENR_TIM7EN}; + case Timer_Key::S_TIM14: return {&RCC->APB1ENR, RCC_APB1ENR_TIM14EN}; + case Timer_Key::S_TIM15: return {&RCC->APB2ENR, RCC_APB2ENR_TIM15EN}; + case Timer_Key::S_TIM16: return {&RCC->APB2ENR, RCC_APB2ENR_TIM16EN}; + case Timer_Key::S_TIM17: return {&RCC->APB2ENR, RCC_APB2ENR_TIM17EN}; case Timer_Key::NUM_TIMERS: case Timer_Key::S_TIM_INVALID: assert(false); @@ -62,43 +82,161 @@ constexpr TIM_RCC_Enable getTimerRCC(Timer_Key t) { __builtin_unreachable(); } -//Get actual register value based on enum -constexpr volatile TIM_TypeDef* getTimerRegister(Timer_Key t) { - switch(t) { - case Timer_Key::S_TIM1: return TIM1; - case Timer_Key::S_TIM2: return TIM2; - case Timer_Key::S_TIM3: return TIM3; - case Timer_Key::S_TIM6: return TIM6; - case Timer_Key::S_TIM7: return TIM7; - case Timer_Key::S_TIM14: return TIM14; - case Timer_Key::S_TIM15: return TIM15; - case Timer_Key::S_TIM16: return TIM16; - case Timer_Key::S_TIM17: return TIM17; - case Timer_Key::NUM_TIMERS: - case Timer_Key::S_TIM_INVALID: - assert(false); - return nullptr; //Unreachable - } - __builtin_unreachable(); + +static inline SHAL_TIM_Status_Register getTimerStatusRegister(Timer_Key key){ + + SHAL_TIM_Status_Register res = {nullptr, TIM_SR_UIF}; + + volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; + + res.reg = &tim->SR; + return res; } -constexpr IRQn_Type getIRQn(Timer_Key t) { - switch(t) { - case Timer_Key::S_TIM1: return TIM1_BRK_UP_TRG_COM_IRQn; - case Timer_Key::S_TIM2: return TIM2_IRQn; - case Timer_Key::S_TIM3: return TIM3_IRQn; - case Timer_Key::S_TIM6: return TIM6_DAC_IRQn; - case Timer_Key::S_TIM7: return TIM7_IRQn; - case Timer_Key::S_TIM14: return TIM14_IRQn; - case Timer_Key::S_TIM15: return TIM15_IRQn; - case Timer_Key::S_TIM16: return TIM16_IRQn; - case Timer_Key::S_TIM17: return TIM17_IRQn; - case Timer_Key::NUM_TIMERS: - case Timer_Key::S_TIM_INVALID: - assert(false); - return TIM1_BRK_UP_TRG_COM_IRQn; //Unreachable +static inline SHAL_TIM_Control_Register_1 getTimerControlRegister1(Timer_Key key){ + + SHAL_TIM_Control_Register_1 res = {nullptr, TIM_CR1_CEN_Msk, + TIM_CR1_UDIS, + TIM_CR1_OPM, + TIM_CR1_CMS_Pos, + TIM_CR1_ARPE}; + + volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; + + res.reg = &tim->CR1; + return res; +} + +static inline SHAL_TIM_DMA_Interrupt_Enable_Register getTimerDMAInterruptEnableRegister(Timer_Key key){ + + SHAL_TIM_DMA_Interrupt_Enable_Register res = {nullptr, TIM_DIER_UIE}; + + volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; + + res.reg = &tim->DIER; + return res; +} + +static inline SHAL_TIM_Event_Generation_Register getTimerEventGenerationRegister(Timer_Key key){ + + SHAL_TIM_Event_Generation_Register res = {nullptr, TIM_EGR_UG}; + + volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; + + res.reg = &tim->EGR; + return res; +} + +static inline SHAL_TIM_Break_Dead_Time_Register getTimerBreakDeadTimeRegister(Timer_Key key) { + + SHAL_TIM_Break_Dead_Time_Register res = {nullptr, + TIM_BDTR_DTG_Pos, + TIM_BDTR_LOCK_Pos, + TIM_BDTR_OSSI, + TIM_BDTR_OSSR, + TIM_BDTR_BKE, + TIM_BDTR_BKP, + TIM_BDTR_AOE, + TIM_BDTR_MOE}; + + volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; + + res.reg = &tim->BDTR; + return res; +} + +static inline SHAL_TIM_Prescaler_Register getTimerPrescalerRegister(Timer_Key key){ + + SHAL_TIM_Prescaler_Register res = {nullptr, 1UL << 15}; + + volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; + + res.reg = &tim->PSC; + return res; +} + +static inline SHAL_TIM_Auto_Reload_Register getTimerAutoReloadRegister(Timer_Key key){ + + SHAL_TIM_Auto_Reload_Register res = {nullptr, 1UL << 15}; + + volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; + + res.reg = &tim->ARR; + return res; +} + +static inline SHAL_TIM_Capture_Compare_Register getTimerCaptureCompareRegister(Timer_Key key, SHAL_Timer_Channel channel){ + auto channel_num = static_cast(channel); + + volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; + + assert(channel_num <= TIM_INFO_TABLE[static_cast(key)].numChannels); + + switch(channel){ + case SHAL_Timer_Channel::CH1: return {&tim->CCR1,0}; + case SHAL_Timer_Channel::CH2: return {&tim->CCR2,0}; + case SHAL_Timer_Channel::CH3: return {&tim->CCR3,0}; + case SHAL_Timer_Channel::CH4: return {&tim->CCR4,0}; } - __builtin_unreachable(); +} + +static inline SHAL_TIM_Capture_Compare_Enable_Register getTimerCaptureCompareEnableRegister(Timer_Key key, SHAL_Timer_Channel channel){ + + uint8_t channel_stride = 3; + auto channel_num = static_cast(channel); + + auto output_enable = TIM_CCER_CC1E << (channel_stride * (channel_num - 1)); + auto output_polarity = TIM_CCER_CC1P << (channel_stride * channel_num); + auto output_complimentary_enable = TIM_CCER_CC1NE << (channel_stride * channel_num); + auto output_complimentary_polarity = TIM_CCER_CC1NP << (channel_stride * channel_num); + + SHAL_TIM_Capture_Compare_Enable_Register res = {nullptr, + output_enable, + output_polarity, + output_complimentary_enable, + output_complimentary_polarity, + }; + + volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; + + res.reg = &tim->CCER; + return res; +} + +static inline SHAL_TIM_Output_Capture_Compare_Mode_Register getTimerOutputCaptureCompareModeRegister(Timer_Key key, SHAL_Timer_Channel channel) { + SHAL_TIM_Output_Capture_Compare_Mode_Register res = { + nullptr, + TIM_CCMR1_CC1S_Pos, //Channel 1 Capture/Compare selection + TIM_CCMR1_OC1FE, //Channel 1 Fast enable + TIM_CCMR1_OC1PE, //Channel 1 Preload enable + TIM_CCMR1_OC1M_Pos, //Channel 1 Mode (OC1M) + TIM_CCMR1_OC1CE, //Channel 1 Clear enable + TIM_CCMR1_CC2S_Pos, //Channel 2 Capture/Compare selection + TIM_CCMR1_OC2FE, //Channel 2 Fast enable + TIM_CCMR1_OC2PE, //Channel 2 Preload enable + TIM_CCMR1_OC2M_Pos, //Channel 2 Mode (OC2M) + TIM_CCMR1_OC2CE //Channel 2 Clear enable + }; + + volatile TIM_TypeDef* tim = TIM_INFO_TABLE[static_cast(key)].timer; + uint8_t num_tim_channels = TIM_INFO_TABLE[static_cast(key)].numChannels; + + volatile uint32_t* reg = nullptr; + + uint8_t channelNum = static_cast(channel); + + assert(num_tim_channels >= channelNum); //Assert that we don't access undefined memory trying to initialize a non-existent channel + + if(channelNum >= 3){ + reg = &tim->CCMR2; + } + else{ + reg = &tim->CCMR1; + } + + res.reg = reg; + + return res; } diff --git a/SHAL/Include/Peripheral/Timer/SHAL_TIM.h b/SHAL/Include/Peripheral/Timer/SHAL_TIM.h index 41093a2..76c18d6 100644 --- a/SHAL/Include/Peripheral/Timer/SHAL_TIM.h +++ b/SHAL/Include/Peripheral/Timer/SHAL_TIM.h @@ -38,7 +38,10 @@ public: //Enable interrupts void enableInterrupt(); - void setPWMMode(SHAL_Timer_Channel channel, SHAL_TIM_Output_Compare_Mode outputCompareMode, SHAL_Timer_Channel_Main_Output_Mode mainOutputMode, SHAL_Timer_Channel_Complimentary_Output_Mode complimentaryOutputMode); + //Capture Compare Functions + void setCaptureCompareValue(SHAL_Timer_Channel channel, uint16_t value); + void enableChannel(SHAL_Timer_Channel channel, SHAL_Timer_Channel_Main_Output_Mode mainOutputMode, SHAL_Timer_Channel_Complimentary_Output_Mode complimentaryOutputMode); + void setOutputCompareMode(SHAL_Timer_Channel channel, SHAL_TIM_Output_Compare_Mode outputCompareMode); /// Set the duty cycle for PWM /// \param dutyCycle 10 * percentage (e.g. 500 = 50%) diff --git a/SHAL/Include/Peripheral/Timer/SHAL_TIM_TYPES.h b/SHAL/Include/Peripheral/Timer/SHAL_TIM_TYPES.h index 69dc9ce..a59ef83 100644 --- a/SHAL/Include/Peripheral/Timer/SHAL_TIM_TYPES.h +++ b/SHAL/Include/Peripheral/Timer/SHAL_TIM_TYPES.h @@ -7,6 +7,12 @@ #include "SHAL_CORE.h" +struct SHAL_TIM_Info{ + volatile TIM_TypeDef* timer; + IRQn_Type IRQn; + uint8_t numChannels; +}; + struct SHAL_TIM_RCC_Register{ volatile uint32_t* reg; uint32_t enable_mask; @@ -47,7 +53,7 @@ struct SHAL_TIM_Auto_Reload_Register { }; struct SHAL_TIM_Capture_Compare_Mode_Registers_Input { - volatile uint32_t* regs[2]; + volatile uint32_t* regs; uint32_t input_capture_1_filter_offset; uint32_t input_capture_1_prescaler_offset; uint32_t capture_compare_1_selection_offset; @@ -56,8 +62,8 @@ struct SHAL_TIM_Capture_Compare_Mode_Registers_Input { uint32_t capture_compare_2_selection_offset; }; -struct SHAL_TIM_Capture_Compare_Mode_Registers_Output { - volatile uint32_t* regs[2]; +struct SHAL_TIM_Output_Capture_Compare_Mode_Register { + volatile uint32_t* reg; uint32_t capture_compare_1_selection_offset; uint32_t output_compare_1_fast_enable_mask; uint32_t output_compare_1_preload_enable_mask; @@ -72,15 +78,27 @@ struct SHAL_TIM_Capture_Compare_Mode_Registers_Output { struct SHAL_TIM_Break_Dead_Time_Register { volatile uint32_t* reg; - uint32_t main_output_enable_mask; + uint32_t dead_time_offset; // [7:0] DTG - Dead-time generator setup + uint32_t lock_configuration_offset; // [9:8] LOCK - Lock configuration + uint32_t off_state_selection_idle_mask; // [10] OSSI - Off-state selection for idle mode + uint32_t off_state_selection_run_mask; // [11] OSSR - Off-state selection for run mode + uint32_t break_enable_mask; // [12] BKE - Break enable + uint32_t break_polarity_mask; // [13] BKP - Break polarity + uint32_t automatic_output_enable_mask; // [14] AOE - Automatic output enable + uint32_t main_output_enable_mask; // [15] MOE - Main output enable }; struct SHAL_TIM_Capture_Compare_Enable_Register { volatile uint32_t* reg; + uint32_t cc_output_enable_offset; + uint32_t cc_output_polarity_offset; + uint32_t cc_complimentary_output_enable_offset; + uint32_t cc_complimentary_output_polarity_offset; }; struct SHAL_TIM_Capture_Compare_Register { volatile uint32_t* reg; + uint32_t offset; }; @@ -102,12 +120,10 @@ enum class SHAL_TIM_Output_Compare_Preload : uint8_t { }; enum class SHAL_Timer_Channel : uint8_t { //TODO change if other timers have fewer than 6 channels - CH1 = 0, - CH2 = 1, - CH3 = 2, - CH4 = 3, - CH5 = 4, - CH6 = 5, + CH1 = 1, + CH2 = 2, + CH3 = 3, + CH4 = 4, }; enum class SHAL_Timer_Channel_Main_Output_Mode : uint8_t { diff --git a/SHAL/Include/Peripheral/UART/SHAL_UART_TYPES.h b/SHAL/Include/Peripheral/UART/SHAL_UART_TYPES.h index 4ecf8f4..e99657d 100644 --- a/SHAL/Include/Peripheral/UART/SHAL_UART_TYPES.h +++ b/SHAL/Include/Peripheral/UART/SHAL_UART_TYPES.h @@ -8,8 +8,6 @@ #include "SHAL_CORE.h" #include "SHAL_GPIO_REG.h" - - //Represents a pair of pins usable for USART Tx + Rx in combination, and their alternate function mapping struct SHAL_UART_Pair{ USART_TypeDef* USARTReg; diff --git a/SHAL/Include/SHAL.h b/SHAL/Include/SHAL.h index 751b34d..d1f4f7a 100644 --- a/SHAL/Include/SHAL.h +++ b/SHAL/Include/SHAL.h @@ -10,8 +10,8 @@ #include "SHAL_TIM.h" #include "SHAL_GPIO.h" -#include "SHAL_UART.h" -#include "SHAL_ADC.h" +//#include "SHAL_UART.h" +//#include "SHAL_ADC.h" diff --git a/SHAL/Src/STM32F0xx/Peripheral/ADC/SHAL_ADC.cpp b/SHAL/Src/STM32F0xx/Peripheral/ADC/SHAL_ADC.cpp index fe172a7..b896821 100644 --- a/SHAL/Src/STM32F0xx/Peripheral/ADC/SHAL_ADC.cpp +++ b/SHAL/Src/STM32F0xx/Peripheral/ADC/SHAL_ADC.cpp @@ -5,7 +5,7 @@ #include "SHAL_ADC.h" //Can hard code registers on F0 because all F0 devices have only one ADC, and use only one clock -SHAL_Result SHAL_ADC::init() { +SHAL_Result SHAL_ADC::init(ADC_Key key) { if(m_ADCKey == ADC_Key::INVALID || m_ADCKey == ADC_Key::NUM_ADC){ return SHAL_Result::ERROR; @@ -81,7 +81,7 @@ uint16_t SHAL_ADC::singleConvertSingle(SHAL_ADC_Channel channel, SHAL_ADC_Sample return result; } -void SHAL_ADC::multiConvertSingle(SHAL_ADC_Channel* channels, const int numChannels, uint16_t* result, SHAL_ADC_SampleTime time) { +SHAL_Result SHAL_ADC::multiConvertSingle(SHAL_ADC_Channel* channels, int numChannels, uint16_t* result, SHAL_ADC_SampleTime time) { ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey); ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_TSEN; //Enable VREFINT and Temp sensor in global ADC struct diff --git a/SHAL/Src/STM32F0xx/Peripheral/GPIO/SHAL_GPIO.cpp b/SHAL/Src/STM32F0xx/Peripheral/GPIO/SHAL_GPIO.cpp index 38f8f8a..239114d 100644 --- a/SHAL/Src/STM32F0xx/Peripheral/GPIO/SHAL_GPIO.cpp +++ b/SHAL/Src/STM32F0xx/Peripheral/GPIO/SHAL_GPIO.cpp @@ -3,7 +3,7 @@ // #include "SHAL_GPIO.h" -#include "SHAL_EXTI_CALLBACK.h" +//#include "SHAL_EXTI_CALLBACK.h" @@ -13,10 +13,9 @@ SHAL_GPIO::SHAL_GPIO() : m_GPIO_KEY(GPIO_Key::INVALID){ SHAL_GPIO::SHAL_GPIO(GPIO_Key key) : m_GPIO_KEY(key) { - volatile unsigned long* gpioEnable = getGPIORCCEnable(key).reg; - unsigned long gpioOffset = getGPIORCCEnable(key).offset; + auto GPIORCCEnable = getGPIORCCEnable(key); - *gpioEnable |= (1 << gpioOffset); //Set enable flag + SHAL_set_register_value(GPIORCCEnable.reg,GPIORCCEnable.mask); } void SHAL_GPIO::setLow() { @@ -54,12 +53,23 @@ void SHAL_GPIO::setAlternateFunction(GPIO_Alternate_Function AF) volatile { SHAL_set_bits(alternateFunctionReg.reg,4,static_cast(AF),alternateFunctionReg.offset); } -void SHAL_GPIO::setPinMode(PinMode mode) volatile { - SHAL_GPIO_Peripheral gpioPeripheral = getGPIORegister(m_GPIO_KEY); - gpioPeripheral.reg->MODER &= ~(0x03 << (2 * gpioPeripheral.global_offset)); //Clear any previous mode - gpioPeripheral.reg->MODER |= (static_cast(mode) << (2 * gpioPeripheral.global_offset)); //Set mode based on pinmode bit structure +SHAL_Result SHAL_GPIO::setPinMode(PinMode mode) volatile { + auto pinModeReg = getGPIOModeRegister(m_GPIO_KEY); + + /* + if(mode == PinMode::ANALOG_MODE && getGPIOPortInfo(m_GPIO_KEY).ADCChannel == SHAL_ADC_Channel::NO_ADC_MAPPING){ + char buff[100]; + sprintf(buff, "Error: GPIO pin %d has no valid ADC mapping\r\n", static_cast(m_GPIO_KEY)); + SHAL_UART2.sendString(buff); + return SHAL_Result::ERROR; + } + */ + SHAL_set_bits(pinModeReg.reg,2,static_cast(mode),pinModeReg.offset); //Set mode + + return SHAL_Result::OKAY; } +/* TODO Fix implementation for STM32F072 void SHAL_GPIO::useAsExternalInterrupt(TriggerMode mode, EXTICallback callback) { uint32_t gpioPin = getGPIORegister(m_GPIO_KEY).global_offset; //Use existing structs to get offset @@ -98,23 +108,25 @@ void SHAL_GPIO::useAsExternalInterrupt(TriggerMode mode, EXTICallback callback) __enable_irq(); //Enable IRQ just in case } +*/ +/* TODO reimplement uint16_t SHAL_GPIO::analogRead(SHAL_ADC_SampleTime sampleTime) { SHAL_ADC_Channel channel = getGPIOPortInfo(m_GPIO_KEY).ADCChannel; return GPIOManager::getGPIOADC().singleConvertSingle(channel,sampleTime); } - +*/ SHAL_GPIO& GPIOManager::get(GPIO_Key key) { unsigned int gpioPort = getGPIOPortNumber(key); - unsigned long gpioPin = getGPIORegister(key).global_offset; //Use existing structs to get offset + uint8_t gpioPin = getGPIOPinNumber(key); if (m_gpios[gpioPort][gpioPin].m_GPIO_KEY == GPIO_Key::INVALID){ m_gpios[gpioPort][gpioPin] = SHAL_GPIO(key); } return m_gpios[gpioPort][gpioPin]; -} \ No newline at end of file +} diff --git a/SHAL/Src/STM32F0xx/Peripheral/I2C/SHAL_I2C.cpp b/SHAL/Src/STM32F0xx/Peripheral/I2C/SHAL_I2C.cpp index b23a52f..07bd3e3 100644 --- a/SHAL/Src/STM32F0xx/Peripheral/I2C/SHAL_I2C.cpp +++ b/SHAL/Src/STM32F0xx/Peripheral/I2C/SHAL_I2C.cpp @@ -95,8 +95,6 @@ void SHAL_I2C::masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t wri //Read phase if (readLen > 0) { - SHAL_UART2.sendString("Read initiated\r\n"); - I2CPeripheral->CR2 &= ~(I2C_CR2_NBYTES | I2C_CR2_SADD | I2C_CR2_RD_WRN); I2CPeripheral->CR2 |= (addr << 1) | I2C_CR2_RD_WRN | diff --git a/SHAL/Src/STM32F0xx/Peripheral/Timer/SHAL_TIM.cpp b/SHAL/Src/STM32F0xx/Peripheral/Timer/SHAL_TIM.cpp index 24b39b2..567c638 100644 --- a/SHAL/Src/STM32F0xx/Peripheral/Timer/SHAL_TIM.cpp +++ b/SHAL/Src/STM32F0xx/Peripheral/Timer/SHAL_TIM.cpp @@ -5,45 +5,96 @@ #include "SHAL_TIM.h" #include -Timer::Timer(Timer_Key t) : TIMER_KEY(t){ +Timer::Timer(Timer_Key t) : m_key(t){ } -Timer::Timer() : TIMER_KEY(Timer_Key::S_TIM_INVALID){ +Timer::Timer() : m_key(Timer_Key::S_TIM_INVALID){ } void Timer::start() { - getTimerRegister(TIMER_KEY)->CR1 |= TIM_CR1_CEN; - getTimerRegister(TIMER_KEY)->EGR |= TIM_EGR_UG; //load prescaler reg and ARR + + auto control_reg = getTimerControlRegister1(m_key); + auto event_generation_reg = getTimerEventGenerationRegister(m_key); + auto status_reg = getTimerStatusRegister(m_key); + auto break_time_dead_reg = getTimerBreakDeadTimeRegister(m_key); + + auto rcc_reg = getTimerRCC(m_key); + + SHAL_apply_bitmask(control_reg.reg, control_reg.counter_enable_mask); //Enable counter + SHAL_apply_bitmask(control_reg.reg, control_reg.auto_reload_preload_enable_mask); //Preload enable (buffer) + SHAL_apply_bitmask(event_generation_reg.reg, event_generation_reg.update_generation_mask); + + SHAL_clear_bitmask(status_reg.reg,status_reg.update_interrupt_flag_mask); + + SHAL_apply_bitmask(rcc_reg.reg,rcc_reg.enable_mask); + SHAL_apply_bitmask(break_time_dead_reg.reg,break_time_dead_reg.main_output_enable_mask); + enableInterrupt(); } void Timer::stop() { - getTimerRegister(TIMER_KEY)->CR1 &= ~TIM_CR1_CEN; + auto rcc_reg = getTimerRCC(m_key); + + SHAL_clear_bitmask(rcc_reg.reg,rcc_reg.enable_mask); } void Timer::setPrescaler(uint16_t presc) { - getTimerRegister(TIMER_KEY)->PSC = presc; + getTimerRegister(m_key)->PSC = presc; } void Timer::setARR(uint16_t arr) { - getTimerRegister(TIMER_KEY)->ARR = arr; + getTimerRegister(m_key)->ARR = arr; } void Timer::enableInterrupt() { - getTimerRegister(TIMER_KEY)->DIER |= TIM_DIER_UIE; - NVIC_EnableIRQ(getIRQn(TIMER_KEY)); + getTimerRegister(m_key)->DIER |= TIM_DIER_UIE; + NVIC_EnableIRQ(getIRQn(m_key)); } -void Timer::init(uint32_t prescaler, uint32_t autoReload) { - TIM_RCC_Enable rcc = getTimerRCC(TIMER_KEY); - *rcc.busEnableReg |= (1 << rcc.offset); +void Timer::init(uint16_t prescaler, uint16_t autoReload) { + SHAL_TIM_RCC_Register rcc = getTimerRCC(m_key); + + SHAL_apply_bitmask(rcc.reg,rcc.enable_mask); setPrescaler(prescaler); setARR(autoReload); } +void Timer::setOutputCompareMode(SHAL_Timer_Channel channel, SHAL_TIM_Output_Compare_Mode outputCompareMode) { + + auto channelNum = static_cast(channel); + + auto CCMR = getTimerOutputCaptureCompareModeRegister(m_key, channel); + + uint32_t OCMR_Offset = channelNum % 2 == 1 ? CCMR.output_compare_1_mode_offset : CCMR.output_compare_2_mode_offset; + + SHAL_set_bits(CCMR.reg,3,static_cast(outputCompareMode),OCMR_Offset); +} + +void Timer::enableChannel(SHAL_Timer_Channel channel, SHAL_Timer_Channel_Main_Output_Mode mainOutputMode, + SHAL_Timer_Channel_Complimentary_Output_Mode complimentaryOutputMode) { + + SHAL_TIM_Capture_Compare_Enable_Register captureCompareEnableReg = getTimerCaptureCompareEnableRegister(m_key, channel); + + uint16_t setValue = 0; //Value to set the register as + auto channelNum = static_cast(channel); + + uint8_t channelStride = 4; //4 bits per field + + setValue |= (static_cast(mainOutputMode) << ((channelNum - 1) * channelStride)); //xxBB shifted by c - 1 + setValue |= (static_cast(complimentaryOutputMode) << (((channelNum - 1) * channelStride) + 2)); //BBxx shifted by c - 1 + + SHAL_set_bits(captureCompareEnableReg.reg,16,setValue,0); +} + +void Timer::setCaptureCompareValue(SHAL_Timer_Channel channel, uint16_t value) { + auto captureCompareReg = getTimerCaptureCompareRegister(m_key,channel); + + SHAL_set_bits(captureCompareReg.reg,16,value,0); +} + Timer &TimerManager::get(Timer_Key timer_key) { @@ -53,11 +104,9 @@ Timer &TimerManager::get(Timer_Key timer_key) { Timer& selected = timers[static_cast(timer_key)]; //Timer queried is not initialized yet (defaults to invalid) - if(selected.TIMER_KEY == Timer_Key::S_TIM_INVALID){ + if(selected.m_key == Timer_Key::S_TIM_INVALID){ timers[static_cast(timer_key)] = Timer(timer_key); //Initialize TIMER_KEY } return timers[static_cast(timer_key)]; -} - - +} \ No newline at end of file diff --git a/SHAL/Src/STM32L4xx/Peripheral/ADC/SHAL_ADC.cpp b/SHAL/Src/STM32L4xx/Peripheral/ADC/SHAL_ADC.cpp index 088a0f6..713e449 100644 --- a/SHAL/Src/STM32L4xx/Peripheral/ADC/SHAL_ADC.cpp +++ b/SHAL/Src/STM32L4xx/Peripheral/ADC/SHAL_ADC.cpp @@ -112,7 +112,7 @@ uint16_t SHAL_ADC::singleConvertSingle(SHAL_ADC_Channel channel, SHAL_ADC_Sample return result; } -SHAL_Result SHAL_ADC::multiConvertSingle(SHAL_ADC_Channel* channels, const int numChannels, uint16_t* result, SHAL_ADC_SampleTime time) { +SHAL_Result SHAL_ADC::multiConvertSingle(SHAL_ADC_Channel* channels, int numChannels, uint16_t* result, SHAL_ADC_SampleTime time) { auto data_reg = getADCDataReg(m_ADCKey); //Where our output will be stored setADCSequenceAmount(numChannels); //Convert the correct amount of channels diff --git a/SHAL/Src/STM32L4xx/Peripheral/I2C/SHAL_I2C.cpp b/SHAL/Src/STM32L4xx/Peripheral/I2C/SHAL_I2C.cpp index b23a52f..798cc7e 100644 --- a/SHAL/Src/STM32L4xx/Peripheral/I2C/SHAL_I2C.cpp +++ b/SHAL/Src/STM32L4xx/Peripheral/I2C/SHAL_I2C.cpp @@ -79,7 +79,6 @@ void SHAL_I2C::masterWriteRead(uint8_t addr,const uint8_t* writeData, size_t wri for (size_t i = 0; i < writeLen; i++) { if(!SHAL_WAIT_FOR_CONDITION_MS((I2CPeripheral->ISR & I2C_ISR_TXIS) != 0, 100)){ - SHAL_UART2.sendString("I2C timed out waiting for TX\r\n"); return; } I2CPeripheral->TXDR = writeData[i]; diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 04293d5..58c9e98 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -1,264 +1,19 @@ #include #include "SHAL.h" - -#define NUM_CHANNELS 6 - -// Physical order on right-side header: A0, A1, A3, A4, A5, A6, A7 -SHAL_ADC_Channel channels[NUM_CHANNELS] = { - SHAL_ADC_Channel::CH5, - SHAL_ADC_Channel::CH6, - SHAL_ADC_Channel::CH8, - SHAL_ADC_Channel::CH9, - SHAL_ADC_Channel::CH10, - SHAL_ADC_Channel::CH12, -}; - -bool isDeviceOn = false; -bool shouldToggleDeviceState = true; -bool shouldCheckSensorThresholds = true; - -uint16_t vals[NUM_CHANNELS] = {0,0,0,0,0,0}; -uint8_t currentSensor = 0; - -bool isAlarmBeeping = false; - -uint16_t sensorThresholds[NUM_CHANNELS] = {0,0,0,0,0,0}; - -int buzzer_beepCount = 0; -bool isBeepingForCalibration = false; - -bool prevIsCalibrateButtonHigh = false; - -int cyclesPerPrint = 2; -int currentCycle = 0; - -bool areSensorRequirementsMetCurrent = false; -bool areSensorRequirementsMetPrevious = false; - -void getSensorData(){ - - vals[currentSensor] = SHAL_ADC1.singleConvertSingle(channels[currentSensor]); - - if(currentSensor == (NUM_CHANNELS - 1) && currentCycle == cyclesPerPrint - 1){ - char buff[125]; - // Print in the same order as the channels[] array (physical order) - sprintf(buff, "A0:%u,A1:%u,A3:%u,A4:%u,A5:%u,A6:%u\r\n", - vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]); - SHAL_UART2.sendString(buff); - } - - currentSensor = (currentSensor + 1) % NUM_CHANNELS; - currentCycle = (currentCycle + 1) % cyclesPerPrint; -} - -void startBeeping(){ - - SHAL_TIM6.setPrescaler(4000); - SHAL_TIM6.setARR(200); - - SHAL_TIM6.start(); -} - -void stopBeeping(){ - SHAL_TIM1.stop(); - SHAL_TIM6.stop(); - isAlarmBeeping = false; - isBeepingForCalibration = false; -} - -void checkSensorThresholds(){ - - bool localFlag = true; - - for(int i = 0; i < NUM_CHANNELS; i++){ - if(vals[i] < sensorThresholds[i]){ - areSensorRequirementsMetCurrent = false; //Conditions not met - localFlag = false; - break; - } - } - if(localFlag){ - areSensorRequirementsMetCurrent = true; - } - - if(areSensorRequirementsMetCurrent){ - if(!areSensorRequirementsMetPrevious){ - SHAL_TIM1.stop(); - SHAL_TIM6.stop(); - SHAL_TIM15.stop(); - PIN(A9).setLow(); - stopBeeping(); - } - } - else{ - if(areSensorRequirementsMetPrevious){ - SHAL_TIM15.start(); - PIN(A9).setHigh(); - } - } - areSensorRequirementsMetPrevious = areSensorRequirementsMetCurrent; -} - -void calibrateThresholds(){ - - // Read every channel once and set threshold to 80% of reading - for(int i = 0; i < NUM_CHANNELS; i++){ - uint16_t sensorVal = (vals[i] * 3) / 5; - - if(sensorVal < 50){ - sensorVal = 0; - } - else{ - sensorVal = sensorVal - 50; - } - sensorThresholds[i] = sensorVal; - } - - char buff[125]; - // Print in the same order as the channels[] array (physical order) - sprintf(buff, "Thresholds calibrated to: A0:%u,A1:%u,A3:%u,A4:%u,A5:%u,A6:%u\r\n", - sensorThresholds[0], sensorThresholds[1], sensorThresholds[2], sensorThresholds[3], sensorThresholds[4], sensorThresholds[5]); - SHAL_UART2.sendString(buff); -} - -void PWMToggle(){ - - //Flash light - PIN(A9).toggle(); - - SHAL_TIM15.stop(); //Stop timer for allowed time off sensors - - if(isBeepingForCalibration && buzzer_beepCount > 2){ - isBeepingForCalibration = false; - buzzer_beepCount = 0; - SHAL_TIM6.stop(); //Reset timer 6 - SHAL_TIM1.stop(); //Stop buzzer - - SHAL_TIM6.setPrescaler(4000); - SHAL_TIM6.setARR(400); - } - - if(!isAlarmBeeping){ - SHAL_TIM1.start(); - buzzer_beepCount++; - } - else{ - SHAL_TIM1.stop(); - } - isAlarmBeeping = !isAlarmBeeping; -} - -void buttonHoldCallback(){ - - shouldCheckSensorThresholds = false; //Dont check sensor thresholds yet, ensure that calibration beep happens - - SHAL_TIM7.stop(); //Stop this timer - - SHAL_TIM2.stop(); //Stop reading from ADC - - buzzer_beepCount = 0; - isBeepingForCalibration = true; - - SHAL_TIM6.init(4000,50); - SHAL_TIM6.start(); - - calibrateThresholds(); - SHAL_TIM1.start(); - - SHAL_TIM2.start(); //Restart value checks - - shouldToggleDeviceState = false; - shouldCheckSensorThresholds = true; -} - int main() { SHAL_init(); - //SHAL_UART2.init(UART_Pair_Key::Tx2A2_Rx2A3); - //SHAL_UART2.begin(115200); + PIN(A8).setPinMode(PinMode::ALTERNATE_FUNCTION_MODE); - PIN(A0).setPinMode(PinMode::ANALOG_MODE); - PIN(A1).setPinMode(PinMode::ANALOG_MODE); - PIN(A3).setPinMode(PinMode::ANALOG_MODE); - PIN(A4).setPinMode(PinMode::ANALOG_MODE); - PIN(A5).setPinMode(PinMode::ANALOG_MODE); - PIN(A6).setPinMode(PinMode::ANALOG_MODE); - PIN(A7).setPinMode(PinMode::ANALOG_MODE); + PIN(A8).setAlternateFunction(GPIO_Alternate_Function::AF2); - PIN(B6).setPinMode(PinMode::INPUT_MODE); - PIN(A9).setPinMode(PinMode::OUTPUT_MODE); - PIN(B0).setAlternateFunction(GPIO_Alternate_Function_Mapping::B0_TIM1CH2N); + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; - PIN(A8).setPinMode(PinMode::OUTPUT_MODE); - PIN(A8).setInternalResistor(InternalResistorType::NO_PULL); - - SHAL_TIM2.init(4000,200); - - SHAL_TIM2.setCallbackFunc(getSensorData); - SHAL_TIM2.enableInterrupt(); - SHAL_TIM2.start(); - - SHAL_TIM1.init(0,2400); //PWM signal - SHAL_TIM1.setPWMMode(SHAL_Timer_Channel::CH2,SHAL_TIM_Output_Compare_Mode::PWMMode1,SHAL_Timer_Channel_Main_Output_Mode::Polarity_Normal,SHAL_Timer_Channel_Complimentary_Output_Mode::Polarity_Reversed); - SHAL_TIM1.setPWMDutyCycle(900); - - SHAL_TIM6.init(4000,500); //PWM switcher - SHAL_TIM6.setCallbackFunc(PWMToggle); - SHAL_TIM6.enableInterrupt(); - - SHAL_TIM7.init(4000,3000); //Calibrate timer - SHAL_TIM7.setCallbackFunc(buttonHoldCallback); - SHAL_TIM7.enableInterrupt(); - - SHAL_TIM15.init(4000,5000); //5 seconds - SHAL_TIM15.setCallbackFunc(startBeeping); - SHAL_TIM15.enableInterrupt(); - - - SHAL_UART2.sendString("Hello3\r\n"); - - while (true) { //TODO set to use button for simulating off sensor, uncomment for real functionality - - if(PIN(B6).digitalRead() != 1){ - - if(prevIsCalibrateButtonHigh){ - SHAL_TIM7.start(); - } - prevIsCalibrateButtonHigh = false; - - } - else{ - if(!prevIsCalibrateButtonHigh){ - if(shouldToggleDeviceState){ - if(!isDeviceOn){ //Turn device on - PIN(A8).setHigh(); - isDeviceOn = true; - } - else{ //Turn device off - PIN(A8).setLow(); - PIN(A9).setLow(); - isDeviceOn = false; - - areSensorRequirementsMetCurrent = true; - areSensorRequirementsMetPrevious = true; - - SHAL_TIM15.stop(); - stopBeeping(); - } - - } - - shouldToggleDeviceState = true; - - SHAL_TIM7.stop(); - } - prevIsCalibrateButtonHigh = true; - } - - if(isDeviceOn && shouldCheckSensorThresholds){ - checkSensorThresholds(); - } - } + SHAL_TIM1.init(48,100); + SHAL_TIM1.setOutputCompareMode(SHAL_Timer_Channel::CH1,SHAL_TIM_Output_Compare_Mode::PWMMode1); + SHAL_TIM1.enableChannel(SHAL_Timer_Channel::CH1,SHAL_Timer_Channel_Main_Output_Mode::Polarity_Reversed,SHAL_Timer_Channel_Complimentary_Output_Mode::Disabled); + SHAL_TIM1.setCaptureCompareValue(SHAL_Timer_Channel::CH1, 5); + SHAL_TIM1.start(); } diff --git a/gcc-arm-none-eabi.cmake b/gcc-arm-none-eabi.cmake index 66b0179..28fb92d 100644 --- a/gcc-arm-none-eabi.cmake +++ b/gcc-arm-none-eabi.cmake @@ -10,7 +10,7 @@ set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PREFIX}gcc) set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy) set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size) -set(COMMON_FLAGS "-mcpu=cortex-m4 -mthumb -fdata-sections -ffunction-sections") +set(COMMON_FLAGS "-mcpu=cortex-m0 -mthumb -fdata-sections -ffunction-sections") set(CMAKE_C_FLAGS_INIT "${COMMON_FLAGS} --specs=nano.specs") set(CMAKE_CXX_FLAGS_INIT "${COMMON_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics --specs=nano.specs") diff --git a/shmingo-HAL.bin b/shmingo-HAL.bin new file mode 100644 index 0000000..38b0f40 Binary files /dev/null and b/shmingo-HAL.bin differ diff --git a/shmingo-HAL.elf b/shmingo-HAL.elf new file mode 100644 index 0000000..9b87b87 Binary files /dev/null and b/shmingo-HAL.elf differ diff --git a/shmingo-HAL.hex b/shmingo-HAL.hex new file mode 100644 index 0000000..04e0ac4 --- /dev/null +++ b/shmingo-HAL.hex @@ -0,0 +1,1265 @@ +:020000040800F2 +:1000000000C00020212A0008712A0008712A000877 +:10001000712A0008712A0008712A000800000000F7 +:10002000000000000000000000000000712A00082D +:10003000712A000800000000712A0008712A0008D7 +:10004000712A0008712A0008712A0008712A000824 +:10005000712A0008712A0008A9040008D1040008C8 +:10006000F90400082105000849050008712A000864 +:10007000712A0008712A0008712A0008712A0008F4 +:10008000712A0008712A0008712A0008712A0008E4 +:10009000712A0008712A0008712A0008712A0008D4 +:1000A000A51E0008E51E0008712A0008712A000834 +:1000B000DD1D00080000000000000000712A00089B +:1000C000712A00080000000000000000712A0008EA +:1000D00000000000712A0008712A000800000000DA +:1000E000712A0008712A00080000000000000000CA +:1000F0000000000000000000000000000000000000 +:10010000000000000000000000000000712A00084C +:1001100000000000000000001D1E00085D1E000819 +:10012000712A0008712A0008712A0008712A000843 +:10013000712A00080000000000000000000000001C +:10014000712A0008712A0008712A0008712A000823 +:10015000712A0008712A0008712A0008712A000813 +:10016000712A0008712A0008712A000800000000A6 +:10017000712A0008712A0008000000000000000039 +:0C018000712A0008712A0008712A00088A +:10019000A3F5803A704700BF174B002B08BF134BE5 +:1001A0009D46FFF7F5FF00218B460F461348144A82 +:1001B000121A02F085FE0E4B002B00D098470D4B13 +:1001C000002B00D098470020002104000D000D48AE +:1001D000002802D00C48AFF3008002F023FF20007B +:1001E000290002F0EFFA02F069FC00BF00000800ED +:1001F000000000000000000000000000940000204B +:10020000C80200200000000000000000284E000886 +:10021000000000209400002094000020C80200206C +:1002200001F0FF01102A2BDB10F0070F08D010F8A7 +:10023000013B013A8B422DD010F0070F42B3F6D1AB +:10024000F0B441EA012141EA014122F007047FF0C4 +:1002500000070023F0E80256083C85EA010586EA1B +:10026000010685FA47F5A3FA87F586FA47F6A5FA57 +:1002700087F68EB9EED1F0BC01F0FF0102F0070263 +:1002800032B110F8013B013A83EA010313B1F8D10E +:100290000020704701387047002D06BF35460338EF +:1002A000073815F0010F07D1013015F4807F02BF28 +:1002B000013015F4C03F0130F0BC0138704700BF79 +:1002C0000348044B834202D0034B03B118477047E5 +:1002D0009400002094000020000000000548064B18 +:1002E0001B1AD90F01EBA301491002D0034B03B134 +:1002F0001847704794000020940000200000000080 +:1003000010B5064C237843B9FFF7DAFF044B13B15D +:100310000448AFF300800123237010BD9400002037 +:10032000000000007044000808B5054B1BB10549EA +:100330000548AFF30080BDE80840FFF7CFBF00BF1E +:10034000000000009800002070440008F8B5184B29 +:100350001E6816F001060ED101221A600F24154DF9 +:1003600004E0284600F07CFE013C0135002CF8DA60 +:10037000114F002E0FDA114B1B6813F0010F0DD037 +:10038000F8BD284600F06CFE013C0135002CF8DA7F +:10039000013E1037EDE73D460F24F7E7074B0122FA +:1003A0001A60002000F046FD0278054B1A70E7E75E +:1003B000B4000020BC000020CC000020B0000020D1 +:1003C000B80000204FF0E02300221A616FF07F4157 +:1003D00059619A6105221A617047000010B5FFF754 +:1003E000F1FF002434B1002000F024FD0278064B18 +:1003F0001A7010BD204600F01DFD214600F028FBBC +:100400000134E4B2EEE700BFB8000020134B1B68D4 +:10041000134AA2FB03239B0C03FB00F04FF0E023E5 +:10042000996988420AD80B1A23F07F43884209D879 +:100430004FF0E02292699A42FAD870470B1A03F102 +:100440008073F1E74FF0E02292698A42FAD94FF0C7 +:10045000E02292699A42FAD8704700BF100000204B +:1004600083DE1B4310B504E04FF47A70FFF7CEFF34 +:100470002046441E0028F7D110BD000010B588B0FA +:1004800002680649684602F0B3FC022001F0A8FEAB +:10049000694601F099FE08B010BD00BFB4460008DF +:1004A00008B5FFF753FF08BD08B5074B5B6913F0AC +:1004B000010F08D0044A536943F001035361034B11 +:1004C0001B6803B1984708BD00040140DC00002010 +:1004D00008B5074B5B6913F0020F08D0044A536953 +:1004E00043F002035361034B5B6803B1984708BDB7 +:1004F00000040140DC00002008B5074B5B6913F0E5 +:10050000040F08D0044A536943F004035361034BBA +:100510009B6803B1984708BD00040140DC0000203F +:1005200008B5074B5B6913F0080F08D0044A5369FC +:1005300043F008035361034BDB6803B1984708BDE0 +:1005400000040140DC00002008B5074B5B6913F094 +:10055000100F08D0044A536943F010035361034B52 +:100560001B6903B1984708BD00040140DC0000206E +:1005700010B5052401E00134E4B2092C10D8094B70 +:100580005A690123A3401A42F5D0064A51690B4328 +:100590005361054B53F82430002BECD09847EAE721 +:1005A00010BD00BF00040140DC00002010B50A248B +:1005B00002E098470134E4B20F2C0FD8084B5A6977 +:1005C0000123A3401A42F5D0054A51690B435361F8 +:1005D000044B53F82430002BEBD1EBE710BD00BFE8 +:1005E00000040140DC00002000F00F00014B43F844 +:1005F00020107047DC00002038B5044603E00120DD +:10060000FFF704FF29464D1E31B123681A6823699C +:100610001A42F4D0012000E0002038BD38B504466D +:1006200003E00120FFF7F2FE29464D1E31B1236899 +:100630001A6863681A42F4D0012000E0002038BD37 +:1006400038B5044603E00120FFF7E0FE29464D1EC1 +:1006500031B123681A6863681A42F4D0012000E0BF +:10066000002038BD38B5044603E00120FFF7CEFE78 +:1006700029464D1E31B123681A68A3681A42F4D086 +:10068000012000E0002038BD38B5044603E0012019 +:10069000FFF7E8FE29464D1E31B123681A68236929 +:1006A0001A42F4D1012000E0002038BD38B50446DC +:1006B00003E00120FFF7D6FE29464D1E31B1236825 +:1006C0001A68E3681A42F4D0012000E0002038BD27 +:1006D00038B5044603E00120FFF7C4FE29464D1E4D +:1006E00041B123681A686368E1680B431A42F2D18A +:1006F000012000E0002038BD10B58AB00DF1040CD7 +:100700000F4C0FCCACE80F000FCCACE80F00236807 +:10071000CCF800300B4B0193083B9A6822F0005252 +:100720009A609A6822F080529A609A6842F08052E9 +:100730009A603220FFF76AFE00200AB010BD00BFA9 +:100740008C4400080800045010B48BB00DF1040C68 +:100750000C4C0FCCACE80F000FCCACE80F002368BA +:10076000CCF80030084B0193083B9A6822F0040251 +:100770009A609A6842F004029A6000200BB010BCA4 +:10078000704700BF8C440008080004500378FF2B1A +:1007900003D0012B03D001207047002070470020B8 +:1007A0007047000010B58EB0FFF7F0FF78B3334C00 +:1007B0000DF1140CA646BEE80F00ACE80F00BEE831 +:1007C0000F00ACE80F00DEF80030CCF800302C4B06 +:1007D0000593EE4604F1240CBCE80F00AEE80F00D0 +:1007E000DCF80030CEF80030264B0093642105A8D9 +:1007F000FFF74AFF00283BD0059B1968069A114273 +:1008000038D11A68089B1A420AD0012006E002205B +:1008100001F0E6FC1C4901F0D7FC01200EB010BD30 +:10082000009A1368039923EA01031360009A13687E +:1008300003990B431360059A1368069923EA010391 +:100840001360059A136806990B4313606421684688 +:10085000FFF72CFF80B1009A1368039923EA010384 +:100860001360009A136803990B4313600020D5E7C7 +:100870000120D3E70020D1E70120CFE78C44000816 +:100880000800045000000450C046000810B58AB0AB +:10089000FFF77CFF002835D00DF1040C1B4C0FCC6A +:1008A000ACE80F000FCCACE80F002368CCF80030A8 +:1008B000174B0193083B9B6813F0040F08D0154BAE +:1008C0009A6822F010029A609A6803990A439A6023 +:1008D000104B9B6813F0010F02D100200AB010BD2D +:1008E0000C4B9A68049922EA01029A609A6804996A +:1008F0000A439A604FF4FA7101A8FFF7E9FE18B1B4 +:100900000020EBE70120E9E70120E7E78C4400083D +:10091000080004500000045010B58AB086460DF15E +:10092000040C244C0FCCACE80F000FCCACE80F004B +:100930002368CCF80030204B01937046FFF7A6FFE8 +:1009400018B1012420460AB010BD04464FF47A7055 +:10095000FFF75CFD019A1168029B0498034319425A +:1009600025D11368099923EA01031360019A1368DA +:10097000059923EA01031360019A136805990B4353 +:100980001360019B1A68059B1A4201D10124D9E723 +:100990004FF4FA7101A8FFF72FFE08B90124D1E73F +:1009A000022001F01DFC054901F00EFCCAE70124FC +:1009B000C8E700BF8C44000808000450DC4600086B +:1009C00030B587B00D46FFF7E1FEB0B10DF1040C74 +:1009D0000B4C0FCCACE80F002368CCF80030094B6F +:1009E00001930C3BDA6822F01802DA60DA6842EA16 +:1009F000C502DA60002007B030BD0120FBE700BF70 +:100A0000C44400080C00045030B587B00D46FFF711 +:100A1000BDFEB0B10DF1040C0B4C0FCCACE80F00D7 +:100A20002368CCF80030094B01930C3BDA6822F0C4 +:100A30002002DA60DA6842EA4512DA60002007B084 +:100A400030BD0120FBE700BFC44400080C00045087 +:100A500030B585B004460170FFF798FE002838D005 +:100A6000294B03F14C0292E8030004AA02E90300B7 +:100A7000264AD16C21F40051D16402980168039D8B +:100A800029430160543393E80300CDE90001D2F813 +:100A9000883023F04053C2F8883000990B680198E1 +:100AA0000322824013430B602046FFF725FE2046B9 +:100AB000FFF732FFB8B92046FFF774FE0546D0B9FC +:100AC00000212046FFF7A0FF00212046FFF778FF16 +:100AD00006E0022001F084FB0D4901F075FB0125C1 +:100AE000284605B030BD022001F07AFB094901F02B +:100AF0006BFB0125F4E7022001F072FB064901F0CF +:100B000063FB0125ECE700BF8C44000800100240A5 +:100B1000F0460008FC4600081447000810B582B0F3 +:100B20000C46FFF733FE80B18CB10020009001909D +:100B3000084B0093303B1A6B22F00F021A631A6BBA +:100B4000013C22431A6302B010BD0120FBE70120E3 +:100B5000F9E700BF3000045030B58DB00C461546A3 +:100B6000FFF714FE002836D02C22002101A802F045 +:100B7000A7F9062308930C23099312230A93182339 +:100B80000B93164B01930433029304330393043302 +:100B900004936A1C124BA3FB02139B08194603EB38 +:100BA0008303D31A0CAA02EB810252F82C2C0633D1 +:100BB0000CA901EB830353F82C0C1F21814013680F +:100BC00023EA010313601368E4B2844023431360F3 +:100BD00000200DB030BD0120FBE700BF3000045005 +:100BE000CDCCCCCC2DE9F04190B005460F469046D7 +:100BF00000230E934FF6FF730F93514B0E93514CFE +:100C00000DF1240C04F1240EBEE80F00ACE80F0037 +:100C1000DEF80030CCF800304B4E09960DF1100E86 +:100C200004F1380CBCE80F00AEE80F00DCF800302F +:100C3000CEF80030454B0493F36823F40053F3607F +:100C4000FBB2092B6DD803EB4303414A0292039395 +:100C50005AB111680720984021EA0001116011681B +:100C60005FFA88F69E4031431160002239462846DB +:100C7000FFF772FF01212846FFF750FF012856D0E9 +:100C80002846FFF78FFD002855D1099A13680B9964 +:100C900023EA01031360099A13680B990B4313604D +:100CA000099A13680A9923EA01031360099A1368E1 +:100CB0000A990B4313600D9B4BB109990A6822EA0C +:100CC00003030B60099A13680D990B4313601E4BC5 +:100CD0001B6C9BB2ADF80630BDF806302846FFF716 +:100CE00033FD4FF4FA6109A8FFF798FC28B3164BBF +:100CF000186C80B2099A13680A9923EA01031360F9 +:100D0000099A13680A990B431360099A13680B999F +:100D100023EA01031360099A13680B990B431360CC +:100D200006E0FBB20A3B03EB43030A4A8EE70020CE +:100D300010B0BDE8F0810020FAE70020F8E700BF1E +:100D4000400004508C440008000004500C00045083 +:100D500014000450180004502DE9F0478AB0804672 +:100D60008A4617469946002608964FF6FF73099360 +:100D7000284B08931146FFF7D1FE17E0CCB20A3C8E +:100D800004EB4404244D019502945DB12B680720C7 +:100D9000A04023EA00032B602B681298C0B2A04049 +:100DA00003432B604046FFF7D7FE0136BE4209DA07 +:100DB00032465AF82610CBB2092BDFD803EB430496 +:100DC000164DE0E74046FFF7BFFC03AC144D0FCDD6 +:100DD0000FC42B682360134B03930024BC420BDA2F +:100DE0004FF4FA7103A8FFF72BFC68B10D4B1B6C95 +:100DF00029F814300134F1E74FF4FA7103A8FFF732 +:100E000031FC28B1002000E001200AB0BDE8F087E5 +:100E10000120FAE740000450180004501400045068 +:100E2000B044000800000450014B1844704700BF54 +:100E300004000020002801DD02487047014B1844DF +:100E4000704700BF04000020F8B5184B1E6816F06C +:100E500001060ED101221A600F24154D04E0284628 +:100E600000F0FEF8013C0135002CF8DA114F002E9D +:100E700018DA114B1B6813F0010F08D10E4B012239 +:100E80001A600020FFF7D6FF02780C4B1A70F8BDED +:100E9000284600F0E5F8013C0135002CF8DA013E67 +:100EA0001037E4E73D460F24F7E700BFB400002009 +:100EB000BC000020CC000020B0000020B8000020C2 +:100EC00008B5FFF7C1FF08BD0346192900F2978056 +:100ED000DFE801F00D17232935414D59656B717716 +:100EE0007D83898F121D952F3B47535F9595002277 +:100EF00002700522426086E0002202700F224260EA +:100F000081E0424A92E8030083E803007BE0404A24 +:100F100092E8030083E8030075E03E4A92E803008C +:100F200083E803006FE03C4A92E8030083E8030093 +:100F300069E03A4A92E8030083E8030063E0384A34 +:100F400092E8030083E803005DE0364A92E803007C +:100F500083E8030057E0344A92E8030083E8030083 +:100F600051E0324A92E8030083E803004BE0304A44 +:100F700092E8030083E8030045E02E4A92E803006C +:100F800083E803003FE02C4A92E8030083E8030073 +:100F900039E02A4A92E8030083E8030033E0284A54 +:100FA00092E8030083E803002DE0264A92E803005C +:100FB00083E8030027E0244A92E8030083E8030063 +:100FC00021E0224A92E8030083E803001BE0204A64 +:100FD00092E8030083E8030015E01E4A92E803004C +:100FE00083E803000FE01C4A92E8030083E8030053 +:100FF00009E01A4A92E8030083E8030003E00022B4 +:101000000270142242601846704700BFE84400088E +:10101000F0440008F84400080045000808450008AE +:10102000104500081845000820450008284500081C +:10103000304500083845000840450008484500088C +:1010400050450008584500086045000868450008FC +:10105000704500087845000880450008884500086C +:101060001923037070470000F8B5184B1E6816F07E +:1010700001060ED101221A600F24154D04E0284606 +:10108000FFF7EEFF013C0135002CF8DA114F002E7E +:101090000FDA114B1B6813F0010F0DD0F8BD284675 +:1010A000FFF7DEFF013C0135002CF8DA013E103776 +:1010B000EDE73D460F24F7E7074B01221A600020B9 +:1010C000FFF7B8FE0278054B1A70E7E7B40000207E +:1010D000BC000020CC000020B0000020B8000020A0 +:1010E00010B485B001700F2994BF00210121074B76 +:1010F0000093019102930391054CE36C01228A4015 +:101100001343E36405B010BC704700BF4C100240AD +:101110000010024082B0037819090A4A52F82120CF +:1011200002F1140103F00F030091019341B15169E1 +:10113000012000FA03F321EA030353615369536169 +:1011400002B07047F84C000882B0037819090B4AC6 +:1011500052F8211001F1140203F00F0300920193E1 +:101160004AB14869012202FA03F320EA0300486108 +:101170004A6913434B6102B0704700BFF84C000846 +:1011800082B003781909094A52F8212002F11401AA +:1011900003F00F030091019329B15169012000FA76 +:1011A00003F34B40536102B0704700BFF84C000896 +:1011B00082B0037818090B4A52F82020101D03F062 +:1011C0000F030090019358B150684FF0030C0CFAD4 +:1011D00003FC20EA0C0050605068994001435160C4 +:1011E00002B07047F84C000882B0037818090C4A26 +:1011F00052F8202002F108005B0003F00E0300907B +:10120000019358B190684FF0030C0CFA03FC20EAEC +:101210000C009060906899400143916002B0704763 +:10122000F84C000882B0037818090C4A52F82020C4 +:1012300002F10C005B0003F00E030090019358B123 +:10124000D0684FF0030C0CFA03FC20EA0C00D060CD +:10125000D06899400143D16002B07047F84C000853 +:1012600010B483B00378C3F3C0021C090F4850F8D0 +:101270002400083200EB820403F007039B00009473 +:1012800001937CB150F822404FF00F0C0CFA03FC94 +:1012900024EA0C0440F8224050F8224099402143AF +:1012A00040F8221003B010BC704700BFF84C000893 +:1012B000F0B59FB00D4604782209184B53F8227000 +:1012C00004F00F0464001A971B9403290DD017B380 +:1012D0003B680322A24023EA02033B603B68A5402F +:1012E0002B433B6000201FB0F0BD064601781CA8D0 +:1012F000FFF7EAFD1D9B142BE9D1327801AC0849B8 +:10130000204601F075FD022000F06AFF214600F042 +:101310005BFF0120E7E70020E5E700BFF84C00088D +:10132000344700080F4BDA6822F47062DA60DA683A +:1013300042F48072DA6003F580631A6842F040027A +:101340001A609A6842F040029A60DA6822F040021D +:10135000DA60054B202283F817234FF400021A604D +:1013600062B670470000014000E100E010B584B0B3 +:101370000C46017801A8FFF7A7FD054B1B788DF8F7 +:101380000C302246029903A8FFF72CFC04B010BDD4 +:10139000B800002030B583B005460C460221FFF7A7 +:1013A00087FF2B78C3F3C00218090E4951F82010AB +:1013B000083201EB820003F007039B0000900193C9 +:1013C00070B151F822000F259D4020EA050041F838 +:1013D000220051F82200E4B29C40204341F8220050 +:1013E00003B030BDF84C000882B003781909094AEF +:1013F00052F8212002F1100103F00F030091019334 +:10140000136913F0400F02D1002002B07047012091 +:10141000FBE700BFF84C000830B583B0050900F0C9 +:101420000F0400F0F0020B4B13441B5D192B05D089 +:1014300004EB05140748204403B030BD014601A861 +:10144000FFF74EFE034B03EB05139DF804201A55DE +:10145000EEE700BFBC00002008B5FFF705FE08BDA1 +:1014600038B5054603E00120FEF7FCFF21464C1E7F +:1014700031B12B689B6913F4004FF4D1012000E0D7 +:10148000002038BD38B5054603E00120FEF7EAFF2D +:1014900021464C1E31B12B689B6913F0020FF4D02A +:1014A000012000E0002038BD38B5054603E00120EA +:1014B000FEF7D8FF21464C1E31B12B689B6913F013 +:1014C000400FF4D0012000E0002038BD38B50546BB +:1014D00003E00120FEF7C6FF21464C1E31B12B6808 +:1014E0009B6913F0040FF4D0012000E0002038BD08 +:1014F000F8B5184B1E6816F001060ED101221A60CD +:101500000F24154D04E02846FFF7AAFD013C0135E4 +:10151000002CF8DA114F002E0FDA114B1B6813F074 +:10152000010F0DD0F8BD2846FFF79AFD013C0135AB +:10153000002CF8DA013E1037EDE73D460F24F7E7BF +:10154000074B01221A600020FFF774FC0278054B5C +:101550001A70E7E7B4000020BC000020CC00002097 +:10156000B0000020B800002008B50346042917D8B1 +:10157000DFE801F0030A101616000C4A92E8030097 +:1015800083E80300184608BD094A92E8030083E88F +:101590000300F7E7074A92E8030083E80300F1E756 +:1015A000054B064A1F21064801F064FA90450008E1 +:1015B00098450008A0450008644700086C470008EB +:1015C0009C47000808B5034602290DD006D8094AF1 +:1015D00092E8030083E80300184608BD064B074A5B +:1015E0002E21074801F046FA064A92E8030083E8F4 +:1015F0000300F1E7A8450008644700080048000818 +:101600009C470008B045000808B5034602290DD0E4 +:1016100006D8094A92E8030083E80300184608BD8B +:10162000064B074A3D21074801F024FA064A92E892 +:10163000030083E80300F1E7B845000864470008A9 +:10164000384800089C470008C045000808B5034614 +:1016500002290CD005D8084A07CA83E807001846B3 +:1016600008BD064B064A4D21064801F003FA064A1A +:1016700007CA83E80700F2E7C84500086447000886 +:10168000704800089C470008D44500082DE9F04147 +:1016900086B00C46017004A8FFF766FF9DF8146041 +:1016A0009DF81550214602A8FFF78CFF029F3B686A +:1016B000DDF80C8023EA08033B603046FFF7ACFE00 +:1016C0000221FFF7F5FD2846FFF7A6FE0221FFF7EE +:1016D000EFFD3046FFF7A0FE9DF81610FFF7C0FDA6 +:1016E0002846FFF799FE9DF81710FFF7B9FD304621 +:1016F000FFF792FE0121FFF75BFD2846FFF78CFE06 +:101700000121FFF755FD3046FFF786FE0221FFF766 +:101710006BFD2846FFF780FE0221FFF765FD30468E +:10172000FFF77AFE0121FFF77DFD2846FFF774FEE3 +:101730000121FFF777FD21466846FFF765FF3B680B +:1017400048EA03033B60009B1A6801990A431A6048 +:101750001A6822EA01021A6006B0BDE8F0812DE99C +:10176000F04186B080460F4616461D46017801A816 +:10177000FFF76CFF019C23689DF8082097401F43EA +:10178000276023689DF8092096401E432660236841 +:101790009DF80A2095401D43256023689DF80B1095 +:1017A0009DF830208A401343236023689DF80C1075 +:1017B0009DF834208A401343236098F8001004A851 +:1017C000FFF7D2FE049A136843F00103136006B0DA +:1017D000BDE8F08130B587B004460D46017801A818 +:1017E000FFF734FF019B1D60217804A8FFF7BCFEC2 +:1017F000049A136843F00103136007B030BD000082 +:101800002DE9F04385B00F4616461D46DDF83090B1 +:10181000DDF83480017802A8FFF7A6FE029B019351 +:10182000642101A8FFF71CFEA0B135B32B0443EAE5 +:10183000470343F40053019A53600024AC4217D28B +:10184000642101A8FFF71EFE58B1325D019B9A6228 +:101850000134F3E7022000F0C3FC2A4900F0B4FC95 +:1018600013E0022000F0BCFC274900F0ADFC0CE0C6 +:10187000642101A8FFF718FE50B1B8F1000F0ED196 +:10188000019A536843F48043536005B0BDE8F08388 +:10189000022000F0A5FC1D4900F096FCF5E70220AF +:1018A00000F09EFC1A4900F08FFC019A536803F087 +:1018B000FF2323F4E063536053684FEA084141EA91 +:1018C00047010B4343F0007343F41053536000246B +:1018D0004445DAD2642101A8FFF7F8FD58B102208F +:1018E00000F07EFC0B4900F06FFC019B5B6A09F87D +:1018F00004300134ECE7022000F072FC064900F0ED +:1019000063FCC2E7A8480008D0480008F048000877 +:1019100010490008484900082449000810B582B061 +:10192000002401940094FFF76BFF02B010BD00B5D6 +:1019300083B00193009200231A46FFF761FF03B0C2 +:101940005DF804FB10B584B000248DF80F4001242D +:1019500001940DF10F040094FFF752FF9DF80F0062 +:1019600004B010BD08B5022802D8044B184408BDC5 +:10197000034B044A8921044801F07CF80800002048 +:1019800064470008544900088049000808B5FFF77B +:10199000AFFD08BD08B5034607292AD8DFE801F0E6 +:1019A000040B11171D232929154A92E8030083E827 +:1019B0000300184608BD134A92E8030083E80300B9 +:1019C000F7E7114A92E8030083E80300F1E70F4AC2 +:1019D00092E8030083E80300EBE70D4A92E8030076 +:1019E00083E80300E5E70B4A92E8030083E803007D +:1019F000DFE7094B094A8321094801F03BF800BFA2 +:101A0000E0450008E8450008F0450008F8450008F2 +:101A1000004600080846000864470008DC49000842 +:101A20000C4A0008017070470723037070470000DC +:101A300038B5094B1B6813F0010F0CD1064B01227E +:101A40001A600524054D04E02846FFF7EDFF013C30 +:101A50000135002CF8DA38BD1C01002020010020DF +:101A600010B586B090F800E0EC46094C0FCCACE81D +:101A70000F0094E803008CE80300064B53F82E3067 +:101A800000931A6822F001021A6006B010BD00BF70 +:101A900010460008084D000882B002780023009329 +:101AA0004FF400430193054B53F8222002F1280321 +:101AB000009303B1916202B0704700BF084D000867 +:101AC00082B00278002300934FF400430193054B4A +:101AD00053F8222002F12C03009303B1D16202B02B +:101AE000704700BF084D000882B0027800230093C1 +:101AF000012301930E4B53F8223003F10C020092A4 +:101B0000DA6822F00102DA60DA6842F00102DA6093 +:101B10000378084AD356002B07DB03F01F015B094B +:101B200001228A40044941F8232002B0704700BFD7 +:101B3000084D0008004D000800E100E030B58BB012 +:101B4000864605780DF1100C1C4C0FCCACE80F004C +:101B500094E803008CE80300194B53F825300493F4 +:101B6000002102910122039203F1140002900091DE +:101B7000019203F1100200921A6822F001021A6029 +:101B80001A6842F001021A601A6822F080021A6094 +:101B90001A6842F080021A605A6922F001025A6102 +:101BA0005A6942F001025A611A6922F001021A616F +:101BB0007046FFF799FF0BB030BD00BF104600081C +:101BC000084D000870B586B004460E4615460178EB +:101BD0006846FFF7DFFE009B1A68019822EA0002C0 +:101BE0001A601A681043186031462046FFF754FF08 +:101BF00029462046FFF764FF207800230293012145 +:101C00000391094A52F8200000F110050295036182 +:101C100020780493059152F8202002F10C010491E0 +:101C2000D36006B070BD00BF084D00082DE9F04339 +:101C30008FB007468E4691461E460278354B53F8C4 +:101C4000225005F120080DF1080C334C0FCCACE804 +:101C50000F000FCCACE80F0094E80F008CE80F00E9 +:101C600005F11803029305F11C030393002300936D +:101C70004FF40043019305F1440300939DF858305D +:101C800046EA8303DBB2BEF1030F12D84FEA5E02CD +:101C90001EF0010F2ED00EA901EB820252F8302C5B +:101CA0003AB1116821F470411160116841EA0931BB +:101CB00011604FEA8E0E3A78032A01D903F003032C +:101CC000B8F1000F0BD02A6A0F2101FA0EF122EAB7 +:101CD00001022A622A6A03FA0EF313432B626B6C29 +:101CE00023F400436B646B6C43F400436B640FB0EC +:101CF000BDE8F0830EA901EB820252F8302C002AD5 +:101D0000D7D0116821F0F0011160116841EA091182 +:101D10001160CEE7084D0008284600080278074BFE +:101D200053F8223013F1380F06D09A6B6FF30F027D +:101D30009A639A6B0A439A63704700BF084D000884 +:101D400010B582B0831FDBB2012B08D904460B4BC0 +:101D50001B5C072B09D00948204402B010BD084B7A +:101D6000084A6B21084800F085FE014601A8FFF7EC +:101D700059FE9DF80420014B1A55ECE72001002084 +:101D8000744A0008C04A0008EC4A000808B5FFF78A +:101D90004FFE08BD00B583B00023009301230193DB +:101DA0000B4B0093A3F54163D3F8103C13F0010FE4 +:101DB0000AD0084AD2F8103C23F00103C2F8103CC4 +:101DC000054B1B6803B1984703B05DF804FB00BFE7 +:101DD000102C0140002001402801002000B583B0F4 +:101DE00000230093012301930A4B00934FF080439B +:101DF0001B6913F0010F09D04FF08042136923F0E3 +:101E000001031361044B5B6803B1984703B05DF8AD +:101E100004FB00BF100000402801002000B583B083 +:101E20000023009301230193094B0093103B1B698E +:101E300013F0010F08D0074A136923F0010313615F +:101E4000054B9B6803B1984703B05DF804FB00BFE6 +:101E500010100040001000402801002000B583B0A1 +:101E600000230093012301930B4B0093A3F582639E +:101E7000D3F8103413F0010F0AD0084AD2F8103406 +:101E800023F00103C2F81034054BDB6803B1984717 +:101E900003B05DF804FB00BF1014004000100040C8 +:101EA0002801002000B583B0002300930123019393 +:101EB000094B0093103B1B6913F0010F08D0074A30 +:101EC000136923F001031361054B1B6903B19847A4 +:101ED00003B05DF804FB00BF10400140004001402A +:101EE0002801002000B583B0002300930123019353 +:101EF0000B4B0093A3F58263D3F8103413F0010F5A +:101F00000AD0084AD2F8103423F00103C2F8103482 +:101F1000054B5B6903B1984703B05DF804FB00BF54 +:101F2000104401400040014028010020014B43F8CB +:101F30002010704728010020034601290ED00229F5 +:101F400005D1094A92E8030083E8030004E0074A48 +:101F500092E8030083E8030018467047044A92E8B9 +:101F6000030083E80300F7E76846000858460008C6 +:101F70006046000810B582B004468C46064B0FCB75 +:101F800084E80F0061466846FFF7D6FF009B236098 +:101F9000204602B010BD00BF7046000800B583B0F7 +:101FA00001466846FFF7C8FF00980C3003B05DF8A3 +:101FB00004FB00B583B001466846FFF7BDFF0098FB +:101FC000283003B05DF804FB38B5044603E0012077 +:101FD000FEF748FA29464D1E31B123681A68636836 +:101FE0001A42F4D0012000E0002038BDF8B5184BAB +:101FF0001E6816F001060ED101221A600F24154D3D +:1020000004E02846FFF72CF8013C0135002CF8DAF3 +:10201000114F002E0FDA114B1B6813F0010F0DD07A +:10202000F8BD2846FFF71CF8013C0135002CF8DA12 +:10203000013E1037EDE73D460F24F7E7074B01223D +:102040001A600020FEF7F6FE0278054B1A70E7E7EB +:10205000B4000020BC000020CC000020B000002014 +:10206000B800002008B5034602290DD006D8094A59 +:1020700092E8030083E80300184608BD064B074AB0 +:102080004621074800F0F6FC064A92E8030083E880 +:102090000300F1E780460008644700084C4B000845 +:1020A000904B00088846000870B584B00C4601705B +:1020B00002A8FFF741FF9DF80C609DF80D503046D7 +:1020C000FFF7AAF90221FFF7F3F82846FFF7A4F972 +:1020D0000221FFF7EDF83046FFF79EF99DF80E104C +:1020E000FFF7BEF82846FFF797F99DF80F10FFF7A6 +:1020F000B7F821466846FFF7B5FF009A13680199C3 +:102100000B43136004B070BD2DE9F04387B0064661 +:102110008846017804A8FFF70FFFDDF810903178AA +:102120006846FFF727FF009C2368019DEF4323EAE1 +:10213000050323600023C9F800302268029B22EACD +:10214000030222602268134323602268039B22EA71 +:10215000030222602268134323603078FFF71EFFDA +:10216000074B1B68B3FBF8F300B1036023681F4003 +:10217000276023681D43256007B0BDE8F08300BFDA +:102180001000002030B585B004460D4601780023CC +:1021900000938023019302A8FFF7CEFE029B1C331D +:1021A00000934FF4FA716846FFF70EFF30B12078C4 +:1021B000FFF7FFFE00B1058005B030BD1320FFF72B +:1021C0002BF9FEF7C1FFF7E738B505460C4603E0EB +:1021D00001342846FFF7D6FF21780029F8D138BD11 +:1021E00008B5032802D8044B184408BD034B044A21 +:1021F0005221044800F03EFC0C0000206447000817 +:10220000F84B0008244C000808B5FFF7EFFE08BDA6 +:10221000704700002F4B1B6813F0080F16D12D4B91 +:10222000D3F89430C3F303232B4A52F82320294BCD +:102230009B6803F00C030C2B3ED8DFE803F00C3D49 +:102240003D3D0F3D3D3D133D3D3D1700214B1B687E +:10225000C3F30313E8E7214B1A602FE01F4B204A1A +:102260001A602BE01D4B1F4A1A6027E0194BD968F2 +:1022700001F00301DB68C3F302130133022904D028 +:10228000032915D0B2FBF3F202E0154AB2FBF3F2D8 +:102290001049CB68C3F3062302FB03F3CA68C2F3F9 +:1022A000416201325200B3FBF2F30C4A136005E0C5 +:1022B0000C4AB2FBF3F2EBE7084B1A60054B9B6844 +:1022C000C3F30313084AD15C044A1368CB4013607C +:1022D000704700BF00100240204D00081000002091 +:1022E0000024F40000127A00584D000870470120C5 +:1022F000704708B500F090FE162303604FF0FF30E2 +:1023000008BD08B54FF0FF31FFF7F3FFFEE770B5EA +:102310000C461646002506E0AFF30080214601F882 +:10232000010B01350C46B542F6DB304670BD70B589 +:102330000C461646002504E014F8010BAFF30080AC +:102340000135B542F8DB304670BD4FF0FF307047C5 +:102350004FF400534B60002070470120704700206D +:1023600070470EB44FF0FF3003B0704708B500F06F +:1023700053FE0A2303604FF0FF3008BD08B500F09C +:102380004BFE022303604FF0FF3008BD4FF0FF30DB +:1023900070474FF400534B600020704708B500F0C1 +:1023A0003BFE1F2303604FF0FF3008BD08B500F06F +:1023B00033FE0B2303604FF0FF3008BD08B500F07B +:1023C0002BFE0C2303604FF0FF3008BD10B5034611 +:1023D0000C4A0D490D48006840B10C4800680344A0 +:1023E000521A934206D8094A136010BD0748084C98 +:1023F0000460F2E700F010FE0C2303604FF0FF30A2 +:10240000F3E700BF00C000200004000044010020EA +:10241000C802002030B5A5B00020FEF70BFD214C0E +:1024200025780722204B53F82510FEF7DBFB1F4BC6 +:1024300023F815002378052B16D01A490A780132A3 +:102440001B4B83FB020303EB4303A2EB43030B7021 +:10245000184A136801331849096893FBF1F001FB2E +:102460001033136025B030BD134B1B68013B114A7C +:1024700012689342E1D10D4A9388D1881089558919 +:1024800004AC0395029001910093538812880B4984 +:10249000204600F0ADFC0220FFF7A2FE2146FFF728 +:1024A00093FECAE76501002020000020680100209B +:1024B000ABAAAA2A4C01002018000020844C000876 +:1024C00008B50220FFF73CFC4FF47A61FFF7E4FA0D +:1024D0000220FFF735FCC821FFF7F2FA0220FFF7D0 +:1024E0002FFCFFF72BFB08BD10B50920FEF794FF6A +:1024F000FEF746FE0420FFF723FCFFF7B1FA1E4B60 +:102500001B781BB11D4B1B68022B11DC1C4B1B786D +:1025100063BB0020FFF714FCFFF710FB174A13689A +:1025200001331360164A137883F00103137010BD52 +:102530000024114B1C70114B1C600220FFF700FCA3 +:10254000FFF78EFA2046FFF7FBFBFFF789FA022020 +:10255000FFF7F6FB4FF47A61FFF79EFA0220FFF7D0 +:10256000EFFB4FF4C871FFF7ABFACFE70020FFF79E +:10257000E7FBFFF775FAD5E7510100205401002071 +:1025800064010020F8B5214B1B6813F0010F0CD13A +:102590001E4B01221A6005241D4D04E02846FFF75A +:1025A00043FA013C0135002CF8DA1A4B1E6816F08C +:1025B00001060ED101221A600F24174D04E02846AF +:1025C000FEF74EFD013C0135002CF8DA134F002ECA +:1025D0000FDA134B1B6813F0010F0DD0F8BD28461E +:1025E000FEF73EFD013C0135002CF8DA013E1037C4 +:1025F000EDE73D460F24F7E7094B01221A60002062 +:10260000FEF718FC0278074B1A70E7E71C01002060 +:1026100020010020B4000020BC000020CC000020DD +:10262000B0000020B800002008B50020FFF788FBAC +:10263000FFF716FA0220FFF783FBFFF711FA0023DA +:10264000024A1370024A137008BD00BF64010020E3 +:102650005101002008B50023052B0DDC204A32F87B +:102660001310204A32F81320914201D30133F3E7CB +:102670001D4B00221A7002E01B4B01221A701A4BEC +:102680001B78F3B1194B1B7823B1174B1A78174BF2 +:102690001A7008BD0020FFF753FBFFF7E1F9022095 +:1026A000FFF74EFBFFF7DCF90420FFF749FBFFF7CC +:1026B000D7F90920FEF7B0FEFEF72CFDFFF7B4FFB7 +:1026C000E3E70A4B1B78002BDFD00420FFF738FB31 +:1026D000FFF734FA0920FEF79FFEFEF735FDD4E739 +:1026E0006801002058010020490100204801002015 +:1026F00030B5A5B0002204E00023134921F81230C0 +:102700000132052A07DC114B33F81230312BF3D993 +:10271000323B9BB2F1E70C4A9388D18810895589E6 +:1027200004AC0395029001910093538812880849E4 +:10273000204600F05DFB0220FFF752FD2146FFF727 +:1027400043FD25B030BD00BF5801002068010020C6 +:10275000AC4C000870B5174E002434700320FFF70E +:10276000EFFAFFF77DF90120FFF7EAFAFFF778F9B2 +:10277000114B1C600125114B1D700220FFF7E0FA80 +:1027800032224FF47A61FFF71DFA0220FFF7D8FAE0 +:10279000FFF7D4F9FFF7ACFF2046FFF7D1FAFFF7B8 +:1027A000CDF92846FFF7CCFAFFF7C8F9044B1C70A7 +:1027B000357070BD1C000020540100205101002024 +:1027C0001D00002000B583B0FDF708FE0020FEF7D5 +:1027D00023FE0321FEF76CFD0120FEF71DFE032101 +:1027E000FEF766FD0320FEF717FE0321FEF760FDEE +:1027F0000420FEF711FE0321FEF75AFD0520FEF727 +:102800000BFE0321FEF754FD0620FEF705FE032113 +:10281000FEF74EFD0720FEF7FFFD0321FEF748FD02 +:102820001620FEF7F9FD0021FEF742FD0920FEF714 +:10283000F3FD0121FEF73CFD1020FEF7EDFD012127 +:10284000FEF7A8FD0820FEF7E7FD0121FEF730FDA9 +:102850000820FEF7E1FD0021FEF7E4FC0120FFF770 +:102860006FFAC8224FF47A61FFF7ACF90120FFF745 +:1028700067FA5E490078FFF759FB0120FFF760FA1D +:10288000FFF732F90120FFF75BFAFFF757F9002055 +:10289000FFF756FA4FF416620021FFF793F9002074 +:1028A000FFF74EFA03240094012306221946FFF78E +:1028B000BDF90020FFF744FA4FF46171FFF72EFADB +:1028C0000220FFF73DFA4FF4FA724FF47A61FFF7F6 +:1028D00079F90220FFF734FA45490078FFF726FB23 +:1028E0000220FFF72DFAFFF7FFF82046FFF728FA3E +:1028F00040F6B8324FF47A61FFF764F92046FFF7EB +:102900001FFA3C490078FFF711FB2046FFF718FA41 +:10291000FFF7EAF80420FFF713FA41F288324FF488 +:102920007A61FFF74FF90420FFF70AFA324900787D +:10293000FFF7FCFA0420FFF703FAFFF7D5F80220AF +:10294000FFF74EFC2D49FFF73FFC1620FEF764FD14 +:10295000FEF74AFD012816D0294B1B786BB9284B8E +:1029600000221A70274B1B78002BEED0264B1B78C9 +:10297000002BEAD0FFF76EFEE7E70320FFF7E0F950 +:10298000FFF7DCF8EBE71E4B1B78ABB91F4B1B784E +:1029900053B11C4B1B789BB90820FEF73DFDFEF799 +:1029A000D3FB184B01221A70184B01221A70032016 +:1029B000FFF7C6F9FFF754F8114B01221A70D1E75F +:1029C0000820FEF729FDFEF7A5FB0920FEF724FDF0 +:1029D000FEF7A0FB0B4B00221A7001230C4A137068 +:1029E0000C4A1370FFF720FEDEE700BF1524000835 +:1029F000E924000855270008C1240008EC4C000811 +:102A000050010020740100201C0000201D00002047 +:102A1000490100204801002008B5FFF7B3FD08BDBB +:102A2000DFF834D0FFF7F4FB0C480D490D4A0023C2 +:102A300002E0D458C4500433C4188C42F9D30A4A73 +:102A40000A4C002301E013600432A242FBD300F0E1 +:102A5000E9FAFFF7B7FEFEE700C000200000002003 +:102A600094000020284E000894000020C802002096 +:102A7000FEE700001FB514461A46094B1B680546C1 +:102A8000D8684CB1074B0091CDE9013406492B467B +:102A900000F060F900F0F6FA044B1C46F3E700BFC3 +:102AA00044000020684D0008754D0008A34D000843 +:102AB00008B513460022FFF7DDFF000008B5064BFE +:102AC000044613B10021AFF30080044B1B6803B12F +:102AD00098472046FFF715FC00000000B0020020D8 +:102AE000002310B50446C0E90033C0E90433836015 +:102AF00081814366C2818361194608225C3000F0FF +:102B0000DFF90D4B63620D4BA3620D4BE3620D4B7E +:102B100023630D4B24629C4206D003F16802944269 +:102B200002D0D0339C4205D104F15800BDE81040DA +:102B300000F09DBA10BD00BF352E00085B2E0008C6 +:102B4000932E0008B92E000878010020024A03499C +:102B5000034800F011B900BF38000020F13C000824 +:102B60004800002041680C4B994210B5044601D042 +:102B700001F0BEF8A168094B994202D0204601F04D +:102B8000B7F8E168064B994204D02046BDE81040F2 +:102B900001F0AEB810BD00BF78010020E0010020B8 +:102BA0004802002008B54B6EDA0705D48B899B05D7 +:102BB00002D4886D00F05FFA002008BD08B54B6EA6 +:102BC000DA0705D48B899B0502D4886D00F059FA89 +:102BD000002008BD0C4B0D4A0D4810B504211A60A9 +:102BE0000022FFF77DFF0A4B01221C46092103F159 +:102BF0006800FFF775FF04F1D0000222BDE8104025 +:102C00001221FFF76DBF00BFB00200204D2B00085E +:102C100078010020014800F02EBA00BFBF0200205A +:102C2000014800F02EBA00BFBF020020F8B50746E9 +:102C3000FFF7F0FF234B1B680BB9FFF7CBFF224ECA +:102C4000D6E90134013B0FD53568002D38D14FF45A +:102C5000D671384600F08AFA044628BB3060FFF788 +:102C6000DFFF0C233B601BE0B4F90C50D5B9174BC8 +:102C7000E36004F15800656600F0F9F9FFF7D0FF52 +:102C8000C4E90155C4E904552560A5610822294617 +:102C900004F15C0000F014F9C4E90D55C4E91255C3 +:102CA0002046F8BD6834CDE70423056043600C304E +:102CB0002946A0604FF4D07200F002F92546346036 +:102CC0002E46BDE7B0020020380000200100FFFFC3 +:102CD00010B50446FFF79EFF236A1BB1BDE8104004 +:102CE000FFF79EBF044B2362044B1B68002BF5D1FA +:102CF000FFF770FFF2E700BF652B0008B00200206D +:102D000008B5FFF787FFBDE80840024A02490020E6 +:102D100000F032B838000020A52B000808B5044A9E +:102D20000449002000F028F8BDE80840FFF778BF0C +:102D300038000020BD2B00080CB407B504AB53F8D5 +:102D4000042B019300F0A4FC03B05DF804EB02B087 +:102D5000704700000EB403B5014603AB054853F8B5 +:102D6000042B0068019300F093FC02B05DF804EBC3 +:102D700003B07047440000202DE9F8430746884619 +:102D800014460026D4E90195B9F1010905D5246856 +:102D9000002CF7D13046BDE8F883AB89012B07D969 +:102DA000B5F90E30013303D029463846C0470643F3 +:102DB0006835E9E70CB410B59CB01EAB02910691E2 +:102DC0006FF0004107910491084953F8042B0591D5 +:102DD000002402A901931B9400F02EFB029B1C709F +:102DE0001CB0BDE8104002B0704700BF0802FFFFF2 +:102DF0000EB410B59DB01FAB029006906FF000416D +:102E00000A48079104910A4953F8042B05910024BC +:102E100002A9006801931B9400F00EFB029B1C703A +:102E20001DB0BDE8104003B0704700BF4400002053 +:102E30000802FFFF10B50C46B1F90E1000F0C8F8FB +:102E40000028ABBF636DA3891B1823F48053ACBF6C +:102E50006365A38110BD002070472DE9F0411F4636 +:102E60008B89DB0505460C46164605D5B1F90E10D3 +:102E70000223002200F09AF8A389B4F90E1023F47B +:102E80008053A38132463B462846BDE8F04100F01E +:102E9000B1B810B50C46B1F90E1000F087F8B4F9CE +:102EA0000C30421C0BBF23F4805343F48053A381A6 +:102EB000A38118BF606510BDB1F90E1000F008B80D +:102EC00002440346934200D1704703F8011BF9E71F +:102ED00038B5064D0023044608462B60FFF735FA47 +:102EE000431C02D12B6803B1236038BDB40200201B +:102EF0002D4B1B68834270B5044653D0C3691BB386 +:102F0000DB6863B10025E369DB685959B1B9043561 +:102F1000802DF8D1E3692046D96800F0BBF8E36959 +:102F2000196811B1204600F0B5F8E3699D685DB1FC +:102F3000294620462D6800F0ADF8F8E70E682046D7 +:102F400000F0A8F83146E1E7616911B1204600F0D0 +:102F5000A1F8E16911B1204600F09CF8216B11B194 +:102F6000204600F097F8616B11B1204600F092F80E +:102F7000A16B11B1204600F08DF8A16C11B1204673 +:102F800000F088F8616C11B1204600F083F8E16A26 +:102F900011B1204600F07EF8236A1BB12046BDE83F +:102FA0007040184770BD00BF4400002038B5074D81 +:102FB00004460846114600222A601A46FFF7CFF958 +:102FC000431C02D12B6803B1236038BDB40200203A +:102FD00038B5074D04460846114600222A601A46B5 +:102FE000FFF795F9431C02D12B6803B1236038BD6C +:102FF000B402002038B5074D0446084611460022A9 +:103000002A601A46FFF793F9431C02D12B6803B1DB +:10301000236038BDB4020020014B1868704700BF20 +:103020004400002070B50D4B0D4D5B1B9C1000261D +:10303000A64209D101F01EFA0A4D0B4B5B1B9C10F6 +:103040000026A64205D170BD55F8043B98470136CD +:10305000EEE755F8043B98470136F2E7044E0008C6 +:10306000044E0008044E0008244E000870477047C4 +:1030700070477047704770470120704701207047C4 +:103080007047704708B5062001F0ECF80120FFF703 +:1030900038F9000038B50546002941D051F8043C04 +:1030A0000C1F002BB8BFE41800F0E0F81D4A1368AD +:1030B00033B9636014602846BDE8384000F0DCB8DE +:1030C000A34208D9206821188B4201BF19685B68A8 +:1030D00009182160EDE71A465B680BB1A342FAD9E3 +:1030E00011685018A0420BD1206801445018834247 +:1030F0001160E0D118685B68536008441060DAE73B +:1031000002D90C232B60D6E7206821188B4204BF1C +:1031100019685B68636004BF091821605460CAE7DE +:1031200038BD00BFC402002070B50F4E0C46316898 +:10313000054611B901F0C8F830602146284601F073 +:10314000C3F8431C03D14FF0FF34204670BDC41CAC +:1031500024F00304A042F8D0211A284601F0B4F864 +:103160000130F2D1EFE700BFC00200202DE9F843A3 +:10317000CD1C25F0030508350C2D38BF0C25002D7E +:10318000064601DBA94204D90C2333600020BDE8C8 +:10319000F883DFF8D48000F069F8D8F800301C46D6 +:1031A00044BB29463046FFF7BFFF431C044658D1B5 +:1031B000D8F800402746002F43D1002C4BD023687D +:1031C0003946304604EB030901F07EF8814542D1CF +:1031D00021686D1A29463046FFF7A6FF01303AD024 +:1031E00023682B442360D8F800305A6862BBC8F8C3 +:1031F00000700FE02268521B20D40B2A17D96119E6 +:10320000A342256018BF5960636808BFC8F8001062 +:1032100062514B60304600F02FF804F10B00231D83 +:1032200020F00700C21A1CBF1B1AA350AFE7626848 +:10323000A3420CBFC8F800205A60EBE7234664683D +:10324000AEE73C467F68B6E71A465B68A342FBD10F +:1032500000235360DEE70C233360304600F00CF8A7 +:1032600094E70560D6E700BFC40200200148FFF7DD +:1032700002BF00BFBC0200200148FFF702BF00BF31 +:10328000BC0200202DE9F0478E681F46BE428246F0 +:103290000C469046334653D8B1F90C0010F4906FA9 +:1032A0002BD065692368096905EB4505A3EB010986 +:1032B00005EBD5757B1C6D104B44AB422A4684BF91 +:1032C0001D462A46430527D511465046FFF74EFFB7 +:1032D000064658B321694A4601F006F8A38923F44B +:1032E000906343F08003A381266165614E44A5EBA2 +:1032F00009052660A5603E463B461F4620683A46C3 +:10330000414600F01DFFA3689B1BA36023683B445C +:1033100023600020BDE8F087504600F0F3FF06462A +:103320000028E1D121695046FFF7B4FE0C23CAF80A +:103330000030A38943F04003A3814FF0FF30E9E759 +:103340003E46DBE793682DE9F74F80460C4617466B +:10335000002B53D0D2F800A0DAF804B0DAF800302D +:1033600001930AF1080ABBF1000FF5D0A6685E458B +:1033700035465FD8B4F90C0010F4906F2DD0226858 +:1033800021696569A2EB010905EB450505EBD575DA +:1033900009F101066D105E44AE422A4684BF3546EF +:1033A0002A46430530D511464046FFF7DFFE064664 +:1033B000002833D04A46216900F096FFA28922F402 +:1033C000906242F08002A281266165614E44A5EBC5 +:1033D00009052660A5605E465D462A46019920687B +:1033E00000F0AEFEA268921BA26022682A4422600E +:1033F000BA68A2EB0B03BB60002BADD10020002309 +:103400007B6003B0BDE8F08F404600F07BFF0646CE +:103410000028D9D121694046FFF73CFE0C23C8F8AB +:103420000030A38943F04003A3810023BB604FF029 +:10343000FF30E4E75E46CFE72DE9F0471F468B8972 +:103440001B069CB006460D46144610D50B6973B991 +:103450004021FFF78BFE2860286130B90C233360D0 +:103460004FF0FF301CB0BDE8F08740236B610023B4 +:10347000099320238DF8293003973023654F8DF869 +:103480002A304FF001082346994613F8012B0AB160 +:10349000252AF9D1B9EB040A0BD053462246294616 +:1034A0003046FFF7EFFE013000F0A480099A524445 +:1034B000099299F80030002B00F09C8000234FF017 +:1034C000FF32CDE9052309F10109049307938DF833 +:1034D00053301A934C464F4814F8011B0522FCF751 +:1034E0009FFE049BD0B9D80644BF20228DF85320FC +:1034F000190744BF2B228DF8532099F800202A2A5F +:1035000013D0079A4C4600204FF00A0C214611F8C0 +:10351000013B303B092B49D968B913E0C01B08FABD +:1035200000F018430490A146D4E7039A111D1268D5 +:103530000391002A01DB079204E0524243F00203A8 +:103540000792049323782E2B0AD163782A2B32D149 +:10355000039B1A1D1B68039243EAE373023405932D +:10356000DFF8B490217803224846FCF759FE38B1C1 +:10357000049BA0EB090040228240134301340493D2 +:1035800014F8011B25488DF828100622FCF748FE88 +:10359000002835D0224818BB039B073323F00703CC +:1035A00008330393099B034409936CE70CFB023235 +:1035B0000C460120AAE700230134059319464FF079 +:1035C0000A0C204610F8012B303A092A03D9002BA7 +:1035D000C6D00591C4E70CFB012104460123F0E7A6 +:1035E00003AB00932A460F4B04A93046AFF300808B +:1035F000421CD7D1AB895B063FF532AF099831E762 +:1036000003AB00932A46074B04A9304600F0CCF9DF +:10361000EEE700BFA44D0008AA4D0008AE4D00081B +:1036200000000000853200089368013B002B10B4B5 +:10363000936007DA9469A34201DB0A2902D110BC26 +:1036400000F0E4BC1368581C10601970084610BCE8 +:103650007047F8B506460F461446D518AC4201D15E +:10366000002007E014F8011B3A463046FFF7DCFF64 +:10367000431CF3D1F8BD936810B5144633B100F084 +:1036800073FB0023A3600023636010BD1846FAE7B4 +:103690002DE9F0470D469CB014461F46064618B16A +:1036A000036A0BB9FFF714FB6B6ED90705D4AB891E +:1036B0009A0502D4A86DFFF7DEFCAB891B0701D584 +:1036C0002B699BB92946304600F0E6FC70B16B6E61 +:1036D000DC0704D54FF0FF301CB0BDE8F087AB89A4 +:1036E0009805F7D4A86DFFF7CCFCF3E70023099306 +:1036F00020238DF82930039730236A4F8DF82A3024 +:103700004FF001082346994613F8012B0AB1252AE8 +:10371000F9D1B9EB040A0BD053462246294630466C +:10372000FFF797FF013000F0A480099A52440992F4 +:1037300099F80030002B00F09C8000234FF0FF32FE +:10374000CDE9052309F10109049307938DF853305E +:103750001A934C46534814F8011B0522FCF760FDF0 +:10376000049BD0B9D90644BF20228DF853201A07F4 +:1037700044BF2B228DF8532099F800202A2A13D019 +:10378000079A4C4600204FF00A0C214611F8013BE5 +:10379000303B092B49D968B913E0C01B08FA00F087 +:1037A00018430490A146D4E7039A111D12680391AF +:1037B000002A01DB079204E0524243F00203079221 +:1037C000049323782E2B0AD163782A2B32D1039BC2 +:1037D0001A1D1B68039243EAE37302340593DFF872 +:1037E000C890217803224846FCF71AFD38B1049BA3 +:1037F000A0EB09004022824013430134049314F8E3 +:10380000011B2A488DF828100622FCF709FD002824 +:103810003ED0274818BB039B073323F00703083328 +:103820000393099B034409936CE70CFB02320C469B +:103830000120AAE700230134059319464FF00A0C32 +:10384000204610F8012B303A092A03D9002BC6D0A4 +:103850000591C4E70CFB012104460123F0E703AB0B +:1038600000932A46134B04A93046AFF30080431C53 +:10387000D7D16B6ED90705D4AB899A0502D4A86D50 +:10388000FFF7FFFBAB895B063FF524AF099823E701 +:1038900003AB00932A46074B04A9304600F084F896 +:1038A000E5E700BFA44D0008AA4D0008AE4D000892 +:1038B000000000005336000813460A46014602483D +:1038C0000068FFF7E5BE00BF440000202DE9F04787 +:1038D000164698468A680B69DDF820909342B8BF77 +:1038E0001346336091F8432007460C460AB1013372 +:1038F00033602368990642BF33680233336025681A +:1039000015F0060506D104F1190AE36832689B1A1E +:10391000AB4226DC94F843302268003B18BF0123F9 +:1039200092062BD404F1430241463846C847013081 +:103930001ED02368226903F00603042B02BFE5684A +:103940003368ED1AA3680CBF25EAE575002593429C +:10395000C4BF9B1AED1800261A34B5421AD10020B4 +:1039600008E00123524641463846C847013003D19A +:103970004FF0FF30BDE8F0870135C6E7E1185A1C6B +:10398000302081F84300224494F8451082F8431017 +:103990000233C7E70123224641463846C847013073 +:1039A000E6D00136D9E700002DE9F0430D7E85B061 +:1039B000782D90460C9E07460C46994601F143022D +:1039C00007D8622D0AD8002D00F0D780582D00F0BE +:1039D000BC8004F1420684F842503BE0A5F1630349 +:1039E000152BF6D801A151F823F000BF453A000885 +:1039F000593A0008D3390008D3390008D3390008F0 +:103A0000D3390008593A0008D3390008D3390008DF +:103A1000D3390008D3390008613B0008833A000815 +:103A2000133B0008D3390008D3390008833B000852 +:103A3000D3390008833A0008D3390008D339000885 +:103A40001B3B000833681A1D1B68326004F14206F4 +:103A500084F842300123A1E033682068191D3160E9 +:103A6000060601D51D6803E04506FBD5B3F90050F5 +:103A7000002D03DA2D236D4284F843305B480A237E +:103A800011E021683368080653F8045B02D4490644 +:103A900048BFADB23360237E54486F2B5CD10823FE +:103AA000002184F843106668A660002E05DB2168BB +:103AB0002E4321F00401216050D01646B5FBF3F1EE +:103AC00003FB115C10F80CC006F801CDAC46634551 +:103AD0000D46F3D9082B0BD12368DB0708D52369E2 +:103AE00061689942DEBF302306F8013C06F1FF36DB +:103AF000921B2261CDF80090434603AA2146384626 +:103B0000FFF7E4FE01304ED14FF0FF3005B0BDE8C5 +:103B1000F083236843F0200323603548782584F838 +:103B200045502368316813F0800F51F8045B03D1CE +:103B300013F0400F18BFADB23160D90744BF43F056 +:103B4000200323601DB11023AAE72848E7E7236874 +:103B500023F020032360F6E70A23A1E71646B9E71E +:103B6000336825686169181D30602E061B6801D511 +:103B7000196002E06806FBD5198000232361164610 +:103B8000B8E733681A1D32601E686268002130464B +:103B9000FCF746FB08B1801B60606368236100236B +:103BA00084F84330A6E72369324641463846C84781 +:103BB0000130A9D023689B0713D4E068039B984287 +:103BC000B8BF1846A2E70123324641463846C847E7 +:103BD000013099D00135E36803995B1AAB42F2DCFE +:103BE000EBE7002504F11906F5E700BFB54D000825 +:103BF000C64D0008B1F90C20F8B5160705460C466D +:103C000051D44B68002B02DC0B6C002B49DDE66ABB +:103C1000002E46D0002312F480522F682B6031D042 +:103C2000626DA389590705D56368D21A636B0BB11E +:103C3000236CD21A0023E66A216A2846B047421C48 +:103C4000B4F90C3006D129681D2945D8274ACA4045 +:103C5000D60741D500226260D9042269226004D5CA +:103C6000421C01D12B6803B96065616B2F60C1B143 +:103C700004F14403994202D02846FFF70BFA0023CF +:103C800063630EE0216A01232846B0470246501CB8 +:103C9000C7D12B68002BC4D01D2B01D0162B19D1F6 +:103CA0002F6000201DE00F69002FFAD093070E68E7 +:103CB00008BF4B690F6018BF0023F61B8B60002EF6 +:103CC000EFDD216AD4F828C033463A462846E0475B +:103CD000002807DCB4F90C3043F04003A3814FF017 +:103CE000FF30F8BD0744361AE9E700BF0100402065 +:103CF00038B50B6905460C4613B90025284638BD72 +:103D000018B1036A0BB9FEF7E3FFB4F90C30002BCE +:103D1000F3D0626ED00704D4990502D4A06DFFF7EA +:103D2000AAF928462146FFF765FF636EDA070546C4 +:103D3000E4D4A3899B05E1D4A06DFFF7A2F9DDE7E8 +:103D4000014620B9044A05490548FFF715B8054B57 +:103D50001868FFF7CDBF00BF38000020F13C000815 +:103D6000480000204400002093682DE9F74F0646E4 +:103D70000C4691461BB9002003B0BDE8F08F8B893B +:103D80001B0751D50B69002B4ED0B4F90CA0D9F804 +:103D900000801AF002076CD11AF0010A00F0988036 +:103DA0003846BA46BB46BBF1000F00F00A8150B955 +:103DB0005A460A215046FCF733FA002800F00781E2 +:103DC0000130A0EB0A072068216963695F453A4624 +:103DD00028BF5A46884240F2FD80A5681D44AA4289 +:103DE00040F3F88051462A4600F0AAF923682B4494 +:103DF000236021463046FFF77BFF002840F0888093 +:103E00007F1B40F0FF8021463046FFF771FF0028FE +:103E10007ED1D9F808305B1BAA44ABEB050BC9F87F +:103E20000830002BBFD1A6E72146304600F034F918 +:103E30000028AAD04FF0FF309EE7D8E9005708F1DC +:103E40000808002FF9D057453B46216AD4F828C00E +:103E500028BF53462A463046E047002858DDD9F8A7 +:103E600008301B1A05443F1AC9F80830002BE8D166 +:103E700081E70025DFF890A12F46E2E7D8E900A509 +:103E800008F10808002DF9D0B4F90CC0A368206827 +:103E90001CF4007F67D0AB429B461BD92B462F46B4 +:103EA000AB465A4620680193514600F049F9A26892 +:103EB000019BD21A2368A2605B442360D9F80830C2 +:103EC000DB1BBA44ED1BC9F80830002BDAD152E7EE +:103ED0005546D7E71CF4906F43D021696769A0EB82 +:103EE000010B07EB470707EBD7770BF101007F10BA +:103EF0002844B8423A4684BF07463A461CF4806FCD +:103F000020D011463046FFF731F930B90C23336029 +:103F1000A38943F04003A3818CE75A4621690190AD +:103F200000F0E2F9A289019B22F4906242F0800243 +:103F3000A281236167615B44A7EB0B072360A76045 +:103F40002B46ACE7304600F0DDF903460028F0D1FF +:103F500021693046FFF79EF8A38923F08003A381EF +:103F6000D4E72F469DE72269824202D36269AA42C2 +:103F700016D9AB4228BF2B461A4651461F4600F0C1 +:103F8000DFF8A3682268DB1B3A44A3602260002BA1 +:103F900094D121463046FFF7ABFE00288ED0B7E71C +:103FA0006FF00043AB4228BF2B46A76A93FBF2F3A6 +:103FB000216A534330465246B847071E3FF77EAF4B +:103FC000A6E7D8E900AB002008F10808EBE60BF102 +:103FD0000107F8E6934208DCA56A216A524630469A +:103FE000A847051E3FF70CAF92E75146019200F03B +:103FF000A7F8019AA3689B1AA3602368134423605F +:104000001546FDE6012004E700FCFF7FF8B50E46EB +:104010001446054618B1036A0BB9FEF759FEA369A9 +:10402000A360A3891A0701D5236943B9214628460D +:1040300000F032F818B14FF0FF373846F8BD23686A +:104040002269981A6369F6B28342374605DC214635 +:104050002846FFF74DFE0028EDD1A368013BA36081 +:1040600023685A1C22601E706269431C9A4204D065 +:10407000A389DB07E1D50A2EDFD121462846FFF7C9 +:1040800037FE0028D9D0D6E7024B0A460146186809 +:10409000FFF7BCBF4400002038B5284B0546186820 +:1040A0000C4618B1036A0BB9FEF712FEB4F90C30D6 +:1040B0001A0721D4D80607D409222A6043F0400306 +:1040C000A3814FF0FF3030E0590712D5616B41B149 +:1040D00004F14403994202D02846FEF7DBFF002397 +:1040E00063630022B4F90C3062602269226023F01D +:1040F000240343F00803A38122693AB99A0501D544 +:10410000180603D52146284600F04EF9B4F90C30C4 +:1041100013F001020AD00022A26062695242A26139 +:10412000226942B913F08000C8D138BD990758BF41 +:104130006269A260F4E70020F7E700BF44000020B6 +:10414000884210B501EB020402D98442234607D805 +:10415000431EA14207D011F8012B03F8012FF8E705 +:104160000244824200D110BD13F8011D02F8011D66 +:10417000F7E738B5C56B044655B98021FEF7F6FF61 +:10418000E06338B1031F7C3043F8045F8342FBD106 +:10419000002038BD4FF0FF30FBE71F2970B5044603 +:1041A0000D46164604D9162303604FF0FF3006E093 +:1041B000C36B2BB1E36B53F8250043F8256070BD4A +:1041C000FFF7D7FF0028F5D0EFE71F2938B50546E0 +:1041D0000C4604D9162303604FF0FF3038BDC26B84 +:1041E00012B152F821304BB9284600F06BF8224644 +:1041F00001462846BDE8384000F052B8012B0AD0ED +:10420000591C03D1162303600120E7E7002142F87F +:104210002410204698470020E0E71F2938B50446BF +:104220000D4602D94FF0FF3038BDC36B2BB1E26BA6 +:1042300052F8253033B90120F6E7FFF79AFF00283E +:10424000F5D0EFE7591C08D0012B08D000242846F0 +:1042500042F8254098472046E6E70220E4E703209D +:10426000E2E70000024B01461868FFF7AEBF00BF4F +:1042700044000020024B0A4601461868FFF78DBF34 +:1042800044000020014B1868FFF773BF4400002072 +:10429000024B01461868FFF7C0BF00BF4400002072 +:1042A00038B5074D00230446084611462B60FEF73B +:1042B00020F8431C02D12B6803B1236038BD00BF36 +:1042C000B4020020FEF713B838B5064D00230446AB +:1042D00008462B60FEF77AF8431C02D12B6803B125 +:1042E000236038BDB40200200A44914200F1FF333C +:1042F00000D1704710B511F8014B03F8014F9142FE +:10430000F9D110BD2DE9F041074614460D4621B9FB +:10431000BDE8F0411146FEF729BF2AB9FEF7BAFE03 +:1043200025462846BDE8F08100F09AF8844206460A +:1043300002D8B4EB500FF4D821463846FEF716FFEA +:10434000804608B94546ECE7B4422246294628BFD4 +:104350003246FFF7C9FF29463846FEF79BFEF1E7D4 +:1043600070B50C46B1F90E10002996B015461E46E0 +:104370000ADAA18911F0800113D14FF48062002084 +:1043800031602A6016B070BD6A4600F047F8002818 +:10439000EFDB019901F47041A1F5005359425941F5 +:1043A000EBE700214022EAE78B8973B59E070546BB +:1043B0000C4607D504F147032360236101236361A1 +:1043C00002B070BD01AB6A46FFF7CAFF009E2846E7 +:1043D0003146FEF7CBFEB4F90C3038B99A05EFD46C +:1043E00023F0030343F00203A381E3E743F08003D8 +:1043F000A381019B2060C4E90406002BE0D0B4F93E +:104400000E10284600F01CF80028D9D0A38923F00C +:10441000030343F00103A381D2E7000038B5074D41 +:1044200000230446084611462B60FDF791FF431C0C +:1044300002D12B6803B1236038BD00BFB402002055 +:1044400038B5064D0023044608462B60FDF785FF6E +:10445000431C02D12B6803B1236038BDB402002095 +:1044600051F8043C181F002BBCBF0B58C0187047F4 +:1044700000000000F8B500BFF8BC08BC9E467047BD +:0C448000F8B500BFF8BC08BC9E467047B1 +:10448C00000000000100000010000000020000000D +:10449C00000000800400000000000020000000105C +:1044AC0000000040000000000400000008000000B4 +:1044BC0001000000100000000000000000200000BF +:1044CC000300000005000000002000004C1002401A +:1044DC0000200000881002401C00000001000000B9 +:1044EC0006000000010000001000000002000000A7 +:1044FC00070000000300000008000000030000009B +:10450C00140000000400000009000000040000007A +:10451C0014000000050000000A0000000500000067 +:10452C0014000000060000000B0000000600000054 +:10453C0014000000070000000C0000000700000041 +:10454C001400000008000000140000000900000026 +:10455C00140000000A000000140000000B00000012 +:10456C00140000000C000000140000000D000000FE +:10457C00140000000E000000140000000F000000EA +:10458C001400000000540040090A040400540040C8 +:10459C0016170404005C0040071404045810024071 +:1045AC00000020005810024000008000381002402B +:1045BC000000200038100240000080001054004021 +:1045CC001F17130F07000000105C00401F17130F7C +:1045DC000700000060100240000800005810024064 +:1045EC00010000005810024010000000581002405A +:1045FC00200000006010024000000100601002402A +:10460C000000020000000000010000000200000099 +:10461C000800000005000000800000000000000001 +:10462C000000000000000000040000000800000072 +:10463C0004000000800000000800000000040000DE +:10464C00000800000C000000008000000038014051 +:10465C00090A0707003801401617070700440040F5 +:10466C000203070700000000010000000800000022 +:10467C00040000006010024000400000581002408E +:10468C00000002003E410C411141274136410341DB +:10469C00064115410F410E4126411341294102416A +:1046AC0019410A410B41000030782530386C580D07 +:1046BC000A000000456E61626C65206661696C657C +:1046CC00643A20496E76616C6964200D0A00000022 +:1046DC0043616C6962726174696F6E204F4B0D0A95 +:1046EC00000000004E6F742076616C69640D0A0046 +:1046FC0043616C6962726174696F6E206661696C8A +:10470C006564000000000000436F756C64206E6FE0 +:10471C007420656E61626C652066726F6D20696EC7 +:10472C0069740D0A000000004572726F723A2047DE +:10473C0050494F2070696E20256420686173206E8B +:10474C006F2076616C696420414443206D61707008 +:10475C00696E670D0A00000066616C7365000000ED +:10476C00636F6E737465787072205348414C5F4967 +:10477C0032435F50616972206765744932435061FE +:10478C006972284932435F50616972290000000048 +:10479C00453A2F50726F6A656374732F456D62656D +:1047AC00646465642F53686D696E676F2D48414C66 +:1047BC002F53686D696E676F2D48414C2F534841DC +:1047CC004C2F496E636C7564652F50657269706807 +:1047DC006572616C2F4932432F5265672F534841E4 +:1047EC004C5F4932435F5245475F4C3433324B4345 +:1047FC002E680000636F6E73746578707220534876 +:10480C00414C5F4932435F456E61626C655F526536 +:10481C006720676574493243456E61626C65526509 +:10482C0067284932435F506169722900636F6E7368 +:10483C007465787072205348414C5F4932435F5223 +:10484C00657365745F5265672067657449324352BE +:10485C0065736574526567284932435F50616972AC +:10486C0029000000636F6E73746578707220534872 +:10487C00414C5F4932435F54696D696E675F5265A5 +:10488C00672067657449324354696D657252656778 +:10489C00284932435F506169722900004932432034 +:1048AC0074696D6564206F75742077616974696EC5 +:1048BC006720666F72206E6F7420627573790D0AB3 +:1048CC00000000004932432074696D6564206F75E7 +:1048DC00742077616974696E6720666F7220545812 +:1048EC000D0A00004932432074696D6564206F75B0 +:1048FC00742077616974696E6720666F7220544307 +:10490C000D0A00005265616420696E6974696174F6 +:10491C0065640D0A000000004932432074696D651E +:10492C0064206F75742077616974696E6720666F97 +:10493C00722052584E450D0A000000005265616409 +:10494C00206279746500000073746174696320538C +:10495C0048414C5F49324326204932434D616E61D8 +:10496C006765723A3A6765742875696E74385F7456 +:10497C0029000000453A2F50726F6A656374732FDB +:10498C00456D6265646465642F53686D696E676F0D +:10499C002D48414C2F53686D696E676F2D48414C03 +:1049AC002F5348414C2F5372632F53544D33324C79 +:1049BC003458582F5065726970686572616C2F4954 +:1049CC0032432F5348414C5F4932432E6370700081 +:1049DC005348414C5F54494D5F5243435F526567A6 +:1049EC0069737465722067657454696D657252439E +:1049FC00432854696D65725F4B657929000000008E +:104A0C00453A2F50726F6A656374732F456D6265FA +:104A1C00646465642F53686D696E676F2D48414CF3 +:104A2C002F53686D696E676F2D48414C2F53484169 +:104A3C004C2F496E636C7564652F50657269706894 +:104A4C006572616C2F54696D65722F5265672F53B7 +:104A5C0048414C5F54494D5F5245475F4C343332AB +:104A6C004B432E680000000074696D65725F6B65C6 +:104A7C007920213D2054696D65725F4B65793A3A16 +:104A8C00535F54494D5F494E56414C4944202626AC +:104A9C002074696D65725F6B657920213D205469C6 +:104AAC006D65725F4B65793A3A4E554D5F54494D81 +:104ABC00455253007374617469632054696D657257 +:104ACC00262054696D65724D616E616765723A3A64 +:104ADC006765742854696D65725F4B6579290000B0 +:104AEC00453A2F50726F6A656374732F456D62651A +:104AFC00646465642F53686D696E676F2D48414C13 +:104B0C002F53686D696E676F2D48414C2F53484188 +:104B1C004C2F5372632F53544D33324C3458582FFF +:104B2C005065726970686572616C2F54696D65723D +:104B3C002F5348414C5F54494D2E63707000000058 +:104B4C00636F6E737465787072205348414C5F5577 +:104B5C004152545F456E61626C655F526567697363 +:104B6C007465722067657455415254456E61626C70 +:104B7C006552656728554152545F506169725F4BAD +:104B8C0065792900453A2F50726F6A656374732FEB +:104B9C00456D6265646465642F53686D696E676FFB +:104BAC002D48414C2F53686D696E676F2D48414CF1 +:104BBC002F5348414C2F496E636C7564652F5065BB +:104BCC00726970686572616C2F554152542F526531 +:104BDC00672F5348414C5F554152545F5245475FD4 +:104BEC004C3433324B432E680000000073746174F4 +:104BFC006963205348414C5F55415254262055411E +:104C0C0052544D616E616765723A3A6765742875E6 +:104C1C00696E74385F742900453A2F50726F6A655B +:104C2C006374732F456D6265646465642F53686D9E +:104C3C00696E676F2D48414C2F53686D696E676FB5 +:104C4C002D48414C2F5348414C2F5372632F5354D2 +:104C5C004D33324C3458582F5065726970686572F8 +:104C6C00616C2F554152542F5348414C5F55415262 +:104C7C00542E63707000000041303A25752C413180 +:104C8C003A25752C41333A25752C41343A25752C2F +:104C9C0041353A25752C41363A25750D0A00000030 +:104CAC005468726573686F6C64732063616C6962BD +:104CBC00726174656420746F3A2041303A25752C0A +:104CCC0041313A25752C41333A25752C41343A251E +:104CDC00752C41353A25752C41363A25750D0A004F +:104CEC0048656C6C6F330D0A000000000000004832 +:104CFC00000400481A1C363718190000002C01401B +:104D0C000000004000100040001400400040014032 +:104D1C0000440140A0860100400D0300801A0600EB +:104D2C0000350C0040420F0080841E0000093D003D +:104D3C0000127A000024F40000366E010048E801ED +:104D4C00006CDC0200000000010203040000000003 +:104D5C000000000001020304060708092C206675F8 +:104D6C006E6374696F6E3A20006173736572746957 +:104D7C006F6E2022257322206661696C65643A206F +:104D8C0066696C6520222573222C206C696E652067 +:104D9C002564257325730A00232D302B2000686CA5 +:104DAC004C00656667454647003031323334353642 +:104DBC00373839414243444546003031323334357B +:104DCC003637383961626364656600003E410C41D8 +:104DDC001141274136410341064115410F410E4116 +:104DEC00264113412941024119410A410B4100005E +:084DFC0094B3FF7F01000000E9 +:104E040029030008A1040008C10E00085914000871 +:104E14008D1900088D1D000809220008192A0008B0 +:044E2400010300087E +:104E280000000000FF00000004040400040404045F +:104E380000093D00400100200200000001010000BF +:104E4800050000000600000008000000090000003E +:104E58000A0000000C000000000000000300000031 +:104E680078010020480000200000000078010020A0 +:104E7800E0010020480200200000000000000000BF +:104E8800000000000000000000000000000000001A +:104E9800000000000000000000000000000000000A +:104EA80000000000000000000000000000000000FA +:044EB80000000000F6 +:0400000508002A21A4 +:00000001FF