From 029cc59a8de950150892847766d46e4fb6ebb9ba Mon Sep 17 00:00:00 2001 From: vintagepc <53943260+vintagepc@users.noreply.github.com> Date: Tue, 26 Oct 2021 20:48:25 -0400 Subject: [PATCH] Assorted cleaning (#332) * Merge/cleanup USBIP part 1 * Fix clang-tidy and cleanup errors * Cleaning & washing of code --- .clang-tidy | 2 +- 3rdParty/MK3/thermistortables_2.h | 76 + 3rdParty/simavr | 2 +- CMakeLists.txt | 37 +- MK404.cpp | 6 +- .../Firmware/Prusa-CW1-Firmware-en-v3.1.0.hex | 1486 ++++++++++++++++ .../Prusa-CW1S-Firmware-en-v3.1.0.hex | 1491 +++++++++++++++++ parts/Board.cpp | 2 +- parts/Board.h | 2 +- parts/I2CPeripheral.cpp | 2 +- parts/I2CPeripheral.h | 2 +- parts/PinNames.h | 7 +- parts/PrinterFactory.cpp | 10 +- parts/TelemetryHost.cpp | 7 + parts/TelemetryHost.h | 4 +- parts/boards/CW1S.cpp | 192 +++ parts/boards/CW1S.h | 91 + parts/boards/EinsyRambo.cpp | 2 +- parts/boards/MM_Control_01.cpp | 19 + parts/boards/MM_Control_01.h | 12 +- parts/boards/MiniRambo.h | 2 +- parts/boards/Test_Board.cpp | 24 + parts/boards/Test_Board.h | 7 + parts/components/74HCT4052.cpp | 56 + parts/components/74HCT4052.h | 63 + parts/components/Button.cpp | 16 +- parts/components/Button.h | 5 + parts/components/Fan.cpp | 75 +- parts/components/Fan.h | 15 +- parts/components/GLIndicator.h | 3 +- parts/components/HD44780GL.cpp | 2 +- parts/components/MCP23S17.cpp | 225 +++ parts/components/MCP23S17.h | 132 ++ parts/components/PINDA.cpp | 4 +- parts/components/TMC2130.cpp | 4 + parts/components/TMC2130.h | 2 +- parts/components/usb_types.h | 91 + parts/components/usbip.c | 553 ++++++ parts/components/usbip.h | 35 + parts/components/usbip_types.h | 172 ++ parts/pinspecs/PinSpec_2560.h | 6 +- parts/pinspecs/PinSpec_32u4.h | 12 +- parts/printers/IPCPrinter.cpp | 1 + parts/printers/IPCPrinter.h | 4 +- parts/printers/IPCPrinter_MMU2.h | 2 +- parts/printers/Prusa_CW1.h | 26 + parts/printers/Prusa_CW1S.cpp | 72 + parts/printers/Prusa_CW1S.h | 42 + parts/printers/Prusa_MMU2.cpp | 6 +- parts/printers/Prusa_MMU2.h | 2 +- parts/wiring/CW1S.h | 67 + parts/wiring/Test_Wiring.h | 3 +- scripts/tests/snaps/ext1/CW1S_mousedn.png | Bin 0 -> 3570 bytes scripts/tests/snaps/ext1/CW1S_mouseleft.png | Bin 0 -> 2537 bytes scripts/tests/snaps/ext1/CW1S_mouseup.png | Bin 0 -> 3595 bytes scripts/tests/snaps/ext1/CW1S_start.png | Bin 0 -> 3613 bytes scripts/tests/snaps/ext1/CW1_cure.png | Bin 0 -> 2653 bytes scripts/tests/snaps/ext1/CW1_down.png | Bin 0 -> 3500 bytes scripts/tests/snaps/ext1/CW1_lid.png | Bin 0 -> 2609 bytes scripts/tests/snaps/ext1/CW1_press.png | Bin 0 -> 2589 bytes scripts/tests/snaps/ext1/CW1_run.png | Bin 0 -> 3523 bytes scripts/tests/snaps/ext1/CW1_start.png | Bin 0 -> 3540 bytes scripts/tests/snaps/ext1/CW1_up.png | Bin 0 -> 3531 bytes scripts/tests/test_74HCT4052.c | 111 ++ scripts/tests/test_74HCT4052.txt | 60 + scripts/tests/test_MCP23S17.c | 284 ++++ scripts/tests/test_MCP23S17.txt | 15 + scripts/tests/test_boot_cw1.txt | 80 + scripts/tests/test_boot_cw1s.txt | 17 + scripts/tests/test_button.txt | 11 + utility/GLPrint.cpp | 16 +- utility/MK2_Full.h | 2 +- utility/MK3SGL.h | 2 +- 73 files changed, 5720 insertions(+), 59 deletions(-) create mode 100644 3rdParty/MK3/thermistortables_2.h create mode 100644 assets/Firmware/Prusa-CW1-Firmware-en-v3.1.0.hex create mode 100644 assets/Firmware/Prusa-CW1S-Firmware-en-v3.1.0.hex create mode 100644 parts/boards/CW1S.cpp create mode 100644 parts/boards/CW1S.h create mode 100644 parts/components/74HCT4052.cpp create mode 100644 parts/components/74HCT4052.h create mode 100644 parts/components/MCP23S17.cpp create mode 100644 parts/components/MCP23S17.h create mode 100644 parts/components/usb_types.h create mode 100644 parts/components/usbip.c create mode 100644 parts/components/usbip.h create mode 100644 parts/components/usbip_types.h create mode 100644 parts/printers/Prusa_CW1.h create mode 100644 parts/printers/Prusa_CW1S.cpp create mode 100644 parts/printers/Prusa_CW1S.h create mode 100644 parts/wiring/CW1S.h create mode 100644 scripts/tests/snaps/ext1/CW1S_mousedn.png create mode 100644 scripts/tests/snaps/ext1/CW1S_mouseleft.png create mode 100644 scripts/tests/snaps/ext1/CW1S_mouseup.png create mode 100644 scripts/tests/snaps/ext1/CW1S_start.png create mode 100644 scripts/tests/snaps/ext1/CW1_cure.png create mode 100644 scripts/tests/snaps/ext1/CW1_down.png create mode 100644 scripts/tests/snaps/ext1/CW1_lid.png create mode 100644 scripts/tests/snaps/ext1/CW1_press.png create mode 100644 scripts/tests/snaps/ext1/CW1_run.png create mode 100644 scripts/tests/snaps/ext1/CW1_start.png create mode 100644 scripts/tests/snaps/ext1/CW1_up.png create mode 100644 scripts/tests/test_74HCT4052.c create mode 100644 scripts/tests/test_74HCT4052.txt create mode 100644 scripts/tests/test_MCP23S17.c create mode 100644 scripts/tests/test_MCP23S17.txt create mode 100644 scripts/tests/test_boot_cw1.txt create mode 100644 scripts/tests/test_boot_cw1s.txt diff --git a/.clang-tidy b/.clang-tidy index 032e02e1..c3726d76 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,4 +1,4 @@ { - Checks: '*,-modernize-use-emplace,-hicpp-use-emplace,-readability*,-cppcoreguidelines-pro-type-union-access,-hicpp-braces*,-fuchsia*,-llvm-header-guard,-cppcoreguidelines-special-member-functions,-hicpp-special-member-functions' + Checks: '*,-modernize-use-emplace,-hicpp-use-emplace,-readability*,-cppcoreguidelines-pro-type-union-access,-hicpp-braces*,-fuchsia*,-llvm-header-guard,-cppcoreguidelines-special-member-functions,-hicpp-special-member-functions,-clang-diagnostic-unused-command-line-argument' HeaderFilterRegex: 'parts|utility' } diff --git a/3rdParty/MK3/thermistortables_2.h b/3rdParty/MK3/thermistortables_2.h new file mode 100644 index 00000000..8b83db69 --- /dev/null +++ b/3rdParty/MK3/thermistortables_2.h @@ -0,0 +1,76 @@ +#pragma once + +// TODO: more descriptive name. +const short table_100k_ntc[][2] = { +{ 25, 125 }, +{ 29, 120 }, +{ 34, 115 }, +{ 40, 110 }, +{ 46, 105 }, +{ 54, 100 }, +{ 64, 95 }, +{ 75, 90 }, +{ 88, 85 }, +{ 105, 80 }, +{ 124, 75 }, +{ 146, 70 }, +{ 173, 65 }, +{ 204, 60 }, +{ 241, 55 }, +{ 282, 50 }, +{ 330, 45 }, +{ 382, 40 }, +{ 439, 35 }, +{ 500, 30 }, +{ 563, 25 }, +{ 625, 20 }, +{ 687, 15 }, +{ 744, 10 }, +{ 796, 5 }, +{ 842, 0 }, +{ 882, -5 }, +{ 915, -10 }, +{ 941, -15 }, +{ 963, -20 }, +{ 979, -25 }, +{ 992, -30 }, +{ 1001, -35 }, +{ 1008, -40 } +}; + +const short table_NCP21WF104J03RA[][2] = { +{ 73, 125 }, +{ 83, 120 }, +{ 95, 115 }, +{ 109, 110 }, +{ 125, 105 }, +{ 144, 100 }, +{ 165, 95 }, +{ 189, 90 }, +{ 217, 85 }, +{ 248, 80 }, +{ 284, 75 }, +{ 323, 70 }, +{ 366, 65 }, +{ 412, 60 }, +{ 462, 55 }, +{ 514, 50 }, +{ 567, 45 }, +{ 620, 40 }, +{ 673, 35 }, +{ 723, 30 }, +{ 770, 25 }, +{ 813, 20 }, +{ 851, 15 }, +{ 885, 10 }, +{ 913, 5 }, +{ 937, 0 }, +{ 957, -5 }, +{ 973, -10 }, +{ 986, -15 }, +{ 995, -20 }, +{ 1003, -25 }, +{ 1009, -30 }, +{ 1013, -35 }, +{ 1016, -40 } +}; diff --git a/3rdParty/simavr b/3rdParty/simavr index 608a6868..5c68c9b6 160000 --- a/3rdParty/simavr +++ b/3rdParty/simavr @@ -1 +1 @@ -Subproject commit 608a6868fafa547604013a080c5a5192f49375d5 +Subproject commit 5c68c9b61793256d9aa4a63d137d9a119f4d70d9 diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dde2e18..e0b37ef1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,7 @@ else() endif() if (ENABLE_TIDY) - set(CMAKE_CXX_CLANG_TIDY "/usr/bin/clang-tidy;-config=") + set(CMAKE_CXX_CLANG_TIDY "/usr/bin/clang-tidy-5.0;-config=") else() unset(CMAKE_CXX_CLANG_TIDY) endif() @@ -62,10 +62,12 @@ set(H_FILES_base parts/ADCPeripheral.h parts/BasePeripheral.h parts/Board.h + parts/boards/CW1S.h parts/boards/EinsyRambo.h parts/boards/MiniRambo.h parts/boards/MM_Control_01.h parts/boards/Test_Board.h + parts/components/74HCT4052.h parts/components/A4982.h parts/components/ADC_Buttons.h parts/components/Beeper.h @@ -82,6 +84,7 @@ set(H_FILES_base parts/components/Heater.h parts/components/IRSensor.h parts/components/LED.h + parts/components/MCP23S17.h parts/components/MMU1.h parts/components/MMU2.h parts/components/PAT9125.h @@ -93,6 +96,7 @@ set(H_FILES_base parts/components/TMC2130.h parts/components/UART_Logger.h parts/components/uart_pty.h + parts/components/usbip.h parts/components/VoltageSrc.h parts/components/w25x20cl.h parts/I2CPeripheral.h @@ -106,6 +110,8 @@ set(H_FILES_base parts/Printer.h parts/printers/IPCPrinter.h parts/printers/IPCPrinter_MMU2.h + parts/printers/Prusa_CW1.h + parts/printers/Prusa_CW1S.h parts/printers/Prusa_MK1_13.h parts/printers/Prusa_MK2_13.h parts/printers/Prusa_MK25_13.h @@ -125,6 +131,7 @@ set(H_FILES_base parts/wiring/Einsy_1_0a.h parts/wiring/Einsy_1_1a.h parts/Wiring.h + parts/wiring/CW1S.h parts/wiring/miniRAMBo_1_1b.h parts/wiring/miniRAMBo_1_3a.h parts/wiring/MM_Control_01.h @@ -162,13 +169,23 @@ set(H_FILES_3rdParty set(H_FILES ${H_FILES_base} ${H_FILES_3rdParty}) +if (NOT APPLE) + set(NON_APPLE_SRC parts/components/usbip.c) + set_source_files_properties(parts/components/usbip.c PROPERTIES SKIP_PRECOMPILE_HEADERS ON) +else() + set(NON_APPLE_SRC) +endif() + set(MK404_SOURCES_base + ${NON_APPLE_SRC} parts/Board.cpp parts/I2CPeripheral.cpp + parts/boards/CW1S.cpp parts/boards/EinsyRambo.cpp parts/boards/MiniRambo.cpp parts/boards/MM_Control_01.cpp parts/boards/Test_Board.cpp + parts/components/74HCT4052.cpp parts/components/A4982.cpp parts/components/ADC_Buttons.cpp parts/components/Beeper.cpp @@ -185,6 +202,7 @@ set(MK404_SOURCES_base parts/components/IRSensor.cpp parts/components/GLIndicator.cpp parts/components/LED.cpp + parts/components/MCP23S17.cpp parts/components/MMU1.cpp parts/components/MMU2.cpp parts/components/PAT9125.cpp @@ -200,6 +218,7 @@ set(MK404_SOURCES_base parts/components/w25x20cl.cpp parts/printers/IPCPrinter.cpp parts/printers/IPCPrinter_MMU2.cpp + parts/printers/Prusa_CW1S.cpp parts/printers/Prusa_MK1_13.cpp parts/printers/Prusa_MK2_13.cpp parts/printers/Prusa_MK25_13.cpp @@ -235,7 +254,6 @@ set(MK404_SOURCES_base parts/KeyController.cpp ) - set(MK404_SOURCES_3rdparty 3rdParty/arcball/Camera.cpp ) @@ -435,7 +453,14 @@ add_custom_command(TARGET MK404 POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${PROJECT_SOURCE_DIR}/assets/Firmware/stk500boot_v2_mega2560.hex" "${PROJECT_BINARY_DIR}/stk500boot_v2_mega2560.hex") - +add_custom_command(TARGET MK404 POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${PROJECT_SOURCE_DIR}/assets/Firmware/Prusa-CW1-Firmware-en-v3.1.0.hex" + "${PROJECT_BINARY_DIR}/Prusa-CW1-Firmware.hex") +add_custom_command(TARGET MK404 POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${PROJECT_SOURCE_DIR}/assets/Firmware/Prusa-CW1S-Firmware-en-v3.1.0.hex" + "${PROJECT_BINARY_DIR}/Prusa-CW1S-Firmware.hex") # Copies the models/materials: file(GLOB_RECURSE MODEL_FILES @@ -512,6 +537,9 @@ add_test(ext1_MK2_Lite env ${TEST_EXPORT_PREFIX} ${TEST_XVFB_PREFIX} ./MK404 Pru add_test(ext1_IPC env ${TEST_EXPORT_PREFIX} ${TEST_XVFB_PREFIX} ./MK404 IPCPrinter --script ../scripts/tests/test_boot_ipc.txt) add_test(ext1_IPCMMU2 env ${TEST_EXPORT_PREFIX} ${TEST_XVFB_PREFIX} ./MK404 IPCPrinter_MMU2 -g lite --script ../scripts/tests/test_boot_ipcmmu2.txt ) add_test(ext1_MMU2 env ${TEST_EXPORT_PREFIX} ${TEST_XVFB_PREFIX} ./MK404 Prusa_MMU2 -f MM-control-01.hex --script ../scripts/tests/test_boot_mmu2.txt ) +add_test(ext1_CW1 env ${TEST_EXPORT_PREFIX} ${TEST_XVFB_PREFIX} ./MK404 Prusa_CW1 -f Prusa-CW1-Firmware.hex --script ../scripts/tests/test_boot_cw1.txt ) +add_test(ext1_CW1S env ${TEST_EXPORT_PREFIX} ${TEST_XVFB_PREFIX} ./MK404 Prusa_CW1S -f Prusa-CW1S-Firmware.hex --script ../scripts/tests/test_boot_cw1s.txt ) + # TODO- move these images out of parts and to their own ext2 dir... @@ -540,6 +568,8 @@ add_custom_target(MK3S.afx COMMAND cd ${PROJECT_SOURCE_DIR} SET(PRINTERS + Prusa_CW1 + Prusa_CW1S Prusa_MK3 Prusa_MK3MMU2 Prusa_MK3S @@ -549,6 +579,7 @@ SET(PRINTERS Prusa_MK2MMU_mR13 Prusa_MK2_mR13 Prusa_MK1_mR13 + Prusa_MMU2 ) add_subdirectory(${PROJECT_SOURCE_DIR}/SDCard) diff --git a/MK404.cpp b/MK404.cpp index 1b70537a..4c8095bf 100644 --- a/MK404.cpp +++ b/MK404.cpp @@ -422,10 +422,14 @@ int main(int argc, char *argv[]) std::ifstream ifBL {argStrBoot.getValue()}; if (!argStrBoot.isSet() && ifBL.good()) { - if (argModel.getValue() != "Prusa_MMU2") { + if (argModel.getValue() != "Prusa_MMU2" && argModel.getValue() != "Prusa_CW1S" && argModel.getValue() != "Prusa_CW1" ) { std::cout << "No bootloader specified, using default: " << argStrBoot.getValue() << '\n'; strBoot = argStrBoot.getValue(); } // MMU does not take a bootloader. + else + { + std::cout << "Model does not take standard bootloader. Skipping... \n"; + } } else if (argStrBoot.getValue().empty()) { diff --git a/assets/Firmware/Prusa-CW1-Firmware-en-v3.1.0.hex b/assets/Firmware/Prusa-CW1-Firmware-en-v3.1.0.hex new file mode 100644 index 00000000..e4fb050d --- /dev/null +++ b/assets/Firmware/Prusa-CW1-Firmware-en-v3.1.0.hex @@ -0,0 +1,1486 @@ +:1000000014C400000C947D290C9456290C942F29BB +:100010000C9408293AC4000038C400000C94E1286C +:1000200034C4000032C400000C944F260C94BE2649 +:100030002CC400002AC4000028C4000026C400000C +:1000400024C4000022C4000020C400001EC400001C +:100050001CC400000C94A32018C400000C94A42914 +:1000600014C4000012C4000010C400000EC400003C +:100070000CC400000AC4000008C4000006C400004C +:100080000C94672002C4000000C40000FEC30000FE +:10009000FCC30000FAC30000F8C30000F6C3000070 +:1000A000F4C30000F2C30000F0C300004472796999 +:1000B0006E6700437572696E6700447279696E6796 +:1000C0002F637572696E6700636F6E74696E756F0A +:1000D0007573006F6E6365006E6F6E6500000000E3 +:1000E00000250028002B002E003100000000002316 +:1000F00000260029002C002F000000000200090F3C +:100100000000030401000C000000000000000000DB +:100110000000000000000000080B000202020100C5 +:10012000090400000102020000052400100105245A +:1001300001010104240206052406000107058103CC +:1001400010004009040100020A0000000705020235 +:100150004000000705830240000004030904120167 +:100160000002EF020140992C080000010102030186 +:100170005072757361205265736561726368207097 +:100180007275736133642E636F6D004F72696769B6 +:100190006E616C2050727573612043573100435576 +:1001A00052574100496E636F7272656374206669CD +:1001B000726D77617265210000110A040A11000056 +:1001C00000080C0E0C0800000004021F02040000CE +:1001D000040E1F041C0000000010080402010000AF +:1001E00019001D00220028002E00360040004B00A0 +:1001F000580069007C009200AD00CC00F1001A01AB +:100200004A017E01B701F40133027102AF02E80234 +:100210001C034A0372039303AD03C303D303E00338 +:10022000E903F003490053005F006D007D0090007A +:10023000A500BD00D900F8001C0143016E019C011E +:10024000CE01020237026C02A102D30202032D0387 +:10025000530375039103A903BD03CD03DA03E3033D +:10026000EB03F103F503F80300000000240027006E +:100270002A002D00300004080201104080401020A8 +:10028000408040800802040180402010020110805C +:100290001020404020040404040404030405020266 +:1002A000020204030202020206060606060604040F +:1002B0000202020404054F7665726865617400509D +:1002C0006C65617365207265737461727400486552 +:1002D000617465722066616E206572726F72004390 +:1002E0006C6F73652074686520636F766572005269 +:1002F000656D6F7665204950412074616E6B0049D1 +:100300006E73657274204950412074616E6B0000F9 +:10031000507265737320746F20636F6E74696E75AD +:10032000650046696E69736865640046616E3220D7 +:100330006661696C757265004E6F742F626164202E +:100340007370696E6E696E67005370696E6E696E68 +:1003500067207475726E6564206F66660046616E14 +:1003600031206661696C757265002020002020468E +:10037000323A0046313A004E6F2F6C6F7720706F23 +:100380007765720055564C4544206661696C7572FC +:100390006500526561642074656D7065722E20651C +:1003A00072726F7200486561746572206661696C73 +:1003B0007572650046333A00435731763200206D3E +:1003C000696E2E00202500203E003C200050617503 +:1003D0007365640020DF46007C2F2D003E3E003E0A +:1003E0007C003C3C007C3C00447279696E672F6362 +:1003F0007572696E6700437572696E670044727941 +:10040000696E670057617368696E67005061757344 +:100410006500436F6E74696E7565002020000706E5 +:1004200005040100080A0B0C0D09436C6F7365206D +:1004300074686520636F766572004F70656E207416 +:10044000686520636F76657200436F76657220740D +:1004500065737400496E736572742049504120744D +:10046000616E6B0052656D6F766520495041207456 +:10047000616E6B004950412074616E6B207465732E +:100480007400526F746174696F6E207465737400C8 +:1004900046616E7320746573740055564C45442054 +:1004A0007465737400486561746572207465737453 +:1004B00000436F6F6C646F776E005761726D2D75BE +:1004C000700048656174696E6700437572696E6794 +:1004D00000447279696E670057617368696E6700DE +:1004E00000005BDF465D005BDF435D0020DF430013 +:1004F0002F3130001908BD06870690056205536547 +:100500006C667465737400436F6F6C646F776E0014 +:100510001908EB05DF05BB05D305C70546616E333A +:100520002052504D3A200055564C45442074656D7C +:10053000702E3A004368616D2E2074656D702E3AFE +:100540000046616E322052504D3A200046616E31B5 +:100550002052504D3A200032061A06DB074C066D39 +:1005600006526573696E2070726568656174001962 +:1005700008486F6C642074686520706C6174666FE5 +:10058000726D00660614081908001908B80792066B +:100590007C075A077A069C0653657474696E677304 +:1005A000004C4344206272696768746E657373001F +:1005B00055564C454420696E74656E7369747900B4 +:1005C000BA00B300AC0052756E206D6F64650019FF +:1005D00008B806B306AE06A906496E666F726D616D +:1005E00074696F6E006361653862626537333664C3 +:1005F00037343739353339004275696C643A203203 +:1006000033370046573A2076332E312E3000534E82 +:100610003A2000190837071407F106CA0646616E2A +:1006200073001908D706E40646616E73206D656E87 +:10063000752073706565640046616E31206D656E6E +:10064000752073706565640046616E32206D656E5D +:1006500075207370656564001908FE060907466118 +:100660006E732077617368696E6720737065656467 +:100670000046616E312077617368696E6720737020 +:100680006565640046616E322077617368696E67E4 +:1006900020737065656400190821072C0746616E98 +:1006A0007320647279696E672073706565640046B3 +:1006B000616E3120647279696E672073706565645C +:1006C0000046616E3220647279696E6720737065CE +:1006D00065640019084F07440746616E732063750F +:1006E00072696E672073706565640046616E3220C2 +:1006F000637572696E672073706565640046616E2C +:100700003120637572696E672073706565640019C6 +:100710000871076707536F756E6400D800D300C86F +:100720000046696E697368206265657000436F6E8C +:1007300074726F6C206563686F001908AD07A207BB +:100740009707890754656D7065726174757265737A +:1007500000A207970754656D702E20756E6974733B +:1007600000526573696E20707265686561742074EB +:100770002E00447279696E67207761726D2D7570F5 +:1007800020742E005B6F66665D005B6F6E5D0057C8 +:1007900061726D2D7570001908D007C507526F740E +:1007A0006174696F6E20737065656400576173686A +:1007B000696E6720737065656400437572696E6762 +:1007C0002073706565640019080908FE07F307E8DF +:1007D0000752756E2D74696D6500526573696E20E0 +:1007E000707265686561742074696D650057617326 +:1007F00068696E672072756E2D74696D650044724C +:1008000079696E672072756E2D74696D6500437528 +:1008100072696E672072756E2D74696D6500537410 +:100820006F70004261636B00D71711241FBECFEFBA +:10083000DAE0DEBFCDBF8091FE0A9091FF0A90936F +:100840005B0880935A0813E0A0E0B1E0E8E3FAE522 +:1008500002C005900D92A039B107D9F728E0A0E9B0 +:10086000B3E001C01D92AA35B207E1F714E0C5E17B +:10087000D4E004C02197FE010E94BB2AC431D107F5 +:10088000C9F70E940B210C941A2DBACBCF92DF929C +:10089000EF92FF921F93CF93DF93FB01EE5BFF4F2D +:1008A00025913491821793070CF056C0FB012591D6 +:1008B0003491281739070CF052C013E2A1E2B0E0DE +:1008C000D0E0C0E021E1115019F490E080E03CC09C +:1008D00030E0A901440F551FFB01E40FF51FE5901F +:1008E000F490FA013296E60FF71FC590D490A90153 +:1008F000C816D9064CF49D01240F351F3595279550 +:10090000EA01AD01DA01DFCF8E159F0534F49E01B7 +:10091000240F351F35952795F5CFBC016E197F093A +:100920004EEC4603C001479F900D1124B6016E198D +:100930007F090E94EE294203C001439F900D1124BC +:100940008E519B4F860F971FDF91CF911F91FF9084 +:10095000EF90DF90CF90089580E79EEFF5CF82EE85 +:1009600094E0F2CF9C01A8EEB3E00E94AC2A609321 +:100970004B0870934C0880934D0890934E086093F9 +:1009800053087093540880935508909356088091AB +:100990005908882341F010924B0810924C0810928D +:1009A0004D0810924E0880914B0890914C08A091F0 +:1009B0004D08B0914E0880934F0890935008A09333 +:1009C0005108B0935208089584E050E040E0E2E21C +:1009D000F4E0949130917B00292F220F220F207296 +:1009E0003F7D232B20937B009770906490937C0035 +:1009F00090917A00906490937A0090917A0096FD9D +:100A0000FCCF9091780020917900322F292F420F4E +:100A1000531F8150F1F6CA010895EBEDF3E0828196 +:100A20008F5F82830895EBEDF3E081818F5F818397 +:100A30000895EBEDF3E080818F5F80830895FC01E2 +:100A40008481882359F0A281B3816C938281938140 +:100A500001969383828384818150848308950F93C8 +:100A60001F93CF93DF938C01EB01FE0164912196DC +:100A7000662349F0D801ED91FC910190F081E02DC1 +:100A8000C8010995F2CFDF91CF911F910F91089581 +:100A9000FC0112861186148613868FEF9FEF9687CE +:100AA00085871786108A118A128A138A148A158AF2 +:100AB000168A178A0895FC017383628383E0848316 +:100AC00088E991E09183808356834583308727832B +:100AD00012861186148613868FEF9FEF968785877F +:100AE0001786108A118A128A138A148A158A168A1E +:100AF000178A0895FC017383628382E0848384EC07 +:100B000093E0968385835087478384E68187228795 +:100B100086E693E0918380830895FC01738362836A +:100B200082E084838EEB93E09683858350874783AE +:100B3000218781E0828786E693E091838083089510 +:100B4000DC011796ED91FC91189720811A963C9143 +:100B50001A97321740F421502083ED91FC910280C6 +:100B6000F381E02D09950895CF93DF93EC01E8DF41 +:100B7000AF81B885EB85FC858C910995DF91CF918C +:100B80000895DC011796ED91FC9118972081199634 +:100B90003C911997231740F42F5F2083ED91FC912E +:100BA0000280F381E02D09950895CF93DF93EC0146 +:100BB000E8DFAF81B885EB85FC858C910995DF91E5 +:100BC000CF9108950F931F93CF93DF93EC01162FCE +:100BD000862F8C7039F0E881F9810280F381E02D55 +:100BE000CE01099516FF11C08B852C852150330B42 +:100BF000821713060CF03FC08F5F8B87E881F98165 +:100C00000280F381E02DCE01099517FF0DC08B8581 +:100C1000882309F43BC081508B87E881F9810280E9 +:100C2000F381E02DCE01099514FF36C0EA858B854E +:100C3000E80FFF27FF1FCF01880F991FED81FE816D +:100C4000E80FF91F05911491D801ED91FC910484EE +:100C5000F585E02DC8010995009739F108171907A6 +:100C6000F9F4E881F9810280F381E02DCE01099544 +:100C700090E080E015C08A8529852450330B8217C7 +:100C800013060CF0C2CF8F5F8A87B8CF8A8588237E +:100C900059F281508A87C1CF15FFEACF8F8198859D +:100CA000DF91CF911F910F910895C801F9CFFC01F9 +:100CB00013860895FC017383628382E0848386E84F +:100CC00091E0918380835683458310861782218724 +:100CD00012861386253008F024E0248708950895AD +:100CE000FC0173836283148284E791E091838083A3 +:100CF000089590E080E0089590E080E008950895E0 +:100D0000FC0113821282158214821782168284E4F7 +:100D100091E0918780871286138614861586168641 +:100D20008FE093E0908B8787128A118A148A138A46 +:100D300080E2858B84E691E091838083668B178ABD +:100D4000089580E008958091A10381110DC082E093 +:100D500080939D0384E080939E031092A0031092E1 +:100D60009F0381E08093A1038DE993E00895409172 +:100D70009B0350919C032091990330919A03421751 +:100D80005307B4F49091E8009570E1F39091E80076 +:100D900092FD19C08093F10080919B0390919C0378 +:100DA00001968F739927892B19F48EEF8093E800B1 +:100DB00080919B0390919C03019690939C03809358 +:100DC0009B0381E0089580E00895EF92FF920F93D6 +:100DD0001F93CF93DF93EC01E62E042F81E0860F63 +:100DE000880FC5DF83E0C3DFEC0EFD2EF11CCE15AE +:100DF000DF0599F007FF0FC0FE018491B8DF182FBF +:100E000080E0B5DF812321968111F1CFCDB7DEB728 +:100E1000E6E00C94E92A8881F1CF81E0F7CFB0E0D9 +:100E2000A0E0E5E1F7E00C94CC2AD82E8A01EB0192 +:100E30007B01E40EF51ECE15DF0551F0D7FE0EC086 +:100E4000FE01849194DF21968111F5CF0FEF1FEF02 +:100E5000C801CDB7DEB7E7E00C94E82A8881F2CF6D +:100E6000A1E0B0E0E6E3F7E00C94CF2A82E08983CA +:100E700042E450E068E171E080E8D1DF64DFDC014A +:100E800012960D911C910115110589F0D801ED9173 +:100E9000FC910280F381E02DBE016F5F7F4FC8019E +:100EA000099597FD04C0F80100851185ECCF898173 +:100EB0002196E4E00C94EB2A615030F02091F1008F +:100EC000FC0120830196F8CF289884E68093DE0306 +:100ED00008958EBD00000DB407FEFDCF8EB50895B8 +:100EE00081508F3008F047C0E82FF0E0E658F84F07 +:100EF0000C94BB2A97079B0789078F079307BB07AB +:100F0000BB07BB079E07A407A807AC07B207BB0730 +:100F1000B607809180008F7780938000089580913C +:100F200080008F7DF9CF80918000877FF5CF84B5D9 +:100F30008F7784BD089584B58F7DFBCF809190001D +:100F40008F77809390000895809190008F7DF9CFE6 +:100F500080919000877FF5CF8091C0008F7780933C +:100F6000C00008958091C0008F7DF9CF8091C200AC +:100F7000877F8093C2000895CF93DF93282F30E0BE +:100F8000F901E750FF4F8491F901EA58FD4FD491E0 +:100F9000F901EA56FD4FC491CC2379F08111A0DF0D +:100FA000EC2FF0E0EE0FFF1FE551FF4FA591B4913C +:100FB000EC91ED2381E090E011F490E080E0DF918E +:100FC000CF9108951F93CF93DF93282F30E0F9013D +:100FD000E750FF4F8491F901EA58FD4FD491F90190 +:100FE000EA56FD4FC491CC23A1F0162F811178DF72 +:100FF000EC2FF0E0EE0FFF1FE352FF4FA591B491ED +:101000008FB7F894EC91111108C0D095DE23DC93D2 +:101010008FBFDF91CF911F910895DE2BF8CFFF9204 +:101020000F931F93CF93DF93F82E8B01C9E3D8E082 +:1010300060E08981C7DF8881880F80644ADF8F2D57 +:1010400048DF802F46DF812F44DF61E08981BADFEE +:10105000CDB7DEB7E5E00C94EA2A9FEF980F903108 +:10106000E8F4E0914108F09142088150990B21E0A9 +:1010700030E0A90102C0440F551F8A95E2F7CA016A +:10108000662369F08E2B9F2B909342088093410832 +:10109000609141087091420882E1C1CF0895809526 +:1010A00090958E239F23F0CF60E08BE0D6DF1092E7 +:1010B000D3031092D4031092D5031092D6030FB627 +:1010C000F894A895809160008861809360001092E8 +:1010D00060000FBE089561E084E0BFCF0895FBCFAC +:1010E00008951F93CF93DF93182F60E080913A0803 +:1010F00069DF80913908880F8164EBDE82E1E9DEE7 +:1011000080E0E7DEC82FD0E080E0E3DED82B61E0AE +:1011100080913A0857DF212F2150330BC90121E07C +:1011200030E002C0220F331F8A95E2F72C233D23C3 +:1011300081E0232B09F480E0DF91CF911F91089586 +:1011400082E0CFDF91E0811190E0892F089583E064 +:10115000C8DF91E0811190E0892F0895FC01858915 +:1011600084FF06C0EDDF882361F090E080E0089501 +:10117000E7DF811109C0EBDF8111F7CF8FED92E03E +:1011800008958FEF92E008958FEE92E00895CF9248 +:10119000DF92EF92FF921F93CF93DF93182F6A0194 +:1011A0007B01CFE2D8E060E088850CDF812F80688A +:1011B00090DE89878F2D8DDE8E2D8BDE8D2D89DE45 +:1011C0008C2D87DE61E08885FDDE8985DF91CF91FA +:1011D0001F91FF90EF90DF90CF90089560E087E03F +:1011E0003CDF60E083E0EECE0895CF93DF93EC0127 +:1011F0008D8981FDF3DF8D8982FD56DF8B899C8986 +:10120000892B19F01092710066DF89899A89892BE0 +:1012100019F081E080935808DF91CF910895CF9322 +:10122000DF93EC018091220190912301DEDFD093C6 +:101230002301C0932201E881F9810190F081E02D22 +:10124000CE010995DF91CF91089581E295E0E7CF36 +:101250000895FC0185819681E2CF0895CF93DF93B5 +:10126000EC016EDF882349F08BED94E09E838D8343 +:10127000CE01EFDFDF91CF910895E88DF98D808168 +:10128000813059F0823091F489E095E09093C80460 +:101290008093C70485EC94E002C08FEA94E09093B9 +:1012A00086048093850483E894E0E0CF8FEA94E09D +:1012B000EDCFCF93DF9390E0FC01EA58FD4F2491EE +:1012C0008A569D4FFC0184918823C9F090E0880FD5 +:1012D000991FFC01E859FD4FA591B491FC01E3521F +:1012E000FF4FC591D49161110DC09FB7F8948C91B7 +:1012F000209582238C938881282328839FBFDF91A8 +:10130000CF910895623051F49FB7F8943C91822FA9 +:10131000809583238C93E8812E2BEFCF8FB7F894A1 +:10132000EC912E2B2C938FBFEACFEF92FF920F936D +:101330001F93CF93DF938C01095F1F4FD0E0C0E074 +:10134000E62EF12C61E0F80181918F01B2DFB70147 +:101350000C2E02C0759567950A94E2F76170F8014A +:10136000319780812FDE2196C430D10559F760E096 +:1013700084E028DE61E084E025DE60E084E022DEB7 +:1013800083EC90E00197F1F7CDB7DEB7E6E00C947F +:10139000E92A1F93CF93DF93EC01162F642F8CE083 +:1013A00011DE612F70E084E0759567958A95E1F70D +:1013B000CE01BBDF612FCE01B8DFDF91CF911F914E +:1013C000089540E061E08EE198E0E3DF8BEF98E183 +:1013D0000197F1F70895E62FF0E0E25EF74F63859D +:1013E000680F606840E08EE198E0D3CF0895CF9316 +:1013F000DF93EC01862F642FEEDFBE018EE198E0D3 +:101400002EDBDF91CF91089542E068E08BE194E01C +:10141000EEDF42E061E08BE194E0E9CF089541E046 +:10142000B8CF08950F931F93CF93DF93EB0198E00C +:10143000899FB0011124606440E08EE198E0A9DF4B +:101440008E01085F1F4FFE0164918EE198E0E7DF97 +:1014500021960C171D07B9F7DF91CF911F910F91BE +:101460000895CF9362E080E0B6DFC4E160E28EE1F0 +:1014700098E0D5DFC150D1F7CF910895CF92DF9298 +:10148000EF92FF921F93CF93DF93CDB7DEB76497B0 +:101490000FB6F894DEBF0FBECDBF7C0110E0D701C0 +:1014A0001C968C911817A8F5612F80E094DFF70146 +:1014B00083856EE3811360E28EE198E0B0DFD701AF +:1014C0001A96EC911A97E10FFF27FF1FCF01880FA3 +:1014D000991F1596ED91FC91E80FF91F8591949154 +:1014E000DC01ED91FC910190F081E02D44E1BE0121 +:1014F0006F5F7F4F0995FE0131966F01D6016D91A7 +:101500006D01662321F08EE198E089DFF7CF1F5F40 +:10151000C6CF64960FB6F894DEBF0FBECDBFDF9185 +:10152000CF911F91FF90EF90DF90CF900895A6DFAD +:1015300060E084E092CD0895CF93CFB7F894809186 +:10154000C903811123C0E7EAF2E08491E7E8F2E001 +:101550009491E82FF0E0EE0FFF1FE859FD4FA591A1 +:10156000B491EC91E92319F461E081E12BDD61E0B4 +:1015700081E19FDE8CB580618CBD8CB580648CBDB3 +:1015800061E08FE096DE61E080E193DE8091C90347 +:101590008F5F8093C903CFBFCF9108958CB58C60C6 +:1015A0008CBD8CB58F7D8CBD8CB58C7F81608CBDE6 +:1015B0008DB581608DBDC0CF0895B0E0A0E0E3EEB1 +:1015C000FAE00C94C22A382E2A013B014801590145 +:1015D000E5DFCFE2D8E060E08885F4DC832D79DCBC +:1015E000898780E076DC80E074DC80E072DC80E07B +:1015F00070DC61E08885E6DC60E08885E3DC832DD3 +:1016000068DC898780E065DC082F80E062DCC82E1A +:1016100080E05FDC182F80E05CDCD12CF12CE12C29 +:10162000D02AFE2CED2CDC2CCC24C12AFE2CED2C57 +:10163000DC2CCC24C82A61E08885C4DCB301A2017B +:101640004C255D256E257F25482159216A217B2166 +:101650004C255D256E257F25832D99DD8985CDB7A8 +:10166000DEB7E1E10C94DE2A0F931F9394E0899F8B +:10167000F0011124EA55FE4F00811181228133814E +:10168000082E04C0000F111F221F331F0A94D2F727 +:10169000462F50E070E060E004C0440F551F661F05 +:1016A000771F8A95D2F78CE688DF809138081F91E2 +:1016B0000F9108951F93CF93DF93182FEB0161E0F3 +:1016C000F8DD209739F460E0812F7CDCDF91CF9149 +:1016D0001F910895CF3FD10511F461E0F5CFE12FBF +:1016E000F0E0E750FF4FE491E150EF3008F07CC0AC +:1016F000F0E0E358F44F0C94BB2A8C0B910B960B43 +:10170000A00BAA0BF40BF40BF40BB40BBE0BC80B21 +:10171000D20BDF0BF40BE70B84B5806884BDC7BD2B +:10172000D5CF84B5806284BDC8BDD0CF8091800004 +:10173000806880938000D0938900C0938800C6CFD2 +:1017400080918000806280938000D0938B00C09352 +:101750008A00BCCF80918000886080938000D09305 +:101760008D00C0938C00B2CF8091900080688093F0 +:101770009000D0939900C0939800A8CF80919000DA +:10178000806280939000D0939B00C0939A009ECF7C +:1017900080919000886080939000D0939D00C093CA +:1017A0009C0094CF8091C00080688093C00080919D +:1017B000C0008F7B8093C000C093CF0087CF809103 +:1017C000C00080628093C000C093D0007FCF809122 +:1017D000C20088608093C2008091C2008B7F80939A +:1017E000C200C093D20072CFC038D1050CF075CFC3 +:1017F0006ACF282F30E0AFEFB0E00E94AC2A24E699 +:1018000030E040E050E00E945E2AB90186E052CF0D +:101810000895CF93DF9390E0FC01E459FE4FD0810F +:1018200082599E4FFC01C0816623E1F0A62FB0E0F3 +:1018300021E03FEF4FEF5FEF0E947A2A24E630E08D +:1018400040E050E00E945E2ACA01B90161507F4F1A +:101850008F4F9F4F8C2F2EDF61E08D2FFEDBDF91AE +:10186000CF91089560E08D2FF8DB60E08C2FAADB2C +:10187000F6CF682F81E0CDCF0895682F80E0C9CFE3 +:101880000895CF93DF93C7EDD3E0688180E0C1DF97 +:10189000698181E0BEDFDF91CF910895FC0116865A +:1018A00081E0878B81E090E0A0E0B0E082879387C1 +:1018B000A487B5878689811106C080913A01882363 +:1018C000E1F08230F1F4178A80E193E022E233E024 +:1018D000309319052093180590930E0580930D05FC +:1018E0000084F185E02D80818093D70381818093EE +:1018F000D8031092CD03C5CF08951286138614869F +:1019000015868FE093E0E2CF08953FB7F894809179 +:10191000950390919603A0919703B091980326B5F3 +:10192000A89B05C02F3F19F00196A11DB11D3FBF17 +:10193000BA2FA92F982F8827BC01CD01620F711DE6 +:10194000811D911D42E0660F771F881F991F4A95E0 +:10195000D1F708958F929F92AF92BF92CF92DF926C +:10196000EF92FF924B015C01D0DF6B017C01CDDF78 +:101970006C197D098E099F09683E734081059105A8 +:10198000B0F321E0821A9108A108B10888EEC80ED0 +:1019900083E0D81EE11CF11C81149104A104B10460 +:1019A00031F7FF90EF90DF90CF90BF90AF909F9076 +:1019B0008F9008956CED70E089E07CDE62E370E06A +:1019C00080E090E0C7DF60E089E0FCDA6AEF70E079 +:1019D00080E090E0BFDF6CED70E089E06BDE62E3F9 +:1019E00070E080E090E0B6DF60E089E0EBCA089547 +:1019F0002FB7F894609191037091920380919303B3 +:101A0000909194032FBF0895CF92DF92EF92FF92AF +:101A10000F931F93CF938C01C62F862F8F7029F0C1 +:101A20008FEF9FEFF80196878587C6FF4AC0E09148 +:101A30002201F091230181899289892B09F441C007 +:101A400060914B0870914C0880914D0890914E0820 +:101A500038EEC32E33E0D32EE12CF12CA7019601F2 +:101A60000E948A2A2F3F3F4F61F1CEDCE091220194 +:101A7000F091230181899289892B19F1858983FF4E +:101A800020C060914B0870914C0880914D08909156 +:101A90004E08A70196010E948A2A2B3382E038075C +:101AA00008F07AC0C9014E960E94B2048CED93E012 +:101AB00042E068E09CDC9CDFF801638B748B858BD3 +:101AC000968BC7FF4AC0E0912201F09123018189E2 +:101AD0009289892B09F441C060914B0870914C08A0 +:101AE00080914D0890914E0828EEC22E23E0D22E10 +:101AF000E12CF12CA70196010E948A2A2F3F3F4F2B +:101B000061F182DCE0912201F091230181899289C7 +:101B1000892B19F1858983FF20C060914B08709152 +:101B20004C0880914D0890914E08A70196010E94A3 +:101B30008A2A85EE93E02E31310530F0C9014E97A7 +:101B40000E94B20482EE93E042E061E050DC50DF9C +:101B5000F801638B748B858B968BC4FF12C0E09168 +:101B60002201F0912301858985FD11C0F80187814B +:101B70009085CF911F910F91FF90EF90DF90CF90C4 +:101B80000895C5FF06C0E0912201F091230181E094 +:101B9000868790E080E0EDCF8FED93E089CFB0E0D5 +:101BA000A0E0E5EDFDE00C94CB2AEC0121DF0F85F0 +:101BB000188929893A896B017C01C01AD10AE20A85 +:101BC000F30A970186014D855E856A01F12CE12CAF +:101BD000C016D106E206F30658F46F87788B898B1E +:101BE0009A8BE881F9810280F381E02DCE0109957D +:101BF000CDB7DEB7E8E00C94E72ACF93DF93EC0192 +:101C0000F7DE6F87788B898B9A8BCE0137DCDF917B +:101C1000CF910895CF92DF92EF92FF92CF93DF930F +:101C2000C62FD42F90E0B0E0A0E06C017D0121E050 +:101C3000C21AD108E108F1086623C1F14FE15FE162 +:101C400065E070E080E1A3DA64E088E10DDDAAECF4 +:101C5000BFEFA70196010E94862A29E030E040E00C +:101C600050E00E945E2ADA01C9018A5B9F4FAF4FA4 +:101C7000BF4FDD2361F080932101C0E0C093CE030C +:101C8000DF91CF91FF90EF90DF90CF9008958093F8 +:101C9000200188EC80932101ABDE6093CF03709329 +:101CA000D0038093D1039093D203E8CF4AE05AE067 +:101CB00060E070E080E16BDA60E088E1D5DCADE304 +:101CC000BFEFA70196010E94862A29E030E040E09C +:101CD00050E00E945E2A24523F4F4F4F5F4F2093A7 +:101CE0002101CCCFB0E0A0E0E8E7FEE00C94CB2AE5 +:101CF000EC018E85811103C08C8D811108C05ADEE4 +:101D00008A819B81CDB7DEB7E8E00C94E72A70DECC +:101D10000A851B852C853D856B017C01C01AD10A83 +:101D2000E20AF30A970186010B3F110521053105EF +:101D300018F490E080E0E6CF6A877B878C879D87E8 +:101D4000EA8DFB8D09959D8D981799F38D8F8823CA +:101D500041F08E899F899D838C838C8D81508C8FDF +:101D6000E8CF888D998DF7CFCF93DF93EC011E8656 +:101D7000EA8DFB8D09958D8F882371F08E899F895F +:101D80009D838C838AE08C8F33DE6A877B878C8788 +:101D90009D87DF91CF910895888D998DF1CFCF9256 +:101DA000DF92EF92FF92CF93DF93EC018F898E87C2 +:101DB0001FDE6B017C018A859B85AC85BD85009704 +:101DC000A105B10591F0A7019601281B390B4A0B1B +:101DD0005B0BDA01C901893E9340A105B10528F0EA +:101DE000E9DDCA86DB86EC86FD868E85882349F090 +:101DF0008A819B81DF91CF91FF90EF90DF90CF9010 +:101E0000089590E080E0F6CFCF93DF93EC01EB896B +:101E1000FC89309771F06D896295617040E0808136 +:101E2000F9DE8091710082608093710060E084E04F +:101E300014D98D8982FF16C061E08BE00ED9D8DD00 +:101E40006093D3037093D4038093D5039093D60308 +:101E500088E198E20FB6F894A895809360000FBED1 +:101E60009093600089899A89892B39F010925808DB +:101E700080915708811110925708BADD6A877B87D5 +:101E80008C879D87DF91CF9108950F931F93CF93F8 +:101E9000DF938C01C0912201D091230189899A8915 +:101EA000892B51F080915808882371F0CE0156D9C2 +:101EB000892B11F4CE01A8DFF80185819681DF918D +:101EC000CF911F910F910895CE018FD9F5CFCF9368 +:101ED000DF93EC011E86E885F98580818093D70326 +:101EE00081818093D8031092CD03CBDCE989FA89F4 +:101EF000309771F080818C3308F08BE39D8991706D +:101F0000909359082CE3829FC00111240E94B204CF +:101F10008D89867069F01BD9811107C089899A89DA +:101F2000892B59F4CE0161D905C00AD98111F6CFA8 +:101F3000CE016ADFDF91CF91089510925808809109 +:101F40005708882379F310925708ECCF40911C0171 +:101F500050911D0160911E0170911F01FC01448F81 +:101F6000558F668F778F21E022A3B1CF08954091DE +:101F700018015091190160911A0170911B01FC0127 +:101F8000478B508F618F728FA2CF0895FC01148E02 +:101F900084E6858F178E168E8FEF9FEF91A380A317 +:101FA00088E790E093A382A381E084A385A3CF0177 +:101FB0008ECF0895CF93DF93EC018AE08C8F84EB72 +:101FC00090E09E8F8D8F81E08F8F88A3CE017FDF81 +:101FD00040E06F8D8C8D1EDEDF91CF910895CF9202 +:101FE000DF92EF92FF92CF93DF93EC0189899A8978 +:101FF000892B09F461C08091570881115DC08091DF +:102000005808811159C0F4DCDC01CB014091430830 +:10201000509144086091450870914608C090470867 +:10202000D0904808E0904908F0904A088C199D0922 +:10203000AE09BF0984179507A607B707E8F1809195 +:102040004B0890914C08A0914D08B0914E082091FA +:102050005908222309F444C0C0905308D090540872 +:10206000E0905508F09056088C159D05AE05BF050B +:1020700068F4840F951FA61FB71F80934B08909399 +:102080004C08A0934D08B0934E080DC081E080939A +:1020900058088093570810924B0810924C081092E1 +:1020A0004D0810924E08A4DC6093470870934808CE +:1020B0008093490890934A088E85811108C08989C8 +:1020C0009A89892B21F180915708882301F18A810F +:1020D0009B81DF91CF91FF90EF90DF90CF9008959B +:1020E0000097A105B10529F0841B950BA60BB70B32 +:1020F000C4CF81E08093580880935708809153089B +:1021000090915408A0915508B0915608B6CF80918F +:10211000CC03882379F08EEC92E0909301058093B4 +:1021200000058FEB92E09093F6048093F50481EF25 +:1021300094E0CFCF8D8981FF2DC0C0901801D09041 +:102140001901E0901A01F0901B0120E030E0A90194 +:10215000C701B6010E945D2B87FF09C084E893E0A8 +:10216000909301058093000582E993E0DCCF20E0A5 +:1021700030E04CE852E4C701B6010E94AC2C1816BE +:102180004CF484E893E0909301058093000586EB7E +:1021900092E0C9CF8A859B85AC85BD85892B8A2B2A +:1021A0008B2B19F490E080E094CF22DCCA84DB848E +:1021B000EC84FD846C197D098E099F09613D77408F +:1021C0008105910578F38D8981FFECCF2091430142 +:1021D00030E0AFEFB0E00E94AC2A24E630E040E00F +:1021E00050E00E945E2AB90183E064DA61E087E092 +:1021F0000E942D081A861B861C861D86D3CFCF937E +:10220000DF93EC0120E030E0A9016C8D7D8D8E8D97 +:102210009F8D0E945D2B87FD0FC020E030E0A9015B +:1022200060911C0170911D0180911E0190911F0110 +:102230000E945D2B87FF11C085EA93E09093010512 +:102240008093000582E993E09093F6048093F5046F +:1022500081EF94E0DF91CF91089560914B087091E8 +:102260004C0880914D0890914E0828EE33E040E0F4 +:1022700050E00E948A2A2150310988A199A1821731 +:10228000930721F039A328A381E08AA3CE01A7DE1A +:10229000E1CFCF93DF93EC0160914B0870914C0834 +:1022A00080914D0890914E0828EE33E040E050E0D8 +:1022B0000E948A2A2130310539F520E030E040E2E1 +:1022C00051E46F89788D898D9A8D0E94F92A209129 +:1022D00018013091190140911A0150911B010E947F +:1022E000AC2C18168CF484E893E09093010580934D +:1022F000000587E793E09093F6048093F50481EF5F +:1023000094E0DF91CF910895CE0169DEFACFCF93AB +:10231000DF93EC0160914B0870914C0880914D085F +:1023200090914E0828EE33E040E050E00E948A2A67 +:10233000C9016AA17BA16217730709F467C03BA3B7 +:102340002AA361E06DA3009709F460C0019764E1DE +:1023500070E00E94012A892B09F058C08C8D2091D1 +:10236000300130913101811113C0232BF9F08DE53B +:1023700093E0909301058093000589E493E09093A6 +:10238000F6048093F50481EF94E0DF91CF910895F6 +:102390004E8D5F8D4217530748F08DE593E0909383 +:1023A00001058093000588E393E0E9CF2091320195 +:1023B000309133019D8D911105C0232B59F08BE293 +:1023C00093E0D7CF48A159A12417350718F08BE225 +:1023D00093E0E5CF8436D0F48C5E8C8F94E6981B26 +:1023E0009D8F8093D7039093D8031092CD0349DA41 +:1023F00081E08CA380913001909131019F8F8E8F6D +:10240000809132019091330199A388A3CE01E7DD39 +:10241000BCCFCF93DF93EC0160914B0870914C08D7 +:1024200080914D0890914E0828EE33E040E050E056 +:102430000E948A2AC9016D8D7E8D62177307A1F0F3 +:102440003E8F2D8F009781F069E070E00E94012A95 +:10245000892B51F48C8D815061F08C8F41E06F8D10 +:102460008C8DD8DB81E088A3CE01B9DDDF91CF91DF +:1024700008958AE08C8F1F8EF1CFCF93DF93EC010C +:1024800080913E018823A1F0EE81FF81608170E0A0 +:1024900090E080E00E94FC2B20912C0130912D01D6 +:1024A00040912E0150912F010E945D2B18162CF0A7 +:1024B0008A819B81DF91CF910895CE0190DDFACF83 +:1024C000B0E0A0E0E6E6F2E10C94C82A8C01FB0142 +:1024D000EA01922E9AE0A92EB12C209711F1BE01AB +:1024E000CF010E94EE296B017C01D801ED91FC9196 +:1024F0000190F081E02D672B19F4C130D10569F40A +:1025000060E36C0DC801099580E3982EF701CE01B8 +:10251000B5010E94012AEB01E0CF692DC8010995A0 +:10252000F5CFCDB7DEB7EBE00C94E42AB0E0A0E045 +:10253000ECE9F2E10C94CB2A8C01CB01BA012DEC31 +:102540003CEC4CE45DE30E94F92A6B017C010E94A3 +:10255000CE2BC62FD0E020E244E650E0BE01C801F9 +:10256000AFDFD801ED91FC910190F081E02D6EE29A +:10257000C8010995BE01DD0F880B990B0E94FC2B49 +:102580009B01AC01C701B6010E94F82A20E030E0AF +:1025900040E251E40E94B02C0E94CE2B70E020E279 +:1025A00041E050E0C8018CDFCDB7DEB7E8E00C9425 +:1025B000E72AA4E1B0E0EFEDF2E10C94C92A8C0126 +:1025C0008091220190912301DC0151962D913C9143 +:1025D000232B09F43FC0209158082223D9F10E94EF +:1025E000AE087C01892B21F48DECE82E83E0F82ED7 +:1025F000D80119968D919C918E159F0551F00E94DE +:10260000E10940E061E0C7010E94F709F801F286A4 +:10261000E186A0902201B0902301D5011496ED909F +:10262000FC90E114F104D1F0F801838594858E15B6 +:102630009F0561F00E94310AD8011C96FC92EE922F +:102640001B9742E061E0C7010E94F7096496EAE047 +:102650000C94E52AFC01E784F088CACFC9D96B0144 +:102660007C01F50181899289892B21F0809158089C +:1026700081112BC060E083E10E94EB09D8015796DD +:10268000EC91F0E0E852FC4F64918EE198E00E94FA +:102690000F0AF80187859089A189B289A70196015F +:1026A000281B390B4A0B5B0BDA01C90185369105F2 +:1026B000A105B10550F0C786D08AE18AF28A8789E0 +:1026C0008F5F843008F0AFC0878BF80183899489CD +:1026D000A589B6890097A105B105A1F0C81AD90A44 +:1026E000EA0AFB0AF9EECF16F3E0DF06E104F10493 +:1026F00048F00E94040AD80153961D921D921D9223 +:102700001C925697E0912201F091230181899289D0 +:10271000892B09F466C060914B0870914C08809138 +:102720004D0890914E0828EE33E040E050E00E94C2 +:102730008A2A79012F3F320709F453C0F8018585B1 +:1027400096858217930709F44CC03687258762E087 +:1027500083E00E94EB09C7016CE370E00E94012A4C +:102760008C01772720E34AE050E08EE198E0A8DE74 +:102770006AE38EE198E00E940F0A20E34AE050E00D +:10278000B8018EE198E09CDEE0912201F0912301F6 +:10279000858986FF4AC0C0902C01D0902D01E09021 +:1027A0002E01F0902F0120E030E0A901C701B60111 +:1027B0000E94AC2C1816ACF462E08CE00E94EB098D +:1027C000B701A6018EE198E0B1DE8091410164ED90 +:1027D00073E0882311F06CEE74E08EE198E00E94C3 +:1027E0002F058091220190912301DC01ED91FC9154 +:1027F0000480F581E02D44E1BE016F5F7F4F0995B4 +:102800008823F1F062E08CE00E94EB098E010F5FFB +:102810001F4FF80161918F01662391F08EE198E0DE +:102820000E940F0AF6CF178A50CF87FFDACFC090E9 +:102830002801D0902901E0902A01F0902B01B3CF1C +:102840008091220190912301DC01ED91FC910680A1 +:10285000F781E02D44E1BE016F5F7F4F099588232A +:1028600009F4F4CE63E081E00E94EB098E010F5F72 +:102870001F4FF80161918F01662309F4E7CE8EE1C5 +:1028800098E00E940F0AF5CF1F93CF93DF93EC01DE +:1028900040E061E08A819B810E94F709EF81F88521 +:1028A000108162E085E00E94EB09612F70E020E278 +:1028B00044E650E08EE198E003DE6D817E818EE19A +:1028C00098E00E942F05DF91CF911F910895EF921C +:1028D000FF921F93CF93DF93FC0112A11123D1F03C +:1028E000EC017C01F6E1EF0EF11C798F688F4A8FC5 +:1028F00064EB73E0C7010E942F0560913401709171 +:10290000350120E240E157E2C701DADDE88DF98DBB +:1029100010821AA2812FDF91CF911F91FF90EF902B +:102920000895FF920F931F93CF93DF93FC01F5A0BF +:10293000FF2039F1EC018C010A5E1F4F718F608F0F +:10294000428F63E773E0C8010E942F056091300158 +:102950007091310120E240E157E2C801B1DD6DE63E +:1029600073E0C8010E942F0560913201709133011C +:1029700020E240E157E2C801A3DDE88DF98D108225 +:102980001DA28F2DCDB7DEB7E5E00C94EA2AFF92A9 +:102990000F931F93CF93DF93FC01F4A0FF20F1F07E +:1029A000EC018C010A5E1F4F718F608F428F648D26 +:1029B00070E020E244E650E0C80182DD6BE673E09F +:1029C000C8010E942F056D8D70E020E244E650E0C2 +:1029D000C80176DDE88DF98D10821CA28F2DCDB750 +:1029E000DEB7E5E00C94EA2A1F93CF93DF93EC0166 +:1029F00018A11123B1F08F8D811118C083E4FB0160 +:102A00008193F98FE88F41504A8F6C8D70E020E3FD +:102A10004AE050E0CE01469653DDE88DF98D1082F4 +:102A200018A2812FDF91CF911F91089587E5E7CFFD +:102A30001F93CF93DF93EB01142F4FEF410F50E023 +:102A4000FB01E40FF51F108260E270E0CE010E94EE +:102A5000132DE0912201F091230181899289892B24 +:102A600031F080915808E2E1F4E0811102C0ECE01D +:102A7000F4E08491115029F0882319F0899331965C +:102A8000F8CFCE01DF91CF911F910895EF92FF9281 +:102A90001F93CF93DF937C01EB018FEF840FFB013A +:102AA000E80FF11D1082D70114969C91992331F003 +:102AB0008EEF840FFB01E80FF11D908311E0180FDA +:102AC000482F50E060E270E0CE010E94132DD70144 +:102AD0001296ED91FC918491115029F0882319F000 +:102AE00089933196F8CFCE01DF91CF911F91FF905E +:102AF000EF900895FF920F931F93CF93DF93EC0114 +:102B00008B01F42E0E94A008882369F084E094E0F1 +:102B10009B838A834F2DB801CE01B8DFCDB7DEB7D6 +:102B2000E5E00C94EA2AE88DF98D8081813029F066 +:102B3000823031F48DEF93E0EBCF86EF93E0E8CF76 +:102B400088EE93E0E5CFEF92FF920F931F93CF9320 +:102B5000DF938C017B01C42F99DFD8011996ED9189 +:102B6000FC911A972081222399F01596ED91FC9102 +:102B700024910196CE0DDF2DD11D8C179D0760F499 +:102B8000222351F0DC012D93CD0131962491F5CF14 +:102B90001796ED91FC91ECCFCDB7DEB7E6E00C9443 +:102BA000E92AEF92FF921F93CF93DF93EC017B0111 +:102BB000142F6CDFA701410F511D98878F83481B8D +:102BC00047FD40E04987EA85FB854081518162816C +:102BD0007381CE010596AADC8F819885DF91CF9114 +:102BE0001F91FF90EF900895EF92FF921F93CF9364 +:102BF000DF93EC017B01142F49DFA701410F511D29 +:102C000098878F83481B47FD40E04987EA85FB850D +:102C10006081718120E240E157E2CE01059650DCEF +:102C20008F819885DF91CF911F91FF90EF9008954C +:102C3000B0E0A0E0EEE1F6E10C94CC2AEC0140E03B +:102C400061E08A819B810E94F7090E94310AED812F +:102C5000FE81D080ED2CF12CC701880F991FEF81E8 +:102C6000F885E80FF91F05911491C8010E94222AE6 +:102C7000282FDD2011F022E0280F89858150990B43 +:102C8000E816F9060CF42E5F84E190E0821B9109AE +:102C900097FD01969595879562E00E94EB09ED817D +:102CA000FE818081882331F06AEC73E08EE198E048 +:102CB0000E942F05B8018EE198E00E942F05ED815A +:102CC000FE81208189858150990B2817190634F4DB +:102CD00067EC73E08EE198E00E942F05CDB7DEB778 +:102CE000E7E00C94E82A0F931F93CF938B01C42F36 +:102CF000CDDEA8014C0F511D481B40310CF04FE0B8 +:102D0000042E000C550B60EE7FE70E94392ACF910C +:102D10001F910F910895B0E0A0E0E1E9F6E10C9475 +:102D2000CC2A8C01EB017B01E40EF51ED990C80181 +:102D30000E94482AD81621F06D2DC8010E94502A01 +:102D40000F5F1F4FEC16FD0689F7CDB7DEB7E7E042 +:102D50000C94E82AA6E0B0E0E0EBF6E10C94D12A6E +:102D600046E050E068EB73E0CE0101960E94392AFC +:102D700046E050E0BE016F5F7F4F80E893E0CBDF1D +:102D800047E150E066E371E086E893E0C4DF269611 +:102D9000E2E00C94ED2A1F93CF93DF93EC01162F02 +:102DA00066FF12C0ED81FE81808129852150330BA1 +:102DB000821713064CF48F5F8083E881F9810280CB +:102DC000F381E02DCE01099517FF0EC0ED81FE8144 +:102DD0008081882349F081508083E881F9810280D5 +:102DE000F381E02DCE01099590E080E014FF02C050 +:102DF000B1DFCE01DF91CF911F910895CF93DF9383 +:102E0000EC01E985FA8581E09081911180E0808371 +:102E1000A1DFCE01DF91CF910895B0E0A0E0E3E122 +:102E2000F7E10C94C22AEC0110E034EDC32E33E03C +:102E3000D32E48E6342E54E4852E6CEEA62E64E0A4 +:102E4000B62E08E274E1972E8D85181708F06CC035 +:102E5000812F90E0880F991FEB85FC85E80FF91F03 +:102E6000A591B491E985FA8580811796ED90FC9043 +:102E7000189781112EC01696BC92AE92159719968E +:102E80000C9319971A969C92F701608170E090E07C +:102E900080E00E94FA2B20E030E040E052E40E9403 +:102EA000F82A26E636E646EE5FE30E94612B2B0108 +:102EB0003C0120E030E0A9010E94AC2C87FF26C035 +:102EC00020E030E040E05FE3C301B2010E94F82A55 +:102ED00025C01696DC92CE92159719963C921997BA +:102EE0001A968C92F701608170E090E080E00E9479 +:102EF000FA2B26E636E646EE5FE30E94B02C20E091 +:102F000030E040E052E40E94F92AD1CF20E030E0E6 +:102F100040E05FE3C301B2010E94F92A0E94C92B7D +:102F2000F70160831F5F90CFCE0168DFCE01CDB780 +:102F3000DEB7E1E10C94DE2A1F93CF93DF93EC011F +:102F4000162F66FF06C0E881F9810684F785E02D1B +:102F5000099517FF07C0E881F9810088F189E02D04 +:102F6000CE01099590E080E014FF02C0F3DECE01AF +:102F7000DF91CF911F910895EF92FF920F931F93CE +:102F8000CF93DF938B01040F151FEB017C01E61A31 +:102F9000F70AC7018C0F9D1F0E94482A8993C0170A +:102FA000D107B9F7CDB7DEB7E6E00C94E92AB0E077 +:102FB000A0E0EDEDF7E10C94C42A04E812E01093D0 +:102FC00022050093210510922405109223051092EA +:102FD000260510922505109228051092270534E445 +:102FE000E32E31E0F32EF0922A05E09229051092AB +:102FF0002B0510922C0510922D0510922E05109283 +:103000002F0580EE94E09093310580933005109267 +:103010003305109232051092350510923405109246 +:10302000360560E089E095E00E94800661E081EF6E +:1030300094E00E9480061093DC040093DB0489E096 +:1030400095E09093DE048093DD041092E0041092EA +:10305000DF041092E2041092E10426E431E03093A0 +:10306000E4042093E3041092E5041092E604109225 +:10307000E7041092E8041092E90428ED34E030935C +:10308000EB042093EA0428E331E03093ED0420932D +:10309000EC0446E3A42E41E0B42EB092EF04A092DB +:1030A000EE0428E12093F0041093C6040093C504B5 +:1030B0009093C8048093C7041092CA041092C90464 +:1030C0001092CC041092CB0428E431E03093CE046B +:1030D0002093CD041092CF041092D0041092D1040A +:1030E0001092D2041092D30441ED54E05093D504D1 +:1030F0004093D4044BE351E05093D7044093D6045B +:10310000C7E3D1E0D093D904C093D8046CE46093B2 +:10311000DA041093B0040093AF049093B204809348 +:10312000B1041092B4041092B3041092B604109239 +:10313000B5044AE451E05093B8044093B7041092A8 +:10314000B9041092BA041092BB041092BC041092FD +:10315000BD04EAECF4E0F093BF04E093BE04E9E3BD +:10316000F1E0F093C104E093C004D093C304C09392 +:10317000C2047AE47093C40410939A0400939904EF +:1031800090939C0480939B0410929E0410929D0443 +:1031900070E4C72E71E0D72ED092A004C0929F0495 +:1031A0003093A2042093A1041092A3041092A404CB +:1031B0001092A5041092A6041092A704E2ECF4E089 +:1031C000F093A904E093A804E2E4F1E0F093AB04E7 +:1031D000E093AA04D093AD04C093AC046093AE0412 +:1031E000109286041092850410928804109287042D +:1031F000EFE38E2EE1E09E2E90928A048092890465 +:1032000030938C0420938B0410928D0410928E04C2 +:1032100010928F041092900410929104AAEBB4E0E3 +:10322000B0939304A0939204E7E2F1E0F093950445 +:10323000E0939404D0939704C093960465E4562ECB +:103240005092980468E772E070938404609383045A +:103250000F2EF9E96F2EF4E07F2EF02D7092070605 +:10326000609206061092090610920806D0920B068C +:10327000C0920A0630930D0620930C0610920E069B +:1032800010920F061092100610921106109212065C +:10329000B0931406A0931306F0931606E093150658 +:1032A000D0931806C093170650921906709305061E +:1032B0006093040610937B0500937A0590937D0537 +:1032C00080937C0510927F0510927E0510928105F7 +:1032D0001092800565E271E070938305609382052A +:1032E000109284051092850510928605109287052C +:1032F0001092880561EB74E070938A0560938905EC +:1033000064E271E070938C0560938B0510928E05DA +:1033100010928D0568E060938F059093630480930D +:103320006204109265041092640410926704109273 +:103330006604309369042093680410926A04109222 +:103340006B0410926C0410926D0410926E0485EA66 +:1033500094E09093700480936F048BE794E09093D3 +:10336000720480937104109274041092730484E4C4 +:1033700080937504109279041092780410927A0464 +:1033800086E692E0909361048093600482E792E085 +:1033900090937704809376040AE000937B04109264 +:1033A0007C0410927D0410927E0410927F0410928F +:1033B0008104109280041092820480E694E090933D +:1033C00048048093470410924A04109249041092D2 +:1033D0004C0410924B0450934E0440934D041092B1 +:1033E0004F04109250041092510410925204109203 +:1033F00053048AE994E090935504809354048BE538 +:1034000094E09093570480935604109259041092BC +:10341000580482E880935A048AE592E09093460427 +:103420008093450400935B0410925C0410925D0449 +:1034300010925E0410925F0485E494E0909322045D +:1034400080932104109224041092230410922604E5 +:10345000109225048BE394E0909328048093270432 +:103460001092290410922A0410922B0410922C041A +:1034700010922D0480E994E090932F0480932E0401 +:103480008AE394E0909331048093300410923304E3 +:1034900010923204109234041092380410923704BF +:1034A0001092390488E492E09093200480931F04E2 +:1034B00084E592E0909336048093350412E01093F3 +:1034C0003A0410923B0410923C0410923E04109275 +:1034D0003D041092400410923F0410924204109256 +:1034E000410410924304109244048FE194E09093BD +:1034F00001048093000410920304109202041092BD +:10350000050410920404F0920704E092060410925D +:1035100008041092090410920A0410920B041092ED +:103520000C0482E894E090930E0480930D0489E1EA +:1035300094E09093100480930F048AE194E09093B8 +:103540001204809311041092130410921704109225 +:1035500016041092180486E392E09093FF03809380 +:10356000FE0382E492E0909315048093140483E0B8 +:10357000782E7092190410921A0410921C04109262 +:103580001B0410921D0410921E048EEF93E0909382 +:10359000E3038093E2031092E5031092E403109298 +:1035A000E7031092E603F092E903E092E803109239 +:1035B000EA031092EB031092EC031092ED031092C9 +:1035C000EE0384E794E09093F0038093EF0310926E +:1035D000F2031092F1031092F4031092F30310928D +:1035E000F5038AE292E09093E1038093E00324E6FE +:1035F00034E03093F7032093F60324E534E030936E +:10360000F9032093F80320EA38E03093FB0320937A +:10361000FA031092FC031092FD0320EE33E0309386 +:1036200047052093460510924905109248051092CF +:103630004B0510924A05F0924D05E0924C05109210 +:103640004E0510924F0510925005109251051092A0 +:10365000520529E434E03093540520935305109229 +:103660005605109255051092580510925705109264 +:10367000590590934505809344058AE394E090931F +:103680005B0580935A058AE294E090935D058093F0 +:103690005C0587EA98E090935F0580935E05109241 +:1036A0006005109261058CE793E090931A0880936F +:1036B000190823E238E030931C0820931B08FF24EC +:1036C000F394F0921D0890931508809314088EE1EE +:1036D00098E0909317088093160884E08093180868 +:1036E0002CE349E351E06EE078E089E098E00E9445 +:1036F0008D052CE34BE351E06EEF77E08EEF97E022 +:103700000E948D052AE048E351E06DEE77E083EFFB +:1037100097E00E948D052EE142E451E06AED77E0EA +:1037200088EE97E00E948D0525E047EC57E061EDBB +:1037300077E08BED97E00E945A068AEB97E0909332 +:10374000D3078093D2071093D40720EF34E030934F +:10375000D6072093D507D093D807C093D7070093F7 +:10376000D907F092DA0786E693E09093D107809329 +:10377000D0074CEA57E05093C8074093C70710930F +:10378000C9073093CB072093CA07B092CD07A09208 +:10379000CC070093CE07F092CF079093C607809393 +:1037A000C50723E047E957E06DE977E088EB97E04C +:1037B0000E945A068FE897E09093B0078093AF0776 +:1037C0001092B10794E5A92E93E0B92EB092AE07FE +:1037D000A092AD072AE8E22E27E0F22EF092B3077E +:1037E000E092B207C4E8D7E0D093B507C093B4071E +:1037F0008EE391E09093B7078093B60782E797E056 +:103800009093A5078093A4071093A6074CEE54E06D +:103810005093A8074093A7079092AA078092A90700 +:1038200038E23093AB0724E12093AC0786E693E0BF +:103830009093A3078093A20761E677E070939A07BD +:103840006093990710939B0750939D0740939C07A3 +:10385000D0929F07C0929E073093A0072093A107A4 +:10386000909398078093970785E597E090938C074E +:1038700080938B0710928D0787EE94E090938F07CB +:1038800080938E0782EE94E0909391078093900747 +:1038900081E491E0909393078093920782E493E010 +:1038A00090938A078093890781E597E09093950725 +:1038B000809394071093960725E04AE357E064E469 +:1038C00077E08CE797E00E945A068DE297E09093AC +:1038D00074078093730710927507B0927207A092D5 +:1038E0007107F0927707E0927607D0937907C0933B +:1038F00078078CE391E090937B0780937A0781E2CD +:1039000097E090936A078093690710936B0780E3B1 +:1039100093E090936807809367078AE391E0909320 +:103920006D0780936C078BE197E090936F0780930E +:103930006E077092700780913A01843010F01092F7 +:103940003A0123E04FE057E065E177E08AE597E050 +:103950000E945A062EE14AE451E06DEF76E08FE4D2 +:1039600097E00E947A052EE14BE451E06BEE76E0A1 +:1039700084E497E00E947A0523E043ED56E069ED88 +:1039800076E087E397E00E945A062EE149E451E091 +:1039900061EC76E08CE297E00E947A052EE148E443 +:1039A00051E06FEA76E081E297E00E947A0523E039 +:1039B00047E956E06DE976E084E197E00E945A0617 +:1039C0002EE147E451E064E876E089E097E00E9468 +:1039D0007A052EE146E451E061E776E08EEF96E06D +:1039E0000E947A0523E048E556E06EE576E081EF37 +:1039F00096E00E945A062EE145E451E068E476E044 +:103A000084EE96E00E947A05CAE1D3E0D093E50601 +:103A1000C093E40689E39CE09093F0068093EF0660 +:103A20002EE144E451E068E376E087ED96E00E9401 +:103A30007A05D093D806C093D7068DE39CE0909387 +:103A4000E3068093E20623E042E256E068E276E095 +:103A50008AEC96E00E945A0625E043E156E06DE1CB +:103A600076E08DEB96E00E945A066EE076E088EBF9 +:103A700096E00E94700688E093E09093B9068093E8 +:103A8000B80663E076E083EB96E00E94700668EF8C +:103A900075E08EEA96E00E94700665EE75E089EAB0 +:103AA00096E00E94700625E04FEC55E069ED75E068 +:103AB0008CE996E00E945A0686EC95E09093950674 +:103AC0008093940682E08093960680E393E090933F +:103AD0009306809392068DE391E0909398068093ED +:103AE000970680EC95E090939A068093990683E080 +:103AF00080939B0680913D01843010F010923D012F +:103B000021E043E451E060EB75E087E896E00E9435 +:103B10007A0525E04CE451E061EA75E08AE796E039 +:103B20000E947A058AE193E090937B0680937A065F +:103B300089EF9BE0909386068093850627E04AE80C +:103B400055E068E975E08DE696E00E945A0681EE40 +:103B500094E0909369068093680682E0F82EF092D4 +:103B60006A0686EF92E0909367068093660689E185 +:103B700098E090936C0680936B0623E043E855E051 +:103B800069E875E089E596E00E945A0621E04FE673 +:103B900055E061E775E08CE496E00E945A0684EEF9 +:103BA00092E090934D0680934C0629E536E050E074 +:103BB00040E070E060E082E396E00E945B0582ED09 +:103BC00092E090933306809332068DE391E09093D8 +:103BD0004B0680934A0629E536E044E056E061E66C +:103BE00075E08AE196E00E945B0525E047E555E037 +:103BF00069E875E087EF95E00E945A066CE475E08D +:103C00008BEE95E00E9470061092F3051092F2057B +:103C10001092F4050AEB12E01093EC050093EB050B +:103C2000CCECD2E0D093F105C093F00580E391E0B5 +:103C30009093F6058093F50561E475E08FED95E0CE +:103C40000E9470061092E7051092E6051092E805B2 +:103C50001093E0050093DF05D093E505C093E405DC +:103C600082E391E09093EA058093E90564E375E0CF +:103C700083ED95E00E9470061092DB051092DA0544 +:103C80001092DC0592EAA92E92E0B92EB092D405EA +:103C9000A092D30524EBC22E22E0D22ED092D905D9 +:103CA000C092D8058CE291E09093DE058093DD050B +:103CB00067E275E087EC95E00E9470061092CF05F0 +:103CC0001092CE051092D005B092C805A092C705FB +:103CD000D092CD05C092CC0588E291E09093D205B8 +:103CE0008093D1056CE175E08BEB95E00E94700646 +:103CF0001092C3051092C2051092C4051093BC0522 +:103D00000093BB05D093C105C093C00584E391E047 +:103D10009093C6058093C50526E040E155E069E82B +:103D200075E088EA95E00E945A0680E992E0909357 +:103D3000A9058093A80588EE93E09093B60580933B +:103D4000B5051092B7051092B8051092B9051092FA +:103D5000BA0528EA35E04AE755E067E075E080E912 +:103D600095E00E945B0530E020E044E455E06EEF12 +:103D700074E082E695E00E945B0525E044EF54E0A4 +:103D800069E875E087E395E00E945A0610922108E1 +:103D900010922008109222088EE893E090931F085A +:103DA00080931E0880914D0190914E01A0914F018A +:103DB000B09150018093250890932608A09327087E +:103DC000B09328088091510190915201A091530124 +:103DD000B09154018093290890932A08A0932B084E +:103DE000B0932C0861E08CE00E94590961E086E004 +:103DF0000E94590961E086E00E94E20761E084E0E8 +:103E00000E9459098BE39DE00197F1F760E08CE097 +:103E10000E94E20760E084E00E94E20763E08EE136 +:103E200098E00E949509CBE4D6E4CE010197F1F722 +:103E300063E08EE198E00E9495092197F1F763E035 +:103E40008EE198E00E94950983E592E00197F1F7F1 +:103E500062E08EE198E00E94950940E068E28EE120 +:103E600098E00E94C909CBEED0E0CE010197F1F7AE +:103E700084E08093230840E06CE08EE198E00E94AB +:103E8000C909CE010197F1F70E94E1098BED9EE28D +:103E90000197F1F7F092240840E066E08EE198E0A7 +:103EA0000E94C9092197F1F71092390888E08093A0 +:103EB0003A088FEF9FEF90933C0880933B08109255 +:103EC00042081092410810923E0810923D0810924C +:103ED000400810923F0887E0809337081092380816 +:103EE00061E088E00E94590961E080913A080E94EF +:103EF000E2070E949C0A60E080913A080E94E20773 +:103F000080913908880F80640E9469078AE00E94C6 +:103F1000690788E00E94690761E080913A080E9481 +:103F2000E20767E970E080E00E940F0887E990E00F +:103F300090933C0880933B0863E870E08CE00E941B +:103F40000F0883E890E090933E0880933D0860E07E +:103F50008AE00E942D0860E089E00E942D0862E05E +:103F600084E10E94590962E085E10E94590961E0FB +:103F700089E00E94590961E085E00E94590961E0E9 +:103F800083E00E94590961E08DE00E94590961E0D7 +:103F90008BE00E94590960E086E10E9459090E9465 +:103FA000EE08109271000E946B080E94540861E0B4 +:103FB000809137080E94590961E0809137080E947A +:103FC000E2070E94CE0A0E94CE0A60E08091370884 +:103FD0000E94E20780E00E9469078093380880E031 +:103FE0000E94690780E00E94690780E00E946907DB +:103FF00080E00E94690761E0809137080E94E20733 +:1040000064E088E10E94340B4AE05AE060E070E02E +:1040100080E10E94C70801E010E020E030E040E0CD +:1040200050E0BA0180E00E94DD0A61E08FE00E946A +:10403000340B68E080E00E94340B04E010E020E0E4 +:1040400030E044E050E060E070E080E00E94DD0A93 +:104050000E94A70880932E080E94A00880932D0834 +:1040600081E090E0A0E0B0E08093430890934408A2 +:10407000A0934508B093460810924708109248084C +:104080001092490810924A0810924B0810924C085E +:1040900010924D0810924E0810924F08109250083E +:1040A000109251081092520810925308109254081E +:1040B000109255081092560880935708809358081C +:1040C00010925908CDB7DEB7EFE00C94E02A1F92AA +:1040D0000F920FB60F9211242F933F934F935F933C +:1040E0006F937F938F939F93AF93BF93CF93DF9300 +:1040F000EF93FF938091210190E09093990080933A +:10410000980061E085E00E94E207C3E0D0E0CE01C4 +:104110000197F1F760E085E00E94E2072197F1F74F +:10412000FF91EF91DF91CF91BF91AF919F918F91CF +:104130007F916F915F914F913F912F910F900FBEA3 +:104140000F901F9018951F920F920FB60F92112487 +:104150002F933F934F935F936F937F938F939F938F +:10416000AF93BF93CF93EF93FF9384E10E94BC077B +:10417000C1E0019709F0C0E085E10E94BC0701970A +:1041800009F4C2608091DA038C1781F0C130C1F16B +:10419000F8F0C23059F1C33071F1C093DA03809165 +:1041A000D9038D3794F18CE78093D903FF91EF9178 +:1041B000CF91BF91AF919F918F917F916F915F91BF +:1041C0004F913F912F910F900FBE0F901F90189518 +:1041D000813031F48091D9038F5F8093D903DDCF93 +:1041E0008230D9F68091D9038150F7CF882391F39B +:1041F000833099F6F7CF823069F3813071F6F2CFD0 +:10420000833041F38111C9CFEDCF8091D903843838 +:104210006CF684E8C9CFA6E0B0E0E1E1F1E20C94ED +:10422000C22A789484B5826084BD84B5816084BDDF +:1042300085B5826085BD85B5816085BD80916E0044 +:10424000816080936E001092810080918100826075 +:1042500080938100809181008160809381008091B2 +:1042600080008160809380008091910082608093C3 +:1042700091008091910081608093910080919000E5 +:104280008160809390008091C10084608093C10020 +:104290008091C10082608093C1008091C1008160E3 +:1042A0008093C1008091C30081608093C30080919E +:1042B000C00082608093C0008091C20081608093C2 +:1042C000C20080917A00846080937A0080917A00A5 +:1042D000826080937A0080917A00816080937A0076 +:1042E00080917A00806880937A001092DF031092A8 +:1042F000AA031092CB038091D70081608093D700EE +:1043000080EA8093D80089B5806189BD89B58260D3 +:1043100089BD09B400FEFDCF61E070E080E090E06F +:104320000E94AA0C8091D8008F7C80618093D80075 +:104330008091E000807F8093E0008091E1008E7E9C +:104340008093E1008DE08093E200559A209AEEEF91 +:10435000FFE7859194918B3F9C4D19F481E0809308 +:10436000A90346E050E0BE016F5F7F4F80E893E015 +:104370000E94BC1746E050E068EB73E0CE01019666 +:104380000E942B2A892B09F0DDC047E150E066E34B +:1043900071E086E893E00E94BC1780914C010E9476 +:1043A000F90B68ED71E080E00E94120A60ED71E0A7 +:1043B00081E00E94120A68EC71E082E00E94120A19 +:1043C00060EC71E083E00E94120A68EB71E084E027 +:1043D0000E94120A62E080E00E94590962E082E0D5 +:1043E0000E94590989E195E09093090180930801A1 +:1043F00080916900806380936900EA9A83E195E087 +:104400009093070180930601809169008C608093EE +:104410006900E99A62E081E00E9459098DE095E027 +:1044200090930B0180930A0180916900806C8093C6 +:104430006900EB9AF8948FEA87BD80916E008260E4 +:1044400080936E001092900010929100109295004F +:104450001092940088EC90E09093990080939800DB +:104460008091910088608093910080919100836099 +:104470008093910010927100789480912201909124 +:104480002301DC01ED91FC910190F081E02D099573 +:10449000809141018111C8C024ED33E03093A80719 +:1044A0002093A70798E69093AB0784E48093AC072A +:1044B00030939D0720939C079093A0078093A107BA +:1044C00082E996E09093FF058093FE0588EA95E0E7 +:1044D0009093A4068093A306909361068093600650 +:1044E00087E395E0909375068093740680910E01A2 +:1044F00090910F01DC01ED91FC910680F781E02D98 +:10450000099580910E0190910F01DC01ED91FC91D4 +:104510000280F381E02D099543E050E060EE7FE7F3 +:104520008CE591E082D708E733243394892B09F492 +:104530001DC10E94E10941E060E084EA91E00E942F +:10454000F709FFCF46E050E06EE971E0CE01019639 +:1045500082D7892B09F021CF109140014CE050E027 +:1045600066E371E086E893E00E94BC178091410108 +:10457000882319F01093400110CF60913F0170E043 +:1045800090E080E00E94FA2B26E636E646EE5FE3F6 +:104590000E94B02C20E030E040E052E40E94F92A72 +:1045A0006B017C0120E030E0A9010E94AC2C20E0EE +:1045B00030E040E05FE387FD2FC0C701B6010E94F5 +:1045C000F92A0E94C92B60933F01612F70E090E0AF +:1045D00080E00E94FA2B26E636E646EE5FE30E9474 +:1045E000B02C20E030E040E052E40E94F92A6B0158 +:1045F0007C0120E030E0A9010E94AC2C20E030E0FA +:1046000040E05FE387FD0CC0C701B601F2D70E940E +:10461000C92B60934001C1CEC701B601E9D7D1CF04 +:10462000C701B601E5D7F3CF2CEE34E03093A807ED +:104630002093A70798E29093AB0784E137CF1092BD +:10464000CE034AE05AE065E070E080E10E94C708CE +:10465000CEC00E94E40460EE71E095958795959533 +:1046600087950E944604BC01990F880B990B0E9404 +:10467000FC2B20E030E040E251E40E94612B60938B +:104680001C0170931D0180931E0190931F012091C6 +:10469000410121110BC026E636E646EE5FE30E949B +:1046A000B02C20E030E040E052E4A3D760932C012E +:1046B00070932D0180932E0190932F012CC180E0E7 +:1046C00090E4ACE1B6E48093AC039093AD03A09387 +:1046D000AE03B093AF0360C1412C512C68EC662E41 +:1046E00062E4762E87C1412C512C50EF652E51E4A7 +:1046F000752E80C11860DDC18091B0038111F0C1B9 +:104700000E94F80C4090B1035090B2036090B30344 +:104710007090B4036419750986099709693E73405E +:104720008105910508F4DCC13092B0031062D8C154 +:10473000992309F4D5C18091B003882329F0109200 +:10474000B0031092B503CCC11061FBCF8091D903A7 +:104750008D3F0CF0D0C18091D9038C5F8093D90339 +:104760001068C9C1E114F10409F070C28091FE0A19 +:104770009091FF0A8737974709F0A8950E94F80C97 +:104780006B017C018091CE03882389F18091CF0356 +:104790009091D003A091D103B091D203A7019601CB +:1047A000281B390B4A0B5B0BDA01C901C297A10523 +:1047B000B105E8F0C092CF03D092D003E092D103CC +:1047C000F092D2039091210180912001891708F085 +:1047D00036CF809121018C3428F0809121018450C2 +:1047E000809321018091210181508093210180914A +:1047F000BA039091BB03A091BC03B091BD03A70184 +:104800009601281B390B4A0B5B0BDA01C901843F67 +:104810009140A105B10548F1C092BA03D092BB0303 +:10482000E092BC03F092BD038091DB03809FC00146 +:10483000112490933101809330011092DB03809119 +:10484000DC03809FC00111249093330180933201D7 +:104850001092DC038091DD03809FC00111249093AE +:104860003501809334011092DD038091B60390915D +:10487000B703A091B803B091B903A7019601281B13 +:10488000390B4A0B5B0BDA01C901843F9140A1054A +:10489000B10508F4D0C0C092B603D092B703E0923D +:1048A000B803F092B9037090AB03772009F4D1CE2E +:1048B0000E94E40464E272E095958795959587954A +:1048C0000E944604BC01990F880B990B95D720E0F4 +:1048D00030E040E251E4F5D660931801709319017D +:1048E00080931A0190931B012091410121110BC06B +:1048F00026E636E646EE5FE30E94B02C20E030E08C +:1049000040E052E476D660932801709329018093A9 +:104910002A0190932B01672D63256093AB038AE0F6 +:104920000E942D086091CD03662309F484C070E0D5 +:1049300090E080E061D79B01AC0160912C01709107 +:104940002D0180912E0190912F0152D64B015C01D7 +:104950002091AC033091AD034091AE035091AF0371 +:1049600048D62B013C0120E030E44CE156E4F4D77A +:1049700018160CF4A4CE20E030E44CE156ECC30150 +:10498000B2019BD687FD9BCE4092AC035092AD0303 +:104990006092AE037092AF032FE632E143E85AE330 +:1049A0006091AC037091AD038091AE039091AF0321 +:1049B000D7D72B013C0120E030E040E251E4C501B3 +:1049C000B401CED79B01AC01C301B20112D62B01B9 +:1049D0003C0120E030E048EC52E4BED718160CF45D +:1049E0007BCE20E030E040EF51E4C301B20165D658 +:1049F00087FD79CE6091D70370E090E080E0FCD62F +:104A0000A30192015AD681110DC06091D80370E0C4 +:104A100090E080E0F1D69B01AC01C301B2014DD61C +:104A2000882349F0C301B201B9D66093D7036093DC +:104A3000D8030E94410C8091CC0310E0811177C013 +:104A40004091D3035091D4036091D5037091D60364 +:104A5000411551056105710599F02091340130919E +:104A60003501232B69F4C41AD50AE60AF70A81E056 +:104A700041EDC41647E0D406E104F10408F480E0F7 +:104A80008093CC030E94A70890912E0810E089170C +:104A900031F012E0811101C011E080932E080E94D4 +:104AA000A00890912D08891731F0882309F422CEAF +:104AB000146080932D0881E00E9471089091B503E5 +:104AC000811136CE911118CE3092B5030E94F80CA8 +:104AD0006093B1037093B2038093B3039093B403D4 +:104AE0008091D90384300CF431CE8091D903845065 +:104AF0008093D903106480913C018823C1F0812FF9 +:104B0000807FA9F04AE0E42E61E089E00E94E2079C +:104B10008BE891E00197F1F760E089E00E94E207FD +:104B20008BE891E00197F1F7EA94E110EDCFC090A6 +:104B30002201D0902301D60155968C9184FF02C0AA +:104B400013FD04C0867029F010FF03C0C6010E9447 +:104B5000F508F6018589867049F011FF07C00E94AB +:104B6000A008811103C0C6010E94040FD601ED9177 +:104B7000FC910280F381E02DC6010995009711F0A8 +:104B80000E940F0980910E0190910F01DC01ED91BF +:104B9000FC910480F581E02D099580910E019091A2 +:104BA0000F01DC01ED91FC910284F385E02D612F72 +:104BB00009957C01B8E084319B07A9F089519840A0 +:104BC00091F080910E0190910F01E816F90659F0CD +:104BD000E0912201F0912301258925FFC3CD26858F +:104BE000222309F4BFCD8091C803882309F4BECDE8 +:104BF00080910E0190910F01DC01ED91FC910084F8 +:104C0000F185E02D09958091C80381508093C803F8 +:104C1000E82FF0E0EE0FFF1FE254FC4FC080D18080 +:104C2000D0920F01C0920E01B4E1EB16B8E0FB0682 +:104C300011F48111DDCF0E94E109D601ED91FC91C3 +:104C40000280F381E02DC601099590CDE091C80363 +:104C5000E53008F08BCD21E02E0F2093C803F0E063 +:104C6000EE0FFF1FE254FC4F91838083F0920F01FF +:104C7000E0920E010E94E109D701ED91FC910680BE +:104C8000F781E02DC701099580910E0190910F01E8 +:104C9000DC01ED91FC910280F381E02DD5CF1F92D4 +:104CA0000F920FB60F9211248F939F938091E10082 +:104CB0009091E100937F9093E10083FF0FC01092E9 +:104CC000E90091E09093EB001092EC0092E3909356 +:104CD000ED001092DF0398E09093F00082FF22C075 +:104CE00093E09093E9009091F200992319F09AE3F0 +:104CF0009093E8009091CA03992341F09091CA03E0 +:104D000091509093CA03911101C05D9A9091DE0376 +:104D1000992341F09091DE0391509093DE0391111D +:104D200001C0289A84FF18C08091E2008E7E8160C5 +:104D30008093E2008091E1008F7E8093E10080917A +:104D4000CB038E7E80618093CB039F918F910F90D8 +:104D50000FBE0F901F90189580FFF7CF8091E20053 +:104D60008E7E80618093E2008091E1008E7E809350 +:104D7000E1008091CB038E7E8160E5CF1F920F9280 +:104D80000FB60F921124CF92DF92EF92FF920F9302 +:104D90001F932F933F934F935F936F937F938F93C3 +:104DA0009F93AF93BF93EF93FF93CF93DF93CDB7D1 +:104DB000DEB76C97DEBFCDBF1092E9008091E800AE +:104DC00083FF25C068E0CE0145960E945C0782EF14 +:104DD0008093E8008D8987FF39C09091E80090FFAB +:104DE000FCCF982F907609F034C19E894F89588D59 +:104DF0002F89F88C911131C0803861F58091AA0318 +:104E00008093F1001092F1008EEF8093E8006C9691 +:104E10000FB6F894DEBF0FBECDBFDF91CF91FF91EB +:104E2000EF91BF91AF919F918F917F916F915F9122 +:104E30004F913F912F911F910F91FF90EF90DF9035 +:104E4000CF900F900FBE0F901F9018959EEF9093EC +:104E5000E800C7CF1092F100D5CF913059F48111FD +:104E6000D3CF4130510581F68091AA038D7F809385 +:104E7000AA03CACF933049F48111C6CF41305105FE +:104E800019F68091AA038260F2CF953041F48091A7 +:104E9000E80080FFFCCF20682093E300B5CF963078 +:104EA00009F0A9C00B8D1C8D22E01092E900109230 +:104EB0009C0310929B03F2122EC010929A03109240 +:104EC00099030E9430071F8299E09983FA8291E04A +:104ED0009E8390EA98879AEF998720919B0330915F +:104EE0009C03275F3F4F3C832B838D831092E90007 +:104EF00010929C0310929B0310939A0300939903C2 +:104F000049E050E0BE016F5F7F4F80E00E940F07D5 +:104F10000E94300779CF10939A03009399030E945F +:104F2000A306DC0112960D911C910115110509F4DF +:104F30003BC1D801ED91FC910480F581E02DBE01CB +:104F40006B5E7F4FC8010995009709F028C1F801F1 +:104F500000851185EACFF3E0FF120EC08F89882308 +:104F600009F440C0823061F440E862E18BE891E0EE +:104F70000E94E506811148CF81E28093EB0047CF84 +:104F8000813029F440E86AE180E791E0F1CF833095 +:104F900099F70E94A306DC011296ED90FC908E0119 +:104FA0000F5F1F4F6801E114F10479F0D701ED9113 +:104FB000FC910680F781E02DB801C7010995080F23 +:104FC000111DF701E084F184EECFD8011C92F601A7 +:104FD00001900020E9F73197BF016C197D0940E08D +:104FE000C601C6CF6AE571E0FB01449150E080E85C +:104FF0000E940F0709CF973009F4BECF983021F4F3 +:1050000081E08093F10000CF993009F0FDCE8370EC +:1050100009F0B2CFE6E5F1E081E031E096E32191DD +:10502000222371F08093E9003093EB00DF011197A8 +:105030002C912093EC009093ED008F5F873079F7EF +:105040008EE78093EA001092EA008F898093DF0355 +:10505000DBCE8B8D9C8D1092E90010929C031092F8 +:105060009B0390939A0380939903898D81117DC04E +:105070008E899D89913A49F4813209F07DCF47E0CC +:1050800050E060E171E080E0B3CF913209F074CF7D +:10509000833269F48F89988DB0E0A0E0809300019D +:1050A00090930101A0930201B0930301ADCE803231 +:1050B00009F080C08091E80082FFFCCF67E080E1CA +:1050C00091E00E945C078BEF8093E8008091A90338 +:1050D000E0E0F8E0882311F0EEEFFAE080911001B3 +:1050E00090911101A0911201B0911301803B944065 +:1050F000A105B105B9F48091170180FD13C0EE3F01 +:105100008AE0F80721F587E797E79183808388E1B4 +:105110009BE00FB6F894A895809360000FBE909323 +:10512000600072CE0FB6F894A895809160008861F7 +:1051300080936000109260000FBEA895EE3FAAE039 +:10514000FA0761F41092FF0A1092FE0A5DCE808188 +:1051500091819093FF0A8093FE0AD5CF8091FE0A39 +:105160009091FF0A918380834FCE0E94A306FC0199 +:10517000028113810115110509F4FECED801ED91CC +:10518000FC910190F081E02DBE016B5E7F4FC80164 +:105190000995811139CEF80100851185EBCF1816DC +:1051A00019060CF431CEE8CEF1E0FF12D4CE6EE554 +:1051B00071E01ACF823209F027CE8F8980931701D0 +:1051C00085CF1F920F920FB60F9211242F933F930A +:1051D0004F935F936F937F938F939F93AF93BF93FF +:1051E000EF93FF93E0910C01F0910D010995FF9170 +:1051F000EF91BF91AF919F918F917F916F915F914F +:105200004F913F912F910F900FBE0F901F901895C7 +:105210001F920F920FB60F9211242F933F934F932B +:105220005F936F937F938F939F93AF93BF93EF930E +:10523000FF93E0910A01F0910B010995FF91EF9125 +:10524000BF91AF919F918F917F916F915F914F919E +:105250003F912F910F900FBE0F901F9018951F92A6 +:105260000F920FB60F9211242F933F934F935F939A +:105270006F937F938F939F93AF93BF93EF93FF931E +:10528000E0910801F09109010995FF91EF91BF911B +:10529000AF919F918F917F916F915F914F913F91CE +:1052A0002F910F900FBE0F901F9018951F920F9285 +:1052B0000FB60F9211242F933F934F935F936F93E9 +:1052C0007F938F939F93AF93BF93EF93FF93E0915F +:1052D0000601F09107010995FF91EF91BF91AF9100 +:1052E0009F918F917F916F915F914F913F912F91FE +:1052F0000F900FBE0F901F9018951F920F920FB630 +:105300000F9211242F933F934F935F936F937F934B +:105310008F939F93AF93BF93EF93FF93E09104011B +:10532000F09105010995FF91EF91BF91AF919F9188 +:105330008F917F916F915F914F913F912F910F903E +:105340000FBE0F901F9018951F920F920FB60F92DD +:1053500011242F933F938F939F93AF93BF9380918B +:10536000910390919203A0919303B0919403309193 +:10537000900323E0230F2D3758F50196A11DB11D91 +:10538000209390038093910390939203A0939303AF +:10539000B09394038091950390919603A091970305 +:1053A000B09198030196A11DB11D80939503909330 +:1053B0009603A0939703B0939803BF91AF919F91E9 +:1053C0008F913F912F910F900FBE0F901F901895C6 +:1053D00026E8230F0296A11DB11DD2CF97FB072E01 +:1053E00016F4009406D077FD08D00BD007FC05D04A +:1053F0003EF4909581959F4F0895709561957F4FEC +:105400000895AA1BBB1B51E107C0AA1FBB1FA6170B +:10541000B70710F0A61BB70B881F991F5A95A9F75D +:1054200080959095BC01CD010895FB01DC0104C07D +:105430008D910590801921F441505040C8F7881B88 +:10544000990B0895FC0105900020E9F7809590954F +:105450008E0F9F1F0895FB01DC014150504030F03A +:105460008D910590801919F40020B9F7881B990BCC +:105470000895FB01DC014150504048F005900D9229 +:105480000020C9F701C01D9241505040E0F7089537 +:10549000F999FECF92BD81BDF89A992780B50895FC +:1054A000262FF999FECF1FBA92BD81BD20BD0FB640 +:1054B000F894FA9AF99A0FBE01960895052E97FB73 +:1054C00016F400940FD057FD05D024D007FC02D06D +:1054D00046F408C050954095309521953F4F4F4F69 +:1054E0005F4F089590958095709561957F4F8F4F90 +:1054F0009F4F089531D0A59F900DB49F900DA49F0C +:10550000800D911D11240895B7FFF4CFF3DF821BA6 +:10551000930B0895A1E21A2EAA1BBB1BFD010DC01F +:10552000AA1FBB1FEE1FFF1FA217B307E407F50753 +:1055300020F0A21BB30BE40BF50B661F771F881F2F +:10554000991F1A9469F760957095809590959B01C5 +:10555000AC01BD01CF010895A29FB001B39FC0016E +:10556000A39F700D811D1124911DB29F700D811D8F +:105570001124911D0895EE0FFF1F0590F491E02D69 +:1055800009942F923F924F925F926F927F928F92E7 +:105590009F92AF92BF92CF92DF92EF92FF920F93C2 +:1055A0001F93CF93DF93CDB7DEB7CA1BDB0B0FB6CC +:1055B000F894DEBF0FBECDBF09942A883988488889 +:1055C0005F846E847D848C849B84AA84B984C8841F +:1055D000DF80EE80FD800C811B81AA81B981CE0F16 +:1055E000D11D0FB6F894DEBF0FBECDBFED010895FB +:1055F0005058BB27AA270ED075C166D130F06BD1A9 +:1056000020F031F49F3F11F41EF45BC10EF4E095DD +:10561000E7FB51C1E92F77D180F3BA17620773070F +:105620008407950718F071F49EF58FC10EF4E0958C +:105630000B2EBA2FA02D0B01B90190010C01CA014C +:10564000A0011124FF27591B99F0593F50F4503EF7 +:1056500068F11A16F040A22F232F342F4427585FE9 +:10566000F3CF469537952795A795F0405395C9F701 +:105670007EF41F16BA0B620B730B840BBAF09150B9 +:10568000A1F0FF0FBB1F661F771F881FC2F70EC058 +:10569000BA0F621F731F841F48F48795779567952B +:1056A000B795F7959E3F08F0B3CF9395880F08F014 +:1056B0009927EE0F979587950895D9D008F481E042 +:1056C00008950CD00FC107D140F0FED030F021F486 +:1056D0005F3F19F0F0C0511139C1F3C014D198F3F4 +:1056E0009923C9F35523B1F3951B550BBB27AA2763 +:1056F00062177307840738F09F5F5F4F220F331FD5 +:10570000441FAA1FA9F333D00E2E3AF0E0E830D0A0 +:1057100091505040E695001CCAF729D0FE2F27D0A3 +:10572000660F771F881FBB1F261737074807AB0771 +:10573000B0E809F0BB0B802DBF01FF2793585F4FE6 +:105740002AF09E3F510568F0B6C000C15F3FECF300 +:10575000983EDCF3869577956795B795F7959F5FAB +:10576000C9F7880F911D9695879597F90895E1E0FF +:10577000660F771F881FBB1F621773078407BA075E +:1057800020F0621B730B840BBA0BEE1F88F7E095B9 +:10579000089504D06894B111D9C00895BCD088F0A0 +:1057A0009F5790F0B92F9927B751A0F0D1F0660F0D +:1057B000771F881F991F1AF0BA95C9F712C0B13028 +:1057C00081F0C3D0B1E00895C0C0672F782F88273B +:1057D000B85F39F0B93FCCF3869577956795B39567 +:1057E000D9F73EF490958095709561957F4F8F4FD6 +:1057F0009F4F0895E89409C097FB3EF490958095DB +:10580000709561957F4F8F4F9F4F9923A9F0F92F86 +:1058100096E9BB279395F695879577956795B79504 +:10582000F111F8CFFAF4BB0F11F460FF1BC06F5FEA +:105830007F4F8F4F9F4F16C0882311F096E911C0FC +:10584000772321F09EE8872F762F05C0662371F01D +:1058500096E8862F70E060E02AF09A95660F771F31 +:10586000881FDAF7880F9695879597F90895990F0D +:105870000008550FAA0BE0E8FEEF16161706E8071A +:10588000F907C0F012161306E407F50798F0621B3B +:10589000730B840B950B39F40A2661F0232B242B10 +:1058A000252B21F408950A2609F4A140A6958FEF2F +:1058B000811D811D089597F99F6780E870E060E081 +:1058C00008959FEF80EC089500240A941616170699 +:1058D00018060906089500240A94121613061406E1 +:1058E00005060895092E0394000C11F4882352F044 +:1058F000BB0F40F4BF2B11F460FF04C06F5F7F4FFC +:105900008F4F9F4F089557FD9058440F551F59F0E2 +:105910005F3F71F04795880F97FB991F61F09F3F9C +:1059200079F087950895121613061406551FF2CFC5 +:105930004695F1DF08C0161617061806991FF1CF15 +:1059400086957105610508940895E894BB2766273C +:105950007727CB0197F908958ADF08F48FEF089530 +:105960000BD0C0CFB1DF28F0B6DF18F0952309F0D7 +:10597000A2CFA7CF1124EACFC6DFA0F3959FD1F322 +:10598000950F50E0551F629FF001729FBB27F00DED +:10599000B11D639FAA27F00DB11DAA1F649F662742 +:1059A000B00DA11D661F829F2227B00DA11D621F91 +:1059B000739FB00DA11D621F839FA00D611D221F4B +:1059C000749F3327A00D611D231F849F600D211D2F +:1059D000822F762F6A2F11249F5750408AF0E1F0D2 +:1059E00088234AF0EE0FFF1FBB1F661F771F881F1B +:1059F00091505040A9F79E3F510570F05CCFA6CF63 +:105A00005F3FECF3983EDCF3869577956795B79505 +:105A1000F795E7959F5FC1F7FE2B880F911D96952F +:105A2000879597F90895DC0101C06D93415050406E +:085A3000E0F70895F894FFCFA0 +:105A3800FFFFFFFF840C840C840C840C840CF70596 +:105A480000E1000000000000000020C2000020C2A9 +:105A5800C8C821050A64640F000020C2000020C2E3 +:105A68000100010001000A010403010301000023F1 +:105A78001E010A641E1E3C463C463C46640A121F30 +:105A8800130040145400C1808100000030315F00D1 +:105A9800000000004E0CCF0EA106A1060C0D0D0B48 +:105AA8000000000046157F067F067F067F067C06FD +:105AB8006F060000000046153E0A7F0657067F065F +:105AC800E20579060000000046154805D9122909A3 +:105AD8002509040D79060F000000070000000300E7 +:105AE80000000100000007000000030000000100A2 +:105AF800000001000000010000000100000001009A +:105B08000000010000000100000001000000010089 +:105B18000000030000000100000001000000010077 +:105B28000000010000000F00000007000000030053 +:105B38000000010000000F00000007000000030043 +:105B48000000010000000100000001000000010049 +:105B580000000100000000000000B40E720EA10653 +:105B6800A10600000000DA0F0912F414A106EAFFEA +:105B780000001F0500000000C60F8711C71491140C +:105B8800EAFF00001F0500000000B70F4911A10639 +:105B9800A10600000000A60FFF10A1066714EAFF87 +:105BA80000001F0500000000670F3D12A106A106B6 +:105BB80000000000670FEF0FA106A106000000001B +:105BC8004615FD0DCF0D57067F06E2057906000044 +:105BD8000000D1157F067F067F067F067C066F06CC +:105BE800FBFF00001F0500000000F4157F067F067C +:105BF8007F067F067C066F06FBFF00001F0500007E +:105C080000007A154805D9122E092509040D7906D0 +:105C1800000000004615970A7F0657066F08E20540 +:105C280079060000000018157F067F067F067F06AC +:105C38007C06450F0000000073167F067F067F066E +:105C48007F067C066F0600000000461544147F0698 +:105C58007F067F069C177906D505B405000000006D +:105C6800461518167F067F067F06CB1679060000B4 +:105C78000000A3157F067F067F067F067C060D17AA +:105C880000000000A3157F067F067F067F067C06BE +:105C9800FE1600000000461544147F067F067F06A6 +:105CA8009C177906C105A0050000000046157F066F +:105CB8007F067F067F067C067906000000000F0A33 +:00000001FF diff --git a/assets/Firmware/Prusa-CW1S-Firmware-en-v3.1.0.hex b/assets/Firmware/Prusa-CW1S-Firmware-en-v3.1.0.hex new file mode 100644 index 00000000..5db3c61d --- /dev/null +++ b/assets/Firmware/Prusa-CW1S-Firmware-en-v3.1.0.hex @@ -0,0 +1,1491 @@ +:10000000DFC300000C94A2290C947B290C94542982 +:100010000C942D2905C4000003C400000C9406298B +:10002000FFC30000FDC300000C9474260C94E3266B +:10003000F7C30000F5C30000F3C30000F1C30000E4 +:10004000EFC30000EDC30000EBC30000E9C30000F4 +:10005000E7C300000C944420E3C300000C94C929BA +:10006000DFC30000DDC30000DBC30000D9C3000014 +:10007000D7C30000D5C30000D3C30000D1C3000024 +:100080000C940820CDC30000CBC30000C9C30000FE +:10009000C7C30000C5C30000C3C30000C1C3000044 +:1000A000BFC30000BDC30000BBC300004472796938 +:1000B0006E6700437572696E6700447279696E6796 +:1000C0002F637572696E6700636F6E74696E756F0A +:1000D0007573006F6E6365006E6F6E6500000000E3 +:1000E00000250028002B002E003100000000002316 +:1000F00000260029002C002F000000000200090F3C +:100100000000030401000C000000000000000000DB +:100110000000000000000000080B000202020100C5 +:10012000090400000102020000052400100105245A +:1001300001010104240206052406000107058103CC +:1001400010004009040100020A0000000705020235 +:100150004000000705830240000004030904120167 +:100160000002EF020140992C0F000001010203017F +:100170005072757361205265736561726368207097 +:100180007275736133642E636F6D004F72696769B6 +:100190006E616C2050727573612043573153004378 +:1001A0005552574100496E636F72726563742066E1 +:1001B00069726D77617265210000110A040A1100ED +:1001C0000000080C0E0C0800000004021F020400CE +:1001D00000040E1F041C00000000100804020100AF +:1001E0000019001D00220028002E00360040004BA0 +:1001F00000580069007C009200AD00CC00F1001AAC +:10020000014A017E01B701F40133027102AF02E835 +:10021000021C034A0372039303AD03C303D303E039 +:1002200003E903F003490053005F006D007D009077 +:1002300000A500BD00D900F8001C0143016E019C1F +:1002400001CE01020237026C02A102D30202032D89 +:1002500003530375039103A903BD03CD03DA03E33D +:1002600003EB03F103F503F803000000002400276B +:10027000002A002D003000040802011040804010C8 +:1002800020408040800802040180402010020110BC +:1002900080102040402004040404040403040502E8 +:1002A0000202020403020202020606060606060411 +:1002B000040202020404054F7665726865617400E9 +:1002C000436C6F73652074686520636F7665720098 +:1002D00052656D6F7665204950412074616E6B00E8 +:1002E000496E73657274204950412074616E6B00D1 +:1002F00000507265737320746F20636F6E74696E43 +:1003000075650046696E69736865640046616E32A2 +:10031000206661696C757265004E6F742F6261644E +:10032000207370696E6E696E67005370696E6E69D6 +:100330006E67207475726E6564206F666600466134 +:100340006E31206661696C75726500202000202086 +:1003500046323A0055564C4544206661696C7572C8 +:1003600065004E6F2F6C6F7720706F77657200524B +:100370006561642074656D7065722E206572726FA0 +:100380007200486561746572206661696C7572659A +:100390000046313A00435731763200206D696E2EA7 +:1003A00000202500203E003C2000506175736564EC +:1003B0000020DF46007C2F2D003E3E003E7C003CAE +:1003C0003C007C3C00447279696E672F63757269EA +:1003D0006E6700437572696E6700447279696E6773 +:1003E0000057617368696E670050617573650043FB +:1003F0006F6E74696E7565002020000706050401A4 +:1004000000080A0B0C0D09436C6F73652074686556 +:1004100020636F766572004F70656E20746865208A +:10042000636F76657200436F7665722074657374CE +:1004300000496E73657274204950412074616E6B7F +:100440000052656D6F7665204950412074616E6B76 +:10045000004950412074616E6B20746573740052C2 +:100460006F746174696F6E20746573740046616E99 +:100470007320746573740055564C4544207465733D +:100480007400486561746572207465737400436F0D +:100490006F6C646F776E005761726D2D75700048D8 +:1004A000656174696E6700437572696E67004472B6 +:1004B00079696E670057617368696E670000005B59 +:1004C000DF465D005BDF435D0020DF43002F3130FE +:1004D00000ED07B4067E069305650553656C6674EA +:1004E00065737400436F6F6C646F776E00ED07E2A5 +:1004F00005D605CA05BE0555564C45442074656DA4 +:10050000702E3A004368616D2E2074656D702E3A2E +:100510000046616E322052504D3A200046616E31E5 +:100520002052504D3A200029061106AF07430664B9 +:1005300006526573696E207072656865617400EDBE +:1005400007486F6C642074686520706C6174666F16 +:10055000726D005D06E807ED0700ED078C07890660 +:1005600050072E077106930653657474696E67739E +:10057000004C4344206272696768746E657373004F +:1005800055564C454420696E74656E7369747900E4 +:10059000BA00B300AC0052756E206D6F646500ED5B +:1005A00007AF06AA06A506A006496E666F726D61C2 +:1005B00074696F6E006361653862626537333664F3 +:1005C00037343739353339004275696C643A203233 +:1005D00033370046573A2076332E312E3000534EB3 +:1005E0003A2000ED070B07F306DB06C10646616EF5 +:1005F0007300ED07CE0646616E73206D656E752043 +:1006000073706565640046616E32206D656E75209D +:10061000737065656400ED07E80646616E732077C8 +:10062000617368696E672073706565640046616E0A +:10063000322077617368696E672073706565640046 +:10064000ED07000746616E7320647279696E67205A +:1006500073706565640046616E3220647279696EFC +:100660006720737065656400ED072307180746610E +:100670006E7320637572696E6720737065656400C0 +:1006800046616E3220637572696E672073706565AE +:10069000640046616E3120637572696E6720737005 +:1006A00065656400ED0745073B07536F756E640091 +:1006B000D800D300C80046696E697368206265651A +:1006C0007000436F6E74726F6C206563686F00ED2D +:1006D00007810776076B075D0754656D706572616A +:1006E00074757265730076076B0754656D702E2004 +:1006F000756E69747300526573696E2070726568F7 +:1007000065617420742E00447279696E6720776188 +:10071000726D2D757020742E005B6F66665D005BD8 +:100720006F6E5D005761726D2D757000ED07A40747 +:100730009907526F746174696F6E20737065656498 +:100740000057617368696E67207370656564004364 +:100750007572696E6720737065656400ED07DD076B +:10076000D207C707BC0752756E2D74696D650052BC +:100770006573696E20707265686561742074696D57 +:10078000650057617368696E672072756E2D7469B4 +:100790006D6500447279696E672072756E2D74699B +:1007A0006D6500437572696E672072756E2D746990 +:1007B0006D650053746F70004261636B0000B81781 +:1007C00011241FBECFEFDAE0DEBFCDBF8091FE0A5D +:1007D0009091FF0A90932F0880932E0813E0A0E0D9 +:1007E000B1E0E2E8FAE502C005900D92A039B10748 +:1007F000D9F728E0A0E9B3E001C01D92AE32B207FC +:10080000E1F713E0C0EED3E004C02197FE010E949F +:10081000E02ACF3DD107C9F70E94DB200C943F2D81 +:10082000EFCBCF92DF92EF92FF921F93CF93DF93A4 +:10083000FB01EE5BFF4F25913491821793070CF07B +:1008400056C0FB0125913491281739070CF052C08E +:1008500013E2A1E2B0E0D0E0C0E021E1115019F4D0 +:1008600090E080E03CC030E0A901440F551FFB013F +:10087000E40FF51FE590F490FA013296E60FF71FAA +:10088000C590D490A901C816D9064CF49D01240F37 +:10089000351F35952795EA01AD01DA01DFCF8E15B9 +:1008A0009F0534F49E01240F351F35952795F5CF0C +:1008B000BC016E197F094EEC4603C001479F900DA5 +:1008C0001124B6016E197F090E94132A4203C00148 +:1008D000439F900D11248E519B4F860F971FDF91E0 +:1008E000CF911F91FF90EF90DF90CF90089580E718 +:1008F0009EEFF5CF82EE94E0F2CF9C01A8EEB3E03C +:100900000E94D12A60931F087093200880932108C9 +:1009100090932208609327087093280880932908F1 +:1009200090932A0880912D08882341F010921F0887 +:1009300010922008109221081092220880911F081E +:1009400090912008A0912108B0912208809323085B +:1009500090932408A0932508B0932608089584E076 +:1009600050E040E0EFEFF3E0949130917B00292FCD +:10097000220F220F20723F7D232B20937B00977044 +:10098000906490937C0090917A00906490937A00A8 +:1009900090917A0096FDFCCF90917800209179009B +:1009A000322F292F420F531F8150F1F6CA010895AB +:1009B000EEEDF3E081818F5F81830895EEEDF3E04A +:1009C00080818F5F80830895FC018481882359F0A2 +:1009D000A281B3816C9382819381019693838283F8 +:1009E00084818150848308950F931F93CF93DF9365 +:1009F0008C01EB01FE0164912196662349F0D80138 +:100A0000ED91FC910190F081E02DC8010995F2CFA4 +:100A1000DF91CF911F910F910895FC0112861186ED +:100A2000148613868FEF9FEF968785871786108A27 +:100A3000118A128A138A148A158A168A178A0895C7 +:100A4000FC017383628383E0848388E991E091836E +:100A500080835683458330872783128611861486C8 +:100A600013868FEF9FEF968785871786108A118AE6 +:100A7000128A138A148A158A168A178A0895FC0125 +:100A80007383628382E0848381EA93E09683858323 +:100A90005087478384E68187228786E693E09183A7 +:100AA00080830895FC017383628382E084838BE9F1 +:100AB00093E09683858350874783218781E08287EF +:100AC00086E693E0918380830895DC011796ED918B +:100AD000FC91189720811A963C911A97321740F48E +:100AE00021502083ED91FC910280F381E02D099546 +:100AF0000895CF93DF93EC01E8DFAF81B885EB85F4 +:100B0000FC858C910995DF91CF910895DC011796B2 +:100B1000ED91FC911897208119963C911997231714 +:100B200040F42F5F2083ED91FC910280F381E02D52 +:100B300009950895CF93DF93EC01E8DFAF81B88585 +:100B4000EB85FC858C910995DF91CF9108950F93EA +:100B50001F93CF93DF93EC01162F862F8C7039F003 +:100B6000E881F9810280F381E02DCE01099516FF1D +:100B700011C08B852C852150330B821713060CF086 +:100B80003FC08F5F8B87E881F9810280F381E02D80 +:100B9000CE01099517FF0DC08B85882309F43BC052 +:100BA00081508B87E881F9810280F381E02DCE01AD +:100BB000099514FF36C0EA858B85E80FFF27FF1FD4 +:100BC000CF01880F991FED81FE81E80FF91F059174 +:100BD0001491D801ED91FC910484F585E02DC801B4 +:100BE0000995009739F108171907F9F4E881F98197 +:100BF0000280F381E02DCE01099590E080E015C0E0 +:100C00008A8529852450330B821713060CF0C2CF36 +:100C10008F5F8A87B8CF8A85882359F281508A8767 +:100C2000C1CF15FFEACF8F819885DF91CF911F91BA +:100C30000F910895C801F9CFFC0113860895FC01B6 +:100C40007383628382E0848386E891E0918380836A +:100C50005683458310861782218712861386253096 +:100C600008F024E0248708950895FC0173836283CB +:100C7000148284E791E091838083089590E080E07E +:100C8000089590E080E008950895FC011382128297 +:100C9000158214821782168284E491E091878087FE +:100CA0001286138614861586168680EF92E0908B46 +:100CB0008787128A118A148A138A80E2858B84E6D8 +:100CC00091E091838083668B178A089580E0089570 +:100CD0008091A10381110DC082E080939D0384E087 +:100CE00080939E031092A00310929F0381E0809353 +:100CF000A1038DE993E0089540919B0350919C03DB +:100D00002091990330919A0342175307B4F49091BC +:100D1000E8009570E1F39091E80092FD19C080938E +:100D2000F10080919B0390919C0301968F7399270A +:100D3000892B19F48EEF8093E80080919B039091AA +:100D40009C03019690939C0380939B0381E00895FC +:100D500080E00895EF92FF920F931F93CF93DF935C +:100D6000EC01E62E042F81E0860F880FC5DF83E0BB +:100D7000C3DFEC0EFD2EF11CCE15DF0599F007FF49 +:100D80000FC0FE018491B8DF182F80E0B5DF81230A +:100D900021968111F1CFCDB7DEB7E6E00C940E2B92 +:100DA0008881F1CF81E0F7CFB0E0A0E0EAEDF6E096 +:100DB0000C94F12AD82E8A01EB017B01E40EF51E7A +:100DC000CE15DF0551F0D7FE0EC0FE01849194DFF1 +:100DD00021968111F5CF0FEF1FEFC801CDB7DEB718 +:100DE000E7E00C940D2B8881F2CFA1E0B0E0EBEFAF +:100DF000F6E00C94F42A82E0898342E450E068E152 +:100E000071E080E8D1DF64DFDC0112960D911C9166 +:100E10000115110589F0D801ED91FC910280F38153 +:100E2000E02DBE016F5F7F4FC801099597FD04C09B +:100E3000F80100851185ECCF89812196E4E00C94BE +:100E4000102B615030F02091F100FC0120830196BD +:100E5000F8CF289884E68093E10308958EBD0000C2 +:100E60000DB407FEFDCF8EB5089581508F3008F088 +:100E700047C0E82FF0E0E15CF84F0C94E02A5C07F3 +:100E800060074E07540758078007800780076307ED +:100E900069076D077107770780077B0780918000DE +:100EA0008F77809380000895809180008F7DF9CFA7 +:100EB00080918000877FF5CF84B58F7784BD0895BA +:100EC00084B58F7DFBCF809190008F7780939000C9 +:100ED0000895809190008F7DF9CF80919000877F59 +:100EE000F5CF8091C0008F778093C00008958091E6 +:100EF000C0008F7DF9CF8091C200877F8093C200B0 +:100F00000895CF93DF93282F30E0F901E750FF4F8A +:100F10008491F901E958FD4FD491F901E956FD4F4B +:100F2000C491CC2379F08111A0DFEC2FF0E0EE0F1B +:100F3000FF1FE551FF4FA591B491EC91ED2381E0A6 +:100F400090E011F490E080E0DF91CF9108951F933D +:100F5000CF93DF93282F30E0F901E750FF4F8491C2 +:100F6000F901E958FD4FD491F901E956FD4FC491BB +:100F7000CC23A1F0162F811178DFEC2FF0E0EE0FDB +:100F8000FF1FE352FF4FA591B4918FB7F894EC91F6 +:100F9000111108C0D095DE23DC938FBFDF91CF9174 +:100FA0001F910895DE2BF8CFFF920F931F93CF93DD +:100FB000DF93F82E8B01CDE0D8E060E08981C7DFB8 +:100FC0008881880F80644ADF8F2D48DF802F46DFBD +:100FD000812F44DF61E08981BADFCDB7DEB7E5E07C +:100FE0000C940F2B9FEF980F9031E8F4E0911508C7 +:100FF000F09116088150990B21E030E0A90102C060 +:10100000440F551F8A95E2F7CA01662369F08E2BBB +:101010009F2B909316088093150860911508709186 +:10102000160882E1C1CF0895809590958E239F2365 +:10103000F0CFCF939091D303981731F0C82F682F3A +:101040008BE0D0DFC093D303CF91089580E0F1DF30 +:101050001092D2031092DD031092DA031092D9039A +:101060001092D8030FB6F894A8958091600088611B +:1010700080936000109260000FBE089561E084E0EC +:10108000B1CF0895FBCF08951F93CF93DF93182F0F +:1010900060E080910E085BDF80910D08880F81640D +:1010A000DDDE82E1DBDE80E0D9DEC82FD0E080E04B +:1010B000D5DED82B61E080910E0849DF212F215029 +:1010C000330BC90121E030E002C0220F331F8A95A3 +:1010D000E2F72C233D2381E0232B09F480E0DF910C +:1010E000CF911F91089582E0CFDF91E0811190E0D0 +:1010F000892F089583E0C8DF91E0811190E0892F66 +:101100000895FC01858984FF06C0EDDF882361F026 +:1011100090E080E00895E7DF811109C0EBDF8111E5 +:10112000F7CF80EC92E0089580EE92E0089580ED94 +:1011300092E00895CF92DF92EF92FF921F93CF93A8 +:10114000DF93182F6A017B01C3E0D8E060E0888557 +:10115000FEDE812F806882DE89878F2D7FDE8E2DD7 +:101160007DDE8D2D7BDE8C2D79DE61E08885EFDEE6 +:101170008985DF91CF911F91FF90EF90DF90CF9005 +:10118000089560E087E02EDF60E083E0E0CE089520 +:10119000CF93DF93EC018D8981FDF3DF8D8982FD93 +:1011A00055DF8B899C89892B19F01092710066DFBD +:1011B00089899A89892B19F081E080932C08DF9125 +:1011C000CF910895CF93DF93EC018091220190910C +:1011D0002301DEDFD0932301C0932201E881F9814E +:1011E0000190F081E02DCE010995DF91CF91089516 +:1011F00084E295E0E7CF0895FC0185819681E2CFF6 +:101200000895CF93DF93EC016EDF882349F08EEDD4 +:1012100094E09E838D83CE01EFDFDF91CF9108951F +:10122000E88DF98D8081813059F0823091F48CE025 +:1012300095E09093CB048093CA0488EC94E002C0BC +:1012400082EB94E0909389048093880486E894E08C +:10125000E0CF82EB94E0EDCFCF93DF9390E0FC0101 +:10126000E958FD4F249189569D4FFC0184918823B4 +:10127000C9F090E0880F991FFC01E759FD4FA59137 +:10128000B491FC01E352FF4FC591D49161110DC09F +:101290009FB7F8948C91209582238C938881282382 +:1012A00028839FBFDF91CF910895623051F49FB79B +:1012B000F8943C91822F809583238C93E8812E2B88 +:1012C000EFCF8FB7F894EC912E2B2C938FBFEACFF2 +:1012D000EF92FF920F931F93CF93DF938C01095FDF +:1012E0001F4FD0E0C0E0E62EF12C61E0F8018191C3 +:1012F0008F01B2DFB7010C2E02C0759567950A9475 +:10130000E2F76170F8013197808121DE2196C430C7 +:10131000D10559F760E084E01ADE61E084E017DE71 +:1013200060E084E014DE83EC90E00197F1F7CDB744 +:10133000DEB7E6E00C940E2B1F93CF93DF93EC0106 +:10134000162F642F8CE003DE612F70E084E075952A +:1013500067958A95E1F7CE01BBDF612FCE01B8DF3B +:10136000DF91CF911F91089540E061E082EF97E017 +:10137000E3DF8BEF98E10197F1F70895E62FF0E0B6 +:10138000EE50F84F6385680F606840E082EF97E0A9 +:10139000D3CF0895CF93DF93EC01862F642FEEDF38 +:1013A000BE0182EF97E020DBDF91CF91089542E00C +:1013B00068E088EF93E0EEDF42E061E088EF93E0E1 +:1013C000E9CF089541E0B8CF08950F931F93CF93CD +:1013D000DF93EB0198E0899FB0011124606440E045 +:1013E00082EF97E0A9DF8E01085F1F4FFE01649135 +:1013F00082EF97E0E7DF21960C171D07B9F7DF9121 +:10140000CF911F910F910895CF9362E080E0B6DFF6 +:10141000C4E160E282EF97E0D5DFC150D1F7CF9110 +:101420000895CF92DF92EF92FF921F93CF93DF93B5 +:10143000CDB7DEB764970FB6F894DEBF0FBECDBF51 +:101440007C0110E0D7011C968C911817A8F5612F2C +:1014500080E094DFF70183856EE3811360E282EF21 +:1014600097E0B0DFD7011A96EC911A97E10FFF27AA +:10147000FF1FCF01880F991F1596ED91FC91E80F82 +:10148000F91F85919491DC01ED91FC910190F0811F +:10149000E02D44E1BE016F5F7F4F0995FE0131965B +:1014A0006F01D6016D916D01662321F082EF97E007 +:1014B00089DFF7CF1F5FC6CF64960FB6F894DEBF03 +:1014C0000FBECDBFDF91CF911F91FF90EF90DF90C6 +:1014D000CF900895A6DF60E084E084CD0895CF9397 +:1014E000CFB7F8948091C903811123C0E8EAF2E0F4 +:1014F0008491E8E8F2E09491E82FF0E0EE0FFF1F0E +:10150000E759FD4FA591B491EC91E92319F461E0FD +:1015100081E11DDD61E081E19FDE8CB580618CBDE4 +:101520008CB580648CBD61E08FE096DE61E080E187 +:1015300093DE8091C9038F5F8093C903CFBFCF91A2 +:1015400008958CB58C608CBD8CB58F7D8CBD8CB5B1 +:101550008C7F81608CBD8DB581608DBDC0CF0895BD +:10156000B0E0A0E0E6EBFAE00C94E72A382E2A017E +:101570003B0148015901E5DFC3E0D8E060E0888520 +:10158000E6DC832D6BDC898780E068DC80E066DC4C +:1015900080E064DC80E062DC61E08885D8DC60E0CB +:1015A0008885D5DC832D5ADC898780E057DC082FBD +:1015B00080E054DCC82E80E051DC182F80E04EDC47 +:1015C000D12CF12CE12CD02AFE2CED2CDC2CCC24BF +:1015D000C12AFE2CED2CDC2CCC24C82A61E08885A5 +:1015E000B6DCB301A2014C255D256E257F2548217F +:1015F00059216A217B214C255D256E257F25832D70 +:1016000099DD8985CDB7DEB7E1E10C94032B0F930B +:101610001F9394E0899FF0011124EA55FE4F008149 +:10162000118122813381082E04C0000F111F221F57 +:10163000331F0A94D2F7462F50E070E060E004C0F8 +:10164000440F551F661F771F8A95D2F78CE688DFF7 +:1016500080910C081F910F9108951F93CF93DF93F2 +:10166000182FEB0161E0F8DD209739F460E0812F5D +:101670006EDCDF91CF911F910895CF3FD10511F41A +:1016800061E0F5CFE12FF0E0E750FF4FE491E1504A +:10169000EF3008F07CC0F0E0E05BF44F0C94E02AFF +:1016A0005F0B640B690B730B7D0BC70BC70BC70B71 +:1016B000870B910B9B0BA50BB20BC70BBA0B84B519 +:1016C000806884BDC7BDD5CF84B5806284BDC8BDE8 +:1016D000D0CF80918000806880938000D093890073 +:1016E000C0938800C6CF8091800080628093800084 +:1016F000D0938B00C0938A00BCCF8091800088601B +:1017000080938000D0938D00C0938C00B2CF8091E5 +:101710009000806880939000D0939900C0939800C7 +:10172000A8CF80919000806280939000D0939B001E +:10173000C0939A009ECF8091900088608093900023 +:10174000D0939D00C0939C0094CF8091C00080688E +:101750008093C0008091C0008F7B8093C000C093B5 +:10176000CF0087CF8091C00080628093C000C0937B +:10177000D0007FCF8091C20088608093C2008091AA +:10178000C2008B7F8093C200C093D20072CFC0385A +:10179000D1050CF075CF6ACF282F30E0AFEFB0E065 +:1017A0000E94D12A24E630E040E050E00E94832AE3 +:1017B000B90186E052CF0895CF93DF9390E0FC010A +:1017C000E459FE4FD08182599E4FFC01C0816623AF +:1017D000E1F0A62FB0E021E03FEF4FEF5FEF0E9476 +:1017E0009F2A24E630E040E050E00E94832ACA01AC +:1017F000B90161507F4F8F4F9F4F8C2F2EDF61E0DB +:101800008D2FF0DBDF91CF91089560E08D2FEADB23 +:1018100060E08C2F9CDBF6CF682F81E0CDCF089560 +:10182000CF93DF93C4EDD3E0688180E0C5DF6981A9 +:1018300081E0C2DFDF91CF910895FC01168681E03F +:10184000878B81E090E0A0E0B0E082879387A48757 +:10185000B5878689811106C080913A018823E1F01D +:101860008230F1F4178A81EF92E023E033E0309385 +:101870001C0520931B05909311058093100500848F +:10188000F185E02D80818093D40381818093D503FD +:101890001092CC03C5CF0895128613861486158640 +:1018A00080EF92E0E2CF08953FB7F89480919503DE +:1018B00090919603A0919703B091980326B5A89BA9 +:1018C00005C02F3F19F00196A11DB11D3FBFBA2FD2 +:1018D000A92F982F8827BC01CD01620F711D811D92 +:1018E000911D42E0660F771F881F991F4A95D1F717 +:1018F00008958F929F92AF92BF92CF92DF92EF9214 +:10190000FF924B015C01D0DF6B017C01CDDF6C19D4 +:101910007D098E099F09683E734081059105B0F3EA +:1019200021E0821A9108A108B10888EEC80E83E070 +:10193000D81EE11CF11C81149104A104B10431F7FB +:10194000FF90EF90DF90CF90BF90AF909F908F90DF +:1019500008956CED70E089E080DE62E370E080E085 +:1019600090E0C7DF60E089E0F2DA6AEF70E080E0E3 +:1019700090E0BFDF6CED70E089E06FDE62E370E065 +:1019800080E090E0B6DF60E089E0E1CA08952FB71B +:10199000F8946091910370919203809193039091D8 +:1019A00094032FBF0895CF92DF92EF92FF920F938F +:1019B0001F93CF938C01C62F862F8F7029F08FEF46 +:1019C0009FEFF80196878587C6FF4AC0E091220104 +:1019D000F091230181899289892B09F441C060919A +:1019E0001F0870912008809121089091220838EEFC +:1019F000C32E33E0D32EE12CF12CA70196010E94D7 +:101A0000AF2A2F3F3F4F61F1D2DCE0912201F091EC +:101A1000230181899289892B19F1858983FF20C04F +:101A200060911F08709120088091210890912208F0 +:101A3000A70196010E94AF2A2B3382E0380708F0F5 +:101A40007AC0C9014E960E947D0489EB93E042E082 +:101A500068E0A0DC9CDFF801638B748B858B968B30 +:101A6000C7FF4AC0E0912201F09123018189928948 +:101A7000892B09F441C060911F0870912008809162 +:101A800021089091220828EEC22E23E0D22EE12CCC +:101A9000F12CA70196010E94AF2A2F3F3F4F61F121 +:101AA00086DCE0912201F091230181899289892BC2 +:101AB00019F1858983FF20C060911F08709120086B +:101AC0008091210890912208A70196010E94AF2AD7 +:101AD00082EC93E02E31310530F0C9014E970E941F +:101AE0007D048FEB93E042E061E054DC50DFF801CD +:101AF000638B748B858B968BC4FF12C0E09122019F +:101B0000F0912301858985FD11C0F80187819085B9 +:101B1000CF911F910F91FF90EF90DF90CF9008959C +:101B2000C5FF06C0E0912201F091230181E0868784 +:101B300090E080E0EDCF8CEB93E089CFB0E0A0E0C7 +:101B4000E4EAFDE00C94F02AEC0121DF0F8518890E +:101B500029893A896B017C01C01AD10AE20AF30A89 +:101B6000970186014D855E856A01F12CE12CC01636 +:101B7000D106E206F30658F46F87788B898B9A8B2F +:101B8000E881F9810280F381E02DCE010995CDB77E +:101B9000DEB7E8E00C940C2BCF93DF93EC01F7DE7B +:101BA0006F87788B898B9A8BCE013BDCDF91CF914D +:101BB0000895CF92DF92EF92FF92CF93DF93C62FDB +:101BC000D42F90E0B0E0A0E06C017D0121E0C21ACA +:101BD000D108E108F1086623C1F14FE15FE165E05A +:101BE00070E080E1A7DA64E088E111DDAAECBFEFE4 +:101BF000A70196010E94AB2A29E030E040E050E0C6 +:101C00000E94832ADA01C9018A5B9F4FAF4FBF4F01 +:101C1000DD2361F080932101C0E0C093CD03DF910B +:101C2000CF91FF90EF90DF90CF90089580932001A7 +:101C300088EC80932101ABDE6093CE037093CF03D9 +:101C40008093D0039093D103E8CF4AE05AE060E05C +:101C500070E080E16FDA60E088E1D9DCADE3BFEFEE +:101C6000A70196010E94AB2A29E030E040E050E055 +:101C70000E94832A24523F4F4F4F5F4F20932101F0 +:101C8000CCCFB0E0A0E0E7E4FEE00C94F02AEC0159 +:101C90008E85811103C08C8D811108C05ADE8A8126 +:101CA0009B81CDB7DEB7E8E00C940C2B70DE0A8583 +:101CB0001B852C853D856B017C01C01AD10AE20A87 +:101CC000F30A970186010B3F11052105310518F430 +:101CD00090E080E0E6CF6A877B878C879D87EA8DDE +:101CE000FB8D09959D8D981799F38D8F882341F071 +:101CF0008E899F899D838C838C8D81508C8FE8CFBA +:101D0000888D998DF7CFCF93DF93EC011E86EA8DF6 +:101D1000FB8D09958D8F882371F08E899F899D8316 +:101D20008C838AE08C8F33DE6A877B878C879D87E4 +:101D3000DF91CF910895888D998DF1CFCF92DF9269 +:101D4000EF92FF92CF93DF93EC018F898E871FDE96 +:101D50006B017C018A859B85AC85BD850097A105BB +:101D6000B10591F0A7019601281B390B4A0B5B0BBB +:101D7000DA01C901893E9340A105B10528F0E9DDEA +:101D8000CA86DB86EC86FD868E85882349F08A81AB +:101D90009B81DF91CF91FF90EF90DF90CF900895DE +:101DA00090E080E0F6CFCF93DF93EC01EB89FC89E4 +:101DB000309771F06D896295617040E08081F9DE45 +:101DC0008091710082608093710060E084E00AD9A4 +:101DD0008D8982FF10C081E08093D2038093DD0360 +:101DE000D6DD88E198E20FB6F894A895809360005C +:101DF0000FBE9093600089899A89892B39F01092DF +:101E00002C0880912B08811110922B08C0DD6A8765 +:101E10007B878C879D87DF91CF9108950F931F93C8 +:101E2000CF93DF938C01C0912201D0912301898946 +:101E30009A89892B51F080912C08882371F0CE016A +:101E400060D9892B11F4CE01AEDFF801858196812E +:101E5000DF91CF911F910F910895CE0199D9F5CFC0 +:101E6000CF93DF93EC011E86E885F985808180930E +:101E7000D40381818093D5031092CC03D1DCE9890E +:101E8000FA89309771F080818C3308F08BE39D895B +:101E9000917090932D082CE3829FC00111240E9421 +:101EA0007D048D89867069F025D9811107C08989E3 +:101EB0009A89892B59F4CE016BD905C014D98111A7 +:101EC000F6CFCE0170DFDF91CF91089510922C08EC +:101ED00080912B08882379F310922B08ECCF409146 +:101EE0001C0150911D0160911E0170911F01FC01A8 +:101EF000448F558F668F778F21E022A3B1CF08954D +:101F0000409118015091190160911A0170911B01C3 +:101F1000FC01478B508F618F728FA2CF0895FC0117 +:101F2000148E84E6858F178E168E8FEF9FEF91A308 +:101F300080A388E790E093A382A381E084A385A394 +:101F4000CF018ECF0895CF93DF93EC018AE08C8F81 +:101F500084EB90E09E8F8D8F81E08F8F88A3CE01E0 +:101F60007FDF40E06F8D8C8D24DEDF91CF9108956F +:101F7000CF92DF92EF92FF92CF93DF93EC018989AA +:101F80009A89892B09F461C080912B0881115DC069 +:101F900080912C08811159C0FADCDC01CB01409101 +:101FA0001708509118086091190870911A08C0908C +:101FB0001B08D0901C08E0901D08F0901E088C199A +:101FC0009D09AE09BF0984179507A607B707E8F171 +:101FD00080911F0890912008A0912108B0912208BB +:101FE00020912D08222309F444C0C0902708D090E6 +:101FF0002808E0902908F0902A088C159D05AE0568 +:10200000BF0568F4840F951FA61FB71F80931F0894 +:1020100090932008A0932108B09322080DC081E07E +:1020200080932C0880932B0810921F081092200890 +:102030001092210810922208AADC60931B0870936A +:102040001C0880931D0890931E088E85811108C07E +:1020500089899A89892B21F180912B08882301F1A4 +:102060008A819B81DF91CF91FF90EF90DF90CF909D +:1020700008950097A105B10529F0841B950BA60BC7 +:10208000B70BC4CF81E080932C0880932B088091FC +:10209000270890912808A0912908B0912A08B6CF66 +:1020A0008D8981FF33C0C0901801D0901901E09054 +:1020B0001A01F0901B0120E030E0A901C701B60130 +:1020C0000E94822B87FF0FC084E593E09093040564 +:1020D000809303058FE693E09093F9048093F804CE +:1020E00084EF94E0BFCF20E030E04CE852E4C70139 +:1020F000B6010E94D12C18164CF484E593E090931D +:1021000004058093030587EB92E0E6CF8A859B85E3 +:10211000AC85BD85892B8A2B8B2B19F490E080E050 +:10212000A1CF35DCCA84DB84EC84FD846C197D0985 +:102130008E099F09613D77408105910578F38D896E +:1021400081FFECCF2091430130E0AFEFB0E00E947F +:10215000D12A24E630E040E050E00E94832AB90111 +:1021600083E07BDA61E087E00E94F2071A861B8633 +:102170001C861D86D3CFB0E0A0E0E1ECF0E10C942A +:10218000EC2AEC018C8C9D8CAE8CBF8C20E030E076 +:10219000A901C501B4010E94822B87FD11C0C09026 +:1021A0001C01D0901D01E0901E01F0901F0120E065 +:1021B00030E0A901C701B6010E94822B87FF13C03E +:1021C00082E893E090930405809303058FE693E003 +:1021D0009093F9048093F80484EF94E0CDB7DEB7D0 +:1021E000ECE00C94082B60911F08709120088091FE +:1021F00021089091220828EE33E040E050E00E9450 +:10220000AF2A890101501109C9F420E030E040EA09 +:1022100050E4C501B4010E941E2B9B01AC01C70113 +:10222000B6010E94822B87FF09C082E893E0909359 +:1022300004058093030582E693E0CACF88A199A1A3 +:102240008017910721F019A308A381E08AA3CE018A +:102250008FDEC4CFCF93DF93EC0160911F087091A4 +:102260002008809121089091220828EE33E040E078 +:1022700050E00E94AF2A2130310539F520E030E0EE +:1022800040E251E46F89788D898D9A8D0E941E2BD2 +:10229000209118013091190140911A0150911B01B0 +:1022A0000E94D12C18168CF484E593E090930405D9 +:1022B0008093030582E693E09093F9048093F804F9 +:1022C00084EF94E0DF91CF910895CE0151DEFACFF3 +:1022D000CF93DF93EC0160911F08709120088091EB +:1022E00021089091220828EE33E040E050E00E945F +:1022F000AF2AC9016AA17BA16217730709F467C0FD +:102300003BA32AA361E06DA3009709F460C0019785 +:1023100064E170E00E94262A892B09F058C08C8D58 +:102320002091300130913101811113C0232BF9F03C +:102330008EE393E090930405809303058AE293E093 +:102340009093F9048093F80484EF94E0DF91CF91A7 +:1023500008954E8D5F8D4217530748F08EE393E04A +:10236000909304058093030589E193E0E9CF2091E0 +:102370003201309133019D8D911105C0232B59F00D +:102380008CE093E0D7CF48A159A12417350718F066 +:102390008CE093E0E5CF8436D0F48C5E8C8F94E6AD +:1023A000981B9D8F8093D4039093D5031092CC03F8 +:1023B00037DA81E08CA380913001909131019F8FB9 +:1023C0008E8F809132019091330199A388A3CE0121 +:1023D000CFDDBCCFCF93DF93EC0160911F087091EC +:1023E0002008809121089091220828EE33E040E0F7 +:1023F00050E00E94AF2AC9016D8D7E8D6217730770 +:10240000A1F03E8F2D8F009781F069E070E00E946F +:10241000262A892B51F48C8D815061F08C8F41E0FC +:102420006F8D8C8DC6DB81E088A3CE01A1DDDF91AD +:10243000CF9108958AE08C8F1F8EF1CFCF93DF93D9 +:10244000EC0180913E018823A1F0EE81FF81608143 +:1024500070E090E080E00E94212C20912C013091CE +:102460002D0140912E0150912F010E94822B1816B0 +:102470002CF08A819B81DF91CF910895CE0178DD88 +:10248000FACFB0E0A0E0E7E4F2E10C94ED2A8C0191 +:10249000FB01EA01922E9AE0A92EB12C209711F1AE +:1024A000BE01CF010E94132A6B017C01D801ED917E +:1024B000FC910190F081E02D672B19F4C130D1051A +:1024C00069F460E36C0DC801099580E3982EF7016B +:1024D000CE01B5010E94262AEB01E0CF692DC8018B +:1024E0000995F5CFCDB7DEB7EBE00C94092BB0E042 +:1024F000A0E0EDE7F2E10C94F02A8C01CB01BA01E7 +:102500002DEC3CEC4CE45DE30E941E2B6B017C0146 +:102510000E94F32BC62FD0E020E244E650E0BE013B +:10252000C801AFDFD801ED91FC910190F081E02D61 +:102530006EE2C8010995BE01DD0F880B990B0E9460 +:10254000212C9B01AC01C701B6010E941D2B20E08C +:1025500030E040E251E40E94D52C0E94F32B70E061 +:1025600020E241E050E0C8018CDFCDB7DEB7E8E003 +:102570000C940C2BA4E1B0E0E0ECF2E10C94EE2A18 +:102580008C018091220190912301DC0151962D91C3 +:102590003C91232B09F43FC020912C082223D9F130 +:1025A0000E9481087C01892B21F48AEAE82E83E0CD +:1025B000F82ED80119968D919C918E159F0551F09A +:1025C0000E94B40940E061E0C7010E94CA09F80115 +:1025D000F286E186A0902201B0902301D5011496E5 +:1025E000ED90FC90E114F104D1F0F801838594851D +:1025F0008E159F0561F00E94040AD8011C96FC927A +:10260000EE921B9742E061E0C7010E94CA096496FE +:10261000EAE00C940A2BFC01E784F088CACFB7D912 +:102620006B017C01F50181899289892B21F08091D0 +:102630002C0881112BC060E083E10E94BE09D80103 +:102640005796EC91F0E0EB54FC4F649182EF97E0E9 +:102650000E94E209F80187859089A189B289A701C2 +:102660009601281B390B4A0B5B0BDA01C901853631 +:102670009105A105B10550F0C786D08AE18AF28A9A +:1026800087898F5F843008F0AFC0878BF80183891A +:102690009489A589B6890097A105B105A1F0C81A4A +:1026A000D90AEA0AFB0AF9EECF16F3E0DF06E104E5 +:1026B000F10448F00E94D709D80153961D921D924B +:1026C0001D921C925697E0912201F091230181897D +:1026D0009289892B09F466C060911F0870912008C7 +:1026E000809121089091220828EE33E040E050E0EC +:1026F0000E94AF2A79012F3F320709F453C0F80135 +:10270000858596858217930709F44CC036872587FF +:1027100062E083E00E94BE09C7016CE370E00E94A2 +:10272000262A8C01772720E34AE050E082EF97E0E9 +:10273000A8DE6AE382EF97E00E94E20920E34AE024 +:1027400050E0B80182EF97E09CDEE0912201F09129 +:102750002301858986FF4AC0C0902C01D0902D01AD +:10276000E0902E01F0902F0120E030E0A901C70198 +:10277000B6010E94D12C1816ACF462E08CE00E94E5 +:10278000BE09B701A60182EF97E0B1DE8091410159 +:1027900061EB73E0882311F069EC74E082EF97E05D +:1027A0000E94F4048091220190912301DC01ED91BB +:1027B000FC910480F581E02D44E1BE016F5F7F4F05 +:1027C00009958823F1F062E08CE00E94BE098E0139 +:1027D0000F5F1F4FF80161918F01662391F082EF27 +:1027E00097E00E94E209F6CF178A50CF87FFDACF31 +:1027F000C0902801D0902901E0902A01F0902B018F +:10280000B3CF8091220190912301DC01ED91FC91E5 +:102810000680F781E02D44E1BE016F5F7F4F09958F +:10282000882309F4F4CE63E081E00E94BE098E01A2 +:102830000F5F1F4FF80161918F01662309F4E7CE06 +:1028400082EF97E00E94E209F5CF1F93CF93DF93C9 +:10285000EC0140E061E08A819B810E94CA09EF811E +:10286000F885108162E085E00E94BE09612F70E06A +:1028700020E244E650E082EF97E003DE6D817E8146 +:1028800082EF97E00E94F404DF91CF911F910895A9 +:10289000EF92FF921F93CF93DF93FC0112A11123BC +:1028A000D1F0EC017C01F6E1EF0EF11C798F688F1D +:1028B0004A8F61E973E0C7010E94F404609130011E +:1028C0007091310120E240E157E2C701DADDE88D85 +:1028D000F98D10821AA2812FDF91CF911F91FF9065 +:1028E000EF900895FF920F931F93CF93DF93FC0116 +:1028F000F5A0FF2039F1EC018C010A5E1F4F718FAA +:10290000608F428F61E973E0C8010E94F404609116 +:1029100030017091310120E240E157E2C801B1DDA0 +:102920006EE473E0C8010E94F4046091320170917A +:10293000330120E240E157E2C801A3DDE88DF98DC3 +:1029400010821DA28F2DCDB7DEB7E5E00C940F2BC2 +:10295000FF920F931F93CF93DF93FC01F4A0FF200E +:10296000F1F0EC018C010A5E1F4F718F608F428F76 +:10297000648D70E020E244E650E0C80182DD6CE442 +:1029800073E0C8010E94F4046D8D70E020E244E61B +:1029900050E0C80176DDE88DF98D10821CA28F2DE4 +:1029A000CDB7DEB7E5E00C940F2B1F93CF93DF93E9 +:1029B000EC0118A11123B1F08F8D811118C083E4AF +:1029C000FB018193F98FE88F41504A8F6C8D70E045 +:1029D00020E34AE050E0CE01469653DDE88DF98DC4 +:1029E000108218A2812FDF91CF911F91089587E562 +:1029F000E7CF1F93CF93DF93EB01142F4FEF410FDE +:102A000050E0FB01E40FF51F108260E270E0CE01A0 +:102A10000E94382DE0912201F09123018189928951 +:102A2000892B31F080912C08EFEEF3E0811102C088 +:102A3000E9EEF3E08491115029F0882319F089938D +:102A40003196F8CFCE01DF91CF911F910895EF928B +:102A5000FF921F93CF93DF937C01EB018FEF840FE5 +:102A6000FB01E80FF11D1082D70114969C91992368 +:102A700031F08EEF840FFB01E80FF11D908311E020 +:102A8000180F482F50E060E270E0CE010E94382D10 +:102A9000D7011296ED91FC918491115029F0882371 +:102AA00019F089933196F8CFCE01DF91CF911F9124 +:102AB000FF90EF900895FF920F931F93CF93DF93B2 +:102AC000EC018B01F42E0E947308882369F081EEDB +:102AD00093E09B838A834F2DB801CE01B8DFCDB739 +:102AE000DEB7E5E00C940F2BE88DF98D8081813005 +:102AF00029F0823031F48AED93E0EBCF83ED93E05F +:102B0000E8CF85EC93E0E5CFEF92FF920F931F9310 +:102B1000CF93DF938C017B01C42F99DFD8011996E5 +:102B2000ED91FC911A972081222399F01596ED9151 +:102B3000FC9124910196CE0DDF2DD11D8C179D07A0 +:102B400060F4222351F0DC012D93CD0131962491C4 +:102B5000F5CF1796ED91FC91ECCFCDB7DEB7E6E05F +:102B60000C940E2BEF92FF921F93CF93DF93EC0107 +:102B70007B01142F6CDFA701410F511D98878F83B4 +:102B8000481B47FD40E04987EA85FB85408151812C +:102B900062817381CE010596AADC8F819885DF91D1 +:102BA000CF911F91FF90EF900895EF92FF921F93A6 +:102BB000CF93DF93EC017B01142F49DFA701410F75 +:102BC000511D98878F83481B47FD40E04987EA8560 +:102BD000FB856081718120E240E157E2CE010596DC +:102BE00050DC8F819885DF91CF911F91FF90EF90FE +:102BF0000895B0E0A0E0EFEFF5E10C94F12AEC01CC +:102C000040E061E08A819B810E94CA090E94040A17 +:102C1000ED81FE81D080ED2CF12CC701880F991F2A +:102C2000EF81F885E80FF91F05911491C8010E9402 +:102C3000472A282FDD2011F022E0280F89858150B6 +:102C4000990BE816F9060CF42E5F84E190E0821BE4 +:102C5000910997FD01969595879562E00E94BE09BE +:102C6000ED81FE818081882331F067EA73E082EF95 +:102C700097E00E94F404B80182EF97E00E94F40408 +:102C8000ED81FE81208189858150990B28171906D5 +:102C900034F464EA73E082EF97E00E94F404CDB765 +:102CA000DEB7E7E00C940D2B0F931F93CF938B01AE +:102CB000C42FCDDEA8014C0F511D481B40310CF034 +:102CC0004FE0042E000C550B60EE7FE70E945E2A59 +:102CD000CF911F910F910895B0E0A0E0E2E7F6E1F7 +:102CE0000C94F12A8C01EB017B01E40EF51ED990C6 +:102CF000C8010E946D2AD81621F06D2DC8010E94CE +:102D0000752A0F5F1F4FEC16FD0689F7CDB7DEB7AA +:102D1000E7E00C940D2BA6E0B0E0E1E9F6E10C94BD +:102D2000F62A46E050E065E973E0CE0101960E9484 +:102D30005E2A46E050E0BE016F5F7F4F80E893E07F +:102D4000CBDF47E150E066E371E086E893E0C4DF63 +:102D50002696E2E00C94122B1F93CF93DF93EC01A5 +:102D6000162F66FF12C0ED81FE81808129852150DA +:102D7000330B821713064CF48F5F8083E881F9814F +:102D80000280F381E02DCE01099517FF0EC0ED8181 +:102D9000FE818081882349F081508083E881F98118 +:102DA0000280F381E02DCE01099590E080E014FFD0 +:102DB00002C0B1DFCE01DF91CF911F910895CF9373 +:102DC000DF93EC01E985FA8581E09081911180E043 +:102DD0008083A1DFCE01DF91CF910895B0E0A0E024 +:102DE000E4EFF6E10C94E72AEC0110E031EBC32E9E +:102DF00033E0D32E4CE8342E54E4852E69ECA62E15 +:102E000064E0B62E0CE374E1972E8D85181708F058 +:102E10006CC0812F90E0880F991FEB85FC85E80F2F +:102E2000F91FA591B491E985FA8580811796ED90F7 +:102E3000FC90189781112EC01696BC92AE921597F1 +:102E400019960C9319971A969C92F701608170E07D +:102E500090E080E00E941F2C20E030E040E052E44F +:102E60000E941D2B26E636E646EE5FE30E94862B87 +:102E70002B013C0120E030E0A9010E94D12C87FF0A +:102E800026C020E030E040E05FE3C301B2010E94D1 +:102E90001D2B25C01696DC92CE92159719963C9262 +:102EA00019971A968C92F701608170E090E080E0AB +:102EB0000E941F2C26E636E646EE5FE30E94D52CE4 +:102EC00020E030E040E052E40E941E2BD1CF20E011 +:102ED00030E040E05FE3C301B2010E941E2B0E947C +:102EE000EE2BF70160831F5F90CFCE0168DFCE012C +:102EF000CDB7DEB7E1E10C94032B1F93CF93DF93A3 +:102F0000EC01162F66FF06C0E881F9810684F7857B +:102F1000E02D099517FF07C0E881F9810088F18944 +:102F2000E02DCE01099590E080E014FF02C0F3DEB1 +:102F3000CE01DF91CF911F910895EF92FF920F93F1 +:102F40001F93CF93DF938B01040F151FEB017C01BF +:102F5000E61AF70AC7018C0F9D1F0E946D2A8993FC +:102F6000C017D107B9F7CDB7DEB7E6E00C940E2B4A +:102F7000B0E0A0E0EEEBF7E10C94E92A04E812E0FF +:102F8000109325050093240510922705109226051D +:102F9000109229051092280510922B0510922A05EF +:102FA00024E4E22E21E0F22EF0922D05E0922C0591 +:102FB00010922E0510922F051092300510923105B7 +:102FC000109232058DEB94E0909334058093330595 +:102FD000109236051092350510923805109237057B +:102FE0001092390560E08CE095E00E94450661E0B2 +:102FF00084EF94E00E9445061093DF040093DE0402 +:103000008CE095E09093E1048093E0041092E30457 +:103010001092E2041092E5041092E40426E431E0F8 +:103020003093E7042093E6041092E8041092E90438 +:103030001092EA041092EB041092EC0425EB34E0B9 +:103040003093EE042093ED0428E331E03093F00454 +:103050002093EF0436E3A32E31E0B32EB092F204B6 +:10306000A092F10428E12093F3041093C904009383 +:10307000C8049093CB048093CA041092CD0410929C +:10308000CC041092CF041092CE0428E431E03093A7 +:10309000D1042093D0041092D2041092D304109241 +:1030A000D4041092D5041092D6044EEA54E0509302 +:1030B000D8044093D7044BE351E05093DA04409393 +:1030C000D904C7E3D1E0D093DC04C093DB046CE403 +:1030D0006093DD041093B3040093B2049093B5049D +:1030E0008093B4041092B7041092B6041092B904FD +:1030F0001092B8044AE451E05093BB044093BA04E0 +:103100001092BC041092BD041092BE041092BF0431 +:103110001092C004E7EAF4E0F093C204E093C10423 +:10312000E9E3F1E0F093C404E093C304D093C60450 +:10313000C093C5047AE47093C70410939D04009370 +:103140009C0490939F0480939E041092A10410927B +:10315000A00470E4C72E71E0D72ED092A304C092D1 +:10316000A2043093A5042093A4041092A604109204 +:10317000A7041092A8041092A9041092AA04EFE9DF +:10318000F4E0F093AC04E093AB04E2E4F1E0F093FC +:10319000AE04E093AD04D093B004C093AF04609349 +:1031A000B104109289041092880410928B0410923A +:1031B0008A04EFE38E2EE1E09E2E90928D048092A1 +:1031C0008C0430938F0420938E04109290041092FC +:1031D0009104109292041092930410929404A7E91F +:1031E000B4E0B0939604A0939504E7E2F1E0F09385 +:1031F0009804E0939704D0939A04C093990465E4EB +:10320000562E50929B0468E772E070938704609397 +:1032100086040F2EFCE96F2EF4E07F2EF02D7092C5 +:10322000FE056092FD05109200061092FF05D092F7 +:103230000206C09201063093040620930306109202 +:1032400005061092060610920706109208061092C4 +:103250000906B0930B06A0930A06F0930D06E093BF +:103260000C06D0930F06C0930E0650921006709372 +:10327000FC056093FB0510937E0500937D059093FC +:10328000800580937F05109282051092810510922F +:1032900084051092830565E271E070938605609362 +:1032A0008505109287051092880510928905109265 +:1032B0008A0510928B056EE874E070938D0560931B +:1032C0008C0564E271E070938F0560938E05109217 +:1032D00091051092900568E06093920590936604C2 +:1032E00080936504109268041092670410926A0437 +:1032F0001092690430936C0420936B0410926D0457 +:1033000010926E0410926F04109270041092710467 +:1033100082E894E090937304809372048EE794E0C3 +:10332000909375048093740410927704109276043D +:1033300084E48093780410927C0410927B041092B1 +:103340007D0486E692E0909364048093630482E7B0 +:1033500092E090937A04809379040AE000937E04CB +:1033600010927F04109280041092810410928204C3 +:1033700010928404109283041092850483E694E0F2 +:1033800090934B0480934A0410924D0410924C0485 +:1033900010924F0410924E045093510440935004E5 +:1033A0001092520410925304109254041092550437 +:1033B0001092560487E794E0909358048093570442 +:1033C0008EE594E090935A048093590410925C0423 +:1033D00010925B0482E880935D048AE592E090930A +:1033E00049048093480400935E0410925F04109295 +:1033F0006004109261041092620488E494E0909357 +:10340000250480932404109227041092260410921D +:103410002904109228048EE394E090932B04809367 +:103420002A0410922C0410922D0410922E04109253 +:103430002F04109230048DE694E090933204809330 +:1034400031048DE394E0909334048093330410921C +:103450003604109235041092370410923B041092F7 +:103460003A0410923C0488E492E090932304809301 +:10347000220484E592E0909339048093380412E0AA +:1034800010933D0410923E0410923F0410924104A8 +:10349000109240041092430410924204109245048A +:1034A00010924404109246041092470482E294E081 +:1034B0009093040480930304109206041092050470 +:1034C0001092080410920704F0920A04E092090492 +:1034D00010920B0410920C0410920D0410920E0422 +:1034E00010920F048FE594E09093110480931004E0 +:1034F0008CE194E090931304809312048DE194E0A6 +:1035000090931504809314041092160410921A04D8 +:103510001092190410921B0486E392E09093020427 +:103520008093010482E492E090931804809317043E +:1035300083E0782E70921C0410921D0410921F04D8 +:1035400010921E04109220041092210481E094E055 +:103550009093E6038093E5031092E8031092E7034B +:103560001092EA031092E903F092EC03E092EB036D +:103570001092ED031092EE031092EF031092F003FD +:103580001092F10381E594E09093F3038093F203AA +:103590001092F5031092F4031092F7031092F603C1 +:1035A0001092F8038AE292E09093E4038093E3039D +:1035B00021E434E03093FA032093F90321E334E06B +:1035C0003093FC032093FB0323E738E03093FE03A2 +:1035D0002093FD031092FF031092000423EE33E0CA +:1035E00030934A052093490510924C0510924B05E3 +:1035F00010924E0510924D05F0925005E0924F0545 +:1036000010925105109252051092530510925405D4 +:103610001092550526E234E0309357052093560565 +:10362000109259051092580510925B0510925A0598 +:1036300010925C05909348058093470587E194E0DC +:1036400090935E0580935D0587E094E0909360051C +:1036500080935F058AE798E0909362058093610507 +:1036600010926305109264058CE793E09093EE0747 +:103670008093ED0728EB37E03093F0072093EF07B6 +:10368000FF24F394F092F1079093E9078093E80701 +:1036900083EB97E09093EB078093EA0784E08093B5 +:1036A000EC072CE349E351E063EA77E08DED97E026 +:1036B0000E9452052CE34BE351E063E977E082ED91 +:1036C00097E00E9452052AE048E351E062E877E083 +:1036D00087EC97E00E9452052EE142E451E06FE64C +:1036E00077E08CEB97E00E94520525E04CE557E02F +:1036F00066E677E08FEA97E00E941F068FE497E086 +:103700009093A7078093A6071093A8072DEC34E0A9 +:103710003093AA072093A907D093AC07C093AB07B7 +:103720000093AD07F092AE0786E693E09093A5076D +:103730008093A40741E457E050939C0740939B0774 +:1037400010939D0730939F0720939E07B092A10787 +:10375000A092A0070093A207F092A30790939A0764 +:103760008093990723E04CE257E062E377E08CE82E +:1037700097E00E941F0684E297E09093840780936D +:1037800083071092850794E5A92E93E0B92EB09295 +:103790008207A09281072FE1E22E27E0F22EF0921D +:1037A0008707E0928607C9E1D7E0D0938907C093E5 +:1037B00088078EE391E090938B0780938A0787E0D8 +:1037C00097E0909379078093780710937A0749ECF4 +:1037D00054E050937C0740937B0790927E07809241 +:1037E0007D073CE330937F0724E12093800786E642 +:1037F00093E0909377078093760766EF76E0709377 +:103800006E0760936D0710936F0750937107409395 +:103810007007D0927307C092720730937407209399 +:10382000750790936C0780936B078AEE96E09093F0 +:10383000600780935F071092610784EC94E0909397 +:103840006307809362078FEB94E090936507809302 +:10385000640781E491E0909367078093660782E4B0 +:1038600093E090935E0780935D0786EE96E09093D9 +:1038700069078093680710936A0725E04FEC56E0CC +:1038800069ED76E080E597E00E941F0682EC96E005 +:10389000909348078093470710924907B0924607D4 +:1038A000A0924507F0924B07E0924A07D0934D074C +:1038B000C0934C078CE391E090934F0780934E07A1 +:1038C00086EB96E090933E0780933D0710933F0769 +:1038D00080E393E090933C0780933B078AE391E079 +:1038E000909341078093400780EB96E090934307C5 +:1038F000809342077092440780913A01843010F01F +:1039000010923A0123E044EA56E06AEA76E08EE259 +:1039100097E00E941F062EE14AE451E062E976E05A +:1039200083E297E00E943F052EE14BE451E060E81E +:1039300076E088E197E00E943F0523E048E656E004 +:103940006EE676E08BE097E00E941F062EE149E4E8 +:1039500051E066E576E080E097E00E943F0522E0D6 +:1039600040E456E064E476E083EF96E00E941F06B0 +:103970002EE147E451E06DE276E088EE96E00E94A9 +:103980003F0522E046E156E06AE176E08BED96E005 +:103990000E941F062EE145E451E066E076E08EECE1 +:1039A00096E00E943F058AE193E09093CF068093D2 +:1039B000CE068CE09CE09093DA068093D90622E054 +:1039C00042EF55E066EF75E081EC96E00E941F063D +:1039D00025E043EE55E06DEE75E084EB96E00E9445 +:1039E0001F066EED75E08FEA96E00E94350688E0CE +:1039F00093E09093B0068093AF0663ED75E08AEA9A +:103A000096E00E94350668EC75E085EA96E00E9433 +:103A1000350665EB75E080EA96E00E94350625E004 +:103A20004FE955E069EA75E083E996E00E941F06D8 +:103A300086E995E090938C0680938B0682E08093D4 +:103A40008D0680E393E090938A06809389068DE348 +:103A500091E090938F0680938E0680E995E0909395 +:103A600091068093900683E08093920680913D01B9 +:103A7000843010F010923D0121E043E451E060E811 +:103A800075E08EE796E00E943F0525E04CE451E0AA +:103A900061E775E081E796E00E943F058AE193E0E7 +:103AA00090937206809371068CEC9BE090937D0658 +:103AB00080937C0627E04AE555E068E675E084E6F9 +:103AC00096E00E941F068EEB94E090936006809330 +:103AD0005F0612E01093610686EF92E090935E0617 +:103AE00080935D068DEE97E0909363068093620667 +:103AF00023E043E555E069E575E080E596E00E9446 +:103B00001F0621E04FE355E061E475E083E496E0B1 +:103B10000E941F0684EE92E0909344068093430631 +:103B200020E536E050E040E070E060E089E296E0B9 +:103B30000E94200582ED92E090932A068093290648 +:103B40008DE391E0909342068093410620E536E0B4 +:103B50004BEF55E061E375E081E196E00E942005BE +:103B600025E047E255E069E575E08EEE95E00E94BC +:103B70001F066CE175E082EE95E00E94350610921A +:103B8000EA051092E9051092EB058AEBE82E82E037 +:103B9000F82EF092E305E092E205CCECD2E0D0936F +:103BA000E805C093E70580E391E09093ED058093ED +:103BB000EC0561E175E086ED95E00E943506109216 +:103BC000DE051092DD051092DF05F092D705E09238 +:103BD000D605D093DC05C093DB0582E391E090939A +:103BE000E1058093E00564E075E08AEC95E00E94D1 +:103BF00035061092D2051092D1051092D30592EAA3 +:103C0000E92E92E0F92EF092CB05E092CA05C4EBC2 +:103C1000D2E0D093D005C093CF058CE291E0909391 +:103C2000D5058093D40567EF74E08EEB95E00E9494 +:103C300035061092C6051092C5051092C705F09280 +:103C4000BF05E092BE05D093C405C093C30588E2CA +:103C500091E09093C9058093C80525E04DEE54E0AE +:103C600069E575E08BEA95E00E941F0680E992E025 +:103C70009093AC058093AB0588EE93E09093B905E3 +:103C80008093B8051092BA051092BB051092BC053E +:103C90001092BD052BEA35E04DE755E064EE74E087 +:103CA00083E995E00E94200530E020E047E455E0FC +:103CB0006BED74E085E695E00E94200525E041ED7E +:103CC00054E069E575E08AE395E00E941F061092D2 +:103CD000F5071092F4071092F6078EE893E09093A0 +:103CE000F3078093F20780914D0190914E01A091CE +:103CF0004F01B09150018093F9079093FA07A09378 +:103D0000FB07B093FC078091510190915201A09163 +:103D10005301B09154018093FD079093FE07A09347 +:103D2000FF07B093000861E08CE00E942C0961E07D +:103D300086E00E942C0961E086E00E94A70761E00E +:103D400084E00E942C098BE39DE00197F1F760E08D +:103D50008CE00E94A70760E084E00E94A70763E070 +:103D600082EF97E00E946809CBE4D6E4CE01019788 +:103D7000F1F763E082EF97E00E9468092197F1F77D +:103D800063E082EF97E00E94680983E592E0019783 +:103D9000F1F762E082EF97E00E94680940E068E294 +:103DA00082EF97E00E949C09CBEED0E0CE01019714 +:103DB000F1F784E08093F70740E06CE082EF97E052 +:103DC0000E949C09CE010197F1F70E94B4098BED86 +:103DD0009EE20197F1F71093F80740E066E082EF6A +:103DE00097E00E949C092197F1F710920D0888E056 +:103DF00080930E088FEF9FEF9093100880930F0829 +:103E000010921608109215081092120810921108BC +:103E1000109214081092130887E080930B081092F8 +:103E20000C0861E088E00E942C0961E080910E0896 +:103E30000E94A7070E946F0A60E080910E080E940E +:103E4000A70780910D08880F80640E942E078AE0E2 +:103E50000E942E0788E00E942E0761E080910E08E4 +:103E60000E94A70767E970E080E00E94D40787E915 +:103E700090E09093100880930F0863E870E08CE066 +:103E80000E94D40783E890E0909312088093110871 +:103E900060E08AE00E94F20760E089E00E94F20799 +:103EA00062E084E10E942C0962E085E10E942C0915 +:103EB00061E089E00E942C0961E085E00E942C0904 +:103EC00061E083E00E942C0961E08DE00E942C09F2 +:103ED00061E08BE00E942C0960E086E10E942C09E1 +:103EE0000E94C108109271000E943E080E9426089C +:103EF00061E080910B080E942C0961E080910B0821 +:103F00000E94A7070E94A10A0E94A10A60E0809176 +:103F10000B080E94A70780E00E942E0780930C08E0 +:103F200080E00E942E0780E00E942E0780E00E9421 +:103F30002E0780E00E942E0761E080910B080E940E +:103F4000A70764E088E10E94070B4AE05AE060E0BE +:103F500070E080E10E949A0801E010E020E030E08B +:103F600040E050E0BA0180E00E94B00A61E08FE0DA +:103F70000E94070B68E080E00E94070B04E010E05D +:103F800020E030E044E050E060E070E080E00E943B +:103F9000B00A0E947A08809302080E9473088093F6 +:103FA000010881E090E0A0E0B0E0809317089093D2 +:103FB0001808A0931908B0931A0810921B081092C1 +:103FC0001C0810921D0810921E0810921F081092D3 +:103FD00020081092210810922208109223081092B3 +:103FE0002408109225081092260810922708109293 +:103FF00028081092290810922A0880932B08809391 +:104000002C0810922D08CDB7DEB7EFE00C94052BED +:104010001F920F920FB60F9211242F933F934F933D +:104020005F936F937F938F939F93AF93BF93CF9340 +:10403000DF93EF93FF938091210190E0909399009B +:104040008093980061E085E00E94A707C3E0D0E07C +:10405000CE010197F1F760E085E00E94A707219764 +:10406000F1F7FF91EF91DF91CF91BF91AF919F91C8 +:104070008F917F916F915F914F913F912F910F9011 +:104080000FBE0F901F9018951F920F920FB60F92B0 +:1040900011242F933F934F935F936F937F938F934D +:1040A0009F93AF93BF93CF93EF93FF9384E10E94CD +:1040B0008107C1E0019709F0C0E085E10E94810716 +:1040C000019709F4C2608091D7038C17A9F0C13021 +:1040D00009F460C008F443C0C23009F44FC0C330D3 +:1040E00009F452C0C093D7038091D6038D370CF4E6 +:1040F00056C08CE78093D6038091DD038823E9F0D6 +:104100008091DB039091DC030196893E23E09207C6 +:1041100008F04CC09093DC038093DB0381E0409176 +:10412000DB035091DC032091D9033091DA0342176D +:10413000530708F080E08093D803FF91EF91CF916F +:10414000BF91AF919F918F917F916F915F914F91AF +:104150003F912F910F900FBE0F901F9018958130B7 +:1041600031F48091D6038F5F8093D603BBCF82302A +:1041700009F0B8CF8091D6038150F6CF882389F318 +:10418000833009F0AFCFF6CF823059F3813009F098 +:10419000A9CFF0CF833029F38111A4CFEBCF809149 +:1041A000D60384380CF0A8CF84E8A4CF1092DC03A7 +:1041B0001092DB03B3CFA6E0B0E0E1EEF0E20C94A6 +:1041C000E72A789484B5826084BD84B5816084BD1B +:1041D00085B5826085BD85B5816085BD80916E00A5 +:1041E000816080936E0010928100809181008260D6 +:1041F0008093810080918100816080938100809113 +:104200008000816080938000809191008260809323 +:104210009100809191008160809391008091900045 +:104220008160809390008091C10084608093C10080 +:104230008091C10082608093C1008091C100816043 +:104240008093C1008091C30081608093C3008091FE +:10425000C00082608093C0008091C2008160809322 +:10426000C20080917A00846080937A0080917A0005 +:10427000826080937A0080917A00816080937A00D6 +:1042800080917A00806880937A001092E203109205 +:10429000AA031092CB038091D70081608093D7004E +:1042A00080EA8093D80089B5806189BD89B5826034 +:1042B00089BD09B400FEFDCF61E070E080E090E0D0 +:1042C0000E94790C8091D8008F7C80618093D80007 +:1042D0008091E000807F8093E0008091E1008E7EFD +:1042E0008093E1008DE08093E200559A209AEEEFF2 +:1042F000FFE7859194918B3F9C4D19F481E0809369 +:10430000A90346E050E0BE016F5F7F4F80E893E075 +:104310000E949D1746E050E065E973E0CE010196EA +:104320000E94502A892B09F02CC347E150E066E334 +:1043300071E086E893E00E949D17109244018091FD +:104340004C010E94CC0B69ED71E080E00E94E50910 +:1043500061ED71E081E00E94E50969EC71E082E0C5 +:104360000E94E50961EC71E083E00E94E50969EBD8 +:1043700071E084E00E94E50962E080E00E942C097F +:1043800062E082E00E942C098EED94E09093090196 +:104390008093080180916900806380936900EA9AA4 +:1043A00088ED94E090930701809306018091690065 +:1043B0008C6080936900E99AF8948FEA87BD8091B8 +:1043C0006E00826080936E001092900010929100B7 +:1043D000109295001092940088EC90E090939900D0 +:1043E00080939800809191008860809391008091E3 +:1043F0009100836080939100109271007894809175 +:10440000220190912301DC01ED91FC910190F0815A +:10441000E02D09958091410181111AC321EB33E010 +:1044200030937C0720937B079CE890937F0784E47C +:1044300080938007309371072093700790937407DF +:104440008093750789E896E09093F6058093F505CB +:104450008BEA95E090939B0680939A06909358067A +:10446000809357068AE395E090936C0680936B06E1 +:1044700080910E0190910F01DC01ED91FC9106807D +:10448000F781E02D099580910E0190910F01DC01DB +:10449000ED91FC910280F381E02D09951092DA03F1 +:1044A0001092D9031092D80343E050E060EE7FE70A +:1044B0008CE591E0DFD7892B09F0D5C2A8E79A2EC9 +:1044C00088248394B4E63B2E18EEA12E13E0B12E7F +:1044D0008091FE0A9091FF0A8737974709F0A895C7 +:1044E0000E94C70C6B017C018091CD03882389F168 +:1044F0008091CE039091CF03A091D003B091D103CE +:10450000A7019601281B390B4A0B5B0BDA01C90185 +:10451000C297A105B105E8F0C092CE03D092CF03B7 +:10452000E092D003F092D10390912101809120017B +:10453000891708F0A1C2809121018C3428F0809164 +:104540002101845080932101809121018150809329 +:1045500021018091BA039091BB03A091BC03B0915B +:10456000BD03A7019601281B390B4A0B5B0BDA012F +:10457000C901843F9140A105B10548F1C092BA0339 +:10458000D092BB03E092BC03F092BD038091DE03A6 +:10459000899DC001112490933101809330011092C4 +:1045A000DE038091DF03899DC001112490933301C4 +:1045B000809332011092DF038091E003899DC00156 +:1045C000112490933501809334011092E00380917F +:1045D000B6039091B703A091B803B091B903A701B6 +:1045E0009601281B390B4A0B5B0BDA01C901843F8A +:1045F0009140A105B10508F4DCC0C092B603D09289 +:10460000B703E092B803F092B9038091AB0388231B +:1046100009F43CC20E94AF0465E272E0959587956B +:10462000959587950E941104BC01990F880B990BF1 +:104630000E94212C20E030E040E251E40E94862BD1 +:10464000609318017093190180931A0190931B01D4 +:104650002091410121110BC026E636E646EE5FE3CC +:104660000E94D52C20E030E040E052E4E7D7609390 +:1046700028017093290180932A0190932B01609166 +:10468000AB0368256093AB038AE00E94F207609158 +:10469000CC03662309F48DC070E090E080E00E94B6 +:1046A000212C9B01AC0160912C0170912D01809116 +:1046B0002E0190912F01C1D76B017C012091AC0399 +:1046C0003091AD034091AE035091AF03B7D72B01AA +:1046D0003C0120E030E44CE156E40E94D12C181655 +:1046E0000CF482C220E030E44CE156ECC301B2018C +:1046F0000E94822B87FD78C24092AC035092AD039A +:104700006092AE037092AF032FE632E143E85AE3C2 +:104710006091AC037091AD038091AE039091AF03B3 +:104720000E94D52C2B013C0120E030E040E251E416 +:10473000C701B6010E94D52C9B01AC01C301B20197 +:104740007DD72B013C0120E030E048EC52E40E9490 +:10475000D12C18160CF455C220E030E040EF51E4A3 +:10476000C301B201CFD787FD53C26091D40370E07B +:1047700090E080E00E94212CA3019201C3D7811117 +:104780000EC06091D50370E090E080E00E94212C83 +:104790009B01AC01C301B201B5D7882351F0C3011D +:1047A000B2010E94F32B6093D4036093D5030E945F +:1047B000100C8091D8039091D30389130E9419089B +:1047C0000E947A089091020810E0891731F012E0F7 +:1047D000811101C011E0809302080E94730890913A +:1047E0000108891731F0882309F419C214608093F5 +:1047F000010881E00E9444089091B50381112DC207 +:1048000091110FC28092B5030E94C70C6093B1034F +:104810007093B2038093B3039093B4038091D60353 +:1048200084300CF428C28091D60384508093D60340 +:10483000106480913C018823B1F0812F807F99F032 +:104840000AE061E089E00E94A7078BE891E0019708 +:10485000F1F760E089E00E94A7078BE891E00197FB +:10486000F1F7015071F7E0902201F0902301D70198 +:1048700055968C9184FF02C013FD04C0867029F008 +:1048800010FF03C0C7010E94C808F7018589867020 +:1048900049F011FF07C00E947308811103C0C701CE +:1048A0000E94D30ED701ED91FC910280F381E02D9F +:1048B000C7010995009711F00E94E20880910E014E +:1048C00090910F01DC01ED91FC910480F581E02DC8 +:1048D000099580910E0190910F01DC01ED91FC9101 +:1048E0000284F385E02D612F09958C01B7E0883EA5 +:1048F0009B07A9F08D5E974091F080910E019091F9 +:104900000F010817190759F0E0912201F0912301D6 +:10491000258925FFBCC12685222309F4B8C18091D1 +:10492000C803882309F4D4CD80910E0190910F0122 +:10493000DC01ED91FC910084F185E02D09958091D9 +:10494000C80381508093C803E82FF0E0EE0FFF1FEB +:10495000E254FC4FE080F180F0920F01E0920E01F2 +:10496000B7E0083E1B0711F48111DECF0E94B409A5 +:10497000D701ED91FC910280F381E02DC7010995EB +:10498000A7CD46E050E06FE971E0CE01019688D5F1 +:10499000892B09F0D2CC109140014CE050E066E345 +:1049A00071E086E893E00E949D1780914101882381 +:1049B00019F010934001C1CC60913F0170E090E08C +:1049C00080E03DD726E636E646EE5FE3EED720E010 +:1049D00030E040E052E432D66B017C0120E030E070 +:1049E000A901DFD720E030E040E05FE387FD28C089 +:1049F000C701B60123D6F2D660933F01612F70E064 +:104A000090E080E01CD726E636E646EE5FE3CDD7A1 +:104A100020E030E040E052E411D66B017C0120E060 +:104A200030E0A901BED720E030E040E05FE387FD41 +:104A30000BC0C701B60102D6D1D6609340017DCC30 +:104A4000C701B601FAD5D7CFC701B601F6D5F4CF65 +:104A500029EC34E030937C0720937B079CE3909310 +:104A60007F0784E1E5CC0E94B40941E060E085EA7B +:104A700091E00E94CA09FFCF1092CD034AE05AE0AC +:104A800065E070E080E10E949A0863CD0E94AF0467 +:104A900061EE71E095958795959587950E94110433 +:104AA000BC01990F880B990BCCD620E030E040E296 +:104AB00051E42CD66B017C01C0921C01D0921D01E7 +:104AC000E0921E01F0921F0180914101811133C0DB +:104AD00026E636E646EE5FE3C701B60166D720E07C +:104AE00030E040E052E4AAD560932C0170932D0190 +:104AF00080932E0190932F011091D4038091D203C3 +:104B0000882309F45DC060913F0170E090E080E08F +:104B100098D6A701960191D56B017C0120E030E089 +:104B2000A9013FD7181654F01092DA031092D90356 +:104B30001092D80327C0C701B601D6CF20E030E0DD +:104B400040E050E4C701B601DDD587FF17C020E083 +:104B500030E045E754E4C701B60127D76B017C017B +:104B600020E030E0A9011DD787FF16C020E030E02B +:104B700040E05FE3C701B60160D515C0B092DA032B +:104B8000A092D903143609F47ACD3092D40364E6A6 +:104B900080E00E94DC0B73CD20E030E040E05FE37A +:104BA000C701B6014BD51AD67093DA036093D903C7 +:104BB000693E43E0740710F7672B09F4B9CFE2CFE1 +:104BC00020E030E04CE052E4C701B601EAD6181606 +:104BD0000CF055CD612F183208F468E2183208F055 +:104BE0004ECD6093D403D4CF80E090E4ACE1B6E442 +:104BF0008093AC039093AD03A093AE03B093AF0347 +:104C000083CD412C512C58EC652E52E4752EADCD40 +:104C1000412C512C40EF642E41E4742EA6CD186037 +:104C2000E6CD8091B0038111F9CD0E94C70C20918F +:104C3000B1033091B2034091B3035091B403621BAE +:104C4000730B840B950B693E73408105910508F445 +:104C5000E5CD8092B0031062E1CD992309F4DECD59 +:104C60008091B003882329F01092B0031092B5030D +:104C7000D5CD1061FBCF8091D6038D3F0CF0D9CDFF +:104C80008091D6038C5F8093D6031068D2CD011536 +:104C9000110509F41DCCE091C803E53008F018CCEB +:104CA00021E02E0F2093C803F0E0EE0FFF1FE25427 +:104CB000FC4F9183808310930F0100930E010E949B +:104CC000B409D801ED91FC910680F781E02DC8016F +:104CD000099580910E0190910F01DC01ED91FC91FD +:104CE0000280F381E02D4BCE1F920F920FB60F92F0 +:104CF00011248F939F938091E1009091E100937F25 +:104D00009093E10083FF0FC01092E90091E090932F +:104D1000EB001092EC0092E39093ED001092E2030E +:104D200098E09093F00082FF22C093E09093E90016 +:104D30009091F200992319F09AE39093E8009091F2 +:104D4000CA03992341F09091CA0391509093CA03EA +:104D5000911101C05D9A9091E103992341F09091E6 +:104D6000E10391509093E103911101C0289A84FFCF +:104D700018C08091E2008E7E81608093E200809175 +:104D8000E1008F7E8093E1008091CB038E7E806175 +:104D90008093CB039F918F910F900FBE0F901F9028 +:104DA000189580FFF7CF8091E2008E7E806180931E +:104DB000E2008091E1008E7E8093E1008091CB0340 +:104DC0008E7E8160E5CF1F920F920FB60F92112455 +:104DD000CF92DF92EF92FF920F931F932F933F9307 +:104DE0004F935F936F937F938F939F93AF93BF93F3 +:104DF000EF93FF93CF93DF93CDB7DEB76C97DEBF12 +:104E0000CDBF1092E9008091E80083FF25C068E0E3 +:104E1000CE0145960E94210782EF8093E8008D899C +:104E200087FF39C09091E80090FFFCCF982F9076D3 +:104E300009F034C19E894F89588D2F89F88C9111C2 +:104E400031C0803861F58091AA038093F1001092FF +:104E5000F1008EEF8093E8006C960FB6F894DEBFF9 +:104E60000FBECDBFDF91CF91FF91EF91BF91AF9179 +:104E70009F918F917F916F915F914F913F912F9172 +:104E80001F910F91FF90EF90DF90CF900F900FBE8A +:104E90000F901F9018959EEF9093E800C7CF109247 +:104EA000F100D5CF913059F48111D3CF4130510564 +:104EB00081F68091AA038D7F8093AA03CACF933095 +:104EC00049F48111C6CF4130510519F68091AA03EA +:104ED0008260F2CF953041F48091E80080FFFCCFF2 +:104EE00020682093E300B5CF963009F0A9C00B8D60 +:104EF0001C8D22E01092E90010929C0310929B03FB +:104F0000F2122EC010929A03109299030E94F50695 +:104F10001F8299E09983FA8291E09E8390EA9887B4 +:104F20009AEF998720919B0330919C03275F3F4F15 +:104F30003C832B838D831092E90010929C03109286 +:104F40009B0310939A030093990349E050E0BE013C +:104F50006F5F7F4F80E00E94D4060E94F50679CFF4 +:104F600010939A03009399030E946806DC0112963D +:104F70000D911C910115110509F43BC1D801ED916A +:104F8000FC910480F581E02DBE016B5E7F4FC8016E +:104F90000995009709F028C1F80100851185EACF2D +:104FA000F3E0FF120EC08F89882309F440C08230DD +:104FB00061F440E863E18BE891E00E94AA06811168 +:104FC00048CF81E28093EB0047CF813029F440E85D +:104FD0006AE180E791E0F1CF833099F70E9468069B +:104FE000DC011296ED90FC908E010F5F1F4F68015F +:104FF000E114F10479F0D701ED91FC910680F7817D +:10500000E02DB801C7010995080F111DF701E084D3 +:10501000F184EECFD8011C92F60101900020E9F74F +:105020003197BF016C197D0940E0C601C6CF6AE522 +:1050300071E0FB01449150E080E80E94D40609CF62 +:10504000973009F4BECF983021F481E08093F100CD +:1050500000CF993009F0FDCE837009F0B2CFE6E5BC +:10506000F1E081E031E096E32191222371F0809319 +:10507000E9003093EB00DF0111972C912093EC00B5 +:105080009093ED008F5F873079F78EE78093EA0089 +:105090001092EA008F898093E203DBCE8B8D9C8D8A +:1050A0001092E90010929C0310929B0390939A0334 +:1050B00080939903898D81117DC08E899D89913A54 +:1050C00049F4813209F07DCF47E050E060E171E0C2 +:1050D00080E0B3CF913209F074CF833269F48F89C5 +:1050E000988DB0E0A0E08093000190930101A0931F +:1050F0000201B0930301ADCE803209F080C08091EF +:10510000E80082FFFCCF67E080E191E00E94210788 +:105110008BEF8093E8008091A903E0E0F8E088231A +:1051200011F0EEEFFAE08091100190911101A09141 +:105130001201B0911301803B9440A105B105B9F46F +:105140008091170180FD13C0EE3F8AE0F80721F53A +:1051500087E797E79183808388E19BE00FB6F89417 +:10516000A895809360000FBE9093600072CE0FB63A +:10517000F894A895809160008861809360001092F7 +:1051800060000FBEA895EE3FAAE0FA0761F4109206 +:10519000FF0A1092FE0A5DCE808191819093FF0AF2 +:1051A0008093FE0AD5CF8091FE0A9091FF0A9183E9 +:1051B00080834FCE0E946806FC0102811381011595 +:1051C000110509F4FECED801ED91FC910190F0811A +:1051D000E02DBE016B5E7F4FC8010995811139CE6C +:1051E000F80100851185EBCF181619060CF431CEA5 +:1051F000E8CEF1E0FF12D4CE6EE571E01ACF823234 +:1052000009F027CE8F898093170185CF1F920F92C7 +:105210000FB60F9211242F933F934F935F936F9389 +:105220007F938F939F93AF93BF93EF93FF93E091FF +:105230000C01F0910D010995FF91EF91BF91AF9194 +:105240009F918F917F916F915F914F913F912F919E +:105250000F900FBE0F901F9018951F920F920FB6D0 +:105260000F9211242F933F934F935F936F937F93EC +:105270008F939F93AF93BF93EF93FF93E0910A01B6 +:10528000F0910B010995FF91EF91BF91AF919F9123 +:105290008F917F916F915F914F913F912F910F90DF +:1052A0000FBE0F901F9018951F920F920FB60F927E +:1052B00011242F933F934F935F936F937F938F931B +:1052C0009F93AF93BF93EF93FF93E0910801F09109 +:1052D00009010995FF91EF91BF91AF919F918F9136 +:1052E0007F916F915F914F913F912F910F900FBEE2 +:1052F0000F901F9018951F920F920FB60F921124C6 +:105300002F933F934F935F936F937F938F939F93CD +:10531000AF93BF93EF93FF93E0910601F0910701E4 +:105320000995FF91EF91BF91AF919F918F917F91DF +:105330006F915F914F913F912F910F900FBE0F9002 +:105340001F9018951F920F920FB60F9211242F9352 +:105350003F934F935F936F937F938F939F93AF93FD +:10536000BF93EF93FF93E0910401F091050109953C +:10537000FF91EF91BF91AF919F918F917F916F912D +:105380005F914F913F912F910F900FBE0F901F9003 +:1053900018951F920F920FB60F9211242F933F93DF +:1053A0008F939F93AF93BF938091910390919203BA +:1053B000A0919303B09194033091900323E0230FC5 +:1053C0002D3758F50196A11DB11D209390038093B0 +:1053D000910390939203A0939303B09394038091CD +:1053E000950390919603A0919703B091980301962D +:1053F000A11DB11D8093950390939603A0939703ED +:10540000B0939803BF91AF919F918F913F912F914E +:105410000F900FBE0F901F90189526E8230F02964D +:10542000A11DB11DD2CF97FB072E16F4009406D014 +:1054300077FD08D00BD007FC05D03EF49095819500 +:105440009F4F0895709561957F4F0895AA1BBB1BD0 +:1054500051E107C0AA1FBB1FA617B70710F0A61B74 +:10546000B70B881F991F5A95A9F780959095BC0195 +:10547000CD010895FB01DC0104C08D9105908019D8 +:1054800021F441505040C8F7881B990B0895FC0146 +:1054900005900020E9F7809590958E0F9F1F089545 +:1054A000FB01DC014150504030F08D910590801996 +:1054B00019F40020B9F7881B990B0895FB01DC0152 +:1054C0004150504048F005900D920020C9F701C0AE +:1054D0001D9241505040E0F70895F999FECF92BDDA +:1054E00081BDF89A992780B50895262FF999FECFA6 +:1054F0001FBA92BD81BD20BD0FB6F894FA9AF99AF1 +:105500000FBE01960895052E97FB16F400940FD058 +:1055100057FD05D024D007FC02D046F408C05095B2 +:105520004095309521953F4F4F4F5F4F089590958F +:105530008095709561957F4F8F4F9F4F089531D023 +:10554000A59F900DB49F900DA49F800D911D1124D7 +:105550000895B7FFF4CFF3DF821B930B0895A1E208 +:105560001A2EAA1BBB1BFD010DC0AA1FBB1FEE1FDD +:10557000FF1FA217B307E407F50720F0A21BB30B28 +:10558000E40BF50B661F771F881F991F1A9469F7A4 +:1055900060957095809590959B01AC01BD01CF0100 +:1055A0000895A29FB001B39FC001A39F700D811DFC +:1055B0001124911DB29F700D811D1124911D08951C +:1055C000EE0FFF1F0590F491E02D09942F923F926A +:1055D0004F925F926F927F928F929F92AF92BF9203 +:1055E000CF92DF92EF92FF920F931F93CF93DF93AF +:1055F000CDB7DEB7CA1BDB0B0FB6F894DEBF0FBE0C +:10560000CDBF09942A88398848885F846E847D8458 +:105610008C849B84AA84B984C884DF80EE80FD805A +:105620000C811B81AA81B981CE0FD11D0FB6F894D0 +:10563000DEBF0FBECDBFED0108955058BB27AA278E +:105640000ED075C166D130F06BD120F031F49F3FA0 +:1056500011F41EF45BC10EF4E095E7FB51C1E92F94 +:1056600077D180F3BA17620773078407950718F09C +:1056700071F49EF58FC10EF4E0950B2EBA2FA02D7C +:105680000B01B90190010C01CA01A0011124FF27EF +:10569000591B99F0593F50F4503E68F11A16F040EA +:1056A000A22F232F342F4427585FF3CF46953795E9 +:1056B0002795A795F0405395C9F77EF41F16BA0BAE +:1056C000620B730B840BBAF09150A1F0FF0FBB1F5C +:1056D000661F771F881FC2F70EC0BA0F621F731FA5 +:1056E000841F48F4879577956795B795F7959E3F02 +:1056F00008F0B3CF9395880F08F09927EE0F979590 +:1057000087950895D9D008F481E008950CD00FC191 +:1057100007D140F0FED030F021F45F3F19F0F0C027 +:10572000511139C1F3C014D198F39923C9F355230A +:10573000B1F3951B550BBB27AA2762177307840784 +:1057400038F09F5F5F4F220F331F441FAA1FA9F33A +:1057500033D00E2E3AF0E0E830D091505040E6952C +:10576000001CCAF729D0FE2F27D0660F771F881F8D +:10577000BB1F261737074807AB07B0E809F0BB0B7C +:10578000802DBF01FF2793585F4F2AF09E3F5105A0 +:1057900068F0B6C000C15F3FECF3983EDCF386953D +:1057A00077956795B795F7959F5FC9F7880F911D16 +:1057B0009695879597F90895E1E0660F771F881F02 +:1057C000BB1F621773078407BA0720F0621B730BB5 +:1057D000840BBA0BEE1F88F7E095089504D0689407 +:1057E000B111D9C00895BCD088F09F5790F0B92F5F +:1057F0009927B751A0F0D1F0660F771F881F991F26 +:105800001AF0BA95C9F712C0B13081F0C3D0B1E037 +:105810000895C0C0672F782F8827B85F39F0B93F47 +:10582000CCF3869577956795B395D9F73EF4909527 +:105830008095709561957F4F8F4F9F4F0895E894A5 +:1058400009C097FB3EF490958095709561957F4FC8 +:105850008F4F9F4F9923A9F0F92F96E9BB27939576 +:10586000F695879577956795B795F111F8CFFAF486 +:10587000BB0F11F460FF1BC06F5F7F4F8F4F9F4FB7 +:1058800016C0882311F096E911C0772321F09EE815 +:10589000872F762F05C0662371F096E8862F70E07B +:1058A00060E02AF09A95660F771F881FDAF7880F55 +:1058B0009695879597F90895990F0008550FAA0BAB +:1058C000E0E8FEEF16161706E807F907C0F0121613 +:1058D0001306E407F50798F0621B730B840B950B16 +:1058E00039F40A2661F0232B242B252B21F408956B +:1058F0000A2609F4A140A6958FEF811D811D089508 +:1059000097F99F6780E870E060E008959FEF80EC72 +:10591000089500240A941616170618060906089515 +:1059200000240A9412161306140605060895092E7B +:105930000394000C11F4882352F0BB0F40F4BF2BEA +:1059400011F460FF04C06F5F7F4F8F4F9F4F08952A +:1059500057FD9058440F551F59F05F3F71F0479520 +:10596000880F97FB991F61F09F3F79F08795089505 +:10597000121613061406551FF2CF4695F1DF08C024 +:10598000161617061806991FF1CF86957105610541 +:1059900008940895E894BB2766277727CB0197F9E9 +:1059A00008958ADF08F48FEF08950BD0C0CFB1DFE0 +:1059B00028F0B6DF18F0952309F0A2CFA7CF112465 +:1059C000EACFC6DFA0F3959FD1F3950F50E0551FA6 +:1059D000629FF001729FBB27F00DB11D639FAA2744 +:1059E000F00DB11DAA1F649F6627B00DA11D661F93 +:1059F000829F2227B00DA11D621F739FB00DA11DB4 +:105A0000621F839FA00D611D221F749F3327A00D6D +:105A1000611D231F849F600D211D822F762F6A2F09 +:105A200011249F5750408AF0E1F088234AF0EE0F8E +:105A3000FF1FBB1F661F771F881F91505040A9F79B +:105A40009E3F510570F05CCFA6CF5F3FECF3983ED0 +:105A5000DCF3869577956795B795F795E7959F5F02 +:105A6000C1F7FE2B880F911D9695879597F908959C +:105A7000DC0101C06D9341505040E0F70895F89467 +:025A8000FFCF56 +:105A8200FFFFFFFF530C530C530C530C530CEE054A +:105A920000E1000000000000000020C2000020C25F +:105AA200C8C824050A64640F000020C2000020C296 +:105AB2000100010001000A010403010301000023A7 +:105AC2001E010A64001E00461E460046640A121F9A +:105AD200130040145400C1808100000030325F0086 +:105AE200000000001D0C9E0E660666060C0D0D0BD6 +:105AF20000000000271544064406440644064106F9 +:105B02003406000000002715110A44061C0644064C +:105B1200A7053E060000000027150D05BA12FC0875 +:105B2200F808D30C3E060F00000007000000030037 +:105B32000000010000000700000003000000010057 +:105B4200000001000000010000000100000001004F +:105B5200000001000000010000000100000001003F +:105B6200000003000000010000000100000001002D +:105B72000000010000000F00000007000000030009 +:105B82000000010000000F000000070000000300F9 +:105B920000000100000001000000010000000100FF +:105BA20000000100000000000000830E410E6606A6 +:105BB200660600000000A30FEA11D5146606EAFF8C +:105BC2000000E404000000008F0F6811A814721492 +:105BD200EAFF0000E40400000000800F2A116606BC +:105BE2006606000000006F0FBB1066064814EAFF4D +:105BF2000000E40400000000300F1E126606660674 +:105C020000000000300FB80F6606660600000000B4 +:105C12002715CC0D9E0D1C064406A7053E06000066 +:105C22000000B21544064406440644064106340602 +:105C3200FBFF0000E40400000000D5154406440602 +:105C42004406440641063406FBFF0000E40400005B +:105C520000005B150D05BA120109F808D30C3E06C7 +:105C62000000000027156A0A44061C064208A70520 +:105C72003E0600000000F9144406440644064406A9 +:105C820041060E0F00000000541644064406440666 +:105C92004406410634060000000027152514440678 +:105CA200440644067D173E069A0579050000000069 +:105CB2002715F915440644064406AC163E060000B4 +:105CC2000000841544064406440644064106EE16C6 +:105CD20000000000841544064406440644064106BA +:105CE200DF1600000000271525144406440644066A +:105CF2007D173E068605650500000000271544064F +:105D020044064406440641063E0600000000E2093D +:00000001FF diff --git a/parts/Board.cpp b/parts/Board.cpp index c4207e7b..b7fd8b8d 100644 --- a/parts/Board.cpp +++ b/parts/Board.cpp @@ -41,11 +41,11 @@ #include #include // for exit, free #include // for memcpy, NULL +#include #include // IWYU pragma: keep #include // for operator<<, setw #include #include // for type_info -#include #include // for usleep namespace Boards { diff --git a/parts/Board.h b/parts/Board.h index 72d10a7c..31150841 100644 --- a/parts/Board.h +++ b/parts/Board.h @@ -112,7 +112,7 @@ namespace Boards virtual void OnAVRCycle(){}; // For boards that can handle extra chunks in the hex (language) - virtual void OnExtraHexChunk(gsl::span /*chunk*/, uint32_t uiBase){}; + virtual void OnExtraHexChunk(gsl::span /*chunk*/, uint32_t /*uiBase*/){}; void OnKeyPress(const Key& key) override; diff --git a/parts/I2CPeripheral.cpp b/parts/I2CPeripheral.cpp index 84ae36e2..1c0dabdf 100644 --- a/parts/I2CPeripheral.cpp +++ b/parts/I2CPeripheral.cpp @@ -26,8 +26,8 @@ #include "I2CPeripheral.h" #include "avr_twi.h" // for avr_twi_irq_msg, ::TWI_COND_ACK, ::TWI_COND_READ #include "sim_avr.h" // for avr_t -#include "sim_irq.h" // for avr_raise_irq, avr_irq_register_notify, avr_irq_t #include "sim_io.h" // for avr_io_getirq +#include "sim_irq.h" // for avr_raise_irq, avr_irq_register_notify, avr_irq_t #include // for uint8_t, uint32_t, int32_t, uint16_t #include // for operator<<, cout, ostream diff --git a/parts/I2CPeripheral.h b/parts/I2CPeripheral.h index 916c0c6a..6707f1ce 100644 --- a/parts/I2CPeripheral.h +++ b/parts/I2CPeripheral.h @@ -26,9 +26,9 @@ #pragma once #include "BasePeripheral.h" +#include // for uint8_t, uint32_t, int32_t, uint16_t #include // for avr_t #include // for avr_irq_t, avr_irq_register_notify -#include // for uint8_t, uint32_t, int32_t, uint16_t class I2CPeripheral: public BasePeripheral { diff --git a/parts/PinNames.h b/parts/PinNames.h index 3e89ef80..4fccdf1f 100644 --- a/parts/PinNames.h +++ b/parts/PinNames.h @@ -3,7 +3,7 @@ Not all boards have every pin, the idea is that if using TryConnect() you can potentially reuse a board and disconnect a pin in its wiring to reduce copypasta code. - Copyright 2020 VintagePC + Copyright 2020-2021 VintagePC This file is part of MK404. @@ -53,8 +53,9 @@ namespace PinNames { E0_FAN, E_MUX0_PIN, E_MUX1_PIN, - FAN_1_PIN, FAN_PIN, + FAN_1_PIN, + FAN_2_PIN, FINDA_PIN, HEATER_0_PIN, HEATER_1_PIN, @@ -88,6 +89,7 @@ namespace PinNames { SWI2C_SDA, TACH_0, TACH_1, + TACH_2, TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, @@ -112,6 +114,7 @@ namespace PinNames { Z_MIN_PIN, __TMC2130_PIN_SET(Z) __A4982_PIN_SET(Z) + MCP_CSEL, PIN_COUNT, INVALID_PIN // Used for testing error cases. diff --git a/parts/PrinterFactory.cpp b/parts/PrinterFactory.cpp index 9d565c4b..feabb838 100644 --- a/parts/PrinterFactory.cpp +++ b/parts/PrinterFactory.cpp @@ -1,7 +1,7 @@ /* PrinterFactory.cpp - Printer factory for printer models. Add your printer implementation to the map of names->constructors. - Copyright 2020 VintagePC + Copyright 2020-2021 VintagePC This file is part of MK404. @@ -20,6 +20,10 @@ */ #include "PrinterFactory.h" +#include "printers/IPCPrinter.h" +#include "printers/IPCPrinter_MMU2.h" +#include "printers/Prusa_CW1.h" +#include "printers/Prusa_CW1S.h" #include "printers/Prusa_MK1_13.h" #include "printers/Prusa_MK25S_13.h" #include "printers/Prusa_MK25_13.h" @@ -31,8 +35,6 @@ #include "printers/Prusa_MK3SMMU2.h" #include "printers/Prusa_MMU2.h" #include "printers/Test_Printer.h" -#include "printers/IPCPrinter.h" -#include "printers/IPCPrinter_MMU2.h" #include // for max #include @@ -85,6 +87,8 @@ using Dtor = void(*)(void* p); std::map>& PrinterFactory::GetModelMap() { static std::map> m_Models = { + {"Prusa_CW1", {&PrinterFactory::_CreatePrinter , &PrinterFactory::_DestroyPrinter}}, + {"Prusa_CW1S", {&PrinterFactory::_CreatePrinter , &PrinterFactory::_DestroyPrinter}}, {"Prusa_MK1_mR13", {&PrinterFactory::_CreatePrinter , &PrinterFactory::_DestroyPrinter}}, {"Prusa_MK2_mR13", {&PrinterFactory::_CreatePrinter , &PrinterFactory::_DestroyPrinter}}, {"Prusa_MK2MMU_mR13", {&PrinterFactory::_CreatePrinter, &PrinterFactory::_DestroyPrinter}}, diff --git a/parts/TelemetryHost.cpp b/parts/TelemetryHost.cpp index ffa371d3..7b69380e 100644 --- a/parts/TelemetryHost.cpp +++ b/parts/TelemetryHost.cpp @@ -36,6 +36,7 @@ TelemetryHost::TelemetryHost():Scriptable("TelHost"),IKeyClient() RegisterAction("WaitFor","Waits for a specified telemetry value to occur",ActWaitFor, {ArgType::String,ArgType::uint32}); RegisterAction("WaitForGT","Waits for a specified telemetry value to be greater than specified",ActWaitForGT, {ArgType::String,ArgType::uint32}); RegisterAction("WaitForLT","Waits for a specified telemetry value to be less than specified",ActWaitForLT, {ArgType::String,ArgType::uint32}); + RegisterAction("IsEqual", "Checks if a value is equal to the specified value and errors if not.", ActIsEqual, {ArgType::String, ArgType::uint32}); RegisterActionAndMenu("StartTrace", "Starts the telemetry trace. You must have set a category or set of items with the -t option",ActStartTrace); RegisterActionAndMenu("StopTrace", "Stops a running telemetry trace.",ActStopTrace); #endif @@ -130,6 +131,7 @@ Scriptable::LineStatus TelemetryHost::ProcessAction(unsigned int iAct, const std case ActWaitFor: case ActWaitForGT: case ActWaitForLT: + case ActIsEqual: { if (m_pCurrentIRQ == nullptr) { @@ -165,6 +167,11 @@ Scriptable::LineStatus TelemetryHost::ProcessAction(unsigned int iAct, const std m_pCurrentIRQ = nullptr; return LineStatus::Finished; } + else if (iAct == ActIsEqual) + { + std::cout << "IsEqual Failed - Expecting " << std::to_string(m_uiMatchVal) << " but got " << std::to_string(m_pCurrentIRQ->value) << "\n"; + return LineStatus::Timeout; + } else { return LineStatus::Waiting; diff --git a/parts/TelemetryHost.h b/parts/TelemetryHost.h index 597ef601..aab82142 100644 --- a/parts/TelemetryHost.h +++ b/parts/TelemetryHost.h @@ -49,7 +49,8 @@ _TC(I2C,"I2C"),\ _TC(ADC,"ADC"),\ _TC(PWM,"PWM"),\ - _TC(Misc,"Misc") + _TC(Misc,"Misc"),\ + _TC(Mux,"Mux") // Ugh, not ideal, but a dirty macro to generate references for string->enum and vice versa. #define _TC(x,y) x @@ -126,6 +127,7 @@ class TelemetryHost: public BasePeripheral, public Scriptable, private IKeyClien ActWaitFor, ActWaitForGT, ActWaitForLT, + ActIsEqual, ActStartTrace, ActStopTrace }; diff --git a/parts/boards/CW1S.cpp b/parts/boards/CW1S.cpp new file mode 100644 index 00000000..6655995f --- /dev/null +++ b/parts/boards/CW1S.cpp @@ -0,0 +1,192 @@ +/* + CW1S.h - Board definition for the Prusa CW1/S + Copyright 2021 VintagePC + + This file is part of MK404. + + MK404 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + MK404 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MK404. If not, see . + */ + +#include "CW1S.h" +#include "3rdParty/MK3/thermistortables_2.h" +#include "PinNames.h" // for Pin::FINDA_PIN, Pin::I_TMC2130_DIAG, Pin::P_TM... +#include // for glutGet, glutStrokeCharacter, GLUT_STRO... +#if defined(__APPLE__) +# include // for glTranslatef, glVertex3f, glColor3f +#else +# include // for glTranslatef, glVertex3f, glColor3f +#endif +#include "gsl-lite.hpp" + +static constexpr char strCW1[17] = "01_4040404040404"; +static constexpr char strCW1S[17] = "02_4040404040404"; + +namespace Boards +{ + + CW1S::~CW1S() + { + #ifndef __APPLE__ + pthread_cancel(m_usb_thread); + usbip_destroy(m_usb); + #endif + } + + void CW1S::SetupHardware() + { + gsl::span flash {m_pAVR->flash, m_pAVR->flashend}; + + if (m_bIsCW1S) + { + std::memcpy(&flash[0x7FE0], &strCW1S, 16); + } + else + { + std::memcpy(&flash[0x7FE0], &strCW1, 16); + } + + DisableInterruptLevelPoll(5); + AddHardware(m_lcd); + // D4-D7, + std::vector vePins = {LCD_PINS_D4,LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7}; + for (int i = 0; i < 4; i++) { + TryConnect(vePins.at(i),&m_lcd, HD44780::D4+i); + TryConnect(&m_lcd, HD44780::D4+i,vePins.at(i)); + } + TryConnect(LCD_PINS_RS,&m_lcd, HD44780::RS); + TryConnect(LCD_PINS_ENABLE, &m_lcd,HD44780::E); + m_lcd.ConnectFrom(GetPWMIRQ(LCD_BL_PIN), HD44780::BRIGHTNESS_PWM_IN); + + AddHardware(m_gpio, 0x06); + TryConnect(MCP_CSEL,&m_gpio, MCP23S17::SPI_CSEL); + + AddHardware(m_enc); + TryConnect(&m_enc, RotaryEncoder::OUT_A, BTN_EN2); + TryConnect(&m_enc, RotaryEncoder::OUT_B, BTN_EN1); + avr_connect_irq(m_enc.GetIRQ(RotaryEncoder::OUT_BUTTON), m_gpio.GetIRQ(MCP23S17::MCP_GPA0)); + + AddHardware(m_beep); + TryConnect(BEEPER, &m_beep, Beeper::DIGITAL_IN); + + AddHardware(m_tmc); + auto cfg = m_tmc.GetConfig(); + cfg.bHasNoEndStops = true; + cfg.uiFullStepsPerMM = 200; + m_tmc.SetConfig(cfg); + m_tmc.SetSimple(true); + TryConnect(X_STEP_PIN, &m_tmc, TMC2130::STEP_IN); + TryConnect(X_TMC2130_CS, &m_tmc, TMC2130::SPI_CSEL); + avr_connect_irq(m_gpio.GetIRQ(MCP23S17::MCP_GPA3), m_tmc.GetIRQ(TMC2130::ENABLE_IN)); + avr_connect_irq(m_tmc.GetIRQ(TMC2130::DIAG_OUT),m_gpio.GetIRQ(MCP23S17::MCP_GPA4)); + avr_connect_irq(m_gpio.GetIRQ(MCP23S17::MCP_GPA5), m_tmc.GetIRQ(TMC2130::DIR_IN)); + + m_lid.SetIsToggle(true); + AddHardware(m_lid); + m_lid.Press(); + avr_connect_irq(m_lid.GetIRQ(Button::BUTTON_OUT), m_gpio.GetIRQ(MCP23S17::MCP_GPA2)); + + m_tank.SetIsToggle(true); + AddHardware(m_tank); + m_tank.Press(); + avr_connect_irq(m_tank.GetIRQ(Button::BUTTON_OUT), m_gpio.GetIRQ(MCP23S17::MCP_GPA1)); + + GetPWMIRQ(FAN_PIN)->flags |= IRQ_FLAG_PWM_INV; + GetPWMIRQ(FAN_1_PIN)->flags |= IRQ_FLAG_PWM_INV; + AddHardware(m_f1,GetDIRQ(TACH_0), GetDIRQ(FAN_PIN), GetPWMIRQ(FAN_PIN), true); + avr_connect_irq(m_gpio.GetIRQ(MCP23S17::MCP_GPB3), m_f1.GetIRQ(Fan::ENABLE_IN)); + AddHardware(m_f2, GetDIRQ(TACH_1), GetDIRQ(FAN_1_PIN), GetPWMIRQ(FAN_1_PIN), true); + avr_connect_irq(m_gpio.GetIRQ(MCP23S17::MCP_GPB4), m_f2.GetIRQ(Fan::ENABLE_IN)); + if (!m_bIsCW1S) + { + AddHardware(m_f3,GetDIRQ(TACH_2), m_gpio.GetIRQ(MCP23S17::MCP_GPB2), nullptr); + } + + AddHardware(m_ht, nullptr, m_gpio.GetIRQ(MCP23S17::MCP_GPB2)); + + AddHardware(m_htUV, GetPWMIRQ(LED_PIN), m_gpio.GetIRQ(MCP23S17::MCP_GPA6)); + + AddHardware(m_muxY,1); + avr_connect_irq(m_gpio.GetIRQ(MCP23S17::MCP_GPB1), m_muxY.GetIRQ(L74HCT4052::A_IN)); + avr_connect_irq(m_gpio.GetIRQ(MCP23S17::MCP_GPB0), m_muxY.GetIRQ(L74HCT4052::B_IN)); + + + AddHardware(m_uv); + avr_connect_irq(m_gpio.GetIRQ(MCP23S17::MCP_GPA6), m_uv.GetIRQ(LED::LED_IN)); + avr_connect_irq(GetPWMIRQ(LED_PIN), m_uv.GetIRQ(LED::PWM_IN)); + + AddHardware(m_tUV,0xFF); + //NOLINTNEXTLINE - so we can keep using thermistortables.h as-is. + m_tUV.SetTable({(int16_t*)table_NCP21WF104J03RA, + sizeof(table_NCP21WF104J03RA) / sizeof(int16_t)}, + 1); + avr_connect_irq(m_muxY.GetIRQ(L74HCT4052::OUT_1),m_tUV.GetIRQ(Thermistor::ADC_TRIGGER_IN)); + avr_connect_irq(m_tUV.GetIRQ(Thermistor::ADC_VALUE_OUT),m_muxY.GetIRQ(L74HCT4052::IN_1)); + + AddHardware(m_tAmb,0xFF); + //NOLINTNEXTLINE - so we can keep using thermistortables.h as-is. + m_tAmb.SetTable({(int16_t*)table_100k_ntc, + sizeof(table_100k_ntc) / sizeof(int16_t)}, + 1); + avr_connect_irq(m_muxY.GetIRQ(L74HCT4052::OUT_0),m_tAmb.GetIRQ(Thermistor::ADC_TRIGGER_IN)); + avr_connect_irq(m_tAmb.GetIRQ(Thermistor::ADC_VALUE_OUT),m_muxY.GetIRQ(L74HCT4052::IN_0)); + + m_ht.ConnectTo(Heater::TEMP_OUT, m_tAmb.GetIRQ(Thermistor::TEMP_IN)); + m_htUV.ConnectTo(Heater::TEMP_OUT, m_tUV.GetIRQ(Thermistor::TEMP_IN)); + + #ifndef __APPLE__ // pragma: LCOV_EXCL_START + m_usb = usbip_create(m_pAVR); + if (!m_usb) + { + std::cout << "Could not create USBIP context. Skipping thread...\n"; + } + else + { + pthread_create(&m_usb_thread, nullptr, usbip_main, m_usb); + } + #endif // pragma: LCOV_EXCL_STOP + } + + void CW1S::Draw() /* function called whenever redisplay needed */ + { + glPushMatrix(); + glLoadIdentity(); // Start with an identity matrix + glScalef(4, 4, 1); + m_lcd.Draw(); + glPopMatrix(); + // Do something for the motors... + float fX = (5 + m_lcd.GetWidth()* 6)*4; + float fY = (5 + m_lcd.GetHeight() * 9); + glLoadIdentity(); + glScalef(fX/350,4,1); + glPushMatrix(); + glTranslatef(0, fY,0); + m_tmc.Draw(); + glTranslatef(170,0,0); + m_beep.Draw(); + glTranslatef(20,0,0); + m_f1.Draw(); + glTranslatef(20,0,0); + m_f2.Draw(); + glTranslatef(20,0,0); + m_f3.Draw(); + glTranslatef(20,0,0); + m_ht.Draw(); + glTranslatef(20,0,0); + m_htUV.Draw(); + glTranslatef(20,0,0); + m_uv.Draw(); + glPopMatrix(); + } + +}; // namespace Boards diff --git a/parts/boards/CW1S.h b/parts/boards/CW1S.h new file mode 100644 index 00000000..b1975ce6 --- /dev/null +++ b/parts/boards/CW1S.h @@ -0,0 +1,91 @@ +/* + CW1S.h - Board definition for the Prusa CW1/S + Copyright 2021 VintagePC + + This file is part of MK404. + + MK404 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + MK404 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MK404. If not, see . + */ + +#pragma once + +#include "74HCT4052.h" +#include "Beeper.h" +#include "Board.h" // for Board +#include "Button.h" +#include "Fan.h" +#include "HD44780GL.h" +#include "Heater.h" +#include "LED.h" +#include "MCP23S17.h" +#include "RotaryEncoder.h" +#include "TMC2130.h" +#include "Thermistor.h" +#ifndef __APPLE__ +extern "C" +{ + #include "usbip.h" +} +#endif +#include "wiring/CW1S.h" // for MM_Control_01 +#include // for uint32_t + +namespace Boards +{ + class CW1S: public Board + { + public: + explicit CW1S(uint32_t uiFreq = 16000000) + :Board(m_wiring,uiFreq){}; + + ~CW1S() override; + + void Draw(); + + protected: + void SetupHardware() override; + + void SetIsCW1S(bool bVal) { m_bIsCW1S = bVal; } + + + // void CustomAVRInit() override; + + // void CustomAVRDeinit() override; + + Button m_lid {"Lid",'l',"Opens/closes the lid"}, m_tank {"Tank",'t',"Inserts/removes the IPA tank"}; + Beeper m_beep; + Fan m_f1 {1500,'1', false}, m_f2 {1500,'2', false}, m_f3 {500,'3', false}; + HD44780GL m_lcd; + Heater m_ht {0.25, 25.f, false, 'H', 15.f, 150.f}; + Heater m_htUV {0.05f, 20.f, false, 'U', 15.f, 150.f}; + MCP23S17 m_gpio; + RotaryEncoder m_enc; + TMC2130 m_tmc {'W'}; + L74HCT4052 m_muxX, m_muxY; + LED m_uv {0x8800FF00,'U'}; + Thermistor m_tUV {20.f}, m_tAmb; + +#ifndef __APPLE__ + pthread_t m_usb_thread = 0; + usbip_t* m_usb = nullptr; +#endif + + private: + const Wirings::CW1S m_wiring = Wirings::CW1S(); + + bool m_bIsCW1S = true; + + std::string m_strTitle = "Curiosity for Washing 1 (Secret)"; + }; +}; // namespace Boards diff --git a/parts/boards/EinsyRambo.cpp b/parts/boards/EinsyRambo.cpp index dc25fe5b..dd74faaa 100644 --- a/parts/boards/EinsyRambo.cpp +++ b/parts/boards/EinsyRambo.cpp @@ -23,8 +23,8 @@ #include "Einsy_1_1a.h" // for Einsy_1_1a #include "HD44780.h" // for HD44780 #include "PinNames.h" // for Pin, Pin::BTN_ENC, Pin::W25X20CL_PIN_CS -#include // for fprintf, printf, stderr #include // for copy +#include // for fprintf, printf, stderr #include #include diff --git a/parts/boards/MM_Control_01.cpp b/parts/boards/MM_Control_01.cpp index b3b6a414..1c5521e3 100644 --- a/parts/boards/MM_Control_01.cpp +++ b/parts/boards/MM_Control_01.cpp @@ -31,6 +31,14 @@ namespace Boards { + MM_Control_01::~MM_Control_01() + { + #ifndef __APPLE__ + pthread_cancel(m_usb_thread); + usbip_destroy(m_usb); + #endif + } + void MM_Control_01::SetupHardware() { DisableInterruptLevelPoll(5); @@ -109,6 +117,17 @@ namespace Boards m_lRed[1].ConnectFrom( m_shift.GetIRQ(HC595::BIT15), LED::LED_IN); AddHardware(m_buttons,5); + #ifndef __APPLE__ + m_usb = usbip_create(m_pAVR); + // pragma: LCOV_EXCL_START + if (!m_usb) + { + std::cout << "Failed to create USBIP context\n"; + exit(1); + } + // pragma: LCOV_EXCL_STOP + pthread_create(&m_usb_thread, nullptr, usbip_main, m_usb); + #endif } diff --git a/parts/boards/MM_Control_01.h b/parts/boards/MM_Control_01.h index 93a0d791..10e81a68 100644 --- a/parts/boards/MM_Control_01.h +++ b/parts/boards/MM_Control_01.h @@ -26,6 +26,11 @@ #include "LED.h" // for LED #include "TMC2130.h" // for TMC2130 #include "uart_pty.h" // for uart_pty +#ifndef __APPLE__ + extern "C" { + #include "usbip.h" + } +#endif #include "wiring/MM_Control_01.h" // for MM_Control_01 #include // for uint32_t @@ -37,7 +42,7 @@ namespace Boards explicit MM_Control_01(uint32_t uiFreq = 16000000) :Board(m_wiring,uiFreq){}; - ~MM_Control_01() override = default; + ~MM_Control_01() override; void Draw(float fY); @@ -59,6 +64,11 @@ namespace Boards m_lFINDA {0xFFCC00FF,'F'}; ADC_Buttons m_buttons {"MMUButtons"}; + #ifndef __APPLE__ + usbip_t* m_usb = nullptr; + pthread_t m_usb_thread = 0; + #endif + private: const Wirings::MM_Control_01 m_wiring = Wirings::MM_Control_01(); diff --git a/parts/boards/MiniRambo.h b/parts/boards/MiniRambo.h index 8372c155..2fd6f7f3 100644 --- a/parts/boards/MiniRambo.h +++ b/parts/boards/MiniRambo.h @@ -34,9 +34,9 @@ #include "SDCard.h" #include "SerialLineMonitor.h" #include "Thermistor.h" +#include "miniRAMBo_1_3a.h" // for Einsy_1_1a #include "sim_irq.h" // for avr_irq_t #include "uart_pty.h" // for uart_pty -#include "miniRAMBo_1_3a.h" // for Einsy_1_1a #include // for uint32_t namespace Boards diff --git a/parts/boards/Test_Board.cpp b/parts/boards/Test_Board.cpp index 3a6bce63..4088f425 100644 --- a/parts/boards/Test_Board.cpp +++ b/parts/boards/Test_Board.cpp @@ -45,6 +45,9 @@ namespace Boards AddHardware(m_btn); TryConnect(&m_btn, Button::BUTTON_OUT, BTN_ENC); + AddHardware(m_btn2); + m_btn2.SetIsToggle(true); + TryConnect(&m_btn2, Button::BUTTON_OUT, BTN_ENC); AddHardware(m_IR,0); TryConnect(&m_IR,IRSensor::DIGITAL_OUT, IR_SENSOR_PIN); @@ -60,6 +63,27 @@ namespace Boards AddHardware(m_thrm,3); + // The ADC mux. + AddHardware(m_mux, 4); + // Share mux pins with the MMU. + TryConnect(E_MUX0_PIN, &m_mux, L74HCT4052::A_IN); + TryConnect(E_MUX1_PIN, &m_mux, L74HCT4052::B_IN); + // Pre-setup the inputs. 5V = FF + m_mux.GetIRQ(L74HCT4052::IN_0)->value = 5000; + m_mux.GetIRQ(L74HCT4052::IN_1)->value = 2500; + m_mux.GetIRQ(L74HCT4052::IN_2)->value = 1250; + m_mux.GetIRQ(L74HCT4052::IN_3)->value = 100; + + + AddHardware(m_gpio); + TryConnect(MCP_CSEL, &m_gpio, MCP23S17::SPI_CSEL); + // Setup a crossover loopback, A4-7 to B3-0 and B4-7 to A3-0 + for (int i=0; i<4; i++) + { + avr_connect_irq(m_gpio.GetIRQ(MCP23S17::MCP_GPA4 + i),m_gpio.GetIRQ(MCP23S17::MCP_GPB3 - i)); + avr_connect_irq(m_gpio.GetIRQ(MCP23S17::MCP_GPB4 + i),m_gpio.GetIRQ(MCP23S17::MCP_GPA3 - i)); + } + TMC2130::TMC2130_cfg_t cfg; cfg.iMaxMM = 20; diff --git a/parts/boards/Test_Board.h b/parts/boards/Test_Board.h index 18340185..cd15da3e 100644 --- a/parts/boards/Test_Board.h +++ b/parts/boards/Test_Board.h @@ -20,6 +20,7 @@ #pragma once +#include "74HCT4052.h" #include "A4982.h" #include "ADC_Buttons.h" #include "Beeper.h" // for Beeper @@ -32,6 +33,7 @@ #include "Heater.h" // for Heater #include "IRSensor.h" // for IRSensor #include "LED.h" // for LED +#include "MCP23S17.h" #include "MMU1.h" #include "PAT9125.h" #include "PINDA.h" // for PINDA @@ -65,11 +67,14 @@ namespace Boards void OnAVRDeinit() override; + L74HCT4052 m_mux; + A4982 m_Allg{'Y'}; RotaryEncoder encoder {true}; Button m_btn {"Button",'p', "Test button"}; + Button m_btn2 {"Toggle",'q', "Test toggle"}; SerialLineMonitor m_Monitor {"Serial0"}; @@ -89,6 +94,8 @@ namespace Boards Heater m_heat {5.f, 25.f, false, 'B',10.f,50.f}; + MCP23S17 m_gpio; + MMU1 m_MM1{}; Fan m_Fan {2000,'F'}; diff --git a/parts/components/74HCT4052.cpp b/parts/components/74HCT4052.cpp new file mode 100644 index 00000000..3675fb76 --- /dev/null +++ b/parts/components/74HCT4052.cpp @@ -0,0 +1,56 @@ +/* + 74HCT4052.cpp - Mux component sim. + + Copyright 2021 VintagePC + + This file is part of MK404. + + MK404 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + MK404 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MK404. If not, see . + */ + +#include "74HCT4052.h" +#include "BasePeripheral.h" +#include "TelemetryHost.h" +#include + +uint32_t L74HCT4052::OnADCRead(struct avr_irq_t* /*irq*/, uint32_t) +{ + uint8_t sel = ((GetIRQ(B_IN)->value)<<1U) | GetIRQ(A_IN)->value; + // give it a chance to respond - attached to SRC 255 so it doesn't bind a REAL adc pin. + union { + avr_adc_mux_t t; + uint32_t raw; + } mux = {{0}}; + mux.t.src = 0xFFU; + RaiseIRQ(OUT_0 + sel,mux.raw); + uint8_t uiIndex = IN_0 + sel; + // Return value. + // printf("Reading %u from chan %u\n",GetIRQ(uiIndex)->value, sel); + return GetIRQ(uiIndex)->value; +} + +void L74HCT4052::Init(struct avr_t * avr, uint8_t adc_mux_number) +{ + _Init(avr, adc_mux_number, this); + + auto &TH = TelemetryHost::GetHost(); + TH.AddTrace(this, ADC_VALUE_OUT, {TC::ADC, TC::Mux},16); + TH.AddTrace(this, A_IN,{TC::Mux}); + TH.AddTrace(this, B_IN,{TC::Mux}); + TH.AddTrace(this, OUT_0,{TC::Mux}); + TH.AddTrace(this, OUT_1,{TC::Mux}); + TH.AddTrace(this, OUT_2,{TC::Mux}); + TH.AddTrace(this, OUT_3,{TC::Mux}); +} + diff --git a/parts/components/74HCT4052.h b/parts/components/74HCT4052.h new file mode 100644 index 00000000..ad48bf40 --- /dev/null +++ b/parts/components/74HCT4052.h @@ -0,0 +1,63 @@ +/* + 74HCT4052.cpp - Mux component sim. + + Copyright 2021 VintagePC + + This file is part of MK404. + + MK404 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + MK404 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MK404. If not, see . + */ + + +#pragma once + +#include "ADCPeripheral.h" // for ADCPeripheral +#include "sim_avr.h" // for avr_t +#include // for uint32_t, uint8_t +#include // for string + +class L74HCT4052:public ADCPeripheral +{ + public: + // NOTE: While this is a combined chip comprising two + // muxes, it makes sense to split due to the ADC architecture + // and have each handled on its own, isolated to its single ADC line. + #define IRQPAIRS \ + _IRQ(ADC_TRIGGER_IN,"adc.out") \ + _IRQ(DIGITAL_OUT, ">adc.digital_out") \ + _IRQ(IN_0, " &vArgs) override; @@ -69,4 +72,6 @@ class Button:public BasePeripheral, public Scriptable, private IKeyClient ActPressAndRelease }; + bool m_bIsToggle = false; + }; diff --git a/parts/components/Fan.cpp b/parts/components/Fan.cpp index 43bab7af..c1fe0ffb 100644 --- a/parts/components/Fan.cpp +++ b/parts/components/Fan.cpp @@ -28,7 +28,7 @@ #define TRACE(_w) #endif -Fan::Fan(uint16_t iMaxRPM, char chrSym, bool bIsSoftPWM):SoftPWMable(bIsSoftPWM,this),Scriptable("Fan"),GLIndicator(chrSym,false,true),m_uiMaxRPM(iMaxRPM) +Fan::Fan(uint16_t iMaxRPM, char chrSym, bool bIsSoftPWM):SoftPWMable(bIsSoftPWM,this),Scriptable("Fan"),GLIndicator(chrSym,false,true),m_bIsSoftPWM(bIsSoftPWM),m_uiMaxRPM(iMaxRPM) { RegisterActionAndMenu("Stall", "Stalls the fan", Actions::Stall); RegisterActionAndMenu("Resume","Resumes fan from a stall condition",Actions::Resume); @@ -44,6 +44,12 @@ avr_cycle_count_t Fan::OnTachChange(avr_t *, avr_cycle_count_t) return 0; } +avr_cycle_count_t Fan::OnFanDigiDelay(avr_t *, avr_cycle_count_t) +{ + OnPWMChange(nullptr, 255U*m_bDigiDelayVal); + return 0; +} + Scriptable::LineStatus Fan::ProcessAction(unsigned int ID, const std::vector& vArgs) { switch (ID) @@ -92,10 +98,56 @@ void Fan::OnPWMChange(struct avr_irq_t*, uint32_t value) // Just a dummy wrapper to handle non-PWM control (digitalWrite) void Fan::OnDigitalChange(struct avr_irq_t *, uint32_t value) { - RaiseIRQ(PWM_IN, value*0xFF); + RaiseIRQ(PWM_IN, value*0xFFU); } -void Fan::Init(struct avr_t *avr, avr_irq_t *irqTach, avr_irq_t *irqDigital, avr_irq_t *irqPWM) +void Fan::OnEnableInput(struct avr_irq_t* /*irq*/, uint32_t /*value*/) +{ + // Trigger update if PWM val or digital changes. + OnEnableChange(GetIRQ(ENABLE_IN), GetIRQ(ENABLE_IN)->value); +} + +void Fan::OnEnableChange(avr_irq_t* /*irq*/, uint32_t value) +{ + // printf("Enable %c changed: EN %02x DIG %02x PWM %02x\n", GetLabel(), value, GetIRQ(DIGITAL_IN)->value, GetIRQ(PWM_IN)->value); + bool bSetTimer = false; + if (value) { + if (GetIRQ(DIGITAL_IN)->value) // 255 is a digitalwrite(1) + { + bSetTimer = true; + value = 0xFFU; + } + else if(GetIRQ(PWM_IN)->value) // 1-254 + { + value = GetIRQ(PWM_IN)->value; + } + else + { + bSetTimer = true; + value = 0U; + } + } + else // enable line low, fan off. + { + value = 0; + + } + if (bSetTimer) + { + m_bDigiDelayVal = value>0; + RegisterTimerUsec(m_fcnFanDelay,5000,this); + } + else + { + CancelTimer(m_fcnFanDelay,this); + if (value != m_uiPWM) + { + OnPWMChange(nullptr, value); + } + } +} + +void Fan::Init(struct avr_t *avr, avr_irq_t *irqTach, avr_irq_t *irqDigital, avr_irq_t *irqPWM, bool bIsEnableCtl) { _Init(avr, this); @@ -103,8 +155,21 @@ void Fan::Init(struct avr_t *avr, avr_irq_t *irqTach, avr_irq_t *irqDigital, avr if(irqDigital) ConnectFrom(irqDigital, DIGITAL_IN); if(irqTach) ConnectTo(TACH_OUT,irqTach); - RegisterNotify(PWM_IN, MAKE_C_CALLBACK(Fan,OnPWMChange), this); - RegisterNotify(DIGITAL_IN,MAKE_C_CALLBACK(Fan,OnDigitalInSPWM), this); + + // Note - this is partly for the CW1 FW where the enable pin is changed after the CWS so + // we use that as a trigger to "lock in" the current value rather than trying to mess with the mashup of + // digital and pwm signal. + if (!bIsEnableCtl) + { + RegisterNotify(PWM_IN, MAKE_C_CALLBACK(Fan,OnPWMChange), this); + RegisterNotify(DIGITAL_IN,MAKE_C_CALLBACK(Fan,OnDigitalInSPWM), this); + } + else + { + RegisterNotify(PWM_IN, MAKE_C_CALLBACK(Fan,OnEnableInput), this); + RegisterNotify(DIGITAL_IN, MAKE_C_CALLBACK(Fan,OnEnableInput), this); + } + RegisterNotify(ENABLE_IN,MAKE_C_CALLBACK(Fan,OnEnableChange), this); auto &TH = TelemetryHost::GetHost(); TH.AddTrace(this, PWM_IN,{TC::PWM, TC::Fan},8); diff --git a/parts/components/Fan.h b/parts/components/Fan.h index 32ddb4ad..d22057a8 100644 --- a/parts/components/Fan.h +++ b/parts/components/Fan.h @@ -39,7 +39,8 @@ class Fan:public SoftPWMable, public Scriptable, public GLIndicator public: // Macro to define a set of IRQs and string names. #define IRQPAIRS _IRQ(PWM_IN,"")\ + _IRQ(ENABLE_IN,"Fan.tach_out")\ _IRQ(SPEED_OUT, ">Fan.speed_out")\ _IRQ(ROTATION_OUT, ">Fan.angle_out") @@ -50,8 +51,8 @@ class Fan:public SoftPWMable, public Scriptable, public GLIndicator // Constructs a new Fan with a max RPM of iMaxRPM (at PWM 255) explicit Fan(uint16_t iMaxRPM, char chrSym = ' ', bool bIsSoftPWM = false); - // Initializes the fan with avr, and connects to irqTach (out), irqDigital (in), and irqPWM (pwm control value) - void Init(struct avr_t* avr, avr_irq_t *irqTach, avr_irq_t *irqDigital, avr_irq_t *irqPWM); + // Initializes the fan with avr, and connects to irqTach (out), irqDigital (in), irqPWM (pwm control value), isEnableCtl (whether the fan is controlled with an EN line) + void Init(struct avr_t* avr, avr_irq_t *irqTach, avr_irq_t *irqDigital, avr_irq_t *irqPWM, bool bIsEnableCt = false); // Flags the fan as stalled/jammed. or not. void SetStall(bool bStall); @@ -72,15 +73,21 @@ class Fan:public SoftPWMable, public Scriptable, public GLIndicator // Callback for full on/off void OnDigitalChange(avr_irq_t *irq, uint32_t value) override; + void OnEnableChange(avr_irq_t *irq, uint32_t value); + void OnEnableInput(struct avr_irq_t *, uint32_t value); + private: // Callback for tach pulse update. avr_cycle_count_t OnTachChange(avr_t *avr, avr_cycle_count_t when); + avr_cycle_count_t OnFanDigiDelay(avr_t *avr, avr_cycle_count_t when); bool m_bAuto = true; bool m_bPulseState = false; bool m_bIsSoftPWM = false; + bool m_bDigiDelayVal = false; + uint8_t m_uiPWM = 0; uint16_t m_uiMaxRPM = 2000; uint16_t m_uiCurrentRPM = 0; @@ -88,6 +95,8 @@ class Fan:public SoftPWMable, public Scriptable, public GLIndicator avr_cycle_timer_t m_fcnTachChange = MAKE_C_TIMER_CALLBACK(Fan,OnTachChange); + // Bit of an ugly hack for the bug that ODR writes update all bits in simavr... + avr_cycle_timer_t m_fcnFanDelay = MAKE_C_TIMER_CALLBACK(Fan,OnFanDigiDelay); enum Actions { diff --git a/parts/components/GLIndicator.h b/parts/components/GLIndicator.h index 1b2e9752..91ccd11b 100644 --- a/parts/components/GLIndicator.h +++ b/parts/components/GLIndicator.h @@ -40,6 +40,7 @@ class GLIndicator void SetValue(uint8_t value); inline void SetLabel(char label) { m_chrLabel = label;} + inline char GetLabel() { return m_chrLabel.load();} inline void SetColor(uint32_t color) { m_Color = hexColor_t(color); } @@ -64,7 +65,7 @@ class GLIndicator bool m_bVisible = false; bool m_bBlackBG = false; bool m_bInterp = false; - std::atomic_bool m_bDisabled {0}; + std::atomic_bool m_bDisabled {false}; std::atomic_int16_t m_uiLerpVal = {0}; static constexpr Color3fv m_colColdTemp = {0, 1, 1}; diff --git a/parts/components/HD44780GL.cpp b/parts/components/HD44780GL.cpp index f535314d..0cfba460 100644 --- a/parts/components/HD44780GL.cpp +++ b/parts/components/HD44780GL.cpp @@ -36,8 +36,8 @@ #include "hd44780_charROM.h" // for (anonymous), hd44780_ROM_AOO #include "sim_avr_types.h" // for avr_regbit_t #include "sim_regbit.h" // for avr_regbit_get, AVR_IO_REGBIT -#include // for array<>::value_type, array #include +#include // for array<>::value_type, array #include //#define TRACE(_w) _w diff --git a/parts/components/MCP23S17.cpp b/parts/components/MCP23S17.cpp new file mode 100644 index 00000000..d525ed22 --- /dev/null +++ b/parts/components/MCP23S17.cpp @@ -0,0 +1,225 @@ +/* + MCP23S17.cpp - simulated GPIO extender. + + Copyright 2021 VintagePC + + This file is part of MK404. + + MK404 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + MK404 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MK404. If not, see . + */ + +#include "MCP23S17.h" +#include "TelemetryHost.h" +#include "gsl-lite.hpp" +#include // for memset + +enum { + R_OFF_IODIR, + R_OFF_IPOL, + R_OFF_GPINTEN, + R_OFF_DEFVAL, + R_OFF_INTCON, + R_OFF_IOCON, + R_OFF_GPPU, + R_OFF_INTF, + R_OFF_INTCAP, + R_OFF_GPIO, + R_OFF_OLAT, + R_OFF_END +}; + +/* + * called when a SPI byte is received. It's guarded by the SPIPeripheral CSEL check. + */ +uint8_t MCP23S17::OnSPIIn(struct avr_irq_t *, uint32_t value) +{ + // Just for tracing, the bytes are not attached to anything. + RaiseIRQ(SPI_BYTE_IN, value); + // (printf("GPIO: byte received: %02x\n",value)); + //TRACE(printf("TMC2130 %c: Clocking (%10lx) out %02x\n",m_cAxis.load(),m_cmdOut.all,byte)); + uint8_t byte = 0xFF; + switch (m_state) { + case MCP_STATE::IDLE: + m_hdr.opcode = value & 0xFFU; + m_state = MCP_STATE::ADDR; + break; + case MCP_STATE::ADDR: + m_addr = value & 0xFFU; + m_state = MCP_STATE::DATA; + break; + case MCP_STATE::DATA: + if (m_hdr.READ) + { + byte = gsl::at(m_regs.raw,ToBank1Addr(m_addr)); + } + else + { + OnWrite(ToBank1Addr(m_addr),value); + } + if (m_regs.bank[0].IOCON.SEQOP==0) + { + m_addr++; + } + break; + // pragma: LCOV_EXCL_START + default: + break; + // pragma: LCOV_EXCL_STOP + } + SetSendReplyFlag(); + RaiseIRQ(SPI_BYTE_OUT,byte); + return byte; // SPIPeripheral takes care of the reply. +} + +void MCP23S17::OnODRChanged(uint8_t bank, uint8_t old, uint8_t value) +{ + auto uiChanged = old^value; + auto base = bank ? MCP_GPB0 : MCP_GPA0; + auto uiDir = ~(gsl::at(m_regs.bank,bank).IODIR); + uint8_t uiPos = 0; + while (uiChanged) + { + // Pin must be in output mode to fire IRQ. + if (uiChanged & 1U & uiDir) + { + m_uiSelf = base + uiPos; + RaiseIRQ(base + uiPos, value & 1U); + m_uiSelf = 0; + } + uiChanged >>= 1U; + value >>= 1U; + uiDir >>= 1U; + uiPos++; + } +} + + +void MCP23S17::OnWrite(uint8_t b1_addr, uint8_t value) +{ + bool bank = b1_addr >= R_OFF_END; + switch (b1_addr % 0x10) + { + case R_OFF_GPIO: + case R_OFF_OLAT: + { + OnODRChanged(bank, gsl::at(m_regs.bank,bank).OLAT, value); + auto inMask = (gsl::at(m_regs.bank,bank).IODIR); + value = value & ~inMask; + value |= (gsl::at(m_regs.bank,bank).OLAT & inMask); + gsl::at(m_regs.bank,bank).OLAT = value; + //printf("ODR update: %02x %02x / I: %02x %02x\n", m_regs.bank[0].OLAT, m_regs.bank[1].OLAT, m_regs.bank[0].GPIO,m_regs.bank[1].GPIO); + } + break; + case R_OFF_IOCON: // update both IOCONs so we don't need to also redirect reads. + { + gsl::at(m_regs.raw,R_OFF_IOCON) = value; + gsl::at(m_regs.raw,(R_OFF_IOCON | 0x10)) = value; + + } + break; + default: + //printf("MCP: Wrote %02x to %02x\n", value, ToBank1Addr(m_addr)); + gsl::at(m_regs.raw,b1_addr) = value; + } +} + +void MCP23S17::OnPinChanged(struct avr_irq_t* irq,uint32_t value) +{ + if (m_uiSelf == irq->irq) + { + // Reentrancy guard + return; + } + uint8_t pin = 0U; + uint8_t bank = 0U; + if (irq->irq >= MCP_GPB0) + { + pin = irq->irq - MCP_GPB0; + bank = 1U; + } + else + { + pin = irq->irq - MCP_GPA0; + } + auto pin_mask = 1U << pin; + //only update GPIO if the dir is in. + if (gsl::at(m_regs.bank,bank).IODIR & pin_mask) + { + //printf("MCP: Pin changed: %c %02x to %d (was %02x)", 'A' + bank, pin, value,m_regs.bank[bank].GPIO); + if (value) + { + gsl::at(m_regs.bank,bank).GPIO |= pin_mask; + } + else + { + gsl::at(m_regs.bank,bank).GPIO &= ~pin_mask; + } + //printf(" now %02x\n",m_regs.bank[bank].GPIO); + } +} + +// Converts the SPI address to a bank1-style (non-interleaved) addr. +uint8_t MCP23S17::ToBank1Addr(uint8_t addr) +{ + // internal config is the same as BANK=1. + if (m_regs.bank[0].IOCON.BANK == 0) + { + uint8_t bank = addr & 0b1U; + addr >>= 1U; + addr |= (bank<<4U); + } + return addr; +} + +// Called when CSEL changes. +void MCP23S17::OnCSELIn(struct avr_irq_t *, uint32_t value) +{ + if (value) + { + m_state = MCP_STATE::IDLE; + } +} + +// needed because cppcheck doesn't seem to do bitfield unions correctly. +// cppcheck-suppress uninitMemberVar +MCP23S17::MCP23S17() +{ + // Check register packing/sizes: + static_assert(sizeof(m_regs.bank[0].GPIO)==sizeof(uint8_t), __FILE__" registers misaligned!"); + static_assert(sizeof(m_regs.bank)==sizeof(m_regs), __FILE__" registers misaligned!"); + static_assert(sizeof(m_regs.bank)==sizeof(m_regs.raw), __FILE__" registers misaligned!"); + static_assert(sizeof(m_regs.bank[0])==0x10, __FILE__" registers misaligned!"); + +} + +void MCP23S17::Init(struct avr_t * avr, uint8_t uiGPIOA, uint8_t uiGPIOB) +{ + _InitWithArgs(avr, this, nullptr, SPI_CSEL); + + for (int i = MCP_GPA0; i <= MCP_GPB7; i++) + { + RegisterNotify(i, MAKE_C_CALLBACK(MCP23S17,OnPinChanged), this); + } + + memset(&m_regs.raw,0,sizeof(m_regs.raw)); + m_regs.bank[0].IODIR = 0xFF; + m_regs.bank[0].GPIO |= uiGPIOA; + m_regs.bank[1].IODIR = 0xFF; + m_regs.bank[1].GPIO |= uiGPIOB; + + auto &TH = TelemetryHost::GetHost(); + TH.AddTrace(this, SPI_BYTE_IN,{TC::SPI, TC::Mux},8); + TH.AddTrace(this, SPI_BYTE_OUT,{TC::SPI, TC::Mux},8); + TH.AddTrace(this, SPI_CSEL, {TC::SPI, TC::Mux, TC::OutputPin}); +} diff --git a/parts/components/MCP23S17.h b/parts/components/MCP23S17.h new file mode 100644 index 00000000..2eb0de02 --- /dev/null +++ b/parts/components/MCP23S17.h @@ -0,0 +1,132 @@ +/* + MCP23S17.h - simulated GPIO extender. + + Copyright 2021 VintagePC + + This file is part of MK404. + + MK404 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + MK404 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MK404. If not, see . + */ + + +#pragma once + +#include "BasePeripheral.h" // for MAKE_C_TIMER_CALLBACK +#include "SPIPeripheral.h" // for SPIPeripheral +#include "sim_irq.h" // for avr_irq_t +#include // for uint8_t, uint32_t, int32_t, uint16_t +#include // for string +#include // for vector + +using mcp_reg_bank_1_t = struct mcp_reg_bank_1_t { + uint8_t IODIR; //0x00 + uint8_t IPOL; //0x01 + uint8_t GPINTEN; //0x02 + uint8_t DEFVAL; //0x03 + uint8_t INTCON; //0x04 + union { + uint8_t iocon; //0x05 + struct { + uint8_t :1; + uint8_t INTPOL :1; + uint8_t ODR :1; + uint8_t HAEN :1; + uint8_t DISSLW :1; + uint8_t SEQOP :1; + uint8_t MIRROR :1; + uint8_t BANK :1; + } __attribute__ ((__packed__)) IOCON; + }; + uint8_t GPPU; //0x06 + uint8_t INTF; //0x07 + uint8_t INTCAP; //0x08 + uint8_t GPIO; //0x09 + uint8_t OLAT; //0x0A + uint8_t _unused[5]; //0x0B-F +}; + +class MCP23S17: public SPIPeripheral +{ + public: + #define IRQPAIRS \ + _IRQ(SPI_BYTE_IN, "8mcp23s17.byte_out") \ + _IRQ(SPI_CSEL, "mcp23s17.a0") \ + _IRQ(MCP_GPA1, "<>mcp23s17.a1") \ + _IRQ(MCP_GPA2, "<>mcp23s17.a2") \ + _IRQ(MCP_GPA3, "<>mcp23s17.a3") \ + _IRQ(MCP_GPA4, "<>mcp23s17.a4") \ + _IRQ(MCP_GPA5, "<>mcp23s17.a5") \ + _IRQ(MCP_GPA6, "<>mcp23s17.a6") \ + _IRQ(MCP_GPA7, "<>mcp23s17.a7") \ + _IRQ(MCP_GPB0, "<>mcp23s17.b0") \ + _IRQ(MCP_GPB1, "<>mcp23s17.b1") \ + _IRQ(MCP_GPB2, "<>mcp23s17.b2") \ + _IRQ(MCP_GPB3, "<>mcp23s17.b3") \ + _IRQ(MCP_GPB4, "<>mcp23s17.b4") \ + _IRQ(MCP_GPB5, "<>mcp23s17.b5") \ + _IRQ(MCP_GPB6, "<>mcp23s17.b6") \ + _IRQ(MCP_GPB7, "<>mcp23s17.b7") + #include "IRQHelper.h" + + // Default constructor. + explicit MCP23S17(); + virtual ~MCP23S17() = default; + + // Registers with SimAVR. + void Init(avr_t *avr, uint8_t uiGPIOA = 0, uint8_t uiGPIOB = 0); + + inline const std::string GetName(){return "MCP23S17";} + + private: + // Lookup for bank mode to internal reg order + uint8_t ToBank1Addr(uint8_t addr); + + // handles a write. Addr MUST be bank1-style. + void OnWrite(uint8_t b1_addr, uint8_t value); + + void OnODRChanged(uint8_t bank, uint8_t old, uint8_t value); + + void OnPinChanged(struct avr_irq_t * irq,uint32_t value); + + // SPI handlers. + uint8_t OnSPIIn(avr_irq_t *irq, uint32_t value) override; + void OnCSELIn(avr_irq_t *irq, uint32_t value) override; + enum class MCP_STATE{ + IDLE, + OPCODE, + ADDR, + DATA, + }; + MCP_STATE m_state = MCP_STATE::IDLE; + + uint8_t m_addr = 0; + union { + uint8_t opcode; + struct { + uint8_t READ :1; + uint8_t HADDR :3; + uint8_t _FIXED :4; + } __attribute__ ((__packed__)); + } m_hdr = {0}; + + union { + uint8_t raw[0x20]; + mcp_reg_bank_1_t bank[2]; + } m_regs = {{0}}; + + uint8_t m_uiSelf = 0U; + +}; diff --git a/parts/components/PINDA.cpp b/parts/components/PINDA.cpp index ef91638d..286e255b 100644 --- a/parts/components/PINDA.cpp +++ b/parts/components/PINDA.cpp @@ -133,8 +133,8 @@ void PINDA::CheckTrigger() // Just calc the nearest MBL point and report it. const float fMaxX = 255.; const float fMaxY = 210.; - uint8_t iX = floor((std::min(fMaxX-1.f, std::max(0.f, m_fPos[0] - m_fOffset[0]))/fMaxX)*7); - uint8_t iY = floor((std::min(fMaxY-1.f, std::max(0.f, m_fPos[1] - m_fOffset[1]))/fMaxY)*7); + uint8_t iX = std::floor((std::min(fMaxX-1.f, std::max(0.f, m_fPos[0] - m_fOffset[0]))/fMaxX)*7); + uint8_t iY = std::floor((std::min(fMaxY-1.f, std::max(0.f, m_fPos[1] - m_fOffset[1]))/fMaxY)*7); float fZTrig = gsl::at(m_mesh.points,iX+(7*iY)); diff --git a/parts/components/TMC2130.cpp b/parts/components/TMC2130.cpp index f4961ff1..8869bac6 100644 --- a/parts/components/TMC2130.cpp +++ b/parts/components/TMC2130.cpp @@ -213,9 +213,13 @@ void TMC2130::OnStepIn(struct avr_irq_t * irq, uint32_t value) TRACE(printf("cur pos: %f (%u)\n",m_fCurPos,m_iCurStep)); bStall |= m_bStall; if (bStall) + { SetDiag(); + } else + { ClearDiag(); + } m_regs.defs.DRV_STATUS.stst = false; // 2^20 comes from the datasheet. RegisterTimer(m_fcnStandstill,1U<<20U,this); diff --git a/parts/components/TMC2130.h b/parts/components/TMC2130.h index 5c179403..419031fb 100644 --- a/parts/components/TMC2130.h +++ b/parts/components/TMC2130.h @@ -63,7 +63,7 @@ class TMC2130: public SPIPeripheral, public Scriptable, public GLMotor // Default constructor. explicit TMC2130(char cAxis = ' '); - virtual ~TMC2130(); + ~TMC2130() override; // Sets the configuration to the provided values. (inversion, positions, etc) void SetConfig(TMC2130_cfg_t cfg); diff --git a/parts/components/usb_types.h b/parts/components/usb_types.h new file mode 100644 index 00000000..b2c90955 --- /dev/null +++ b/parts/components/usb_types.h @@ -0,0 +1,91 @@ +/* vim: set sts=4:sw=4:ts=4:noexpandtab + usb_types.h + + Copyright 2017 Torbjorn Tyridal + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . +*/ + +#include + +#define byte uint8_t +#define word uint16_t + +struct usb_setup_pkt { + byte reqtype; + byte req; + word wValue; + word wIndex; + word wLength; +} __attribute__((__packed__)); + +#define USB_REQTYPE_DIR_DEV_TO_HOST 0x80 +#define USB_REQTYPE_STD 0 +#define USB_REQTYPE_DEVICE 0 + +#define USB_REQUEST_GET_DESCRIPTOR 0x06 + + +// USB Descriptors +#define USB_DESCRIPTOR_DEVICE 0x01 // Device Descriptor. +#define USB_DESCRIPTOR_CONFIGURATION 0x02 // Configuration Descriptor. +#define USB_DESCRIPTOR_STRING 0x03 // String Descriptor. +#define USB_DESCRIPTOR_INTERFACE 0x04 // Interface Descriptor. +#define USB_DESCRIPTOR_ENDPOINT 0x05 // Endpoint Descriptor. +#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // Device Qualifier. + +struct usb_device_descriptor { + byte bLength; // Length of this descriptor. + byte bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + word bcdUSB; // USB Spec Release Number (BCD). + byte bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + byte bDeviceSubClass; // Subclass code (assigned by the USB-IF). + byte bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + byte bMaxPacketSize0; // Maximum packet size for endpoint 0. + word idVendor; // Vendor ID (assigned by the USB-IF). + word idProduct; // Product ID (assigned by the manufacturer). + word bcdDevice; // Device release number (BCD). + byte iManufacturer; // Index of String Descriptor describing the manufacturer. + byte iProduct; // Index of String Descriptor describing the product. + byte iSerialNumber; // Index of String Descriptor with the device's serial number. + byte bNumConfigurations; // Number of possible configurations. +} __attribute__ ((__packed__)); + +struct usb_configuration_descriptor +{ + byte bLength; // Length of this descriptor. + byte bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). + word wTotalLength; // Total length of all descriptors for this configuration. + byte bNumInterfaces; // Number of interfaces in this configuration. + byte bConfigurationValue; // Value of this configuration (1 based). + byte iConfiguration; // Index of String Descriptor describing the configuration. + byte bmAttributes; // Configuration characteristics. + byte bMaxPower; // Maximum power consumed by this configuration. +} __attribute__ ((__packed__)); + + +struct usb_interface_descriptor +{ + byte bLength; // Length of this descriptor. + byte bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). + byte bInterfaceNumber; // Number of this interface (0 based). + byte bAlternateSetting; // Value of this alternate interface setting. + byte bNumEndpoints; // Number of endpoints in this interface. + byte bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + byte bInterfaceSubClass; // Subclass code (assigned by the USB-IF). + byte bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + byte iInterface; // Index of String Descriptor describing the interface. +} __attribute__ ((__packed__)); diff --git a/parts/components/usbip.c b/parts/components/usbip.c new file mode 100644 index 00000000..48d64f2d --- /dev/null +++ b/parts/components/usbip.c @@ -0,0 +1,553 @@ +/* vim: set sts=4:sw=4:ts=4:noexpandtab + usbip.c + + Copyright 2017 Torbjorn Tyridal + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + + + This code is heavily inspired by + https://github.com/lcgamboa/USBIP-Virtual-USB-Device + Copyright (c) : 2016 Luis Claudio Gambôa Lopes +*/ + +/* + this avrsim part will expose your usb-avr as a usbip server. + To connect it to the host system load modules usbip-core and vhci-hcd, + then: + ~# usbip -a 127.0.0.1 1-1 +*/ + +// NOTE: I'm excluding this from coverage because: +// a) it's not my code +// b) I may end up converting it to C++ and rewriting it in the future +// c) there probably isn't a good way to test this on the build runners anyway... +// pragma: LCOV_EXCL_START + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define USBIP_PORT_NUM 3240 + +#include "usb_types.h" +#include "usbip_types.h" + +#include "avr_usb.h" + +#define min(a,b) ((a)<(b)?(a):(b)) + +struct usbip_t { + struct avr_t * avr; + bool attached; + bool udev_valid; + struct usbip_usb_device udev; +}; + +static ssize_t +avr_usb_read( + const struct usbip_t * p, + unsigned int ep, + void * buf, + size_t blen) +{ + byte * b = buf; + struct avr_io_usb pkt = { ep, blen, b }; + if (buf) { + while (blen) { + switch (avr_ioctl(p->avr, AVR_IOCTL_USB_READ, &pkt)) { + case AVR_IOCTL_USB_NAK: + if (pkt.buf - b == 0) return -1; + else return pkt.buf - b; + case AVR_IOCTL_USB_STALL: + printf(" STALL (read)\n"); + return -1; + case 0: + if (!pkt.sz) + blen = 0; + break; + default: + fprintf(stderr, "Unknown avr_ioctl return value\n"); + abort(); + } + pkt.buf += pkt.sz & 0xff; + blen -= pkt.sz & 0xff; + if (pkt.sz & 0xf00) break; + pkt.sz = blen; + } + return pkt.buf - b; + } else { + int ret; + while ((ret = avr_ioctl(p->avr, AVR_IOCTL_USB_READ, &pkt)) + == AVR_IOCTL_USB_NAK) { + usleep(50000); + } + return 0; + } +} + +static int +avr_usb_write( + const struct usbip_t * p, + unsigned int ep, + void * buf, + size_t blen) +{ + struct avr_io_usb pkt = { ep, blen, buf }; + do { + switch (avr_ioctl(p->avr, AVR_IOCTL_USB_WRITE, &pkt)) { + case 0: break; + case AVR_IOCTL_USB_NAK: + if (buf) return -1; + usleep(50000); + continue; + case AVR_IOCTL_USB_STALL: + printf(" STALL (write)\n"); + return -1; + default: + fprintf(stderr, "Unknown avr_ioctl return\n"); + abort(); + } + pkt.buf += pkt.sz; + blen -= pkt.sz; + pkt.sz = blen; + if (!blen) break; + } while (1); + return 0; +} + +static int +control_read( + const struct usbip_t * p, + byte reqtype, + byte req, + word wValue, + word wIndex, + word wLength, + byte * data) +{ + int ret; + struct usb_setup_pkt buf = { + reqtype | USB_REQTYPE_DIR_DEV_TO_HOST, + req, + wValue, + wIndex, + wLength }; + const unsigned int ctrlep = 0; + struct avr_io_usb pkt = { ctrlep, sizeof buf, (uint8_t*) &buf }; + + printf("ctrl_read typ:%u req:%u val:%04x len:%u bytes\n", reqtype, req, wValue, wLength); + avr_ioctl(p->avr, AVR_IOCTL_USB_SETUP, &pkt); + + ret = avr_usb_read(p, ctrlep, data, wLength); + + avr_usb_write(p, ctrlep, NULL, 0); + + return ret; +} + +static bool +get_descriptor( + const struct usbip_t * p, + unsigned char descr_type, + void * buf, + size_t length) +{ + const unsigned char descr_index = 0; + return control_read(p, + USB_REQTYPE_STD + USB_REQTYPE_DEVICE, + USB_REQUEST_GET_DESCRIPTOR, + descr_type << 8 | descr_index, + 0, + length, + buf) == (int)length; +} + +static bool +load_device_and_config_descriptor( + struct usbip_t * p) +{ + struct usb_device_descriptor dd; + struct usb_configuration_descriptor cd; + if (!get_descriptor(p, USB_DESCRIPTOR_DEVICE, &dd, sizeof dd)) { + fprintf(stderr, "get device descriptor failed\n"); + p->udev_valid = false; + return false; + } + + if (!get_descriptor(p, USB_DESCRIPTOR_CONFIGURATION, &cd, sizeof cd)) { + fprintf(stderr, "get configuration descriptor failed\n"); + p->udev_valid = false; + return false; + } + + strcpy(p->udev.path, "/sys/devices/pci0000:00/0000:00:01.2/usb1/1-1"); + strcpy(p->udev.busid, "1-1"); + p->udev.busnum = htonl(1); + p->udev.devnum = htonl(2); + p->udev.speed = htonl(2); + + p->udev.idVendor = htons(dd.idVendor); + p->udev.idProduct = htons(dd.idProduct); + p->udev.bcdDevice = htons(dd.bcdDevice); + + p->udev.bDeviceClass = dd.bDeviceClass; + p->udev.bDeviceSubClass = dd.bDeviceSubClass; + p->udev.bDeviceProtocol = dd.bDeviceProtocol; + p->udev.bConfigurationValue = cd.bConfigurationValue; + p->udev.bNumConfigurations = dd.bNumConfigurations; + p->udev.bNumInterfaces = cd.bNumInterfaces; + + p->udev_valid = true; + return true; +} + + +static void +vhci_usb_attach_hook( + struct avr_irq_t * irq, + uint32_t value, + void * param) +{ + struct usbip_t * p = param; + p->attached = !!value; + printf("avr attached: %u\n", p->attached); + + avr_ioctl(p->avr, AVR_IOCTL_USB_VBUS, (void*) 1); + + (void)irq; +} + +static int sock_read_exact( + int sockfd, + void * buf, + size_t n) +{ + while (n != 0) { + ssize_t nb = recv(sockfd, buf, n, 0); + if (nb == 0) { + fprintf(stderr, "disconnect\n"); + return 1; + } + if (nb < 0) { + perror("sock_read_exact"); + return -1; + } + n -= nb; + } + return 0; +} + +static int +open_usbip_socket(void) +{ + struct sockaddr_in serv; + int listenfd; + + if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket error"); + exit (1); + }; + + int reuse = 1; + if (setsockopt( + listenfd, + SOL_SOCKET, + SO_REUSEADDR, + (const char*)&reuse, + sizeof(reuse)) < 0) + perror("setsockopt(SO_REUSEADDR) failed"); + + memset(&serv, 0, sizeof serv); + serv.sin_family = AF_INET; + serv.sin_addr.s_addr = htonl(INADDR_ANY); + serv.sin_port = htons(USBIP_PORT_NUM); + + if (bind(listenfd, (struct sockaddr *)&serv, sizeof serv) < 0) { + perror("bind error"); + exit (1); + } + + if (listen(listenfd, SOMAXCONN) < 0) { + perror("listen error"); + exit (1); + } + + return listenfd; +} + + +#define sock_send(sockfd, dta, dta_sz) if(send(sockfd, dta, dta_sz, 0) != dta_sz) { perror("sock send"); break; } +static void +handle_usbip_req_devlist( + int sockfd, + struct usbip_t * p) +{ + struct usbip_op_common op_common = { + htons(USBIP_PROTO_VERSION), + htons(USBIP_OP_REPLY | USBIP_OP_DEVLIST), + htonl(USBIP_ST_NA) + }; + struct usbip_op_devlist_reply devlist = {htonl(1)}; + + + avr_ioctl(p->avr, AVR_IOCTL_USB_RESET, NULL); + usleep(2500); + + load_device_and_config_descriptor(p); + + // get config AND interface descriptors + struct { + struct usb_configuration_descriptor config; + struct usb_interface_descriptor interf[p->udev.bNumInterfaces]; + } cd; + if (!get_descriptor(p, USB_DESCRIPTOR_CONFIGURATION, &cd, sizeof cd)) { + fprintf(stderr, "get configuration descriptor failed\n"); + if (send(sockfd, &op_common, sizeof op_common, 0) != sizeof op_common) + perror("sock send"); + return; + } + + ssize_t devinfo_sz = sizeof (struct usbip_usb_device) + + p->udev.bNumInterfaces * sizeof (struct usbip_usb_interface); + struct usbip_op_devlist_reply_extra * devinfo = malloc(devinfo_sz); + + devinfo->udev = p->udev; + + for (byte i=0; i < devinfo->udev.bNumInterfaces; i++) { + devinfo->uinf[i].bInterfaceClass = cd.interf[i].bInterfaceClass; + devinfo->uinf[i].bInterfaceSubClass = cd.interf[i].bInterfaceSubClass; + devinfo->uinf[i].bInterfaceProtocol = cd.interf[i].bInterfaceProtocol; + devinfo->uinf[i].padding = 0; + } + + op_common.status = htonl(USBIP_ST_OK); + + do { + sock_send(sockfd, &op_common, sizeof op_common) + sock_send(sockfd, &devlist, sizeof devlist) + sock_send(sockfd, devinfo, devinfo_sz) + } while (0); + + free(devinfo); +} + +static int +handle_usbip_detached_state( + int sockfd, + struct usbip_t * p) +{ + struct usbip_op_common op_common; + if (sock_read_exact(sockfd, &op_common, sizeof op_common)) + return -1; + unsigned version = ntohs(op_common.version); + unsigned op_code = ntohs(op_common.code); + + if (version != USBIP_PROTO_VERSION) { + fprintf(stderr, "Protocol version mismatch, request: %x, this: %x\n", + version, USBIP_PROTO_VERSION); + return -1; + } + printf("executing %u\n", op_code); + switch (op_code) { + case USBIP_OP_REQUEST | USBIP_OP_DEVLIST: + handle_usbip_req_devlist(sockfd, p); + break; + case USBIP_OP_REQUEST | USBIP_OP_IMPORT: { + struct usbip_op_import_request req; + if (recv(sockfd, &req, sizeof req, 0) != sizeof req) { + fprintf(stderr, "protocol vialation\n"); + return -1; + } + + avr_ioctl(p->avr, AVR_IOCTL_USB_RESET, NULL); + usleep(2500); + + + if (!load_device_and_config_descriptor(p)) { + printf("Failed load_Decice_And_config while attach\n"); + op_common.status = USBIP_ST_NA; + if (send(sockfd, &op_common, sizeof op_common, 0) != sizeof op_common) + perror("sock send"); + } else { + op_common.code = htons(USBIP_OP_REPLY | USBIP_OP_IMPORT), + op_common.status = USBIP_ST_OK; + struct usbip_op_import_reply reply = { p->udev }; + do { + sock_send(sockfd, &op_common, sizeof op_common) + sock_send(sockfd, &reply, sizeof reply) + } while(0); + } + printf("Attached to usbip client\n"); + return 1; + } + default: + fprintf(stderr, "Unknown usbip %s %x\n", + op_code & USBIP_OP_REQUEST ? "request" : "reply", + op_code & 0xff); + return -1; + } + return 0; +} + +static void +handle_usbip_connection( + int sockfd, + struct usbip_t * p) +{ + bool attached = false; + while (1) { + if (attached) { + struct usbip_header cmd; + if (sock_read_exact(sockfd, &cmd, sizeof cmd.hdr)) + return; + + byte ep = ntohl(cmd.hdr.ep); + int cmdnum = ntohl(cmd.hdr.command); + int direction = ntohl(cmd.hdr.direction); + + switch (cmdnum) { + case USBIP_CMD_SUBMIT: { + if (sock_read_exact(sockfd, &cmd.u.submit, sizeof cmd.u.submit)) + return; + ssize_t bl = ntohl(cmd.u.submit.transfer_buffer_length); + byte buf[bl]; + + if (ep == 0) { + struct avr_io_usb pkt = { ep, sizeof cmd.u.submit.setup, cmd.u.submit.setup }; + if (avr_ioctl(p->avr, AVR_IOCTL_USB_SETUP, &pkt)) { + printf("FATAL: SETUP packet failed!\n"); + } + } + + if (direction == USBIP_DIR_IN) { + if (bl) { + bl = avr_usb_read(p, ep, buf, bl); + if (ep==4 && bl < 0) bl = 0; //teensy & linux hack? + } + if (ep == 0) + avr_usb_write(p, ep, NULL, 0); + } else { + if (bl && sock_read_exact(sockfd, buf, bl)) + return; + if (bl) + bl = avr_usb_write(p, ep, buf, bl); + if (ep == 0) + avr_usb_read(p, ep, NULL, 0); + } + + + struct usbip_header ret; + memset(&ret, 0, sizeof ret); + ret.hdr.command = htonl(USBIP_RET_SUBMIT); + ret.hdr.seqnum = cmd.hdr.seqnum; + ret.u.retsubmit.status = htonl(bl < 0 ? USBIP_ST_NA : USBIP_ST_OK); + ret.u.retsubmit.actual_length = htonl(bl < 0 ? 0 : bl); + ret.u.retsubmit.start_frame = 0; + ret.u.retsubmit.number_of_packets = 0; + ret.u.retsubmit.error_count = 0; + memcpy(&ret.u.retsubmit.setup, cmd.u.submit.setup, 8); + +// printf("return %zd bytes\n", bl); + if (send(sockfd, &ret, sizeof ret.hdr + sizeof ret.u.retsubmit, 0) != sizeof ret.hdr + sizeof ret.u.retsubmit) + perror("sock send"); + if (bl>0 && send(sockfd, buf, bl, 0) != bl) + perror("sock send"); + +// printf("done\n"); + + + break; + } + case USBIP_CMD_UNLINK: + if (recv(sockfd, &cmd.u.unlink, sizeof cmd.u.unlink, 0) != sizeof cmd.u.unlink) { + perror("sock_recv"); + return; + } + break; + default: + fprintf(stderr, "protocol vialation, unknown command %x\n", ntohl(cmd.hdr.command)); + + } + + } else { + switch (handle_usbip_detached_state(sockfd, p)) { + case -1: return; + case 1: + attached = true; + default: + break; + } + } + } +} + +void * +usbip_main( + struct usbip_t * p) +{ + int listenfd = open_usbip_socket(); + struct sockaddr_in cli; + socklen_t clilen = sizeof(cli); + + while (1) { + int sockfd = accept(listenfd, (struct sockaddr *)&cli, &clilen); + + if ( sockfd < 0) { + printf ("accept error : %s \n", strerror (errno)); + exit (1); + } + fprintf(stderr, "Connection address:%s\n",inet_ntoa(cli.sin_addr)); + handle_usbip_connection(sockfd, p); + close(sockfd); + } + +(void)p; + return NULL; +} + + +struct usbip_t * +usbip_create( + struct avr_t * avr) +{ + struct usbip_t * p = malloc(sizeof *p); + memset(p, 0, sizeof *p); + p->avr = avr; + + avr_irq_t * t = avr_io_getirq(p->avr, AVR_IOCTL_USB_GETIRQ(), USB_IRQ_ATTACH); + avr_irq_register_notify(t, vhci_usb_attach_hook, p); + + return p; +} + +void +usbip_destroy( + void * p) +{ + free(p); +} +#undef sock_send +// pragma: LCOV_EXCL_STOP diff --git a/parts/components/usbip.h b/parts/components/usbip.h new file mode 100644 index 00000000..ea25caed --- /dev/null +++ b/parts/components/usbip.h @@ -0,0 +1,35 @@ +/* + usbip.h + + Copyright 2017 Torbjorn Tyridal + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . +*/ + + +struct usbip_t; + +struct usbip_t * +usbip_create( + struct avr_t * avr); + +void +usbip_destroy( + struct usbip_t *); + +void * +usbip_main( + void * /* struct usbip_t * */); diff --git a/parts/components/usbip_types.h b/parts/components/usbip_types.h new file mode 100644 index 00000000..a004a413 --- /dev/null +++ b/parts/components/usbip_types.h @@ -0,0 +1,172 @@ +/* vim: set sts=4:sw=4:ts=4:noexpandtab + usbip_types.h + + Copyright 2017 Torbjorn Tyridal + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + +*/ + +//ref https://github.com/torvalds/linux/blob/master/tools/usb/usbip +//ref https://github.com/torvalds/linux/blob/master/drivers/usb/usbip + +#define USBIP_SYSFS_PATH_MAX 256 +#define USBIP_SYSFS_BUS_ID_SIZE 32 + +struct usbip_usb_interface { + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t padding; /* alignment */ +} __attribute__((packed)); + +struct usbip_usb_device { + char path[USBIP_SYSFS_PATH_MAX]; + char busid[USBIP_SYSFS_BUS_ID_SIZE]; + + uint32_t busnum; + uint32_t devnum; + uint32_t speed; + + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bConfigurationValue; + uint8_t bNumConfigurations; + uint8_t bNumInterfaces; +} __attribute__((packed)); + + +#define USBIP_PROTO_VERSION 0x111 +struct usbip_op_common { + uint16_t version; + +#define USBIP_OP_REQUEST (0x80 << 8) +#define USBIP_OP_REPLY (0x00 << 8) + uint16_t code; + +#define USBIP_ST_OK 0x00 +#define USBIP_ST_NA 0x01 + uint32_t status; + +} __attribute__((packed)); + +#define USBIP_OP_DEVLIST 0x05 + +struct usbip_op_devlist_request { +} __attribute__((packed)); + +struct usbip_op_devlist_reply { + uint32_t ndev; + /* followed by reply_extra[] */ +} __attribute__((packed)); + +struct usbip_op_devlist_reply_extra { + struct usbip_usb_device udev; + struct usbip_usb_interface uinf[]; +} __attribute__((packed)); + + +#define USBIP_OP_IMPORT 0x03 +struct usbip_op_import_request { + char busid[USBIP_SYSFS_BUS_ID_SIZE]; +} __attribute__((packed)); + +struct usbip_op_import_reply { + struct usbip_usb_device udev; +// struct usbip_usb_interface uinf[]; +} __attribute__((packed)); + +struct usbip_common_hdr { + uint32_t command; + uint32_t seqnum; + uint32_t devid; // (busnum << 16) | devnum + uint32_t direction; + uint32_t ep; +} __attribute__ ((__packed__)); + +#define USBIP_CMD_SUBMIT 0x0001 +#define USBIP_CMD_UNLINK 0x0002 +#define USBIP_RET_SUBMIT 0x0003 +#define USBIP_RET_UNLINK 0x0004 +#define USBIP_DIR_OUT 0x00 +#define USBIP_DIR_IN 0x01 + + +struct usbip_cmd_submit { + uint32_t transfer_flags; + int32_t transfer_buffer_length; + int32_t start_frame; + int32_t number_of_packets; + int32_t interval; + unsigned char setup[8]; +} __attribute__ ((__packed__)); + +/* ++ Allowed transfer_flags | value | control | interrupt | bulk | isochronous ++ -------------------------+------------+---------+-----------+----------+------------- ++ URB_SHORT_NOT_OK | 0x00000001 | only in | only in | only in | no ++ URB_ISO_ASAP | 0x00000002 | no | no | no | yes ++ URB_NO_TRANSFER_DMA_MAP | 0x00000004 | yes | yes | yes | yes ++ URB_NO_FSBR | 0x00000020 | yes | no | no | no ++ URB_ZERO_PACKET | 0x00000040 | no | no | only out | no ++ URB_NO_INTERRUPT | 0x00000080 | yes | yes | yes | yes ++ URB_FREE_BUFFER | 0x00000100 | yes | yes | yes | yes ++ URB_DIR_MASK | 0x00000200 | yes | yes | yes | yes +*/ + +struct usbip_ret_submit { + int32_t status; + int32_t actual_length; + int32_t start_frame; + int32_t number_of_packets; + int32_t error_count; + long long setup; +} __attribute__ ((__packed__)); + + +struct usbip_cmd_unlink { + int32_t seqnum_urb; + int32_t pad1; + int32_t pad2; + int32_t pad3; + int32_t pad4; + long long pad5; +} __attribute__ ((__packed__)); + + +struct usbip_ret_unlink { + int32_t status; + int32_t pad1; + int32_t pad2; + int32_t pad3; + int32_t pad4; + long long pad5; +} __attribute__ ((__packed__)); + +struct usbip_header { + struct usbip_common_hdr hdr; + union { + struct usbip_cmd_submit submit; + struct usbip_ret_submit retsubmit; + struct usbip_cmd_unlink unlink; + struct usbip_ret_unlink retunlink; + } u; +} __attribute__ ((__packed__)); diff --git a/parts/pinspecs/PinSpec_2560.h b/parts/pinspecs/PinSpec_2560.h index 67071a1d..1f14c303 100755 --- a/parts/pinspecs/PinSpec_2560.h +++ b/parts/pinspecs/PinSpec_2560.h @@ -23,8 +23,8 @@ #pragma once -#include "PinSpec.h" #include "Config.h" +#include "PinSpec.h" #include "PinSpec_Helper.h" class PinSpec_2560 : public PinSpec @@ -32,9 +32,9 @@ class PinSpec_2560 : public PinSpec public: - PinSpec_2560():PinSpec(DPin2Port,DPin2Mask,DPin2Timer,"atmega2560"){}; + PinSpec_2560():PinSpec(DPin2Port,DPin2Mask,DPin2Timer,"atmega2560") {}; - std::string GetMCUName() const { return Config::Get().GetDebugCore()?"atmega404":m_strMCU; }; + std::string GetMCUName() const override { return Config::Get().GetDebugCore()?"atmega404":m_strMCU; }; private: diff --git a/parts/pinspecs/PinSpec_32u4.h b/parts/pinspecs/PinSpec_32u4.h index 01a70695..789eba19 100644 --- a/parts/pinspecs/PinSpec_32u4.h +++ b/parts/pinspecs/PinSpec_32u4.h @@ -33,7 +33,7 @@ class PinSpec_32u4 : public PinSpec PinSpec_32u4():PinSpec(DPin2Port,DPin2Mask,DPin2Timer,"atmega32u4"){}; private: - const unsigned char DPin2Timer[31] = { + const unsigned char DPin2Timer[32] = { // TIMERS // ------------------------------------------- NOT_ON_TIMER, @@ -69,11 +69,12 @@ class PinSpec_32u4 : public PinSpec NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, - NOT_ON_TIMER + NOT_ON_TIMER, + NOT_ON_TIMER, }; - const unsigned char DPin2Mask[31] = { + const unsigned char DPin2Mask[32] = { // PIN IN PORT // ------------------------------------------- _BV(2), // D0 - PD2 @@ -111,9 +112,10 @@ class PinSpec_32u4 : public PinSpec _BV(6), // D28 / D10 - A10 - PB6 _BV(6), // D29 / D12 - A11 - PD6 _BV(5), // D30 / TX Led - PD5 + _BV(2), // D31, HWB }; - const unsigned char DPin2Port[31] = { + const unsigned char DPin2Port[32] = { // PORTLIST // ------------------------------------------- PD, // D0 - PD2 @@ -151,6 +153,8 @@ class PinSpec_32u4 : public PinSpec PB, // D28 / D10 - A10 - PB6 PD, // D29 / D12 - A11 - PD6 PD, // D30 / TX Led - PD5 + + PE, // D31, HWB }; }; diff --git a/parts/printers/IPCPrinter.cpp b/parts/printers/IPCPrinter.cpp index 75e6bb87..66ec25c3 100644 --- a/parts/printers/IPCPrinter.cpp +++ b/parts/printers/IPCPrinter.cpp @@ -52,6 +52,7 @@ static constexpr mqd_t MQ_ERR = -1; IPCPrinter::~IPCPrinter() { + m_pVis.release(); // Just to shut up clang-tidy if there are not defines. #if ENABLE_PIPE unlink(IPC_FILE); #elif ENABLE_MQ diff --git a/parts/printers/IPCPrinter.h b/parts/printers/IPCPrinter.h index d0a5ad35..0f0bd216 100644 --- a/parts/printers/IPCPrinter.h +++ b/parts/printers/IPCPrinter.h @@ -21,9 +21,9 @@ #pragma once #include "BasePeripheral.h" -#include "Printer.h" // for Printer, Printer::VisualType #include "IPCBoard.h" // for EinsyRambo #include "MK3SGL.h" +#include "Printer.h" // for Printer, Printer::VisualType #include // for array #include // for uint32_t #include // for unique_ptr @@ -101,7 +101,7 @@ class IPCPrinter : public Boards::IPCBoard, public Printer, public BasePeriphera std::vector m_vStepIRQs, m_vIndIRQs; - std::array m_vStepsPerMM = {100,100,400,280}; + std::array m_vStepsPerMM = {{100,100,400,280}}; }; diff --git a/parts/printers/IPCPrinter_MMU2.h b/parts/printers/IPCPrinter_MMU2.h index bb09f78a..33cc9f1f 100644 --- a/parts/printers/IPCPrinter_MMU2.h +++ b/parts/printers/IPCPrinter_MMU2.h @@ -20,8 +20,8 @@ #pragma once -#include "IPCPrinter.h" #include "GCodeSniffer.h" +#include "IPCPrinter.h" #include "MMU2.h" #include #include // for pair diff --git a/parts/printers/Prusa_CW1.h b/parts/printers/Prusa_CW1.h new file mode 100644 index 00000000..6d4729d2 --- /dev/null +++ b/parts/printers/Prusa_CW1.h @@ -0,0 +1,26 @@ +/* + Prusa_CW1.h - Printer definition for the CW1 + Copyright 2021 VintagePC + This file is part of MK404. + MK404 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + MK404 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with MK404. If not, see . + */ + +#pragma once + +#include "Prusa_CW1S.h" + + +class Prusa_CW1 : public Prusa_CW1S +{ + public: + Prusa_CW1():Prusa_CW1S(){ SetIsCW1S(false); }; +}; diff --git a/parts/printers/Prusa_CW1S.cpp b/parts/printers/Prusa_CW1S.cpp new file mode 100644 index 00000000..65ba170e --- /dev/null +++ b/parts/printers/Prusa_CW1S.cpp @@ -0,0 +1,72 @@ +/* + Prusa_CW1S.cpp - Printer definition for the CW1S + Copyright 2021 VintagePC + This file is part of MK404. + MK404 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + MK404 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with MK404. If not, see . + */ + +#include "Prusa_CW1S.h" +#include "GLHelper.h" +#include // NOLINT must come before freeglut +#include // for GLUT_DOWN, GLUT_LEFT_BUTTON, GLUT_RIGHT... + + +std::pair Prusa_CW1S::GetWindowSize() +{ + return {125,50}; +} + + +void Prusa_CW1S::Draw() +{ + glScalef(50.F/35.F,4,1); + CW1S::Draw(); + m_gl.OnDraw(); +} + +void Prusa_CW1S::OnAVRCycle() +{ + int mouseBtn = m_mouseBtn; // copy atomic to local + if (mouseBtn) + { + switch (mouseBtn){ + case 1: + m_enc.MousePush(); + break; + case 2: + m_enc.Release(); + break; + case 3: + m_enc.Twist(RotaryEncoder::CCW_CLICK); + break; + case 4: + m_enc.Twist(RotaryEncoder::CW_CLICK); + break; + } + m_mouseBtn = 0; + } +} + +void Prusa_CW1S::OnMousePress(int button, int action, int, int) +{ + if (button == GLUT_LEFT_BUTTON || button == GLUT_RIGHT_BUTTON) { + if (action == GLUT_DOWN) { + m_mouseBtn = 1; + } else if (action == GLUT_UP) { + m_mouseBtn = 2; + } + } + if ((button==3 || button==4) && action == GLUT_DOWN) // wheel + { + m_mouseBtn = button; + } +} diff --git a/parts/printers/Prusa_CW1S.h b/parts/printers/Prusa_CW1S.h new file mode 100644 index 00000000..90725e4b --- /dev/null +++ b/parts/printers/Prusa_CW1S.h @@ -0,0 +1,42 @@ +/* + Prusa_CW1S.h - Printer definition for the CW1S + Copyright 2021 VintagePC + This file is part of MK404. + MK404 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + MK404 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with MK404. If not, see . + */ + +#pragma once + +#include "Printer.h" +#include "boards/CW1S.h" +#include +#include + +class Prusa_CW1S : public Printer, public Boards::CW1S +{ + public: + + std::pair GetWindowSize() override; + + void Draw() override; + + void OnMousePress(int button, int action, int x, int y) override; + + protected: + void OnAVRCycle() override; + + private: + std::atomic_int m_mouseBtn = {0}; + + + +}; diff --git a/parts/printers/Prusa_MMU2.cpp b/parts/printers/Prusa_MMU2.cpp index e8ed3345..22313c65 100644 --- a/parts/printers/Prusa_MMU2.cpp +++ b/parts/printers/Prusa_MMU2.cpp @@ -16,8 +16,8 @@ #include "Prusa_MMU2.h" #include "GLHelper.h" -#include "MMU2.h" #include "MK3SGL.h" +#include "MMU2.h" // void Prusa_MMU2::SetupHardware() // { @@ -35,12 +35,12 @@ std::pair Prusa_MMU2::GetWindowSize() void Prusa_MMU2::Draw() { glScalef(50.F/35.F,4,1); - float fY = (float)(glutGet(GLUT_WINDOW_HEIGHT)/4); + auto fY = static_cast(glutGet(GLUT_WINDOW_HEIGHT)/4); MM_Control_01::Draw(fY); m_gl.OnDraw(); } -void Prusa_MMU2::OnVisualTypeSet(const std::string &type) +void Prusa_MMU2::OnVisualTypeSet(const std::string& /*type*/ ) { // if (type=="lite") // { diff --git a/parts/printers/Prusa_MMU2.h b/parts/printers/Prusa_MMU2.h index 17f23ddb..de1c8234 100644 --- a/parts/printers/Prusa_MMU2.h +++ b/parts/printers/Prusa_MMU2.h @@ -16,9 +16,9 @@ #pragma once -#include "boards/MM_Control_01.h" #include "GCodeSniffer.h" #include "Printer.h" +#include "boards/MM_Control_01.h" #include class MK3SGL; diff --git a/parts/wiring/CW1S.h b/parts/wiring/CW1S.h new file mode 100644 index 00000000..1402b60f --- /dev/null +++ b/parts/wiring/CW1S.h @@ -0,0 +1,67 @@ +/* + CW1S.h - Wiring definition for the Prusa CW1S + Copyright 2021 VintagePC + + This file is part of MK404. + + MK404 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + MK404 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MK404. If not, see . + */ + +#pragma once + +#include "PinSpec_32u4.h" +#include "Wiring.h" + +namespace Wirings +{ + class CW1S : public Wiring + { + + public: + CW1S():Wiring(m_pSpec) + { + m_mPins = GetPinMap(); + }; + + protected: + std::map GetPinMap() + { + return { + { LCD_BL_PIN, 6}, + { LCD_PINS_D4, 10}, + { LCD_PINS_D5, 18}, + { LCD_PINS_D6, 31}, + { LCD_PINS_D7, 19}, + { LCD_PINS_ENABLE, 4}, + { LCD_PINS_RS, 12}, + { BEEPER, 9}, + { BTN_EN1, 20}, + { BTN_EN2, 21}, + { BTN_ENC, 0}, + { X_STEP_PIN, 5}, + { X_TMC2130_CS, 7}, + { MCP_CSEL, 8}, + { TACH_0 ,0}, + { TACH_1, 2}, + { TACH_2, 1}, + { FAN_PIN, 13}, + { FAN_1_PIN, 11}, + { LED_PIN, 3} + }; + }; + + private: + PinSpec_32u4 m_pSpec = PinSpec_32u4(); + }; +}; // namespace Wirings diff --git a/parts/wiring/Test_Wiring.h b/parts/wiring/Test_Wiring.h index 7e53686c..9482b235 100644 --- a/parts/wiring/Test_Wiring.h +++ b/parts/wiring/Test_Wiring.h @@ -75,7 +75,8 @@ namespace Wirings {E_MUX1_PIN, 77}, {X_SLP_PIN, 74}, {X_RST_PIN, 75}, - {X_MAX_PIN, 73} + {X_MAX_PIN, 73}, + {MCP_CSEL, 17} }; }; private: diff --git a/scripts/tests/snaps/ext1/CW1S_mousedn.png b/scripts/tests/snaps/ext1/CW1S_mousedn.png new file mode 100644 index 0000000000000000000000000000000000000000..ba15aee220efcf62017522bc23c9190c4f809bee GIT binary patch literal 3570 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 N4>vD(^^tQ|{{!l8FWCS9 literal 0 HcmV?d00001 diff --git a/scripts/tests/snaps/ext1/CW1S_mouseleft.png b/scripts/tests/snaps/ext1/CW1S_mouseleft.png new file mode 100644 index 0000000000000000000000000000000000000000..f0eb2d899161e5736d56af6bbef83afa748e3000 GIT binary patch literal 2537 zcmcgtdo@d zm`X!KW0VQQT#8yUm@rIc#z^98W|&z9-v+~v+B#>?*+2LE-ap>UdCvR1&-;8npXW(G z?%}-Zn+@OS>FKR*oBfL`b$ zy$HHoAe)haOfy_?{rA!C4!?qy5fFHNiW+T6*MOt(kO`NCgG9Za&M@F^(w@4uaTZ+Z zr4TEAgkr<{iWMyy{|RaS{G(W&HCD=GVC8bdP>|Jz}tbpL}l~xr#MISJb zNOnuzW~%sOG&?>5KJYrXw(vxvMXq49g8ckj@h(06#cPfjzHp)wfBk#_NxA8{qvI;5 zL#FiANm)c4wF3t^U}L%~yQYOl0|eUwqQdcRyrLT#sWs$DnxxS>2gp7PD_r%V^S1u- zqcw&`yW<2z{xk>d&FzkS=0u;k1Iq9~bQoW=6=YHQ;uzx3d(fhw;X=H6nx2^Bpc@{1 zcGU{m=@Xt6Ah*!^%&?$28bb9w_N2r+@p?@8HKrehJkW+?hUgirRq5#mU_`sRhwa#yTnP-XxssWzu7oUe9sV$KZR*(&FvUUPQ zrq14v!R~rGReO6s>TW8&i}2@R0dq)AsPdz9u%6Qp^hM7EK=qp}LaqLe*`b(~kJUb6 znI@Cen0)_jtzmpUqb*W>19Hq#4qF>HW#H7uLHL1}<}Qr0_$2&h5zdZ-)Jm;IC5>Z# zu5?t}-0QFvKPr>+`YZw{?Nfr~U~t=*>*&0UkGcrDSXz2#O|KTIw{iG5HgaN}eAqujy@IwoKD092({Ec@$U9$IUvCEAA9 zV6oFW&K+4H$B6^{(H-eaLQsWphKEpt3u9%XszPF>Jmu3u3q}sO)!FEFXQf+a;2e8` z6_`o!Bnjk$A=W$25=e;1qOP$YkbT^ndnhOuj?J{qWCTs;l{g0_5x+oMtEh69m$1m5 z$qsx4r;s*=Qo$6XSZVbsP3`cL)o{R;-WfjYord=ilovPpioM+ED0vJDXsT$u2l0wQ7VI&64I%b0CwMX1EGYf_5Dg z5E+D~i(UPN3LG_Ykc#9AV`CQ-No?_vbm8YKIQeQ+P9c8t1h?8hsw`q9M-+%!`U%!I z-qj(l_*PU~ETcWVu1X3-7B$*!xDOH2C!~8_TYZmB3d0l6Q8{ulp3fAQTSF!~A)#+m z<8mmWCx%5IW*HuLU#JvuU6{NMcq!cpiGlODp>=rm)y&cBtK(lM~E}zw1)ma1x_LJz4wRq#cvb80*Xb*=DCX> zJxNcIH9NNaqvjL2vlNm>z$giXWhP8F6g80Vf;e(_Xn323u*agiF~`QP7>cfh87_O4;GlLtGt@0D)v`%^7QB98!k9La(4Hky{=o(k0SffuIR3tTa{S-il~7-;S`?cki1gt`_iGO-R9Kix1Wx zAt&YE4%m?JA+84W59#ggiB7l+?ceR4^6kFWP)Ls2p@H}+w4K&x;J+JVHhi$5fM^`Q zzG+Eyd&zb!48K0AYNbCbjliqO%TiXuf@13}m&O3ghMc->9R|&=Tu7TD@0P-L>6`{( zN7%M@Pi)Lo{B%3W>(`|$YK!A{q3+q|Z23Q_O#t}5utv8_-Im6X@a5EjaowZJqDn1q zUDW17TRZYMh4S~G{qKRS5s7?Kt!XUc{T62rUAe#z&f;CT!!KXZm;8F526QF9niyH_ zuDQJCO?z%bPqJ7}_D9zMtuI@ECQ(I@#^I_n8wXhUfNj2e#CgWuzr#OxUb7gT3f7Kh z%w*r1*L#>s7e=CQWZdhQz1;`HX=Ixwyb7S5S!pxvXY9;9Z=FeJJuqr9%RjR-nbo?Y zBOSOW{v%QB6M8WXQooQrgkfNH OVV5HwhszHJUH%`*865rq literal 0 HcmV?d00001 diff --git a/scripts/tests/snaps/ext1/CW1S_mouseup.png b/scripts/tests/snaps/ext1/CW1S_mouseup.png new file mode 100644 index 0000000000000000000000000000000000000000..47c42877bed45741432be6da9fe4a068dfeb6b64 GIT binary patch literal 3595 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 GyY_E^JOMKR literal 0 HcmV?d00001 diff --git a/scripts/tests/snaps/ext1/CW1_lid.png b/scripts/tests/snaps/ext1/CW1_lid.png new file mode 100644 index 0000000000000000000000000000000000000000..097087c67b36b104a58e6701d2b1b2a387dcc113 GIT binary patch literal 2609 zcmcIme^k;}8^>B(d78FP!u$?RPqP-3qkw}zO>po+u8f)``$mEbMLwLKKFU<=ks~) z{bf&h(8sopwh##9%@dB&8L^>^oK$gtx{_dN-SxjvY;(~gY6)KZQPyOhdS>t@vt>EV@pN*7GP8K zghoDf|0@L&2o7ng0cabDa;y8lw`GVz`J1lRx^t_?`z%d;L?yvYX zyFe)4pAVWwl|9rHsO8drVi3^R_xB{#J%NVzU#xk?}(e9>*QAg*jM zf$itV^J?@Wz)@v`{v0y5l*y16aebAy5D}=e%xStR6;Q6(7vsqmPRXJQY!(Mw&$}yO zkfdfG3HSTLVlPULM7?NBx>O{PFu-vOQ+S*koxt`k;$Dr=Ql!KI#YkigzGKC$)M3H> zmC0*PoH*?p5KzYx$bfH@Vo|9aF9WQ!qD>gw8T1>m!2@g1M9ZXvUsXWpAVa58u*~iWc#fud+7Tlk$Ber zG}tj%W+zVt_Ml-#=J5f*Gz3F8;yX5SSj^ctDuV=Q7d+*fw-;PZhAddFgV>Zs<5^zU za>|bD_+aeh?Bww1GWBnL3EW3}+0pzwLg8#TGw!%nxUK^6)DvQ}B=c=n?+_07_Akih z2 zf$_I^rPd*fnb=P{E2LMmy^z{8{bls!NXc4;%5w5Zj&lfh_4Ji&aR`-#toF8xp{aSU*RWmGZElowZqP#ci1IaeG(rIU}w2u%wMAw7&xNCy=j9RKZn6o8d+>!Yua zwdDA`u29UxK3AC2E+91yXx7?2?-_fnJ(&(nMQL)fRU|5o#*bNddmyf=IMe zM^2nf3N6oN1Z2$+Epi9EfY~D|M{8n92P>p zO*V22l-ZI+mWaIY!ctSr#5z_@O%sS=43ejUs7KN=qJrO*L~Aj)v9ZBLCyb#-j4%e( z21MSp%?(J9wO&w9leW)LvNYrCE@Sq4^tkt!c8$0Flp)6UZlj$7Gg86vVwF(WazZE6 zVG123tr+=1UQ)@&Ns1m&*C^&Ik2JdF*ZcZho6xg4cZV7tudpxDr)FkOu))bMrUT}m zmf-FgGJKth4MCtZxaz|{esBpy8MzTt&4BLPi|;O6RObhV4pcN&N&L3$=)raNefG*G z#SwmUb_Z2;_9~sbM3H*P!Y=Wg(BoV}x7NIH#6`_E7@9s+S`Y} z-Kx7^Z7vvYPbh+sdMji7UNr2mGd7&2S05HRhn*kl)v67xV?DQzJXoIN zAO-RpJbX)-Jc04#F^8i;@{|+x!OrI@(;S44BKKSap2 zWJan7#lYEqiz}{yJRJtdJvMIeBF~Tp-hBPR4>$cQ!JpHmC36MS1PA51#b2(`0gc1n z%k(r}S7oQus?{g^9)BjchxU&8yjk-38l8DB-9m)tmChgaJwQxM%=Fypc`xaPy}f26 zD&^(rOBv$OFpSu_(GSYjpakCRvr{8TlE7O4%iQ(kXm}yz{)@!Pn&CO)ZCf)>t%ldt zS#7g@iLMt)NlA}q7BBksv3YsqaPxrQ1#y!d>s;dJn7e^4i*}4u9xy#i--tDXA?&(9 zwYS|*Qu^G6()OP;r+y=r=pzV)j9(IS7S%2fx=QznVg!op)33zICWX3Ja8BmKL&;z6 zLzF(@2{_Wq@(uIrh3T=b2^_afw3m3HL)17;JAGJG_%(P)bZrNQrq>{YsAs{~u^v60 zMNvgR3jm7yVbefL^~!PeS9en8tCuQRM4k@rt<+dSle{3hL#6)^Nx$h&uje^>tP{!{+} DsaG}1 literal 0 HcmV?d00001 diff --git a/scripts/tests/snaps/ext1/CW1_press.png b/scripts/tests/snaps/ext1/CW1_press.png new file mode 100644 index 0000000000000000000000000000000000000000..478852d3ffc5632b4be6afaffedbe2641f940a3d GIT binary patch literal 2589 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 bT|SJwbER>-F-~%#&pN;5UFG|kXl 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 Wp3GI=y4m|}A6%W?oobF +#include +#include +#include +#include +#include + +/* + * This demonstrate how to use the avr_mcu_section.h file + * The macro adds a section to the ELF file with useful + * information for the simulator + */ +#include "avr_mcu_section.h" +AVR_MCU(16000000, "atmega2560"); +// tell simavr to listen to commands written in this (unused) register +// AVR_MCU_SIMAVR_COMMAND(&GPIOR0); +// AVR_MCU_SIMAVR_CONSOLE(&GPIOR1); + +/* + * This small section tells simavr to generate a VCD trace dump with changes to these + * registers. + * Opening it with gtkwave will show you the data being pumped out into the data register + * UDR0, and the UDRE0 bit being set, then cleared + */ +// const struct avr_mmcu_vcd_trace_t _mytrace[] _MMCU_ = { +// { AVR_MCU_VCD_SYMBOL("UDR3"), .what = (void*)&UDR3, }, +// { AVR_MCU_VCD_SYMBOL("UDRE3"), .mask = (1 << UDRE3), .what = (void*)&UCSR3A, }, +// { AVR_MCU_VCD_SYMBOL("GPIOR1"), .what = (void*)&GPIOR1, }, +// }; +// #ifdef USART3_RX_vect_num // stupid ubuntu has antique avr-libc +// AVR_MCU_VCD_IRQ(USART3_RX); // single bit trace +// #endif +// AVR_MCU_VCD_ALL_IRQ(); // also show ALL irqs running + +#define PIN(x,y) PORT##x>>y & 1U + +volatile uint8_t done = 0; + +static int uart_putchar(char c, FILE *stream) +{ + loop_until_bit_is_set(UCSR0A, UDRE0); + UDR0 = c; + return 0; +} +static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, + _FDEV_SETUP_WRITE); + + +int main() +{ + stdout = &mystdout; + sei(); + PORTF=0xFF; + DDRF=0x00; + PORTH = 0xFF; + DDRH = 0x00; + + ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescalar to 128 - 125KHz sample rate @ 16MHz + + ADMUX |= (1 << REFS0); // Set ADC reference to AVCC + ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit reading + + // No MUX values needed to be changed to use ADC0 + ADMUX |= 4; //ADC4 + + ADCSRA |= (1 << ADATE); // Set ADC to Free-Running Mode + + ADCSRA |= (1 << ADEN); // Enable ADC + ADCSRA |= (1 << ADSC); // Start A2D Conversions + + DIDR0 = 0b11111110; + + DDRJ = 0b01100000; + + printf("READY\n"); + + volatile uint8_t val = 0; + uint8_t muxvals[] = {0x00,0x20,0x40,0x60,0x00,0x60,0x20,0x40,0x00}; + int i=0; + + while(i<8) + { + volatile uint8_t newVal = ADCH; + if (newVal!=val) + { + printf("ADC %02x CH %02x\n",newVal, muxvals[i]>>5); + val = newVal; + i++; + PORTJ = muxvals[i]; + } + } + + + cli(); + + printf("FINISHED\n"); + + // this quits the simulator, since interupts are off + // this is a "feature" that allows running tests cases and exit + sleep_cpu(); +} diff --git a/scripts/tests/test_74HCT4052.txt b/scripts/tests/test_74HCT4052.txt new file mode 100644 index 00000000..4b43a455 --- /dev/null +++ b/scripts/tests/test_74HCT4052.txt @@ -0,0 +1,60 @@ +# This script is a component test script for use with the test firmware and printer. +ScriptHost::SetTimeoutMs(1000) +ScriptHost::SetQuitOnTimeout(1) +TelHost::IsEqual(74HCT4052_ +#include +#include +#include +#include +#include + +/* + * This demonstrate how to use the avr_mcu_section.h file + * The macro adds a section to the ELF file with useful + * information for the simulator + */ +#include "avr_mcu_section.h" +AVR_MCU(16000000, "atmega2560"); +// tell simavr to listen to commands written in this (unused) register +// AVR_MCU_SIMAVR_COMMAND(&GPIOR0); +// AVR_MCU_SIMAVR_CONSOLE(&GPIOR1); + +/* + * This small section tells simavr to generate a VCD trace dump with changes to these + * registers. + * Opening it with gtkwave will show you the data being pumped out into the data register + * UDR0, and the UDRE0 bit being set, then cleared + */ +// const struct avr_mmcu_vcd_trace_t _mytrace[] _MMCU_ = { +// { AVR_MCU_VCD_SYMBOL("UDR3"), .what = (void*)&UDR3, }, +// { AVR_MCU_VCD_SYMBOL("UDRE3"), .mask = (1 << UDRE3), .what = (void*)&UCSR3A, }, +// { AVR_MCU_VCD_SYMBOL("GPIOR1"), .what = (void*)&GPIOR1, }, +// }; +// #ifdef USART3_RX_vect_num // stupid ubuntu has antique avr-libc +// AVR_MCU_VCD_IRQ(USART3_RX); // single bit trace +// #endif +// AVR_MCU_VCD_ALL_IRQ(); // also show ALL irqs running + +#define PIN(x,y) PORT##x>>y & 1U + +volatile uint8_t done = 0; + +static int uart_putchar(char c, FILE *stream) +{ + loop_until_bit_is_set(UCSR0A, UDRE0); + UDR0 = c; + return 0; +} +static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, + _FDEV_SETUP_WRITE); + +uint8_t SPI_TX(uint8_t cData){ + + SPDR = cData; + while(!(SPSR & (1< fExtrEnd = { + const std::array fExtrEnd = {{ static_cast(m_uiExtrEnd[0])/static_cast(m_iStepsPerMM[0]*1000), static_cast(m_uiExtrEnd[1])/static_cast(m_iStepsPerMM[2]*1000), static_cast(m_uiExtrEnd[2])/static_cast(m_iStepsPerMM[1]*1000), - }; + }}; const std::array vfPos = {{ static_cast(m_uiX)/static_cast(m_iStepsPerMM[0]*1000), @@ -182,7 +182,7 @@ void GLPrint::OnEStep(const uint32_t& value, const uint32_t& /*deltaT*/) { //printf("New extrusion %u at index %u\n",m_ivStart.size(),m_ivStart.back()); // Add a temporary normal vertex - std::array fCross = {0,0,0}, fA = {0,0,0}, fB = {0,-1,0}; + std::array fCross = {{0,0,0}}, fA = {{0,0,0}}, fB = {{0,-1,0}}; std::transform(vfPos.begin(), vfPos.end(), fExtrEnd.data(), fA.data(), std::minus()); CrossProduct(fA,fB,{fCross.data(),3}); Normalize({fCross.data(),3}); @@ -225,7 +225,7 @@ void GLPrint::OnEStep(const uint32_t& value, const uint32_t& /*deltaT*/) else if (!bColinear) { // First, update the previous normal with the new vertex info. - std::array fCross = {0,0,0}, fA = {0,0,0} ,fB = {0,-0.002,0}; + std::array fCross = {{0,0,0}}, fA = {{0,0,0}} ,fB = {{0,-0.002,0}}; auto itPrev = m_fvNorms.end()-3; std::transform(itPrev, itPrev+3, vfPos.data(), fA.data(), std::minus()); // Length from p->curr CrossProduct(fA,fB,{fCross.data(),3}); @@ -278,7 +278,7 @@ void GLPrint::AddSegment() const float fLayerZRad = m_fZHt/2; //0.5*layer height. TODO (vintagepc): Sort this out based on guessed z height. //std::cout << "Adding segment from: " << extPrev[0] << " " << fZ << " " << fY << " to " << m_fExtrEnd[0] << " " << m_fExtrEnd[1] << " " << m_fExtrEnd[2] << '\n'; - std::array fCross = {0,0,0}, fA = {0,0,0} ,fB = {0,-2,0}; + std::array fCross = {{0,0,0}}, fA = {{0,0,0}} ,fB = {{0,-2,0}}; auto pStart = m_vPath.begin(); bool bIsSkipping = false; @@ -418,11 +418,11 @@ void GLPrint::AddSegment() void GLPrint::Draw() { - const std::array fColor = {m_fColR,m_fColG,m_fColB,1}; + const std::array fColor = {{m_fColR,m_fColG,m_fColB,1}}; //std::vector fG[4] = {0,0.5,0,1}; - static const std::array fY = {1,1,0,1}; + static const std::array fY = {{1,1,0,1}}; //static const std::array fK = {0,0,0,1}; - static const std::array fSpec = {1,1,1,1}; + static const std::array fSpec = {{1,1,1,1}}; glLineWidth(1.0); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,fSpec.data()); diff --git a/utility/MK2_Full.h b/utility/MK2_Full.h index 9c0bbe26..f6c729e8 100644 --- a/utility/MK2_Full.h +++ b/utility/MK2_Full.h @@ -21,8 +21,8 @@ #pragma once -#include "OBJCollection.h" #include "GLObj.h" +#include "OBJCollection.h" #include "gsl-lite.hpp" #include #include diff --git a/utility/MK3SGL.h b/utility/MK3SGL.h index c3e298c4..53c03b3a 100644 --- a/utility/MK3SGL.h +++ b/utility/MK3SGL.h @@ -29,8 +29,8 @@ #include "IScriptable.h" // for IScriptable::LineStatus #include "Scriptable.h" // for Scriptable #include "sim_avr.h" // for avr_t -#include "sim_irq.h" // for avr_irq_t #include "sim_avr_types.h" +#include "sim_irq.h" // for avr_irq_t #include // NOLINT for glTranslatef #include // #include // for GLPrint