From cbd17ac9e354cf5c95c7f3ab8c2b345821e6b46e Mon Sep 17 00:00:00 2001 From: gaoxu Date: Tue, 14 Jul 2026 18:15:44 +0800 Subject: [PATCH 1/4] feat(isp): support isp dma input and add example --- components/esp_driver_isp/CMakeLists.txt | 8 +- .../esp_driver_isp/include/driver/isp_core.h | 1 + .../esp_driver_isp/include/driver/isp_dma.h | 39 +++ .../include/esp_private/isp_private.h | 47 +++- components/esp_driver_isp/src/isp_core.c | 60 ++-- components/esp_driver_isp/src/isp_dma.c | 265 ++++++++++++++++++ .../esp_hal_cam/esp32p4/include/hal/isp_ll.h | 78 +++++- .../esp32p4/include/hal/dw_gdma_ll.h | 2 + docs/en/api-reference/peripherals/isp.rst | 10 + docs/zh_CN/api-reference/peripherals/isp.rst | 10 + examples/peripherals/.build-test-rules.yml | 8 + .../peripherals/isp/dma_input/CMakeLists.txt | 8 + examples/peripherals/isp/dma_input/README.md | 53 ++++ .../isp/dma_input/main/CMakeLists.txt | 3 + .../isp/dma_input/main/isp_dma_main.c | 153 ++++++++++ .../isp/dma_input/pytest_isp_dma_input.py | 175 ++++++++++++ .../isp/dma_input/sdkconfig.defaults | 1 + 17 files changed, 902 insertions(+), 19 deletions(-) create mode 100644 components/esp_driver_isp/include/driver/isp_dma.h create mode 100644 components/esp_driver_isp/src/isp_dma.c create mode 100644 examples/peripherals/isp/dma_input/CMakeLists.txt create mode 100644 examples/peripherals/isp/dma_input/README.md create mode 100644 examples/peripherals/isp/dma_input/main/CMakeLists.txt create mode 100644 examples/peripherals/isp/dma_input/main/isp_dma_main.c create mode 100644 examples/peripherals/isp/dma_input/pytest_isp_dma_input.py create mode 100644 examples/peripherals/isp/dma_input/sdkconfig.defaults diff --git a/components/esp_driver_isp/CMakeLists.txt b/components/esp_driver_isp/CMakeLists.txt index e70375f3291..fe69095f571 100644 --- a/components/esp_driver_isp/CMakeLists.txt +++ b/components/esp_driver_isp/CMakeLists.txt @@ -6,10 +6,16 @@ set(public_include "include") set(priv_requires "esp_driver_gpio") -set(requires "esp_hal_cam") + +if(${target} STREQUAL "linux") + set(requires "") +else() + set(requires "esp_hal_cam" "esp_mm" "esp_driver_dma") +endif() if(CONFIG_SOC_ISP_SUPPORTED) list(APPEND srcs "src/isp_core.c" + "src/isp_dma.c" "src/isp_af.c" "src/isp_ccm.c" "src/isp_awb.c" diff --git a/components/esp_driver_isp/include/driver/isp_core.h b/components/esp_driver_isp/include/driver/isp_core.h index bcc2c4de5cd..6869fac72cb 100644 --- a/components/esp_driver_isp/include/driver/isp_core.h +++ b/components/esp_driver_isp/include/driver/isp_core.h @@ -32,6 +32,7 @@ typedef struct { uint32_t h_res; ///< Input horizontal resolution, i.e. the number of pixels in a line uint32_t v_res; ///< Input vertical resolution, i.e. the number of lines in a frame color_raw_element_order_t bayer_order; ///< Bayer order + uint32_t dma_burst_size; ///< DMA output burst length in units of 64-bit beats. Set to 0 to use default value 16 int intr_priority; ///< The interrupt priority, range 0~3, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) struct { uint32_t bypass_isp : 1; ///< Bypass ISP pipelines diff --git a/components/esp_driver_isp/include/driver/isp_dma.h b/components/esp_driver_isp/include/driver/isp_dma.h new file mode 100644 index 00000000000..7bb2cc8585d --- /dev/null +++ b/components/esp_driver_isp/include/driver/isp_dma.h @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "driver/isp_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Process one ISP DMA frame: feed the input buffer through the ISP and wait for completion + * + * @note Input buffer content should be ready before calling this function. If the buffers are in + * cacheable memory, the caller should synchronize them around DMA access. Buffer sizes are + * derived from the ISP processor resolution and pixel formats. Both buffers must be 8-byte + * aligned. This function blocks until both input and output DMA channels finish. + * + * @param[in] proc Processor handle + * @param[in] output_buffer Destination buffer for ISP output (8-byte aligned) + * @param[in] input_buffer Source input buffer for RAW frame data (8-byte aligned) + * @param[in] timeout_ms Timeout in milliseconds for waiting transfer completion + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG Invalid argument + * - ESP_ERR_TIMEOUT Wait timeout + */ +esp_err_t esp_isp_dma_process_frame(isp_proc_handle_t proc, void *output_buffer, const void *input_buffer, uint32_t timeout_ms); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_isp/include/esp_private/isp_private.h b/components/esp_driver_isp/include/esp_private/isp_private.h index 076ef6ab894..140f9b9f261 100644 --- a/components/esp_driver_isp/include/esp_private/isp_private.h +++ b/components/esp_driver_isp/include/esp_private/isp_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -58,6 +58,8 @@ typedef enum { /*--------------------------------------------------------------- Driver Context ---------------------------------------------------------------*/ +typedef struct esp_isp_dma_frame_ctx_t esp_isp_dma_frame_ctx_t; + typedef struct isp_processor_t { int proc_id; isp_clk_src_t clk_src; @@ -70,10 +72,14 @@ typedef struct isp_processor_t { DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(spinlock); isp_color_t in_color_format; isp_color_t out_color_format; + isp_input_data_source_t input_data_source; uint32_t h_res; uint32_t v_res; color_raw_element_order_t bayer_order; bool bypass_isp; + uint32_t dma_in_burst_len; // ISP DMA input burst length (64-bit beats), kept in sync with the input GDMA dst MSIZE + uint32_t dma_out_burst_len; // ISP DMA output burst length (64-bit beats) + esp_isp_dma_frame_ctx_t *dma_frame_ctx; /* sub module contexts */ isp_af_ctlr_t af_ctlr[ISP_LL_AF_CTLR_NUMS]; isp_awb_ctlr_t awb_ctlr; @@ -131,6 +137,45 @@ bool esp_isp_awb_isr(isp_proc_handle_t proc, uint32_t awb_events); bool esp_isp_sharpen_isr(isp_proc_handle_t proc, uint32_t sharp_events); bool esp_isp_hist_isr(isp_proc_handle_t proc, uint32_t hist_events); +/*--------------------------------------------------------------- + DMA INPUT +---------------------------------------------------------------*/ +/** + * @brief Configure the ISP DMA input path (frame size, burst length, data type) + * + * @note Internal helper invoked while creating a processor whose input source is DWGDMA. + * + * @param[in] proc Processor handle + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG Invalid input color format or frame size + */ +esp_err_t isp_dma_configure_input(isp_proc_handle_t proc); + +/** + * @brief Create the ISP DMA frame context + * + * @note Internal helper invoked while creating a processor whose input source is DWGDMA. + * + * @param[in] proc Processor handle + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG Invalid processor, burst length, or frame size + * - ESP_ERR_INVALID_STATE Processor input source is not DWGDMA or the context already exists + * - ESP_ERR_NO_MEM Failed to allocate the context or synchronization objects + * - Other errors returned by the underlying DMA driver + */ +esp_err_t isp_dma_new_frame_ctx(isp_proc_handle_t proc); + +/** + * @brief Delete the ISP DMA frame context + * + * @param[in] proc Processor handle + */ +void isp_dma_del_frame_ctx(isp_proc_handle_t proc); + #ifdef __cplusplus } #endif diff --git a/components/esp_driver_isp/src/isp_core.c b/components/esp_driver_isp/src/isp_core.c index c97423cc29c..13d0ee28cdf 100644 --- a/components/esp_driver_isp/src/isp_core.c +++ b/components/esp_driver_isp/src/isp_core.c @@ -18,6 +18,7 @@ #include "esp_private/mipi_csi_share_hw_ctrl.h" #include "hal/hal_utils.h" #include "hal/color_hal.h" +#include "hal/mipi_csi_brg_ll.h" #include "soc/mipi_csi_bridge_struct.h" #include "hal/isp_periph.h" #include "soc/soc_caps.h" @@ -79,7 +80,17 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ esp_err_t ret = ESP_FAIL; ESP_RETURN_ON_FALSE(proc_config && ret_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); ESP_RETURN_ON_FALSE(proc_config->h_res <= ISP_LL_HSIZE_MAX, ESP_ERR_INVALID_ARG, TAG, "invalid h_res"); - ESP_RETURN_ON_FALSE(proc_config->input_data_source != ISP_INPUT_DATA_SOURCE_DWGDMA, ESP_ERR_NOT_SUPPORTED, TAG, "input source not supported yet"); + if (proc_config->input_data_source == ISP_INPUT_DATA_SOURCE_DWGDMA) { + ESP_RETURN_ON_FALSE((proc_config->input_data_color_type == ISP_COLOR_RAW8) || + (proc_config->input_data_color_type == ISP_COLOR_RAW10) || + (proc_config->input_data_color_type == ISP_COLOR_RAW12), + ESP_ERR_INVALID_ARG, TAG, "dma input only supports RAW8/RAW10/RAW12"); + uint32_t in_bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(proc_config->input_data_color_type); + uint64_t frame_bits = (uint64_t)proc_config->h_res * proc_config->v_res * in_bits_per_pixel; + ESP_RETURN_ON_FALSE((frame_bits % 64) == 0, ESP_ERR_INVALID_ARG, TAG, "frame bits should be 64-bit aligned"); + ESP_RETURN_ON_FALSE((frame_bits / 64) <= ((1UL << 22) - 1), ESP_ERR_INVALID_ARG, TAG, "frame size exceeds hardware limit"); + ESP_RETURN_ON_FALSE(proc_config->dma_burst_size <= 16, ESP_ERR_INVALID_ARG, TAG, "dma burst size out of range"); + } if (proc_config->flags.bypass_isp) { ESP_RETURN_ON_FALSE(proc_config->input_data_color_type == proc_config->output_data_color_type, ESP_ERR_INVALID_ARG, TAG, "isp is bypassed, input and output data color type should be same"); } @@ -173,7 +184,9 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ isp_ll_yuv_set_range(proc->hal.hw, proc_config->yuv_range); } - if ((out_color_format == ISP_COLOR_RGB888 || out_color_format == ISP_COLOR_RGB565) && proc_config->input_data_source == ISP_INPUT_DATA_SOURCE_DVP) { + if ((out_color_format == ISP_COLOR_RGB888 || out_color_format == ISP_COLOR_RGB565) && + (proc_config->input_data_source == ISP_INPUT_DATA_SOURCE_DVP || + proc_config->input_data_source == ISP_INPUT_DATA_SOURCE_DWGDMA)) { isp_ll_color_enable(proc->hal.hw, true); // workaround for DIG-474 } if (proc_config->flags.byte_swap_en) { @@ -184,16 +197,23 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ proc->in_color_format = in_color_format; proc->out_color_format = out_color_format; + proc->input_data_source = proc_config->input_data_source; proc->h_res = proc_config->h_res; proc->v_res = proc_config->v_res; proc->bayer_order = proc_config->bayer_order; proc->bypass_isp = proc_config->flags.bypass_isp; + proc->dma_out_burst_len = proc_config->dma_burst_size; + if (proc->input_data_source == ISP_INPUT_DATA_SOURCE_DWGDMA) { + ESP_GOTO_ON_ERROR(isp_dma_configure_input(proc), err, TAG, "configure dma input failed"); + ESP_GOTO_ON_ERROR(isp_dma_new_frame_ctx(proc), err, TAG, "create dma frame context failed"); + } *ret_proc = proc; return ESP_OK; err: + isp_dma_del_frame_ctx(proc); if (proc->intr_hdl) { esp_isp_deregister_isr(proc, ISP_SUBMODULE_GENERAL); } @@ -207,6 +227,8 @@ esp_err_t esp_isp_del_processor(isp_proc_handle_t proc) ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); ESP_RETURN_ON_FALSE(atomic_load(&proc->isp_fsm) == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "processor isn't in init state"); + isp_dma_del_frame_ctx(proc); + //declaim first, then do free ESP_RETURN_ON_ERROR(s_isp_declaim_processor(proc), TAG, "declaim processor fail"); #if SOC_ISP_SHARE_CSI_BRG @@ -338,20 +360,26 @@ static void IRAM_ATTR s_isp_isr_dispatcher(void *arg) do_dispatch = false; } - if ((error_events & ISP_LL_EVENT_DATA_TYPE_ERR) || (error_events & ISP_LL_EVENT_DATA_TYPE_SETTING_ERR)) { - ESP_EARLY_LOGE(TAG, "data type error"); - } - if ((error_events & ISP_LL_EVENT_ASYNC_FIFO_OVF) || (error_events & ISP_LL_EVENT_BUF_FULL)) { - ESP_EARLY_LOGE(TAG, "fifo overflow"); - } - if ((error_events & ISP_LL_EVENT_HVNUM_SETTING_ERR) || (error_events & ISP_LL_EVENT_MIPI_HNUM_UNMATCH)) { - ESP_EARLY_LOGE(TAG, "hnum / vnum setting error"); - } - if (error_events & ISP_LL_EVENT_GAMMA_XCOORD_ERR) { - ESP_EARLY_LOGE(TAG, "gamma xcoord error"); - } - if (error_events & ISP_LL_EVENT_CROP_ERR) { - ESP_EARLY_LOGE(TAG, "crop error"); + if (error_events) { + if ((error_events & ISP_LL_EVENT_DATA_TYPE_ERR) || (error_events & ISP_LL_EVENT_DATA_TYPE_SETTING_ERR)) { + ESP_EARLY_LOGE(TAG, "data type error"); + } + if ((error_events & ISP_LL_EVENT_ASYNC_FIFO_OVF)) { + ESP_EARLY_LOGE(TAG, "fifo overflow"); + } + if ((error_events & ISP_LL_EVENT_BUF_FULL)) { + //This error does not affect the operation of the ISP + ESP_EARLY_LOGD(TAG, "buffer full"); + } + if ((error_events & ISP_LL_EVENT_HVNUM_SETTING_ERR) || (error_events & ISP_LL_EVENT_MIPI_HNUM_UNMATCH)) { + ESP_EARLY_LOGE(TAG, "hnum / vnum setting error"); + } + if (error_events & ISP_LL_EVENT_GAMMA_XCOORD_ERR) { + ESP_EARLY_LOGE(TAG, "gamma xcoord error"); + } + if (error_events & ISP_LL_EVENT_CROP_ERR) { + ESP_EARLY_LOGE(TAG, "crop error"); + } } if (need_yield) { diff --git a/components/esp_driver_isp/src/isp_dma.c b/components/esp_driver_isp/src/isp_dma.c new file mode 100644 index 00000000000..a22bed0863a --- /dev/null +++ b/components/esp_driver_isp/src/isp_dma.c @@ -0,0 +1,265 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "sdkconfig.h" +#include "esp_log.h" +#include "esp_check.h" +#include "esp_heap_caps.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "driver/isp_dma.h" +#include "esp_private/dw_gdma.h" +#include "esp_private/isp_private.h" +#include "hal/color_hal.h" +#include "hal/isp_ll.h" +#include "hal/mipi_csi_brg_ll.h" + +#define ISP_DMA_IN_BURST_LEN_DFT 8 +#define ISP_DMA_OUT_BURST_LEN_DFT 16 + +struct esp_isp_dma_frame_ctx_t { + isp_proc_handle_t proc; + csi_brg_dev_t *csi_brg_hw; + dw_gdma_channel_handle_t dma_in_chan; + dw_gdma_channel_handle_t dma_out_chan; + SemaphoreHandle_t in_done_sem; + SemaphoreHandle_t out_done_sem; + dw_gdma_block_transfer_config_t dma_out_trans; + dw_gdma_block_transfer_config_t dma_in_trans; + uint32_t input_frame_size_64bit; + uint32_t output_frame_size_64bit; +}; + +static const char *TAG = "ISP_DMA"; + +static bool IRAM_ATTR s_isp_dma_done_cb(dw_gdma_channel_handle_t chan, const dw_gdma_trans_done_event_data_t *event_data, void *user_data) +{ + (void)chan; + (void)event_data; + BaseType_t high_task_woken = pdFALSE; + xSemaphoreGiveFromISR(*(SemaphoreHandle_t *)user_data, &high_task_woken); + return high_task_woken == pdTRUE; +} + +static dw_gdma_burst_items_t s_isp_dma_burst_len_to_items(uint32_t burst_len) +{ + switch (burst_len) { + case 1: return DW_GDMA_BURST_ITEMS_1; + case 4: return DW_GDMA_BURST_ITEMS_4; + case 8: return DW_GDMA_BURST_ITEMS_8; + default: return DW_GDMA_BURST_ITEMS_8; + } +} + +static void s_isp_dma_frame_ctx_destroy(struct esp_isp_dma_frame_ctx_t *ctx) +{ + if (!ctx) { + return; + } + if (ctx->csi_brg_hw) { + mipi_csi_brg_ll_enable(ctx->csi_brg_hw, false); + } + if (ctx->dma_in_chan) { + dw_gdma_channel_enable_ctrl(ctx->dma_in_chan, false); + dw_gdma_del_channel(ctx->dma_in_chan); + } + if (ctx->dma_out_chan) { + dw_gdma_channel_enable_ctrl(ctx->dma_out_chan, false); + dw_gdma_del_channel(ctx->dma_out_chan); + } + if (ctx->in_done_sem) { + vSemaphoreDelete(ctx->in_done_sem); + } + if (ctx->out_done_sem) { + vSemaphoreDelete(ctx->out_done_sem); + } + free(ctx); +} + +esp_err_t isp_dma_configure_input(isp_proc_handle_t proc) +{ + ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(proc->input_data_source == ISP_INPUT_DATA_SOURCE_DWGDMA, ESP_ERR_INVALID_ARG, TAG, "processor input source is not dwgdma"); + + bool valid_format = isp_ll_dma_set_data_type(proc->hal.hw, proc->in_color_format); + ESP_RETURN_ON_FALSE(valid_format, ESP_ERR_INVALID_ARG, TAG, "dma input only supports RAW8/RAW10/RAW12"); + + uint32_t in_bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(proc->in_color_format); + uint64_t frame_bits = (uint64_t)proc->h_res * proc->v_res * in_bits_per_pixel; + ESP_RETURN_ON_FALSE((frame_bits % 64) == 0, ESP_ERR_INVALID_ARG, TAG, "frame bits should be 64-bit aligned"); + + uint64_t frame_size_in_64bit = frame_bits / 64; + ESP_RETURN_ON_FALSE(frame_size_in_64bit <= ((1UL << 22) - 1), ESP_ERR_INVALID_ARG, TAG, "frame size exceeds hardware limit"); + + /* + * The input burst length is fixed at ISP_DMA_IN_BURST_LEN_DFT: it must be representable as a + * DW-GDMA MSIZE (1/4/8) and not exceed the ISP input async FIFO capacity (8 x 64-bit). It also + * has to equal the input GDMA dst MSIZE (derived from proc->dma_in_burst_len in + * isp_dma_new_frame_ctx), otherwise the async FIFO overflows. + */ + isp_ll_dma_set_frame_size(proc->hal.hw, (uint32_t)frame_size_in_64bit); + isp_ll_dma_set_burst_len(proc->hal.hw, ISP_DMA_IN_BURST_LEN_DFT); + isp_ll_dma_apply_config(proc->hal.hw); + proc->dma_in_burst_len = ISP_DMA_IN_BURST_LEN_DFT; + + return ESP_OK; +} + +esp_err_t isp_dma_new_frame_ctx(isp_proc_handle_t proc) +{ + esp_err_t ret = ESP_FAIL; + ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(proc->input_data_source == ISP_INPUT_DATA_SOURCE_DWGDMA, ESP_ERR_INVALID_STATE, TAG, "processor input source is not dwgdma"); + ESP_RETURN_ON_FALSE(!proc->dma_frame_ctx, ESP_ERR_INVALID_STATE, TAG, "dma frame context already exists"); + + uint32_t output_burst_len = proc->dma_out_burst_len ? proc->dma_out_burst_len : ISP_DMA_OUT_BURST_LEN_DFT; + ESP_RETURN_ON_FALSE(output_burst_len > 0 && output_burst_len <= 16, ESP_ERR_INVALID_ARG, TAG, "output burst len out of range"); + + uint32_t in_bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(proc->in_color_format); + uint32_t out_bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(proc->out_color_format); + uint64_t input_frame_bits = (uint64_t)proc->h_res * proc->v_res * in_bits_per_pixel; + uint64_t output_frame_bits = (uint64_t)proc->h_res * proc->v_res * out_bits_per_pixel; + ESP_RETURN_ON_FALSE((input_frame_bits % 64) == 0, ESP_ERR_INVALID_ARG, TAG, "input frame bits should be 64-bit aligned"); + ESP_RETURN_ON_FALSE((output_frame_bits % 64) == 0, ESP_ERR_INVALID_ARG, TAG, "output frame bits should be 64-bit aligned"); + + struct esp_isp_dma_frame_ctx_t *ctx = heap_caps_calloc(1, sizeof(struct esp_isp_dma_frame_ctx_t), ISP_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(ctx, ESP_ERR_NO_MEM, err, TAG, "no mem for dma frame context"); + + ctx->proc = proc; + ctx->input_frame_size_64bit = input_frame_bits / 64; + ctx->output_frame_size_64bit = output_frame_bits / 64; + + csi_brg_dev_t *csi_brg_hw = MIPI_CSI_BRG_LL_GET_HW(proc->csi_brg_id); + ctx->csi_brg_hw = csi_brg_hw; + mipi_csi_brg_ll_set_intput_data_h_pixel_num(csi_brg_hw, proc->h_res); + mipi_csi_brg_ll_set_intput_data_v_row_num(csi_brg_hw, proc->v_res); + mipi_csi_brg_ll_set_burst_len(csi_brg_hw, 512); + mipi_csi_brg_ll_enable(csi_brg_hw, true); + + ctx->out_done_sem = xSemaphoreCreateBinary(); + ESP_GOTO_ON_FALSE(ctx->out_done_sem, ESP_ERR_NO_MEM, err, TAG, "no mem for output semaphore"); + ctx->in_done_sem = xSemaphoreCreateBinary(); + ESP_GOTO_ON_FALSE(ctx->in_done_sem, ESP_ERR_NO_MEM, err, TAG, "no mem for input semaphore"); + + dw_gdma_channel_alloc_config_t dma_out_alloc = { + .src = { + .block_transfer_type = DW_GDMA_BLOCK_TRANSFER_CONTIGUOUS, + .role = DW_GDMA_ROLE_PERIPH_CSI, + .handshake_type = DW_GDMA_HANDSHAKE_HW, + .num_outstanding_requests = 5, + .status_fetch_addr = MIPI_CSI_BRG_MEM_BASE, + }, + .dst = { + .block_transfer_type = DW_GDMA_BLOCK_TRANSFER_CONTIGUOUS, + .role = DW_GDMA_ROLE_MEM, + .handshake_type = DW_GDMA_HANDSHAKE_HW, + .num_outstanding_requests = 5, + }, + .flow_controller = DW_GDMA_FLOW_CTRL_SRC, + .chan_priority = 1, + }; + ESP_GOTO_ON_ERROR(dw_gdma_new_channel(&dma_out_alloc, &ctx->dma_out_chan), err, TAG, "create output dma channel failed"); + + dw_gdma_channel_alloc_config_t dma_in_alloc = { + .src = { + .block_transfer_type = DW_GDMA_BLOCK_TRANSFER_CONTIGUOUS, + .role = DW_GDMA_ROLE_MEM, + .handshake_type = DW_GDMA_HANDSHAKE_SW, + .num_outstanding_requests = 2, + }, + .dst = { + .block_transfer_type = DW_GDMA_BLOCK_TRANSFER_CONTIGUOUS, + .role = DW_GDMA_ROLE_PERIPH_ISP, + .handshake_type = DW_GDMA_HANDSHAKE_HW, + .num_outstanding_requests = 1, + }, + .flow_controller = DW_GDMA_FLOW_CTRL_DST, + .chan_priority = 1, + }; + ESP_GOTO_ON_ERROR(dw_gdma_new_channel(&dma_in_alloc, &ctx->dma_in_chan), err, TAG, "create input dma channel failed"); + + ctx->dma_out_trans = (dw_gdma_block_transfer_config_t) { + .src = { + .addr = MIPI_CSI_BRG_MEM_BASE, + .width = DW_GDMA_TRANS_WIDTH_64, + .burst_mode = DW_GDMA_BURST_MODE_FIXED, + .burst_items = DW_GDMA_BURST_ITEMS_512, + .burst_len = output_burst_len, + }, + .dst = { + .width = DW_GDMA_TRANS_WIDTH_64, + .burst_mode = DW_GDMA_BURST_MODE_INCREMENT, + .burst_items = DW_GDMA_BURST_ITEMS_512, + .burst_len = output_burst_len, + }, + .size = ctx->output_frame_size_64bit, + }; + ctx->dma_in_trans = (dw_gdma_block_transfer_config_t) { + .src = { + .width = DW_GDMA_TRANS_WIDTH_64, + .burst_mode = DW_GDMA_BURST_MODE_INCREMENT, + .burst_items = DW_GDMA_BURST_ITEMS_32, + }, + .dst = { + .addr = MIPI_CSI_BRG_MEM_BASE, + .width = DW_GDMA_TRANS_WIDTH_64, + .burst_mode = DW_GDMA_BURST_MODE_FIXED, + .burst_items = s_isp_dma_burst_len_to_items(proc->dma_in_burst_len), + }, + .size = ctx->input_frame_size_64bit, + }; + + dw_gdma_event_callbacks_t dma_cbs = { + .on_full_trans_done = s_isp_dma_done_cb, + }; + ESP_GOTO_ON_ERROR(dw_gdma_channel_register_event_callbacks(ctx->dma_out_chan, &dma_cbs, &ctx->out_done_sem), err, TAG, "register output dma callback failed"); + ESP_GOTO_ON_ERROR(dw_gdma_channel_register_event_callbacks(ctx->dma_in_chan, &dma_cbs, &ctx->in_done_sem), err, TAG, "register input dma callback failed"); + + proc->dma_frame_ctx = ctx; + return ESP_OK; +err: + s_isp_dma_frame_ctx_destroy(ctx); + return ret; +} + +void isp_dma_del_frame_ctx(isp_proc_handle_t proc) +{ + if (!proc || !proc->dma_frame_ctx) { + return; + } + s_isp_dma_frame_ctx_destroy(proc->dma_frame_ctx); + proc->dma_frame_ctx = NULL; +} + +esp_err_t esp_isp_dma_process_frame(isp_proc_handle_t proc, void *output_buffer, const void *input_buffer, uint32_t timeout_ms) +{ + ESP_RETURN_ON_FALSE(proc && proc->dma_frame_ctx && output_buffer && input_buffer, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE((((uintptr_t)output_buffer) % 8) == 0, ESP_ERR_INVALID_ARG, TAG, "output buffer not 8-byte aligned"); + ESP_RETURN_ON_FALSE((((uintptr_t)input_buffer) % 8) == 0, ESP_ERR_INVALID_ARG, TAG, "input buffer not 8-byte aligned"); + + esp_isp_dma_frame_ctx_t *ctx = proc->dma_frame_ctx; + ctx->dma_out_trans.dst.addr = (uint32_t)output_buffer; + ctx->dma_in_trans.src.addr = (uint32_t)input_buffer; + + ESP_RETURN_ON_ERROR(dw_gdma_channel_config_transfer(ctx->dma_out_chan, &ctx->dma_out_trans), TAG, "configure output transfer failed"); + ESP_RETURN_ON_ERROR(dw_gdma_channel_config_transfer(ctx->dma_in_chan, &ctx->dma_in_trans), TAG, "configure input transfer failed"); + dw_gdma_channel_enable_ctrl(ctx->dma_out_chan, true); + dw_gdma_channel_enable_ctrl(ctx->dma_in_chan, true); + + isp_ll_dma_trigger_frame(ctx->proc->hal.hw); + + if (xSemaphoreTake(ctx->in_done_sem, pdMS_TO_TICKS(timeout_ms)) != pdTRUE) { + ESP_LOGE(TAG, "wait input done timeout"); + return ESP_ERR_TIMEOUT; + } + if (xSemaphoreTake(ctx->out_done_sem, pdMS_TO_TICKS(timeout_ms)) != pdTRUE) { + ESP_LOGE(TAG, "wait output done timeout"); + return ESP_ERR_TIMEOUT; + } + return ESP_OK; +} diff --git a/components/esp_hal_cam/esp32p4/include/hal/isp_ll.h b/components/esp_hal_cam/esp32p4/include/hal/isp_ll.h index 5749c95d4b7..d6599b607b3 100644 --- a/components/esp_hal_cam/esp32p4/include/hal/isp_ll.h +++ b/components/esp_hal_cam/esp32p4/include/hal/isp_ll.h @@ -28,7 +28,7 @@ extern "C" { #define ISP_LL_PERIPH_NUMS 1U #define ISP_LL_HSIZE_MAX 1920 -#define ISP_LL_VSIZE_MAX 1080 +#define ISP_LL_VSIZE_MAX 1280 /*--------------------------------------------------------------- Clock @@ -535,6 +535,82 @@ static inline void isp_ll_enable_line_end_packet_exist(isp_dev_t *hw, bool en) hw->frame_cfg.hsync_end_exist = en; } +/** + * @brief Set DMA input data type + * + * @param[in] hw Hardware instance address + * @param[in] format color format, see `isp_color_t` + * + * @return true for valid format, false for invalid format + */ +static inline bool isp_ll_dma_set_data_type(isp_dev_t *hw, isp_color_t format) +{ + bool valid = false; + + switch (format) { + case ISP_COLOR_RAW8: + hw->dma_cntl.dma_data_type = 0x2A; + valid = true; + break; + case ISP_COLOR_RAW10: + hw->dma_cntl.dma_data_type = 0x2B; + valid = true; + break; + case ISP_COLOR_RAW12: + hw->dma_cntl.dma_data_type = 0x2C; + valid = true; + break; + default: + break; + } + + return valid; +} + +/** + * @brief Set DMA input burst length in units of 64-bit + * + * @param[in] hw Hardware instance address + * @param[in] burst_len Number of 64-bit beats in one DMA burst + */ +static inline void isp_ll_dma_set_burst_len(isp_dev_t *hw, uint32_t burst_len) +{ + hw->dma_cntl.dma_burst_len = burst_len; +} + +/** + * @brief Set DMA input total frame size in units of 64-bit + * + * @param[in] hw Hardware instance address + * @param[in] num64b Number of 64-bit words in one frame + */ +static inline void isp_ll_dma_set_frame_size(isp_dev_t *hw, uint32_t num64b) +{ + hw->dma_raw_data.dma_raw_num_total = num64b; + hw->dma_raw_data.dma_raw_num_total_set = 1; +} + +/** + * @brief Apply DMA input registers + * + * @param[in] hw Hardware instance address + */ +static inline void isp_ll_dma_apply_config(isp_dev_t *hw) +{ + hw->dma_cntl.dma_update_reg = 1; + while (hw->dma_cntl.dma_update_reg); +} + +/** + * @brief Trigger one DMA input frame transfer + * + * @param[in] hw Hardware instance address + */ +static inline void isp_ll_dma_trigger_frame(isp_dev_t *hw) +{ + hw->dma_cntl.dma_en = 1; +} + /** * @brief Get if demosaic is enabled * diff --git a/components/esp_hal_dma/esp32p4/include/hal/dw_gdma_ll.h b/components/esp_hal_dma/esp32p4/include/hal/dw_gdma_ll.h index 0295fee38cc..fe183849be0 100644 --- a/components/esp_hal_dma/esp32p4/include/hal/dw_gdma_ll.h +++ b/components/esp_hal_dma/esp32p4/include/hal/dw_gdma_ll.h @@ -415,6 +415,8 @@ static inline void dw_gdma_ll_channel_set_dst_master_port(dw_gdma_dev_t *dev, ui { if (mem_addr == MIPI_DSI_BRG_MEM_BASE) { dev->ch[channel].ctl0.dms = DW_GDMA_LL_MASTER_PORT_MIPI_DSI; + } else if (mem_addr == MIPI_CSI_BRG_MEM_BASE) { + dev->ch[channel].ctl0.dms = DW_GDMA_LL_MASTER_PORT_MIPI_CSI; } else { dev->ch[channel].ctl0.dms = DW_GDMA_LL_MASTER_PORT_MEMORY; } diff --git a/docs/en/api-reference/peripherals/isp.rst b/docs/en/api-reference/peripherals/isp.rst index f53ce1d440d..8bf8e5c3556 100644 --- a/docs/en/api-reference/peripherals/isp.rst +++ b/docs/en/api-reference/peripherals/isp.rst @@ -240,6 +240,15 @@ Before doing ISP pipeline, you need to enable the ISP processor first, by callin Calling :cpp:func:`esp_isp_disable` does the opposite, that is, put the driver back to the **init** state. +.. _isp-dma-input: + +ISP DMA Input +~~~~~~~~~~~~~ + +Besides image streams from camera controllers, the ISP can also read image frames from system memory through DW-GDMA. To use DMA input, set :cpp:member:`esp_isp_processor_cfg_t::input_data_source` in :cpp:type:`esp_isp_processor_cfg_t` to :cpp:enumerator:`ISP_INPUT_DATA_SOURCE_DWGDMA`, and configure the input format, output format, and resolution according to the image frame. + +DMA input is useful for feeding software-generated data, offline RAW images, or other test images in memory into the ISP. It can be used to validate an ISP pipeline without a camera sensor, reproduce issues with a specific input image, or generate inspectable output images in pytest. Call :cpp:func:`esp_isp_dma_process_frame` to send one input buffer to the ISP and write the processed image into an output buffer. The input and output buffers must be accessible by DMA; if cacheable memory is used, perform the required cache synchronization before and after the DMA transfer. + ISP AF Controller ~~~~~~~~~~~~~~~~~ @@ -958,6 +967,7 @@ Application Examples -------------------- * :example:`peripherals/isp/multi_pipelines` demonstrates how to use the ISP pipelines to process the image signals from camera sensors and display the video on LCD screen via DSI peripheral. +* :example:`peripherals/isp/dma_input` demonstrates how to feed software-generated RAW8 Bayer data into the ISP through DW-GDMA and save the processed RGB888 frames as PPM images in pytest. * `esp_video/examples `_ provides some examples of enabling ISP control algorithms. API Reference diff --git a/docs/zh_CN/api-reference/peripherals/isp.rst b/docs/zh_CN/api-reference/peripherals/isp.rst index 25edb05f509..6397d4f7122 100644 --- a/docs/zh_CN/api-reference/peripherals/isp.rst +++ b/docs/zh_CN/api-reference/peripherals/isp.rst @@ -240,6 +240,15 @@ ISP 调用 :cpp:func:`esp_isp_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。 +.. _isp-dma-input: + +ISP DMA 输入 +~~~~~~~~~~~~ + +除来自摄像头控制器的数据流外,ISP 还可以通过 DW-GDMA 从系统存储中读取图像帧作为输入。使用 DMA 输入时,应在 :cpp:type:`esp_isp_processor_cfg_t` 中将 :cpp:member:`esp_isp_processor_cfg_t::input_data_source` 配置为 :cpp:enumerator:`ISP_INPUT_DATA_SOURCE_DWGDMA`,并根据输入图像格式设置输入、输出格式及分辨率。 + +DMA 输入适用于将软件生成的数据、离线保存的 RAW 图像或其他内存中的测试图像送入 ISP 进行处理。它可用于无摄像头传感器参与时验证 ISP 流水线、复现特定输入图像的问题,或在 pytest 中生成可检查的输出图像。调用 :cpp:func:`esp_isp_dma_process_frame` 可以将一帧输入缓冲区送入 ISP,并将处理后的图像写入输出缓冲区。输入和输出缓冲区需要满足 DMA 访问要求;若使用带 cache 的内存,请在 DMA 传输前后执行必要的 cache 同步。 + ISP AF 控制器 ~~~~~~~~~~~~~ @@ -958,6 +967,7 @@ Kconfig 选项 :ref:`CONFIG_ISP_CTRL_FUNC_IN_IRAM` 支持: -------- * :example:`peripherals/isp/multi_pipelines` 演示了如何使用 ISP 流水线处理来自摄像头传感器的图像信号,并通过 DSI 外设在 LCD 屏幕上显示视频。 +* :example:`peripherals/isp/dma_input` 演示了如何通过 DW-GDMA 将软件生成的 RAW8 Bayer 数据送入 ISP,并在 pytest 中将处理后的 RGB888 帧保存为 PPM 图片。 * `esp_video/examples `_ 中包含自动启用 ISP 控制算法的一些示例。 API 参考 diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 41a59e33b9b..992bad46074 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -283,6 +283,14 @@ examples/peripherals/i3c/i3c_lsm6dscx: - esp_hal_i3c - soc +examples/peripherals/isp/dma_input: + disable: + - if: SOC_ISP_SUPPORTED != 1 + depends_components: + - esp_driver_dma + - esp_driver_isp + - soc + examples/peripherals/isp/multi_pipelines: disable: - if: SOC_MIPI_CSI_SUPPORTED != 1 diff --git a/examples/peripherals/isp/dma_input/CMakeLists.txt b/examples/peripherals/isp/dma_input/CMakeLists.txt new file mode 100644 index 00000000000..813a03e8521 --- /dev/null +++ b/examples/peripherals/isp/dma_input/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.22) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +idf_build_set_property(MINIMAL_BUILD ON) +project(isp_dma_input) diff --git a/examples/peripherals/isp/dma_input/README.md b/examples/peripherals/isp/dma_input/README.md new file mode 100644 index 00000000000..3298c0ab2c3 --- /dev/null +++ b/examples/peripherals/isp/dma_input/README.md @@ -0,0 +1,53 @@ +| Supported Targets | ESP32-P4 | +| ----------------- | -------- | + +# ISP DMA Input Visual Test Example + +## Overview + +This example generates a standard RAW8 Bayer color-bar pattern in software, writes it into a DMA-capable PSRAM input buffer, feeds it into the ISP through DW-GDMA, applies the ISP color adjustment module, and prints the RGB888 output as base64. The pytest script decodes the output into PPM images for inspection. + +The data flow is: + +1. A synthetic RAW8 Bayer **color-bar** pattern is generated in software into the ISP DMA input buffer. +2. The pattern is transferred into the ISP via `DW-GDMA → ISP DMA input`. +3. The ISP processes the data (demosaic, color adjustment) and outputs RGB888 (BGR24 byte layout). +4. The RGB888 frame is base64-encoded and printed with machine-parseable markers. +5. pytest decodes the payload, swaps BGR→RGB, and saves one PPM file per frame. + +## Hardware Required + +- An ESP32-P4 devkit with PSRAM (this example allocates the ISP DMA input/output buffers from PSRAM). + +If you replace the software-generated pattern with a RAW image embedded in flash, copy it into a DMA-capable buffer before feeding it to the ISP DMA input path. + +## How to Use + +Run the test locally. It builds and flashes the example, captures the serial output, and saves one PPM artifact per frame: + +``` +cd examples/peripherals/isp/dma_input +pytest pytest_isp_dma_input.py --target esp32p4 --port PORT +``` + +The pytest log directory (`dut.logdir`) contains `reference.ppm` for the standard reference color-bar image and `isp_dma_input_frame00.ppm`, ... for the decoded ISP output frames. The pytest script checks that the decoded frame contains the expected standard color-bar structure and verifies that the ISP color brightness adjustment brightens the black bar. + +ISP feature-specific setup is kept under `main/isp_features//`, and pytest feature checks are kept under `pytest_features/.py`. The current color brightness check lives in `main/isp_features/color/` and `pytest_features/color_brightness.py`; new ISP feature checks can follow the same pattern while reusing the common DW-GDMA input/output and image parsing flow. + +## Example Output + +Each frame uses the same standard vertical color-bar input pattern with positive color brightness enabled to validate the ISP color adjustment module. + +```text +Feeding 1 frames through ISP DMA input... +IMAGE_META frame=0 width=128 height=96 format=BGR24 encoding=base64 color_brightness=64 +IMAGE_BASE64_BEGIN +IMAGE_BASE64 ... +IMAGE_BASE64_END +Frame 0 done +ISP DMA visual demo done. +``` + +## Reference + +- [ESP-IDF: Image Signal Processor](https://docs.espressif.com/projects/esp-idf/en/latest/esp32p4/api-reference/peripherals/isp.html) diff --git a/examples/peripherals/isp/dma_input/main/CMakeLists.txt b/examples/peripherals/isp/dma_input/main/CMakeLists.txt new file mode 100644 index 00000000000..af79c8d577c --- /dev/null +++ b/examples/peripherals/isp/dma_input/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "isp_dma_main.c" + PRIV_REQUIRES esp_driver_isp esp_mm esp_psram mbedtls + INCLUDE_DIRS ".") diff --git a/examples/peripherals/isp/dma_input/main/isp_dma_main.c b/examples/peripherals/isp/dma_input/main/isp_dma_main.c new file mode 100644 index 00000000000..111b3fd71cc --- /dev/null +++ b/examples/peripherals/isp/dma_input/main/isp_dma_main.c @@ -0,0 +1,153 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "mbedtls/base64.h" +#include "esp_check.h" +#include "esp_cache.h" +#include "esp_heap_caps.h" +#include "driver/isp_dma.h" +#include "driver/isp_core.h" +#include "driver/isp_color.h" + +#define EXAMPLE_WIDTH 128 +#define EXAMPLE_HEIGHT 96 +#define EXAMPLE_BASE64_CHUNK_LEN 384 +#define EXAMPLE_DMA_ALIGN 64 +#define EXAMPLE_FRAME_COUNT 2 + +static const uint8_t s_color_bars[8][3] = { + {255, 255, 255}, // white + {255, 255, 0}, // yellow + { 0, 255, 255}, // cyan + { 0, 255, 0}, // green + {255, 0, 255}, // magenta + {255, 0, 0}, // red + { 0, 0, 255}, // blue + { 0, 0, 0}, // black +}; + +static void s_generate_raw8_color_bars(uint8_t *raw, uint32_t w, uint32_t h) +{ + for (uint32_t y = 0; y < h; y++) { + bool even_row = ((y & 1) == 0); + for (uint32_t x = 0; x < w; x++) { + uint32_t bar = (x * 8) / w; + uint8_t r = s_color_bars[bar][0]; + uint8_t g = s_color_bars[bar][1]; + uint8_t b = s_color_bars[bar][2]; + + bool even_col = ((x & 1) == 0); + if (even_row) { + raw[y * w + x] = even_col ? b : g; + } else { + raw[y * w + x] = even_col ? g : r; + } + } + } +} + +static void *s_alloc_dma_buffer(size_t size) +{ + return heap_caps_aligned_calloc(EXAMPLE_DMA_ALIGN, 1, size, + MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT); +} + +static void s_configure_neutral_color(isp_proc_handle_t isp_proc) +{ + esp_isp_color_config_t color_cfg = { + .color_contrast = { .integer = 1, .decimal = 0 }, + .color_saturation = { .integer = 1, .decimal = 0 }, + .color_hue = 0, + .color_brightness = 0, + }; + + ESP_ERROR_CHECK(esp_isp_color_configure(isp_proc, &color_cfg)); + ESP_ERROR_CHECK(esp_isp_color_enable(isp_proc)); +} + +static void s_print_base64_payload(const unsigned char *encoded, size_t encoded_len) +{ + printf("IMAGE_BASE64_BEGIN\n"); + fflush(stdout); + for (size_t offset = 0; offset < encoded_len; offset += EXAMPLE_BASE64_CHUNK_LEN) { + size_t chunk_len = encoded_len - offset; + if (chunk_len > EXAMPLE_BASE64_CHUNK_LEN) { + chunk_len = EXAMPLE_BASE64_CHUNK_LEN; + } + printf("IMAGE_BASE64 %.*s\n", (int)chunk_len, (const char *)&encoded[offset]); + fflush(stdout); + vTaskDelay(pdMS_TO_TICKS(1)); + } + printf("IMAGE_BASE64_END\n"); + fflush(stdout); +} + +void app_main(void) +{ + const uint32_t h_res = EXAMPLE_WIDTH; + const uint32_t v_res = EXAMPLE_HEIGHT; + const size_t in_size = (size_t)h_res * v_res; // RAW8: 1 byte/pixel + const size_t out_size = (size_t)h_res * v_res * 3; // RGB888: 3 bytes/pixel + + isp_proc_handle_t isp_proc = NULL; + esp_isp_processor_cfg_t isp_cfg = { + .clk_hz = 240 * 1000 * 1000, + .input_data_source = ISP_INPUT_DATA_SOURCE_DWGDMA, + .input_data_color_type = ISP_COLOR_RAW8, + .output_data_color_type = ISP_COLOR_RGB888, + .bayer_order = COLOR_RAW_ELEMENT_ORDER_BGGR, + .has_line_start_packet = false, + .has_line_end_packet = false, + .h_res = h_res, + .v_res = v_res, + .dma_burst_size = 8, + }; + ESP_ERROR_CHECK(esp_isp_new_processor(&isp_cfg, &isp_proc)); + ESP_ERROR_CHECK(esp_isp_enable(isp_proc)); + s_configure_neutral_color(isp_proc); + + uint8_t *isp_in_buf = s_alloc_dma_buffer(in_size); + uint8_t *isp_out_buf = s_alloc_dma_buffer(out_size); + assert(isp_in_buf && isp_out_buf); + + size_t encoded_len = 0; + int ret = mbedtls_base64_encode(NULL, 0, &encoded_len, isp_out_buf, out_size); + ESP_ERROR_CHECK((ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) ? ESP_OK : ESP_FAIL); + unsigned char *encoded = calloc(encoded_len + 1, 1); + assert(encoded); + + printf("Feeding %d frames through ISP DMA input...\n", EXAMPLE_FRAME_COUNT); + for (int frame = 0; frame < EXAMPLE_FRAME_COUNT; frame++) { + s_generate_raw8_color_bars(isp_in_buf, h_res, v_res); + + ESP_ERROR_CHECK(esp_cache_msync(isp_in_buf, in_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M)); + ESP_ERROR_CHECK(esp_isp_dma_process_frame(isp_proc, isp_out_buf, isp_in_buf, 1000)); + ESP_ERROR_CHECK(esp_cache_msync(isp_out_buf, out_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C)); + + size_t out_len = 0; + ESP_ERROR_CHECK(mbedtls_base64_encode(encoded, encoded_len + 1, &out_len, isp_out_buf, out_size) == 0 ? ESP_OK : ESP_FAIL); + + printf("IMAGE_META frame=%d width=%u height=%u format=BGR24 encoding=base64\n", + frame, (unsigned)h_res, (unsigned)v_res); + s_print_base64_payload(encoded, out_len); + printf("Frame %d done\n", frame); + } + printf("ISP DMA visual demo done.\n"); + + free(encoded); + ESP_ERROR_CHECK(esp_isp_color_disable(isp_proc)); + ESP_ERROR_CHECK(esp_isp_disable(isp_proc)); + ESP_ERROR_CHECK(esp_isp_del_processor(isp_proc)); + heap_caps_free(isp_in_buf); + heap_caps_free(isp_out_buf); +} diff --git a/examples/peripherals/isp/dma_input/pytest_isp_dma_input.py b/examples/peripherals/isp/dma_input/pytest_isp_dma_input.py new file mode 100644 index 00000000000..393b040cf0a --- /dev/null +++ b/examples/peripherals/isp/dma_input/pytest_isp_dma_input.py @@ -0,0 +1,175 @@ +# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import base64 +import logging +import re +from dataclasses import dataclass +from pathlib import Path + +import pytest +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets + +IMAGE_META_PATTERN = ( + r'IMAGE_META frame=(?P\d+) width=(?P\d+) height=(?P\d+) ' + r'format=(?P\w+) encoding=(?P\w+)' +) +IMAGE_META_RE = re.compile(IMAGE_META_PATTERN) +IMAGE_CHUNK_PATTERN = ( + r'IMAGE_BASE64 (?P[A-Za-z0-9+/=]+?)' + r'(?=\r?\n|IMAGE_BASE64|IMAGE_BASE64_END|Frame )' +) +IMAGE_OUTPUT_TEMPLATE = 'isp_dma_input_frame{frame:02d}.ppm' +REFERENCE_IMAGE_NAME = 'reference.ppm' +EXPECTED_PIXEL_FORMAT = 'BGR24' +EXPECTED_ENCODING = 'base64' +STANDARD_COLOR_BARS_RGB888 = ( + (255, 255, 255), # white + (255, 255, 0), # yellow + (0, 255, 255), # cyan + (0, 255, 0), # green + (255, 0, 255), # magenta + (255, 0, 0), # red + (0, 0, 255), # blue + (0, 0, 0), # black +) +RGB888_BYTES_PER_PIXEL = 3 +PPM_MAGIC = b'P6' +PPM_MAX_VALUE = b'255' + + +@dataclass(frozen=True) +class ImageMetadata: + frame: int + width: int + height: int + pixel_format: str + encoding: str + + +@dataclass(frozen=True) +class RgbImage: + width: int + height: int + pixels_rgb888: bytes + + def __post_init__(self) -> None: + expected_size = self.width * self.height * RGB888_BYTES_PER_PIXEL + if len(self.pixels_rgb888) != expected_size: + raise ValueError(f'Expected {expected_size} RGB bytes, got {len(self.pixels_rgb888)}') + + +def parse_image_metadata(meta_line: str) -> ImageMetadata: + match = IMAGE_META_RE.fullmatch(meta_line) + if not match: + raise ValueError(f'Invalid image metadata line: {meta_line}') + + return ImageMetadata( + frame=int(match.group('frame')), + width=int(match.group('width')), + height=int(match.group('height')), + pixel_format=match.group('format'), + encoding=match.group('encoding'), + ) + + +def collect_base64_payload(dut: Dut) -> list[str]: + payload_lines: list[str] = [] + while True: + match = dut.expect(rf'IMAGE_BASE64_END|{IMAGE_CHUNK_PATTERN}', timeout=60) + if match.group(0).decode('utf-8') == 'IMAGE_BASE64_END': + return payload_lines + + payload_lines.append(match.group('payload').decode('utf-8')) + + +def _bgr24_to_rgb888(raw_bytes: bytes) -> bytes: + rgb_bytes = bytearray(len(raw_bytes)) + for offset in range(0, len(raw_bytes), 3): + blue, green, red = raw_bytes[offset : offset + 3] + rgb_bytes[offset : offset + 3] = (red, green, blue) + return bytes(rgb_bytes) + + +def _encode_ppm(image: RgbImage) -> bytes: + header = b'%s\n%d %d\n%s\n' % (PPM_MAGIC, image.width, image.height, PPM_MAX_VALUE) + return header + image.pixels_rgb888 + + +def decode_bgr24_base64_image(metadata: ImageMetadata, payload_lines: list[str]) -> RgbImage: + if metadata.pixel_format != EXPECTED_PIXEL_FORMAT: + raise ValueError(f'Unsupported pixel format: {metadata.pixel_format}') + if metadata.encoding != EXPECTED_ENCODING: + raise ValueError(f'Unsupported payload encoding: {metadata.encoding}') + + raw_bytes = base64.b64decode(''.join(payload_lines), validate=True) + expected_size = metadata.width * metadata.height * RGB888_BYTES_PER_PIXEL + if len(raw_bytes) != expected_size: + raise ValueError(f'Expected {expected_size} decoded bytes, got {len(raw_bytes)}') + + return RgbImage(width=metadata.width, height=metadata.height, pixels_rgb888=_bgr24_to_rgb888(raw_bytes)) + + +def generate_standard_color_bar_image(width: int, height: int) -> RgbImage: + pixels = bytearray(width * height * RGB888_BYTES_PER_PIXEL) + for y in range(height): + for x in range(width): + bar_index = (x * len(STANDARD_COLOR_BARS_RGB888)) // width + offset = (y * width + x) * RGB888_BYTES_PER_PIXEL + pixels[offset : offset + RGB888_BYTES_PER_PIXEL] = STANDARD_COLOR_BARS_RGB888[bar_index] + + return RgbImage(width=width, height=height, pixels_rgb888=bytes(pixels)) + + +def save_ppm_artifact(image: RgbImage, output_path: Path) -> None: + output_path.parent.mkdir(parents=True, exist_ok=True) + try: + output_path.write_bytes(_encode_ppm(image)) + except OSError: + logging.exception('Failed to save ISP DMA artifact to %s', output_path) + return + + logging.info('Saved ISP DMA artifact to %s', output_path) + + +def assert_image_is_meaningful(image: RgbImage) -> None: + distinct_pixels = {image.pixels_rgb888[i : i + 3] for i in range(0, len(image.pixels_rgb888), 3)} + assert len(distinct_pixels) > 1, 'ISP output is a single flat color; the pipeline likely produced no real data' + + +@pytest.mark.generic +@idf_parametrize('target', soc_filtered_targets('SOC_ISP_SUPPORTED == 1'), indirect=['target']) +def test_isp_dma_input_example(dut: Dut) -> None: + frame_count_match = dut.expect(r'Feeding (?P\d+) frames through ISP DMA input...') + expected_frame_count = int(frame_count_match.group('frame_count').decode('utf-8')) + logging.info('Expecting %d ISP DMA frame(s)', expected_frame_count) + + for expected_frame in range(expected_frame_count): + metadata = parse_image_metadata(dut.expect(IMAGE_META_PATTERN).group(0).decode('utf-8')) + assert metadata.frame == expected_frame, f'Out-of-order frame: expected {expected_frame}, got {metadata.frame}' + logging.info( + 'Received frame metadata: frame=%d size=%dx%d format=%s', + metadata.frame, + metadata.width, + metadata.height, + metadata.pixel_format, + ) + if expected_frame == 0: + reference_image = generate_standard_color_bar_image(metadata.width, metadata.height) + save_ppm_artifact(reference_image, Path(dut.logdir) / REFERENCE_IMAGE_NAME) + + dut.expect_exact('IMAGE_BASE64_BEGIN') + logging.info('Receiving base64 image payload for frame %d', metadata.frame) + payload_lines = collect_base64_payload(dut) + logging.info('Received %d base64 chunk(s) for frame %d', len(payload_lines), metadata.frame) + + result_image = decode_bgr24_base64_image(metadata, payload_lines) + logging.info('Decoded frame %d to RGB888 image', metadata.frame) + output_path = Path(dut.logdir) / IMAGE_OUTPUT_TEMPLATE.format(frame=metadata.frame) + save_ppm_artifact(result_image, output_path) + assert_image_is_meaningful(result_image) + dut.expect_exact(f'Frame {expected_frame} done') + + dut.expect_exact('ISP DMA visual demo done.') diff --git a/examples/peripherals/isp/dma_input/sdkconfig.defaults b/examples/peripherals/isp/dma_input/sdkconfig.defaults new file mode 100644 index 00000000000..cc641ea6033 --- /dev/null +++ b/examples/peripherals/isp/dma_input/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_SPIRAM=y From 5edf9932f13467050bbe689e8a163bcc62288548 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Wed, 15 Jul 2026 11:30:49 +0800 Subject: [PATCH 2/4] feat(isp): Add example and script to check raw picture by ISP dma input --- docs/doxygen/Doxyfile_esp32p4 | 1 + docs/en/api-reference/peripherals/isp.rst | 6 +- docs/zh_CN/api-reference/peripherals/isp.rst | 6 +- examples/peripherals/isp/dma_input/README.md | 18 +- .../isp/dma_input/golden/golden.ppm | Bin 0 -> 201615 bytes .../isp/dma_input/main/CMakeLists.txt | 4 + .../main/assets/sensor_240x280_bggr.raw | 470 ++++++++++++++++++ .../isp/dma_input/main/isp_dma_main.c | 49 +- .../isp/dma_input/pytest_isp_dma_input.py | 66 +-- 9 files changed, 538 insertions(+), 82 deletions(-) create mode 100644 examples/peripherals/isp/dma_input/golden/golden.ppm create mode 100644 examples/peripherals/isp/dma_input/main/assets/sensor_240x280_bggr.raw diff --git a/docs/doxygen/Doxyfile_esp32p4 b/docs/doxygen/Doxyfile_esp32p4 index 8ae3c77644e..f207c7181fa 100644 --- a/docs/doxygen/Doxyfile_esp32p4 +++ b/docs/doxygen/Doxyfile_esp32p4 @@ -16,6 +16,7 @@ INPUT += \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_ccm.h \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_color.h \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_core.h \ + $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_dma.h \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_crop.h \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_demosaic.h \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_gamma.h \ diff --git a/docs/en/api-reference/peripherals/isp.rst b/docs/en/api-reference/peripherals/isp.rst index 8bf8e5c3556..da3478ff5b8 100644 --- a/docs/en/api-reference/peripherals/isp.rst +++ b/docs/en/api-reference/peripherals/isp.rst @@ -67,6 +67,7 @@ The ISP driver offers following services: - :ref:`isp-resource-allocation` - covers how to allocate ISP resources with properly set of configurations. It also covers how to recycle the resources when they finished working. - :ref:`isp-enable-disable` - covers how to enable and disable an ISP processor. +- :ref:`isp-dma-input` - covers how to feed image frames stored in memory into the ISP through DW-GDMA. - :ref:`isp-af-statistics` - covers how to get AF statistics one-shot or continuously. - :ref:`isp-awb-statistics` - covers how to get AWB white patches statistics one-shot or continuously. - :ref:`isp-ae-statistics` - covers how to get AE statistics one-shot or continuously. @@ -247,7 +248,7 @@ ISP DMA Input Besides image streams from camera controllers, the ISP can also read image frames from system memory through DW-GDMA. To use DMA input, set :cpp:member:`esp_isp_processor_cfg_t::input_data_source` in :cpp:type:`esp_isp_processor_cfg_t` to :cpp:enumerator:`ISP_INPUT_DATA_SOURCE_DWGDMA`, and configure the input format, output format, and resolution according to the image frame. -DMA input is useful for feeding software-generated data, offline RAW images, or other test images in memory into the ISP. It can be used to validate an ISP pipeline without a camera sensor, reproduce issues with a specific input image, or generate inspectable output images in pytest. Call :cpp:func:`esp_isp_dma_process_frame` to send one input buffer to the ISP and write the processed image into an output buffer. The input and output buffers must be accessible by DMA; if cacheable memory is used, perform the required cache synchronization before and after the DMA transfer. +DMA input is useful for feeding software-generated data, offline RAW images, or other test images in memory into the ISP. It can be used to validate an ISP pipeline without a camera sensor, reproduce issues with a specific input image. Call :cpp:func:`esp_isp_dma_process_frame` to send one input buffer to the ISP and write the processed image into an output buffer. The input and output buffers must be accessible by DMA; if cacheable memory is used, perform the required cache synchronization before and after the DMA transfer. ISP AF Controller ~~~~~~~~~~~~~~~~~ @@ -967,7 +968,7 @@ Application Examples -------------------- * :example:`peripherals/isp/multi_pipelines` demonstrates how to use the ISP pipelines to process the image signals from camera sensors and display the video on LCD screen via DSI peripheral. -* :example:`peripherals/isp/dma_input` demonstrates how to feed software-generated RAW8 Bayer data into the ISP through DW-GDMA and save the processed RGB888 frames as PPM images in pytest. +* :example:`peripherals/isp/dma_input` demonstrates how to feed a RAW8 BGGR image in memory into the ISP through DW-GDMA. ``pytest_isp_dma_input.py`` saves the processed RGB888 frames as PPM images and compares them pixel by pixel with the checked-in golden image. * `esp_video/examples `_ provides some examples of enabling ISP control algorithms. API Reference @@ -988,5 +989,6 @@ API Reference .. include-build-file:: inc/isp_color.inc .. include-build-file:: inc/isp_crop.inc .. include-build-file:: inc/isp_core.inc +.. include-build-file:: inc/isp_dma.inc .. include-build-file:: inc/components/esp_driver_isp/include/driver/isp_types.inc .. include-build-file:: inc/components/esp_hal_cam/include/hal/isp_types.inc diff --git a/docs/zh_CN/api-reference/peripherals/isp.rst b/docs/zh_CN/api-reference/peripherals/isp.rst index 6397d4f7122..e42060cf39e 100644 --- a/docs/zh_CN/api-reference/peripherals/isp.rst +++ b/docs/zh_CN/api-reference/peripherals/isp.rst @@ -67,6 +67,7 @@ ISP 驱动程序提供以下服务: - :ref:`isp-resource-allocation` - 涵盖如何通过正确的配置来分配 ISP 资源,以及完成工作后如何回收资源。 - :ref:`isp-enable-disable` - 涵盖如何启用和禁用 ISP 处理器。 +- :ref:`isp-dma-input` - 涵盖如何通过 DW-GDMA 将存储在内存中的图像帧送入 ISP。 - :ref:`isp-af-statistics` - 涵盖如何单次或连续获取 AF 统计信息。 - :ref:`isp-awb-statistics` - 涵盖如何单次或连续获取 AWB 白块统计信息。 - :ref:`isp-ae-statistics` - 涵盖如何单次或连续获取 AE 统计信息。 @@ -247,7 +248,7 @@ ISP DMA 输入 除来自摄像头控制器的数据流外,ISP 还可以通过 DW-GDMA 从系统存储中读取图像帧作为输入。使用 DMA 输入时,应在 :cpp:type:`esp_isp_processor_cfg_t` 中将 :cpp:member:`esp_isp_processor_cfg_t::input_data_source` 配置为 :cpp:enumerator:`ISP_INPUT_DATA_SOURCE_DWGDMA`,并根据输入图像格式设置输入、输出格式及分辨率。 -DMA 输入适用于将软件生成的数据、离线保存的 RAW 图像或其他内存中的测试图像送入 ISP 进行处理。它可用于无摄像头传感器参与时验证 ISP 流水线、复现特定输入图像的问题,或在 pytest 中生成可检查的输出图像。调用 :cpp:func:`esp_isp_dma_process_frame` 可以将一帧输入缓冲区送入 ISP,并将处理后的图像写入输出缓冲区。输入和输出缓冲区需要满足 DMA 访问要求;若使用带 cache 的内存,请在 DMA 传输前后执行必要的 cache 同步。 +DMA 输入适用于将软件生成的数据、离线保存的 RAW 图像或其他内存中的测试图像送入 ISP 进行处理。它可用于无摄像头传感器参与时验证 ISP 流水线、复现特定输入图像的问题。调用 :cpp:func:`esp_isp_dma_process_frame` 可以将一帧输入缓冲区送入 ISP,并将处理后的图像写入输出缓冲区。输入和输出缓冲区需要满足 DMA 访问要求;若使用带 cache 的内存,请在 DMA 传输前后执行必要的 cache 同步。 ISP AF 控制器 ~~~~~~~~~~~~~ @@ -967,7 +968,7 @@ Kconfig 选项 :ref:`CONFIG_ISP_CTRL_FUNC_IN_IRAM` 支持: -------- * :example:`peripherals/isp/multi_pipelines` 演示了如何使用 ISP 流水线处理来自摄像头传感器的图像信号,并通过 DSI 外设在 LCD 屏幕上显示视频。 -* :example:`peripherals/isp/dma_input` 演示了如何通过 DW-GDMA 将软件生成的 RAW8 Bayer 数据送入 ISP,并在 pytest 中将处理后的 RGB888 帧保存为 PPM 图片。 +* :example:`peripherals/isp/dma_input` 演示了如何通过 DW-GDMA 将内存中的 RAW8 BGGR 图像送入 ISP。``pytest_isp_dma_input.py`` 会将处理后的 RGB888 帧保存为 PPM 图片,并与示例中提交的 golden 图片进行逐像素比较。 * `esp_video/examples `_ 中包含自动启用 ISP 控制算法的一些示例。 API 参考 @@ -988,5 +989,6 @@ API 参考 .. include-build-file:: inc/isp_color.inc .. include-build-file:: inc/isp_crop.inc .. include-build-file:: inc/isp_core.inc +.. include-build-file:: inc/isp_dma.inc .. include-build-file:: inc/components/esp_driver_isp/include/driver/isp_types.inc .. include-build-file:: inc/components/esp_hal_cam/include/hal/isp_types.inc diff --git a/examples/peripherals/isp/dma_input/README.md b/examples/peripherals/isp/dma_input/README.md index 3298c0ab2c3..b554725300c 100644 --- a/examples/peripherals/isp/dma_input/README.md +++ b/examples/peripherals/isp/dma_input/README.md @@ -5,22 +5,20 @@ ## Overview -This example generates a standard RAW8 Bayer color-bar pattern in software, writes it into a DMA-capable PSRAM input buffer, feeds it into the ISP through DW-GDMA, applies the ISP color adjustment module, and prints the RGB888 output as base64. The pytest script decodes the output into PPM images for inspection. +This example embeds a 240 x 280 RAW8 Bayer image of a real scene in flash, copies it into a DMA-capable PSRAM input buffer, feeds it into the ISP through DW-GDMA, and prints the RGB888 output as base64. The pytest script decodes the output into a PPM image and compares it with the checked-in golden image. The data flow is: -1. A synthetic RAW8 Bayer **color-bar** pattern is generated in software into the ISP DMA input buffer. -2. The pattern is transferred into the ISP via `DW-GDMA → ISP DMA input`. +1. The embedded BGGR RAW8 image is copied from flash into the ISP DMA input buffer. +2. The image is transferred into the ISP via `DW-GDMA → ISP DMA input`. 3. The ISP processes the data (demosaic, color adjustment) and outputs RGB888 (BGR24 byte layout). 4. The RGB888 frame is base64-encoded and printed with machine-parseable markers. -5. pytest decodes the payload, swaps BGR→RGB, and saves one PPM file per frame. +5. pytest decodes the payload, swaps BGR→RGB, saves one PPM file per frame, and compares it with the golden image. ## Hardware Required - An ESP32-P4 devkit with PSRAM (this example allocates the ISP DMA input/output buffers from PSRAM). -If you replace the software-generated pattern with a RAW image embedded in flash, copy it into a DMA-capable buffer before feeding it to the ISP DMA input path. - ## How to Use Run the test locally. It builds and flashes the example, captures the serial output, and saves one PPM artifact per frame: @@ -30,17 +28,15 @@ cd examples/peripherals/isp/dma_input pytest pytest_isp_dma_input.py --target esp32p4 --port PORT ``` -The pytest log directory (`dut.logdir`) contains `reference.ppm` for the standard reference color-bar image and `isp_dma_input_frame00.ppm`, ... for the decoded ISP output frames. The pytest script checks that the decoded frame contains the expected standard color-bar structure and verifies that the ISP color brightness adjustment brightens the black bar. - -ISP feature-specific setup is kept under `main/isp_features//`, and pytest feature checks are kept under `pytest_features/.py`. The current color brightness check lives in `main/isp_features/color/` and `pytest_features/color_brightness.py`; new ISP feature checks can follow the same pattern while reusing the common DW-GDMA input/output and image parsing flow. +The pytest log directory (`dut.logdir`) contains `isp_dma_input_frame00.ppm`, the decoded RGB888 ISP output from the current hardware run. The repository includes [golden/golden.ppm](golden/golden.ppm), the checked-in reference image. The test compares the decoded RGB888 pixels with this reference image, making image-quality regressions visible in review and detectable in CI. ## Example Output -Each frame uses the same standard vertical color-bar input pattern with positive color brightness enabled to validate the ISP color adjustment module. +The example processes one embedded 240 x 280 BGGR RAW8 frame. ```text Feeding 1 frames through ISP DMA input... -IMAGE_META frame=0 width=128 height=96 format=BGR24 encoding=base64 color_brightness=64 +IMAGE_META frame=0 width=240 height=280 format=BGR24 encoding=base64 IMAGE_BASE64_BEGIN IMAGE_BASE64 ... IMAGE_BASE64_END diff --git a/examples/peripherals/isp/dma_input/golden/golden.ppm b/examples/peripherals/isp/dma_input/golden/golden.ppm new file mode 100644 index 0000000000000000000000000000000000000000..ba31afa2173523f58f9b14a625a8a21822fa1086 GIT binary patch literal 201615 zcmY(scaUZGb?4VaAR);mOIndj0FyeroMZP40ErSQtw^o73MG2&RoUxRX@g`*U=Rs_ zLIwtygo&MVdaqx@_8xiq_biQ@uHJoj?>1rY-LrM?K6mix>AjCVTaO4=@59lZ zPh7hny7wNrwjX-;K63OvboL)PcOKgM?0nnNziV#Yar7UWT6dk>AGvxD9i98;+FfVo zk$3Bdgt_yvXaBEVJ0Fc6{J^vO$hr04%>F0d?GO2`(}$mq9el!RPjBDzbZ?FJZ=cz@ zH@fqPPq{Ex_s;3r+?f5i!<%G}`&l)4Ahr-?lVvd$&Jw zw{D&8-*?t;jddT4^*;Kgy&t(-4_wXr_Szj;X@BZ$ee%l(pPbo#IJW(XxBtRySCcCi<4|U;Ixj`LxOX9J9pG)_wK6S=xJ_`ws-BdT}ye( zQ0Q}@t=4xmwmq%8?&h7bty`}4p1Hl}+PUN2`H*{bY~8YU4>Z+XOZSegeL%R{hmPhx zhj8HO);2NP+VVF0?)H|m*>jdV-ul*=_Kv;Suodc#Qqx;3*-~k1x}b|BE#c79(^ID| zUwZsoFMjq9{>{KwzC2)gVZd;D;O8|@e$hPei^m^-dgwDxKmFJ<&kTJ23!giF;un79 zxu<{QS3mo;-yC@Ug@K=Q|J=~84;(W-rFDNsJ4`$_G)S=jz!$#oJYVhP|2TweC z>iFl59~=1mFAj{3{rp$IcH)ozlkK~&7%opbCKoNih%Fp5C9)E!yrWQc*SpqY-BM`S z%WYSs>#p`3r8eQJH$mFn>=54e7U8V*+>Nc#_P(dNJKEWnjrAV)?y2>;Ux;RP_w(7R4xsR~$E?mt6c(zuyZPgt|eV6Uh?#*VeM z=j`3GH1}-v9m3Vx^>p^fn(|sXp{Lb%HClwD+~duTHFsdcS!odNYR6OSItmqIGHc6~ z4T-GPA38BPH~iN7KmX!)f8qE4VBpJNd)(|CFxVbHp?U21$dk_=d*YdA2cACm#EHS5 z|I!)DAAG~~$A9#TzxVaez3|lm&#ydgbUk5m|FqfsIfLP|S`9oue)8m#gM&|;IQiJI zF+MeFd>74^-YuDb`w$~5PC42KO>>*iD zVXAIBJ2!c);B8+2v zoTPb|#_`=S|2r^^G(|O>o?~k=_o$fyHH1AkSd#=Xq(awEu z``&2x_8ExcPTTi^&DG>l@IY>HptZaYwCsi~TdRAc{X2ZABDVY1D$nOO>mUu`V<>+I z=I^N7!XeVi*&IB^#vx&^?ReUUp7w3F*y>x}-l401*V((n(#^N`ZhE%wxVQN8HcM!? zRJUAhj@>)Wmo~P*fS2xSblt7y^E=zFS`WE{6W+C>(y|n4&T>nTt~BlW3OqZDwXs6Q znaVkR0p09^`P{`X{>4i_`+NV>z%T#$fYvoIWE=RxiN}wP41E6CCyxz1_1xGCFaGKC zSI?W?czNVImj-_8-w!yx{2BMJ516cvS?o_543Fz{PmPRxc4+AFtd^xPBKXHurfNgtrfJ zdydu?OKY>QDb!eTwzr?_p|?FRlH1w=RMmuxbq=r-NHkO<#izT6Y0L{hhjTnY3m+H<5kdhG}+m`=V;yY zkODdn?M(~@L*P?SPvqAv7U=%z{#`i4JdnXvjU5HfwrqjG(ayuM?uX#*71wdk)w%<> z?$)8Jb&s2JH*Rx?yA8v4N4s|gtj!zbHSLXc$;&@^*Ug^2D*7hNO3PL{@*c2_194TG_EODLD4OF5o8Lb? zJF7kW{?Go|i$D8YzccXsmj*^m#A7FQ15jNjy?C7d-SKQ&d-_cpB>SDPNVyrNc4#(jy?0(GhamB5qTH(IF@rH(}am-zGyAi zJS_yX;iy(^<*K7vcT^hi>}|?0bRwt49&q9)oXxG#-afv9p~@I1a8verhuc(124?nT zi3xeGe>g@`D|Ow)=IL4wxkj{AHC8P2E!_2329y~ZRS%$QxVd!;?``kh z@$P*H>I8C4un!7P7Jyqx<*4rN$D9F!!5QG3@q&3kmc6|n;cwmDk37APfzaE%KdP8p zpmjrg<1W`JgN}q=-+!)mcdY%;UB3&rcnNhoH|4DEI;*z{F&i~iHun)vG}B&(K$P%+ z-2`t`nqwJ~t-FXh&xDU4892qBwSaA((GArQ4#q-q<1WGer%6C0vbusUwG1njElatN z*s?!oAOi}njYH&}lsC3>-__f5_xIiXLxPXQ{`Gd;-EBt`uy68CNx^4&H!+qX(aoMp zxSGdR&q-C~tTru~B7PN~G1Z<*&0VgZu2ezVn@TxjG4F=oI5%s4@4_$q={KMH>hBGB zetF=yN#c~&^^HIHMs@Sw_ETT&)%E_R!S^oz%r{?t{OiAuOBt|@4p_a9>n%?htWS&# z6G*hE^cTN~12?A&#$?WzOj|NJYc_Ao6-ST(u6a z1DIX)ZELm1sCT#b?091(qp8`An`H-8hap)Ub!$g5RH5Z5cfEz?nM&7N>W)?Vp6VXq zR)QBg*1YX4ZI4xUJ=I-Tnc=g?+hhq6D%HGG)DLwM)go8&>TB|%*(lpP66X4CCmCNM z6aP83{V@VX9QlpTU17U-$I-p5I!1)r*1hlSe@p->@(T=TJ}_fb`IPz*o6X^Tgdk&s zrNnE0Oo-UF9|E4Dw|7Y#TpPi$7$N)sjCtz^r(3s18@ISYh9ohD>NXD5Ew1t{PZe(O zK|9c*uJ|qv@wV=o^4sR(E_Vmv=F+y7t zM9eYgc&FyRt=zX)dQ|klETLprB*;|mP~!3WsKId*?#`jIq#i%yJxUI3?xD$))VR#P+cjb!CY{8k$Q8RjD z@!|P}p;zDfnScK$KldBIGcfw40fXnn*S_)P*z%v;@Ba@!zWYmuWyJQMPtVey@j3!g!xf&qd zC7Y<%jLU^mN3E%-x0HUQDl!)(hSV389ZR8y{1TLk6o3?cAk95e2vbN}i%oZBhj0}E zyW=YK32T1KR@gq>zKPR#j>@R8W6f?m3VV*yF5#^1Bg?!sv`BT==(EU9OJ1C+if8&C zqFN4tfr5_W=sxb3aC9D6n|JN4hqNzj_1&?pyOeBd4aEv7L{Z6#4fX3$&E0cv|Ipe0 z)ZP2o(f$yf$4;ZW>`FkKLV5yuBZY4Hh$u-NiiIdJbccYii#_ z4^clyb(<8!l`CMQH?)m2g&!YZRL&z;H}P3#I&6HgzW8*G=5ezxMi5|MUMcVEW2W zjsEuFwTu7p!L9%J|NQ6Q{qg><-MgzVwH8CqT5hnkRhnwQ&e5RTgNyDn z47pz(1@4#NSxN7r)b$iQ?o#JWW9KwwHHHC?2klBfgg@PiPv)(8s@wJgMP=Vn-oj?k z#~W)LTCyFLWLNFLQQ5PVwg@Dew??5vIBK^E#1@{({!$*c9uQbiHLxET2E>`5EyfOF z5}Jp|yRAt>;I>-tkVklNqwT}f-CH~id zYPZ}~+|+FpTP1e1zE4(iSE!c{MoYVdr*be_yLq~HFk0F3ly=4#;PspCs&c~0uCu&j zqxn|dp<2W?uwt$3sxY&Jd<4Os-*y&von$>)A4kUSpxqR)v`{wIU{pt6=aPi{5IXwK` z|Ld>*)j#~;SN{4F``tb7&hAhyubW%?xp&X~!vFf82EP7{$6U`1*vFnUSO};ltl5$h z!m~L?C0GJxN4aJxR0t9Tq2>;THsjh>YKhX4N-8aNjGKyGDK5%9u>w;aVTTgLDnrEPb4-&+->qCsshZ^N^-v}Y;qnhJZ? zGA*gww#qHMC3@&+fTGf>ZQge^?m3ZYO1auC)pb}KH=$SE2erYnB41Faeu@bs$S+{P zKBzi8<2PL0PwXv$*4ntwKp>8sw$kyyqN`HO1@J}E;;T!6h9hNY0JD5i>n=f-cW@U9 zv9Jn(m<=#ixpkHSa$jAN*ThOS#GXO2qqxNrfIxe;>n-mBv#UgJa}U&=MV`zpPK!#b zM#5GiE$&&$J3nbzP~V9-)9a%XqE?hJjGc28w%o;S9;}?X)R*$4vSrRR%-I?f3g%p! znn*n@Hj?1YqT2vKD?qU*J&Xt2rL~2wmeHaftvTK`!3t`O`Z=myd!@tEaMpIf+g)yq zHu}=sYjpl8o@@0+Yc1kTvwOPT8Eds^IG~~qd`PbRLMc0%iJO<#Ph6k;{Eg|a_4j`N z?|=A>fB4bw{NvyL#^3$bSO5C2ytfaZYq#`?xbE7-Q{VpH6JP%y2fp;114b_vWnf4< zFruf!On|iN+iB2YHYfwR5iU|yZ^}{<2bV|Ce^#2ww4j>^HT^nsrE4g*$biTNDlKhf z%7nUf=SXeVTnk)b8y)7E@RVR4xn@#E26Al5tip5m7EY2KWS^RZt#$~Cz$_WLeaBoouyAI@ zY6{*MV7yBIWA`@wjgK@X$|45E184hzqeUa`A#Q};7o$V%v%xJ=tm>qtbU?m9jWI>| zTXFLBLl^^BHSEPB?_|sGTXTCTwm^%OD({Waf6Mk6v-mV~wu92Db%edp=YF|siP}wu zvsx)Ti-!(uN%at4ZOH91uGM?wt3ekj7M%y?>Ylm0htiTD_=v%U>oBMLxH!~a99;oV zNLuU>yaJH6WSazt0;;Op2p8{8tU{%MjLSPxRGlU3r|a9JRjw8_mPRf{!rN#ggVt)x zP@sX(W$xxoo$)BLOrX-tL7eGPNwr3sozrc!y7ydn>vR_f+oXr)t~Ck3c9x2^d=3+0 zh@}SuL1&@#s}F8|{Xc*FTmS9<{Oy1IuV4L#zxkCP|L98}-M8&@-G$sUOAE(dKl|7p z{clfx@t}F$m0-T$OO->#ibA<|YjdTd5{1WyVg`m??;>FV(%(7AeME z5)@^YunOmOORmnJqqW<%+z!yvZNp7T^;d35#woRA|5A_VproN5C**AQY}Jvgjh1_- znL4aUAkK=Z-to|kEo?dSeMyu`u7m++X^RJLE1-2!G|7vTNv?fq=Qi)C+Tv;5C#Y6% zeV~p^!5E+7x@CLw05!%cn9Bz=Z{Zn{7oBfDveh5rv?UZBMx1fo#?l>2RT{-~kEMCi zxMisb>U=dw11$)teqQ||t^`NKm54G|(A5JJ)m=U$&NT0ND|ej*5nIBRhnyYc8mh@( zKS^P@GPDlnDU-J)RTW8OcNC*?zyRlPNB+>3+jEz1SqpdUrF#rjh7Ti4Y>bi-=$}Z` zDWVU!JXw~N0ad(d%S+Ew(nNKO8pl~^c+t{g+n#IK(k(}}V@lNJ`TxXc^1lVv~Rwd#;B1$)s?*JKE`~ojTsQEq|n10(`T7x`TB@*_r}# zpZQ99Xf2kMS4xqE#jQ9iRf;%T*7U2v5;!fT%9;N5^B*4m%fI=-@BZI^_x1nwFggg#r8X>ijiJQ>JRo)VMoN&eRFbLva+P z8t&SX;Va7UjD}m%Wx`cx5R4;tvBofTQ@19X?re_-;>ba=D6mShyU=##nzk$>MdlXy zA}*Ei-Baul?$S~4=+I|(e#?>RvI5nlUGxf`y?DR!4)OvI@>|}#qpxjsFta;%hUtMGC{*ff_Lc-fzzhv{F8WKqv~uvbkv!B zzQ+;`r{tsyVJqQznA%{B+)@UMwB`U9oZyOUuorivOH;iC(kjfJ!Y<*;?RtxXCHFE4 zt_WRW58&3E8mh=neP#Nwr1M7G&D1E{I`v=r!Nafr{f~d+ z?|+O+zwo06_PaY{{e~tJ)s0X5%*(HQ?)U%jiQoOVwmiV}fY6p{6Rgme!*y^k>Rdca z#*57IWEqJKic=ZUSpi!Yjnl8DP_?GZrWjN9djM(WDXGsYQxRp(H67W8J=fx~aG)h! zwPh+Y95O9?vTjed7zjK`ccII%()Y;q?dgs!)pg}0;Q}*iX3cd08waRrxat6@<)xgj z?jw~lu~x*Cb{@aiJhd-ws0dnS4 z#gr`D;zd^)8&I)l%Mh#l5~(WF@%(ZlS7RSXo`O``$dD<2<|@v7^@!L^+s>oN)F74} zfZv*_aFi`gIwM%A*)w%(s%lGCtckKcRdwf@?o7>*EHn1`h~QL5T9HNsc$<5?7c}3V z?YJ@$3;}nxt=1#x68;dIY6T3+9DFsD5_t(sH5>U8$jRDtz06r^QYPKN_@=3_BU8*J zx(ByCn2nOOYNcUIL!i71r67td+p2f%G&I^DGBotrZG9TAD;89$sv^I=*->j%8gAzN z9vF)kD()bUSTBUvncH_44oAy3J;ei8eh;wW8Cn>ptgunxTy|4dw$-IR&5sH&+g%2- zw{**uKR^=Ifow@NQBU% zo~Z{-={jU`9{h$2)l~`^MRug>0eB1vibN_=5-5t)L~`+s&)2q{^1eicWI}Ya|Y)RLmI((sh!gp`3}^|t&3qP@*T3=FG0t0MxuX$bS9Ao;0V1IJso z=Q6Hh-cigE+El_^$XVO97jEx=`ENe`wZHx0ul>y@-bV+nUPV_*82p<iWkJx~6A5&q7mq~@3oTuuf z#gQqg>ZHhy`XXw)S$eQ6EvbSSOW*{UBJ1gkeJUWnT8V}^S5$wo#;Bofq7ENZ zt|Um8n%2A+S~2Z~4i%_02Nbixih(vuxr0hG;fO7vcEe7Cw5M7kY?ZvJkk%yA=0ZuA zO&JSWYp?RFk8XbbZ$J7M|K;wle7Nu0rO+!K4{R!vgGx!5De~(+Tc(IOo0ECf=YzB< zS>(5)xC>QvaSN7I$(ktIk|mX16;w-*8O*#jRzPx*Ul(^;Y;vq6*>LjMc_7IO48t>@ znqx&(qA3X}3^}KfuZWlU6n((4z_TIR!XlCcAspo=k0=92wRt_ZAXY$y3=$yCd<0@; zNVP2)v{CqR=C^rY(#VD3;s~D@!=Q=gxXa( zwB)wYcCvsN4|G1+knb(@=@O%Fw1t&)zr(SLLy(-pHHh6!ci@oA;4V;XnhfeXy8*T{ zyM^T-4LLG>N3!osZQ0UFf(0b??P{w7Xjy_W-qR-xHeYDmXV+A8!E03h&x=fDAYjY}P&18(JIEwAr zZGHK}n_u~>`_Fy2@7(QMdM&kI2fz$Zm1hS?rwi)!tNsCNfs0W6gEd`bXEYqD&55ch zE|hXp&UBG*q*#_fT6{~I?c$Kl(V97ycV%nVSjia5nIk1f@<_?qh(2551wtRmE6N~p z%`4_5T9X}nx@S+YKcfj*7KXtI!MCN_=44aSWp>}3+JPSlren}dr8h!3iSn=;uMAIq zrg|Xl7n;~Kz@>+RpcqIY5XjXY7r>*XC@LlaF}LRS$@qK` zQYl>sB_ms@s&Z)W4x#!DYp#O_;426Q3saw5Bwt}lb>NvB`3>-q$b5#}5ZBwStQ4&dV zw@5C*x5yW%l^6bBrjrCJF4B_3IqY&C95rKvD})?-LXaj{;ohA9#tIv=)Qnwog!L^C zRHxe9jzqe}6X3@2=kClFp$rZ2)ncs`DImM?CV* z`~^0HNf}#?IlCg3Rg7yMqu79XS>dCiXtmlplizieYV2&!6#8{7Cu9C<~)@05YO_*XyXC~{(7p(ELL@eb< zW`U3ZA*2}IxHVfc<;n`@N(hi_li-u6i5~~T!iHbQ|CZv_Y%L3O# z%@WNcyufUV7Wl{-hj0mNq-u-S2z#t*$OALWs{DUdpHz&5h5&^d*cL+Pcr*}bGWR^Os!1$6tKOu@M zF~>We{2{x+D)yN1LX7732_)JYYnj80UxC>cZ*%>o7`*M+4nV_BbTBSX!eza|uo>NidQ3 z=7nM2DM(8Vm@HUgS#uIodek={UyDIaB}S{|)BF-%>4Qmy#moiG-cp6RITOF8$QGd; z3wqQm$hGj#rc7C8<<|84J=zQzi;I4?_U9olNR6ZJn?3n`+E6C#2~?AJ3XhnPPFx zW^l;AG2{;s##qo@NSh)lODtngW=)ZVeluhUhV9XWBbGF6#+{R<})iH%5LKyi{%nwUNTKgah%+|z~E!uG=`X1CZ-6x#M zE<`be)e+5bmQbkXD{OJx2+OuL3f0(;4!tt&-5hVZap{Vj0;fs9mIor9Jk#ZAnBr8~ zZ3=Ktu7?z(C(7{bII>jnEye|!gG$I72^DS83PXm6EJBn(x<$?GsiGN%$({%o#t##c zYf2(c7S*K85=AwqGE(9(?V|LlWGa~n3+4B9I0xo0)OiQB|3Jq;+P_)+0P9213?w%o2^8BQawzVGgHEp_KBw=qk3s9xFqXHBvSO3wBDy6iZ}0hsJVuEFsny z$s58sNH#?(?8(F75%Hij{v@6mR?U$D4~i|uVAUM18#jxFK;ekq&8#Vy(*?33(UH0( zRJDg|gk`ft@TELwTsNU=2w4(Ot_x$}>zGMntZG2jB@v4(D*(&8mK2=YCcm@7N3={u zBs1H(Fw)eelb|XvFAh9Zt;2XgtUlglMRlh%8SuKMRF9ze!i(Y%Km{x%65FPzm;_)` zEN)-YH#Mm;%HT>82j)RcGDr34V2~8R9x~zC9_zv?gTfMRL#*ruPD*-0rO`}PlO2hU zCDJej8|o0?DAhahMV#D4eHyJWqM@4odBQv&c|`FBc;GFeWUK3^1F+ zXc$O;&TyzER#`C;d<4VZ+|C%k=S*!O$nK2z2Q|q17+ttx^m#HpF$v<4 zqyXew7-EbFf=`{vHf)<=74H;lyVG6t`H0V0-I-`&Jn#SncWn(zaBJpR&r91)890J8 z^VCUkzdUU=@?A$duN(!^1Z_Rck0RYIQ@AcVpQ0wB9${$nXO$PnE8`XLvgCzg{NhzA zL9(hLTB7O~>;>t%m^$SnU{(uxR`j7XSW-4hD9or86Y@)=4^K;zfr`w7!B9F{cn<;x zPOk%y&_;EC+G{i=@Wz%zk^o&>JWfC?N^50{vXTG7#T1Pg!XbFphr)cS-Pkm&__d2` z_FxIFtf90-tfJq{A*b+Z*i31BF_3oBa|1s{AIJhVA;TF6zs98HCQqD z^7c@{5iZ)o1%mA&_~9z=6pV%BNZSxV=S%n*eYj?b)FBz!LB|LTs%n@a1fEe*wHt7x zkg*QzsXo>kBZK#Ozrcxd67(NvL}NKD@jhk%CFD~)tvbJ~kK<36ix)BxWKR|{@yWC% zww+>|_bl-(mIN2WCD~%+?iN06l+2Ee!DE0r{p4gzDm#cxw!Hk_8&jcp4_2@f_Gklc zxnFsz;ifUvu!Jjk4{Nw#3Du3E7UdzAN0=kP+2kWH!Yf}VLx4XqY!c|aGR(OcQWyYp z+4vKl2~UPn0w2N-hESQYz~PFdKwVxGOfBRUFRkhZ)U6JgqI2RayiXR2sQdTc|hF%BV3C%|46;e6KzTS20U0WlLrG zPydeSO~kEL{n@hH;L)pED+|6j3vN&l0dgPA;X+cwVP>80L{;! zK~)_EQHM&3R_Mz(}oh>s--1~qgKiDn`m85eJbRiD0&hd42^FX%&Y6#-ON<*4J1v2(N=+AS zakwYl@Mh>>fPG)^Ryr8e5vZ<6bPB)Gl0h16IwEyftm%w4l$9FKN>y5xggMwSGKvEg zt`;jIv~!PP21Q#&dblL6ELg#<;lLRJY~-0hpbRe6A;+mN8eBPnbH-@lld*`D=LEVc z9MYRo-ks!JwH^0F^u2%#4^&m)tF$f7o!88yWHWhR?;W?rA#R>cav_mXA z06Am97R&>)bu(kfC;OuMbO^s!QzvRibJ+XipGt!F;FsW6mc((XhGF#s5S>m zU~CPrC9hr0nEYuZ+7d{c{0xwiQ^~mkZLosDHf@$Ui924mhs*rwPIlDyXbX4Eo9Khc zIO-%-zamibT4N1;2>f;d9@RybEzzzcx@8G=tdXugCgwztM(z@%a!f*3)n{^nGDf61 zjKb5nz~PX=N&1AUlfX=6nD$Nmu{Q;;Cx>U~k(xN>0)SG+=yK=F{A zK`>@Tb}JKfw+L^VE0Ho^5q#<5Qf<+yrR<`#l*#C5hKV`sw=#KAP)Wv_5Of|SA_+q< zN~b~>2y7WV=xK8h$;cD zu+5-DlZ}Y8KZeI9j2lVa`jJ+fHsZRquxUMN#Z;`t35zdjT#Xsl<8TPrgwdZh2l51i zT2)~9B)D`yB)3O?hidQ!OHo&)+dym19P1k+T|9=^Q8boz1fGXBMM4@5Bos*yayD_lsy>6X z&>LyOq$AuUxC>{z<%xGKfvRz%VF?~l&C@`uVcVwM4tHeSZ0a|t-6RviGvW!fY{#Lg z!JYuG_m?1$>O)LRu!5d51XSi#dbv)rgZgBs$2pZ+9N`QRG@K#D4g{+D%&4)E7Aba= z+-mTr0N5VL@S@G@3EM{67R;h!Hq0u@7D`LdI#A%pd8)oe&HKP?j$ma4X_abZS!tAI z=&(_ju{4Ha0PKjRZIPro7%^>z3ByLvxDh~#^~-C960jBw=BU9+?RDNPS~M$ zHEG-69}mf>$Lf~i#?=%Y;?fQ4N&Q;Fu$G2ND~S4YrnR)im*xC~aXG19jN33CYZ>Em zTECdoE+mXA8453KVz}td#?u%{@JfrF)CZt>CkU;^xJPM^3RA$8$YcSH$RS}I4ouay7qs-Hg z0lrzruwguSAZpd4M|d|S5EdXLhZ+JIEiWZhCVK+8TED|H?+$K_zJ#o>KQ(?Jt&>+% zU?YFp0tq`lb1h=?$DP5PV>3&>W*=lwG)>9%G#T)yj2gwt;$~@l3B6Qv)|j-^bQ@7y z2-6Z*F*XBpAY@we3&6`OrgfiT$)}xP)h}-l+NI^8x%t7F`IA$#CvQv+P9V;cgmF1& zUJdIO1ICpQYK%$7T4+`yDyw`-@Tq=j6XbMDVf|9rupBY0hO|oo1X<7eQbM;7vn+;P z>q+No+PWAwuf!~?kQuYCM~y2{_P4C1Oe<)3k^o=`*U!hy%PBJ(8Bjc#)vR$b!4~U! zmVj--up)st6UOztVJ&A~%h~)zzy@+&AM{!Sl#@Jgs#;mMZB}@FC=w!uEMvSKR643V z#l9kgU>3!1&{b$zHycJDi4X75Hlo7`rkh2LF~$^?gjmgB6F%`Ige5Ft4|WK%zu^dV z&EYPS9gH0)RckBE3ErD9hnfN&wn437qyL`)P?eM7SFL}++ZpK)_$30zA(1Jhm{h9(49_V7MWRr`4O)Sj7l)4dQx<<*a`bYUr@KS&VMbapI7nTO6XNRVyh~e=Yr>VhK+e)!a^1PSfZrg1F- zil&v2Zehc)w5eb88Ss5N^C8nhSicYg z>7R_0kZv)AO6!*shLt#BB~`7(4NECR*tnFjtrrzR7I9{1K)w|RvLY)a4wjD1qLWs} zYR<5nF|Xw<>jlet9;zW6ebBFF=#ALvY5RFQ0=eE_;N5BcdGtpli1y27oqouXuMStG z$U;%c)SC@UKrAKoBarJi8y+STkw>K)4Aq2TlL@;nvaANm%!(=4M%b;9o-xw5CHJtV z;sK=nqFDE^xLhSFf-bH2P*L?u3_$%l-U*LH)mEm@<_tCMIO@$dVemJM8(dr4v{_ed zaLwc=2T9%$1rF4?U^fEm%d!K^^A)1Kp*-q}or7xpfDYL~JvMT>l_UY@5I(Y+0crFZ zo+(}+oJ*pF#26nT&4UV56fu`ENJ2EMWy#tuTCyXuq`B9QxCky9Eue?x;FKvU~ zjWns57e|Igk!-#Ufh|GtG|N%R%f5)jMwDI|!ppxY2e$+b1Sz{#LQrQwT9<<(%K@^# zVI?p!zowm8)z7W#=I8Yb3!0hvk?A?j%+lb*+^HLrBU7^gJTg8xbbXvSb>-UeOP6&^ z==p|e71a%LLM|J0bqhXDVp80sGdj)n{~d-Y7aSLLKf}{+^{0Ga9U;}!s8&#IbDVNPi^fI>+Xy}#;CSTnd z?zuRppWa1B>ldmGTsb0-TiBog#0fW9kpa7&6D-9%^C`JWau$h9&jVaft5pfsPIU!b zfMzYL^QWXR-=J)#29dxOvy=fMFNGwSBYQ%rswC#MsDv*D*pS8ws*AnkJwmmr&$^|k zb}=F;dpSZbMybHtyq;1GwrMp20~l1Ll8VAJWg1JogmELNUy*<-7}LzHL7jlN=+`Xz zhUQlJXn5W?Jh?P9v1pi?GtV#T=jKPIros5+^@-u@R*m&`#DsZ~0!`EFXpRbAH0S6y{U* zQ7~TTkfU`DS&ksfa7eJCncrlE!NTYRUG01nR_#2!wH#EV)e4+RMU&-EK-J8}RGv8y zN!KjqOzRa?TEB#PXJmhQXlcW8ng^>$G_{YAjARj{PAVNH%?Z_c(w#H->i~vRwfHM$ zUss5zuq)$bP#IfTDyS-m8J)dg66P(v!>syQ1_wI z(nAY2$OT$oO|xFLY&4DQHAlEji1`nc;F&;^MV7@dH=vQ)P11zFY7Ml+!)&(XI>TM# zrnEZ9DDEFiE|gY zLd{}8Gru8nI_KBUtQ+Q5jq{v#1EnPdQL!9?I{TOzo`~>_&p5XM%t$ooYSH9*tcdKu zsTil|GYqR^R`DBQ#xc&cZEY6O{vn9{XCPD_j( z!b!pCue&x|HeXEzn2aE{fuR(rau-~%>h?!t^)V)cs6%}?m^5^MsHK?`H+?1P)@j>CvabAEQub^28|AX8hggEJR(A~6xWjblsVZW zr$HiHqaGKA!4hSLUc(YzF^yta!5HJW6eW1eyn0orHOt}Q#UNcQsSpF=tM!l|!nHX( z>r+)1j1ft&B)J<`H*msi*DY^Sh)J;~Qt30#`7HB(mZsTt!}PLoW`$ryKf9uxUeZi0 z4vo)g$LEdH%bM}Y!K>FbSFVj*zB+vA^2i5Q^p~$`FI^da|DyK7<>B*}PM$q??Ckr` zymNMFIzYfJWa?)&G?VMP>2+|$3~Q%1bTa`0&P|J(+8Jo~4^3?l?9Z68ECuw8CI$PE z8NV9PuA2`JPX{m|rsXJ9t6;-6*mL8Cg*f!GBs8-@b~et2&GS*K5{5aRUedA@w=Pp2 zW=u>Q!Km!suc28&``E9+N^hSdT-#I#-#7m6=cS{&F^rfIO#_zi>_kD>F?`fk7& zEfJL#;mS{iRadt|ue1v`^3;#4klCro=rE}LE`eE`?XESvgL0Zf9gK&xM^O7jkH!UB z%>)fYL+2~&5&uBf=x-a=YR2`tBiOQUit#Y47a2z&s$VPdy=so&f}LT}a4tr@9=5n> zDQ{Gyd$V5QHqE{&hQ#cv6JoPhDm8EukMmI65xiQUBKe?!zSQxoBfASLlcJw$gc<}>~<@1*a?Zq2I?_W9f?zzFU z=UJY3`@Lu1c!$tU`$s0$bd#$_7@k<>oQ5g><)wALPCMn}Q~BQMwc*K?;qhh7e$bnbg4jvaDM+TGl|@;A;V@ zE!?APO-YC!z+K>$3H1M{nLyqr<8QVx!{+sd#n+_EZ3?th?Zr707Jm&yxm5X6>B#^* z7eL5Luu0v=C85>IZnEUs7>t_LvTn7gT@il;lbWRzOd`%Ir6Rm5lpeGcBvi9^RGTcO zsZ+2J*fWHkwwryUgkr021QcOa9R)}YVOfZwFuJKt+fu?jPa2JpHxU`UEap_#Rz=~c~~&p>fEv#Om~(oLeeiz7D{ zSTWA587CKXH)eI$rnFZl)urb0Br$wt`sBs&!OJ&}oxcpv#L#;e(BzSGmruTP9*mE@ z`R<7~-{&9VIR2M!5!#8BksC|H*B6JbEwBV^wy@4dg9!D;@c1eL^CJ^0NVi0sf zg|HQ{=OTs~S@JOTvk`bUETjl{*3Bnb5>9`~vXZs?i@Jq`eu)<(a-^nXk)ZX8b}2u! zOm7O26ivn}Vo;^z!EGu$n>X9^5Fi<50LHLR@487a3LqR`q5Ro0`DisXu(C{WuwvWn zfHVvfRDuKrCNL`nW`!Lv=M-@$Kg!9e)Xs@*qpMr0YM0BLjc*5Om1nNguv+4>ZOnaO zcw`vXAQo$ZLuMezWhjo?v|h6)sX<1E522>>KsR0jl2K;T6X#?Y(m|4L!%~bX0JT#J z+x$r}LMNZ`PIpLJpi9za!dK7tR#VPbdH zJj+pFOz7s3qY%NXC#{pX3Ej-HYFteV>wqydu`EfSn1bZR;p_7X&&yz@BCVg8)s4?+ zu1rXLFs_F7^2G3^@xcq%PriTo_}NRR-n&Q~f9vcsufP5DYj3e~^6mGIzxnRT*Uvrk z$~#ZL^v1KVyrsFmWSCq-?X@=+88ym~SpsSO)EZ%$UPH0<6RXB49L}nKY6W_=Q)`e< zs9s%+G;GfXU|w@$6?r$!1dNb8DZ_yq#IZm%p`8oCwr)DAox&$aA$ItNZ)Dt0Kr#uA zJrQT~EDj`!CKwmtIcZo-!!zz02SVzU;!(+}$hB@!3^sU6({Ghl9-1TWLc3moH-f2l ztuH&gn&78U*jExXbtM@b@C0CX*r>9u2BM9xFswl!78gNoA+rQ4ra+TWI~&rV4!5z^ zsJD6`LpHFG4pv0F zOfOyJnvWQIdLM_tc^O$|^r5lTdUytjb+kIi*c2tFb-$|Eu;rv~f#N+rLhVC!vzC@l z=^FhvX$Qf!+SM1UOeqKO(tX7+#F+??(ngB7P4cW^F-+?fMbb`(2*d0q%439la_+Q` zT+9}7D;SF@C{j03wD^9$7o)|oP5lx2Sr(b;&S^g(w24mvb%dbEC z(rc!vMdIkYFdI0Ti50{6vSDfo12b}C4iOgAZ!E&<$aNgfntsy9`tUW$7Z9%667Gc+ zb|7>UKEu?;$OJqGxNF@sRCD9fqn05&6VptF^)qqZbd1nUMusN>;x`t;e5(2lRj4t~ z_>H0IFue{A2WdtGkDd1-b>ebfzkuek{*J7wSp325^Nig+`;`K(W1RfM{bspP#D7xh|~x8C5iMX02N|| zVL`Owgjm{xP#2KuPcc7Cs2%mXu@l&7>qZmd9_dPlb8E1V$8q z#fVP%G!q+x*F^D9MbvWm>VoFR95vnWmC2E-Q<`hD+Us+}muE+=%<0CL;A-Uh?BJED zk;~U5&R-Ll&tK7BVtxG7*{efmuMjwjQ*WOieD@qM559Ho)SK_0eB-@iufFs2D{nsY z{kM+2^rpmj-+21luWGK&b7t+e1s!JN%A)r20!#hXrT^bIUYTPzu5IXwEYWH$Y+qZ( zZ_6c(uMx&6zZrGKGhbWcju2ijCbZ-0;H{rTv>DpKjJsw;hgFpZW2^=HYbPOJMz?V~ zU|)<{W@E-FdDA;yB3w*^d{^gxt4QMw=KHq$XKCR4;Wif)q@9cxrK(gsxf9xD0J zg>qs@&_gw|Q|lq)ghpv+**9QSvNl>Lu};QsW0iGlVmU;asW%nh%i%{n(`sP0PSJdI zf>I3pI`hAxmS{D$7Sv@QWnLbz)pe=kloC&Y8UIj&Rcr}7i?#6MqFX?2S*sE3$v4vd zfLMkeArnSS_N~xc6UoInqvzxl?icB%YLoh!pSY~auVR=_0dH)E+Alil8u92T$yJB2 zNaG@oCaWG8q<`WfsMB!{bZY}D$<*xFX^~$_q-lyKAKFf~#ar^0sq6?<*-lSn@^^H~7*4|hKZ2m;CMYokLCThuR$a{bo zy1p*Y0bHkKAgk3M1)y#!M5tpQo_T1LkVv#?dV_HR(pJ=CCa46u9VJYZ-iz2d-UVVF zw=AY56mh0tG_S}6B1TarVdrQI%DK+k~{ceWhpHYLzPup z4d8@N(5>KmWl9b{^($rFa*5`fgyIDBYyA9AiaX?8TH-Q&sdT~vVnUAka!O5yoFb$! zk76V5s(I!cfuA7&&(LUCY3i2hx}~ylwWe5h`F3onQt|(VxbdYEIiZASfuSh7E1v+sAJx+aQ4-VbvcC(lt!GQ*cf1JFcQrY zr@@~XVEhBd62~hoh=omf#uj2hQC;dOX(LRn4^6D{-sv6~hTnMm95MeB%48zxvO=^#OsFm!?l%n51FCg>k{4YZzbETwT;$U%;7|C?2nY{fh3o z$Td6Yt}p9vtmsf|ZgYH1w%|`D*6CeXW`f4)pl(7$TlFE_wJO~_4T9ld2KcD}VVvBw z%!GlT;jf(}*-3ebu#1>aVOpX{v3@FMoS_(}#l-s(xt5ZUQ0jfUvIHL6xROWZ2y{=$ z@}&4G6d`L63rk`l0y6Op+sY)eRDuM~flegtFo#M|aVx#kMM^xBIi%D$oAjgbijrF~kP~Y|o)J7A<~ z-8iyFj;3!+p(h2GcnqX?d>$h)bOm9Y9lkuz7Ge7e&5B9=)#*Vj@x>b;t-CUL>fDtR zXRjWAm(JS-1o`AU7oUCO{S$AUh3Db-F38GT?+_P3}0S6b#V%ShcC{KT$)3l zxe~xWd2al~`3XD;TTWh>HjOVDZ@}<^{>BpYa>1HwtJ>>pgzkonQ%L4OJ{rCXr6IPD zTwNKt$__r=_@?#-qRj)5YLUl98$|FPS7Op{o(7`{FaA~(8ySaZG1C5~IxbWu0TL|v`4dUs6YX&Z zk@2+>Y!j$AzC!P-DXfYu=UDk7CJomr(q>dL!qEx&mQ~UOUnhP;h1R@Wv98wCITSJo z!GKbMmt?V!HgK_fw6-)(|gMP)(h3gtNUbueh><5GIUM7a#{b2a)W#ZJ^ z7f-x?cIfT%LvOx!>h*VrUVnS|jdxDI@;br)lj6k7uO0v1%O_v{{;}`A^7OaA_sq9n ze)?N49s4%o{Hyr=q0ot%xW&p3}2WUxi~!x-j}9_K9~V@ zECirxugrin(v6IBJ406%hcMgMs2N3~RhMGCzCviOtQc$xZWgh^6}E4YMipLe?~!6iuE>7-lJO@PR4pgmkBu zu@(g+nx39vQA$O03A}mH@Pp7nJ4h>9S2wTLMrI0{+2ZhA9;8uVf`U%`vr>f_m+1%Q zphfcddRg58R;5ir5w}V&rN};<*~!m=s3`pnx)AIPs3OIiHQ1J;)@zai6hFh6866Iq zek&CQ8p8qWqTW;^$P z--a*VIQhPmc*E~q)xLL;0Ns&yFA@}bC*C|y48C#x?g+dA8waAfx{M$r zyf8d`Wz|Tk8ut%g_8F(5!`B$y>kM{EKSsU!09o?TcuF+-h!G6Tb!6WsRL|49i0mx*cW>)6P2_sajmSNAN@JvsPJT8uOsbXHP z!Wg=$R)PqoASbC@z#~*9>5^fg`Hc_)4z99~;s+QVkcs57rP~u1&3iWq7WX z)LA6@@F0!jQpUBk-G-)Ox_O3nh<>vCIDwzjP?$)QKWgKby|W3!WW+obBPe0$i{k4L z7T$~IhEH9h;e*%cR;}`m=;ab5T#)AF0y8<6vJ2bEMwE@f6(e+HZIQl96If*$3qu!X zPMw<>x-d700XREOze00iV(5J|`Rd?19}K;FdH9_R`g2#%;gheubNsb;;rZliXPNAq z9zL0;Cw5x#9;TTPW?M6{Nr;S0g;f`AnoAJInG|7|&%raZS5|teyrWt9`Lra~#hh-I zW^9gjALI~Ft((sp7u3j`m%tm3TGg)BPt6zcu1rkBv)F*O67B-ii%;M`1{o&NE8Q?$ zE{zV{g}CLVGETtmZ*mdu@} z3=qo*QbA=&LUC^3uFDjdm?0<9$?KnE93>#wWDES2?!(rQCl zrLnxqGrZ;;Shn^qc}KTGqjSNLSy$hbyMNj{3~m=agNyEg1@F+3)aVj;b`8yXM;8*N zHv^-~zR?Z$5O`hmo1x)P(@gb*nrKUgeOnn@fyBm+;JbTwSb0>Zg zXAggpCF~9`h6f;RR=42%r@om_f^)Y~CcNf>nLD9{yFfa)bU$JJ5$HvJ&?rS{z zakHuA#}q=E;%%i+9TdPrh;o5K(9Zb(*i<#44w=M zR+Uq&{0BW}(flkh-Vv=UP2%nkflY3W@8h<=)$T`lkBN*_+|3`sr0_Elj*oxBtiZBJ z*!nSP=V$ONy`G3_B=K{;5wjJ@)`ygpfVcE_q0O(u>c&aldjVa8aDHYAFw@rYA@+#w z5g3V5EJ-X(3`F2(EX`!Xw@Nu{Jo7rEG3ZSY65;u~@r(C@v!90M?xEj&bD#Pa=)3O& zW;`e*Iiw$lSbQ_LDJPm?W*g56HWqT8+jUQEx+ZC+R?(=z=~bASB|AI=-7UF>76YTJ ztnco@8Sn#!Jp(h&UToyKz|f+nZ`R#C78scJ^-Xf&>Kd`N4KNCEbwbe$toz*UL(bL# zM{^g2|7L6Kus3vBYTKQ4?cf$#w%0TxEu1x6w+Nn#>tgaMWAaPPC6$JvlGwsxeg^j&F2IrP#W`q7O~+UUiS>3v{xW`t-5(01p-~m z-8#OBa`sK`dM9=~Q#aj{qMre(Z|atR`nHzVd`KZSDDW(_FndSiS)QM}!;6pJ1JXRo z#WG#YXK|}vgqEK`!l5T~G(H~?ia&hoN4zzCjjIMewHRi$ z7~J_DSq>ZXbtwH^xCKz}@blSQKb@u1B<-v;GsZafxV}@srzm0N#-Nd4?_|c}bdKAI zC~0z~Rg|U=pBd;rfwcLV_5I6>AkypCR5`!9?k2D`@bF<^cp!y5`SPcLIgy5X@j=|e z{lFq4+B;ZAJ^-xzRbFE1VG?;7C;2n^5ohh#<*8e4#3fA%?R)O*4B2-MF zRDDAWfZ5$U1Aw`3c27}$(9%2W>KYYJ?i}{^jM4Eq+6Qf|{XAORdNDNYLezcs#$H=P zkG;0TQP*j!X{XGUO~&#DV_6NN0-X$)EoBuH7&aA^S_+En#if?~63U!cYRU!AGn8Xs z*48)e>YEWEP4CH&v1gn`!QVf{>HwsDgYqQehaZv~ke@s-A|iz5F*Lr8EP>=%Yc!ZW z{O)6`!Lf}vKsy1#8Om&k0Gnfyz6-(y6^isTgW*W8{h9Y>kn51v|~X_M>&h+ zV6OU*DLIlOZuMb!`5`Vxc==Ii3IF-As?YJJG$Z+!Kj(eqN%}-4zcO3d6&OId;#x4X z*cO9Vnnd1u?CZ@h&NBEwzV1r%2uNUBF&~uQt2Ki(eLG)KLY_*2Ah0ozwR;Q#DL#{e zv1tIYulWQSxZL3u_)##gHi&81Cli9&#bD&yVUj#ULddscbb>gijb#+by{3!{-Op+a zL*2f$M?nl6hDTe^S%X6SnhLc1zIbu+3ambq6>8;SV2P&VvjkoxwXPxaz%bASqF8W% zmTRyLp6N}PVM#l)D3VWW4Bhpp<#jtey%j&ZLuVv4iN;v*j^l&PvrMBreIv8M@r4lf z*T{l*VA0(-&!cZ}34V6>f}$~Z_o%yb)Z0Do=^jQ`csqyO?E}u%J_3JsY# zrp$apdak8?f-<*_+qpuEn}lbw_a!Z)f0aNBx$(!k|Mf3Fjo)NFy*Xmc?71y&t#u zIV&KqZD{^8t~G`s2Phhx^C3<}+#<&EZCXE8NtRL1)NP73&@)Zfvjq{+4WXP-l9Wa@ z4IqVO0dcXc<65wMJ5Uk*OWuKHSMMC279qbN4LkniZ|7PtY%q;5^zPjAq%xf?`n6RTayc7T5BQS=L zL9%~hD?GCo&jeh(!a!Orjt{YzxWMkfN(wA|=AVB6I|Y|N$3CT(M_tHV027ax(<)uz zGp>2ldG|#>uRa!FC_E!#kCq0j*IX!L_LgA}5I_RzbI5iJh3eDdud z@ROO61aSOrYN_xH0EaiAda>7p_LU~zXKa;d)pw90aFN8+xsShRMPODU3V(x%{Fege zZQ%Wk;(GyU5H7`Vb4?mODK!aYFp9+DNupfz5#g1m7(QqDkDH$bmPrcT@huYZy(|9w z0>mrs9OwJOgU>qyS2JS>Esq54W4Zk4c4++dqusYvd&gsV=AmP7gae*tDR*v?ursi zVXh$$md-Qhz|cnxE0?l(SQcpNfL6Sw4aT3zV~G z-qAgWKA~>~!@gmDBglEq-nZ=NUlCd!UWcEP;2Cd+*&^PK*gNApzOilp)E?!U zU@U$IB!g$jSrnb(YF=BInYNmkQ)u}fUZ`j0Q!wmXxW`JWnK^Og2?fIOn&@kgB3RRW zPV(j#IMv$I(-=TrieBCNh62x0n_pAsXzRAWj@$T(!Uo}A^?cdCi9-Ijc8|5p0DBm` z(n7-dx3DkJ#+-8V6&K8@5ikN;no1=+c+_(c-Frgs{416kpP=s-RsrRNOLLd7`E6+R zOC0rNnnBdUCSv}_;Ko;;<)?x5FZuDX*}aR>@N$PHZi3$XIB)T*PsFiQii-t{9+_83 zoFBDsNCyL0)IxN83!kCNSmOft7_$uc?%?^0^Uq*wZeQc!Bhk^g$9G+0JHDwcbRcZQ z8p^u{fIXw@uHjV{SsEf4M&K$BEsB*fxa{VwA6j$tEU;t;hnJk)6ZXzAH~ic)%LN5s zXaED!i$8^~Q=?JY>pLvR~%XT3rYX(HKSL zG=QeO^4RQ>=-eVhL8&pX$dFqYlbJ_F-pD_7HOtx3?M9Gmao#ZudV#UGcO25Tw-4zx z!rmo=8|1WT>E20-1qG!9MT23wKT1G5vaB7C;LutKNRMoY2pQo8ky$w}4vQ4A5R5^o zi5-epSdUj&@8ASD85qk5X8M*$J0b)ORUzcXyTnSZ<9mP^*44}$kBX)}RQ?{CFa@JS zy?03)Pk}Voyy>jPFqOzlW#z$v@GyL+IT<7RES{V4rE!UYA9&``zwr%YaVSyr?d|Vj zU1n#32)9TRG(m8FUo4H{PrKsxR|&r?Ld_*XnqG5pocn${cD$3Tt6kthyq40LJj zv8qI7jIIOb5Dh+WbpL{X2%Wj;>PKoWyZRB#i>}@USI?vnvhtQSsvTY9TzGmWS?=Af z{l1PNZ%e1IwaeYuQUDaT#tf#D{RTRo*pTqbgva+^I$#4=@WP61|0yLLzvV62}(Z(wNfzkoENg71rdp!jOi^pVe} zXWaUp+Mj4Eha5-)Y<>W4G~8_XoHd0Hk;kF6=VY;x35YUFT9;ojMn;A93g?#^+4@3i(+L|XSwA)aAx zF{pb;rA}*dMsf($Db?EsM^-76vroXh<{#da_HcMz7N${=&<>`J6I&s4^7szrMvzR3 zl_$Vf3IrhsU7$UnToy-=j3ANDWdSY%$@jo8#wqq`!t&$zrAG-%4-+vo6rOpbVJb)o z4#&ik+IoVnrXN(D*Einf=UQn5*1isHe5)ri2xFn^^=H^zfz{{!6+940wEoJ>ipxJS73YiR>-y+Ba$!H8LK0X1eN0Wo+@CM=s zi6S!{&EC?YDhY(eJf5lF8htAO!yf%Mvw`1PlOB@oMm^s(+H z2p_U1LI$i${NYq-pE2!~Btt^q6-$5mR@}^O93(N3bOv&APo7cD3;jDTEAJ636rR~- zZ3Wwq5APs+6#(ZnN~-U3cJtORc)F*(Ju~o|h*C(ncihuAZR-$E!`_OUF(UJkrXJL? z#xpVlSJ~CjiL30WYO`0OlUtnCt<3wFm@x07Y~^*9(i&rNbu5Be`ON0xG8|^087a5kc^XGNuEM_C`nX28}+DsRBmI)p1IeQ4_ln#bNU?r5EG zv}3lY_ONrr(l*SU$Z%Yg^WZ$C9S@Ca+CzFn#Itu`#W%1X9^Khrr$)A2L(Ie(lFA^4 zF`|Ebk8+RhdB$$~CT>&SNsxTUJNdDH8jn;Z@sy`TBNM;)833k45YCa=`z$#35HL&s zzW6!7)-0WZ92G-P!ebQ41XgD*&>Jl1Kqzi=pBwcmA6$KwwDTSRB*mC-^V`IoA42Qk zP4#yKJox<0ZvZ*NI7WC7uNZeav&Yy@dO&fr!M}iCC|YKPuqzw#iw0Y`hXtey#~xH;4Iz?wg<<0W^Q@V@1VS~ldw>=sgWk~OPIziJesVWF zz8yw*jBNm8$k{i#l+K*x5AX zXdHAl4^W6_M^m4>sl(gSB_X1kW?<~9X>&5ju4=MWGAn7clr@-20CTOW7`0p*n_m@` zTM~`2oL_7%C^6+0ne&PQwh1>8Qq;&rTBqc#r>IRJ4K=agCNWB*Wm|g=GY8iNFcf+Nfttb~Plq!Z zN$-5eHBX{IH0to~WDcl2X8^?f!(S5!TgI z&$dK{>0950wt?=~BB3Ri^c@pJ=$e}-u=-Va?W_2WZ&)Vy3Wy>-D8T^1hh$s=OG_d} zQ=|U}9tKh?_mJFxS&+Q=&^2|3Q4|9yhytU7mobFl|0@Y| zfpQl4rlH88RTq-9b@TQssJ7eg$y>-e!qWvl?+V)ZUBp{0YU&GrdoDg`Iw%UPR- zZOtQ|mJxUJu)V(5)imINA!YE_YpLsU)ps~*+c4rhbs!m2uFYQ2;H+x0S2dVQtFcW^;0)R2-V$yR=*#*Y*Y|5OOYq*hRyq-<5lZo=PEcxXn+q1cL|T|>Ejey^#&?O2iZ41V?O|~GZeZ#T z-8a^Uo@XHfNh8436ov+Ee*D@qOb-eRi;0+6vP`;JXJt(Gh2}K0sMMB_Ay5G@z=luI zdX(CcjMV|AclY@uszwB~;9HD}v6CHJ7hvzQy)j6IXcBp&HuA!>W)1Q*QfUETAP zyJu05+{>dx^|121Bb)A_b(SqIfHV}XS(*--C6DcjvTu1{x)i06}#v5M+R=&W0 z295AAn*u~Uv$8Asnz;Ea1uJ;-SrQ6lhm6O5{!LF0`7}zv%m78>Utto^0#5iJdI!(K zu6zFpZ~x5my4XIzx8qxc#e(}*B1Uw4%G}m_thmucTC9GVxWP{)MhABdH=P7x1>TYj zL=;Ib1v`4}5x*uydno%Fn3xb7AYz1ZxB5Bl1HPXZ*}T9D^&mt@V2;d&TV zzNi?dtdb*}yfr$a5E|Q(8eM~hSZC3VTmx@(MWBBk?ozUOjs+S9b97C6yJp=T)BcW$ zKQ5Tit**(XWalsrRRZXMkhkixEUD*){I;WM4gslyq*q4gKBeihm{7iuE$#2 z%_9p0L@iRMZ3GY8-7#x#nS`{VZa##l(HfKHL_lU|$X#;XJs#4mgrH-8r-OP8&NR?spq2GuNx zs6MVkQ@4F%yDls#B?3JoOnBF@GPF+CjX!Uk>wu48SP4p8H|Y|SJUop?2(JQZbvQr+=5zGRR^RE&~mZh8QF}|h%Kl< zHq#YGW*3}6Cuf$#WE5k^;b6#UJ39}}OlhTIxRGH@&orfF#a>J2_A%FXS!%k>)t$C# zV{*o2uSsxfnuF{^uOhe@kM6X!XpiFK16 z@GdD+X$BYWduB)-V1VFz2(W$Ap9be1_?Di)Z!|~HH2_d6{ue+LcY-Bbr|+Ovo?#M4 zPzMg=pZHAZR04IPA6_73b-^?4mRnnlJ|(-=g3d0>GMQ_|P@D;_O{?(f19ma>4jas&m#&Ths$5Pr6%1pk-j} zXdc4H@N^9Gj8Jsb5Xu?+SnInPWSi?jSEr$(RqQyGl#?8OWs^$dHBUakaTb zCfXvQi>r+V75lT2>_R*Zb5;R`FNbVKJcDQBjaYT!uAw4HF(xSOC?g2 zMLDpH03&uqzhw0B3>%rX}uo5YB4@)rDnr4NnpE=b^hIx4hGf)p5|mY)lFRz*Tc+ChOCLX*8(s0ac@2oGulu70+UG`ced zV5V|$8$X8DUZ8$qT`?=L;5OMa&RFDUNL9uhxNvHs?cZSU;fr%0|8L^%&j~vybPdxh?G;EgnD5KFIfAezD_N6tJVY)|^jIC-PW(gLvZ`j3WiTx?|P3L1_$$ z(k+oVdJR))G&niJ~$t$q3LnMKB&;+V_=t(?u7G=SNFIre(C*3Z$Y*Ny2JhSVD|SFh_HQ+t3o z+b$)f;b&S=eiHPLt)UkY!q4Vz9;ANd>M?J}B(19-1=2d^?V5(SeLb=yAw{%?8bexaJu!qI;xV76cVTSpMeEs$f98R2`aWz7 zo_WjUU7NWFyk(fXEWsq{2Ui5r{*^Bni)cL1I#B{<_RMN$U=7Xr7+|x+gE0z|L8w*j zla+RCO%{6CRr|)UDEx^9C!e$VTxJ~VR54}55qthQY3~<6o6JcayPTM@Z`0|yAzDJV zrKqp3F^o5&!+RoN5Zg>`Hok(2k;Lk!BJeEp7rqNa97&3*4U#%H=v#SAfpA%U7M=v= zA1AD^4e&EDFww?y591aeOGsnxo^J|TxJM!s58ut~Z|=^%-WV5|N8%A*4kS~&>=aJ| zY4`A!V?Y`}A>^KUtSamanFbDk2t(LMTQ%QrZpxRYZZ!fBLmeg7cs~D76b4#6tl{}&= z=>90p(&qd^V{X1FE8CEfDON^$Hqt^@%+(t)*Ka`4#?%{8m#*3?o6+Q0eiwT>2b#Mua*Wla%Cw~YF`ruA=RZy5#8P&B?ec|3~19$<#3VQFvw znxjj^2FWW4-Hjp4BxtJBO5mA+3!~L|iEyAjZenhr_n57S6q)$gGj_{6%|;3KY7rRw z%s=&Mcur!Fhz;JpgypA5Xi$yIA)`YAOVSMyH~PxE%+@(^Ho!^3`g05rJyYXzc#@nC zwXZS6Ko-#}V~))q*gujiHU(QwWTb*eN9m~tLmB4RgzKPa?bk^gs6;X*24L3r1zH-J z&41Sz)?Y_YSY-3d&NqsdpYt6>gs{J0{W+sO27D=y`I=ZOB0M%f=U8ASL6{p_FX`0> z6;0<0Is4`x<6ElDfMUys=6M|+`X=uNrtk4W@#4r3YVMPLw9k^VlZ1xMwI_FZd7)+S z>>4DjPGD@$JGw)GXU)l2RTR8LDg#=EoXMf_{$eZ#7zJWzv`=DrNzkaVPtPov1A=D@ zFh;C4^s?v!Y&#A{HG@Ba7BHq9l^wS7Hgid{p|AlH1BL7;sk0T;nDeWxg|(*KGDCKW zIlIi1Rcgpqkj^i*msFg&aU(W6+nAXZo1S6KDukR3sq}!EQP*xzAe@T5a^sZ`E}P1l zY*lTTfq2^Jb_!+|4A)D6XJP5Oeox~N)a~U?{1wlh_6cA2488}y8owYGG=-f`@j767 z=!}P_cg5ScN_!|BA`)6k?s_aB$>0rd;&!4s0#L_(@!?J!Gpy-b-ibS&aU!GlJ(G9* zQ};u&4{=Z_R#jjentcGa;}#xB!zf0p%uQT#oJ#u4yYxiknTa72;rLbN4$qiA$XJaH zAZw2Z{|KaS{wO`#=GP>D(7Mbr5;nh2-uV%7rX52Gpe{6$kq3Ho5IORNm#-SMvsN&qvT4=wARfMlVuvS~K?;(AJ$y!CAoQyUpxe}ODP z0^zPu$PfM)0T~iDQh{g5pQs5S{7ln|xC$;k)jcmln%`Z=IV6Nnb20si2#gsv*R#h* z#webN+wO6^{hMO-kKS|)?e81HbVB&~Ms_?yTkgS4*T9CWXBi5jkq6J@@X4OJyXGA2 z)3~qLR`M2iPeak-33QIzTZgR;y~5A!11bnAQw$G`-Oy_+ZFbgn`{)NHlix;J%VAD- z{|TOLWv!IXBiYMaEG3PWf-1^IU?aPjqV+>98?*8wZ)8hWKR1W6h0y zES?5h8uR(ebqX+Z*O<#&EfsC1@-}OgjMqg%t9wmaQGVdsJ|GRAeTb!Ie%d}qBOT%h zwmEqAV9<5V0cpzGPQq#m%g)&)fhFk;``4V^OOCE(%Got9*2mxqT+LnY?q3a$?*eIO z|2nTEFR2(HBeW-2qaTOhlQD)_p8;A5^af|{3;E!qs_}|{;$HmRqc}1-GoR{dIK-t7 z<=`FnEJ$z^lU97%)#nL{3E@D%%zOv(h0*5sJQ5o?Igh`v?;Q361}Z{m5P5 zos}>%EX_oTdz`%w^v;N622a{4l8edPuF>1hky{{~mXKA?JAT_c%6#^ge+;{6(>Jo` z8QRf;+0(a5@din$j^5QVhi3NoF1tJDL9*bvV~k>5rZDR$#4{}+o(63oo->$n*GqXC zdYrYLK+9U$ZY^uISF}4SJFR7HnxbP1>WxK>wz6h(aRXpB1g0XWmeP4Dt>l}xSHXb0^WdJS(JpjSCL-M-c@@y z)1^g5;ZU@MvIf^kmWIaUWh9RmCj39L;~y69C_F6#S?|OiFFTWz@YLOS8o-(R!D-o& z4B>=lKaHDXI`ANF?z4F2gS@|sVz>CW8#zT^9YXlefM*yYoGZKA=k8d7)imkS4V)2;4`b8cfUZg=dtHk$C$*aeEvy z{!?I!cm_t_&q*KuA1?MkU(IE>2H5)RKe(V(WNIW zT6)2sirVJJe@NDn^yquo!0~p z6BxUD*C<{qlo%fZa)zgr-owK4urw?|#m(G>nE^8@8txSdJ-kP8;h&_RF@79N0S_?ZI9qD5&8r9A}I5_hLh1kb=Vo@ufgC^J?jk|Ery;3OMWXxvu61jb;V zu?U($EaFWR1tAJ-7DJ_hj&5oLvxgJx3}v z9WZ0i#iV9MUQH9Rk(w2CH6uDT?eyiV6m)GaZld6PWDMU|zE?$y$aw5KlurewbdRmN z&sx>%Z|wCo^mqwo*R!UG$GAUFY?*MkPTCtsd1O68V)47+73LjXp zsS7=L;-#Z242^E;{6C`>gj`?(lYfV<5Q>JJfiW@z6^#N3Oh{l!LN((b$4!44o_Q2M z_aup#FNr(YjNzbC7l7G6&!HTQ+vMaK-fNmHBnK^0((1D?@j2!ciV5)_I3fx0{M+h} zu^|7Xau?Wc62ntwGGL?FFalL3&@*oTln9yc{fP91(luh4TvHm=iMM{{V&4N%kk%Nc zdE`#v5yhfYOt=|*M<5Nh6@kl#GUZWjIgbDvfx)^%FMwdyE+rrGBoxgwTo+=)J9XDL z^;uv>R0kqNwjOg78^>#NM3qQrnQ^l>nQld#(y5zxbP%#|vQii5K$&Z+_Y3ii*g!v{ zF2FNN5}M*Y#lIr(fO3YJaXCbAwn*Fv%`9{6`X0vFG+!+4jJAzcEh;{TT5fh#wR>vX z?d2$e26Jh>t*lYzfccg7;#yN)l_96XQcy!bXf3RUrDHOSR99Gv>fnM8MNVf(jxH)S zGxAynrICE*YC6d}Yi{1@tJhw>cv<8}eiLOaZDL&@9D-tpuDS3KQmt;aRN_eY+iUuP zbg*gATi1*Bpzt~foJe$vIZMlgvzZtkFrGn50cKa*tfyn%-Zmyl!k!svjR({%KOh!; zU}%%314vVvtEDAGcnoi&pJ5NY=-~7nqIbU0TfvD>U}=C&438&i25A71(||l~;fwJ6 zQ;a)SSc!0~K8as>jtv`}eH6ba!84xGZblNa841zskm@5r`8xo*223w|tqMQM?w?~Ti6lUfTNW)jU8ML-Y{E|roVD`3;;M~$xX?3bq2dg}MsNxx| z4u&ZujRfZya06o|fOyUfO+YVr=FyN-2AFL{b=LeEB(x=`Opu&j8hfL}lv8fZE(6T) zbL@@0n6%vJYneFD7#i?%^p*6;OKFDdX_k!4$g9_)uBBRwn=M69bRD;hK)RxJzYnd! zZ0WRCc33Lf(IKu{^hTejq2E!1sVHL?H`fgV0Nd3%M(N*Lz}zm{18mbOGDu?R&uvbc zR2Hw^MM<*^uydCES(_p`7(Zc9>;76H899fj(@df{8AyjF?*Qh&)F(&|3DwL#z_=4j zYW{OQLBO)(B7TXKoj7<&bb?AxVj9piVb(#{V%e=DExwZ^o61oDLICVt|CS9_$X#_I zyP~v;08U6;&9NXKoNGS>B&Xc^g1eU_>@Hu*h z?@p)5zskL!lBIer(9RySb=i}}Foi>J)(C9uUu%zA-=W-?6t*)(GbmeB=0BquBwMIl zyU(!bS+HmWF*h(Yv^$61aF5@VC2#t6XyR6I{HETO4~%&){DT{WdzlNU{U(w-(nQ1x zEB$`wj38OPvwX;!OBMoW!`?8UYKW6^-HS!mlf9)Hw|X zC`QYmt|(T1s2!F=Gm9(C4Tc2Ix?N4xXb)HIpslhOR6A>XAZH3E z1e`l+dt{PWKSV*%-nKEUb%yx1<}rS8Pv;zX*7JS#*s?ExM;0kPEyeD@^uV_lqaHS( zF&W(j()*8No4EZd9G6th?lZ}c;W;nLSOHyu z>If}8*7}+D5HM>`OecJTD{T5;fcOpN+hE`8kBqH@n?E8yBp|f)z2q*`iHn-UHDg2R zAROj=l|SCCrYD4s;&y(axR3+MZ~d&#^#br97CzsnWtpS{?0qC_O#>t{7^=`QP$u^^(Sut01YEDE2Ni*fkIXiG- zS$SurQEHc{gRPZ3{H*3@rh$S1?63L(JqJXuN;4?IX5mK4S=r*QMl*|*p|j1F;yOA( z^hRuUDUYDql2@rh8l|zBW$-Wso;9R-j7iOlzQ%w%-;kCUb@>LIOhL|6?6u5jkbLn< z)aC0`WMNHIQ7!&6X^@zFqSP%=G~bt!i}H4J2|pe)9r45QUicy1we1+u^sx4Nq3HjA z#)IS%qZYVYEl&V@%HK5}>YWPp&M@fLAyQmBE&{-q)E;o%q>L6Bi#6CDmzvnm#XHw3__#=3+RDorQj0dnUV(Q~?9=Y%w}E zz7a4lkzxCqQ$}@<_N)5+ULUK=BZE9SE@PW)vqUujC#RA^tza9#YrPTLVCR(dfH)ic z$rVmU;#ed~YY!0^dgLuz2_&wMQ!Pg)sn67Bf^lC!(OSvq#FT_ZH=c`7XM%||lF;3k z;90C2F`@}|h>)gq7yK)#?<1`#7w4)?-9e<`0s(1!ISP{*PlHh`o(9ealUbb$Mf(Xe z4{lL_nRqkJ4&s@iiHs6-R=<7H-ZnvxkH3KtEnc)r^6mg+u=(Fqhs4~T@O`2s4K z8=zVP3FYjlXhvqBpY3J!FtfCQw0?zE#$5KdRtTi?tH3j36v!D)rYu>dri|j)v_exx ziQ!s~F*TQpy_zkAeE9|#rlKyU##~N|xdNUqL(x)s)yBd)LqRQ%u>}nPSj_Db(H?Y& zaJ3qUw{W{L@!@Ai7kQd`Jx%@m;9Jx%ei2%gaW+G3?Rdxl1gyrIQ|1GqqMVD&;miVO82$>22-; zRq|alp7rOz&-fv9qtyQMYF~`r1tw<8`j>hdh+5X`!aQ!x{Fi`V+u`t3_tLq@p=+E(p&FQ7nmF94cs|id{iIWkL8jr&vKNII+cP) zAg%KZnxpWd?XA=F{?aiiwMm+e3kDPL8`45Co}~006#%IjHES;wdZa;9wnHoN3~V}b z8sOQMS4J@tl(Aq|dDM+!@JzAY)s$5db3NafUS!Fth)ykxxt1TBS`d9X6JS$ZL|;i` zJ{WuTx?uR?mDo#Hqb^+m*rtL8b77;osM?TU0k%y=NDgIpNYJ{~S=H$xq*Tpyvrb~; z;}O6^FWGClu|62JFsXO*42>b1Yb3}$4lQf5otMJXI_dA233SdT^e=}7)_e?4Rn8wU zGh1=@u0Rp{vqFiEZ|Dh&dl0W$&M$zbA&JwXK|=q zv^Wf^vj~3RKv8BWn%mEkBjt;4eTSCT znNlbkSpse;?iA73>JhI)LPsRDv0OI4W@Mv=L9_tkqANR{lVlzgA)4M3y-eFbMT<@l+YV;Sc+`$+=i~n(P7Y$pbHMpu#sQm znfDR33_B5QAeKgAhw!kmZrEB+d~OWENdW^`4h(>2hH(%zz8r3bt+2t316&HEMP^Xa z5*F1{FeiFL%({HFWxJpfJV&RK2rZ@i6V;KK7oCwCotg(fJMt={uH{-Y@?`>eEsN3` zgGdrK-M$5V>00ciYlh3IJerGIWAhqg@@h>*jj?o>g>^Bxb@sA$=HN04XJV+WX}ZE% zHk6&c$uo; z&(j8~OesnOet;-wuEoY5-43Fqhqk=Kd;ZZ|DC)r29yT3~AwvNuntqT9Af8bdGj}N= zqWSy!y~YHfjS{h;Y-fl|thrT*J^xmqn$igkfW&I9Gn`sK#BURp`z7(#zi}tvUPw5w z`a^gFHvWmi06`(+goxX`g^i46{+UmPpU-k;9e))|@GN5&c4T?isf+c_*XVe$yr`1Uq>^j=9`imL`U%pa+BiNa6y4&_*t7aT1&Ghg(7`K z?Y~MBvgsI>rklp2OW=sn*_-iGIM1@`Y2m?Z&RZY{4p8cSA*&##&nb_N_tD2GD{8eB zLTHklS!`!jX0~tV;n$JdCw){Jn_gs07sW^bg~I+5l0C9ET|@?IJm}!VvalT4s3@;Zvke{ zzy@FzNRQq2jtD=Cz?frCJqKMX|5@onJ?SP$CZ*zbnwe<>d83m#40(yh{|gFTO0o4r z%~KE$Vpb5_!0)99@B2lXMzM83-!(Ln|EZrNG{@Sm5Bvtnl05nrv5* z?5jR=lH=L2FIaTMgv51}^S-bm>HF9e%x{g+!2t#Q=_O8#C%(l%iWY+xjdd+J!F2V3 z9Epj9Ry#MbkAU<(l6#nLuLpSXdt{``6bz@1L72{LKu5mr1&If@j_{sZo5)g5(DIW{ zW0a=(nE)Fx45AviUMOeuhLcT{+6VT^6SELpHsMYlI0+$F(=_V-fqrN;?0d)ekLw7EkCw~a-^APOE#XJuxqk^ z5Wp~QlVJqM)Nk+?SU7G=3}mo}uAs$B*dojEQyjFs@pIz#FG)N927yGNMO3pNR;dNR zEb@b~HR5>}Y|A!4EDq!c0tPSxb^aH{SKzB9Z2T0r_Jek$K{A>ICYM~tCf|{MP}~o; zv~YnO@-q5dr62r8Ctc;nT$NvkV$q?!)i}r8Q2vHUEZRVtK`aj0o2Iia6E~4$kTVp` zhC!w$ghCM>^oDQu%j2h5I|_eI0Y$>=cYGk7`erigInx2Fli+-VJa677h{xOCvl0b6Apf1np?j z<>*}u4cQ($BgND}(&=iR!jJ`)hOaQ6nfYR2LD7lp&snUI9H>)t1zn+RpjI;xFsw_Q z1j2HR1=YEBzz=}MZ!r7&`5Xfgyk(uc+aj4Pxj3{0E;PmkxqWe%)x?CT68So84Ye6u z_Fm~hq4xAhI!SFaRout3-k+kxi2^frG^a*OU{!38;L2ANGKt}%o^q0pWx3(^qKG8X z2I_e?_pD5an0n8!RflM(?01k2J2)FCu_@VEjJbg-!ve+F|7|;!Y=9lvkqnsjmvBv4 zG<%lF9qHTxqh5dKtSqc;(&nOEai)&Zep^xVHO^eT=FQDCr(OokP&9Zx{oa++A6^08C=K}E0II3H8Ybz6{038DQ*3cP`WY_~ zqBa#vfp(H4h6?r@it}u%9bg)c@yNK4G%3~%$$wTNavg{(CoV_xtfO(--aO@KnFi0m z8`a@%pMwNQYGK)Nh7wLbFDc_f9-Uq5zWyC|-zLSYEspfqZAwP89EU!<0iKD{VL=n+ z1;FfHk-rwiu2{?~+3d+-DV)@eD+^z79_g15HDFHUGysO$s1B9J1k$YRfEjhF_v_Iu zijYQQOCpG|$WIs`$OCo=itbe>HcR7107+tU9OU)ylw1D+_Ly?XpZwn`cm5wDpmHLv z9QFJo-d*x1|108T>nHFpwfAodNVAEXFM?a5wK{)GMJ1821jXNjrTGNO_^p2zzxs^? zs1ViMiObK3I`b$(nqEMqt^5m*ee;jP^H1Uym>)f6vx9b?vFOF6pZbKNAEf*|BP}6G zBq@vzx)QPaiHUMb6?RjP1m}WGxcXNmL8sDmh-7F-_d!e+WVoQtvLKMgXd7W^t7Bi@ zAV{De6yZU%SPi>5?}!8)g*ruVNN}zMhOA>O2q!DgnVDccFvg~{pmlR==mDj&I31Le zyJW!4d{7-0nh#O)B$L6I8|fsGqEpi;@chb!E3wzo*o}gI2GUU*UC2ukI(a%~}yN5YLiIk(9 zMkSjx}(R5}KkJEC6T!&7SVl*R!M2GR~ylICC|PLQB7L0mJ!X%#|w!@T_FBNa&BQQoz_)P>C7Hx09PC zx5i%5=Ab1kZ;dT(gp+ZkZRMSGi1vyOC(BCBkh^{q7@NwwtQCEZ>Op=TPowzH66a`~ zu-A_PW=A7i*Jr(L3yi|?d3^Zr5?Gq?cP{w47GY^e$C9&C=H1xN%nj)fc|D4vvfY>>Aw$&&0z>bf5;6#lbeihpejPA?18y^*+MSpc*h^2tZ{3fOj9Y ziSGd$%XUKgDFL$_U(X&8z(WBf;3PtVKbB3iM&NDvtK`iWs1z~TcA;p%{BO2wQ(Qpc z(g|*H%szj7O?p72vW`GYdnhrF?{P(vcK;VE14Dz^4HFz}K(*;xqy=m*360HfbeLZr zm1U>z!SKp+Mb6JKpSi^-Js9F&DRdO716f7!`+{M>Oc4W!pMQ|FaF-%_#GMWapwsB4 z;bg!p=_6f3r1y7l{=NMh^0EWzE+Uarh(NjCiLT#q8kLlN3vKr75#q1}Hfg z(SW(wMEVG>PRHUXVviNuQiy7txpEz5Mm$Gfx)J%&^-~{RI&nrb&PM9CDiZzSh!&lz5fsEGQJ3r;QjMDHqxDfZ-WHf%Gl= z`32kiTw^!Iz8k~JyUCa!fzxB=sJ|=7PGyXa%+z8mn{IHpY=?O>2kf4(-)vI5Kcg+!DYDmZ2`RvY%SLyY3 zUZh~VG0_wGA&e>#MU6jrQqQ>6#@HVjyAWGq7dih|r#QGlk~Y5QfDX|x46@fbzKO*3 zw>(PXny3b=16Da_i$T{AwH&)4+MZownv(&r4(%hDu{#Kb(mP10G>e{Y(*WXW?9Wm$ zHzvh-hMZB(uz{9s5QT6>_hNt(B>I+6&iYIkUVrc`o2obtOPy1}s248scT5Gy*R@Sy z*#Tp~3~@o%$PA5VLTf6h-+?KIKjtWIahJ(d?l(w7&Xl>Z9wBYct2O3Sha2movomq( z#H>@(6ZQ;Ra+nOti3Aq*r(_i9%m&dTb4EVO8Mk?VkJZIAAnh$IGN)%mUQ9pr{b=WIanuW6mVqO9#s+7?0-lwLhYikf2UonCvX->sOFJrht)*S;nxR8< zRQFN@q~$lN?TYIf4>oiJ>f7V%2I6Y_lj}#Rl=|UwjiYB9N6$5lQCz&*GWL4=c?atYEd*-Rv+NaKUOuybW|5oqP>piRIyH{T8Sv%jm zPQ5j_{pR2f_0IV1w?=QiKD7PT=pOaX_^mg_Z@oEj`;Ey@-kH7k&cfr@rysmF{pp+Y zpS`|#|Ba;w=NIq4x$^L>)yHqIJvqPf?A+p$|JwV8>vOALp5OT9?D{v!t6wFretUNP z`wNeLcz5&u`Ry04ZGHdd-j~#Q{zldIH|HSg-52L?ev`8G?9GpVI4irZ#Ft3e{!eKA zr*|Lx!Zrb<3jlug_WyF`2CNG+zjN=GS8sm%DxNmSO3Np|;7*Z4V^-NVNDB1JWF2i? zdxk3JnG|*taA2=GHB>7N?k}ldU1$~{HZO=Tr+VQ8=0_Zk%^XlQ7ieZyD}nbE+D!7d z7J-o}f%GD#oS-ex(Or#PTikuf1gb_L-8j3Z?!5RwB6XbIwbcA!I5|!vl z`07_$7EgdSP*OdW9RQnvge>c247lq-HT-NSz(8w+nSnGV6kS-xK`}s1DQ6MPhz(;# z4y_+BHfNT`TrY^do=P}s_Mr71oOG8F`$f1E3jV9GhfWHzMoE6{*`L{`xVpwNE!a;B4z&Pm6*R?F#h=i(_cO`{^{?O z`L7=s|MFh!pWci4yiIVi+(RX=7a3$_p?kNW!tXgTQ21~t`&MRD_rSij`S*TPQ5d)iE@{9cq_Vmb-h%e zagZXv9oIR*urk;+7uUCvG_;X2ynb$UGkJ99+{Dduvv;VJxjU~e-b-0}kjPf1rTa;o zwxmw+Wh)|s^(6k11*eX$f6j^1{GkW_s)affS5DlOqde5vcknQ}1ud;3OtgUjo5oYN zpD)YCK>ju{Q$LD1ridch0LXd!{MC#HILtEcT;;r@J0g>Q&F%AP%(Xc02#E8rQaOnKXuKt&YA&hh1vki!9;|Ps^mlhnOU%juT&_Sl7S!z z3KU3wjf6tUIp-C#e+n2|bEOjmgvN|KitHS5P|Ui>RA{-7^ik|pG8_2MvYY$N6XEnlxcu@+xqSyb{s@;#N{);OV;SNW55~O_b5q|Z^MIb36 znEX=w*+Yr1MuZae-}zIGt#d_>&q5#jR@@oz^Yyc3b|W<=s!5h?FPoc&!y%3Bd< z-;Ox{`vY(ODdG)PZ~x`sAO3#e-M=0F(?3uC^$PX!d)Ff`WW4-ADlb=TYLPLm#Fky- zE@*TXG`R|!y=9%D>b``A{*;#CS6c^OYa2Y*KJZrG_#6GRZw}1;adPV~vwOcE-=O|D zb@NZtx89w)^~c#y-krPq$Hn`2Zu^!)16*H)gKUHu|u<>}kokI%0?cxUH}vrG5h-hKS) z+P&Xx-ASHZPnf%h7Z=Z8k)GO3;TT4S+DI=6Ywg6%Y$tJCIe)E*7(cr*mEIt=NQKaB z?3*A<)3-{`g5kXHIjbE;JcG-j(;DnRAv4Kj{<_`8cAU*D=AET49OZU`o zsqC@UHgUQ>h8X^{ws{$&FwxMg2ssNk77-AY290tQR3Vsw9Q`1hP^f)>;|Bbk3-OW* z19Em!&}cqtwI8)RUou$^Tii!&UapVW9LJpQ6K?Num+z3( zdC=}q9Cie#6Rx;Zo`jR0&@rd~m^*yj6L;Jd;F`}r;pUm(aZl*DFMQM!JnV@( z=1)8kJbT2Oc+{VKB6N-q54poUf7F+7Jdi~3j9i40j|G#C1ycC5ghdyUUO z9+z@7lyoBQ)t3`reGOX+^ZH++-uZjXyZ4xXvjmv2QVXU^%XLkwqkaXgy(gBVlqkkpmnic4cfW zhuq%etT{@K(4S!HC&h6koOHw=rg2Yf>eEX|We}(%10!+$5e^UJ4Chr&LE%G~S$E=$ zXlcgL8|*+~Ppg~>qq4rhn3*7WW;nRR zA3@?W=ngP59Hi&c{0yEcBnR39TE^J`%;;yF4aV6vwxwjr0R?(P3KyJ3K(?8Ipeen; zO6*ysk4)F|*lEQ!*jFy6QFwHQtLesz>0mhK!wjhpu2N_I`O)crT(B3`P|m_?imiw? z?2epj`Hm%Yg@R`Z{Hw$rCLTYVt+b7D(8-o}0%=Om4Z-vA57HtGHt-zra^%4?F^40g zkHr}FAEOLMV@xkan~z&uFB!~-OxD9@E2utVvmdtF4$Fn(uqwH*+7DT*#~e=niHqZQ z&k2Y3nB8~M6+GtjQXu(+JIGyd((OIw2%dBcw&fXj+{?j~Q~vl9UVt4w8Av?tO*-LA zKH`c$=Glj|M)hG&_?SQ8uqWZDFX^Z^g^F+_9SyvGESPvSkPu;yKkPdfVTnKPfBi%_ z1=zpjOgZL%9pnr61Bu)PM|??#y@`iBJSM;7J4+q#Cr9{_B7EV4p~RQ`@lwHrL*b-| zP+~-UN<`wD5pm~b;b8e-K}kLzk;LO`5lOE{q`WC>$E&}Kc>T{2Z~W!JTYo+H&i@?x z{XY-?;a`XU^xlcTestn*mtXz|y?kcW#avbm(~VMFMu{h{Do|7xDrpFoHA1*wd=MS#oHn&Ymm|yu<`Xm;nY09l-BOU?%F3MQh zP7(FNMqrYnoDFHgphROnZnK=N0aZenmb_|0`!Q+7QK^ME8|EzbbeEx`=?Wz#is5`C z&zPEz#xPvVqnL3M)p+G{sy(mh)WuZrjL*!u1d$(HrwxpGKh1a{Blg3r==U?==a>I+ z0k4muE9A@ajbwv>!ZR^Hkj#$+j8V>7Jo6~+VR@UQyo;hSw3INr@4oF9(vTQ-S0YKIj@sPdXV+l!CYU*SObC!qvg^ zNBytvU;E;ZdE>ZQPWs|b`cr=XA0yBIA?mHa#QyGYhClwx`rj8Uf4fH6 z-cNI1%yL}GbY07KXO?)fO1(w3;fm%!bqnQh=m@v;1X}z2Exnx8EPt=3ZCDRb*iOZT z?5JuPWM0N`F(v{$Y>}?v6btYy2Oe5DQiCK?We05_1vBG30~<=~Raag`}kz--Nt*mHC`zMQ0w%nS$7(kkc7#DwBhy67vZ?4^3;(&f`vZcs57t{5&} zGqcT#mQdk2=3iH1-@6ub;d1OpSNKwr(90rL%>f8ivDxK%O30lRn_FwlYoHm#*$_@< z>djBC91l`?_Oeb_MIXKgLKD;!s$EZ z4guyPRuAm0Kj%y^{**U()B*DSC%kZV{JuU>kOoc)eo05X@gV;c!ow5C<57R`crbiC z7=J7fcf^Y_iPxHBA7lOmK*-mTujUP%@W+8bu+8-=;iRMfF#qdVDE@dj;kYk&Dkxv@ zbO|!tR$x8$FAgf0E`!DjZ=A zL|8rY4E>1P7vT>}1rlgI4y3$xs7NBWaF8$|#PxQ7CCT+4NdST7#hp`&-?G#rVwXti?=~ zsgvD;3{aS!0A}Myso+_Pe&_vbFMn{sn_q~h9Yc0Ht1LRR6qE2wRyn$z!c?KO-q69jCm9! zdqb2+bb)%j7BKn|W`G2A3m1o7!F~LP;sw&du-qCxRs>lTfGdCp)qFB{5YK>K zzAPO9KZgGBgg=2BM14noFu7&87fu9TMFr{4(cJ-`2JHFq_;!3XpbO3^-9a38hK|_$ zyex;Tv?Sc%KI)*!eaPrM5Mx8&9kn`+qw7o-x|oBp#zV1Y>R^oNK$PL7X!(%7=8(z4 zi;onfPB>gI`$CYzEAi)|l3$N`<6X{1E9PiKg^Y*-pzBWd6wC z!^*ETg&bHDHM`C=Y| zF{kX-6ISyPW9-2w<4chSX$fPDFGa=Sy0Zl0|s=6 z^N7`jx&X;^juA1?xG%!sLStxD%bREqXcc|f%5{)u`0$8RN{MZeD7@(hZ9YMfdY(r> zrNAR=I;;o}(=BRb0z!}mcz6Vs!p1J&NlyUjLV+tG)j%@;Q6qC-&jjO7gir->&^7;Y zAAU-x!_PdUZiMju&Ek{WO8-awnF3u;97~4&1cAM}v*>V-xV*CchIbu8k{e zASR0WOwLEPSuy6uJtz@!CanScvDcLy+*-$Kx53Fa)q)yw8jQBV8%0aVjw%Zm?6gv+ z;Ib8kVqcZS>QXc5{_yCSp+u=kiuqaw75&j=D)POnRMdq_T%Ugbqca~|5cDb1q7GX+vii)o2jLNQwNKTBf zSq?^?IdJ-wqc-blpZ687DNZU>`Es5hT1#N3DTlw%{>)!cklNF;~(NN5Wxi@Q?**9X{rWqqsQgOg!m5d)%9H z$Ps_g=07B84~fing%1nPLp*9`JL2?H8hel@9*Cko04#`wRDlrO$S1?_rvnM_6{tSp z3xY1q@Z2DX_WkmQ4|{_e&tOth?h$uDGpc|*D0c_X9Px!jqIg4c?GAuaz6;DR77YfD z$QaQ)2VDR-2z2>Zp=fX5u+wwM?xk3&xJji2W~s7y)w1Q3p2AKOZ5K$}J-l2>#o6Eo zpo^}P1<_zc@A1lOmWG*ypHI`jN9mU5;OUpCLuX#0B2J#64xK!G@Wd-T9zJ#ErBg2- zIC&}}#t;*i5SL$`R9vl-&m8T=CQ}S&EDn%NMs(k2Rv9ED2W%_>By~ugjJZ`#Lr(?` zHzc$V0*z@!*cuYuS7~SP%mpR81=YC(@Us+R<8qqu3h8|yeFY3hekjE-<&}T_zf8UN zcU|{+=DX2O@4fee-a9}NMDGVU=b#s&5g>YRBqfrfx)fP%aV9gF%#5dG=1xm8amKNe z*p@7-S+=Y~HA{Bvdw;lp#r=HGW;}PTckQ*$21G*Ov!DIE&s%odySz)_oDirN@5&b0 zsOT8U@w0v9%(HQa3JXN-*%U#BNLGlz0MD>ALOQVXv~TMv1U7>$g|&5(&oAkX{E8GV zm$Rfq9q>vvvt)Kl7LR0eJ`SruwfL3VL@1oWB1b^7_$0Gevhe+We3Cp@Am1GnM~4?k z=R1A;8x*YNc?U6m5_a%~HHciZzKZaYc?uy%epL zLRFF{nI9-q_;X+g$CP16I|iy{++vl(((oRjEeOPke6)HLTFxOk6fwjS`e+*<(}e5ONG@=;719G$RpKk2C)Q?R#;4uPA6%#fH_~S&r_II1m&O0Sbj{V#x-(V&rKQxzCyIP|DoEPf+yyHr5T* zK+DvMZE{JZgp;fcU19*1T7V2`<9L=iZsXWAVP+;J%K}C*JZKmh6Z|}gUzZlGAd5TR zw}JkC66kT-uh8b*=4^ z#|NGXC>s6D!%OLM@Cz5Z*Pnzc72eV!Pl>{lEO5q(+zGY6ROv0|V-YTyzYNM1tm`j> zW=Wm$Ay{`P-x`Z zbN@Y#+RjUDj|ffA9aYz*t#@0~zAORkP;HSf0=a2oadkANkH@vqs4f!Lgo2u2Ko<_> zY`~DLF)+6Yb%;Ea$9e$EMIG?#BVoQuW(sa$OQ;fg&risA>LM`&Km5rR9CiLff)i8$ z)y{G0#vWpWR!sB;f%z;bnt{Qb-Voi+Ya$RB z&eeThvPQd+tZ!w*Srof*>Q)cL@Zj`K_!+}lfO&e6KwXGB;N${eCQO-G3W79ja7Faj zrDthIG7gVf$Fio8aZXJA;{^VRWghEqgUJ`!A#|-W*d>}q1ge*g3Ge!aZ{t!JiK5#d z2`wBCQ9azf$8Z*04XQyq62*M&y5tLRzvme&kHg~72cWe|W4uZiZ_-2?bg|YVf1M)K zrixtA#9P&|7GxJM11d^*zVi$!*>!#?*@0?@Nc~y-g}eiefCGe z8~;Ko?~+1IXlZgTM`KHC`&x(GZ2LQe90!F)ee&PZN3mQT?WGr{lAr|uaDa3cA9xsz~y zD3%|J0xFoY%D0+Xvx^IMkbb=&lYdtryow*-RO zJ-Z}N3xZ^X2QUWAuIZbO$yL|Xg6I()%@~Kr&BGat4)e&kWi)Lcp0EyP>`VIuw@J>{ zW~T>}<9s~CNWo5VubdK|o97~KUF4Q2QDmV5@QJ`KdvET6Z7g)LwPWjqEYjZ7D@CG` z&IFk8=tN<~>d^BL3|A3AR2gYdM4Jji^~!i#VWe3RYZVb~BGifIqDXyFw1q3mILBsX ztf4Sm3pqKlr0{ZZxKH{JVx7dZJx&+#wZNAEdLe(E@W-FyCt`}AYS!H2G+ zk6lL`KXjaaL^#hMS&u((o_*}T_#|@iWAn!Ulq!0pKqI=>QPmXg>529CM~3>sgS~-) zZeL#~M}L2px3AaN-xnAj^$iYt`UeQ#kchxwpSQ2u+tcOm>k0RE*;*P^u~>c}02+}f z+Nvs5dAYKxn$T3&sH>`rN|Va+5>0iLseM_!_|sH8+uTB=AS2`mvn zt_TEh-3x;eb9t4k`MR~P-B59rFqU7{m9!a3+w>)^hGdg2-k^=u>l2N*+#-nxRTKrw zl|i0pW$Hju6BGs}4>kB1d7N)I5rtMwkxi?x8l4Wd@K`+})6X&FBm1V)d#}wXjb^ zb$}W4f?M!RaFQQtzk2w)cVa=yUJcSFYnvM4Wx*x%k3+=hybrN8USM60!Tg z)o;En)eK7ER#?tn*_a&YOZ4|fh6h7~{lTGr|3I&Quq!mu8yXhS4UY_RQO0m!uqQYq zuIH}s)q&(_pTGNxIv&sS`;iLfvPw&1qpi8w*wUh@uh%v<8(P{-EluXuW4wx-rlTdOQ9%k%pRL&3sGEY{gwH@jMqT`0+HM@MeP zhSrm#oAHsGk-?Slz;bMOEjG9u>Rs@6PZ6#w{6ZF|i64VYPlT}ih3UqcU8mdUALbr|+d*T@__YxyPnL-t2-R33Fam(5P+dIVz z1lM=zL_$B)s)6}{7mdF4ukNwS%RG&-wjWtP_bnZg54z?zkr~WuJEvDXb2q*7Yv_&K zN5RjiXj^)YQ538>dwK>W!_1D>UE9vvwtevY3;X^DkhA^ZQ^(j=I_Mqj^$qm| zM*0ZHFfIxMpJW3ercKH^>TNpic89dhAU>bizn72lSk31se|y?S}d~>&2EO%8=;8}Pii?jFjY{}ggZyrJF4q% zq^j@El$@r+7qkA8N#9=9wKe9xIpVuD=37rWmIfRP1D2T{`(&qnwAI*KtLv)Lw->9L zqWb!HQMtb;yZ6A`^t%9m9@PWaI%ol+qZ*zG(|tbu%UDPJbCnhMADz0mda`*wILr>rZu3%5FYd+ z>B80ESrx8VM;eeELUlx12vmpQ=U^R-4JXT?Nx*womC<%%c?T4YpDY{?o84Ag7GHe6 zX6swwv!8kPe`MQ!)4ubT>)@B(;}6^r^3fy6nEzLOR$kmcP&|DQ%kIRdFJn^|$=N&6$@5U=Brh;=5U*?EXaggUOP+X`I zWaUvSIEsH+rNwD(yHYc^P<(tlxOMor-!iuW2@?!vrn1Zt`2n_BR8BrfI%Z!wgqabs zC=G}jgHCvKHz=cQyO7Xx>turT9if>;GB`t9-5RLI-=K7YJ7-Ewu#o^l78+w@(#62w z=%jf#OEJYbnB|;Ket<2wdScx%yY0GxU_N7Ym?%Cj?TR`(E()VwxxF8LdPmo2!xnZl zd0!6FVhJjKoo7?DCy^cow$8B1LsK`TiU#rjPD+T&q0xy4meZ>Z)u;niMS&WkAlL|Q zVQC?oW3BMB05(^GEh2L4txB{LC~8%_3Alx^C_xB=|0d06}*xldl8R`Yn!LgxmdL)t=7N{QT zw_m@ih(t*AiozjXaZ=`6I9cGfwUq$LurvtgV(w$Js;NQQSg&cU)3-Egn*^RYsvGJJ z_1KI_$r~a!)K^r(&&kZK^6A~g)LDEIPCgG!{PR&j`aCvq;ve0OPppQ=Z-lbDL~wj7 zl-~A@Z3Q#Cf$p>vsg|r5dgbAntL-NBNp(a8dzov+^YZ4vG=oMK%gK&h0CJCM!NqHn^9Q#@qOhzVe z*KNF%xbv?6=rzybd+vju+xFkHAN;~`@GJN6N3b+PTE?)A#861+FM+q~{I`zNubd~p zHt#)>nr5Y7r{r*%62;-po1l)q}_q>$Ucxa2SOEKO0I*9_xq3MwyBQu9sE}c6_&OMo!eF9DnXV3lVBTyaAo_xJ>zH2FA$Xi{yaH9NX|Fw&`vgfkJPmhNmPR5>{2|buDeqpKp z+k2%it%V-U2JTIVo*WC`8xK8^CL(uI(Ys^uC(|5jFGrN45eb*Wprec;{0*%h^;n#l zs9m@Lm_xhA{=L)Sffzy&(rZc&)CDB0j5P{3BbOnn0CViBCf=?9 z=ix^DI<6=}$d7u0{9STHC4*n>N`^8=HET?G{f+PNd)7SxW+8PERHcU%W=NKNxns3#vh#}c9I-H|S#ghRtZFcSz5oDDB0 zqr+U}OYkrur-yQ$h>#A93`9oy?HvgIkSux)rKR9mk9f{8Fh_NBBS#U9O`uxQSWjqL zfp?R#wWX-JiEki;wpqJ&jFla3z>N^p9?b)BB zoJc-9UHse}k$iSO_HZWr$2h zcC;#ll_&h?yg)6~t%^a^twnHnyrs}zA=%^n>(F)J9p0#0yXV~diTmJn*U2OM;fKM? z&+Yr~JC8qh9DQWp$EkbdJ^d8}2r#=DCh3%_SWPqZBDG~{H zb%i=RJ-uDzeZheNe;=Azurzu@#p-nG8Oe4c(iFJeY_*oQm8ZBfxXyemZBpVW#kEz&?qr51Was}Gb_R4uO5EUk%ki(*rpcrF8GY%XXG3?McrRp4@P z1VW@>WMrb%`Gx>9N3uV_EGL6dG`-x60Yb$Ds0PMzr8_4!=9%4gPAoYl*R7dVn(L^l z=u%nsZ&*@U{Aa`lfrQrf3NRx%C^F{ijC6w>@GRi(WtdCs@mSt+tZY-eL4L?TA>}_H zjV{V9QnjNXVzra+-1X6v4>TfO5seBFKU z8aAC!8b==iZ13qK+ukp&dmq^LKlGe@O33`|IQfj+(0lP)-{n7rF5dMVy`k#Zkiz{+ zr^g(QMLN5}*TM63cTY!X02jJnb~9jL|FB5;F25hP0( zSsp)l);82>>T4A(&4PQ|Ta>MWhxsV;GYALI`u0}zb76gbQNv^2#^O-d)#)lLg=6NR z`y%FT@2tztA{#_ZULrZj3dsaf8XRG4Dx{nvFe2l-;jx`?YAcrB4W|M2UNp1q9$3~e zIN*#(dQ-Hn@#=%wwkM|maOCNU_|ucc&&`xPHyM2}7Jq66X68!tsch`2GMbd?Jb9BXEfp)bDpxl#5d68`c)Ff3?W;x%f@m1x+RVV z_<8b%@5YLrhK-!kfRlyH=o7_3Swh=#TXw0@aPN4QkL~lUV>$>Q++jlkmbly$O)^M| zYF#=K?a-T-qP2tN>bL0qyAY}3#%Y)>PupxIJq@iL7xqs{E;^2kD6S$SJpcyGc?z`z z02Y!Xgy-A_Ze`UWGQMy#YMH=!=9qIiIJr`Y*kD2=+K}fdm(&i8Ev#!xHLc%ne)cEP z!~f3;+4M z+U{*B)JN^i7>)+7b;NsmJw4aFy&b{+UPAUdWM2-wf$i+?AN2JNV0sAOBWLS@XCge@ zYier%%s^V^XG2p1HifoLP;n8cZfOR$`54O$jpz+of#7dwTbnuZ5p@l3D{5P_~)aeZ>=C)MhhZU>5A)JZ4YKz?oGv?n@v1Fmwaxr`1z^gXD0!0^r^|v zy$l#8!uL|q2ZEfzbL0+6BNaIt4WEt_FLy}AO3_(o5Y9$E#YCIEvb(3^)=|mY9!m)b zxe`GelHliDWe}GGW;U-JMvkA7_li@(aNIZ|?4)TdCkM&2I@88Kvu2uHe%wu$)69^w zk2PPjq9w^bv0_QzaAub6<2Q2S+e_xm4O4niKQ^UHO|sz2G&)5-h0zoT^6WX|aQ%NgseTDPf_}M&}HrtHMxKexL&VOeQGT3V}Dm13Ow3Z_y-Ma*Qnu zYGHa%B`j_$h&5?rO?jRQ$>Nu+0cCw(%lc*V(7Tz+Lg`OMgVC`E>-2pfXYKzn<#rzhCo73k}f z@%&hI48zYtR|`D%^@)qQ4ADO_!lR>)i=IQRKbY(rtIN#Cr|yO`7vz1h zsoT-Hi_r9`H**%4ybO#Vpq9hq$3$fOFqRQ4En;#X1>zgIW$Rgzym84&PnWG`ps(Tn zWaEP=1ati9>G*Tgv1g|ePiKjer-f{WoFfl1kaOtC(Z~~HBJQMu7sH{`{_xpAFxx0a z3Pnwvyq-=Zh&te}N{tq89w#;q#bBveP4EP%lkDHp!{c5T%K^YM^%MfJA%yFq7)x<3 zGm3)Mj8n((wFvs(#Daq9HQVG0{7f2%U`BGVdXX|W&IZ9am49l@F}`d|-N51?kQs;# z>Vs4U;bg)(IA$9fM{MYOM{KjuKD+&~1X+4;i=Zu^u(O7DbqB->GkoR5yG9%KnF~~J z0A^7ur0R{9<`~+(O@MP4JG60Xnz||Z>5;SGZ%`jZLR0wQm$PvYC94z|C_bOGYTQh+Dwi+CbHkni{<&=neQ;Q&*E;T?6rI zTiVo3Ef^gH6pdvkr-$nLCS`2{H54?nrlFaSNN#0KjWSuxA4PeZyR5i>{114JPTh{r z+>Otkl`P&4&zynkPGg#(m*5!) zd*+1=CP!%7u+1~j&FeCO9N5F4WAQ$1NUI#F16s0+wuuD-vEiIpw5Apa&%~x>WZ9US zXZqeanq@C8VAl7i^gW~4ccy_+0$}6UITm(pbNJ7KpAqWdnHz_EkQZA((R3v_mJbj= z;F+vYKsqp_W6$ZYtfP0Oa7wZ=mK*iAT>;O& zp6de71Kk7`N1&hP4S{E2O8521%uEhQR!C($o*Kc~@b+GZ)dfF;XPX`UY$z!wA5@_( z>S~2$fxyVw8XOf3HR@)OB*NH*we>}H4a(Yj$|#B&ii7pqno3=5Rbed7ABD+j3`Q!4 zryDXi$nr$we2nPaS$O6ImiCeNWrf9okPeI=5#G^#jOY-gJq9^%1%_{$u1<;a6L=20 z+ZHG5o}Q|@pMji{&(4BpEROgy*~nAlF_`&&I&ptI_GBt@dpLp8$l*Eq#AxL1Nc24A z-S1O2Fb$fA(#Tn_ngWB4@_o(hbmZ1nU~L_#OeqaQrfQ6fi%kdJ(YJ>2C4)p5ylaQ7 zbOs~ZH>`>< zYE6@TOJT4v&tFd{!u6QaqHQBr^2X5ML~wP88e)?++5(;neYH7$w&t1aQmnRaW+S%u zx8d#oh5zi_d&jZ+D{MLpI{VJAWJo&>KSnlF_!jLPIXrt#e&ag&GWqbITqhsc#vVw~ ztfaE*oiShg74$RJZC`IUFcwJe?dBse2F!3Ztw-*@eo<%X?V?;r;ak+cheRnn*xzkx zA?d z=;*5TYDO|+vRS3F(3Q=_@&_3L69dVC%RzwW#Iq9+GI}HVAPs;K%+b5)_!B9Dk03mH zHtN{CE|s_?r&2f@8ZALKF;iG@wa{_vaUA{o3X`ZMJg zP52PWLBA+v6f10*o4lrgQ#(2 znz3$KZ%`b>*^u>yt~+JyOB;Jf&HZEaHHq1lX z`#>6IrXPtmB*2UvZ9V+Re)Ma?e~#Gr!gcx^&OMjEvmAbI&pa>1W+bDPaYavSTePd& zH_++rzb=EB<~nLCR0jWmUQi9lxej|Hq=nrfJJNlf#^yRf&V<_sKZ9ohY1%e$;V|o( z8klYn$)IdR=e#>0P4y6vlL-=hRasM|sIH_BL~=N2_;Dsn%SM-KCpMDPv~3&!W&&WB z&SBpjV`79-`|<1vnPASNJBX%_qR@4Q<33+4&)hOL4#{}Vukp8SP1Za&S@AFpEhCi) zS!@WF#$>*imXC4{C@T%hDCmvo@t|Rm5|3SSsAW8p4e1=t$at!D`3B9O1f>%ojpTr( zF`U6OT#X4v84epk#)R(~O?WjyEfzvtGI?hPs|qVF!u!o8(EU1PK8>em@W$y=qR zkpt$@`GRyMsRI?DG~ZvF@28m3M8}cnXgQ#f<2RKr{?2*) zu6OzyQv8O*449?Z-P9EC>hktn@%LSWiiOxfatxt29(N*<40?J*z}Pt*f_SDxID!ZX z^>!KRYvhqSTn?kq8_kO9S`>w`KISM|K7wtau4`(6nN@W{Y{1n3TSuLxx{@NJ zWEI1Dp7P4X$V&Cp4&6sIBl*YnAzq-HoIZ_B?&lng{TzDXXEesXtTYfC;na34y;nB2 zmY;0Hd6o=zXJ6Ts-SM(#r%IllNIXA7CK!B>4j?cdOk>tj0ix7mtkYUT!IGJo>ZPSH?_3iLmTwdI8$cTIOtF|cvhBtJ zPi+~`Km`X_v;!^g3b*+NOL0Z#hIK}4sN-mwShCOFWcrmEE3!iC1gka{aG2%yM>sOG zBC-pjr*3TAoEk$>5VX>PX9$@c1%}>?sedAn-O_i>sM>~&of-e!T44UBZ+_D~v+kPN z^eyZ%W6PQvkj%{`XQuW=A)$rEv2r4sqv-wH$lZpy&J$5CWY3KJ%0kxQ+&pqz>ymsS zxr;-7R8jRdc!Sy?qbLc;RvD;48;giE(a(<~SLm;j@tl*>wFqevLt3B-UA(!#S0$Nv zhT3pwEBnS8F25I9|E_)OP50ir;F&-$JNG`cZ3FCI*$*Ds_NjV5avgt0CBfQ9(IZht=X1^`PZb+73p)2lfYD{)@270a%;902U-s>0_;MvuE9g!@0p>x;4IUhZ} zqAU)3BR|6ZU518gfoHQ7zYaW$;$Us9>{@_l0tN=OAXyM~osib*np$mLJ^Hz*x>nIp zM_^g2Y8iE8+>9cW(N|uP9N(^(I!w%5#HP-|6Xbonv}8mk4@zfG!sFY4^d5|j4&ge5 zLNDSug$unG8QUfj-P3u&I+3;*ZIvq>SC7W9=5RCQOt9pIsqll8kjIFMJ7WYUbLf0n z!1#75bUGM58w#Ecai#KfK$VJ07OkXLKd;@@|fC8R@JzvG3);HFwYAO`e&EaRAAzEFVNbOckp2Tvkp|SbP~$&T4gQOlcJ#BdgiHSp+Y+aNOYq=c;S!d|we$34?imeDc8;IM5ZZ6D1b zl1+Unnr6+tE85PCsc%}_HEQS`H*^hH`bKg^Mqa*|>(HCKC0<;Zn}tEB3p<6@k;NT( z>WUwaJ5DrB@xGPyJ>J4hF9#817YF}4REr4SBd|o4Jtf7ez_X~6@~Bd45FYH`(1y#H zhAZ$@DuOjY8cr_qRVxFv)Vp(B4Yq|BO=G_-LUPht)KiKALT`v1NADPX)Flf>G0 z+&iy3w|?T>c?Z?u+W!!}fmtVDd_ZFOzU$yU=l;*B9ujh`&~osx_3%+*_0Ocl5>I62 z${n>ek*inWWCA3+dqk~}5LDdL5$Np;4-C>vhU&nhqlW11#n}-2EZRAGJN31d0?!op zsSlP_;v|DuIR^yN1oHUtM+9?26P^Yz<|tpsqb{tk#jGo=tSrLeG#e$8Dc;mnn%yJh zhB`cr;M55nN7T6E*&|9P1b7D3gm+j3{)TUaD&aPG4qlm%Ty%<>)DCaS>a{E98Oq#b zf3mX?eVFDv@qlg(I*ziUZgM$Fa1uBl37n3G&c|Yxqp)<-QLogZmyGbUxF1Uv^87oAg67KXT)s2UYbM~~f%zG-v+3^P{d{&A5E zihM9dFpxzc#kpm;S=gv4-$%fh6C>5|8+(`=SR9V!TqEo1apL4@Gt0qv1#_-5FmUUh z_vT&S`W?^OrCd*pPAo~uTCubN)0n0#CAYZ|el|qQ+5Mu4)GC8j92KmL3)B*Y-kKs` ztv=BVbWtF}$HRXXR(I>2r;Gap-SYp-9U1xt@z4~(G;0^!wkCSIV3+(M8}8nd9*I?bTSyHR}2*B_$H{b3LV#Mwy4fFd?6d(UpdVT(fAss=i9oSYvFc zRaH{XPxO&t)71>k-i8|Tu|%|O#rCZ2`z6&*Y@P@O1Y0t?s-Nh)7uH!Wu@~#0`_!vPd7@ zJS}sg_Ls>8UI)qGfB>_MXSv309^hiuIx?^Co78rVA*cD131o(2`ldXSNbQ^8NkN2e z?s=Cs5k)*rf*6b|hYT3gr_5(L4}N6Z{rl35e=GP|ZB&?@mhy^3$MtA`XR!OKr{hYXn?{aK;41e& zqb{7CKo@2f;u#6;=@#Ma72n|PzNYyP^imv?t2#@9ST={tg= zkOdS7vA_5N7vq<8cM z*U+=Bp_c>W-w0;^Bs}@2WlR4)H1RJ=$DftLliV7GW``wF5^rfQ?Yx@2))u*bCDwH< z($x{`>0}Oz*1I6xcir90y#~9ld#<$yx;i+I^mT{(dWn+39xM8pv1nFU_`LSAQfqUq zvA)uErN!J>YievT(A6wY2sYGd>uV{R=GY9EcG?Yl7#qk45mD%qwIP| z>BMIF)OOYKMI^f&%$yN`S>TyUO8PLK*-K>ilM{!aH#)XY#M0Zrk@e!tL3nu6-7qN` ztN9HFt7>b{GVS*l;+S<$jnldxdXk%MF$;`}B`oy=PS(^Rl3%gRs7$riOF)y}#)M`M$=&Jy&7&g&VRuT-lGU%@N`K!jt zaz#8UI>wF0LXSJq-d2*HF3rq@CwJ%tg{46<{0vu9VZo7(jBSQfx1xY~WHZ8XG}l~5 zi`~$o=X#d%lVptZr_GdLk>#y8D^phm(m1SyATB&7@#- z;AzBfrx4G@XZ?|bPEAuna-$OEe>kPmW;C~6t(u;XZk~ueE$bI@ftyTF_Gx)83yP)# zbLoh#Huq9)Il$5$eCTKM1`Flpu^KkOSZ>gD9Z!Qa&@{DR;}yo!H?5f^SwB0b=e!F` z7e zM%bW#Jg1{l6tO?b>S6f+Eu#|sa*lGzUMAU+BCHV+Ha3HWB^zyK0d`7ACa+{=n{+@d zl(x7;R}2jyDzZzRRHV&U)5IwHa(NWyLRY}FW-j-X3N!^Oqf}@p)UaU;6O48mgIIAx zeo7P?@|0##!$rNQ4WcM7XPUXL8;Ki-$UQ;CQJi24v&F*6xQAqSOID{?XF(?kyPi1m z$Y9qB>si?NmWEW#uIE(WpNzS zrYw8$RaS>uuK60;{H;U5_7Q*Ec<@Rlcx^Utbtch0pX^x(T^WyD%OpBy;@78Rozum= z^Tqv3vF`cm;kjVjpk$0m+7L3YwzI2lWBB^%Y|CZ3>3ppIEM0dxUU!*kygONUH&c5j zU2&SKIv=mOoTxlY7at5K_lL?(hAPfRTF(c|ZnYIA8Q9dwzgrwCOTgzH7^;|Cz{jAn zMw=x_rte+&bsLwtLK_3oXYiYhXU6wv3Ia&<@H5KI%1}bIAz?Di^A?G9)8tBg`&>6M zYnoXU>06fO=Nrgr-eS!5MLqL?nK_p2gJ(yY7LGZ{S@1Kj{u!HP)rM)9Zs!r!6d*i6 zvK+duAwn!xqLq4DNNDaL#Edn|oVd7~D7A2rIty+gME%%x$xRo^ct&rC;3gIScbE3H zQ^)E#9ns#UWA*5=jmV_(z0UD*CaLEByB^?QX^@8-9i z6<)bew4W8U92YbnNDaIB4F`oyM~cQHWz(^`2{pc0R6Hm-n#l+AbT))i&bSZs?8>X6NGv$EDDoYZ7Q$&VN=RKM-JX1wd9U)6`B1CTUov-De224U74gU zl{6)Jns~l8QK*mPX@ZiqR^W~7>oofhPcT8 zGBPQ*n8nOkw5TrS=A-4!By4rSCFZMK&(q@t>Ey49|BwwudYj7ZQkcAi${N+!<0?nA z$Qn}FLONGW>x`=HVYNF>DBNOE66;mjBPyht4r9}33Wd#;K5KQr+M2Ytm)NdVxVvjT z0}bB6M(=2gXQbJkYV(d?2~2bbC%Ymuy|KCe$XsuHaiDCW+tgW-=P^qrrFgKC%WG7w zSR|I6s9e0kj)K7YA&>^xa&;R#)3yPa>2?t1Hd=j_4hb+LV8dP)$a#5-_6a)c#E8oB zEnX)06Xkw$`fq*UIcO}Bkc#OK0EfjD>LT0}gCb0(j7~-Od#ascODI7Eh1B4|Q zHu-~kk56THLgwNwvqW5_t>N~Yy5v}4bTKb9C;6r%&xGVnNv>hZ(ZU zIuWia$yu4_;IR_psZn6EQ_z=#;y&Jj&{VlzEb&a?irSd3XFHr&t_5PnvB+4Uwn`d% zKG;+62!rHvPj-z;!mHPF`{#~4-8k3rCDITbPZsfC@q{Ay$U{ed;xK(o$WI(Sf1~+v z=L~(zM6T=Lu@9qDqW~qFNd&14PfT=<93~SV^Q>mkyUqr0IhR*c8C2tPcuNwA+1b*? zMIOyGo>2%!W`JbTeYAGzSUM%cLOBaNH@BP_ zpy-|v!rVJ(?Cy`=+!qZ_ldH5(qdf>(IK1}av&Bj?@myg&%a`kAA!8J7-u zT@Jv;c;ulY(!=%J&b14y7A%%a z{-ti>e<~(lBMgf_S5CcAlzB}x`G#uhP37dzil*LDOuwy~`B6dk2iDPVNTD_OxxnBs zdi~C5++7-Tl|&uMsJk@bDNEWD5o;`Di-(=Xd@S*lm%BqW zz9L1{Xfaii?L(gH&s$p`7_NL**Y;9MTM$lw+)*I>mKYRU}Zdkak-j%s^QW%U-BTqK@UHxw36 zfzg?7a1i`26ta5D=*|U=F1E*AE^fEjq*oa$O!x|-k)n94AQH+81(;G4Q@4KcHkmw^ zC*SQYpc&8UB7fvJoX0QOZev10EN(@HX}CMMzxXSHWFnF-L=@@+`C4C|+Lf{Ej zuMq9-N<*H;3?nJ^PE}jmC&TdD2@F1H(k9vW#y7{Av%qf1+oMvQ9Hdy{WFfbj*s=%ADKHJ*?K;+bUre5d}QtZKzHTc=GniOLJ#R!h7ZBB-V?Bd z%C!gpXM#}LBMMtsVGF69QKdbsazs>)xY8ceIpYMH0kwc^(7WRr21&GbsYqX_HXE;9 zYv0*vdT>;Hv>HD?4DIdsH*XQHm1XDhl52UzzIcPz{+eeO>pq)3a1V7-V?z2u{X zEGfBI-%Xj@FP<{|IZBmqo~@QdTWiVMc5-Etl@zo(SXcKFXAjIY&gFV9y=$UfjnawS z7a>==bCBMnv`y0{9Y_9^ZSUeu!~m5Jf;MI}GYuOU5mqYQqUZSrsHOt0PcP8FL8mAs zLMR$M8wN52tw)eE!oxZ|4vcBt7kKU+#nS-BqBz*urN45O+l27qKToa#Z17CG9Zv!9 z%;r+ruag~VhRq4U3|)h2{Bs|k3_4`xfVMhHoVgwBm+sXI|LVDIc8^8{foFwAY+Dr+ zWS8PCp&nix{wJ2P?T{x4Ge37LPic9%Pv@DxYEYEE*5;AB@x(peIA6o(wiuq_^R#KHjE zSu6q!ix3oDVo$`_club>dn-%2r%WAxr)&S7?%F&0j(0WJey+Omj{3?k2~F3R%8t*C zy&vei-#1==)71Hvw&N2Ko$o5H{LFggze#~tgrlgpLcc~|nDIuXJE`R@Laq{pJ*ITT zb)E#FadDE=drQGNsOG45CA5y1)*dx*;*91SJUn+`?BM)#+r>%pPharAde8Ri%Y@_W zFWFyx(f-Qwgzd#=3G++O>z;jRc;TV$xd(=acXbbL8=tx)%5I-Z^kcI)QE$?>kCo5u z`%nL)ZRgL_M}J$i_t&c3|53E{UzIE0RjvMe?ef1anE7M%+$*}puj{6tS5G{nnRro^ zd0shoR~k4qcCSeBE`A@tUqTuzHggw2);I?T*jBn#YQ{YA?W7Dw*30lUr z%e}>TMn9Cr=r9bk3s~ zBVh@W1B#Njyda&E*_*g_vK9iy_!~$g0{adL4WtPi50K3NnrM7ozjWNZ@ZG$y%(HR#n?X*+KD$*>DP+Jexgjju1voHo{Pp_S7+Z; zO}wR^d|MiSQ$72>Veu`^>`&cO|63|~k-DCww(^c4M=0uy1#Mv;RO~5^L(vemvn1#$ z4S{NRS=3hwX~)FH;uy3{fPZ%~0_@Qnh-apU6v5hx-Wf~B8^$ZIX|Md!c>P1o)ej+L z_0>;w*FU%R{odI18`YIZgznmBhU;Hgdw*;0{>s$zxwhkDcjr%}z`qtgxy}xr^&U1Y zm#DpEYHx+oT?VQNjVmbv+`5xGcbUdnqI6YieYHAI3GkM$0PF&TkKYm*ZgP9&`ZITv zfBvfH8xJkt{3GkPUh#hCkDT9p!S|gPJl}rK{q?7vUwg{_>I=57J@0t+8RyrZb-a9^ z@PF-r@0I&)&s<0yb*NLwN+)7LjvzW!H|kq6qPvd(*32H?cFRon5m|t(&r|CYEWW#n3B3 z-#&X|cr&JDbe0Bw&NT?*9Fk?pf$E@`LeT_f7STOu?jJSx4x4(0EKI3%kC;09z%%n% zUX*iog*yewk(1CuqKkIu*-f;Eht@l}Qn@G+L%cgQGe0w^2F%d4y!|G&e-_w0AWfi2 ziR*NpP+yY*A-P{vj8gLZaVHWTBkqasm`A>*NPS;5{sZu=9RG+my>2Fx13 zoP9$x@iRr{XGQ5Zin2dNOM9mNUaI;wjsz|=hK3^)X1>Io2!T>4+L1`2E?lMLcM)eX zpcNuSmLi<+J;2*n7DJyPqzyqo`5+Ry$X}7TI_kdq?*d)_$#m^~SuD8u6=5`{<*p9W5Uz$6pH}QzB0Y90w!16BKdkR`5k*&;(Hq{Pu+2T^EubIo_Bob z72CI8wtVY((>I>Ae)Cz=s}Idzf1a>^<0aeI1!KFu{*vjXCkXdTPq<#Z8{WGm)m6Z& zT1Oy$cX4zmAje=CNo8!oHZ>#9;tVm<(tDd|*R*87^fP0Yg;;br1pR z(FN!D68&<7b!d{X3{J>JZ8|h4orvtOZ&=qeXzCwgTb-$g9;6`w=B{DGwLWY2Fv{6I zvq4xHq@B2FNz=%Yb2k2eN3v15g_RTM{5}Dg1wXIub6ptGGzaqT+70onVIG11H3Ug8 zm6E79XfQXZ59aik)t6}NcBKEzHuf)#Q-7x#`)ft&hee}5C>Z`nb^52O@i#=I-%^YT z;Q^}Q=lsmuimCVV(r-CuekwKoJBdfL)~PU=U6H6Q5`=Y~@er)*OcvYY31kLHmi05V zEJGSpdy)}vF+?5ll#xXyOksaMi}kdI0#}lJuxb9sfv&%>^?ZqJhKKcNjLy#u*FV!- z`ApsZsqV_hsA$9WFO8jFsoOu|x@Y(+nA~yohm!A4;pYO2S7~#@&qjYaTA~Qh`m1za z0cowLLIB%Yrgeesa-F+EkhZ&2=}2-k1*>)5a+J1Y5O_BGgNft)=4T%G|MXSQcmBu> znEzNDjo*CH`08`!Z@gdy$=?(rBp0t3UwXm#{6q7L&$wTHXnpnx|IM3HaWU*+@dZma zo@qS(y8h0Wgy!!5TX^>Sf}_t==U*A_{#JAGYt{Kjz*~9x%cA4=)F;0rjHe%|_TJMU zy_di7nzCb4xH_^=lAB2}HMG=D&0!;pZ7{h_SvkQhmKB6~1vZ}Z$_bDbdV?axqR6ep z;NFa&K1$y9c~%vP_4~4WhS)$edlvT%=~c$JMI|M>0G`1%kmhBt=FtV;+<|j)o40bC zM&>PpQv`2h6WAU|G54zN9};@D$&nGg zb_fs4B&tKKDSdLjj`9YlkoG;kkBwQ`dKyg zwqo|J{K=o1vad<4|CudGlEw|5?ZFV)pEDjobqK7+V~$wV5eo`z$0LZ4#~PyyDI#Px z{0x`{+Dj9bXi%7SYusq`jfBOzx}f5+b=6 zUv%~x#rf~@kG}%aMJHbr9e-SS^pWcLeZ}D~)CWJ;pS({f_uet>{!p>{S5nP{A?CP?}lI&iMp_BnfYju0}8`A$6$}UAQnW!24E)Pk~J#Y)jS~> z5@xnd+{6k-*@~c92#Gtj;>FFw#7ObB&>20}T>1vVQZHs;%|o-6;W_wO5cR->ZE(^$ zn6?by&J6)v^s-djh8xe0ckql0M3<(otk#qInq%lC z{lx!PjQ*uE^nFX-jY}KH36#dM9}HmzI~^ zzpQ)yf$LwqYW>zrrf~JW4u7LM`&}+RFF5>I+IlB{ z|CgHMUnviMq1gLr;m&J@y*Kifzc0mlBukw{-?K`1-5Q%SI-04RS&XomlU?)rF#`d8p%RpL>s9dl>mu`q+lip&FmAFQpvkyM48UMa2^|$zS1QMFiWnWj1|G04Y zhnn=Pa@`whB-pi?nD@b zgJ+=bEh+YaXT&o$NIc{(1K}iz#kNQoy#bz;&S;{s)7SlOAJPYysov)j}g@h(6d>L{U{QR{S zG%r14eEAvuiw||rKWlmAW$P=?>7KjqeBnvcQ|Icwe#svok4w}wSKR%}#OZ%g-}z0! z>1Rb3zs*1WQhok=?dAWYx%i#-^7pEOCFF&%6Jw!y~q76M#)3F#rpdz0Ljn~(rD-240U_u1ztdDpwvUbBuy z0!h|$_IbX~e)ir{Q={0uP9QD5$}LP85{AhugcHY_!8dq#c-SX!T32P*0T|V zC0ydQFC5FFa9es|lj6Clc ze;J8`a8AGBm=ZjLYLPf5-*L?S1X0>N^^SGsJ;(Ih%FruHxI)p2%`Uem5)G%*k-R+g zHv;rV3k!fWVPt9fu&9s^6O>nq@*&m960n_1(@-#-OO=O`C2L0t8+!^zUXHat>2Cd* zz2Rd=%dg?jBw@0#z2!45w2nVGTYkrd;91Yo;Mv*sdtcoNC2|voQkkEBT!%um01HNXm^%Cn#zml&o*aSZ9~bS@0MP_pM)H^8$93P zzU^jUY(Uy`+hNbGH@I)U-hJb>zFQCZZ#_VAMzteCHy*No`%0ybnRN+7wuYXOqAQ=v z+xxWbia%N||5wxAKM~;BdfA`UEB@rT{128rza&f-ePG@5vF)M{O&7dtz32_~(sx3; zUQ>qdReZ&YBL~@8_Wr1Drqvb9uPa&D1WDElf|LdK>0rLxm=)t&Bcl$10o{3=0YNVW zgG|VH&)_^0khbFD!0=22S5isYz%kG}y@~2JO|QszT+p&j_(m4Mv!!nw|8sPjnMe!4 z;f27^Y6u3<#k4Pw*3W~OGz{5UYAAR_ISID+2$&|jDVkOV^v2L;28CV7a|a5o+p8|kT6>YHdrB&; zZkc|D3a!}u?nv6-c42Dp3ditC*Vt3`v6pS5FIiT+YD0+D@oXJ`-8KQ9|AlbOegKh1 z8@ED$dU; zDM*zR`LmKn>6z`Eg-yMw?nmMs4?>>39lwyHU)!&ptq63#M(9vmey)P;w%?JW4bg*i z?dtr@*7A#B(-TVM5PHiJEsnn7j3m*S?O~Cf!LyN>$-qc+?sz%ahHQ|N!L|1M*&f>BmSt%np(o~ci&2K)^5Mad*}BEQndEH>$O`Bd%t%hVjXGO zd&?ou%?H)P`yGeAle*y==jA(2IQM)4bGBaiW6Q4B<2z3)ZPzMlTJUV+??u0iudt!1aP@|Q zRqG9J1{xh{nfwg#;2BLGV-Nwr1`m?N^l^&<9tiW?He5hb$Uya7y@?t(fmxKAAU%WF zMCleZdIs|-qfdz^AGVCX!E0#6T0W#DQ0tum#(>$#%qY*)P#7KK>K!tev#)2Ewn16e z+|}#r=+j!e-9xMWE7mhymk3O4imlv%a0jZ5pNAhzudoQ0HdqjBUmhq6Y(Hnx^B5%qn?7waqB_H;p^-O8aEyE-*Ub0=0jX)hYvar?2jGVZ`!?6Nv0Kll$BUb z^Bc3j{eEoUTk2JRwC??#W$&+@SN-0y2PFT>ddX*&J-^|Cu?)Ti9tR zy_^A&5eRxuD5>ZdQhk=^{?vNTeTH{V9bTz10SQ;q%5CwL7r93^IJ;-H{#7(?6CyYh zU1Q!p;4K9~&V!;nL!m{c8wAfrehzf>2RjG2BZ6aVAR7czcB3;}IS=Y|8as#7*$Fg5 zehgF&SiJ}@t8hn)Y6qtx=#Yg(EOI3(<<-5*kG zrt?O2c}MRf7W4DiE1AQBYU_$uEu*gy;Mq3yhJE%Og8WR;P#b^TIdW7fomD)|)M1gJ z!7bbvNc*yryo#n#kV_KgeZY*?AyQsRf#`Kbz*r~;M@3%wV*Ya^XyyoI*R&@3PX#-U zIhsFETR#G*f?>VJt#NR9iKp0;0Ut-n;8-qTt?^w%9#A_oorY~UI6 zqSxt=E&$AyV1ZFFL3W00s38gPEcrPsG6>2urIt*Z)@}HL{B=Vk#Wx+yJ#dZh)&qgt z4k11}Zrty_`JnfEhrzS!=IdNH>?g>~P-yp|>pX`K`ffbvIecB>x@(lp>%`8=Jcp91 z%C*~)-+C=}#mnkdf3RKtJKMg`>{tBOcG)ip>!m-lT=G-fWj{CV{)zLlUs*1e!=P>V zPqa&ZWZ(5-XyG2EbgSZsDK=3y(0`OvR>|N{?)t518DSwlH0pr-eG?lmBW3Xpva_LU z(aJ$`o9X1Coj8D%_i!QPRkb=)>YqUa>|>gt`|rIx!z%E6U_r@r4e} z;n+uT_VhFI2)hxzfh!!HLt58JpnoFRKgNj<7^7yuqN${SXUKD~yWiK*<7w&Cnmb(m ztNo)JqSM<`D=&=C?(&aq4o+<)xQR&4bPb4`bY^30rR)WudKi(_T00r(&tQK#Xyn`{ zzuG03Poz+|j`BBNZh0qbev(3s!d9uM={$S-XO(6aEthc2MN9r zDUgF9KgGNOyrsy}`U__>Is6w{W50E`z8|P3KOYc0V>;DhYADB>;KYY{BhM9= z6b+aDM+H!dDXwstBLL0F*C|JdEm#crIS(2(Z2GO5#wYR)Uz>aAyB^eLy>!9_DVlT* zq}3a*bKbb0_YvqE2fnQyJVXFy^ylpT*C=aN$^VBj1ywDzTX)yq`C)9|Y1h^N3X&+<&saiHt+e=e#x(Fdwz*tXW8|>df|&iX!2$yHK&swT!KzKtNiVj zPE4>vEoajOx}8!Q{0T%Y1Ia+z=&OnvjsbYYpUI}G)r%)VDGPEmo08%k z!xh658z9NjDmZ4C=yVq-MZmFncm+c?Xl{jR7#&qK26_i(j5?sVYt+>?=tQ0C9`SY# zsx3X<_FjKyKV-wx*26qfk^6M^;vXSbuSJ3u;f|YYMpm>CMwVW5M6YD*%&z#FJ>WST z7stW{iM5vy@DLnI{F=147+sKAn=Z#Ss@2pgVQgJa(Knp-43|^MZ_4dk@Qgj^96Vwk zMumQnk_yS0+6u3xkr!YcaB1uKYjQ9|@fdlXYKv#;th(YUt?^>T*U!H;C2wdj9#MZz zij)gn$b8gu0qjYk|4WYYk@!ck}2EjY-TMm$`HA&9b zsfWMoI&>Z3y?(!T@H@HJT&0YU2%cR&t!u1d*A>ZYUJ2|yYyZ}7tylhrv~1t|D==)| z`wI#vlu?{}e{S9L6Z=Ja(s1 zQ{%w7v06spj;;!hkxtq2vobP1gUiV9IYTNq21-I6V9v%ARIrIRB zLG#e_nIo?e>h$ZF?v%mjGI$eSJ^3TY)W4v6SjOL^{Oy{3*EISgf7`bd-x$?KvlhVQ z9L&k_=ZPhQJSz%1g%&DVox&&>xM`}eyJ9MBGa+kN2b^p$&+t~N=|T7ZmH zd+~Sbj{GL}?N{tq{Kk6uuS|P>X1VkiK-#(QH+pjZnPvA!wo5*7T>7zX&xf{M@7XVW z-?RHI>$aDd)U8#b9ZRf16a3ks+JoWT;qKDuk*qCv&vtSkf@UPQTtOv;6b-6*5R2zw z<3-s_kDe~l!ja#o!;mj zrwX}#al*{>#^}r@8J)xvgwdwDgH%MAxviAo3FtJtglI_Nmt{91mMVVP`1;HAkmUlg z?q1pI3m?-ZAfz@WlAqr;93D9w96DqlKWiC1Z5nw#W9Zq8(HCq}uLU-Lq^x)$lcYWV zGAUZ5kI7f86E8bwo;8g<8R*!n1P9sbNCzVBeeyG8Lwp)g<$@d>{ser38VX?M0)!Lb znXlnPuuavQvbZzCC=Z)~XY#YJ`F=<1Tkg(xU2PxR8sD?ke*|K+woe_6AKF_!wKe}l zZU4E}^(!XRyQ_DOZC< z1bDUvicJ2zOkY}YB5rtCZP~nSW8N*_NnL-X=ho{9k~3kb&90jcsW%=3$%u9C!~4;k zUDth^%0E8yYFjVi>FRg$;ovII z$eIXM^$B^6&;H{Mnqiya1`r;ZTAZFlgSj}db^Vz;kqZhd((R~M=i$s`W}ZYy>js{4 znAX02ch1w};M?)B>a( z+Al{xd-J^34B{I`%P-h;-y5GgfLS~F_<&wKI98< zD;iy}+~SiIO*q2ka>21N%7HP@otbkV)+3}0e4*$V zo*NE%Zrbm?`C8|7-*#Mkwd>%u>Vf^9Yp?WPcUAswI@GG+U^q7t>#kaM$t{k(pP6_6 z!hZSh2=gUBx9XGwU{m9^U&6__1ln>#0j$Hm!U}$!e9RvrH#WZ2oUJ za+j}NRl0J9LCu6%+%eRxyM!70C|U^4hBw1Mzl#9U7&eeK$Zv=SZ6s=5y(6oL5cTeHF@#W0F`OZ2+5}*ZOUH^VHw4d8PgyNx zAfrPzYx8cZEhJ&EErUeXvNZW((bXw^N}n$p&IRe|Ii&>O7pv_2k zBvWpp1tp1|L!q|s+MAC$TaSC&UUD@(XRmq1-S}g7>)XzzH`V61cqO#9cf6e+yCBc4 zuc%EgdMj^L0=va};fkVfke_wael8_KF=k+Lj&nT3O;=zG!Y;6L$os&UPnrF>oCLA- zQ;UJINK}?oZ(kp~~wz~sadFk!flw5q!x%Vg5Js%o%69f%Tf5sWmw)&NEpullzKYtBZhC^)7`6e^|)Kx{9WB}47Ifb{>+h3Ymq>{7QJqKeQ>P`ZM5E6RUm`U!Xq!FE6MP9E!55*iFq&B$S&A#A2W`ta z%uy7pj9CmJv?XHXFnhgvXjVTxr!I@nWAV`^8&bpAgrcmvu=>J`8pDn0NhDm+s5{0r ziiAg=7fy}7l5oX_(DL=6n(M-~2f{V?MC*=3>!0*2JL*|}BHHjwtm%bd?b%@MbK&|I zf_miizUr@kD!b)Y#k)~aG@Ct2UzIzWqs0pypP%>R+Ma%g|v&DSOl zT;;#^+R(v+ksA(&u0Q0t?pmVow(mx-y(GDEMoA&ExpK-Xn!j^f#bpQ62Y;#UdBeK< zQ^K?F6ZO&$eEU9iT>PH<()XRa-*N8d^?mOp@4GH~JG}R8+t%l^E_hbyxm9sxEA~W& z%^`T!yv0o|*>md))@)5|+DRCkIkEZ5=mu%xhHp?$LC`R~mqJ8Wi|2>nghiH)Q*@i# zLOw)Tj?b=7Fy;#b=fpbLEQxy2`K;?3Mu(s=f8hTTjA5}MiExKWgZg0aU~q60Jd>rN z9E7vA#oyZlnBDDN90uJjU0yPFV~0^CXY^=jbRI7>5t)MCtVR!v&7k9L_i*GVg!)xrhEcW96N3`~`wl~pY?xr#DebtbJL)7xzg z_M3wfroeb+a8e>XClOj{3a>In*H{zl?b+*=MCO(RyA`!b^g3r44Vh_6_F&Q$NSJ)7 z3{QeaY>c4vMH6O!R;D+}D~(r1`;{e_vPW{9;T+t>(hqCXwAzZ2@!`BZ+tRzY#xLI+ zz3kHH<(GvoyTpI#?#LB;!&hGwyy}X;x2__*S6}7%)|Kw7uT-zv7yH(3%eDniZ;z7T z#O=;oR=xbP+Y5IdcIJG*)RUF9&g$&e$#Quo0f}^n)TT6s%`r#t_z;G zY&soYbGOoPi6jksOv-}rpHQf@t1D;a+T2y^WatWQ+N^0n)6mcRMh4Rp7is_rSyq-v ze%5P(#<`Cw1{Y*SfW&0Q&^Xp3F*!?HA9~&RI`j?FrWp98-IWwQZOp=@_XNJdw2i>< zJWf$mJKc#S27Y{Wlu-aP#KSAexzp9w37$#L;2Hhd+uDW17nWfiD?>CA4$q^X0A}fY z86!pWq}a^!f-V>!4IPpb>-1IvFf%C{zQmC*g+|ASuvHh*){Sr%T`dd2$=+ypr0bkD z8!{N53!Y&b{{S-uYqQg7gw^G;s4CY`5ib6paM|r1)u!4l4iIbqXDqQ>OsYM@<1#a{ zChV1n=n>SE097s5{|(KqcpQqysRxEty`x!^xdA*B@web|l{6K|{+P?k4egOV5JwYVs_x`W2HW(;k%1O6WJE z@maAN%CL8NpLZz6xivEz4KNfji=(huDJfIR%N3TmEnBKoRw&g~N^Ol&U#CaSlBW91 zmPTtwtGBn+*

Y6|f8%ku6qO7VFuR?B5!ny4gQ`fToGy_#J`q?-Rkvd&ATB$L1c0 z%-k0oKN6n2FFO4|Z05oAx`(q?-=8~iP)W~<@@#Q0F*!|EwUL5DuJK^h}3d4l^rV%uNF~J4n%7r|44p2tn=%==I zYptE0wl2yj5{+%Xmd^0tcx+?}OI~!0iH@S2@U7+S37wu;w^%D=&Cv9^e`tx~j;1V5 z$O!Z`a;nvB(mNNI%(7-qcXay}s2g6&wz$mR0h!OnNzlq17#H(bGwpVp+ill0)#D~? zn(FYn)qsrAAS`Z|e9Grj{Y*x3*xfb)RI47B>eoOxiC23dsdI#D zErC9>zt`j&BFurI3~&DucQ=vY?IkjO1H8k9$=`4Cw=3=@#Z{`il44S*+(mBYjB;mxJtbMg%i{f|YEfMAnc?ADC>AbR z=Py_tsklweKcME_?o8ii&$-o+`#m*%vm@t5TlPW1ocu0fN`Bj%y2e}hEpz;0J2N`e zcJi|?m7Q99NyC-5EWi1QtZ&^Dz5JNA>t5%MI|=)y8?74-Th<+1vg*6a%oWP?K4oGL zkvV;#GQPv!Gp`ghN``01j5k}(k2#G?f=ic#t1_cCOM+!epj7cPyo=qqITAh=$YyiO zSfa+HuK`s}i%2MTi;c&htT-{w-SR2}J$SOKmaQ1cS+g-QzlM`OgG1rW1Wq#}(6UI*QtZ~*CVzd&W_qI&WeX02 zQbw8E09oZkhG<40{GthylX)jRzCJp+F*LTpJGekq1udE!?jDrxDrj?v{XRXTY(%SeV!8Ei+asEg2zE{ zVk2!Y>d-p42R|4k6;YuXtIN}5j$U2yW=ow#H%s#y89^%z!<4|YpH_v9tW(*JaxNKer7bItZEqJ!kcPx00 zE-&-6rM>NWuHIt8*;6FZUt;YpAnd(GRz1{_W%j``_fR?SXamcBl2jn9Eh&k_v1fQ~(+_xn6E>rIHggv!haZr`h zk|j$U9(ca?-e*G3eda&=EA83;@;vuv?~8wNKlfj*Xa3}V_TN0u{D`}=S(%lgg(IbXd3BTFx;_4?3*F1FQkP!gTDH$wzSmK{o3NMc zA{?bV%>`Snggu7sLNwmZ8Dx1BUD;oCZ__ZvrE2*gow>zOZB2Gt0RU>X^ z)Xj!Ed(>r%sE)8^4X75M%@%N2{q{`FEHGvRtWy;=)r!X^lEdDgxtaV;+p^YdV7fl8 z45NC&Qf!DNe3Bq7`{v2Xx=c5_BR0P?F~3dJ16}D2%`OCIR+FDe&JYY(t5}f{H-={b z8x)uDkbVcI;kxi-&)}@Pe_HDqhbn}I#yR?NHbmUOP)98KLh^Jf= zm2N3^w{()9{X=sQZ%iOCXY>t(J2JC|^;FN&vAK)9V_Tp-BD~CPqjbn7Wr8~qb_AY5 zIM|M{@ooMB7&X5gj5;CXp15;qD7%pMb_V{Ni%Xfqsbp9!tQpl$WO(wenj1)yhuvN` zP4*yJ^JxyZTf(~-q;XQT7V@}5E>}>6emK0G=5Xga7{0_*PghIY+fiui$R!-zg|5C5 z@GMB~E;M)MJNinr;bq$BGUs5aqp#T3Q|KL9stuI6t5QnT1Tm%t5mhhl&$C~E<8)0Fy-DKEZVEsXJM^*6}4l} zyfygLkBZ;>D)Pb~JTIT~zxIt0`EP%fc=gZ4Z=a7o_iy1Bza}CteUW(WeELUU#h&}~ z##eu?^e&J^5oB`fr^-6l)XtoWH{Bj;e8yjQ#$R{VSNn9R{waUWNq5B~zMA7&%`s2y z@o?jl-s;Ev)ejKMNA9o}?35mJhaW|qwuMx6Jf|*|s*4lJ+C;oM7O#j9(TZqfc_dI4 z3YLdMOJo0xNLkolh@qEhnaFf@4li&pPb^t5I<|ano*r1}A_MAK=tGtk!C6c@(uV@D z*@?Ee7H!qe*s5K@nQf8T9pRbnOk9MT24?1cQ?ul1nX^G3_ZaSd3ALY9K6BEnJv!&= zVU*$&9wdUZo8Y+*lQZ2Y9}OCmgBmyCX&rDk_qm$7J*|D9nsB#t zI2&6L>!eFdSM3ZwgSX#1DjR0?C9@lFlk#IwTfx*3q$hWFJ3l!X7H`S)y2Q%O2-L~> zt)M;3)Vqb9|EwEgAViU7wUBRqt-Gp@Nrqrp@~VTxXyzK8ED71;atU8{8mKn-hENL_ zh+C&3K2;02K{ZGwfHVSyh!tLMprF9tQKYrxS=-aj?n06?cvc5W2?N#SWUhG=82d)b zwZRh4Xt}+wz*m>6gk@7Ctx{U?4sYpBOX0mlX5K@V!bh!zPgn{bw-=u@=RamGc-)+K zJTv#GCI2zrH02$)U6qIOk&+oo{q zabLs3fyT!r>YoPHfriterl-TrPluY$gj${sG@TAKJm{}~K&yF_2-hE0vUeK_wkr|L zSzerMND=YYoLEbCxG_6Wmkia$!*vNF+K`GiWCv>!!RqXAZEmt0Huqsox8uxf}C-k8<7Qp61~pu+&= zd3(-!no?(F5H1ZVx-PevpGRb5s8Kh88=zwVY?5{uOaCASQ7S2ue(EU<4(%PqlKu1##nHi~BM{x1hEOxD-=4;N1AP`BE$X@3FZZ%bj(KIx?MgVF;b57a znInuLppl;!A?hY6IKVR@G(&SaH5C%#f|<*7C5mGK3s6yAbKTJo+fMyF z`0C%Z=l=@;|1;FHpSz#^yYKn)5-*+izx=iLrLVLXz6ihimFKy?)E#+Gsox?$Lok-r zu&to|qIl<7Pu*jI`sacT&xh)tjx;{QYq;So85?*9>z)iZoDS5UB4g9=NUqLmzFP@j z0-l-N<;xA_Ru&}clkvJltSOObNrf9zp@w9%J`rn3hU??e#$>!HJJy&5m_s!=q1r4U z9jlFd%Y6zI&S~aQLoo#woi1NWC52!VOl3YxXIC$?7C8XQ8L(rBR&EG}+SGwkM=?chY9l!tc=im=YXftOtYc_S$PDlv zTT7RssCFw*S2i!Ih~sN@rA2fP=m+$kMM4~b69|tY&TNUVxbs`QX_|B7KbHY|B4x%{yjFKWZx^KcC1N`|Uaf$DguHW{goISZNk$k|Zxj66NP{``ifywwX?vvbBK9rR}$bmV6Q z4Wq`5D2E`Rmmy>Vt#q5tZHX}*m)+Soj&!d+3#vlXGGY-t17kt*@T_ZShVvjvl2ptH z0wX6wckzO{y2jPc74TI-olhHUEG%QpvE~=r_;KHV;!{>59FC&1SIRabYgxhMHcWZz@FQJ zB8}~YlOWn1Pa;Bxvag^us91Y&{TbR~*+AX${tvX4l1z2t8=?W=j#Tm6i``V4hR z!0fF$1(-dRCk-TrYEA^JpNKR*?yY(_Q2uSjv)-st#>$iF+Jbl^*;v3#iY6fg=}=8H zP!$eT#zNHz1KZKMoN!H6uqsZ3D`M6hwvUmYMFJHf7f%-U^kpw>NKr{yOI~6p6q|Hp zbs%^aGXp~xS1~x0)l{4WFAzi8f+!n6+R&V(xoK*H3?yG1tRV}yeWR-lBqwP1rass& z$H3swysv*IIJidZp3^#+*)^$lj!KHwJGhw=!|6{<`$YE$P27fO1H%R$Q4%uYLUV5G z=9K`|j)pehz`O(pOxjzRrTA|ocbWSBjaF`XVE2!^N9AC9Fe_~!KTq+8Z%>kG(a%5V~X1mo&{e9iw~?QVtR4BbfpSY~CYV9s#q zg2xC;`gmscqvpJ$geAIFvCVKET;A5*{KTgX$3K?j{QRF?FPu}K|4MuQYtIYcc%T2q zb@nUw(_eX>IS;A>FMbnv>3_WB>gT?(p7=}Ziiefr2^5lWUQtf_{;byT1e>1r)SmLz zK1+n^Plp>w&Zj+Xj-*zt&04(< zzZrOz!k^6K+(lUd<(V)hlN+UN#%D?IlI|`>%`gOw)XFW{Yc~X^W~syhY#4G#R#u4$ z4Qq9SD?^v-pAPg+`g^8=eKTZcclQeVs<^!Lx_ z+txv-4Xwz|@C{CaBxh@Fv%6=SAmKwfIA9`lB<3#kjc(EgSunJgnI6nvGPFDJEX`jm zI-Ft=z#4Kg$_y1uBs+ec!0ZJfd{+A8b6_l4di4eR+3+IpoIAZnsc4k)oXZKA6_bhJ zKy7tcfv!OVa%F2**i-u zUC0`U7!c_)XAkn7;9M@yJ$j4PzCyAzV77IoeGLUl5|P$LBcVTkZJ=PCE$@DF&XLUA zN5E>PK$=8-+*%|YgD|Hbu@xL6OG7_AWyknRYn%uDB>5RUw?Fv{@J!YXzVJ8KvmE`- zY0rY>^MPl-^ql!zJ^ht-_G|C6U;Cf`9}b2b53^o5?|kfE!@KWR3P;fs5(UM19fz`8 zu0_!BRG-$W&Jch(Q2QiIgZ%7Tb`0|DsY2yA8mxWXS9Q$2{6VeaA!p87MIBT!>~4Q7 zt2!sUCO6Ws23m(aLG#30?#NevRl5fc{J zwGCl5lA$4AEY<->$&sZ9|FpXU+ z!883|j7^}hV(@3D*3v#HnEs3Ot?J_?J8 z9P5Bb>mV(IZL8A`yKqC9{T@l+8hyE7OHG?j!}%IqCQ z&aM)B7XU5+!v>7)T__&Kyb_!ifwUX-qnCFI{7v~vmTacRnB+;X^yRO%=6&CizRR5d zFnXPlpM`jkrFG_P&pS#8Mu z>Qt&WJK2nO5lfJV>tkeTP#vjH25VyQ4bn0gj-lYyB$9P0UIR;m?p(HMETL~m$Ftqe zG^F;9((#GJ!sghjjYe8F*rPG;h{=is`58Rx?Nlr)q47k@5M0o&O|adSjAzW%H{A6U zP;?vTJZ=pVCej?_S(Lhwc}K4-t0E|86T#jU(ZQ*3|AZX+XhLZpqH&wx0EnjHZtn5X zIcQW*+IwLaWM;zEh#9Gmg}f}wqa|GM+|PDG4ucYuY|GSd&oB7EVAHD^thKM6b z=NsUeRBUtD9V#SQIEJA@+g*?l7dY47M3;6MU?zbRsCyzVkxoKEZ%tveWf@>ryGtFN z5(cWBJ*5V=U46V+sCE~-A=16P3AT%U&3Q^1(a&NJ_*~gD!J;+R^aDg@&I9K3LqM8P zvL67?)`H^%Nn0-Rjx9+&Xv%$1z9zOwanHdws@i+%kABj4{L`Etor}Ntx%=t!))Sv= zPoDEUbzVDt-gD+_@6%svr_VW`JnuMl&T;B%qVSdT{>T2+G=GJX+sTPCTCz01^Uiqv z4UtB2@+n{pust;=aq)p_@a(I5(p!7VQ*|8WIZ*QiL^@RWuzT4LZHW=ZT2Co3l$#r? zP9{Zy6ZHD4BD|8Bfi&+R*@gJ9CKjm)$LgZw=db`f9$FrDq?qBa=V$nv-hH1Q8ZMif zPH#d|meEG=MrsP|&=CU3RJt|0SV_qrnsLgKiX|- zI_3|EfHsQN8AQn-FY>2Q0$r(Nz9RGJC~!lY0~7>1hJD@RYAe02!>|sKGW603c$U^G z49^TDXzB8`^=i#s_SzO|f^JmkmR_~7$zE44@->+mL7Ufs+0gJx|KLg(HQ!Wp>Crj5 zVEDe2!jV}}@R-iQk4@vY%+u2+b>#25FtB<7RQu+{g+e4(Zc8y=lukpL#djfm19IXT zoRf_zZkOR2WfUuCI&dq32J{&qBW~zbLaZ8#>_R^Yx;%Ex=M)KAXWFn1Xs^i$o^1}F z-&tQ(2}j`(bME(*;A+J=0UE2i`>P)Quy!)xIfVb=9m)=w7d{3TFo&FF1(a)3>JC$@B z|A*w#%AA(l<8?Q|G5j^BKraEXy;Y>;C$#Dl@@Dl(t@4<=;;5(MQE%nZNcCag(rYt9 zZHkTU#&-6bBx;icphe0M!dx8z&xF4^{Lc$H7*>TtmEmwz1hNra7Boj`ugJ`B=|us( zBOrgp1OZ$Hu{zTL&vE?>sLNK{d~>`n&HgNSrKpX(j8B8%ForaTpuxPO;Dofe!kOtk zVJQ`*I!TPf^LXAOD;7Yqp+BJ7k*KjcQwr1#8)Gz~i1nyzL|}{!sbdfT6VB#dsRnio zVBJS{CQAcgV63&YxtdxWHTACgCatyE(NM>?5NDln9)v&ZYVqy=a^89r-iRjTQ(Slw;Z{(|)<$Y{KDlnsRFC|MdXS452D4Bt?^ ztdp?dxiul#=}bO7IYmGeIV%~th*#aiz~N}8XJ$Pb?BdK@{Fbx0h}Xqdtq)Dl#aAwn zs4+H65*}NN#fZ$zf>+FlIU7ep!{m%r1LGX_IgFqP&I~1>s4e!n z&OUrc60J0$h{+id19kzDeQo`cmRs9M%dYwsPgA?Ap`HlzV`rK+bZqVvv7U}E;0%G= zKr{GZ^q3E`;&6Da#OTJz_!i&D`oI_svm!euSFa6B&KNEf_y+kIg+xk4^V{((F{hL% zd|U(g%;FMyy$zK^N>LU|rqyawkuQX4EFu|>AypMQBvLvS|HZ-6xk8+S__;V#n#p|?*MNOhC-zKO8xDHN}l9r zS^zxRBk|HXweUep&JS&c51P{VqD5Qs@58)d%D>lK_>ieUvb2(Y-;%5&RJ!fCH#pKa znxf!&1fyo{@M!(~lU0o%x3Fp8A^5PMmW;@m2Wb zIr9(ypfpV=u?oc#%C4wOHQy3%xG`A&M5y5ecm}|p3aG`&P~Az`G6|Wq%rTJgb1JNS zI9&4sd*NZly-cyuGN7eO3$hxrp~N7T5(zvxQJWx36W}>q8wpp3^pjvTSP>#Q%hyyy zJw+bDvkQwj&q_0%)!fP|`ib&qSHc)6i;$MVF!`CI{i1hH-?qkLVuCZHcX9#3Ow%h9 z^~uae?};ICz@N#?h#MLeKrD0OX9mxbFv*r7w!ZR?K9$bZgHL0^n5k&YJEENJ>jKZc zy5KC3<{GhX(H+{*;jV9|(hZ#^KSP^wiW08+Mv1O54w!rk^gw6t3JU8G44Q2zvP*}T z?n;GhL?#y!vzPeT5IwZPH@q=0x>*ALJT3d(m=*cYa{*Ke9>OhboDj*(-05gL%wxA# zR5N4E*iD87nt%r5O)|1BMo`1;40?ev2S9ME`aQZ0NoX_7#P~|Gx7F<+&zrEfl@uhZ zm;2g_2v{ngL9F3QGUwfAEqK6Q^pMbx^n*)s?$5}yP`Uke$14>{@aSpMIuzq-~<%wU^ zJ^D%P*{=dm{S`Vv=qdU<==DAMP4x6PffHYPPM#+WJVzh@%6!-FmF0cx$x^)0+?tkD z%aKUkUD4)~j9r2x3stT<;a>ijR{5y6`k1r)K5x|{f!br9%7;Cb54o2=kf^`gn!Z-C zGcKMs0Z&$W5&0RuVQ^!lj97iPQ9S|7lA?L72?J({WkER@E)TnSLeWG?m`ox%1%mla z&DpaHsp(ZlcQ$`GNz{xFBJ{aN%wW;I&CJo-O8pwy){r&0;6u)RXv;Brx&gDkor+h1 zv^?$sm;l>o3|#Es9vH`=K_$i0J4JrhO?24jR>*M0&H-RdekN#iHL^7M8F9nN&r(d` z!}=y?ZG*e6MXPVs8k*GFdJImIoMGeasi!qyXd*f>9UNuxipU)xnc6yMQX0&ID>k6u z86gi8hN$aPm5kqu(*eI4$(e@^37NEv9L>K2NCw!PEIc!tJdMptETJ#jQ#lffF-iCE z+uT08hWS~R_gOU$0m!Mgz^)}cpx23C+TnpoYrLv~AYWs22C4a}(6S;=D=v;gS9__W zrO4h?ptcsfJ4-Z3b=NXi_j0wn+&C)o>grj_hk>?bN*-=}TZUV8Ww(V(27repcR!Fe zWg%bOX-(h7D-6Vv{y|389huqRH|6}moW8@9d%HD#AT#T`iho#fbisZb21lEYzq{ml7faW+#+z;n*4&5$=c|4+Q1hUt;$A9%TE&Cj>POub4-q2PRX;)vMXS2cRdFO# zbs!@P=SEVoFsC<=TTwznCXx+VBF9xH!Zj2D6LL`tqmBfY2Vok4s>7U(Ys`*%HUb- zM!IJnJfPIEGlKB3rfO^k)&buz@Qh~z4j>jIh8+zuXmJ!HC;^NKt#e9k8z(snZSG>8 zGcDVISyD8WZllJnHTO8{(VQi;`eqi_x@wyVuHAJ_i*7x=BLKd^9VCmthiQ1>ggEW$ zo8r!rRVq>BF=#d*}$n)3ddu!7~u(2@QTo`F7@>dmQ zrkOG!e8Zh;h?n-}*59ndkZdTYu3%dWw*NuZwM^C&6$6Fq~adP zMzrz{Th4x1x8iJJB2ClS)bxpu`|f*v>EnOTfABx@9ywQV^y~a%U#A~Em;KNeT;x6R zP5SY#8(#c6|L7m$$Ii!&o||~{i^$<;l@w$nZ3$-;*0(Poz9&|DZL000xAK8l^W(ni zhtTLeH7BAiCtMW|gc}~y(=u85!EhrW|6!u;1|@OrZqks|OH`Zsl$isbfrLp7HKQ0Rzzxn65pHVCDjbKIDjDk=RtlLdOo3HJ-^g@G zO^SvTj&+Er#^yUH1YzW7{*g1CHkw|Us>G|+=P`TSTodFIv7kF-vnm^4O6|A728tg^XFB!mF&E}bl2g;4`4!@Ll)2pdlU(Nd7Ysov_Ox^ib{QDmeRd=3M)_+I#qq&ln zU?OLEU8>>YSj|pf)lG!I_71{Zdxxjyc3$P8>JF{)cEYv%ds^kK-s;<;)mJDSNNs*L za{AKAoXWC9ZI>zVeVSKbRSkRi}_H zqmmMCXeb{WW7`xq1{$Aff9CJVCQ2A1e@bJrkTjFxWY#^yoc#edqMRNwT+vW>G3WC@ zm&QOj5{kYdhrto)86jk>Vh_9Hr-BT8)_YxpWa-{v`d9(Ew|BL(eTFGd&bA?EODC>5 zNCjccc7{JoDX_kc>Iwc03WCo17Q$WIsMR$&tLhw;wa6ogB#RYuoptb`Gzj!fhK8|5 z3x~&REkCM0_d_IcxebLWQF)0@Z85rN@lNy0qDJy-qSTS74QDB2gA{F4MH55gO38BY ztZ!72e@4!RjQtGs%5a;Et^uXBTWM-n>Y5ij=4z{yno4E)GHIiunT{wgl_)Dw@|fZ5 zSJ-T*Z&Fs`SxO|KgkrK{I}}pFtlRcU(C0-kO_X2-Ds7A&>}2}dR#{P`>W5Q(Cpg_k zjCNs38LP^yK3O#Bf*QpYbKK<2QIuGwIZI|066WL*TehMEO{N&N=1hJDR*kc>FIuD| zN}2woq?XE3zf_fyRjcIGD+To#r7gIS_=|V@O7?k*_Iiu2_Lp80UjAKo;l9Mu9g25^{A^KU zo~%gL(!xktP-1B)UJ;Eg4MQj5%ahTi@yPO6v?3l_8j4lQg;=0V!h}2S&(N$om@Ozp z?3GA$c9)KgLmRRdwy`Uav314la8q=%qC9WOUU#u^_6HUC){LBHXuN2Q%Wk)%2?iNOXRq73!TN~mb@Z!UZo|!%95@&~A4%Lr#@`Wd7k+d@rFAM<3`9>`i)LUG1f%*qNjx}r?(1d-{A z;eX3eqb4`2z`-y(?EF@40qz~Ap9Uz}+f6Ldu*EWM#U^`6hOLY+yOt9fj%7>iOP4sS zGSuo!PjiOWl<95E@HCjTrHZ|XIV8*qGigr37Lu?AZMKkIji_2&Q=?vI#N$Z#oJqeU z;j!~h%4ds7qYCXR7Ox6(mXu;K(|7NUC$js8@<&!+CCXm7Abb4<*z%2;ipJBHYoX90 zUahARA;kz9PbSwI?ScPPn8jsesLlE$X9LxXllJ?kIH_^yqqObmn!tSo*x<}EGPG;Z z(>X#VMQuTsqwA!HkhF{`w6V)k-{Gk3bTy!6P&DZZv~{~1T5)cGXD*zzO=?{u60{r) z8=BqiV;F#E%$D|w&^$L!m6LM|zumIzKn*XDWZPceKL8|FDWM&A4f1_H& z*$}Svk3I!lOiW_mLgdeGFxPd;ZfJF}s=|4yeqdzZyB}c}~xoG>B&s*O7OUJu^>Hp-b?vMV~`N3a1KK?tg@4x@r{p|CZt^GN^zkTP# z5AJV2a8tw0$7*kQWZC`)Ypy@maLbvR8%`0`hfh}DaJ=z*ry6cMQG3f{&3B$?xb3m7 z!*^-Z>rp2%LeWS=YwhgnW$QN~Rb@@>NKR}^Pw&uULwb5c*5pF=)SBe@LSn`0)QW}V z*y_@m`JCY~7q^2?^0O-tcct^S{6bgJGF!UDmQ!NQraiXMo>fF}Vav+5rt&glDN{Vl zoXFf*F!PRD*MMHfO~I`}+LvbVo^c|EHVBc{n+15)9~LakqPSy} z-9_1hEOC2M*~CC4$#9gC5Sf`_WisZMXA|rTM|XH`jf|j~U!47$nqK4V9HIuHsG8Z~ zW#9&Xsq*^Pu~RQkpZ#&ktDjZB^Y0Ds{I&M2KUcr?m-=`AUiaP?4Ig|}|M8!R^7sE( z@$r9D{q#>YKmYgUPybl{#!pSdQ%b5pNf&i*zp(Mn`)h8!r|`BXif%tqeCO$syUvu~ z^J3v0XA5pWi}JAS{#Q$X_+rt$FBaeTQt<=N5)F4hv1HvIeiFfRN6)gk)u~O}k{h?O zeT>1~EQmCAo~E{4p1j}+_T4b8-M?WMgXm*h_T+43*4f$+yeOQY9o3yI2-h@(s_VUt zomzdnR@+8+YMNb@4QfR_!3E*2XwWJf-BpcT`zq>`6q9o4RAnBH-|7!q!x82c*xADp zNt%NZQy|PcmQXk|7|sZUG6S(CzQ_`9fF8_DkI(E2m^B$`D=;Q37SuMLcZ3+2t$532 zZV$m{7oUSx69*QGsszVy`A_t(=RXuYyS1!k%d^I32t#=`T>4~V7_xtg)l|YBWmJW} z5u2|Oc~;-B2J-~T##38b_QqCo(34pKEb$>B>vcM|yAnL^#d_4s4CgUvYXx;}LxIjw zFf1^pp3=d*P#xGhk^wUbnJf*va5wg<_1#9@#M6K}*R0kx8y}LNjpS^pt~FIw^S{-n zj}D57x*xtV26={Wh<#M1qf3WZU}zN;aDzp2HpDI^EsYb5Je>(mN*M@Jt@hI7vKgU9 ze$Cm9z}N}XW}JwOLuaqOu;}R28uV=?Os_ZNEc8TV^`y&ch97-x)!C04-~CI&JO3>( ze&=ts{{VC2hv#bE|GfUAFRDNMqW0sjDnI&L^(SAn{`B+mAOF@hze*Fg?FJEW{S1=5@M5INf~O>Vw8d&lJr0?NH`U%{Sl&eYawRS}6n|w`Oo`w!jUAwow!{6B9Yv7_wtL<=AgYXVdZMRm_#hYqX zV{S{kC5PQ=c22=ozh8|+)I^p&ny^G-=5W*&i8^9&dpvH7#RzjaoEc6KmT=q}N$^>4 zZuc`YL@G)w@(?o&-IQpLoSJE9<$r4>Z_6rqfwz;4t@C6jhiha~k^KegjK}1mAmF!g ztSD?~$eLW8JF}M4pUj|Oa_sB{xEiFktDo+D7C@tOaWVN={)7VK))*4$J)y;%XHWpv))eQs~=KpML*mSjz`7op6KH^pyoJFjI zYCT0<5XDINaL8^r$7mb`3BtYDAJH^ zY}I1y_roVCXYjA;4d<3L-*j~CQ}5Qj@o%+1{!`^!f2n@^^STet*Sz;t{rg{n=lT!+ z+Wg5ERUdp&_sRLH4?b`B^jzmJ&Q-ki$Hdm1N^YSNOm(l^2$-vG{$bJWCyVbmMShm} z{+W^=JY9VE3q;9%uj}zz!96eK-F>$3$aB@-KV{i=jS}S87!0@fE}dOqWJ=DqE3>y= zp4xmFgWAFyE@4p!TToelL$K|Ly|?l0SFrOawfSKKz44Zt}#$k@2G*r zHS&+_s%vxCwYm7m2i^@GuDUKllZ!Tv;T*<;)s2#$^>eYw>sO<3a}*MivL&)I!!cVV zZVkswkyvIpYDvV+@t8TDv?Nm2c*+t>TBA{d5oaP3Imqxbd_%gk-JES1$3b(Y%fK@r zmn5uf%f@FHXBr40(dh>aM4!Eu5sMVGHYcVQQZo#rkaHgrD}k&b6ZQ2eF+6__0}rpP zzm#S1dM6;SA{2~G5h800%|%eaP!cFH_lc?imUzSy)KF9=kn3kaj%?E0s&`HWdRAy~ z44pp%V+w!3n6&I^YK2<3n_E4tG@#eG}ZQYC^=z+XXIq6U~`xcurn7M^&$?#;i{zxCIK zxBp)I=3gt`_-oZ$f2(=>i`sX-tbhM+tv@+m_t96iAAU(Rd~$y5cb~Vs|5@Rs`;^=Q z>T4ZSt6Oe=q~VqaO27Yf(H&0}-EpSy_R~dooi4rmEMPAB!SjVbcrowJ=Zf!nwdn3w z^6q-3=$;qq?|#O$>#)cmp-`k_VAPj%T05B6g{v>MJJ)~ubM}51Sv|QiiYwmZ~cavDWOW9G0wtHY7jW^K*;3JCNOy z^BeV&0W;_reg#ov!tFX~4xQN|WwJ?@p5V|}XY36Gz0#CDG>;-}>l@NWCjbM0F}!V1 zWeFj!sJ{A$MI521!2@G5i=d}3&_7702|BZY8BZMyM9is2Trg^W zu*m3YLv`V2=2VCW4-!KE7lCR=geQ0SnQSo1{16&u*8*v6QkHWi*6;Ao$%-z5O&QEY z4b(Tvcp1B@FSQKV{i*c!t5-erY}@OfHNEo7WiS7s?#(|pz58X&8-J+=-tT=`_u-c{ z@BiJvGp{ute9`>T-)rCbbM}4jgR|<+>jlq2rqFkkO|Fb=BrWevY`vIZ z_8^hkeici~z%zV<)(pm)Wo^1FweiyIO_!uL>}Ir-63gN|>(48SHn#Yy>o67YKvb*S z2v~;?wZEpF&>Fg&HS(;KFQ{oDg5WvEz2M5!yzmDC=z?U@ubzS9z}prR`eBJBI6NBI z&WOYa<18t778(p~7TgjBXa(L@ShOISS3V0|VI4-^HuAGB-HUr)^riowsq=u2v%1#y zU~Ki?Wvfr`qfxUgS+ZqYvShhPa<{<+jOh?aLUNOvN&;yF5(uQ-6fPlz5+HOiF1YvJ zdsmw-$&lQe|JmmV{=3#*-}*EfNu!zf?DOt-mlMzAwB(#Bud}1Ipl4~(A~sfu-0?qb zsiU)26pKd3gG^GP!IcdfSwrvCh_{eulG>!U0e14tg{gF;s&ict6EvPlYKzp|+KEx2 zp>0&w;6R_|nHWq%716cI@LLLynx`i zQ)}uIeASqg*=Dw;=`f9hrrAMuPSBMA^YTbS;TD$rDq@O=$ z@YNeqGwRwpCja<%^*?-$V33f|{>*F6XC)-G{^B)|jM<-g8*}{TBk=6}E$;dsRlodu z@;#4fJm=Imxw{wPjcpG;TOz%dr-X}1nf23oCv^ZwQaibNqJBSd(aK9pzB|cVo$RZ@{U%S9 zQay-`uGxc8)A>RNA}@o$P_iv;Js=qa(wbdM8{@1c+{>403K?~GIkQ)1bn>5~NUtnF z&ymqID~N@qWJPIu`Q3zscb3iUlwR+|G&wpXId5!Qp`m`((q~?rvi^MY$LFfoU-z%O z>fa!chH`i}^iJ9tp13^-yz90I32E3pG-Yp$`^nGz*-$%;ndIK)mgXP)y6Ms9>`%Vx z`sM5HU%%=2)!((s;e7U84Ax=&)jN*gegM+|%(my=s($K~jQbupj3@t+n=`S|H-B;Q zYDP)i&MDQ5qo;hGPBH2v8H}S(CpX{oh?R3mZs$M^4kM6}-RyUUyb}I;p2eP9+mKZ? zk)ThazuG213(Ww=#Di%-y0#f#ok>()*Ff0}Y1wRFogu#j^_%t7}B=S=_aF z^3N*`#6{ByG=6+Z+YDo8M_$k3{P{~ntW%>D<%R+V<`yz~g^@>#Z^g8iM$tl`(?uG5 z#2BI+844UA?IAh<)TKuxN(9WUvvMigpMg?0hnoy3F%n2qYeZ3~G`BXl5d&hR|I}m{ z)v~R7w`=NAGl-*ep&UwW=F8Mt)H#tjbj-qAD*5ipx{Rv&w5jt{7&u1`51KZItO~>< zZ)Q&}QxVj%(vap#St-S(pc=Lh4?&iJ7s;$Jb*f9r;)gP4tx2Cn-jgY*l3U^51k$vU zsrd#XS~7Wt$17%c8#t#vDQQev8nf5p<1-D;rX@f8b=$gg&2Jy8Uf)-A*lXvz`{oSjE=6RsPQZuRPyU$>*U%cXc>SfE5 zsCKVFq+QSc!}+UsFxPV*I)3%O<5%xumS4U`sEB{gc<`rkmRw#g9do|<3(If2ujtl0 z%hrB{#(a7)Xr0Sh`e6Po4+CI=M39W3fuP`3tbMR}^*xD|jU30xUoW(|vuYaT&8(fC zR^5{5pCshDep+G`j1Iy)jR&#R>IRH=Udjv{m4+NLk8~wu-khCB0Ei!kKWi_YP*{wP z5jP$#EkPm%m^Gfc#^o0y-!YqXOgi%$MXAv2Li=7}9i#4dly6AUmmJQkkgPeL601k& zmZv0hkU`n3*~U5Zh~mYBB$G0b)6D?0<`@*`@M+?W$&X-U&>R9HG?Z6hLW05 zGn%s|HQ^AnMn~ueo%8n1*{2j$3^#q1852}UHy*cln$(Y2Dy3kau*Nek~KvwIAl zYMF43(4^0eE%SEX|DUb@*gO4=-PP-QYuEQzeKLT7ULW_HLe-yy{p)*cKN+mqf|?ha zyyI%aw##iVd}wH2!Sptxw|>&spJ@KpFP%@lWP9Q-LOFi<3c?*mY>3%^`L^TfcO0;e zr{98F18LuruVg*+gy1)v7*)`=ygct+{Y0uW-{PQqG^%i zlqe^RLRA)NJj?a-V36nVUCow9IZ1*Vk*%giPyoU>9nkm(Yt zCMHzYCHg03w-ISdRUQT>2hwPFcxFJ0uSPJ$Aq$0u6iuI<4=HL}hybGTOxY5~&LXs* z@u#Xmj4L&zuxQHuvpZM8Lkhds$~ea_@H}_PxY{XFO~JIZxTJB6xGXSEU3SNem-n>2 zy03O!Z}o@QJnvujue0#!&61aNVZh#7{ykd&3hqU+a8*yJ7yl@Rnkm zyZXULCx88Ct|wlw{^*b9pS)mu;;;6fzvOuGZ!i$+6EB;7_L}*LznhAH9(G)nAPIXJ3tbPLJ)5FO@K4o>S*;e+Wem`L1a7S2=i&q1Iy1jMWe2F2A4A z$IiR&FIu(&wr0p3Z^+EcwR^yGTGhmq>XziHsVTKB%7_h-nj3*JM4B6}l4q%FLVr#) zImJIGq{e0D#TS&|a>wQtVg!IVYIJ5Sp|BJ~=s@n^TjTP^kICja6Tq_}jUy^x5#;_T zjT7-%fQ<)+AuC=X`i8`Vf_5Db>c~;oDDt2}IDR{ovKDh)eM$GS33C@~rlI>XXugol z;DTG3M**Jk(o*)>txJqVtwr1b#%#@`0ueOQTNiQMcJchR8Es3`X7J?_DuQr>lxj%h zcI#|xG!j&K6Ar|bGcgtFpc&ayJ2EG?18KTWC|rVj(1yx4j#l3eRaIIQ03IA(gsdoh?I?iXAHgp1EJDMIL0hi95-F0T6E4uzEri@ zfLY^NXNZ)Dx13|d^XIH6oOfGM&mBw)De77So+U_BE1e`1XIc)P`QsosF9bmmfVxQlzFg>hh=d01Drd+ zU>uIT;R?G(drb8B4LJo6;9QeEt9DW*`e$`B-Z-(U86y(ZUvkx+Io?%8t}vsrHqBd| zVze8wnDd;<8GqwA6eGJpBN;93=G@$|dGaM!l7o0}OrV}W0Z7XYc!qex8Aymw=b0>N z6fMC?*&&`;Ck<6nTR^U6MDr%g`>gP5X>^)J8f8>@#`^&n&65EVIYCKtv)xYud7$CrtNstKVGSFv*RQ|YxUH{l)0IW*ju>wLCPj2f zr6pDO{m0aAJnnwtdB;!wXny>^O^-bfwz2Z>|Cjl(Kihx$H^Jsq+*h*t zVe6U)`OwGO9CH49YF3`vAz?^m9sDh+a$=&dAsJNr8n6^!W3pGSY5t~+s>x}UgpJ_Y zpNwptkwaldTzZ~HDd@#BkIB!wDGxm70c?Uk*oDS6&%vP0ICHY$NIKfzYWEA%AYGz` zXz|ZVdGixM|^5?iDp&ZF_)`mO{A6{WLO>Zk(ux!FSs_s`}Y_C$7q0VqGz2&PJ zbJixeaVo@Z%m9}$;QG|~&P9bVXM~Gc^C!$*mWS%4G%=0g&)Ml5snS#;1KAC7(Bd|y z&O#YZf+y4chp^TnLNN&xUCb=kx@n2H-`eRIz88W4qsBDHfT}^2fiwnli}ThHt>Bpx zytT>xdi-;|rzW{+Zt9e-B1py5*|I<;x5A$RGm{Xw>Z}b{f<%~ee*66Vjvfp_27*NE z3i)gL4rCTO6VYcgC3110TE$Y2*KrG$-MNCX)e;`+!xQn+vzO8@Hb(WvGL&8pMoG;m za(Sme@xtt9U-LZwiSLCi{@0IyYR?-dylTQ=YRJi=6mmK&ALnT z-acel^L;}>?wI27_7(TkKkyC5qfa@1@C)!_y-0f>BYhXyT{f(hwNDKf?K8SLJs(#GVrdVTOOdAUH9`c zupQHZzZ`ATy<8>$gXiqLY^wv5W>i+gD3U5CCHv~IByTO=INjfv>YJ48nV96}!J3rH z+EkxdGHLpZteaBPnUqT^P&{y69-es&o*AJ-d1=@((j00tj}S0Y(Q$K50i>E6!E*vR z6e$JQo*77w=3BwD^2tE`3;p?X=PZxt2Q}>B8>ya3OIrsyYx2B&KuWj}d70o{CfLtg z#pGmCy5f##q2geO_9fIUqYQvy38vb6_|T!FQZlEq%y_~SC@aoT#atkqv5GikN!T&7 zYf3wz9~DPhkppay4P6VWIWuuIj#q*XHoLk;QYSM0NU><4)3uY(nQ_Hjv3PG47{-Uh zIepMS-d^71gh@=ELDuL>n=(78v7IZ>{Q|%$$uf`EqpL}gsq<&f!`N%UGxP5FAMw&U zp-D>%zy{JfLzF&q8DP$6zg4m5Rot_{rPOfFEkwZyHoGA+3q~iZX=-Lpxw&NaO6Su1 zjCcM3bA07#&)1)`fAwkaH-A&}{lC;c`eNN#8}&c_N5fCwp7Qj%reA!x><{ma zzx5GAUe-;8xy3Vj8gGB7;j7=7^p$VdfBmVtM}A)ajb|tR$FFK0d8+nnzo`9>XX^j+ zxk=ytP5rliUG1Lpsq-B$b=!TF}_T+k~- zTIEwD;gX#L2_aw{Lp2x0NH|z+pJxL{^$o?J0j**k(!YZ%)()8mxe+|mDo8VOLNY~7 zx%Ca!S+k24P^df~E}`WMDe_d+_;?|ZoZ3!Co0e^k4_=Vnu?(J^HFI$qLEj8yfkgsl zq>SmXWrj9O49MmynQk)L5Lbm9;KU7AW*kvFNA(d|669qa8|rg>bS^uI_@aIavj}Js z1kX%BqFMt98bJfuIh7rE?On9Ppw!XTLVp&KAjX%Pa_Am0axSVf{no;HtFqfyWX-&l#_*h3 za%zU`XtS56v@S^ZRY_ie29uP`_{^Nt{P7$Jm0V~^Eb%6nRi;`dCYx%LE5y=`ld`Q% znYKnO%`r9I*^=RJPxG~9cp8)KbyBUDm77#-&N90*?A~mbKhxKgRoR?V*H+lrncL8j zS=XA~(4OBsdwk10EU#s5{W?)&9 z+VYyD42=DY`o^r5d4<#4iBRH-jfTv8LbHVYqExFR!{JVG`V*|4WJhJXrzXwmPnDbM zRF^-=S()Ol0@A6TYQW5ZxUmJr5S7pIoKI!lXdPXy6x4lQQ&%u1TZ-$T93WhQS=hDU zS#s9o2PNWDtXRc&U%(qDjE)C%6FFc)p1{*E2^-bPHBwMFj>_lcw1Nrbwv0173+Hom zj!emr)(oyv@F}&F#6+b3WB|+DCE!`cb*d@|1Ocjx$y}&TYB?(qZwws;+k$8O@N_a7 z;+fg&$v%_*!xfK4XXwn(fJQ0KC$F8P&hg1qPFS+o_05SBn`op;AR(prv)1KEpa`UE z2~z6#;OIlqU?#^M=dA+a3er^xzN++wnVFM2z;ou*xgu_GN`-6(vvAaqXT7G_CZxovX=eq1)3F$IAETe649%s&W-9Da*ta*24b>5!VeoH2)77n{7aGrAu zLS=6KWR)e9UKRcRqsJytcbDqOD4RSc#}r>^H;gSAm(1xQ`G$-FG8f{P(upEDsyIuG zn>21j_mgB9DKnlUPvZ&d=qNcuisAFwQb&i4cBy2kn;dzj%4kr7A*W5zw89hkS(t53 zu_24o4-2HiIkQk*iwv1XhTL*PUWK8sOtK*qC)1gtP7*g{QOU{c;ZIQDG~uQklGNl! z5ZOd+8%xtcL0Q~{3M{F_h_Ebz8?P!km2(mkb8{&!x+yJdY-aAbtURuKmk5#CQBE4- zk$7lEZf+8!IyWaSho%xbXwtwc-IUtjLM>33g+geNnVUE@WE(ukiBhNeh6cajU(b0~ zl~hHoGmG2WX@-Ies~M34-N2F%>Zz2Y9pmHs4OWum(>wX!C=VJ1dtbT%_})fp?PO^l;y zOP&l}r`%5REaVLlUU=o)ydbu;3oytKa@&M&P`;!5soMfOUl90%3Y~t&iFE0lF^xI@!phInpD$eMwnjaTyzT()eOh5~|EbA{{s(`7*JTY>sNu{9L43F-iF1xG)=ij zZK;zJ0h_c#Qu&6rOib5jDe^6?x62=*4nHZGA|mp7!Uq)Z8hxFq=+fC^({tp?FG)@p z=z?LMPvTEGXZ`%q->+D)5D6XSX;f3ik-%Fjee{?T=;GnqVv3@$gqfRH)X_PieHJ5D zXz>HI82THKE||xSOnm|5%*c|dv+5LA#9K)U&tA;8@Wz@si(Jq?pP4Y?mJu=9<|R$- z(5y9QTDzpJo7-emm+CqZM~#%BGTK_%(EU^3nYtsKGk7N4L(0(EKxi|&A#52iO90}p z6d!5sYUC#HoaFH?Cj4$-*S}&B2|Nn#hs_^KGyW0W-h`$uKLbKEQKY+ftY_qjz;!LByf)T-efTusTIY z#l~?$&}d%lDE#tcp zmYHiLquw;y^(PB-#gy-G?pF&p&a^uP)7g>u(jNlhIH8j`5MG>vGP&M2bxMdUY_juvgxyZtGwekj9kWO(0Z>c$JkPFM;f2t8D}d1#wjW1jO)fFYA-F|frv^I zM-qQp)`Bv5oYKl<<|m}ZlUYs>mktt=^K&^*nRfDo9CQikA4z1tpp28($;-~l!F5Zw zR6PDxPQL|IU|4|qe|$9yO`JB-SrW$~WyYsxNXVANhLXXT;)hex2`ES!%D$6RAjy;* zvG|Q84#-J8m=65;a50=S+caA?CN3J*0aKmY zsaj6vq&3dWXp-7F95Sau$oLnnFvB-w)WGzliPP|+G@g*!7Ew-R1Hrb2cU;vZkW8sY zW__ay1EqWp7=vNlvRGw}VAxxQPeyi5bomKVl3jj1JC|RJ>Ao$^Iw(d3(yBalCNEMG zX|5=ZGWw%c!T~4;n+qopWwc9R2(bAF337qD0=5t>3h=8;ZH-XsRMH$~6m1 zcWxo=SE=Jmlkz8EsRhNH_L7iYkdj}NSzMY*7eHQq8`@BtF*G{puJ+8*grd}Dg2B%x?x$m;g=hPcX^8%IA~xRN02i#m3DQ?Vza1VnIvUw&@F1|(J(QJD0Bp& zLgUe$i}y#=cu!Tlt1`jvO?3E@tR6ADkM|_O?20!zxnju{H(joArRH%ZrudQy8d|kM z=B2=1b@q+RDIS|$M63AC8M$NAb2&hHOlmd;*A==8b%BaY=$a`oW1~riY)E-0roFe? zM0he=6_j4+J%*zm-9bK&^+p{#ZdUIsYL&?^Ol1y9IyV$lW86z%B2SaG^TlGpGjq@K zOfM?SsID!ZIt{Gy(E#Q&qC9mZ1e60X>lh!WBt@0v%Se{BEkx6xt`eD!T4IVcGG{JJ znYJ)xS`YK^anZ?iOHGl&lc24I%1Ko#_9 zHA6dRqzo~o&hb$a^r2&b>U5ekdEAFC3e%`jkoJ$YyHma148Na#WIinF(lJWSsr0~C zOLdd(Lu{meuU&Hw)M?eaqBE70`N=ZWUYdWIe-H!M;+eH6|12Sc3|^34T6xpjM6Z^h zV-CgAi_&Mnz!%FXNJcXeX0~+|wa?3;IBM!#WU=gNJs5`(P?AkQ4$Ox|L`jJ(mbPvl z%;Uh98S~{GmLqX{I5?)Tqr0$e-uRha1v3}sw=KwPTaq(lQSQt|^xE)oknZ7F=LvHb z6m|4q1tf-M_7rw37*Ax{+Kr8G?ZJ@p3TJdrXq&I^xt7jaR5Ww``01TRt#b-nX40Hh zFtv@F@y*i-X)~&)ko(K6Z!4e=ZqoGZ+9~8vNCjq)!*bWeIXrlec$<5S(Kg0t$8IV& zk&=^Ut0JY76qGV@!H|o5mt#n0R6cSFN4_eJMFeU#2zC(S&=k%!5G5y#Z9?6ESY0v- zq!S1VWSPh&qWi()AURACf%6axWHQshz&H`kC0FMyCK^qJRn_BX%$&g3leYP=WqdLP za`e+tlELSt(g&hhVd{gE&6hV>-fBvBS{Ecw#aS&XS@=NmwB>OPT`5x+;qfHXhjVTr zpVBF&Ch7xbjs5ts_Bk)C$!JZa+>b+2zF&Y|dn-2X9a7H=a;t&P)c+Q>n6s!^3<4Hh31d ztn!sy0To|jxND3vTm)3pWds>36t@h!mikf^6+*pGKU8BlvwsE8|92)HyOoSVU|6~g zMj(om$vMy%ku=o}nhy~rab-^H0?yaSow+2ZZ86`%^n1=?QAR42|iV=~E($LK3sPQ;6d-NPL?Tbids!f(T+e~9v&K2VfJJ`NtIcF`E z;@-}M*ysDNP8dm#C$FDhf(fBgB0QTBcwo>6Kdv*0dMaQ(h2p$;wl?0nX_72Mp5;ss zB5pA@-})JpFiBNjbtA=lWEjUeD&uV))@+BCTS`*V40)ZOzyFM~8O5{4cILEhrYP{gh-^;D2O**EXHiR=_e4H% zbs87#wA|?T4Uj|Cbl(<0QgyR3e{vLEYB>N@h45Q)XRRunbNl$YYYOMC$>~^09amPn z08IH44#`C}K~0kLMrE<6IXt79znapc&j`!zUYs#^0p+_=lC3Iu`9T?yGg}5dX*}n5 z-=5cXTlO5fEmkuMm}?dXJ$Et|STu8rsdzGH%Ah?`6`4DCMgE*sWQh1#*d}1scqZ3B zp=*`MvmI1Ut|;kQLS00DXE#>dwG2ow`k1C3+WFbXi8VO$mwFyH@%)ZudF@Ntj|w^# z6?7~poV9R5=OQ+d32i;a?F%MMn@3J3f3jF^{WPqwv1LNj^zn_2c@rn56C!!4GQ72E z?rLC6G21uK4=W+V#X9<0(=D2-4Wz!)}e6)hS|>W zvC7Sg?m?VLF92RnIke^C0M+ackS4X_s`^gjoDW@^xjI&Y=e#*<#pd3Q<d5@cu`+X33Ya-goe?@rQ{h+5UBORLA`7so z^rk+RRggEATG`vc3H_BgK*_j${@x&ru7Y|OHNZOXHtM_0yGjj`s7WjQbkcwfuU}~ z{USnyAmN|Wr_O^r!D)3tAbCR}t7_tbo`<7%C0#Ymm|s3b>IA6YU`LjAhFNl8sA2l@ z^UZP7SEbLnhilsGyVGW`&gr?6YwrBJ zik3adK>*B!$eeeZKvw`PeO|O`(%_~?QBi>)eQi{WaoTtf=QZC3XvZ(OOV`_w;-Msx z5!OuGD_-(IZr561EF%}X@8B2$#^ZowRhF}Yd#OC>;drk*@Yvvg{CxiCO5KlBwDe1y za$eAL8=x&(ct0u8?AdEDfqlsD5Q?g=X3tkrh1b+SW2+eA#8A#I+T74UIz5D9b_ zF$&mI=LUc=k))=}logC1j+_^tjwG)YwsqT)jsZ2E^(V-8ITnyUCY~uyY^qfIkZYsn z69A89{Xj3Gt{MmfFfg=bjJOX&4F*L-?tqPqiS)PDHoylmC(#8j1G|7Xp(04m0M)Aa zlcYBBJEjG?L=PN;01#P2lntTHN^?%~_!8aT1iLH6?Mt$I<1H>JaB5(55^eRPS2hJ{ zPE`F|)K@FfL%cUL5b~yV(n^rS8TX0@;y2{~8dW@mMUUq3+Zi4r!5VKDZymgg_nAeF z+Qae(T9ml3akG7MBQAR3Z5i`drFP$zJZ}}pvM}NxvukZu_nnz@?@ph6XZD;sbLZWi zGY^cd&0!Mn{5#XT*JkuEAmYK4d22K0tpVY{LwjAITgWLG-5i51#;{YM3#q^x^B|DJ z#|pKWe@|}D-MRDEW_Pd2nty-pqA!UPUPztx-Hcq|ad0c6+L_bdwT6yJhCVT*onBEX zbnoIQbG-NMz>=lJg34WdA1{d)meI9_7b!yygs%WgPlF~PXTt;Vz7H??*_$b+BPjFA!@*dtr8Y{!UNs{c+t zZl%9vOkIc(p^KI~tpiBo>%<`|ABY>ohyj^Fhkquop><#c4JZeA21W5TO}aKie6kGH zmu@NTs8Qso&=6TeNg1da+<<3#f6$o`oKt+j*h`%=CTT&EgTUAcbC!58MOkJ;81>;|8a#^)a1lL1E)H%Ld1Or`Qz#wfw&fqn;)c9l3&JdJ^^82gbaC z?2No=>|A&ikj%&q!?dM|owtp>_3rX-JZ60Ak0n3-ZOJeHTKe=$g+G5G^ReHje)l)& z-~V0mw|^J+AJ4}B=dc2#|`&CYPjRuhBe0Wiy+!bTHS10t`9@n)xZm!t4nRjILd?}%G zZCdwzhQ?LJ%f4f%hao>4-?}Qbb8URvii~-8auf(hdL?&qn8F#lqirbc1mrBM3>Cl<#%8oH*9E#% z>gGtvfe>|}dBm;a#tGG>?t%xQF+lo@PlrH0c`9{rcwkjasVeYw1`Wc@N1WV<`<-7h z`>xc+#Yv4lX;T(~WDRDyX`0T4E`^|zIfY6@YNR_Dw@d*u zM4B6_GRC@{X>~O;`$#TZDRSCB>l_NH6O7b})a`p~1l2fd2maZ^6=372>7>wOPiP5G znK&bSSbf}~c#Alim*yFSTW05{s z_@C=|Ld@E_Q(JFIpSdEgXN~upPt?Bl;j|C8`*)wO-GAACbkKd^y5rz=&(Q(*@j=It zKKtQb*RcWn(LT$eYo`5YCu}=XvhiTi`u(LJ?8J=kZ>@N5OU1hzOW*pq?A5o6UV5YS z`PcG)`{~_z~=kmVwOR-0On)%RUSr0yrWk2xajC&u;S^I;eTfULH@GEJHzM8$@ zVT^-~vb*lg>A63v>)x!MhqYyNeJOL^ec9a)WOv<7O}jvGu6SD62*e4m$(y&9`3xCz z)}+tAJ-h4PobLOw=B&XoX5E!F`yNI`fpg#r$AF6PG=3bwbI+g4>*l+60Q+42?%ccb zy6)kgpT)P!>VT*N;01T${AJ+7Jf>SLq4N|N1K{*ot1w0KSxw927+uYX^Jv<9G3{3q#Tq9FpO@fk(O;T1yYq!BV&%V z&YWC@no%tdS(S^6K&Sb0C8hhd_+-&P9YU3neK1X=fieDB<5@Me$(RW6jMgD?2U8qL zO;X4w#z}>8LKeXV%S}lc6agaQQQaY(Ea)@v4U9lTH|?sc%-}_jlA=KhJNun&oo5154qTjacBtl1pW|rAbv)8=DO7#B*MA{Wb9t!pQW&ec7OB1- zt?doh^+oC~2Wl@3PU#KJ2n@{#hFU}6mVv=(gMs#7xFZyq*&AxT7U;MXn|UEJ^Hg}+ z(Serz15LZHPu||!xb6C+O;@WvJXiD98Ry>)nSZ^t?CFh`XFj(6YJJHQZx#LY&D_V| z&icWd*^j=J`mNUzANk9e2mfHW>uJN?&lv9gxnb>(4Qsz6Tf_2u4J#fnEPv3j=pIAQ z-G=%1h;`p(n7hW%wbn5A&YODfOMSj|ADk2NY9;8mBoY6!O9sBqoo%# zNi~C8nQ??DC!=mZPyFGQ@qrlW5=>V$t0E1$|4`%@PSTKG%Y2f0f%NBi=F8OD>O{Yf zRtQY9WonI*yjA1ezBo^%&TEtW!hrNRn`f-eMPL|@^6c`)+wBPs2h)MD^t$OxK|#0! z&p2nvIV!dTuwfngW#gGK)*ZAT)&Yy=UW^+UwHg%y;KfF(^5}(>fz=WYt5i5@8wKHU z3m<5D;>GDZPqghhU415GKX}D)^t$^*zw1oYeKzL36!2XRdM-y@7sHN=1Fp*f*R=sp zZ@|?z;0uHtmwGGvLf*b$RUldw3|0;fRtAGr;c#U*;*Uftqr<+)kZ<5K*Y#o7 zpLzTK$JhVAmA(IVUH;5*_MfKXL-xZl>%oX^=b(98pLOds`}SV@?tagKkmultc}Kvw zd7x}#Z`sG!DmL^Q*IzDQcd=sKnUeQU7~ef$dhcNQtK0MbysqH6kFtOHZq|?fk@@(W zIgkH6G{pFONucR;hTIRwpr*=P> z-u)nqD5LxStoaXS&c7?Ii+QbL5PqmQ^La45G~|tLP3p|?#t;l0SAt|+c+U+25%uT# z%e+}DGFz82OFVtLbVy;EZ?LQCTnT!zR!dNix#5aIq$xClVe%N zGkg5w9G*C*SL8TPRSNawPLZ00X}COb4j}EK{cRkDoysfCWZPAvKofik14xjZN3%HLAI8Q`8r-!`fqg9tjDz8NRSEG*egU$;9 z&()ak`f%kyq$&^ty_oy@AlUZwhyB5!%3xTVKNJDaRnZtX-oc>j%7EiipW|W(b6pO3 zuSI>A!;Z84?(<>$=|S7ch~;?5dN^b|5_TMkxQ@k~$HG|4`9c5wGuHiK+kuGdV9b4J z$bOLfkn2#`e`2KiSj2xMH04;#v*jYEyPDn)IX}MP-td`c-H`X=Vb6y#`#VAVn|-dg z2mSB#*SsI_zjNLDk1LMXE}36CYkA?c?Zvasmrhmw{etiBXT7hT@w{@@@z;~q7mnHf za-6H_&xgx?voHUtt+_wll=G8~S&zS$^1V0X{^P}jZ@!fJotM(T_j1Y)U(EXHt2sY^ zIpwkElYjV|v>*LG@jFi&9{QnS?SC3pf6cJuLBrB7$*!^N0mFiO)vj@`q5E#bg0*7P z7RR;UYM4AfZu+tb3%;7#c4tb<(u~$y`CQQ7P(t9wDa{m8QgSAysiS5c3>jeH09UzD z-6cXKm^ZGp0*z!IA@tMT*=*(5s1Ib^9C)ssLjM#4R~dkYLzZ5NdWJ+b!8bA|aw8}B ze9=XvSB_-aUzcGQAr`g2*TBB2u@vZC?Wa1v>!mE}Bb zuB64MvE&ydw=N{c&$|1&lb?BI^7a$WJ5PBJUv(e6Y&|px&A=@?Pe(i#BECy8u9)LO z*nU1#**jF#KjIyTdHSRN;0RZDU&MJmqhy` zq2jIK@~r{m_K<0N(6}vN+7hVvWT4`cfO%`UVp|Y1?T^_G->@9HVLm)!KJuyU_`h7I z|7|<|PwRo0X>ZuPYtXSj;y4sD?+vn9RBY`x?dq#J{m+TL|5JPIpZ>mKS)13wmDeM+ zS3{n&*B$%LRBSt9S-;=5@t|kZe%FS*j`w$!zP4ff3-1*?|Bmzd*V7+++OY7xo0onm zXUUf{7k(+T>#mf}+aV#DGne3GaLbes0AP{`In%rIT4lhvj_z}364ZAv1O_B?z@=On zp5G+J%#<`!_NnDu!a%Jd2q`6n(ahNpt=xlTGS>h}%9zP{7&bA>_Im^!7%;ZDk0n7P8>*=8V zY*=I1b|z#z-d}zsXgn4+oeY~#MVyy{>UV~mm%`4A5!<<-^Fr8idcb^a&~iM0>-Jsz z3?y4mgl#8drlX;Fyz0^SbP#jGYt1LdOEL9rx5B)KYbD{|AqV(&_rwy1RJ{l(vWvh{`coA+I<-*Mi1 zsL#3Ys`E(1aX9Qd8Ld1ObDaq}PX{%s@s{rMQQxJg|H{y)k3HGvJ|A*l3VAMvfuj3L z*nKSos$Kmd2i#*Y;tfQBH=eotXm7=_KKn_2Tf}iD;Fie9Lk= zs&QCxG{hRII4)*95iL6!;t}(SD8IyZF6z8EjM>f(@gug=BbJjxe9L-j$aCq2^Zbx} z>s-`!CSpAucAk&2^mry~t^8!K^?cBHy5DqWzm}rE34|%KY-0ns`(+G9ow#sj0p57=Fxk!4xR8PxMaEGRJjOK4No-kQSa7HR zvENMJczDjPvy+d8eLF6D4~8*#DF&V~@XW`Di}s$6InM?wFAw>zimYKhGXQ4*S0LPV zIRck>Lc)`h(5@ z_YrIFp!M>A=|ZpbDzS6W*&DT84LL5e@MBX4BKE^4$2|F#;nBY~{o|D7x1S)n80M`; zccRfx1P#^B&u6N(S4oa&Fe_q7yf1D_nGAl>NJiiS&q6jBW=p{*a8i3KH)Za`+CsE=tLQgo+x6Ec;M zsKka=Oacd5v;e%;@l^d%QUl{VD8cF?D>|-ysr8<3I-YyA^{pL~j|F`@FWUADVBP}} z|KTCek*MQ9(0y{)b85r`gieKpY@7l)gRToPqCz4#%ZWbMIoxa%M(w;jhnuR};ew(|j@2M1veVQ$Kg3SeyK!kAs4G6Y=9j`iciG2`Jr^U(o_ zF^(6OZaLd$JQ)DeybNR(b_(BxA^t8ez;<>7D4I?UIxa*juf<#!gAj7}C2{zm5r+@X zJy$+uu^5jJ;&P2A2V}jR4cd6k*G9_E3>r@bG1iVOpVI*r6fYhRTy`{AdL&SOXt4A^ zf62k1^W4Ae=VQD`uB0!(92)w0YUqAmsb^rfpBy;sfqhQ-HFlf2nZ|fTb+m3;t z!1(HbIfr4jJf%t0p25x!ODBEz6{*&%_Dx85aOas%p9AAn7 zX`7Rl`FN`%-fA0Xwxm}zV~`w5n*cMVO2x$}I(iD>1%UhD1w``&ZBS4LqbAILo;e7WpZ|pXJUHQWN!Ephm7WoMweOxiw4y~ zFvQ&6WN#(uKk>{CuM`j}JZlWc*=*vUKR4h#)?~#$gKY>2Wq9J5>m-fN3(#bPSEXMe zg{izS`I0(SHJ6DOFVy<;mUI3)9WSt9@y?JuVs6+?9V^^l{YmA2zuWTmcK?p6m}h_3 zx}&dr%Ybcn)UhuJssXd$`9RRLZ_so&=r}36JdD>Xv^mUPDZJuJ%zJ$Vnqj{XG@iK5 zc5FX4fDs-7c#UU5e!jG^J0Be=-ybAKGaZTAPu_4{{3j4CJ30uAt>=cyjt9z*1z^9n z6G72Z&fg&D<41@AZAY$oPDy}_oE{~R9 zBLo!UnFofd28S#AW44R^=CgxD(5xw91VT>p;VWft9!dP|$GKmB(XiyPxaqfyo3aPvFV|5dl!go~oLfmj`-vpSXUtiWD{LcoxM&_8rBY zG^+IuMe+#M-B8n+*|BQ;H=pTvWlP7Q-j-b#s`rH}cL(e{!q#m;$F3M=+Z(a(i`owj z+YS!lpC#&79u+(j3<6sBB^C5t2?L?Z-Vx13+40$|-Irtj-cQ*>tNMrV%w${a=RnSN z){}!o0j!krqy5B>Sh<9g5dknTJ`yh5KLD!B4-A?Q2Cav~mIGnq-T?B5;|Tvt z$bII9=lYPhcNn(p3B|m@kb5xTydJP$9e{K>uLI_o^Gc+WXre#DN_SofL1`*Z_35aA zHx^$}bvTmq_My^ew;1mEwV|#ne(EwZ*C|c2X!OItGbNOIp9RL`ukp;t%b-_kGnz+* zIBv)q3t?`U%;6>wV{yx>5(BSDE<;CQQfS10P~?uPdgc#^AndON(mLYPvzp<|aUMTI zU|`YlUSDFRAIhPI57f}LE#*cexRthy@73vSu2ASWtAlDf1Uil9u@*~;$CGHcVN{%A zl%6WO4(pHsq_|~STy>4wOQXg}+^Wu;MOPHDv6)&{(Wn)eJCQh2n&)NBSeU%%p^1j3RmpuFWWN!d#TtR zEZs3sy0cG&vSSgPKLBGB2f82@gpPjst$wwh%kM=yFIL=SN_< zs10D)dKSk%Aat#noa$(g7$w%VjO*jz~#alUNCrQksQQR_D`{A&8|6u9PYnB56$V^TDKPy8+ z=sBpA&b|N+*?OUmz`=bbD&h|T;FVxyZxmn?GJCHM^WuecoeHtsU`>_hhKqJyaKC?c z?2~Wbyzn7I_x(vzIaq|Q6I5t9WC}2k=0{Z4Pvcp+Vnn%VR1_mJ@n^yoE^L>7@5 zNNB$|dP-gWWM+@+=npta)f@zX0~sr8z%w*M*BS{)78nbjDb!E!RgQCeq!5%0AQCjg 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 MevZTaJ$K>%2SUP+1^@s6 literal 0 HcmV?d00001 diff --git a/examples/peripherals/isp/dma_input/main/CMakeLists.txt b/examples/peripherals/isp/dma_input/main/CMakeLists.txt index af79c8d577c..8d7c2262783 100644 --- a/examples/peripherals/isp/dma_input/main/CMakeLists.txt +++ b/examples/peripherals/isp/dma_input/main/CMakeLists.txt @@ -1,3 +1,7 @@ idf_component_register(SRCS "isp_dma_main.c" PRIV_REQUIRES esp_driver_isp esp_mm esp_psram mbedtls INCLUDE_DIRS ".") + +target_add_binary_data(${COMPONENT_LIB} + "${CMAKE_CURRENT_LIST_DIR}/assets/sensor_240x280_bggr.raw" + BINARY RENAME_TO "sensor_raw") diff --git a/examples/peripherals/isp/dma_input/main/assets/sensor_240x280_bggr.raw b/examples/peripherals/isp/dma_input/main/assets/sensor_240x280_bggr.raw new file mode 100644 index 00000000000..d6415e3b273 --- /dev/null +++ b/examples/peripherals/isp/dma_input/main/assets/sensor_240x280_bggr.raw @@ -0,0 +1,470 @@ +0/>LyȾĹ̿Ͻ̾ȿͽ»n]=>'&98=;;9774944;:77965635<8467;<59<;97=697=>/;@9=8687;866966<869814873485154<997;78:.0.U +,  @#j= * +,'oþȿĿȼǽŽ˾ɿопӽ˿ʹźſĹr\;3"9xIE41-+&&! 021086679499%7::5;7;445;9::;7;95=<9'847:7589;3876894<9:A9=<;<;8789888=7;75754477;98395<586976><<993448685/M $/5 X8 / % "ÿ̿˻лſ˾ҿվؼξɿʾźiU1,(cģmV@9-.)%$/11476856794589977:?988@<6:999;768:46?94855589=679;7:98<98:>::;;;85;-7067;<59797;36440778;6>56995:<297547540}I *OA'}G +0)!ǽϾ̿ͻȼƺͽǹʻֺ̺̺μѾٽѼ׼ѽ;ϽӼվ˿ŻʾǼӿɿƾǾŹƼZEAط{TD4/))%"4.5672443805;9=:87:947<4643:;466866518:398=75=:*8583989;;:;4;6<7998>:<::772:34587=674213737086<99<8:99;;>;85;&qFN:0!a4 ) +' +ý»˼ŻȾȿǻοι̺̼ɺʿʾ˾ȾμͼϺϽվӾԿοҾϾѻѽλлɽӽѽҿ;ӿнп˻ѽʾ˷Żɼʽǻ˺̿ȾͿȼºƭn[=6)'#/55434:794039973865685>;<4762456872:74<613;58+8877989778565638:0239774>5/467:32749255238427676;875.;6;=9>?998313LQI9)D+¼žþúĿȽȻ¿»ո˾ƾżȼʿɿ˽̺̻̺ͼ;˻οѿҾսٿտѿпҾнӼн׻Ͻɼн˹ͻͿʿ̻־ѾӺϽּҾмӸ̼ľǷķ»ɼǹŹǻź˻ŻúƻȺŽĿͿrJ>/51457335288:636976479:84:9488845=96:5743325/666966574695?9:::878192776;68184723968975<68:52:76794599874::68536861.NE:3UǺȶŹƻ»¸ƹƳżǷŷķŻĵijŲĺƹ˵ɸͺʷȺ̻ʿѽνԼк׾ϽϾ׿ԿѾպڽԻֻӵӻԼҽҿѷϻμ̸βй̸Ի˻˸ӿȾҼɸȵѽ̸̿˹̼ѻο̻źɷʶ˷ǸɼŻƹɾ̷ʱ˺ȿ˽ȿƻǾǿ˴e52630847426641265444:547583686283674186465;4;3267.574128158;:295533666:2544888474481/485239;666:8563417:<;48757881/=F?4$·ŷüijŻƷĶüôŲĸijµƴɴͻʶõ¹ŹɾҹζιҼʼԻ͹Ͽ̺׺ι˾ؾϾεѽǿƻοԸκ̻ϵϴͺϺʶʺҺѹϵʹȴѸʺµƺȹȹǾʿͽǹֻƷʽ̯Ǹ¸Ķ÷·ɷŹƺ̿ĸɿʸ˽ŸûƸɼļȿʾ.3513/142431764/616034052-75754246.56<51186365651232>756149506496521558470,03436234963546564666:9832661578/4576;7%341B?3ů˴ȴǸijĵŷѴͶȺ̹͸ǵͺθʺйп˹Ȼ̶Һ̻ҼҺɺʼ˻Ʒκ͹ƾͺηʹȷɵƵȳʱȴмͶȶƻŲö̵ζǺȶȸ͹Ҹ̻͹˱ȸȵƴɲóķ÷õŷĹȽŶüúȽ¼ĸĸȴ/34523052/2421344483501451:40626/47464867925664:;8310/2772333229275622665/;714461523065624847336668443333357437;3/24.(0=ñIJòòȲƱʷͷ̴Ǵɴ̲µι˹˴̶кҷշ̸ĺͷظϽʹ˱жͳͶʹŻʹȶͰҴͺʸϹɰDzɯͱijǴŷǵůʴȸ˱ǺijĶƴƵIJIJį±ɱ´ƹ¼üûŷŷú0/.520547252/1,/.1.0...21.80341154.551555042853231113433841:3346774334446826054-69266304233065143.46685755461954+330..'&¯ìįįïȲɴƵ̳ɵĶ̮ȹ˷öǶеȸ˶ɷʴǸʶɲ̯ǵȷdzdzȷdzɷɵȱƱɰƱƲijǭ¯ɱŷƴîõįİıŷɵųûƲ¶ĴøƵŷ54/2.64-5310+4013/0.202013/21120/12424013075/+872'57:67642:62396104463431578374/2133/3/403/.115143373176349332032002-,-(îƩIJDzǵȰȳĴɶƶ̰ɰòʵͷαʱ°ȴŶ˳ʷͳ˴ϱеưįγʸĴ²̱dzǮĭĬìŭʱŭ°ï²IJȰȰĶĬı°ð±įƶõ1+0-/0/.,//3014++2//5+.26/11.11.0111/0163464/45632050253485745/4358401516.31431/6//.3155341./224406216824522/2/./+/0*+(*¬®³ǫ°űƳűɮ̫ȱȳòȲɰƭȴʹŰɰʲ˵±Ů²ͳªɫƯįŰĬïŰ۬®«éîê­í©2,+.-1-.*1,2.,0,0.200.1..22/4//459/221043423051217411014513155357/22833-03423.50303-221/.33./312326213.12321322/.,-*&)*'ê³IJƮ̯ɯĥȲʲūð˲ʮİ̯ͰƬѲòųέįįƫDZDZǬİǬëīçèªì«.,,,-/+,,,,/9012..0-1//3/.-0/2.11220.61202/-1.0./213216.42/111/65652083122//4-210+,/.00..141/,4-20524-.22///0-1,--(''($(­ìêïȩ˰ƲƯŬʮ˰˪®ʴ¬ŪŪħƪ©ì©,-,-0./,./0+/,-+,++//0+-,/0/.03/1,.)-+,013/.32,/025...20-41/4630:*6-,010/+010*-//(/-,0/.-1//0,0-+-002+,,,/--,+%,(.(%+$%$ëǧ¬­ŬʧĩɪĬīéĦŮìíì§ŭĨȪī(,+-,+-+-./)-)--,-*//-./..1-,0-+13131*.23:-3-/421//00/5.2/225/338-0017153..100230-*/--0/.310/+(.01&,0.)+,.1/-+*).%((**"§¨çíī¯èήɬ̩ǬǬȧ¤ĬƧƤ(/,**(((),/(+*'+'),,,.02.*++-2,+.20++1/.1-002///0111.*.20/6/2212324/221++0-,0.0/,/,21/3-/.2.1*+,,3.*.''+,+(/+**($(+""|"ƨ¤éŨŧêƨǩƫĩ¦¬èǡ¤¦ħzz,')*,-.)+(--).-+****)*)./.,+2-/+40-,,+,...01/./310+1/414040+333/41.20.-,1.*12.,,-.+,1,3,*/(+2.,-*-++-/-.+$($-'*&%"# "z xŨȦŬèçèħéëå¤åĨħĤ¬}zxt(-)+&+)&/()*0*(+*.+,)/)/6+(-1...302/01211,,4-02,/50/1/211/000.1/-11120/--.+.1)--00/./--+-+/3,,),-(,&)(*)*+"#'+%%"&$} yzvu¦í£èçéĠä|y{wywruo"%#%("&)(-++)++(,2*,*--.0/),*)3--,,,,0/20).2-023,/3/4-11.3(/130-,+.1111/0/,-7...,-,,-.**)+)'*+*++,)+('&(&'$#% &#&z'~v y"xtn ãà§ɨ¤§zzzy{s{sxnsm"%&)'%$)/'&&(*--+(+*&.+1)0,,1---,/)..2/-1,+.11+0.*211..+2.+-20010///1.-/...*/0-0.-/2/*-+,,,+2&-&.)#$%)"(%()'##!x$|%y$yqrpppǩŦĩŢæ~y}zw}yxpxrznwnrmsj'&(%''+%)*%*%')').)++)*-+-+,-/.-2./--0,//.$/,++*.203-02.+-2423-0/15++0,1--*+-1/*,41,0&,-+)$*-'%(*&%%'%&*$&)(#$~x#} ss#o!pnolãŸååß¡ää¤ģ}|{y~wr~myrur{kuelkkg"&&#&#(%'*%*',%*%$+)-**,),-,,.-,+-,---0-/..-04+1--.1,211,00./6./,1)/22-0-,/,,.-**/02-&(--(/))(***)*((&&#&&#z z!w#uu!pqlkggeǧéè¦ã|}~yvt~synsoskplkhjikfld!!$')((%*'*$%&)/')/*++)(),++,-/*.-*).//+/0/3/12/2+--.-1.2,300020*1-,-1-*.--++.+0--()*-+))))/&&%'+*$*#&($${#y{y!t!t!pooiefh)d_}ģ¥}{vyvv~r|sznumulrjuneegde_h]"}#'|&$%$)##$)&)*.'$&)'(*),-+0,(*+-.,.+--.,+1/.+,+10,-.-/.-//+,04,01005,/.2+.5('./,-*/-))''%$*$('$(%#%%#$"{"zu!txrq"p l!ogk#ncb\}ŧäĠĞ~y{zwq~uvnsktjtktkslofobjfjce_fWz$} ~#(~ }!"*)%%%'(+&#','%'+*)&)+.-.*3,3/,,2+-7--,20,.5.,+0/420/.//223-*.*/15+--.+***,+,(()(*,')((#$&&$"##|%z)w&y!v rrn!kklhfefb`_zĤĠ}z}{tror~pyprksmqimeldobhbk_fZe`v$z|}#)!&$"%$'%+()&'"-&(*)*).*--./-3*/.,0(/-0//)./1001/0+-.0-1..0-/-//001/11,,*./)),--++-)++&&&)''%$~$""~%y y'ww"p p!pnmiji``bb_Yww|~x|¦¡¢âäŸ}zxyxzxq}rzqymxjtitfldkfieked`cbg[bY|z${"z"{#z }&!{$"$%($&*&"&('&&,)(,/+)(.0.,12*2++0204010,-1/0/24-/,.+.0--,0/+,)0//-&*(*,#*+-)(%,*'((&"$*$~""y!z%u${"wu!n&q n!ogmgedcb]]_Z~wvyy|}~¤ţġĢâ~}|yyzwrq|q~oyotjrhqgnelejcl`eag_`[bYc]qv#y!|"}y#}#% %#"'%&&)%(')/)*,',+(,/0,(,-/.13)/)-0110../21/120.0./1.'120--0...,/,*()/+-*&(*&)-*&,)$&$')|$y#~%y!u x!ps mnllhecb]_^^[\tsv|zzx}~£âĤåƤĞx~yr{wq~x~t{sxlvnqiwhqflkh^l_hbc`h`e\a\aYwrr$x x!x#z"{"}&!"! $)'('''())(%(+*+&)'(/0)-++--0400/.*1..04,.-//100./.-3.-,0-*,--(*),0,).*%')(%'#"#&'z)~!~%{'x%xvrq!ponmihida`_`]^]Zn|suv{|z{y~}}ĜƟˤģ¡ģ~{{}yxxtq}rzo{mvkslujrjncjbk_k^dbc_eZa[\]^Wp"p s#w ty u#y$y#{$x%|'}&#%&&$''(-')1*)&*)+)-))(*.//./-+,-./,0++0111,+.--1-5..20+.+),,.*/,+)'(*,'($#&'(!!~%{$&{"|"wr#ts"qu!rkg#h"gd"dcde`\XXZX{nyrvxrvwyy}¡¢¢ããá¥}|{tvr~r}r|onzhojvhrhm`majcjk]aa]i]`Z_Xc[]Ol!tqtu yt&v$z#z$"}#$%#%('))+))+,+&%.'.-.)&',302-34*12,0.2./1,3,.1/,0--0110/1*.*+,.+))/,($(!(*%$)),"%'"!w!}"z#z"k"z omoltm fia_]cb\]X\V~o{n~qxtvt{wy~~£Ɵ¡¡àť˦ǥǢĥ~~zxvut|o|nl}kvi{irdobn`eghcmbbf[X`[]\dX^Rmllutu v$x#y!v$x }#"}"$%#"*#%(,'+'-.++0/1(/-,+-+1,//232.--1/00.+//3/,/100,-0-,.2-+/2,-*+)''*('"$)%$'%}%#z!~"{ s!v!p%r!o!p"nkjfhbdfc_[\WYWXvk|mo~t~qqrwuwz{~â ģĥ¢äâĤĤ}|xxsswqzn}ro~nwiqfrftcoefem_gbc[`\cZ^XaW^UZWilnn s nq!w&x"x#y!{$x!&}'"&# (',('%+))(),--*-,.+/0,-'.2-++100223.+0/100-.1/-./+(1+**)(%+,(((+'(('(''$&'"!|#z#z&uvso$l#s lmf!dfg_aa`_XZWcSzezp~mzpqtpuvzyz~}ȡģ ţĢĤáŤĢãĞ|zy|vtv}r}m|kumtisisirbthsam_l]nbhZf[a[bX^U\^ZXiio!mr!oq$u&r!u$v!{#~"}%~%~('&"&%'%)&-)**,)+,,02,-4.+0(*(-/2..34-,/1/32100/,,,--0--...*1,'-))&*,%$($('$&}$~"|"w"v'v!tp"sp"qmkk!fifd___][[ZWTVzhskwk{l{mpsu|quv}|}} Ġ£ãƣǢŦǢá£ģà~|xuvq{q~q{l{rwmuhvgqaphp_l_f[k`i`eXf\]T]V_WZS\Ugten l!mp o$q"y#u"x#z"y#~%',$$%(%(+*%)$*/1(-&,--++*.+(+,,+23-0,1-,+1./0.+*//-./1--,.-,*&%-*)))*)()%(%&}~#}{$x#rrs$qt"l!r!hlggdf`_`[XZWUTVVrgshxmyj~m|q{rs~xuwyxy›¡ßǢ¡ĨŤçţàè£ĝ}|ywvvs~p~izl{kykxjrbmemco\lak`g]oYfY`YcV\Z]UWUXVfhdkn!p#qrq$u q#s!x#x# {${*-&'()*+'*-(++2-.)-*2/,/-5/.21--,00.2154203423,.22)*+/+-(*)*((+*),.+&)$#'$${(|'zu%u"s!s p!r"h%kl jhief]c_Zd]XV_XTU|dthsfwnyl}l|owsuzyxy}||œĢŢȥߊ¦ȡãƦĨŦ墢¡~y{tvtvnnzm}n~lxewethjbpdpcoee`l]j[cZdZ]Y\U]VYR\Qejh knq!m"or q#v$z#u#w{$#'|$")&%!.$('+&*/+,(--,-,/.,./-,+0**,-,.1--,014.1//10,-0-1/)/%&)-+/&(&&&'&$!|(y"{{t$u"v!s!q&sno"ihhg fc`_g^\X\XUURQyjukxglzp}l}o}ovqquvzyşŞƢ¦¤¦ĠȤ¡Ɵŝģ¡ğ~}}|zxtttuqxo{ozktkteqjvhnemeagn`h\dYcZa[bZ_UWZZS]RWSffkjkpn"nqr q u!x!v'x#}#{&&(&'($'(),&)***,+.*0+,--///+/6311031.2../220/./0+/-002,(+0&,',%.&*&%('$~%|&#~"|%s w"u t p"v l"o!k hmeggfgb_][][WdSTPxgrfrewiwl|mzi}msrtxvwwxz}~áǦ̫§é¡ĦȤƜŢĠ}}}zztruunp|lxivgwgrjqdtcoci^jam^f^f[_]^Y^R\W]SZRYSdgc!ilhmmqv#qt"zu v#u{"}(y"$$&$(#$)')'+*,..*-*(*0,.7/21//6-2-2+/1.211-6/,-/.---(-*-(+-)*)%(&(&&''~$|"y!w&~$w u#r tq qlh ki!fcdaadb`][WXSUPRrfohrb}n|i|mjpvlrwxvv}~w~£ȥȧşĥƢ¤¦¢~}~{{~uxqrqolxkwkwmuhvgjepdp`jblbi\f`d_]V^X]TVVYQ\TYPfbfhkp!lm#nr m!v&u sw x){$}&%'|$%(+,(%&(++.*+-'/-)02,-%./3/3721,.10002422.45-30-,.0.),*.**,('%')(&("~"z'~*|#yw!t!rn"l!j"jkeg ewdad_a][[YSgTRPldqevgwixj|km~mmprp~tsuwxx|}|~~àá¤âǞȤƢʞŸǤȟ¡~{}|yxurr}qn|kzhykvgvfvgnbqbkcf^c]lZfYe[bZ]X_TYYhTaOZM_edhjj#i klq&uu t]VNLIHKDBFACGFFCLKOR U_"^%d!k%s&w(x,)2545502-0430071.00/(2-,-./+**+0)---','()('%''~&"~(~"w#x"v$s"s$rv qmnig jhdba^\[^WXUVUQNPkci^sgzgzhxe~nwlnprtJ0+!(#&!% %!%&"" % % %!$ )!-#-&,%0'2-0+5.7*;-:.<3;1?9B7F?IAWHZRZUi[sfzgrz|~~|uutuqqzmyq{pzkzixhvfscq_jdh_j]d]b\h\dY`X_U_[pQ\QZQTNc`bghj#lljio o o      ! " ! " +$ " '& %" +' & ( ' +'+ * *.+1 0146<CGL!T#b#d!i*r/r+x-,3/,/+.++*&%*/#%$%&%~%$$|$z zx!q sr"m#mm njkgcdbaaaZ^YYUUSPPLshqgofscyh{jyjwj~lml|p}L  #&!$(!" ("(!,(,$+&0%,#*",%*%.$2$/'.',&,(1(1'1'/'0$0$2%1%,'-&/*0+9*5+405.81:3D7H;L@NGWKaTi\kdtkxlytu}~~~~z{}wxtqpn|j|lzgwesgtbscjZpamcl_h[eWdYbUZfZTXU[Q\RbPUIbadckhkjk!m"ls!r     + +  +!    + ! %" # " $'& &' ' ) ) * ' +*$ $ & & & - &$ ) ( * +$ &) ( %( % " " +! +&' & ) ,-69@HN#V!_"h*q(v+{&{#|$z"{&z tp suq kngg d f_`a_``YYZWVRUOLRi`mcr`tfvcwi|l~o}k|kmp}T !!'##&$)#!($-$% ,$*"-$0&0#-&+'(',&+%.&1'-%*$)&-"**+&,()(.'.)-&/%,$0$.$/'+*-#0)/#("($.#+$*"& )"'("&*$!#"+%-,65@AHLUT^_njvpwpqqm}m|mvmygqfqcubtascqem^i]h^bXWhVY`Z_SZRZR\N[OSed`ehfjfhl k"m%mq'         + +#   " +! +! " " " # #$ && +# # & $$ ) +% $$ +( ' +% % *# +%#! ' % # $ ' ! " % %"! +      $,7D Sq"n qkjlg"bdhcbb_^WYVXTYRNTNo`m^ldqetg|iwhskzlkk~mb*!"#""&&(!'&) % %!%( (#+$,#2%+%.$+$*%&"+%-'1!+*%-)+%,&+#.',(*$)$)",%,!+%*$/%)"%"(!*!'$*"##""# $7tqo|q~lxkwjthrcpfxejdk_n^k_e\gZ_ZaX_U]T_XWRXNVRSNb^*gbddhgml#o!jn.#   +!  + # ! + $ $$ % ( +" "$ $ +$  +!%& # $% % %$ #! "# # $!" # ! +          f s!uj!i higdfda\]]WVXVURVRPMnbobgbsetgxgyj{ixkpgl~d4*  :&=&='8"1#4$:$8%5!5#4)$!&!% )!%$)$&&#)"#$&")$&!(!*%+ &"("(#(!'"# (")!&")%)!)!'!& %!'$$"!!   5moprxkxkwfudvencqdm`kco_mYfWaYbVbV]UWRYQZT[SQQUJ_b!afcb jfhmn l$h: +  $VSQNJIEE EE G" $ % "! " !  " + ! + +! + "  +!       lonmijdfdc_ccXYYSVURVRLNIp\idtbtcrcu`zhvgyk~iklwdC0&8$<=#<$8#9#>(9%8!# ;urunnqnskpaD%':A<><@87:6=7:44303,/1&%$!#!& ! "$ "#,)(( (%$     Ktl~mxm|iyhviufogmalag_i\lWh]e\_ZcY^W^QfW`QULURSMVJ`cc`eceh hl!okjE +  " $#%$ $ &$&% iostwqsuxvx.E#K$IIGLIJ JF F$  // +0 * +0 +,))) +& +% + 8--*($%    h"i!llg fik)haa[_\\Z#`VSVQPPJNpbqaparbrbzdzf{kyl~l~nxn|hQ  5!5!6#9#:$7#;!:&<&:""2rnsrnvtyu}lK(0IJKKIJEMJJLKIGGLLKJJIC'#-7:;5998:89768-8365414+&DeUmMgOfJcKcGYDS>V?Q:A A4E1800(*$ !(#Xupjmujyfqvlewdpbp_p\k]x`k\aWc[eW^Y_U\PXRXRVISLPJ\_bdacfjjl"mneQ +   "  ""$# %%"& bonooputz{x2E$L!M J J"H I!NK#M K# 5 7 ; +79 +6 ;97 2 9(&[$V(U(Z'W$X+^)Q'T!U!I @)|$x!ne f]VF< 4  0lookgg ke da`_`\%bWXVRORQOOMr^mhkbscrgpexfvdzn{ikzggY$  2 6"7#:#<#5";$;&>$B%')pomtrvvxvwlN")EHJKQKJJIKGJJMLPJMJOJA# +89;;?:=8;::69;677677:) .JqUzW{WtVyU{SmTnXjUpRZ#;[_X~V|WT{UvNwKjIO >b|lo{kzhwgxguds`penck^l`jZcZcYfWcU[UXTYPWQWLYJXMQIU_!_`agifgn#lkj W +   ! +"$# + "' +& + Xoq stuwsqyv5BK"KJIH!PK!P$SK"! 6 +7: 8 9: 7 77 7 4-$T*W%W%W$U'U$U T#Q$P"D + Y'('''&'}%x)z'{ + +F#pml$hgkbcaa^^]W]YWSSU JMNJJo\r^o`pgsfugxfshwmwh}k}lzjh, 4"7$8"9$9 @"B%9%;&9&/{nsqptquvxusZ'GKHJJJMNKJJKLKDNMPLRJ=# -86787777<897779<67746 4Tt[[yUsUvSwRoTtRsToUQ$IWYZq\~S~T}R|T|OF  Vetnwozg}iyirhpdmci`q\k_k\eYbXaWbWbVfTmQ^PYMXPTLPMSHX[acec#cfg h giib  "#$ +# %"##  +Spnttqrs|wu8BK$K"KJ#M L!J#M J!M  +6 7 +7 7 7 6 : : 86 0 7&]$W#S#V#U$U,c$T#N"R!7q+(+)'~''~$}(}!s  ] jiikjg f``a^^XX ZXWT!USPSILImXm^ncjan`sgxfxdunzgg|l~iu:  +!3 83%15!9$3"="9&.hkpqprrsvuvud#EEDHJHJKHNIHJJNLKLLPI=" -77688;868978979685971BWvYxWwVvVuVkUlVqToSuN;.VZ^WVXSSQzR|J/ +0df}jzkvj{hweyfmasbnan^l`l]k[bWaX`W^S]TgT]SUQVLVLUFOJYZb^bdgbjji!lg!b "%! !" "# ! Eqrrvotstx"y@ +BFI$IJNL LJ"M#K 69 < : 6 9 <4 65 . <'T#V,X%T$W"T#R%O&S$T* *'*%''%$z'x"g b$hkke"lgdc`^_[[XXVWTSS`NIHKf]lat]rrkeqdvbtezdugyiwovluF '7#8$7"7%9$<&=$=&5%7Rmqpsrmuyvy{m!AI@FHHKLGMIKKHMKLNJMH9 -6;;8:95287688:967830,LY~VyV}WzYyRWsPmTmUnH.K\\ZXY~URU}SxPvB  Ksg~mnzjyh{eqrtex_t^k\i_fVhZbW`^bWbQcQ_S`SYNWNWPSMQM\_\dbhcdjifh*qg   $ "! '$!($4"trrqnr!twxzH ="H!H"JL!L!H!KMO!K  9 : :7 5 74 7 4 4 +G'X$T'[#T$R#Q#Q'R#V#M"+()*(&$}&{$u#T  !h$ljkhgcb^a_^^XWS[SR#RQMPKKJi[o]iZk_nbueudxdvjyjuj{lxhvW   !/4$8$5!6$5%7 9$>$9=eknssrsurtxr>FGGEIKIEKFHIKJKJIJIC9!.7534<897398693469571*SW~T{Zx_wWoWrQpSpUqQiC"\[`ZU[~OS}TzPyOr, +\uh|jhxhxgyhseo_q`i_j]ieh[gVdU^U^U]U^NiO]RVOTHOJPIRG]_^^cbb efgg"l ih" !  "!!#$ )qmqppsou tzN<E I!KH!K LM M%MI6 +3 7 7 5 +8 2 +3 2 2 +$M*S&U&[#[!U$U QN"QM"')+&'('z)|$|&w 5 + :hkgf chfdl_f`[^ZYSTPQMOKIJKiYk\j[giharewc~iugsfsgwhyeua)   1 9 55#6#7$7#7":"42_mmqmptrutx?IHGGIEJGKLFIIFIKKJIF80748984779=:864979436' _XtWqTrZyStSsSwPvPqQd= #uTZZWSU|Q|R~P}Pe + Biyh~hzkviyfserbrbnbn[lbiYe\h[dW]VbSYPWNZRYOSOUKTKPGOI[XXa!^`ffefhgf"g0 #"% +"#%  +! nnmptsrwvyS :IIH"G!J#LH J#L G4 7 +9 2 +8 8 +8 +6 8 +2#N(Y&T$W,X%O(T&P%T$T%S1%(%%((({#y$|%s"  Pgikhgfb]b]]bY^WUXSPQNJLHGEj]l\o[iap^ofxdvdsftg{fhykx`9 2 54 :"5!3#5"6"4#;#Qknmorstpuu9H?GEKFKGHIGHFFIIMNLE3.9166:6756557;6825761,c[xUpRrYqSpSsSpQnPmSd%-zZ\UYU}W~S{QzTwLS + "[hvg|hkzjx`rdrcrco`n`jYmYbZaXfT_SZS\S^QSOTLTLSNTGkDMC[ \Z_^^_dagfml!h#@    " $ !#% %ykmplppxrz[ 8FF"G!IF F IFHH7 4 7 +93 3 235 5 Q(Z(U!S&Z"R$STP&Q&E b&*'&|({)x$z%t%v$u \k gkgfecbca]^SXUWVQORMLKENDaZeYi\afoarat_scparhtdwlykubP + ..!765 4"9 4":$= Iinooqopzux4EDDHGFKEH?DBIGFIJHGF1!-66738487678444558441!5nZwWz`rQtPlQlSpPkNuKT  Rmfwiyj{gqewes`q]v^o_l`iZfd^SaVcZ`P]PXQZTYMTKUIRHUI^GQFY[X\^eb i`fe d!ihZ +  + ! [ egk inlpqpg +,H AEHEIF!EFE 77 5 +22 3 2 +3 4 5#Q'WTS&S"O&P$P)P!P - o&+$%"}+$|%v"u$V &fm lfffb^_]]j\WYYTUQNOKJJJLFd[jWj]n^gYmas^iaqaucxdzdlvdi4  +  ! 7+S1b9e:p>uJKRVV+CFGHHF3/45:6756654233344032( EjYyTwTsTuRpTsMqQlMqNV 8VT[TWRWzNwPvNs2 6bd{j}hvjvesdvbrcp`iZoacZgWdXeVbU\S]R[NWLXKZNYMRJRJXDMGSX\]\^_dbffdki]    +  +     + +    +   $%* +/064:  1 3. 1 0 3 0 . 1 . +R%V%W%S"W(P&M%N$R%K!w+%y"}'*%}({#y(v#7  ;ighh!hbab__[[XWXXW PSNOMOJGIDfVc_dXj]j]nao\p`odvexbzixh~itE 2-)#!     +       !%!&& ' /A7L=S=[?]ER?[BYGaE\<% +KNzSxUvV|V{QxWvNoNvLf  Mb{exh}fzguex`u_kZkdh^i\iZdn\WdU`VYZXSVP_OWLYQTKOJSGQGLDZX[U[[^b`eehhc`  1A <A;=85 7 +7( +  +                + +   + .:@IOOU"Y'[&^ + Thefgeda]ba^bY[V%UTSNRMJNHGGG_[gXiYjZgZk]kcmcqarctexk~a}jsT MQOPUSUUSTX '% !#"!! " +#+f(^ WPE7741(     +    +         + + .\dri|izg{`sdq`qal]gZj]h^`YjWcWfW\X[V^QZOZMVPSJOHQMPINFLEf WW[]X^]baacffd%  0P R W V _ T X +W +ZO ++'+$(,+%+* B>89<< 9 3 6 2 +  .$ "     +     + bi!iead_b__`^XYURT_TPLLKKHHFF\TgWeVh\e\l]m_jaoapcsatgxexc}Z. GNRKTURWZUW" &'*%)('"'&'&$))+*-*) 1FABC@BAEA@# .($"#&'!%"  @ustrniic`d^]Z_YSTQOI% &7e8[4S,J&C#:#4 5(% + @lhxgpvqcwew^qbs`q_h]icfWbV`UcX_S`R_RZP\OWITHRMSGOFOGOCF=S[TYY_\`b`b c!fec4 % Q ORR SQ Z S ^ +S +)'()'%(*+& + A@@ ?D FBAC >    +   +]z <v r m c b[X U QD + ad!edbdac_]["`TSNVRQRQNJNIEDHDaVdZd\gZhXg^l^m`r`nctdocrdzdz[> + +,HNPRRQTW[[( #!"%)''"*#*(*&())%(* 3F?BAAE=CFB" *.-(%,/+,&dy5h|||vvy}rpo "Tkongtgtbsfuftap]uah^fYfWgUhT_R^S\RZOZRSKULVKVFOFKHMENDIERUVXXY__^_eboheF  UP V P S T U TU +X $)&*()))++@@@BE=?@DC +       + no + `|x xyxs s p o P  *"cef"j!ce^b[i_XZ^TUSONKJIKGHED@hYiSfRfZgZgZkam]o\sbqavdnhtcraQ  ?RPNSRQVTT7 %!*#'*&!)&&&)$'$)$+)  +);BAAB=?CCC.+//-.-)1$ "pg }|wwyxssoji ;_pexeyexkxcrbm_o^k^o\n\jYaXqQ`S_UaS`MrWbLXJYKQLKKMIMHRBJEUWTYVZ[Y]bc'da`dW  R Q M +N Q W U T ZU$$%%&*+*,* C@>C<@BD>=        +   y\n~z w w t s pt n 1  Bfga eda]^^YXVWWWTNSPKJIJEHDB?aTaUeUfZiXj^i\f_qbq`rdrbubu`ybb- + .OMPPRUWc]B"$&%('&$($%'+'*%)'*(!'1>?CDC ?=          G }{xwxv vs {m + U`ecfdc\]]Y^\UVRUMaJKJKGCHGBAfQgT_TeYeVgec]f^m]per_vbxjs`qcl; |POQSTRTUXO3 &&'&%'%($)((')''&(,# "7B9BA@?CAB*&)+),+-' C{; O}yvuxsrluJ* 1abvhygxfpalaq\j[dYoZiZf[c[bU_X`U[N^MRPcP^LRHRKUHLGPEODGAHASRUSV[`]__^%dec`_  @ MP +Q VQ U X T U  !(')&&' (*+E?@ ?A@?C C <   +        +,x{ +| w q r o r n l  \dfddc_aXYX\ZUXT^NNPDKGIIDEAA]OdQeYcYjXgXiXe\n]o^nkndshv_vesK + aPONRRRVTVTJ + "&$#%&$'#("%*'(&)%(! 9A?E>?@D>A.)))-/+.,Ql$ 'd|w{rsrpom. +Hl`zfrcsarcsdp^q_mZgZdWd[dXhVbR_P\Ne[oMXIWHPEQHNFMHPEKDG@JBOSUWVYZ[\\__u b!b a +5N P OM O Q +X T +R , &%%'!'%*(('I=?ABB;@<7  + +      *|| xut +u u ps ]  aad!cb `^l]^Y\UXQRRSLIIGDHECCD=\Oj[nPgVdXbVd[i\n[q[n^ubl`pbtbuX+  HONPOOSTWQSe +%!%'&'&"+#'$(%)$'%& 7C@?=@@@@@ +&*-*-&+( aW +>pzywxtrrmp + +Yeescubseobn_l_o_lXgZd]hYeUdU`S_P[OVLWORKPHUJTHODOAIDK>GBE>SNMSYZY[[^` `^!dad5 + &OL NO MV +R N U ; ")'()&')(C@@AA@AA?;   +    ~ + C |uus v pl lG  +:_c g^d^]\]XZYVVMONQNFIKFGBAC?AYP[O\PcYdVeXhXe\lXl\pZuaubt_v`uZ? .ILLMOOSRTQ| !#$)$'#''+$'%)%()'$$ 0=C>@@ 9@ > A?@3 +    +    +w +Ux z r t s +r +p +nm -  + ^e_ae]a`][\X\UPRPQUNJMJIECBA?C\MaSaXaUcVbUdZg[m]k]mcn\u`obvbzaT + + 8LKKLNPTSW +$#'!##'#%#$&'%'!+'' .A?=>>AA:@ (**,.,-(&*|{r) |{swvrunnk[> + )\`pexeu^n`o\oZpYj\j\dZeVuP_V\Q`N[RXMUPXOUITJOJQCIHOCE@JAF?I@MRSTUTZ\\^e!_ca^bU  #' +,)/ +5)< >:##!#"$%' F<@6? ><C?2  +  +  + 3 d +iw s +t u q pn +m f Y ige_e]`[_Y VWRQTQNKMJFFGGD>A?>[ObQ`P^RbUfYdZf_mYm`m]m^p`naqar^_*     +! !! b0570:79;; (++*+*')# 9W3{srtprpogD! +Accneub{bsbr_jbi[iYk\kWbWbYbSaO`R^PZMRKTJULXJPHLJODJC?FC@IRN[NZP^R]UgV\WfWhTk[k_t\n_t]o`s`d; +    + +   +  +          + +       + *+/.0256897;;B@?( *fJLQQUVSW]! "Ojbxdoctam^n_g_k[jXcWfV`TYP_PcTcO[MWNWOUISH\HQBLGPCIDG?D?D<@>JLPORWSZYZ]^[]`]_    +    +  7 77 33 1. / -    !   +   +   +  +   +  " +2Zc`d^b]\[YZTQSPNNOMOJFHCCE@?><VOWO\Q`QcShN^Q_eaWkUe_d]lWoak_kt_I  +   7+G/D)C&F)H+D-G)E1G `'$$#" ~{P "t|njc[zVsRoQ[ !<5-'##    + +  + + 8VeZsgs`s`r_n`p\mZhYcYdWbPeWfQ\PbTcK\QZJVKTFPFOGSBMEI@L@C@D=G9LONOOVOWXXW[ZZ^^`$ +      ? FE H D FMKI2 + +%''( +& %+"   + ,810 -+ ,')& +!   + + +   C'dcb]^][XYVWTUTLNFMKFKJGFAD@?>>YL[PaRdK`QqP_ViQhViVdXi\lZl^s^q^mX, +     2%D%B*I+F*B,M1I*E0I o+)%'%'''%v 9ƾ9UC;8776668) ,87411-..& P_h`kct]o]o]l[m[nUjWfZ\ScS_P^RULWNQHYLZHUJRIQKOJKDLCJBJ=E?E?C;OLNTOQRUWYUWX]^]a4  +     +A @ F JH KHMM 7 ) (% ( * +&"'&   + 6?;99=>:69 + 9>:789576 +T`d`\]^][XWaVQTNOMNOHJFEFC;>? :@ ]M^MXNeM\R`Q_WcTeRdVcYmXiXh\l^kjbYB + +      .+A(G-I/J)H,J.G,I*I'n*&&'(%+$$s @̾(j@7:::::78 59=!999":$5!7,   5\]hanck]r^p]n[jWg\iXgW[X_R\T\O[QZMYMSKWGVHODMDKBHFE>K@F;H?A=F9JKKMVPURRVY\V[]_]E    +  @DG J FH KH I6( #&&$ & $ +'(  +;755775571 )::8747344  \]a`^XZZXZTSVOLLJOLDFGBG C@A?<;= [HWKTMaO\QaSaVbWdUgZbZeYk]m[n^k^pZV +     #)E'C.H.G+H/F,K,J+J, g'%(%)(%$'jEѹy=95843566~::;8354"53 Kd^l]m]oan_jZkZl]hXgVfUXU_T]N[ShOVMZG_ESFPIOEMBLEOBF@I?CD;A?D;>6IINNNLLRSVVYX\[`]W      ; AC D E E CFG ; $ +% %%($ % % $e B69895744  4<;893466#  +@]]^^Z]ZUXTVQOPMNLNIGFH@C@==@ ;:7 WHYIYM^L^P\NYOaV`SfTeXa^n]iYe[m]n\gD  +     (C-D,C,D-D*G*D.H*F& W'$$%$'& 'dK϶z(876857453N % 956875630 N[m\gZkak^nYkXcTbUfW_b^T]S^P`N_N^KXIZMNJRESAR?MAJ@I>GBF:8736325 655747321 QY[[[\[]UXSUNQPLPHNHIGCBA<A?==6= \NYHWKZJZKZPWR_PfWjQeYaUcXfTkVm[nZjO!     -A,A.C-G)G/D'C+G/F* +T($#&"$%'&] Tϳa-79:85535/6, 7; 969825-  ,VXlYo[o^n^cchXgWb[YZcO_P[P[PUMYJ_HUJWLVDOEJCMDFBG@I>E:E;I=A9?<:9HIGQMPOLNMU\UZSYVZ)      ,?ADE >>G F? !((#''$ +# +;=9;283446954574532 UY_[[\ZZTRQTRNLLKMKEBEC?C?>:<= :9QFWNRKVKYNXN\RsNcMePeUeScVfWcYi[jZiT5  +  +  '<*B(C)C*E1?)D(C-F) J)"#&'&!%%T WְG 487325332'!2 73877414! + A]YeXh]k[hVkWfZaUaTbT^OaRZPZMWJXKSIQHRJRGNHPCJBGBICF@D;D6?8=6IHHRMPNPNPSTWWWZYX:     + +     %> @ ;BCD B E?  $!# " +$!$#)<26762543 6945610.1  !YZY[XYWUQURTNOQNLJJCDBCCA@>< ;969\ISIRLTLZKUJYPaP]S^QcS_W_UiUkWjWgZgYH  +       */$0(8&7%9'6%:)=+! + :*$!#"(%$$T WΥ2 + 763561456 +4 6!6"023510 + -RcZnWn[nWcYhWeYhQ^S`P\Q[O\OVPUOTNVIVONFODSCl:OBHCK?E?E;E:E:@9<6?8GJILJLMPNUNSQV[YY[H      +  +        +lw "%%!:47664334 $76252122%  9V_Z ZYTVVTSOQMQOLGDGJJFC==A>8?863LGPFSHRKTNYJXO[OZO`OaT_R_UcVkWiViXjYS% *KEL?B757440./.--+ +!    + +  +   )/57#:,C1N2Y0Q"] f$m%k)w(},(k0-10/12,) + +EV_^g[iYf[eXeSg_jW\R_R[M[O_LWJXJ[JUAYKQEMGS@M@A=B>G@D;D=A8??:98 7PBTDRDUHWIUJXL[N]L_UaR`QhVcTdYfZbWhWc5 PI 0qQ@\fVjRkVdU_T^O^P\L4 ('0#+ ( )&!   +   +   +   + + +  'WSgVjZfUlXlXeSdSaRbO_QbQ]N[JZJYJWGMFRERFMCMCNAJ@K?F8H6CF>@>F8?;>:=5=7=7:4HDAKJGLIPPQRRSTUSZV"  768;@@;>:h$+,--..*-@c%g df ggi"e> +75 4797:75  +          +UXYZYRRUMNPNOJHKFEEAEB>><<>995 5 47 SDMDSDVJZJWLYJZN\O^N\P\S~OhU`VgQfYkVbO0 ybjK`ud{gyfwdsfsa|f}_E&98?7A9B8B9H9D;=5; !  + + +  +  $K^[iWnZeVjUdRcP[S[M[YNL^IZJVGTJWJPIQFJGIALAPAJ>D@?5?4:794G>EEDJHKOKOOSORSaUR8 + + i39:8>9:;=,$+..)--;cgcid `!d d!=:9576: 753   + +  + +     4TW[XWRQQPPNWJJIJFEEC@=>@<>89<5640 KCODUFSFTKUJVJULWH[L^LYLcP_R_RbS_UbRiSE ^řQh@Zwvdcu`{dq`sioezaC(>5?5B4@5B8@4>7B5; !   + +  ;SbVhXjXcTbV[X[SaP]QcP`NdHSGVKRJQILDLCLCLBJBE?@>H>F=<6E8@;>5>7?5=670FDCHDJHJLILMOMRSXPRH + +94<673=:C; +.,-..,,.8cg#`]dk+d`4666986981  +         +     GSVVUWXRMPRJKJKGFEGCB>?;=<6:9975 72QAOEPEQIQHRJRIWHXLVNWP\OsL`SdR`S^SfSfRT% + +>˯02D6;9D3D3B5>5>72 !    + +  + 'NT_TbReXbO^S`Q_P_T^Q[MZLZHTJSGQHMEKDKBLEGAJ=J=B=F=>=?9@:?8<7<7<6<4<4ADAEIBHEGJLMOLVQRUOM   '5983:8>< +y,)-),.,* +3!adb_]bcf1725 94 35 6% +   +   + +  + +  + + PRTSUSRLPMMMQEIEH?ADA>=><797 887 5 4 1 IGIAGANGTDPKTHOKWGVNUMVI^O`NaPgLcTbT^OY4 $hεH-t 6Us^ndwcw`s`sbp\q[7 -?4C3B7A5>5>3>7@3-  + + + + + + >\RfXbXbU`V_PXR[O]NWO\KXLhGYFOGMFNFNENBJAI@HAI=I:A6@8E5A8C8@5>5:3G@?DHCKIHFILQNKP!KTSQ 337769=;l&(&+)-))"$,\__Z`aY`. 65 3 635, 2#    + +       + +OSTRQPXPOKMFKJECEGDAC@=<88;87 3 8 44.S?S@JBLEPDQFRFRJRHQLXJTLTMXN_NdOiS^R_S\C A߲ܮ\{q&2QgXj[mZn[jYj]obqT,*;3=1<2<0>0=2>280(  +   + + + + 'J]RaQ_QbXxO^O^N]LXRUK]JSFNIQFOJQCMAMAKF;D:D5E7@8A9?6;5<3=/;5828.>J>DFBCHJGLNLOPKMRPM!  51625379 +`%+(')&(!!$)UXT][]WY)340/2. 01!         + +   + .SPOSPLQJIJLFDAHDDD>A><<:3 7=9635 1, 2 J?S@J@QBRGREPESBQIVJTLXKWMYOYJ\L_McN_Q^H*  $b_iz|\Tjuw{y}m- *JaXdVeThSiYi\iXgM.$:08/91;29/80639-#  + + + + +   + + =Q\OaO^PZN`OWP[J\LYDTJTIPHTFPHPDODODN?ICF@I@D>A:@9G:>:>7<795949281705.;?BCCDEGILHIKMIMJLNN0    +' #$(+2. *18;;BBE2978:BDD'+ *,.+0.    + +   +     AUOONQKOJGFIHJDDD@?><=::9 : 85566 2 4 3 0 J>NBJBM@NDN@KFQEPFQHSKVIUJXIYNeSiM^M`R]I?  *'%      "! +!$%  + +   + + + +$JKVM[Q]OYLZNYP\IZHXGUJSFRGRGPENAH?JCI=F?8A5>8@6=8:2;282:54/21;<A>=ECGIHGJJNGKKRRM>   ! &                   +       +   +      +    + + +     + JOONPHNNKMJGIDFEC??>@?:;8397522 2/ 1 -C9FAL=H=MDJBRAPCSHVIQKQFSLVJZJVM\NZL_MZKI$ +  +!,%$        +     $!$"    +          +  + +  6SNYNYK\P]NVNYNVJRGUJPFOAOCMGR=MDF?E>FAF=F;H;A7=;B8>6=6;5:27182509-3.7.><=BBBDCMFHIGJKKLNLMJ       +             +      + +    +   KMNMPSPGKIJDFAB<@@=<9 :<787 +595 221 / /- D;G;J@M@MBKAMCKCRDSFOGPITHSHUJYI\M[O^N_MW5$!"!!$ %! !!       + +   +      ! + + + + CXN^JYO]NXLZMWGXGRDNCUJPCSDL@N?QAO@F9=>@C@CADGDJFJHKLMNGB:><;>?:> ;;: 9:7754 44 3 +. )( ) & +& & +             + +      +   4KKNLJJIHIBHDC@?BB@=8=8888755 4 510 //)C=B:D=I>H?MBRDPDLANDSITFRHTHUJTLYLYHTO\JUIVENGRBPCTDTGRCPHVGUHUDSGOJRHWGZFXKTLUMTKVHWJTEUGREUFQFXHNFJ@IBF=A3GLJMKIJFJGDEEEDAAA@:><; 97 58 5703 10 /+ - , H8C;B>F=L@IANDPANCNCSENEOHTJUIWL[IWLZMVM]N]MXJYJTKTJ^LdOfKYI[JXKZLWMXJ[J[OXKYO`P^O[J\P\NfQcNeNaMaR_M]KcNbL[N[MWQaHaIZOTK]HYM]JSN[H\ITJWKYHTHQ=K>E:D?>86.7-0(1'+"%&#+BQHYG]JYNVKVJSHTKUIQGQBQHJHOBIAMCMBL?I;C=F>C;A6?9A6<5A6;8;4:0:55150713.5+5-:=@<@@GCEF?CHGKHGIHMNMQSPNKOOQNORRPRQRSRQQRO!VSPTOUOOQPSNOOMMQOLLOLMNLLFGJHGDE@@@@@@JFENJJFLFCGFFA@D?@@<= ;9789444 2 0 42 * 0, , DTALHPHQJXIXHTFWGUL`IXI\L]R[L\PdXyNaObMbScTpVeP`QaSaTaS`OaWeQgVdQbRgVpQfShRfT`QfRfSaWeQaSsOeRpPfNcSeUhScQ_QeR]P_P]U_Q`L^M]O`NWO\IXJWGTGSISGSERKOGRDTIVIUGTJZIVJSEWHSBQFRARCJDI=KDLBJ>H=H=G;C8=4=49684726.7/6-3/1,-.0'?<<>??=>DDFADHIDHGEVKIVSRQOOQTRYPRQUTVPROUUTTTTURTVQUPXSQRTRSTUQSRKTPPOTOQRPMNILKNGHHHIEFDBE@ADC@<A?@;9:68:56 6341/0 . 0. ,,G;F9ETAKAI@F@K=J@J>I;E7C=B8@5?6>6>3,6:37082833.4/7.3+0*0)698;=<>>?@E@CHEHDIIFS%550201*#%&'&"~wpogVUQTSTQRORRQOQNKSPPPORPPPQPUSNQKPMKMKHLIMGGHHFGDEED?F?C?=>;@; :: 7575535 1 2 2 0 + + - +* , +@8D:G:C=CF@IAKD9?:@6@5=7;8=5;6719180502.6,1*3).*,-**:77;:=??@BABDDECEGFV08,10311148657882262,/,.1)((%%*|ul`k`\\ZUSVSRTRSPPKLNLLLJKEEFHGDAADCA@?@:><=9: 5677 454/. 2 + .,- , +*'A:C4H>E>E;JAG;I>K?J?MBLCLFNBPGOEQFUIU\ܧ۰ޮީקעАË|q~`q[pZlTmRiSYHVGvGZGQGSBO@PBNDMEKEKBO?H>H?J?G?J=G>F;D;A6C8@8A8>9?8=5:581;091501-2*/*/..*/).%:58< 9?<==?BCC@ECCFk03/-153.63533:87-0-/2+0-.+-,-''/('%%'#)(')%,),.,.*)77575,/1&VZQIFHAGBHFDA?A?:>??87/7866 33 3 0 2 ,/ . + +-+) ) =9?:C8B9D;B=F@D>JC8@;D:A5B7>6@6@293;4;39381;05.5+/,.*1-/).%-&9768:=@<<?;BADFBC{60-030042/2213/3.+0//-,.1,*,-1+,,+)('')-/-,-1.-.(**(1851,110/30y3GFDDCF@A@?@==8;;8:6 88 666 2 33. 0 + .-. ) ,))@5C;@8?9C7K:A9C=JBI>O?KBODNCMDOEjε~ݙeIRCRFOCK@I@K=K@KAJ?DALAF=E:D:B9B8D5?9B9<7@2=38374:3B;DI 8+/5./.01.422...3/&)*.-%'+.(-23$)124-...,***+*)'(1*.,(336/.1131/1+qFEB?>B@@C@@?:=;964772242320/ +/ , ) + ++ & '@4>9<4A6E;>7C>D;KKEQIu󿻉JTDMAK@KBLDK?K=H?I=KBF=E=D9C:C;@8A6>7@9<7:4=69575645/1/5+000+-+**+*,((%.-47 79;4:<9<?AC@J#4.,..-).5/-2-..032*&-+)%/1,/0(0./112/-+/+,)/-1+%,)(+-),.2324224+.,.yEC<??>>=A<=@7<89 ;54416 3 +3 11 ++ - +0 / * ) (% , ;6=7A6A;>6?8B9F=C>F>E=HCNANPcRAN=RBL@L>F;I=E@G>C?E<@=A:@6?;>8@6@3<584;2<59.4421606-500)/,.+2'0)*'(-+*4 675 7;< <9?9A@X+1.+2...-/-/611/54.*%(&+*,*,,(.,).,,,+*+)+-++%),&-'+.,..+*622-3371+,2%WAD@=@>><=;<;7;978 6151 3 0 0 +- 1 +/ (* +( ) & ') ) +=6>6<8?3A8=;@:C:BOAJ@JAF@D?F,))(,.)-*)())*'&,*+.11)./3...3,+FBCB>:<?7:;97 53 6352014 - 4-2 , ++ +) & '&() 7217<6@7>7A7>:@;E9FXo¿rBI?IAH>GD:D;E8B9A8E:<6@5:6;1=5>1;084528/5.4.1+2,/.2)+(-%+%(%)++'(*433 357 9 :; 8C3)&('*,,4+,+*,3/,/-'"' ',,,)&+++(''.*,0+%)'+)**&(*)'('')-+&'/,613242/(,,-(C?> ?9<;=:9962 9 541/ 0 0 . 4- ) ) , , +(*& $ + . ( A4>883<4A6?:=7B;C:FBlչkX;J=K@J=E:E8E:@;B9C8@6@3>6<6;3<0:393404/5040212,3*.*,&.(,','#!+&,-'(1 22 38; 577D.)&#)%*+.++,**/-,,2(*!+,(%'&(#+')%!%%).-)'#*1+',(''*+.(*&))'#'43+10-0+*.4-3![>==979<=76;68 61+3 2 . - 3 +0) +( . % $'% , &(7/:/61<7A6D3@8A9@:yحǪOL8=5;1:38191;1742240/03-2(-,0(,$+'('+$(%*(,).(,+1122 +74 57E%+$'$)))+%*)&'.,*+-.,%$,(&)'''&()+&.&**$,(+.$-(+-(&-*,)(-&(,)))*,0*14104,/+-.+B ?<=2; :6976 7 141222/. - (' .)) ( & ! & %, '<4<2>1:3>8?4>8;R~sAD9E9@7;295;6=4:2;14052704,3/2+2*/+0'/&-&+&+$'&.(0+/)2)6 3344 78X0&"&'$( !((%%)',)*+''("'($'(('&'&'#)+&,)())&#+*++$&)%+,))"'%%'')(-132./-.+)*-..9:9:93 : 35117 +1. //1 , 1 ) / '( & & $ #% & ' ( + +<492825195=4FV۬߇c>E9G8@8=6=7@7?5=3;6:1>1;3:070506/3-0-1,/&+'-),%)&*'&")%*%('*)+)2 421 35Y%&&""#$ (,(%+%%+*$&$$'&$& )&(*%$&&$"$+)+(%)0,*'&&+)&'#&*(#"%&&#/())/)/,..+*(/-00)| 9858887456011 +01. .+, )) ) ( +) (" ) +) ' '( +>-64:3:4;5MhޙhS;L8A8>8<:;7B7<5:3817251705/6/4-3.1*6)3)0&,()#)*+&(%'%,&+'+).(-1/38j&$" $'%" %'%&&.)%#%,#$!"!##%%()"&'"%!"($!(#"''*'"%&&**%++)($$%))$$(&/)1--1-.-++%+* \:7 62958 225 03 /2 / ' +* ) ) ( +$) +'% & +% (% ( +92919185QuޙǰIE9D9?4@6>4<5;57283:2621.3,4,4.0-0)/)/'.*+()%+$)#(%&')*+)&**%/009v)'!%' "'+('%&&,''%*$&"'(&"&)%%'# %$"+&,!)&%$*")**%%%&'+&,'$'%''#(!(%&')+-+0-)-(-')(H 8466444241.1 + , , +(% &) %# " ( &)( * +) +306.7:f|åBF9?2@6>3=7@78292<08.6/6-3,0*0,/&-')&***$+%%!+()(-&0*/(,',). 09& ##!'%! &!$'&*-+%("!$$'!$%##$$/''()'))*)$*%#'++#%!#%''&!$%)%(%%&,$$((-+.-),(-'&*/+ =35 346 121 /.0/ + +, '( +('$ & +" ' +% ) & ' % & 7-8;nԚߓf:@4>3 3 12, , / * , ++ ) ) '% $ "! +& +'& & %$ % " +& ڛږףِӕܘv5:/4,3-5.1.0-/,1)1+0',+(%)%%" #''%(%+&*$'$&')"%#($ #!"!! $%!$(&!$#""!!#' !%!(!#!)'%%"'")('%##!!#$#$%%&$&/!$#(**+)+(&((*&)-(%!%$#%#20. , 00( ) *) ( ' ' # ! # +' +' ! '% % ' +%"ڕܙڔtX081803,0.2,2)0)/)1(0)' '%"$$)#$'*('#+&%"$%*#&$%% ! ""!!!$&!&%& !! $"!!$&$ !$%( $''($%$ #'"&!#'%%'# &$#'*$-& %$",& %$)(((**#$! "k-. - - , , +' ( $ & +# % +"#$$&$%' +$ & $ $ԒٖגқܧޙZE-3-6,3+/*.+,&.+.%-')&-56.&$%'%%*'$"'%%!"$*#*&'% # $ #!&#$%""($ !"'#&#!#$% # !'(  &$ #"$%$""$ ! %,&#$&$" "$%#$$#*.)'$!#"$#!!N/- , , ' ) & (+ 3 5 +2 (% % " # $  % ( "Ғ՜ٚךߞ졙A9)5+1.-(,-+*0-7*::@8?6975*%('&(%'"$$&"*('!&&!%% $%%"$!$##"! ! # ""!(!"! "#$(!"!'#!"%%&!!%! &&&( "!$! #'""& !'#$$"$$#"%#$6 , +, +0 -18778;8 7&# & +%% #! +%% ҕՕԒۖޝ֙؞q36040<7?>06A:;;<6:0.%&$%&'"* &"#"$$$%#%! " $%&!!$&"$$#  %!  !! !#!&#"  !" "!"#(##"$ %$#"$&')"%%'($$& ;<=;=<7;9974 3 $ +" +&! $$ +# !Ӓ͎ӏܓٝޖ}XAKA:>?=E;B;CC=@9@;A9@<97=6;7<5867-$"###*$&#$%$""$" "!!#!% # !$"$& $#! $!$! #"!"%!!"$# # *&"#$#)%" !&%$R@==;;:;9 566 7* % ! !!$ȊɋֈӒΒߝڛߗЉ܌ڢޘRLBF?A=?:A<<:>9?9;6;796=45)(#)%"$###%$"'! $!# !$ !#!! #" $ !$ #&!##%#%!$"& $'$!#"K?: =9 897: 76 3 0 +$$ "&%'! +ȇćÊNJ͒ԕߙߚܔיޜܑݎDE:F>D9C9A9B:<689:59264721%%"%$'#$!$"""!  !!   %  "" !! # " ##%"$#" !$*""C> : 9 9: 7 8 6 +53 32 +" "!"! +ȇĉ̏ˌ͈ʋˍюҐ՗ޓɈ؍ތ܍ܕܓۖ|fAK=F:A:<4859:93316/50) "%#!#$#&   """   "! %#  !( ""   "$$#"'"#" # s<> <=;677 3 3 2 . .  $" +ƐŠʌɍώҐ˔Б֑ޕؒۖޚڐӍޔڏޑܔ׏Ζg[;D681910350313-/..($! ~~z$! !!!  ! !! !o6 9864424 2 1 , ,##xx}ƊɅʑNJŁÄɅǁ҇ЃՁ̂ɉҋӍڑ؋ъχ҇؉ڌڍލۍݍّߑޗَэܑՑՑӒΒьĄȇDžbQ::9>7<64376513/704/1)2))" su~|~!!#  ! U 585 355 22 2- - ( lz}yǍ·‚ǀdžɄȅǃĄґЋ׌Ӏʇ͆̈ғێ؇׊ސݐލ׈Ԑىؒ݊ۉ݆ۏݑߒى܍Պߓ؋Ӎߋۋؓ݋ܙܖ؍ΌĊ̎·֒ѐՑːŊƆŅŃÇȈHE7;8;6559636534-0-0-)*+( _}~{}} }}!   Z =397 3 40 - /,- ,%r}}~~}|y~ʈʃƁÃňΊΊӄ˃{΁ȂӃ΂ʌ֌ڍʁÈωҋԖ܎׈ی߆߈ߑ؃͊ԅێܐߍܔ݋Ҏߎސߎ݉؊ߍՕږݚ֗ђψzy‰ωЍ̉Ɉʄƈńƃud=9:;4<2324/4-/00/-.,(-*($ +~upy|yyx~~#!!#!|&l95731 +1 2 -1 1+ +' ۉwsnvv~{uw{ʇƂDŽ~Æȇˁ|ֈˁɅφȇЈÉ҈΁Ӈӈ֐،ӎۈߏԍ݇܆Հ҇҅Ԅ؇ݎݎ݊ߏ܉ܓۑًދڏޑՑޙܕ֑ڐۏۊ؈ߐߊӉޏׇٕ̓֗ӖӔээΈƊȃ€DžÈʈ…]I6;4416.00/112-,---*'(&$#{wym_rm}}usx~!}{ }O +7 -51110 ) ) +% ( $ ircWs\w{}vux{v|y͋Ʉ̀̀ƀłƒɃˁυ҇҅яɋψ܋چĉЁՃЅ҅̀ͅ؈քԈيۊޅ߆؈׎׌׎Ԑވݐڈ׃҆ӅȄ֐באԏΈъԊԆ̃Ӌԇч́̋ωВχό͌̇ɐхdžɆxÁƒ{|}w~J?36381202/0.-*-*-'($*%$!_o[cdy}w}rwtrs}yz{{}{}~{|y}|zxy}r? 6 12 , - . (* %& %|`bcj}{~{puvqow{z}}zz|{zyŁ}~{Žҍ΍ӂӉև̃ҋ։΁ʀĀ̈́ՅЃˉ҂ЇЈԐՊ։؃ʃ׋ڏՏممӋ҈ϋՋҏԌҎΎχΌҐЍӆɇψʇńÇ͈ˀ͊ъȊÇĈÆÈƁ{~~wzvy{oa3?22/.01////-,((%&&##!SZYis|yyyutvsprw{{xxx}vy~~!{!zyzxy{xf 5 0, 1 /*( ( '%!{\|`jm~y|xrtstsq|y|~xzy{}|zɃʆȍэІчԊDŽͅΆ|ʅ؆ԃ̂†̍˃΅ƁӁDžԋ҆ԍՊ׊σ˄Ԉʀ̃Ӈσ΋ԇŁԏЅ̓ϊτŅʀǀ~DŽ̊ɃɇςȈ|Ʉ~̇ŃłɉĊņƉ‰~{{{~|wxwr^M430110/+-,)(%.)%%$"$cjiruzvrrsqtspt|uxx~~{}}{zzy}{}x}} z}y}y|v~{||vusqU0 .. +* - *)"# kkjuvvtrorprtpv{uzyy{|zuq}zxÂ~~wxLJʃЁ{̅̆ȇʁÂĀȆʆфΉ҆ы׌ЉՌш̓Ѐʆ͂̃φӋڏԈȀ~χÀʀĄDžDžƆ΄ÇÄyĉ}~yw}zrxxxysqtnyH<-2/0*+),+)%*!$"##kiimvsuqrnp|xprsu{x|vy~{ru~w||xwy|}y~}z~}|y~~ |}{}}zzu|zxvxvrunqm? +. 1-%& &! ijhnstzpqqsuqtpspxvpw{xuw|zz~Ā~}}ȀЇԉlj҅΃z~΅ˀˌӐֈυǃƄă͂΀ˈՅˇ}}ĂuÅΈ΃ʁ΂}|ɁĀ{}z}{|zxz~vttwuwjnqeY71,+-))-'(&(!"$ %ggcirsuoemlovkosroupswtur{x{vq|y~~z||}~|~  ~}}x}}~}|||||yz}yyx{}xxvttztpulm[0 .'' '## "bbhhjpldeoqmnqqqmortuwyuwk}qnww}{}~z}ƀ|}xyw~z}}~ȇ҄ςˁȀǀʆzˇ|~ƃ|zx~~}zŃz|zx}z{yxrxvpzowlxtnlpimP<-,%,*&$&!#%!! "^hjlkjk hg `sohmhnqproqp{|tpxz}z"pzzzxzzxvrwt|wzwtzvzwzxy~{z~xsz~|w}}~{z"x{zyqxlxopmosngiehbA , +'*! #  \ No newline at end of file diff --git a/examples/peripherals/isp/dma_input/main/isp_dma_main.c b/examples/peripherals/isp/dma_input/main/isp_dma_main.c index 111b3fd71cc..4460e7502ac 100644 --- a/examples/peripherals/isp/dma_input/main/isp_dma_main.c +++ b/examples/peripherals/isp/dma_input/main/isp_dma_main.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -19,42 +19,15 @@ #include "driver/isp_core.h" #include "driver/isp_color.h" -#define EXAMPLE_WIDTH 128 -#define EXAMPLE_HEIGHT 96 +#define EXAMPLE_WIDTH 240 +#define EXAMPLE_HEIGHT 280 #define EXAMPLE_BASE64_CHUNK_LEN 384 +#define EXAMPLE_BASE64_DELAY_MS 10 #define EXAMPLE_DMA_ALIGN 64 -#define EXAMPLE_FRAME_COUNT 2 +#define EXAMPLE_FRAME_COUNT 1 -static const uint8_t s_color_bars[8][3] = { - {255, 255, 255}, // white - {255, 255, 0}, // yellow - { 0, 255, 255}, // cyan - { 0, 255, 0}, // green - {255, 0, 255}, // magenta - {255, 0, 0}, // red - { 0, 0, 255}, // blue - { 0, 0, 0}, // black -}; - -static void s_generate_raw8_color_bars(uint8_t *raw, uint32_t w, uint32_t h) -{ - for (uint32_t y = 0; y < h; y++) { - bool even_row = ((y & 1) == 0); - for (uint32_t x = 0; x < w; x++) { - uint32_t bar = (x * 8) / w; - uint8_t r = s_color_bars[bar][0]; - uint8_t g = s_color_bars[bar][1]; - uint8_t b = s_color_bars[bar][2]; - - bool even_col = ((x & 1) == 0); - if (even_row) { - raw[y * w + x] = even_col ? b : g; - } else { - raw[y * w + x] = even_col ? g : r; - } - } - } -} +extern const uint8_t sensor_raw_start[] asm("_binary_sensor_raw_start"); +extern const uint8_t sensor_raw_end[] asm("_binary_sensor_raw_end"); static void *s_alloc_dma_buffer(size_t size) { @@ -86,7 +59,7 @@ static void s_print_base64_payload(const unsigned char *encoded, size_t encoded_ } printf("IMAGE_BASE64 %.*s\n", (int)chunk_len, (const char *)&encoded[offset]); fflush(stdout); - vTaskDelay(pdMS_TO_TICKS(1)); + vTaskDelay(pdMS_TO_TICKS(EXAMPLE_BASE64_DELAY_MS)); } printf("IMAGE_BASE64_END\n"); fflush(stdout); @@ -120,6 +93,10 @@ void app_main(void) uint8_t *isp_out_buf = s_alloc_dma_buffer(out_size); assert(isp_in_buf && isp_out_buf); + size_t embedded_raw_size = sensor_raw_end - sensor_raw_start; + assert(embedded_raw_size == in_size); + memcpy(isp_in_buf, sensor_raw_start, embedded_raw_size); + size_t encoded_len = 0; int ret = mbedtls_base64_encode(NULL, 0, &encoded_len, isp_out_buf, out_size); ESP_ERROR_CHECK((ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) ? ESP_OK : ESP_FAIL); @@ -128,8 +105,6 @@ void app_main(void) printf("Feeding %d frames through ISP DMA input...\n", EXAMPLE_FRAME_COUNT); for (int frame = 0; frame < EXAMPLE_FRAME_COUNT; frame++) { - s_generate_raw8_color_bars(isp_in_buf, h_res, v_res); - ESP_ERROR_CHECK(esp_cache_msync(isp_in_buf, in_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M)); ESP_ERROR_CHECK(esp_isp_dma_process_frame(isp_proc, isp_out_buf, isp_in_buf, 1000)); ESP_ERROR_CHECK(esp_cache_msync(isp_out_buf, out_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C)); diff --git a/examples/peripherals/isp/dma_input/pytest_isp_dma_input.py b/examples/peripherals/isp/dma_input/pytest_isp_dma_input.py index 393b040cf0a..e5603445560 100644 --- a/examples/peripherals/isp/dma_input/pytest_isp_dma_input.py +++ b/examples/peripherals/isp/dma_input/pytest_isp_dma_input.py @@ -22,19 +22,9 @@ IMAGE_CHUNK_PATTERN = ( r'(?=\r?\n|IMAGE_BASE64|IMAGE_BASE64_END|Frame )' ) IMAGE_OUTPUT_TEMPLATE = 'isp_dma_input_frame{frame:02d}.ppm' -REFERENCE_IMAGE_NAME = 'reference.ppm' +REFERENCE_IMAGE_PATH = Path(__file__).parent / 'golden' / 'golden.ppm' EXPECTED_PIXEL_FORMAT = 'BGR24' EXPECTED_ENCODING = 'base64' -STANDARD_COLOR_BARS_RGB888 = ( - (255, 255, 255), # white - (255, 255, 0), # yellow - (0, 255, 255), # cyan - (0, 255, 0), # green - (255, 0, 255), # magenta - (255, 0, 0), # red - (0, 0, 255), # blue - (0, 0, 0), # black -) RGB888_BYTES_PER_PIXEL = 3 PPM_MAGIC = b'P6' PPM_MAX_VALUE = b'255' @@ -112,17 +102,6 @@ def decode_bgr24_base64_image(metadata: ImageMetadata, payload_lines: list[str]) return RgbImage(width=metadata.width, height=metadata.height, pixels_rgb888=_bgr24_to_rgb888(raw_bytes)) -def generate_standard_color_bar_image(width: int, height: int) -> RgbImage: - pixels = bytearray(width * height * RGB888_BYTES_PER_PIXEL) - for y in range(height): - for x in range(width): - bar_index = (x * len(STANDARD_COLOR_BARS_RGB888)) // width - offset = (y * width + x) * RGB888_BYTES_PER_PIXEL - pixels[offset : offset + RGB888_BYTES_PER_PIXEL] = STANDARD_COLOR_BARS_RGB888[bar_index] - - return RgbImage(width=width, height=height, pixels_rgb888=bytes(pixels)) - - def save_ppm_artifact(image: RgbImage, output_path: Path) -> None: output_path.parent.mkdir(parents=True, exist_ok=True) try: @@ -134,14 +113,45 @@ def save_ppm_artifact(image: RgbImage, output_path: Path) -> None: logging.info('Saved ISP DMA artifact to %s', output_path) -def assert_image_is_meaningful(image: RgbImage) -> None: - distinct_pixels = {image.pixels_rgb888[i : i + 3] for i in range(0, len(image.pixels_rgb888), 3)} - assert len(distinct_pixels) > 1, 'ISP output is a single flat color; the pipeline likely produced no real data' +def load_ppm_image(image_path: Path) -> RgbImage: + ppm_data = image_path.read_bytes() + try: + magic, dimensions, max_value, pixels_rgb888 = ppm_data.split(b'\n', 3) + width, height = (int(value) for value in dimensions.split()) + except ValueError as error: + raise ValueError(f'Invalid PPM image: {image_path}') from error + + if magic != PPM_MAGIC or max_value != PPM_MAX_VALUE: + raise ValueError(f'Unsupported PPM image: {image_path}') + + return RgbImage(width=width, height=height, pixels_rgb888=pixels_rgb888) + + +def assert_image_matches_reference(result_image: RgbImage, reference_image: RgbImage) -> None: + assert (result_image.width, result_image.height) == (reference_image.width, reference_image.height), ( + f'ISP output dimensions do not match reference image: ' + f'{result_image.width}x{result_image.height} != {reference_image.width}x{reference_image.height}' + ) + + if result_image.pixels_rgb888 == reference_image.pixels_rgb888: + return + + mismatch_offset = next( + offset + for offset, (actual, expected) in enumerate(zip(result_image.pixels_rgb888, reference_image.pixels_rgb888)) + if actual != expected + ) + pixel_index, channel = divmod(mismatch_offset, RGB888_BYTES_PER_PIXEL) + raise AssertionError( + f'ISP output does not match reference image at pixel {pixel_index}, channel {channel}: ' + f'{result_image.pixels_rgb888[mismatch_offset]} != {reference_image.pixels_rgb888[mismatch_offset]}' + ) @pytest.mark.generic @idf_parametrize('target', soc_filtered_targets('SOC_ISP_SUPPORTED == 1'), indirect=['target']) def test_isp_dma_input_example(dut: Dut) -> None: + reference_image = load_ppm_image(REFERENCE_IMAGE_PATH) frame_count_match = dut.expect(r'Feeding (?P\d+) frames through ISP DMA input...') expected_frame_count = int(frame_count_match.group('frame_count').decode('utf-8')) logging.info('Expecting %d ISP DMA frame(s)', expected_frame_count) @@ -156,10 +166,6 @@ def test_isp_dma_input_example(dut: Dut) -> None: metadata.height, metadata.pixel_format, ) - if expected_frame == 0: - reference_image = generate_standard_color_bar_image(metadata.width, metadata.height) - save_ppm_artifact(reference_image, Path(dut.logdir) / REFERENCE_IMAGE_NAME) - dut.expect_exact('IMAGE_BASE64_BEGIN') logging.info('Receiving base64 image payload for frame %d', metadata.frame) payload_lines = collect_base64_payload(dut) @@ -169,7 +175,7 @@ def test_isp_dma_input_example(dut: Dut) -> None: logging.info('Decoded frame %d to RGB888 image', metadata.frame) output_path = Path(dut.logdir) / IMAGE_OUTPUT_TEMPLATE.format(frame=metadata.frame) save_ppm_artifact(result_image, output_path) - assert_image_is_meaningful(result_image) + assert_image_matches_reference(result_image, reference_image) dut.expect_exact(f'Frame {expected_frame} done') dut.expect_exact('ISP DMA visual demo done.') From 3e162786cb1dfb0c042c7108d64a7efa5ab3e10a Mon Sep 17 00:00:00 2001 From: morris Date: Mon, 20 Jul 2026 12:44:18 +0800 Subject: [PATCH 3/4] feat(build): support aligned embedded binary data Allow callers to align embedded binary start symbols for DMA-capable assets. --- docs/en/api-guides/build-system.rst | 4 ++++ docs/zh_CN/api-guides/build-system.rst | 4 ++++ .../cmakev2/get-started/hello_world/README.md | 2 +- tools/cmake/scripts/data_file_embed_asm.cmake | 3 +++ tools/cmake/utilities.cmake | 18 +++++++++++++-- tools/cmakev2/utilities.cmake | 23 +++++++++++++++++-- 6 files changed, 49 insertions(+), 5 deletions(-) diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index ac57d66a3e9..3f10f099fc2 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -996,6 +996,10 @@ To embed a file into a project, rather than a component, you can call the functi Place this line after the ``project()`` line in your project CMakeLists.txt file. Replace ``myproject.elf`` with your project name. The final argument can be ``TEXT`` to embed a null-terminated string, or ``BINARY`` to embed the content as-is. +Use the optional ``ALIGN`` argument to align the embedded data's start symbol to a positive power of two. For example, to align binary data to 16 bytes:: + + target_add_binary_data(myproject.elf "main/data.bin" BINARY ALIGN 16) + For an example of using this technique, see the "main" component of the file_serving example :example_file:`protocols/http_server/file_serving/main/CMakeLists.txt` - two files are loaded at build time and linked into the firmware. .. highlight:: cmake diff --git a/docs/zh_CN/api-guides/build-system.rst b/docs/zh_CN/api-guides/build-system.rst index b3f72737849..9e4c577ca67 100644 --- a/docs/zh_CN/api-guides/build-system.rst +++ b/docs/zh_CN/api-guides/build-system.rst @@ -996,6 +996,10 @@ CMake 文件可以使用 ``IDF_TARGET`` 变量来获取当前的硬件目标。 并将这行代码放在项目 CMakeLists.txt 的 ``project()`` 命令之后,修改 ``myproject.elf`` 为你自己的项目名。如果最后一个参数是 ``TEXT``,那么构建系统会嵌入以 null 结尾的字符串,如果最后一个参数被设置为 ``BINARY``,则将文件内容按照原样嵌入。 +可选的 ``ALIGN`` 参数用于将嵌入数据的起始符号对齐到指定的正整数 2 的幂。例如,将二进制数据按 16 字节对齐:: + + target_add_binary_data(myproject.elf "main/data.bin" BINARY ALIGN 16) + 有关使用此技术的示例,请查看 file_serving 示例 :example_file:`protocols/http_server/file_serving/main/CMakeLists.txt` 中的 main 组件,两个文件会在编译时加载并链接到固件中。 .. highlight:: cmake diff --git a/examples/build_system/cmakev2/get-started/hello_world/README.md b/examples/build_system/cmakev2/get-started/hello_world/README.md index 63693a0cbf2..16366d1fb98 100644 --- a/examples/build_system/cmakev2/get-started/hello_world/README.md +++ b/examples/build_system/cmakev2/get-started/hello_world/README.md @@ -34,7 +34,7 @@ Below is short explanation of remaining files in the project folder. └── README.md This is the file you are currently reading ``` -For more information on structure and contents of ESP-IDF projects, please refer to Section [Build System v2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system-v2.html) of the ESP-IDF Programming Guide. +For more information on structure and contents of ESP-IDF projects, please refer to Section [Build System v2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system-v2/index.html) of the ESP-IDF Programming Guide. ## Troubleshooting diff --git a/tools/cmake/scripts/data_file_embed_asm.cmake b/tools/cmake/scripts/data_file_embed_asm.cmake index 5d19e7a1ba9..b8612976894 100644 --- a/tools/cmake/scripts/data_file_embed_asm.cmake +++ b/tools/cmake/scripts/data_file_embed_asm.cmake @@ -74,6 +74,9 @@ append_line(".data") append_line("#if !defined (__APPLE__) && !defined (__linux__)") append_line(".section .rodata.embedded") append_line("#endif") +if(DEFINED DATA_ALIGNMENT) + append_line(".balign ${DATA_ALIGNMENT}") +endif() make_and_append_identifier("${varname}") make_and_append_identifier("_binary_${varname}_start" "for objcopy compatibility") append("${data}") diff --git a/tools/cmake/utilities.cmake b/tools/cmake/utilities.cmake index 4580c30e2a9..4b78dff163f 100644 --- a/tools/cmake/utilities.cmake +++ b/tools/cmake/utilities.cmake @@ -103,9 +103,10 @@ endfunction() # target_add_binary_data adds binary data into the built target, # by converting it to a generated source file which is then compiled -# to a binary object as part of the build +# to a binary object as part of the build. ALIGN optionally sets the +# alignment of the embedded data's start symbol. function(target_add_binary_data target embed_file embed_type) - cmake_parse_arguments(_ "" "RENAME_TO" "DEPENDS" ${ARGN}) + cmake_parse_arguments(_ "" "RENAME_TO;ALIGN" "DEPENDS" ${ARGN}) idf_build_get_property(build_dir BUILD_DIR) idf_build_get_property(idf_path IDF_PATH) @@ -119,11 +120,24 @@ function(target_add_binary_data target embed_file embed_type) set(rename_to_arg -D "VARIABLE_BASENAME=${__RENAME_TO}") endif() + set(align_arg) + if(DEFINED __ALIGN) + if(NOT __ALIGN MATCHES "^[1-9][0-9]*$") + message(FATAL_ERROR "ALIGN must be a positive integer") + endif() + math(EXPR alignment_mask "${__ALIGN} & (${__ALIGN} - 1)") + if(NOT alignment_mask EQUAL 0) + message(FATAL_ERROR "ALIGN must be a power of two") + endif() + set(align_arg -D "DATA_ALIGNMENT=${__ALIGN}") + endif() + add_custom_command(OUTPUT "${embed_srcfile}" COMMAND "${CMAKE_COMMAND}" -D "DATA_FILE=${embed_file}" -D "SOURCE_FILE=${embed_srcfile}" ${rename_to_arg} + ${align_arg} -D "FILE_TYPE=${embed_type}" -P "${idf_path}/tools/cmake/scripts/data_file_embed_asm.cmake" MAIN_DEPENDENCY "${embed_file}" diff --git a/tools/cmakev2/utilities.cmake b/tools/cmakev2/utilities.cmake index 4e2a7c5fabf..5fb245466dc 100644 --- a/tools/cmakev2/utilities.cmake +++ b/tools/cmakev2/utilities.cmake @@ -829,7 +829,8 @@ endfunction() #[[ target_add_binary_data( - [RENAME_TO ]) + [RENAME_TO ] + [ALIGN ] [DEPENDS ...]) *target[in]* @@ -849,6 +850,11 @@ endfunction() Use the given symbol name for the embedded data. If no symbol name is provided, the embed_file file name will be used instead. + *ALIGN[in,opt]* + + Align the embedded data's start symbol to the given positive power + of two. + *DEPENDS[in,opt]* List of additional dependencies for the generated file containing @@ -859,7 +865,7 @@ endfunction() build process. #]] function(target_add_binary_data target embed_file embed_type) - cmake_parse_arguments(_ "" "RENAME_TO" "DEPENDS" ${ARGN}) + cmake_parse_arguments(_ "" "RENAME_TO;ALIGN" "DEPENDS" ${ARGN}) idf_build_get_property(build_dir BUILD_DIR) # In cmakev1, the executable target was named "${project}.elf". @@ -884,11 +890,24 @@ function(target_add_binary_data target embed_file embed_type) set(rename_to_arg -D "VARIABLE_BASENAME=${__RENAME_TO}") endif() + set(align_arg) + if(DEFINED __ALIGN) + if(NOT __ALIGN MATCHES "^[1-9][0-9]*$") + message(FATAL_ERROR "ALIGN must be a positive integer") + endif() + math(EXPR alignment_mask "${__ALIGN} & (${__ALIGN} - 1)") + if(NOT alignment_mask EQUAL 0) + message(FATAL_ERROR "ALIGN must be a power of two") + endif() + set(align_arg -D "DATA_ALIGNMENT=${__ALIGN}") + endif() + add_custom_command(OUTPUT "${embed_srcfile}" COMMAND "${CMAKE_COMMAND}" -D "DATA_FILE=${embed_file}" -D "SOURCE_FILE=${embed_srcfile}" ${rename_to_arg} + ${align_arg} -D "FILE_TYPE=${embed_type}" -P "${idf_path}/tools/cmake/scripts/data_file_embed_asm.cmake" MAIN_DEPENDENCY "${embed_file}" From 8163ee0de81d2ccc23268ab2dfb06dfd883de467 Mon Sep 17 00:00:00 2001 From: morris Date: Mon, 20 Jul 2026 12:44:18 +0800 Subject: [PATCH 4/4] refactor(isp): read DMA input directly from flash Avoid the PSRAM copy for unencrypted flash --- .../esp_driver_isp/include/driver/isp_dma.h | 13 ++--- components/esp_driver_isp/src/isp_dma.c | 27 +++++++++++ docs/en/api-reference/peripherals/isp.rst | 2 +- docs/zh_CN/api-reference/peripherals/isp.rst | 2 +- .../dma/async_color_convert/README.md | 10 ++++ examples/peripherals/isp/dma_input/README.md | 17 +++---- .../isp/dma_input/main/CMakeLists.txt | 4 +- ...{isp_dma_main.c => isp_dma_example_main.c} | 48 ++++++++----------- .../peripherals/jpeg/jpeg_decode/README.md | 3 +- .../peripherals/jpeg/jpeg_encode/README.md | 3 +- 10 files changed, 77 insertions(+), 52 deletions(-) rename examples/peripherals/isp/dma_input/main/{isp_dma_main.c => isp_dma_example_main.c} (75%) diff --git a/components/esp_driver_isp/include/driver/isp_dma.h b/components/esp_driver_isp/include/driver/isp_dma.h index 7bb2cc8585d..adaeb52bd6a 100644 --- a/components/esp_driver_isp/include/driver/isp_dma.h +++ b/components/esp_driver_isp/include/driver/isp_dma.h @@ -17,14 +17,15 @@ extern "C" { /** * @brief Process one ISP DMA frame: feed the input buffer through the ISP and wait for completion * - * @note Input buffer content should be ready before calling this function. If the buffers are in - * cacheable memory, the caller should synchronize them around DMA access. Buffer sizes are - * derived from the ISP processor resolution and pixel formats. Both buffers must be 8-byte - * aligned. This function blocks until both input and output DMA channels finish. + * @note The driver synchronizes cacheable buffers before and after DMA access. Input buffers use + * an unaligned cache write-back, while cacheable output buffers and their derived frame + * sizes must be aligned to the cache line size. + * @note This function blocks until both input and output DMA channels finish. On timeout, + * the output buffer may still be owned by DMA and must not be accessed. * * @param[in] proc Processor handle - * @param[in] output_buffer Destination buffer for ISP output (8-byte aligned) - * @param[in] input_buffer Source input buffer for RAW frame data (8-byte aligned) + * @param[in] output_buffer Destination buffer for ISP output + * @param[in] input_buffer Source input buffer for RAW frame data * @param[in] timeout_ms Timeout in milliseconds for waiting transfer completion * * @return diff --git a/components/esp_driver_isp/src/isp_dma.c b/components/esp_driver_isp/src/isp_dma.c index a22bed0863a..83cecbf2743 100644 --- a/components/esp_driver_isp/src/isp_dma.c +++ b/components/esp_driver_isp/src/isp_dma.c @@ -9,6 +9,7 @@ #include "sdkconfig.h" #include "esp_log.h" #include "esp_check.h" +#include "esp_cache.h" #include "esp_heap_caps.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" @@ -56,6 +57,17 @@ static dw_gdma_burst_items_t s_isp_dma_burst_len_to_items(uint32_t burst_len) } } +static esp_err_t s_isp_dma_sync_cacheable_buffer(void *buffer, size_t size, int flags, const char *buffer_name) +{ + size_t cache_line_size = esp_cache_get_line_size_by_addr(buffer); + if (cache_line_size == 0) { + return ESP_OK; + } + + ESP_RETURN_ON_ERROR(esp_cache_msync(buffer, size, flags), TAG, "sync %s buffer cache failed", buffer_name); + return ESP_OK; +} + static void s_isp_dma_frame_ctx_destroy(struct esp_isp_dma_frame_ctx_t *ctx) { if (!ctx) { @@ -243,6 +255,21 @@ esp_err_t esp_isp_dma_process_frame(isp_proc_handle_t proc, void *output_buffer, ESP_RETURN_ON_FALSE((((uintptr_t)input_buffer) % 8) == 0, ESP_ERR_INVALID_ARG, TAG, "input buffer not 8-byte aligned"); esp_isp_dma_frame_ctx_t *ctx = proc->dma_frame_ctx; + size_t input_frame_size = ctx->input_frame_size_64bit * sizeof(uint64_t); + size_t output_frame_size = ctx->output_frame_size_64bit * sizeof(uint64_t); + + ESP_RETURN_ON_ERROR(s_isp_dma_sync_cacheable_buffer((void *)input_buffer, input_frame_size, + ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED, + "input"), + TAG, "sync input buffer cache failed"); + /* + * Discard dirty CPU cache lines before DMA writes the frame. Otherwise a + * later cache write-back could overwrite data produced by the ISP. + */ + ESP_RETURN_ON_ERROR(s_isp_dma_sync_cacheable_buffer(output_buffer, output_frame_size, + ESP_CACHE_MSYNC_FLAG_DIR_M2C, "output"), + TAG, "sync output buffer cache failed"); + ctx->dma_out_trans.dst.addr = (uint32_t)output_buffer; ctx->dma_in_trans.src.addr = (uint32_t)input_buffer; diff --git a/docs/en/api-reference/peripherals/isp.rst b/docs/en/api-reference/peripherals/isp.rst index da3478ff5b8..3ef72afeb37 100644 --- a/docs/en/api-reference/peripherals/isp.rst +++ b/docs/en/api-reference/peripherals/isp.rst @@ -248,7 +248,7 @@ ISP DMA Input Besides image streams from camera controllers, the ISP can also read image frames from system memory through DW-GDMA. To use DMA input, set :cpp:member:`esp_isp_processor_cfg_t::input_data_source` in :cpp:type:`esp_isp_processor_cfg_t` to :cpp:enumerator:`ISP_INPUT_DATA_SOURCE_DWGDMA`, and configure the input format, output format, and resolution according to the image frame. -DMA input is useful for feeding software-generated data, offline RAW images, or other test images in memory into the ISP. It can be used to validate an ISP pipeline without a camera sensor, reproduce issues with a specific input image. Call :cpp:func:`esp_isp_dma_process_frame` to send one input buffer to the ISP and write the processed image into an output buffer. The input and output buffers must be accessible by DMA; if cacheable memory is used, perform the required cache synchronization before and after the DMA transfer. +DMA input is useful for feeding software-generated data, offline RAW images, or other test images in memory into the ISP. It can be used to validate an ISP pipeline without a camera sensor, reproduce issues with a specific input image. Call :cpp:func:`esp_isp_dma_process_frame` to send one input buffer to the ISP and write the processed image into an output buffer. The input and output buffers must be accessible by DMA. The driver synchronizes cacheable buffers automatically. Input buffers use an unaligned cache write-back; cacheable output buffer addresses and their derived frame sizes must be aligned to the cache line size. ISP AF Controller ~~~~~~~~~~~~~~~~~ diff --git a/docs/zh_CN/api-reference/peripherals/isp.rst b/docs/zh_CN/api-reference/peripherals/isp.rst index e42060cf39e..d355f117ac7 100644 --- a/docs/zh_CN/api-reference/peripherals/isp.rst +++ b/docs/zh_CN/api-reference/peripherals/isp.rst @@ -248,7 +248,7 @@ ISP DMA 输入 除来自摄像头控制器的数据流外,ISP 还可以通过 DW-GDMA 从系统存储中读取图像帧作为输入。使用 DMA 输入时,应在 :cpp:type:`esp_isp_processor_cfg_t` 中将 :cpp:member:`esp_isp_processor_cfg_t::input_data_source` 配置为 :cpp:enumerator:`ISP_INPUT_DATA_SOURCE_DWGDMA`,并根据输入图像格式设置输入、输出格式及分辨率。 -DMA 输入适用于将软件生成的数据、离线保存的 RAW 图像或其他内存中的测试图像送入 ISP 进行处理。它可用于无摄像头传感器参与时验证 ISP 流水线、复现特定输入图像的问题。调用 :cpp:func:`esp_isp_dma_process_frame` 可以将一帧输入缓冲区送入 ISP,并将处理后的图像写入输出缓冲区。输入和输出缓冲区需要满足 DMA 访问要求;若使用带 cache 的内存,请在 DMA 传输前后执行必要的 cache 同步。 +DMA 输入适用于将软件生成的数据、离线保存的 RAW 图像或其他内存中的测试图像送入 ISP 进行处理。它可用于无摄像头传感器参与时验证 ISP 流水线、复现特定输入图像的问题。调用 :cpp:func:`esp_isp_dma_process_frame` 可以将一帧输入缓冲区送入 ISP,并将处理后的图像写入输出缓冲区。输入和输出缓冲区需要满足 DMA 访问要求。驱动会自动同步带 cache 的缓冲区:输入使用允许未对齐的 cache writeback;带 cache 的输出地址及其派生帧大小必须按 cache line 大小对齐。 ISP AF 控制器 ~~~~~~~~~~~~~ diff --git a/examples/peripherals/dma/async_color_convert/README.md b/examples/peripherals/dma/async_color_convert/README.md index 77efb5f5dc2..1f73d026889 100644 --- a/examples/peripherals/dma/async_color_convert/README.md +++ b/examples/peripherals/dma/async_color_convert/README.md @@ -52,6 +52,16 @@ The accompanying pytest script captures the `IMAGE_META` and `IMAGE_BASE64` outp It also compares the generated result with `golden_result.ppm` by hashing the decoded RGB pixel content. This turns the example into a regression test as well as a visual demo: the image must both render correctly for a human and match the stored golden output for CI. +### Viewing The Result Locally + +Build and flash the example for your target, then run the pytest script from this example's directory: + +```bash +pytest pytest_async_color_convert.py --target esp32p4 --port PORT +``` + +Replace `esp32p4` with another supported target and `PORT` with the board's serial device. Pytest prints the artifact directory after the test completes; open `async_color_convert_result.ppm` from that directory with a PPM-compatible image viewer. + ## Replacing The Embedded UYVY Asset The example embeds `main/assets/sample_96x64_uyvy.yuv`. diff --git a/examples/peripherals/isp/dma_input/README.md b/examples/peripherals/isp/dma_input/README.md index b554725300c..149af62f193 100644 --- a/examples/peripherals/isp/dma_input/README.md +++ b/examples/peripherals/isp/dma_input/README.md @@ -5,19 +5,18 @@ ## Overview -This example embeds a 240 x 280 RAW8 Bayer image of a real scene in flash, copies it into a DMA-capable PSRAM input buffer, feeds it into the ISP through DW-GDMA, and prints the RGB888 output as base64. The pytest script decodes the output into a PPM image and compares it with the checked-in golden image. +This example embeds a 240 x 280 RAW8 Bayer image of a real scene in flash, feeds it directly into the ISP through DW-GDMA, and prints the RGB888 output as base64. The ISP driver synchronizes the DMA buffers' cache automatically. The pytest script decodes the output into a PPM image and compares it with the checked-in golden image. The data flow is: -1. The embedded BGGR RAW8 image is copied from flash into the ISP DMA input buffer. -2. The image is transferred into the ISP via `DW-GDMA → ISP DMA input`. -3. The ISP processes the data (demosaic, color adjustment) and outputs RGB888 (BGR24 byte layout). -4. The RGB888 frame is base64-encoded and printed with machine-parseable markers. -5. pytest decodes the payload, swaps BGR→RGB, saves one PPM file per frame, and compares it with the golden image. +1. The embedded 16-byte-aligned BGGR RAW8 image is transferred from mapped flash into the ISP via `DW-GDMA → ISP DMA input`. +2. The ISP processes the data (demosaic, color adjustment) and outputs RGB888 (BGR24 byte layout). +3. The RGB888 frame is base64-encoded and printed with machine-parseable markers. +4. pytest decodes the payload, swaps BGR→RGB, saves one PPM file per frame, and compares it with the golden image. ## Hardware Required -- An ESP32-P4 devkit with PSRAM (this example allocates the ISP DMA input/output buffers from PSRAM). +- An ESP32-P4 devkit with PSRAM (this example allocates the ISP output buffer from PSRAM). ## How to Use @@ -43,7 +42,3 @@ IMAGE_BASE64_END Frame 0 done ISP DMA visual demo done. ``` - -## Reference - -- [ESP-IDF: Image Signal Processor](https://docs.espressif.com/projects/esp-idf/en/latest/esp32p4/api-reference/peripherals/isp.html) diff --git a/examples/peripherals/isp/dma_input/main/CMakeLists.txt b/examples/peripherals/isp/dma_input/main/CMakeLists.txt index 8d7c2262783..4bebe72a62c 100644 --- a/examples/peripherals/isp/dma_input/main/CMakeLists.txt +++ b/examples/peripherals/isp/dma_input/main/CMakeLists.txt @@ -1,7 +1,7 @@ -idf_component_register(SRCS "isp_dma_main.c" +idf_component_register(SRCS "isp_dma_example_main.c" PRIV_REQUIRES esp_driver_isp esp_mm esp_psram mbedtls INCLUDE_DIRS ".") target_add_binary_data(${COMPONENT_LIB} "${CMAKE_CURRENT_LIST_DIR}/assets/sensor_240x280_bggr.raw" - BINARY RENAME_TO "sensor_raw") + BINARY RENAME_TO "sensor_raw" ALIGN 16) diff --git a/examples/peripherals/isp/dma_input/main/isp_dma_main.c b/examples/peripherals/isp/dma_input/main/isp_dma_example_main.c similarity index 75% rename from examples/peripherals/isp/dma_input/main/isp_dma_main.c rename to examples/peripherals/isp/dma_input/main/isp_dma_example_main.c index 4460e7502ac..11e2e8c72bf 100644 --- a/examples/peripherals/isp/dma_input/main/isp_dma_main.c +++ b/examples/peripherals/isp/dma_input/main/isp_dma_example_main.c @@ -7,13 +7,11 @@ #include #include #include -#include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "mbedtls/base64.h" #include "esp_check.h" -#include "esp_cache.h" #include "esp_heap_caps.h" #include "driver/isp_dma.h" #include "driver/isp_core.h" @@ -22,20 +20,14 @@ #define EXAMPLE_WIDTH 240 #define EXAMPLE_HEIGHT 280 #define EXAMPLE_BASE64_CHUNK_LEN 384 -#define EXAMPLE_BASE64_DELAY_MS 10 #define EXAMPLE_DMA_ALIGN 64 #define EXAMPLE_FRAME_COUNT 1 +/* CMake embeds this RAW asset in mapped flash with 16-byte alignment. */ extern const uint8_t sensor_raw_start[] asm("_binary_sensor_raw_start"); extern const uint8_t sensor_raw_end[] asm("_binary_sensor_raw_end"); -static void *s_alloc_dma_buffer(size_t size) -{ - return heap_caps_aligned_calloc(EXAMPLE_DMA_ALIGN, 1, size, - MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT); -} - -static void s_configure_neutral_color(isp_proc_handle_t isp_proc) +static void example_configure_neutral_color(isp_proc_handle_t isp_proc) { esp_isp_color_config_t color_cfg = { .color_contrast = { .integer = 1, .decimal = 0 }, @@ -48,21 +40,22 @@ static void s_configure_neutral_color(isp_proc_handle_t isp_proc) ESP_ERROR_CHECK(esp_isp_color_enable(isp_proc)); } -static void s_print_base64_payload(const unsigned char *encoded, size_t encoded_len) +static void example_print_base64_payload(const unsigned char *encoded, size_t encoded_len) { printf("IMAGE_BASE64_BEGIN\n"); - fflush(stdout); + size_t chunk_count = 0; for (size_t offset = 0; offset < encoded_len; offset += EXAMPLE_BASE64_CHUNK_LEN) { size_t chunk_len = encoded_len - offset; if (chunk_len > EXAMPLE_BASE64_CHUNK_LEN) { chunk_len = EXAMPLE_BASE64_CHUNK_LEN; } printf("IMAGE_BASE64 %.*s\n", (int)chunk_len, (const char *)&encoded[offset]); - fflush(stdout); - vTaskDelay(pdMS_TO_TICKS(EXAMPLE_BASE64_DELAY_MS)); + if ((++chunk_count % 16) == 0) { + /* Let the test host drain the UART without delaying every chunk. */ + vTaskDelay(1); + } } printf("IMAGE_BASE64_END\n"); - fflush(stdout); } void app_main(void) @@ -87,15 +80,15 @@ void app_main(void) }; ESP_ERROR_CHECK(esp_isp_new_processor(&isp_cfg, &isp_proc)); ESP_ERROR_CHECK(esp_isp_enable(isp_proc)); - s_configure_neutral_color(isp_proc); + example_configure_neutral_color(isp_proc); - uint8_t *isp_in_buf = s_alloc_dma_buffer(in_size); - uint8_t *isp_out_buf = s_alloc_dma_buffer(out_size); - assert(isp_in_buf && isp_out_buf); + /* ISP writes this RGB frame through DMA, so PSRAM must be DMA-capable. */ + uint8_t *isp_out_buf = heap_caps_aligned_calloc(EXAMPLE_DMA_ALIGN, 1, out_size, + MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT); + assert(isp_out_buf); size_t embedded_raw_size = sensor_raw_end - sensor_raw_start; assert(embedded_raw_size == in_size); - memcpy(isp_in_buf, sensor_raw_start, embedded_raw_size); size_t encoded_len = 0; int ret = mbedtls_base64_encode(NULL, 0, &encoded_len, isp_out_buf, out_size); @@ -105,24 +98,25 @@ void app_main(void) printf("Feeding %d frames through ISP DMA input...\n", EXAMPLE_FRAME_COUNT); for (int frame = 0; frame < EXAMPLE_FRAME_COUNT; frame++) { - ESP_ERROR_CHECK(esp_cache_msync(isp_in_buf, in_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M)); - ESP_ERROR_CHECK(esp_isp_dma_process_frame(isp_proc, isp_out_buf, isp_in_buf, 1000)); - ESP_ERROR_CHECK(esp_cache_msync(isp_out_buf, out_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C)); + /* + * The RAW image is immutable mapped flash. Its aligned address can be + * read by DMA directly, so no PSRAM copy is needed. + */ + ESP_ERROR_CHECK(esp_isp_dma_process_frame(isp_proc, isp_out_buf, sensor_raw_start, 1000)); size_t out_len = 0; ESP_ERROR_CHECK(mbedtls_base64_encode(encoded, encoded_len + 1, &out_len, isp_out_buf, out_size) == 0 ? ESP_OK : ESP_FAIL); printf("IMAGE_META frame=%d width=%u height=%u format=BGR24 encoding=base64\n", frame, (unsigned)h_res, (unsigned)v_res); - s_print_base64_payload(encoded, out_len); + example_print_base64_payload(encoded, out_len); printf("Frame %d done\n", frame); } printf("ISP DMA visual demo done.\n"); - free(encoded); ESP_ERROR_CHECK(esp_isp_color_disable(isp_proc)); ESP_ERROR_CHECK(esp_isp_disable(isp_proc)); ESP_ERROR_CHECK(esp_isp_del_processor(isp_proc)); - heap_caps_free(isp_in_buf); - heap_caps_free(isp_out_buf); + free(encoded); + free(isp_out_buf); } diff --git a/examples/peripherals/jpeg/jpeg_decode/README.md b/examples/peripherals/jpeg/jpeg_decode/README.md index 24cb0ca5947..df3acb7520d 100644 --- a/examples/peripherals/jpeg/jpeg_decode/README.md +++ b/examples/peripherals/jpeg/jpeg_decode/README.md @@ -60,8 +60,7 @@ The test writes the `PPM` file and compares it with `golden_output.ppm`. This ma To run the pytest helper locally on hardware, build the example for your target first, then invoke the test script with the target and serial port: ```bash -idf.py set-target esp32p4 build -pytest --target esp32p4 --port PORT pytest_jpeg_decode.py +pytest pytest_jpeg_decode.py --target esp32p4 --port PORT ``` Replace `esp32p4` with another supported target such as `esp32s31` when needed. diff --git a/examples/peripherals/jpeg/jpeg_encode/README.md b/examples/peripherals/jpeg/jpeg_encode/README.md index 2c32e2d705a..bd06bef71b5 100644 --- a/examples/peripherals/jpeg/jpeg_encode/README.md +++ b/examples/peripherals/jpeg/jpeg_encode/README.md @@ -55,8 +55,7 @@ It also compares the generated JPEG with `golden_output.jpeg`. This turns the ex To run the pytest helper locally on hardware, build the example for your target first, then invoke the test script with the target and serial port: ```bash -idf.py set-target esp32p4 build -pytest --target esp32p4 --port PORT pytest_jpeg_encode.py +pytest pytest_jpeg_encode.py --target esp32p4 --port PORT ``` Replace `esp32p4` with another supported target such as `esp32s31` when needed.