diff --git a/AntennaTracker/ReleaseNotes.txt b/AntennaTracker/ReleaseNotes.txt index 9d463c5ca5e6f1..a94ebaed91b4ec 100644 --- a/AntennaTracker/ReleaseNotes.txt +++ b/AntennaTracker/ReleaseNotes.txt @@ -1,5 +1,9 @@ Antenna Tracker Release Notes: ------------------------------ +Release 4.5.2 14th May 2024 + +No changes from 4.5.2-beta1 +------------------------------------------------------------------ Release 4.5.2-beta1 29th April 2024 Changes from 4.5.1 diff --git a/ArduCopter/ReleaseNotes.txt b/ArduCopter/ReleaseNotes.txt index 18c838e4a6e88f..6d4c77c8548e57 100644 --- a/ArduCopter/ReleaseNotes.txt +++ b/ArduCopter/ReleaseNotes.txt @@ -1,5 +1,9 @@ ArduPilot Copter Release Notes: ------------------------------- +Release 4.5.2 14th May 2024 + +No changes from 4.5.2-beta1 +------------------------------------------------------------------ Release 4.5.2-beta1 29th April 2024 Changes from 4.5.1 diff --git a/ArduPlane/ReleaseNotes.txt b/ArduPlane/ReleaseNotes.txt index 477554dafd41fd..360fe2d4a80f16 100644 --- a/ArduPlane/ReleaseNotes.txt +++ b/ArduPlane/ReleaseNotes.txt @@ -1,5 +1,9 @@ ArduPilot Plane Release Notes: ------------------------------ +Release 4.5.2 14th May 2024 + +No changes from 4.5.2-beta1 +------------------------------------------------------------------ Release 4.5.2-beta1 29th April 2024 Changes from 4.5.1 diff --git a/ArduPlane/quadplane.cpp b/ArduPlane/quadplane.cpp index 2809694fce8dd4..7217486133bbe5 100644 --- a/ArduPlane/quadplane.cpp +++ b/ArduPlane/quadplane.cpp @@ -310,7 +310,7 @@ const AP_Param::GroupInfo QuadPlane::var_info2[] = { // @Param: TRIM_PITCH // @DisplayName: Quadplane AHRS trim pitch - // @Description: This sets the compensation for the pitch angle trim difference between calibrated AHRS level and vertical flight pitch. NOTE! this is relative to calibrated AHRS trim, not forward flight trim which includes TRIM_PITCH. For tailsitters, this is relative to a baseline of 90 degrees in AHRS. + // @Description: This sets the compensation for the pitch angle trim difference between calibrated AHRS level and vertical flight pitch. NOTE! this is relative to calibrated AHRS trim, not forward flight trim which includes PTCH_TRIM_DEG. For tailsitters, this is relative to a baseline of 90 degrees in AHRS. // @Units: deg // @Range: -10 +10 // @Increment: 0.1 diff --git a/Rover/ReleaseNotes.txt b/Rover/ReleaseNotes.txt index f0d1680f2ad470..47b170ac933b97 100644 --- a/Rover/ReleaseNotes.txt +++ b/Rover/ReleaseNotes.txt @@ -1,5 +1,9 @@ Rover Release Notes: -------------------- +Release 4.5.2 14th May 2024 + +No changes from 4.5.2-beta1 +------------------------------------------------------------------ Release 4.5.2-beta1 29th April 2024 Changes from 4.5.1 diff --git a/Rover/Steering.cpp b/Rover/Steering.cpp index 5253c2dfbebb61..5724c46976b9c6 100644 --- a/Rover/Steering.cpp +++ b/Rover/Steering.cpp @@ -10,10 +10,8 @@ void Rover::set_servos(void) motor_test_output(); } else { // get ground speed - float speed; - if (!g2.attitude_control.get_forward_speed(speed)) { - speed = 0.0f; - } + float speed = 0.0f; + g2.attitude_control.get_forward_speed(speed); g2.motors.output(arming.is_armed(), speed, G_Dt); } diff --git a/Tools/AP_Bootloader/board_types.txt b/Tools/AP_Bootloader/board_types.txt index 124e933c1b625b..7b2fe285cc6aa5 100644 --- a/Tools/AP_Bootloader/board_types.txt +++ b/Tools/AP_Bootloader/board_types.txt @@ -274,6 +274,7 @@ AP_HW_BlitzH7Pro 1162 AP_HW_BlitzF7Mini 1163 AP_HW_BlitzF7 1164 AP_HW_MicoAir743 1166 +AP_HW_BlitzH7Wing 1168 AP_HW_JHEMCUF405WING 1169 AP_HW_MatekG474 1170 @@ -299,6 +300,8 @@ AP_HW_JHEMCU-H743HD 1411 AP_HW_LongbowF405 1422 +AP_HW_MountainEagleH743 1444 + AP_HW_SakuraRC-H743 2714 # IDs 5000-5099 reserved for Carbonix @@ -327,6 +330,9 @@ AP_HW_Holybro-UM982-G4 5402 AP_HW_Holybro-UM960-H7 5403 AP_HW_Holybro-PERIPH-H7 5404 +#IDs 5501-5599 reserved for MATEKSYS +AP_HW_MATEKH743SE 5501 + # IDs 6000-6099 reserved for SpektreWorks # IDs 6600-6699 reserved for Eagle Eye Drones diff --git a/Tools/ardupilotwaf/boards.py b/Tools/ardupilotwaf/boards.py index cdfdc0c90afa83..b25591523afafa 100644 --- a/Tools/ardupilotwaf/boards.py +++ b/Tools/ardupilotwaf/boards.py @@ -542,6 +542,14 @@ def embed_ROMFS_files(self, ctx): if not embed.create_embedded_h(header, ctx.env.ROMFS_FILES, ctx.env.ROMFS_UNCOMPRESSED): ctx.fatal("Failed to created ap_romfs_embedded.h") + ctx.env.CXXFLAGS += ['-DHAL_HAVE_AP_ROMFS_EMBEDDED_H'] + + # Allow lua to load from ROMFS if any lua files are added + for file in ctx.env.ROMFS_FILES: + if file[0].startswith("scripts") and file[0].endswith(".lua"): + ctx.env.CXXFLAGS += ['-DHAL_HAVE_AP_ROMFS_EMBEDDED_LUA'] + break + Board = BoardMeta('Board', Board.__bases__, dict(Board.__dict__)) def add_dynamic_boards_chibios(): @@ -777,14 +785,6 @@ def configure_env(self, cfg, env): if fnmatch.fnmatch(f, "*.lua"): env.ROMFS_FILES += [('scripts/'+f,'ROMFS/scripts/'+f)] - if len(env.ROMFS_FILES) > 0: - # Allow lua to load from ROMFS if any lua files are added - for file in env.ROMFS_FILES: - if file[0].startswith("scripts") and file[0].endswith(".lua"): - env.CXXFLAGS += ['-DHAL_HAVE_AP_ROMFS_EMBEDDED_LUA'] - break - env.CXXFLAGS += ['-DHAL_HAVE_AP_ROMFS_EMBEDDED_H'] - if cfg.options.sitl_rgbled: env.CXXFLAGS += ['-DWITH_SITL_RGBLED'] @@ -1357,13 +1357,6 @@ def configure_env(self, cfg, env): env.DEFINES.update( HAL_PARAM_DEFAULTS_PATH='"@ROMFS/defaults.parm"', ) - if len(env.ROMFS_FILES) > 0: - # Allow lua to load from ROMFS if any lua files are added - for file in env.ROMFS_FILES: - if file[0].startswith("scripts") and file[0].endswith(".lua"): - env.CXXFLAGS += ['-DHAL_HAVE_AP_ROMFS_EMBEDDED_LUA'] - break - env.CXXFLAGS += ['-DHAL_HAVE_AP_ROMFS_EMBEDDED_H'] def build(self, bld): super(linux, self).build(bld) diff --git a/Tools/autotest/rover.py b/Tools/autotest/rover.py index bab8ed9594d625..26304003fb01c8 100644 --- a/Tools/autotest/rover.py +++ b/Tools/autotest/rover.py @@ -2608,7 +2608,7 @@ def assert_receive_mission_ack(self, mission_type, raise NotAchievedException("Unexpected mission type %u want=%u" % (m.mission_type, mission_type)) if m.type != want_type: - raise NotAchievedException("Expected ack type got %u got %u" % + raise NotAchievedException("Expected ack type %u got %u" % (want_type, m.type)) def assert_filepath_content(self, filepath, want): @@ -6749,6 +6749,39 @@ def NetworkingWebServerPPP(self): shutil.copy('build/sitl/bin/ardurover.noppp', 'build/sitl/bin/ardurover') self.reboot_sitl() + def MissionRetransfer(self, target_system=1, target_component=1): + '''torture-test with MISSION_COUNT''' +# self.send_debug_trap() + self.mav.mav.mission_count_send( + target_system, + target_component, + 10, + mavutil.mavlink.MAV_MISSION_TYPE_FENCE + ) + self.assert_receive_mission_item_request(mavutil.mavlink.MAV_MISSION_TYPE_FENCE, 0) + self.context_push() + self.context_collect('STATUSTEXT') + self.mav.mav.mission_count_send( + target_system, + target_component, + 10000, + mavutil.mavlink.MAV_MISSION_TYPE_FENCE + ) + self.wait_statustext('Only [0-9]+ items are supported', regex=True, check_context=True) + self.context_pop() + self.assert_not_receive_message('MISSION_REQUEST') + self.mav.mav.mission_count_send( + target_system, + target_component, + 10, + mavutil.mavlink.MAV_MISSION_TYPE_FENCE + ) + self.assert_receive_mission_item_request(mavutil.mavlink.MAV_MISSION_TYPE_FENCE, 0) + self.assert_receive_mission_ack( + mavutil.mavlink.MAV_MISSION_TYPE_FENCE, + want_type=mavutil.mavlink.MAV_MISSION_OPERATION_CANCELLED, + ) + def tests(self): '''return list of all tests''' ret = super(AutoTestRover, self).tests() @@ -6836,6 +6869,7 @@ def tests(self): self.NetworkingWebServer, self.NetworkingWebServerPPP, self.RTL_SPEED, + self.MissionRetransfer, ]) return ret diff --git a/Tools/bootloaders/BlitzWingH743_bl.bin b/Tools/bootloaders/BlitzWingH743_bl.bin new file mode 100644 index 00000000000000..08a22a32f96584 Binary files /dev/null and b/Tools/bootloaders/BlitzWingH743_bl.bin differ diff --git a/Tools/bootloaders/BlitzWingH743_bl.hex b/Tools/bootloaders/BlitzWingH743_bl.hex new file mode 100644 index 00000000000000..275e235c6dda6b --- /dev/null +++ b/Tools/bootloaders/BlitzWingH743_bl.hex @@ -0,0 +1,1103 @@ +:020000040800F2 +:1000000000060020E1020008E3020008E302000805 +:10001000E3020008E3020008E3020008E30200082C +:10002000E3020008E3020008E30200086928000870 +:10003000E3020008E3020008E3020008E30200080C +:10004000E3020008E3020008E3020008E3020008FC +:10005000E3020008E3020008D53D0008013E000865 +:100060002D3E0008593E0008853E0008711000082A +:1000700099100008C5100008F11000081D110008B3 +:100080004511000871110008E3020008E3020008AE +:10009000E3020008E3020008E3020008B13E0008A2 +:1000A000E3020008E3020008E3020008E30200089C +:1000B000E3020008E3020008E3020008E30200088C +:1000C000E3020008E3020008E3020008E30200087C +:1000D000E3020008E3020008E3020008E30200086C +:1000E000153F0008E3020008E3020008E3020008ED +:1000F000E3020008E3020008E30200089D11000883 +:10010000E3020008E3020008893F0008E302000858 +:10011000E3020008E3020008E3020008E30200082B +:10012000C9110008F11100081D1200084912000849 +:1001300075120008E3020008E3020008E302000869 +:10014000E3020008E3020008E3020008E3020008FB +:100150009D120008C9120008F5120008E302000809 +:10016000E3020008E3020008E3020008E3020008DB +:10017000E302000855340008E3020008E302000827 +:10018000E3020008E3020008E3020008E3020008BB +:10019000E3020008E3020008E3020008E3020008AB +:1001A000E3020008E3020008E3020008E30200089B +:1001B000E3020008E3020008E3020008E30200088B +:1001C000E3020008E3020008E3020008E30200087B +:1001D000E302000841340008E3020008E3020008DB +:1001E000E3020008E3020008E3020008E30200085B +:1001F000E3020008E3020008E3020008E30200084B +:10020000E3020008E3020008E3020008E30200083A +:10021000E3020008E3020008E3020008E30200082A +:10022000E3020008E3020008E3020008E30200081A +:10023000E3020008E3020008E3020008E30200080A +:10024000E3020008E3020008E3020008E3020008FA +:10025000E3020008E3020008E3020008E3020008EA +:10026000E3020008E3020008E3020008E3020008DA +:10027000E3020008E3020008E3020008E3020008CA +:10028000E3020008E3020008E3020008E3020008BA +:10029000E3020008E3020008E3020008E3020008AA +:1002A000E3020008E3020008E3020008E30200089A +:1002B000E3020008E3020008E3020008E30200088A +:1002C000E3020008E3020008E3020008E30200087A +:1002D000E3020008E3020008E3020008E30200086A +:1002E00002E000F000F8FEE772B6374880F30888B5 +:1002F000364880F3098836483649086040F20000E5 +:10030000CCF200004EF63471CEF200010860BFF36B +:100310004F8FBFF36F8F40F20000C0F2F0004EF637 +:100320008851CEF200010860BFF34F8FBFF36F8F8B +:100330004FF00000E1EE100A4EF63C71CEF20001E3 +:100340000860062080F31488BFF36F8F02F0EEFA86 +:1003500003F0FCFA4FF055301F491B4A91423CBF55 +:1003600041F8040BFAE71D49184A91423CBF41F895 +:10037000040BFAE71A491B4A1B4B9A423EBF51F83D +:10038000040B42F8040BF8E700201849184A914280 +:100390003CBF41F8040BFAE702F006FB03F05AFBFE +:1003A000144C154DAC4203DA54F8041B8847F9E7A6 +:1003B00000F042F8114C124DAC4203DA54F8041B21 +:1003C0008847F9E702F0EEBA00060020002200207C +:1003D0000000000808ED00E00000002000060020FA +:1003E00068440008002200205C22002060220020D7 +:1003F000BC430020E0020008E0020008E002000820 +:10040000E00200082DE9F04F2DED108AC1F80CD064 +:10041000D0F80CD0BDEC108ABDE8F08F002383F338 +:1004200011882846A047002001F0A4FDFEE701F056 +:1004300033FD00DFFEE7000038B500F02FFC00F0D0 +:10044000ABFD02F0D1F9054602F004FA0446C0B94A +:100450000E4B9D4217D001339D4241F2883512BFA9 +:10046000044600250124002002F0C8F90CB100F078 +:1004700075F800F065FD284600F01EF900F06EF8F2 +:10048000F9E70025EFE70546EDE700BF010007B0FB +:1004900008B500F0D5FBA0F120035842584108BD33 +:1004A00007B541F21203022101A8ADF8043000F0B3 +:1004B000E5FB03B05DF804FB38B5302383F3118806 +:1004C000174803680BB101F021FE0023154A4FF4D1 +:1004D0007A71134801F010FE002383F31188124C47 +:1004E000236813B12368013B2360636813B1636819 +:1004F000013B63600D4D2B7833B963687BB90220F3 +:1005000000F088FC322363602B78032B07D16368EB +:100510002BB9022000F07EFC4FF47A73636038BD83 +:1005200060220020B90400088023002078220020E7 +:10053000084B187003280CD8DFE800F00805020803 +:10054000022000F05DBC022000F050BC024B0022F3 +:100550005A6070477822002080230020F8B5504B65 +:10056000504A1C461968013100F0998004339342C7 +:10057000F8D162684C4B9A4240F291804B4B9B6899 +:1005800003F1006303F5C0239A4280F088800020C5 +:1005900000F09EFB0220FFF7CBFF454B0021D3F874 +:1005A000E820C3F8E810D3F81021C3F81011D3F8ED +:1005B0001021D3F8EC20C3F8EC10D3F81421C3F8C1 +:1005C0001411D3F81421D3F8F020C3F8F010D3F8A5 +:1005D0001821C3F81811D3F81821D3F8802042F05D +:1005E0000062C3F88020D3F8802022F00062C3F8B4 +:1005F0008020D3F88020D3F8802042F00072C3F826 +:100600008020D3F8802022F00072C3F88020D3F835 +:10061000803072B64FF0E023C3F8084DD4E90004EF +:10062000BFF34F8FBFF36F8F224AC2F88410BFF31E +:100630004F8F536923F480335361BFF34F8FD2F848 +:10064000803043F6E076C3F3C905C3F34E335B0154 +:1006500003EA060C29464CEA81770139C2F8747224 +:10066000F9D2203B13F1200FF2D1BFF34F8FBFF32C +:100670006F8FBFF34F8FBFF36F8F536923F4003336 +:1006800053610023C2F85032BFF34F8FBFF36F8F17 +:10069000302383F31188854680F308882047F8BD0E +:1006A0000000060820000608FFFF050800220020C1 +:1006B0000044025800ED00E02DE9F04F93B0B44B38 +:1006C0002022FF2100900AA89D6800F0E3FBB14AB8 +:1006D0001378A3B90121B04811700360302383F36C +:1006E000118803680BB101F011FD0023AB4A4FF4F0 +:1006F0007A71A94801F000FD002383F31188009B63 +:1007000013B1A74B009A1A60A64A1378032B03D0A3 +:1007100000231370A24A53604FF0000A009CD34696 +:100720005646D146012000F06BFB24B19C4B1B6860 +:10073000002B00F02682002000F082FA0390039B39 +:10074000002BF2DB012000F051FB039B213B1F2B10 +:10075000E8D801A252F823F0D907000801080008E0 +:100760009508000825070008250700082507000848 +:1007700027090008F70A0008110A0008730A000890 +:100780009B0A0008C10A000825070008D30A0008D0 +:1007900025070008450B0008790800082507000810 +:1007A000890B0008E50700087908000825070008FC +:1007B000730A000825070008250700082507000818 +:1007C0002507000825070008250700082507000859 +:1007D00025070008950800080220FFF759FE0028A9 +:1007E00040F0F981009B022105A8BAF1000F08BF73 +:1007F0001C4641F21233ADF8143000F03FFA91E795 +:100800004FF47A7000F01CFA071EEBDB0220FFF7B2 +:100810003FFE0028E6D0013F052F00F2DE81DFE831 +:1008200007F0030A0D1013360523042105A80593CC +:1008300000F024FA17E004215548F9E704215A484A +:10084000F6E704215948F3E74FF01C08404608F149 +:10085000040800F03FFA0421059005A800F00EFA04 +:10086000B8F12C0FF2D101204FF0000900FA07F780 +:1008700047EA0B0B5FFA8BFB00F058FB26B10BF03D +:100880000B030B2B08BF0024FFF70AFE4AE70421E5 +:100890004748CDE7002EA5D00BF00B030B2BA1D1C1 +:1008A0000220FFF7F5FD074600289BD00120002617 +:1008B00000F00EFA0220FFF73BFE1FFA86F84046D2 +:1008C00000F016FA0446B0B1039940460136A1F192 +:1008D00040025142514100F01BFA0028EDD1BA46C6 +:1008E000044641F21213022105A83E46ADF8143029 +:1008F00000F0C4F916E725460120FFF719FE244B46 +:100900009B68AB4207D9284600F0E4F9013040F07B +:1009100067810435F3E70025224BBA463E461D7039 +:100920001F4B5D60A8E7002E3FF45CAF0BF00B039C +:100930000B2B7FF457AF0220FFF7FAFD322000F0B7 +:100940007FF9B0F10008FFF64DAF18F003077FF410 +:1009500049AF0F4A08EB0503926893423FF642AF56 +:10096000B8F5807F3FF73EAF124BB845019323DDCA +:100970004FF47A7000F064F90390039A002AFFF6AE +:1009800031AF039A0137019B03F8012BEDE700BF5C +:10099000002200207C23002060220020B9040008EF +:1009A000802300207822002004220020082200203A +:1009B0000C2200207C220020C820FFF769FD07469A +:1009C00000283FF40FAF1F2D11D8C5F120020AAB4C +:1009D00025F0030084494245184428BF424601924D +:1009E00000F032FA019AFF217F4800F053FA4FEAF3 +:1009F000A803C8F387027C492846019300F052FA05 +:100A0000064600283FF46DAF019B05EB830533E7F5 +:100A10000220FFF73DFD00283FF4E4AE00F096F918 +:100A200000283FF4DFAE0027B846704B9B68BB42FE +:100A300018D91F2F11D80A9B01330ED027F00303BA +:100A400012AA134453F8203C05934046042205A9FA +:100A5000043700F0F7FA8046E7E7384600F03AF945 +:100A60000590F2E7CDF81480042105A800F006F9FE +:100A700002E70023642104A8049300F0F5F800289D +:100A80007FF4B0AE0220FFF703FD00283FF4AAAECA +:100A9000049800F051F90590E6E70023642104A8CA +:100AA000049300F0E1F800287FF49CAE0220FFF7E9 +:100AB000EFFC00283FF496AE049800F03FF9EAE717 +:100AC0000220FFF7E5FC00283FF48CAE00F04EF961 +:100AD000E1E70220FFF7DCFC00283FF483AE05A924 +:100AE000142000F049F907460421049004A800F0FE +:100AF000C5F83946B9E7322000F0A2F8071EFFF624 +:100B000071AEBB077FF46EAE384A07EB09039268FB +:100B100093423FF667AE0220FFF7BAFC00283FF48D +:100B200061AE27F003074F44B9453FF4A5AE4846F0 +:100B300009F1040900F0CEF80421059005A800F0A1 +:100B40009DF8F1E74FF47A70FFF7A2FC00283FF41C +:100B500049AE00F0FBF8002844D00A9B01330BD0CB +:100B600008220AA9002000F09DF900283AD020228E +:100B7000FF210AA800F08EF9FFF792FC1C4801F053 +:100B8000FFF913B0BDE8F08F002E3FF42BAE0BF051 +:100B90000B030B2B7FF426AE0023642105A80593DD +:100BA00000F062F8074600287FF41CAE0220FFF731 +:100BB0006FFC804600283FF415AEFFF771FC41F250 +:100BC000883001F0DDF9059800F0E4F946463C462E +:100BD00000F0ACF9A6E506464EE64FF0000901E646 +:100BE000BA467EE637467CE67C22002000220020C2 +:100BF000A08601000F4B70B51B780C460133DBB2A9 +:100C0000012B11D80C4D4FF47A732968A2FB0332E3 +:100C100022460E6A01462846B047844204D1074B5B +:100C2000002201201A7070BD4FF4FA7001F0A8F98B +:100C30000020F8E710220020B0260020B423002076 +:100C4000002307B5024601210DF107008DF807309A +:100C5000FFF7D0FF20B19DF8070003B05DF804FB5B +:100C60004FF0FF30F9E700000A46042108B5FFF70E +:100C7000C1FF80F00100C0B2404208BD30B4054C55 +:100C80000A46014623682046DD69034BAC4630BC6A +:100C9000604700BFB0260020A086010070B50A4E54 +:100CA00000240A4D01F088FC308028683388834294 +:100CB00008D901F07DFC2B6804440133B4F5C02F42 +:100CC0002B60F2D370BD00BFB62300208823002024 +:100CD00001F040BD00F1006000F5C02000687047E1 +:100CE00000F10060920000F5C02001F0C1BC0000DE +:100CF000054B1A68054B1B889B1A834202D9104486 +:100D000001F056BC0020704788230020B623002045 +:100D100038B50446074D29B128682044BDE838405D +:100D200001F05EBC2868204401F048FC0028F3D0A4 +:100D300038BD00BF882300200020704700F1FF501D +:100D400000F58F10D0F8000870470000064991F8B0 +:100D5000243033B100230822086A81F82430FFF7D9 +:100D6000BFBF0120704700BF8C230020014B1868D3 +:100D7000704700BF0010005C194B01380322084483 +:100D800070B51D68174BC5F30B042D0C1E88A642C9 +:100D90000BD15C680A46013C824213460FD214F91B +:100DA000016F4EB102F8016BF6E7013A03F1080357 +:100DB000ECD181420B4602D22C2203F8012B0424F1 +:100DC000094A1688AE4204D1984284BF967803F847 +:100DD000016B013C02F10402F3D1581A70BD00BF4F +:100DE0000010005C1422002080400008022803D17B +:100DF000024B4FF080729A61704700BF00000258AA +:100E0000022803D1024B4FF480729A61704700BFF1 +:100E100000000258022804D1024A536983F4807307 +:100E2000536170470000025870B504464FF47A765B +:100E30004CB1412C254628BF412506FB05F0641B1B +:100E400001F09EF8F4E770BD002310B5934203D083 +:100E5000CC5CC4540133F9E710BD0000013810B573 +:100E600010F9013F3BB191F900409C4203D11AB106 +:100E70000131013AF4E71AB191F90020981A10BD36 +:100E80001046FCE703460246D01A12F9011B00295E +:100E9000FAD1704702440346934202D003F8011B83 +:100EA000FAE770472DE9F8431F4D14460746884678 +:100EB00095F8242052BBDFF870909CB395F824304D +:100EC0002BB92022FF2148462F62FFF7E3FF95F858 +:100ED00024004146C0F1080205EB8000A24228BF71 +:100EE0002246D6B29200FFF7AFFF95F82430A41B3C +:100EF00017441E449044E4B2F6B2082E85F82460EC +:100F0000DBD1FFF723FF0028D7D108E02B6A03EBE2 +:100F100082038342CFD0FFF719FF0028CBD10020F6 +:100F2000BDE8F8830120FBE78C230020024B1A78F0 +:100F3000024B1A70704700BFB4230020102200201B +:100F400010B5114C114800F06FFB21460F4800F01E +:100F500097FB24684FF47A70D4F89020D2F80438C4 +:100F600043F00203C2F80438FFF75EFF0849204649 +:100F700000F094FCD4F89020D2F8043823F0020357 +:100F8000C2F8043810BD00BF3C420008B026002063 +:100F90004442000870470000F0B5A1B071B60023CC +:100FA0000120002480261A46194600F04BFA4FF41F +:100FB000D067214A3D25136923BBD2F810310BBB02 +:100FC000036804F1006199600368C3F80CD00368FA +:100FD0005E6003681F6001680B6843F001030B60EB +:100FE00001680B6823F01E030B6001680B68DB07C8 +:100FF000FCD4037B8034416805FA03F3B4F5001F89 +:101000000B60D8D100F05EFAB4F5001F11D00024B7 +:101010000A4E0B4D012001F09DFB3388A34205D9F8 +:1010200028682044013401F0DBFAF6E7002001F0E3 +:1010300091FB61B621B0F0BD00200052B623002024 +:101040008823002030B50A44084D91420DD011F894 +:10105000013B5840082340F30004013B2C4013F0AF +:10106000FF0384EA5000F6D1EFE730BD2083B8EDEE +:1010700008B5074B074A196801F03D0199605368AC +:101080000BB190689847BDE8084001F025BC00BF4F +:1010900000000240B823002008B5084B19688909F0 +:1010A00001F03D018A019A60054AD3680BB11069CD +:1010B0009847BDE8084001F00FBC00BF00000240A7 +:1010C000B823002008B5084B1968090C01F03D0150 +:1010D0000A049A60054A53690BB190699847BDE8C4 +:1010E000084001F0F9BB00BF00000240B823002017 +:1010F00008B5084B1968890D01F03D018A059A6011 +:10110000054AD3690BB1106A9847BDE8084001F061 +:10111000E3BB00BF00000240B823002008B5074B26 +:10112000074A596801F03D01D960536A0BB1906AD2 +:101130009847BDE8084001F0CFBB00BF0000024067 +:10114000B823002008B5084B5968890901F03D0112 +:101150008A01DA60054AD36A0BB1106B9847BDE883 +:10116000084001F0B9BB00BF00000240B8230020D6 +:1011700008B5084B5968090C01F03D010A04DA6012 +:10118000054A536B0BB1906B9847BDE8084001F0DE +:10119000A3BB00BF00000240B823002008B5084BE5 +:1011A0005968890D01F03D018A05DA60054AD36B63 +:1011B0000BB1106C9847BDE8084001F08DBB00BF33 +:1011C00000000240B823002008B5074B074A196801 +:1011D00001F03D019960536C0BB1906C9847BDE8EC +:1011E000084001F079BB00BF00040240B823002092 +:1011F00008B5084B1968890901F03D018A019A6018 +:10120000054AD36C0BB1106D9847BDE8084001F05A +:1012100063BB00BF00040240B823002008B5084BA0 +:101220001968090C01F03D010A049A60054A536DE2 +:101230000BB1906D9847BDE8084001F04DBB00BF71 +:1012400000040240B823002008B5084B1968890D36 +:1012500001F03D018A059A60054AD36D0BB1106E0D +:101260009847BDE8084001F037BB00BF00040240CA +:10127000B823002008B5074B074A596801F03D0123 +:10128000D960536E0BB1906E9847BDE8084001F0ED +:1012900023BB00BF00040240B823002008B5084B60 +:1012A0005968890901F03D018A01DA60054AD36E67 +:1012B0000BB1106F9847BDE8084001F00DBB00BFAF +:1012C00000040240B823002008B5084B5968090CF7 +:1012D00001F03D010A04DA60054A536F0BB1906FCB +:1012E0009847BDE8084001F0F7BA00BF000402408B +:1012F000B823002008B5084B5968890D01F03D015D +:101300008A05DA60054AD36F13B1D2F88000984796 +:10131000BDE8084001F0E0BA00040240B823002014 +:1013200000230C4910B51A460B4C0B6054F82300EF +:10133000026001EB430004334260402BF6D1074AC0 +:101340004FF0FF339360D360C2F80834C2F80C3416 +:1013500010BD00BFB82300209040000800000240EC +:101360000F28F8B510D9102810D0112811D0122844 +:1013700008D10F240720DFF8C8E00126DEF800506E +:10138000A04208D9002653E00446F4E70F240020C9 +:10139000F1E70724FBE706FA00F73D424AD1264C65 +:1013A0004FEA001C3D4304EB00160EEBC000CEF8E4 +:1013B0000050C0E90123FBB273B12048D0F8D83007 +:1013C00043F00103C0F8D830D0F8003143F00103F6 +:1013D000C0F80031D0F8003117F47F4F0ED0174815 +:1013E000D0F8D83043F00203C0F8D830D0F800313C +:1013F00043F00203C0F80031D0F8003154F80C007B +:10140000036823F01F030360056815F00105FBD195 +:1014100004EB0C033D2493F80CC05F6804FA0CF451 +:101420003C6021240560446112B1987B00F054F8BF +:101430003046F8BD0130A3E7904000080044025850 +:10144000B823002010B5302484F31188FFF788FFFB +:10145000002383F3118810BD10B50446807B00F093 +:1014600051F801231549627B03FA02F20B6823EA63 +:101470000203DAB20B6072B9114AD2F8D81021F027 +:101480000101C2F8D810D2F8001121F00101C2F810 +:101490000011D2F8002113F47F4F0ED1084BD3F87E +:1014A000D82022F00202C3F8D820D3F8002122F07D +:1014B0000202C3F80021D3F8003110BDB823002088 +:1014C0000044025808B5302383F31188FFF7C4FFA6 +:1014D000002383F3118808BD090100F16043012254 +:1014E00003F56143C9B283F8001300F01F039A406B +:1014F00043099B0003F1604303F56143C3F8802176 +:101500001A60704700F01F0301229A40430900F15E +:1015100060409B0000F5614003F1604303F56143C7 +:10152000C3F88020C3F88021002380F8003370477F +:10153000026843681143016003B118477047000017 +:1015400013B5406B00F58054D4F8A4381A681178AC +:10155000042914D1017C022911D11979012312899E +:101560008B4013420BD101A94C3002F0A5F8D4F8FE +:10157000A4480246019B2179206800F0DFF902B0FF +:1015800010BD0000143002F027B800004FF0FF3308 +:10159000143002F021B800004C3002F0F9B800001D +:1015A0004FF0FF334C3002F0F3B80000143001F07C +:1015B000F5BF00004FF0FF31143001F0EFBF000025 +:1015C0004C3002F0C5B800004FF0FF324C3002F052 +:1015D000BFB800000020704710B500F58054D4F863 +:1015E000A4381A681178042917D1017C022914D172 +:1015F0005979012352898B4013420ED1143001F0E6 +:1016000087FF024648B1D4F8A4484FF4407361798B +:101610002068BDE8104000F07FB910BD406BFFF7B7 +:10162000DBBF0000704700007FB5124B0125042688 +:10163000044603600023057400F1840243602946D8 +:10164000C0E902330C4B0290143001934FF4407305 +:10165000009601F039FF094B04F69442294604F143 +:101660004C000294CDE900634FF4407302F000F89F +:1016700004B070BD904100081D1600084115000817 +:101680000A68302383F311880B790B3342F8230067 +:101690004B79133342F823008B7913B10B3342F8A3 +:1016A000230000F58053C3F8A4180223037400201C +:1016B00080F311887047000038B5037F044613B1EA +:1016C00090F85430ABB90125201D0221FFF730FFFF +:1016D00004F114006FF00101257700F079FC04F1AA +:1016E0004C0084F854506FF00101BDE8384000F020 +:1016F0006FBC38BD10B5012104460430FFF718FF58 +:101700000023237784F8543010BD000038B5044618 +:101710000025143001F0F0FE04F14C00257701F0B3 +:10172000BFFF201D84F854500121FFF701FF204620 +:10173000BDE83840FFF750BF90F8803003F06003F9 +:10174000202B06D190F881200023212A03D81F2ABC +:1017500006D800207047222AFBD1C0E91D3303E0E0 +:10176000034A426707228267C3670120704700BFB0 +:101770002C22002037B500F58055D5F8A4381A681A +:10178000117804291AD1017C022917D11979012372 +:1017900012898B40134211D100F14C04204602F013 +:1017A0003FF858B101A9204601F086FFD5F8A448BA +:1017B0000246019B2179206800F0C0F803B030BDDB +:1017C00001F10B03F0B550F8236085B004460D46D7 +:1017D000FEB1302383F3118804EB8507301D082107 +:1017E000FFF7A6FEFB6806F14C005B691B681BB1A6 +:1017F000019001F06FFF019803A901F05DFF02461F +:1018000048B1039B2946204600F098F8002383F353 +:10181000118805B0F0BDFB685A691268002AF5D03E +:101820001B8A013B1340F1D104F18002EAE700007A +:10183000133138B550F82140ECB1302383F31188CF +:1018400004F58053D3F8A4281368527903EB82037C +:10185000DB689B695D6845B104216018FFF768FE8D +:10186000294604F1140001F05DFE2046FFF7B4FEA6 +:10187000002383F3118838BD7047000001F02AB9B6 +:1018800001234022002110B5044600F8303BFFF749 +:1018900001FB0023C4E9013310BD000010B5302363 +:1018A000044683F311882422416000210C30FFF7A5 +:1018B000F1FA204601F030F902230020237080F372 +:1018C000118810BD70B500EB8103054650690E46C6 +:1018D0001446DA6018B110220021FFF7DBFAA06984 +:1018E00018B110220021FFF7D5FA31462846BDE88D +:1018F000704001F017BA000083682022002103F035 +:10190000011310B5044683601030FFF7C3FA204678 +:10191000BDE8104001F092BAF0B4012500EB81045B +:1019200047898D40E4683D43A469458123600023D5 +:10193000A2606360F0BC01F0AFBA0000F0B4012512 +:1019400000EB810407898D40E4683D4364690581AB +:1019500023600023A2606360F0BC01F025BB00009F +:1019600070B5022300250446242203702946C0F8DE +:1019700088500C3040F8045CFFF78CFA204684F85D +:10198000705001F063F963681B6823B12946204653 +:10199000BDE87040184770BD0378052B10B50446AC +:1019A0000AD080F88C300523037043681B680BB1A4 +:1019B000042198470023A36010BD00000178052989 +:1019C00006D190F88C20436802701B6803B1184759 +:1019D0007047000070B590F87030044613B10023D2 +:1019E00080F8703004F18002204601F04BFA636801 +:1019F0009B68B3B994F8803013F0600535D00021AE +:101A0000204601F03DFD0021204601F02DFD6368D8 +:101A10001B6813B1062120469847062384F87030CE +:101A200070BD204698470028E4D0B4F88630A26FF5 +:101A30009A4288BFA36794F98030A56F002B4FF0BE +:101A4000300380F20381002D00F0F280092284F837 +:101A5000702083F3118800212046D4E91D23FFF76D +:101A60006DFF002383F31188DAE794F8812003F0F7 +:101A70007F0343EA022340F20232934200F0C58022 +:101A800021D8B3F5807F48D00DD8012B3FD0022B51 +:101A900000F09380002BB2D104F188026267022229 +:101AA000A267E367C1E7B3F5817F00F09B80B3F5E0 +:101AB000407FA4D194F88230012BA0D1B4F88830B3 +:101AC00043F0020332E0B3F5006F4DD017D8B3F501 +:101AD000A06F31D0A3F5C063012B90D86368204676 +:101AE00094F882205E6894F88310B4F88430B0478C +:101AF000002884D0436863670368A3671AE0B3F5DE +:101B0000106F36D040F6024293427FF478AF5C4BC0 +:101B100063670223A3670023C3E794F88230012B95 +:101B20007FF46DAFB4F8883023F00203A4F8883056 +:101B3000C4E91D55E56778E7B4F88030B3F5A06FC8 +:101B40000ED194F88230204684F88A3001F0DCF817 +:101B500063681B6813B10121204698470323237053 +:101B60000023C4E91D339CE704F18B036367012361 +:101B7000C3E72378042B10D1302383F31188204648 +:101B8000FFF7BAFE85F311880321636884F88B5050 +:101B900021701B680BB12046984794F88230002BC7 +:101BA000DED084F88B300423237063681B68002B1D +:101BB000D6D0022120469847D2E794F884302046B8 +:101BC0001D0603F00F010AD501F04EF9012804D0DB +:101BD00002287FF414AF2B4B9AE72B4B98E701F0C8 +:101BE00035F9F3E794F88230002B7FF408AF94F8CE +:101BF000843013F00F01B3D01A06204602D501F04D +:101C000057FCADE701F048FCAAE794F88230002BBE +:101C10007FF4F5AE94F8843013F00F01A0D01B06CA +:101C2000204602D501F02CFC9AE701F01DFC97E755 +:101C3000142284F8702083F311882B462A46294603 +:101C40002046FFF769FE85F31188E9E65DB11522AC +:101C500084F8702083F3118800212046D4E91D23E5 +:101C6000FFF75AFEFDE60B2284F8702083F31188FB +:101C70002B462A4629462046FFF760FEE3E700BFD1 +:101C8000C0410008B8410008BC41000838B590F8D0 +:101C900070300446002B3ED0063BDAB20F2A34D80F +:101CA0000F2B32D8DFE803F03731310822323131DF +:101CB0003131313131313737856FB0F886309D425F +:101CC00014D2C3681B8AB5FBF3F203FB12556DB93E +:101CD000302383F311882B462A462946FFF72EFE30 +:101CE00085F311880A2384F870300EE0142384F8F9 +:101CF0007030302383F31188002320461A4619469A +:101D0000FFF70AFE002383F3118838BDC36F03B1C8 +:101D100098470023E7E70021204601F0B1FB0021AE +:101D2000204601F0A1FB63681B6813B10621204621 +:101D300098470623D7E7000010B590F870300446A6 +:101D4000142B29D017D8062B05D001D81BB110BDF4 +:101D5000093B022BFBD80021204601F091FB00211A +:101D6000204601F081FB63681B6813B10621204601 +:101D70009847062319E0152BE9D10B2380F8703022 +:101D8000302383F3118800231A461946FFF7D6FD46 +:101D9000002383F31188DAE7C3689B695B68002B33 +:101DA000D5D1C36F03B19847002384F87030CEE7D4 +:101DB00000238268037503691B6899689142FBD20E +:101DC0005A68036042601060586070470023826860 +:101DD000037503691B6899689142FBD85A680360D0 +:101DE000426010605860704708B50846302383F39E +:101DF00011880B7D032B05D0042B0DD02BB983F359 +:101E0000118808BD8B6900221A604FF0FF3383618F +:101E1000FFF7CEFF0023F2E7D1E9003213605A60EA +:101E2000F3E70000FFF7C4BF054BD96808751868D1 +:101E3000026853601A600122D8600275FEF7E2BAA8 +:101E4000402400200C4B30B5DD684B1C87B00446A5 +:101E50000FD02B46094A684600F04EF92046FFF79E +:101E6000E3FF009B13B1684600F050F9A86907B082 +:101E700030BDFFF7D9FFF9E740240020E91D000835 +:101E8000044B1A68DB6890689B68984294BF0020F6 +:101E90000120704740240020084B10B51C68D8680A +:101EA000226853601A600122DC602275FFF78EFF02 +:101EB00001462046BDE81040FEF7A4BA40240020A9 +:101EC00038B5074C01230025064907482370656093 +:101ED00001F0E4FC0223237085F3118838BD00BFB4 +:101EE000A8260020C84100084024002000F044B982 +:101EF000034A516853685B1A9842FBD8704700BF89 +:101F0000001000E08B600223086108468B82704756 +:101F10008368A3F1840243F8142C026943F8442C2B +:101F2000426943F8402C094A43F8242CC268A3F1C3 +:101F3000200043F8182C022203F80C2C002203F88E +:101F40000B2C034A43F8102C704700BF1D040008F7 +:101F50004024002008B5FFF7DBFFBDE80840FFF78D +:101F600061BF0000024BDB6898610F20FFF75CBF88 +:101F700040240020302383F31188FFF7F3BF0000D3 +:101F800008B50146302383F311880820FFF75AFF74 +:101F9000002383F3118808BD064BDB6839B1426822 +:101FA00018605A60136043600420FFF74BBF4FF086 +:101FB000FF307047402400200368984206D01A681A +:101FC0000260506018469961FFF72CBF704700000F +:101FD00038B504460D462068844200D138BD0368F8 +:101FE00023605C608561FFF71DFFF4E7036810B5AF +:101FF0009C68A2420CD85C688A600B604C602160CF +:10200000596099688A1A9A604FF0FF33836010BD57 +:10201000121B1B68ECE700000A2938BF0A2170B5C3 +:1020200004460D460A26601901F030FC01F018FC48 +:10203000041BA54203D8751C04462E46F3E70A2E5E +:1020400004D90120BDE8704001F068BC70BD0000FB +:10205000F8B5144B0D460A2A4FF00A07D96103F16F +:102060001001826038BF0A2241601969144601607C +:1020700048601861A81801F0F9FB01F0F1FB431B5F +:102080000646A34206D37C1C28192746354601F094 +:10209000FDFBF2E70A2F04D90120BDE8F84001F06A +:1020A0003DBCF8BD40240020F8B506460D4601F0C1 +:1020B000D7FB0F4A134653F8107F9F4206D12A469A +:1020C00001463046BDE8F840FFF7C2BFD169BB68A2 +:1020D000441A2C1928BF2C46A34202D92946FFF7DF +:1020E0009BFF224631460348BDE8F840FFF77EBF1C +:1020F0004024002050240020C0E90323002310B412 +:102100005DF8044B4361FFF7CFBF000010B5194CD9 +:10211000236998420DD08168D0E9003213605A607B +:102120009A680A449A60002303604FF0FF33A3616A +:1021300010BD0268234643F8102F5360002202604E +:1021400022699A4203D1BDE8104001F099BB93681F +:1021500081680B44936001F083FB2269E169926816 +:10216000441AA242E4D91144BDE81040091AFFF70D +:1021700053BF00BF402400202DE9F047DFF8BC80AA +:1021800008F110072C4ED8F8105001F069FBD8F870 +:102190001C40AA68031B9A423ED814444FF0000921 +:1021A000D5E90032C8F81C4013605A60C5F80090A9 +:1021B000D8F81030B34201D101F062FB89F31188E5 +:1021C000D5E9033128469847302383F311886B699A +:1021D000002BD8D001F044FB6A69A0EB04098246C9 +:1021E0004A450DD2022001F099FB0022D8F81030A8 +:1021F000B34208D151462846BDE8F047FFF728BF53 +:10220000121A2244F2E712EB09092946384638BF70 +:102210004A46FFF7EBFEB5E7D8F81030B34208D0D6 +:102220001444C8F81C00211AA960BDE8F047FFF764 +:10223000F3BEBDE8F08700BF5024002040240020FA +:1022400000207047FEE70000704700004FF0FF30AD +:102250007047000002290CD0032904D00129074847 +:1022600018BF00207047032A05D8054800EBC200BC +:102270007047044870470020704700BFA042000824 +:102280003C2200205442000870B59AB0054608462A +:10229000144601A900F0C2F801A8FEF7F3FD431CA3 +:1022A0000022C6B25B001046C5E900342370032348 +:1022B000023404F8013C01ABD1B202348E4201D8A1 +:1022C0001AB070BD13F8011B013204F8010C04F8B8 +:1022D000021CF1E708B5302383F311880348FFF7A8 +:1022E00049FA002383F3118808BD00BFB0260020FF +:1022F00090F8803003F01F02012A07D190F8812066 +:102300000B2A03D10023C0E91D3315E003F060035D +:10231000202B08D1B0F884302BB990F88120212AE5 +:1023200003D81F2A04D8FFF707BA222AEBD0FAE70E +:10233000034A426707228267C3670120704700BFD4 +:102340003322002007B5052917D8DFE801F0191658 +:1023500003191920302383F31188104A01210190B9 +:10236000FFF7B0FA019802210D4AFFF7ABFA0D48CA +:10237000FFF7CCF9002383F3118803B05DF804FB69 +:10238000302383F311880748FFF796F9F2E73023EB +:1023900083F311880348FFF7ADF9EBE7F441000838 +:1023A00018420008B026002038B50C4D0C4C2A46C7 +:1023B0000C4904F10800FFF767FF05F1CA0204F1B8 +:1023C00010000949FFF760FF05F5CA7204F1180013 +:1023D0000649BDE83840FFF757BF00BF883F0020DF +:1023E0003C220020D4410008DE410008E9410008F9 +:1023F00070B5044608460D46FEF744FDC6B22046B9 +:10240000013403780BB9184670BD32462946FEF7F1 +:1024100025FD0028F3D10120F6E700002DE9F04763 +:1024200005460C46FEF72EFD2B49C6B22846FFF79F +:10243000DFFF08B10636F6B228492846FFF7D8FF75 +:1024400008B11036F6B2632E0BD8DFF88C80DFF8B7 +:102450008C90234FDFF894A02E7846B92670BDE803 +:10246000F08729462046BDE8F04701F0EBBD252E58 +:102470002ED1072241462846FEF7F0FC70B9194BD1 +:10248000224603F10C0153F8040B8B4242F8040B73 +:10249000F9D11B7807350D341370DDE70822494662 +:1024A0002846FEF7DBFC98B9A21C0F4B19780232C4 +:1024B0000909C95D02F8041C13F8011B01F00F01A2 +:1024C0005345C95D02F8031CF0D118340835C3E741 +:1024D000013504F8016BBFE7C0420008E94100087C +:1024E000D6420008C842000800E8F11F0CE8F11FBE +:1024F000BFF34F8F044B1A695107FCD1D3F8102159 +:102500005207F8D1704700BF0020005208B50D4BAC +:102510001B78ABB9FFF7ECFF0B4BDA68D10704D59A +:102520000A4A5A6002F188325A60D3F80C21D20765 +:1025300006D5064AC3F8042102F18832C3F8042103 +:1025400008BD00BFE641002000200052230167457E +:1025500008B5114B1B78F3B9104B1A69510703D515 +:10256000DA6842F04002DA60D3F81021520705D54C +:10257000D3F80C2142F04002C3F80C21FFF7B8FF5A +:10258000064BDA6842F00102DA60D3F80C2142F01F +:102590000102C3F80C2108BDE641002000200052D2 +:1025A0000F289ABF00F580604004002070470000AB +:1025B0004FF4003070470000102070470F2808B516 +:1025C0000BD8FFF7EDFF00F500330268013204D1AC +:1025D00004308342F9D1012008BD0020FCE700004F +:1025E0000F2838B505463FD8FFF782FF1F4CFFF78D +:1025F0008DFF4FF0FF3307286361C4F814311DD8F5 +:102600002361FFF775FF030243F02403E360E368EF +:1026100043F08003E36023695A07FCD42846FFF7A0 +:1026200067FFFFF7BDFF4FF4003100F0F5F82846D3 +:10263000FFF78EFFBDE83840FFF7C0BFC4F8103188 +:10264000FFF756FFA0F108031B0243F02403C4F870 +:102650000C31D4F80C3143F08003C4F80C31D4F8B9 +:1026600010315B07FBD4D9E7002038BD00200052B1 +:102670002DE9F84F05460C46104645EA0203DE06F2 +:1026800002D00020BDE8F88F20F01F00DFF8BCB0BA +:10269000DFF8BCA0FFF73AFF04EB0008444503D184 +:1026A0000120FFF755FFEDE720222946204601F0E3 +:1026B000B9FC10B920352034F0E72B4605F1200293 +:1026C0001F68791CDDD104339A42F9D105F17843B2 +:1026D0001B481C4EB3F5801F1B4B38BF184603F137 +:1026E000F80332BFD946D1461E46FFF701FF076007 +:1026F000A5EB040C336804F11C0143F002033360C2 +:10270000231FD9F8007017F00507FAD153F8042FEA +:102710008B424CF80320F4D1BFF34F8FFFF7E8FE54 +:102720004FF0FF332022214603602846336823F010 +:102730000203336001F076FC0028BBD03846B0E7D6 +:10274000142100520C20005214200052102000527C +:102750001021005210B5084C237828B11BB9FFF79F +:10276000D5FE0123237010BD002BFCD02070BDE8E6 +:102770001040FFF7EDBE00BFE64100200244074BCA +:10278000D2B210B5904200D110BD441C00B253F833 +:10279000200041F8040BE0B2F4E700BF50400058BD +:1027A0000E4B30B51C6F240405D41C6F1C671C6FC6 +:1027B00044F400441C670A4C02442368D2B243F438 +:1027C00080732360074B904200D130BD441C51F808 +:1027D000045B00B243F82050E0B2F4E70044025832 +:1027E000004802585040005807B5012201A90020B6 +:1027F000FFF7C4FF019803B05DF804FB13B504466E +:10280000FFF7F2FFA04205D0012201A900200194A8 +:10281000FFF7C6FF02B010BD0144BFF34F8F064B58 +:10282000884204D3BFF34F8FBFF36F8F7047C3F855 +:102830005C022030F4E700BF00ED00E0034B1A68B3 +:102840001AB9034AD2F8D0241A607047E841002030 +:102850000040025808B5FFF7F1FF024B1868C0F3BB +:10286000806008BDE8410020EFF309830549683323 +:102870004A6B22F001024A6383F30988002383F341 +:102880001188704700EF00E0302080F3118862B6B5 +:102890000D4B0E4AD96821F4E0610904090C0A4382 +:1028A0000B49DA60D3F8FC2042F08072C3F8FC20B8 +:1028B000084AC2F8B01F116841F0010111602022DE +:1028C000DA7783F82200704700ED00E00003FA0594 +:1028D00055CEACC5001000E0302310B583F311884D +:1028E0000E4B5B6813F4006314D0F1EE103AEFF373 +:1028F00009844FF08073683CE361094BDB6B23660E +:1029000084F30988FFF7BCFA10B1064BA36110BD30 +:10291000054BFBE783F31188F9E700BF00ED00E00A +:1029200000EF00E02F0400083204000870B5BFF388 +:102930004F8FBFF36F8F1A4A0021C2F85012BFF3B6 +:102940004F8FBFF36F8F536943F400335361BFF36D +:102950004F8FBFF36F8FC2F88410BFF34F8FD2F841 +:10296000803043F6E074C3F3C900C3F34E335B0118 +:1029700003EA0406014646EA81750139C2F860524D +:10298000F9D2203B13F1200FF2D1BFF34F8F5369DF +:1029900043F480335361BFF34F8FBFF36F8F70BD2C +:1029A00000ED00E0FEE70000214B2248224A70B50E +:1029B000904237D3214BC11EDA1C121A22F00302B7 +:1029C0008B4238BF00220021FEF764FA1C4A002324 +:1029D000C2F88430BFF34F8FD2F8803043F6E074F2 +:1029E000C3F3C900C3F34E335B0103EA0406014697 +:1029F00046EA81750139C2F86C52F9D2203B13F1D5 +:102A0000200FF2D1BFF34F8FBFF36F8FBFF34F8F04 +:102A1000BFF36F8F0023C2F85032BFF34F8FBFF365 +:102A20006F8F70BD53F8041B40F8041BC0E700BF54 +:102A3000C4440008BC430020BC430020BC43002029 +:102A400000ED00E0074BD3F8D81021EA0001C3F8ED +:102A5000D810D3F8002122EA0002C3F80021D3F8ED +:102A6000003170470044025870B5D0E92443002279 +:102A70004FF0FF359E6804EB42135101D3F8000973 +:102A8000002805DAD3F8000940F08040C3F80009B7 +:102A9000D3F8000B002805DAD3F8000B40F0804093 +:102AA000C3F8000B013263189642C3F80859C3F803 +:102AB000085BE0D24FF00113C4F81C3870BD000071 +:102AC000890141F02001016103699B06FCD41220B9 +:102AD000FFF70EBA10B50A4C2046FEF7D1FE094B9F +:102AE000C4F89030084BC4F89430084C2046FEF7E8 +:102AF000C7FE074BC4F89030064BC4F8943010BDA5 +:102B0000EC410020000008400C43000888420020EF +:102B1000000004401843000870B503780546012BF7 +:102B20005CD1434BD0F89040984258D1414B0E2194 +:102B30006520D3F8D82042F00062C3F8D820D3F83B +:102B4000002142F00062C3F80021D3F80021D3F83D +:102B5000802042F00062C3F88020D3F8802022F069 +:102B60000062C3F88020D3F88030FEF7B5FC324B0A +:102B7000E360324BC4F800380023D5F89060C4F805 +:102B8000003EC02323604FF40413A3633369002B7A +:102B9000FCDA01230C203361FFF7AAF93369DB0764 +:102BA000FCD41220FFF7A4F93369002BFCDA0026CD +:102BB0002846A660FFF758FF6B68C4F81068DB680A +:102BC000C4F81468C4F81C6883BB1D4BA3614FF0A4 +:102BD000FF336361A36843F00103A36070BD194B29 +:102BE0009842C9D1134B4FF08060D3F8D82042F0FF +:102BF0000072C3F8D820D3F8002142F00072C3F865 +:102C00000021D3F80021D3F8802042F00072C3F8ED +:102C10008020D3F8802022F00072C3F88020D3F8FF +:102C20008030FFF70FFF0E214D209EE7064BCDE7CA +:102C3000EC410020004402584014004003002002F0 +:102C4000003C30C088420020083C30C0F8B5D0F8C5 +:102C50009040054600214FF000662046FFF730FF08 +:102C6000D5F8941000234FF001128F684FF0FF3019 +:102C7000C4F83438C4F81C2804EB431201339F42D3 +:102C8000C2F80069C2F8006BC2F80809C2F8080B64 +:102C9000F2D20B68D5F89020C5F898306362102303 +:102CA0001361166916F01006FBD11220FFF720F908 +:102CB000D4F8003823F4FE63C4F80038A36943F461 +:102CC000402343F01003A3610923C4F81038C4F86B +:102CD00014380B4BEB604FF0C043C4F8103B094B6A +:102CE000C4F8003BC4F81069C4F80039D5F898302E +:102CF00003F1100243F48013C5F89820A362F8BDD5 +:102D0000E842000840800010D0F8902090F88A1027 +:102D1000D2F8003823F4FE6343EA0113C2F8003806 +:102D2000704700002DE9F84300EB8103D0F8905084 +:102D30000C468046DA680FFA81F94801166806F0F9 +:102D40000306731E022B05EB41134FF0000194BFE5 +:102D5000B604384EC3F8101B4FF0010104F1100304 +:102D600098BF06F1805601FA03F3916998BF06F502 +:102D7000004600293AD0578A04F1580137434901E7 +:102D80006F50D5F81C180B430021C5F81C382B18C0 +:102D90000127C3F81019A7405369611E9BB3138A1A +:102DA000928B9B08012A88BF5343D8F89820981823 +:102DB00042EA034301F140022146C8F89800284640 +:102DC00005EB82025360FFF77BFE08EB8900C368C6 +:102DD0001B8A43EA845348341E4364012E51D5F8BC +:102DE0001C381F43C5F81C78BDE8F88305EB49176C +:102DF000D7F8001B21F40041C7F8001BD5F81C18B8 +:102E000021EA0303C0E704F13F030B4A28462146A9 +:102E100005EB83035A60FFF753FE05EB4910D0F82A +:102E2000003923F40043C0F80039D5F81C3823EAF0 +:102E30000707D7E70080001000040002D0F89420B4 +:102E40001268C0F89820FFF70FBE00005831D0F884 +:102E5000903049015B5813F4004004D013F4001F74 +:102E60000CBF0220012070474831D0F89030490152 +:102E70005B5813F4004004D013F4001F0CBF022071 +:102E80000120704700EB8101CB68196A0B68136061 +:102E90004B6853607047000000EB810330B5DD687C +:102EA000AA691368D36019B9402B84BF402313600B +:102EB0006B8A1468D0F890201C4402EB4110013C4E +:102EC00009B2B4FBF3F46343033323F0030343EA8F +:102ED000C44343F0C043C0F8103B2B6803F0030326 +:102EE000012B0ED1D2F8083802EB411013F4807F89 +:102EF000D0F8003B14BF43F0805343F00053C0F8B8 +:102F0000003B02EB4112D2F8003B43F00443C2F80D +:102F1000003B30BD2DE9F041D0F8906005460C46ED +:102F200006EB4113D3F8087B3A07C3F8087B08D5B2 +:102F3000D6F814381B0704D500EB8103DB685B6807 +:102F40009847FA071FD5D6F81438DB071BD505EBD1 +:102F50008403D968CCB98B69488A5A68B2FBF0F609 +:102F600000FB16228AB91868DA6890420DD2121A4C +:102F7000C3E90024302383F3118821462846FFF754 +:102F80008BFF84F31188BDE8F081012303FA04F27A +:102F90006B8923EA02036B81CB68002BF3D02146B7 +:102FA0002846BDE8F041184700EB81034A0170B59F +:102FB000DD68D0F890306C692668E66056BB1A442C +:102FC0004FF40020C2F810092A6802F00302012A17 +:102FD0000AB20ED1D3F8080803EB421410F4807F34 +:102FE000D4F8000914BF40F0805040F00050C4F8FD +:102FF000000903EB4212D2F8000940F00440C2F885 +:1030000000090122D3F8340802FA01F10143C3F8A0 +:10301000341870BD19B9402E84BF4020206020684C +:103020001A442E8A8419013CB4FBF6F440EAC440E9 +:1030300040F00050C6E700002DE9F843D0F890605A +:1030400005460C464F0106EB4113D3F8088918F0EA +:10305000010FC3F808891CD0D6F81038DB0718D543 +:1030600000EB8103D3F80CC0DCF81430D3F800E097 +:10307000DA68964530D2A2EB0E024FF000091A60D2 +:10308000C3F80490302383F31188FFF78DFF89F391 +:10309000118818F0800F1DD0D6F834380126A640CC +:1030A000334217D005EB84030134D5F89050D3F8A0 +:1030B0000CC0E4B22F44DCF8142005EB0434D2F841 +:1030C00000E05168714514D3D5F8343823EA060678 +:1030D000C5F83468BDE8F883012303FA01F20389D7 +:1030E00023EA02030381DCF80830002BD1D0984793 +:1030F000CFE7AEEB0103BCF81000834228BF0346C4 +:10310000D7F8180980B2B3EB800FE3D89068A0F12C +:10311000040959F8048FC4F80080A0EB090898440A +:10312000B8F1040FF5D818440B4490605360C8E719 +:103130002DE9F84FD0F8905004466E69AB691E40F7 +:1031400016F480586E6103D0BDE8F84FFEF708BC56 +:10315000002E12DAD5F8003E9B0705D0D5F8003EC8 +:1031600023F00303C5F8003ED5F80438204623F0C9 +:103170000103C5F80438FEF721FC370505D52046C4 +:10318000FFF772FC2046FEF707FCB0040CD5D5F81B +:10319000083813F0060FEB6823F470530CBF43F4A8 +:1031A000105343F4A053EB6031071BD56368DB6811 +:1031B0001BB9AB6923F00803AB612378052B0CD155 +:1031C000D5F8003E9A0705D0D5F8003E23F003035A +:1031D000C5F8003E2046FEF7F1FB6368DB680BB1E3 +:1031E00020469847F30200F1BA80B70226D5D4F8FA +:1031F000909000274FF0010A09EB4712D2F8003BEC +:1032000003F44023B3F5802F11D1D2F8003B002BFB +:103210000DDA62890AFA07F322EA0303638104EBF9 +:103220008703DB68DB6813B13946204698470137CE +:10323000D4F89430FFB29B689F42DDD9F00619D5CF +:10324000D4F89000026AC2F30A1702F00F0302F4E6 +:10325000F012B2F5802F00F0CA80B2F5402F09D1EC +:1032600004EB8303002200F58050DB681B6A974261 +:1032700040F0B0803003D5F8185835D5E90303D5B0 +:1032800000212046FFF746FEAA0303D50121204670 +:10329000FFF740FE6B0303D502212046FFF73AFEFD +:1032A0002F0303D503212046FFF734FEE80203D5A0 +:1032B00004212046FFF72EFEA90203D50521204652 +:1032C000FFF728FE6A0203D506212046FFF722FEFB +:1032D0002B0203D507212046FFF71CFEEF0103D583 +:1032E00008212046FFF716FE700340F1A780E9078A +:1032F00003D500212046FFF79FFEAA0703D5012131 +:103300002046FFF799FE6B0703D502212046FFF701 +:1033100093FE2F0703D503212046FFF78DFEEE060F +:1033200003D504212046FFF787FEA80603D5052113 +:103330002046FFF781FE690603D506212046FFF7E8 +:103340007BFE2A0603D507212046FFF775FEEB0515 +:1033500074D520460821BDE8F84FFFF76DBED4F8BC +:1033600090904FF0000B4FF0010AD4F894305FFAC0 +:103370008BF79B689F423FF638AF09EB4713D3F8B2 +:10338000002902F44022B2F5802F20D1D3F8002981 +:10339000002A1CDAD3F8002942F09042C3F8002931 +:1033A000D3F80029002AFBDB3946D4F89000FFF758 +:1033B00087FB22890AFA07F322EA0303238104EB3D +:1033C0008703DB689B6813B13946204698470BF1A9 +:1033D000010BCAE7910701D1D0F80080072A02F15A +:1033E00001029CBF03F8018B4FEA18283FE704EB6A +:1033F000830300F58050DA68D2F818C0DCF80820A2 +:10340000DCE9001CA1EB0C0C00218F4208D1DB6829 +:103410009B699A683A449A605A683A445A6029E724 +:1034200011F0030F01D1D0F800808C4501F10101AA +:1034300084BF02F8018B4FEA1828E6E7BDE8F88F51 +:1034400008B50348FFF774FEBDE80840FFF744BA2B +:10345000EC41002008B50348FFF76AFEBDE80840CC +:10346000FFF73ABA88420020D0F8903003EB4111C0 +:10347000D1F8003B43F40013C1F8003B7047000053 +:10348000D0F8903003EB4111D1F8003943F4001328 +:10349000C1F8003970470000D0F8903003EB4111BB +:1034A000D1F8003B23F40013C1F8003B7047000043 +:1034B000D0F8903003EB4111D1F8003923F4001318 +:1034C000C1F800397047000030B50433039C017225 +:1034D000002104FB0325C160C0E90653049B03637C +:1034E000059BC0E90000C0E90422C0E90842C0E928 +:1034F0000A11436330BD00000022416AC260C0E986 +:103500000411C0E90A226FF00101FEF761BD00005D +:10351000D0E90432934201D1C2680AB9181D70473C +:1035200000207047036919600021C2680132C2603F +:10353000C269134482699342036124BF436A0361F1 +:10354000FEF73ABD38B504460D46E3683BB1626903 +:103550000020131D1268A3621344E36207E0237A7C +:1035600033B929462046FEF717FD0028EDDA38BDAD +:103570006FF00100FBE70000C368C269013BC36054 +:103580004369134482699342436124BF436A4361A0 +:1035900000238362036B03B11847704770B5302373 +:1035A000044683F31188866A3EB9FFF7CBFF0546D0 +:1035B00018B186F31188284670BDA36AE26A13F831 +:1035C000015B9342A36202D32046FFF7D5FF00239D +:1035D00083F31188EFE700002DE9F84F04460E460B +:1035E000174698464FF0300989F311880025AA46FE +:1035F000D4F828B0BBF1000F09D141462046FFF7AF +:10360000A1FF20B18BF311882846BDE8F88FD4E9DB +:103610000A12A7EB050B521A934528BF9346BBF13C +:10362000400F1BD9334601F1400251F8040B91427F +:1036300043F8040BF9D1A36A403640354033A36206 +:10364000D4E90A239A4202D32046FFF795FF8AF372 +:103650001188BD42D8D289F31188C9E730465A464D +:10366000FDF7F2FBA36A5E445D445B44A362E7E7B7 +:1036700010B5029C0433017203FB0421C460C0E94D +:1036800006130023C0E90A33039B0363049BC0E9CC +:103690000000C0E90422C0E90842436310BD0000F5 +:1036A000026A6FF00101C260426AC0E9042200228E +:1036B000C0E90A22FEF78CBCD0E904239A4201D16A +:1036C000C26822B9184650F8043B0B6070470023CB +:1036D0001846FAE7C3680021C2690133C360436931 +:1036E000134482699342436124BF436A4361FEF7F6 +:1036F00063BC000038B504460D46E3683BB123695E +:1037000000201A1DA262E2691344E36207E0237AF3 +:1037100033B929462046FEF73FFC0028EDDA38BDD4 +:103720006FF00100FBE7000003691960C268013A0D +:10373000C260C269134482699342036124BF436A31 +:10374000036100238362036B03B1184770470000D5 +:1037500070B530230D460446114683F31188866AFE +:103760002EB9FFF7C7FF10B186F3118870BDA36AA9 +:103770001D70A36AE26A01339342A36204D3E16934 +:1037800020460439FFF7D0FF002080F31188EDE7D1 +:103790002DE9F84F04460D46904699464FF0300A01 +:1037A0008AF311880026B346A76A4FB949462046D6 +:1037B000FFF7A0FF20B187F311883046BDE8F88FEE +:1037C000D4E90A073A1AA8EB0607974228BF17461A +:1037D000402F1BD905F1400355F8042B9D4240F8BA +:1037E000042BF9D1A36A40364033A362D4E90A23FB +:1037F0009A4204D3E16920460439FFF795FF8BF321 +:1038000011884645D9D28AF31188CDE729463A4630 +:10381000FDF71AFBA36A3D443E443B44A362E5E73F +:10382000D0E904239A4217D1C3689BB1836A8BB154 +:10383000043B9B1A0ED01360C368013BC360C3698D +:103840001A4483699A42026124BF436A03610023D8 +:1038500083620123184670470023FBE700F024B978 +:10386000014B586A704700BF000C0040034B002218 +:1038700058631A610222DA60704700BF000C0040F2 +:10388000014B0022DA607047000C0040014B586386 +:10389000704700BF000C0040FEE7000070B51B4BF6 +:1038A0000025044686B058600E4685620163FEF727 +:1038B000EBFF04F11003A560E562C4E904334FF0A7 +:1038C000FF33C4E90044C4E90635FFF7C9FF2B46BE +:1038D000024604F134012046C4E9082380230C4A3F +:1038E0002565FEF70FFB01230A4AE060009203758D +:1038F000684672680192B268CDE90223064BCDE9B1 +:103900000435FEF727FB06B070BD00BFA8260020D7 +:10391000244300082943000899380008024AD36A62 +:103920001843D062704700BF402400204B684360BA +:103930008B688360CB68C3600B6943614B6903622A +:103940008B6943620B6803607047000008B53C4B0D +:1039500040F2FF713B48D3F888200A43C3F888201F +:10396000D3F8882022F4FF6222F00702C3F88820EF +:10397000D3F88820D3F8E0200A43C3F8E020D3F836 +:1039800008210A43C3F808212F4AD3F80831114609 +:10399000FFF7CCFF00F5806002F11C01FFF7C6FFC6 +:1039A00000F5806002F13801FFF7C0FF00F580608C +:1039B00002F15401FFF7BAFF00F5806002F17001D7 +:1039C000FFF7B4FF00F5806002F18C01FFF7AEFF56 +:1039D00000F5806002F1A801FFF7A8FF00F5806004 +:1039E00002F1C401FFF7A2FF00F5806002F1E001DF +:1039F000FFF79CFF00F5806002F1FC01FFF796FFE6 +:103A000002F58C7100F58060FFF790FF00F018F967 +:103A10000E4BD3F8902242F00102C3F89022D3F863 +:103A2000942242F00102C3F894220522C3F89820A0 +:103A30004FF06052C3F89C20054AC3F8A02008BD8F +:103A400000440258000002583043000800ED00E036 +:103A50001F00080308B500F0C7FAFEF731FA0F4B54 +:103A6000D3F8DC2042F04002C3F8DC20D3F8042174 +:103A700022F04002C3F80421D3F80431084B1A683D +:103A800042F008021A601A6842F004021A60FEF757 +:103A9000D5FEBDE80840FEF787BC00BF00440258D1 +:103AA0000018024870470000114BD3F8E82042F09C +:103AB0000802C3F8E820D3F8102142F00802C3F846 +:103AC00010210C4AD3F81031D36B43F00803D363B1 +:103AD000C722094B9A624FF0FF32DA6200229A61E4 +:103AE0005A63DA605A6001225A611A60704700BF57 +:103AF000004402580010005C000C0040094A08B560 +:103B00001169D3680B40D9B29B076FEA01011161BB +:103B100007D5302383F31188FEF7E8F9002383F3F8 +:103B2000118808BD000C0040064BD3F8DC2002438E +:103B3000C3F8DC20D3F804211043C3F80401D3F800 +:103B4000043170470044025808B53C4B4FF0FF3138 +:103B5000D3F8802062F00042C3F88020D3F88020A0 +:103B600002F00042C3F88020D3F88020D3F88420EC +:103B7000C3F88410D3F884200022C3F88420D3F83B +:103B80008400D86F40F0FF4040F4FF0040F4DF4075 +:103B900040F07F00D867D86F20F0FF4020F4FF008E +:103BA00020F4DF4020F07F00D867D86FD3F888007A +:103BB0006FEA40506FEA5050C3F88800D3F888008D +:103BC000C0F30A00C3F88800D3F88800D3F8900047 +:103BD000C3F89010D3F89000C3F89020D3F8900069 +:103BE000D3F89400C3F89410D3F89400C3F8942049 +:103BF000D3F89400D3F89800C3F89810D3F898003D +:103C0000C3F89820D3F89800D3F88C00C3F88C1030 +:103C1000D3F88C00C3F88C20D3F88C00D3F89C0028 +:103C2000C3F89C10D3F89C10C3F89C20D3F89C30A8 +:103C3000FDF776FBBDE8084000F0AEB9004402583D +:103C400008B50122534BC3F80821534BD3F8F42095 +:103C500042F00202C3F8F420D3F81C2142F0020221 +:103C6000C3F81C210222D3F81C314C4BDA605A688D +:103C70009104FCD54A4A1A6001229A60494ADA60E6 +:103C800000221A614FF440429A61444B9A699204AF +:103C9000FCD51A6842F480721A603F4B1A6F12F416 +:103CA000407F04D04FF480321A6700221A671A68E6 +:103CB00042F001021A60384B1A685007FCD5002206 +:103CC0001A611A6912F03802FBD1012119604FF014 +:103CD000804159605A67344ADA62344A1A611A6874 +:103CE00042F480321A602C4B1A689103FCD51A6892 +:103CF00042F480521A601A689204FCD52C4A2D496D +:103D00009A6200225A63196301F57C01DA6301F2B9 +:103D1000E71199635A64284A1A64284ADA621A68D1 +:103D200042F0A8521A601C4B1A6802F02852B2F1F5 +:103D3000285FF9D148229A614FF48862DA61402203 +:103D40001A621F4ADA641F4A1A651F4A5A651F4AD7 +:103D50009A6532231E4A1360136803F00F03022B87 +:103D6000FAD10D4A136943F003031361136903F099 +:103D70003803182BFAD14FF00050FFF7D5FE4FF063 +:103D80008040FFF7D1FE4FF00040BDE80840FFF74C +:103D9000CBBE00BF008000510044025800480258CA +:103DA00000C000F0020000010000FF010088900840 +:103DB0001210200063020901470E0508DD0BBF0148 +:103DC00020000020000001100910E0000001011097 +:103DD000002000524FF0B04208B5D2F8883003F00E +:103DE0000103C2F8883023B1044A13680BB150684C +:103DF0009847BDE80840FEF76FBD00BF3C43002078 +:103E00004FF0B04208B5D2F8883003F00203C2F890 +:103E1000883023B1044A93680BB1D0689847BDE855 +:103E20000840FEF759BD00BF3C4300204FF0B042B0 +:103E300008B5D2F8883003F00403C2F8883023B103 +:103E4000044A13690BB150699847BDE80840FEF772 +:103E500043BD00BF3C4300204FF0B04208B5D2F84C +:103E6000883003F00803C2F8883023B1044A93690C +:103E70000BB1D0699847BDE80840FEF72DBD00BFE3 +:103E80003C4300204FF0B04208B5D2F8883003F030 +:103E90001003C2F8883023B1044A136A0BB1506A88 +:103EA0009847BDE80840FEF717BD00BF3C4300201F +:103EB0004FF0B04310B5D3F8884004F47872C3F8DB +:103EC0008820A30604D5124A936A0BB1D06A98479A +:103ED000600604D50E4A136B0BB1506B9847210650 +:103EE00004D50B4A936B0BB1D06B9847E20504D510 +:103EF000074A136C0BB1506C9847A30504D5044ACC +:103F0000936C0BB1D06C9847BDE81040FEF7E4BC51 +:103F10003C4300204FF0B04310B5D3F8884004F480 +:103F20007C42C3F88820620504D5164A136D0BB194 +:103F3000506D9847230504D5124A936D0BB1D06D8F +:103F40009847E00404D50F4A136E0BB1506E9847A2 +:103F5000A10404D50B4A936E0BB1D06E984762044E +:103F600004D5084A136F0BB1506F9847230404D54A +:103F7000044A936F0BB1D06F9847BDE81040FEF72D +:103F8000ABBC00BF3C43002008B5FFF7B7FDBDE860 +:103F90000840FEF7A1BC0000062108B50846FDF761 +:103FA0009BFA06210720FDF797FA06210820FDF766 +:103FB00093FA06210920FDF78FFA06210A20FDF762 +:103FC0008BFA06211720FDF787FA06212820FDF736 +:103FD00083FA09217A20FDF77FFA07213220BDE814 +:103FE0000840FDF779BA000008B5FFF7ADFD00F015 +:103FF0000BF8FDF743FCFDF715FBFFF753FDBDE89C +:104000000840FFF72BBC00000023054A1946013386 +:10401000102BC2E9001102F10802F8D1704700BF6D +:104020003C43002010B501390244904201D10020E8 +:1040300005E0037811F8014FA34201D0181B10BD11 +:104040000130F2E7034611F8012B03F8012B002A97 +:10405000F9D1704753544D333248373F3F3F0053F7 +:10406000544D3332483733782F3732780053544D1C +:104070003332483734332F3735332F37353000005C +:1040800001105A0003105900012058000320560067 +:1040900010000240080002400008024000000B002F +:1040A00028000240080002400408024006010C00FB +:1040B00040000240080002400808024010020D00C3 +:1040C00058000240080002400C08024016030E008F +:1040D000700002400C0002401008024000040F0073 +:1040E000880002400C00024014080240060510003F +:1040F000A00002400C000240180802401006110007 +:10410000B80002400C0002401C08024016072F00B5 +:104110001004024008040240200802400008380051 +:10412000280402400804024024080240060939001D +:10413000400402400804024028080240100A3A00E5 +:1041400058040240080402402C080240160B3B00B1 +:10415000700402400C04024030080240000C3C0095 +:10416000880402400C04024034080240060D44005A +:10417000A00402400C04024038080240100E450022 +:10418000B80402400C0402403C080240160F4600EE +:1041900000000000A11500088D150008C9150008D1 +:1041A000B5150008C1150008AD15000899150008DF +:1041B00085150008D515000800000000010000006A +:1041C0000000000063300000C44100089824002073 +:1041D000A82600204172647550696C6F74002542F6 +:1041E0004F415244252D424C002553455249414CE4 +:1041F000250000000200000000000000C1170008B8 +:104200003118000840004000583F0020683F00205F +:104210000200000000000000030000000000000099 +:10422000791800080000000010000000783F00200E +:10423000000000000100000000000000EC41002030 +:10424000010102004523000855220008F122000860 +:10425000D5220008430000005C4200080902430028 +:10426000020100C03209040000010202010005241D +:1042700000100105240100010424020205240600A7 +:1042800001070582030800FF09040100020A00007B +:104290000007050102400000070581024000000000 +:1042A00012000000A84200081201100102000040A4 +:1042B000091241570002010203010000040309042E +:1042C00025424F4152442500426C69747A57696E09 +:1042D0006748373433003031323334353637383984 +:1042E000414243444546000000000000D519000843 +:1042F0008D1C0008391D00084000400024430020A8 +:10430000244300200100000034430020800000000E +:104310004001000008000000000100000010000043 +:10432000080000006D61696E0069646C6500000042 +:104330000000812A00000000AAAAAAAA0000002406 +:10434000FFFE00000000000000A00A0000000001C5 +:1043500000000000AAAAAAAA00000001FFFF0000B6 +:10436000000000000000000000000040000000000D +:10437000AAAAAAAA00000040FFFF00000000000057 +:10438000000000000000100000000000AAAAAAAA75 +:1043900000000000FFFF000000000000000000001F +:1043A0000000400000000000AAAAAAAA00004000E5 +:1043B000FFFF0000000000000000000000000000FF +:1043C00000000000AAAAAAAA00000000FFFF000047 +:1043D00000000000000000000000000000000000DD +:1043E000AAAAAAAA00000000FFFF00000000000027 +:1043F000000000000000000000000000AAAAAAAA15 +:1044000000000000FFFF00000000000000000000AE +:104410000000000000000000AAAAAAAA00000000F4 +:10442000FFFF00000000000000000000000000008E +:1044300000000000AAAAAAAA00000000FFFF0000D6 +:10444000000000000000000000000000000000006C +:10445000AAAAAAAA00000000FFFF000000000000B6 +:1044600000000000000000009004000000000000B8 +:1044700000001A0000000000FF0000000000000023 +:1044800054400008830400005F400008500400000E +:104490006D40000800960000000008009600000033 +:1044A0000008000004000000BC42000800000000FA +:1044B00000000000000000000000000000000000FC +:0444C00000000000F8 +:00000001FF diff --git a/Tools/ros2/README.md b/Tools/ros2/README.md index 9832e412f999d5..c6d6504517be13 100644 --- a/Tools/ros2/README.md +++ b/Tools/ros2/README.md @@ -13,6 +13,14 @@ For example `ardurover` SITL may be launched with: ros2 launch ardupilot_sitl sitl.launch.py command:=ardurover model:=rover ``` +Other launch files are included with many arguments. +Some common arguments are exposed and forwarded to the underlying process. + +For example, MAVProxy can be launched, and you can enable the `console` and `map`. +```bash +ros2 launch ardupilot_sitl sitl_mavproxy.launch.py map:=True console:=True +``` + #### `ardupilot_dds_test` A `colcon` package for testing communication between `micro_ros_agent` and the diff --git a/Tools/ros2/ardupilot_sitl/src/ardupilot_sitl/launch.py b/Tools/ros2/ardupilot_sitl/src/ardupilot_sitl/launch.py index 10203e148bf530..a0ea49a58ab6fa 100644 --- a/Tools/ros2/ardupilot_sitl/src/ardupilot_sitl/launch.py +++ b/Tools/ros2/ardupilot_sitl/src/ardupilot_sitl/launch.py @@ -286,26 +286,36 @@ def generate_action(context: LaunchContext, *args, **kwargs) -> ExecuteProcess: master = LaunchConfiguration("master").perform(context) out = LaunchConfiguration("out").perform(context) sitl = LaunchConfiguration("sitl").perform(context) + console = LaunchConfiguration("console").perform(context) + map = LaunchConfiguration("map").perform(context) # Display launch arguments. print(f"command: {command}") print(f"master: {master}") print(f"sitl: {sitl}") print(f"out: {out}") + print(f"console: {console}") + print(f"map: {map}") + + cmd = [ + f"{command} ", + f"--out {out} ", + "--out ", + "127.0.0.1:14551 ", + f"--master {master} ", + f"--sitl {sitl} ", + "--non-interactive ", + ] + + if console: + cmd.append("--console ") + + if map: + cmd.append("--map ") # Create action. mavproxy_process = ExecuteProcess( - cmd=[ - [ - f"{command} ", - f"--out {out} ", - "--out ", - "127.0.0.1:14551 ", - f"--master {master} ", - f"--sitl {sitl} ", - "--non-interactive ", - ] - ], + cmd=cmd, shell=True, output="both", respawn=False, @@ -355,6 +365,16 @@ def generate_launch_arguments() -> List[DeclareLaunchArgument]: default_value="127.0.0.1:5501", description="SITL output port.", ), + DeclareLaunchArgument( + "map", + default_value="False", + description="Enable MAVProxy Map.", + ), + DeclareLaunchArgument( + "console", + default_value="False", + description="Enable MAVProxy Console.", + ), ] diff --git a/libraries/AC_AutoTune/AC_AutoTune.h b/libraries/AC_AutoTune/AC_AutoTune.h index 4c2198c11ac88c..aff6c928f86cf0 100644 --- a/libraries/AC_AutoTune/AC_AutoTune.h +++ b/libraries/AC_AutoTune/AC_AutoTune.h @@ -286,9 +286,9 @@ class AC_AutoTune LowPassFilterFloat rotation_rate_filt; // filtered rotation rate in radians/second // backup of currently being tuned parameter values - float orig_roll_rp, orig_roll_ri, orig_roll_rd, orig_roll_rff, orig_roll_fltt, orig_roll_smax, orig_roll_sp, orig_roll_accel; - float orig_pitch_rp, orig_pitch_ri, orig_pitch_rd, orig_pitch_rff, orig_pitch_fltt, orig_pitch_smax, orig_pitch_sp, orig_pitch_accel; - float orig_yaw_rp, orig_yaw_ri, orig_yaw_rd, orig_yaw_rff, orig_yaw_fltt, orig_yaw_smax, orig_yaw_rLPF, orig_yaw_sp, orig_yaw_accel; + float orig_roll_rp, orig_roll_ri, orig_roll_rd, orig_roll_rff, orig_roll_dff, orig_roll_fltt, orig_roll_smax, orig_roll_sp, orig_roll_accel; + float orig_pitch_rp, orig_pitch_ri, orig_pitch_rd, orig_pitch_rff, orig_pitch_dff, orig_pitch_fltt, orig_pitch_smax, orig_pitch_sp, orig_pitch_accel; + float orig_yaw_rp, orig_yaw_ri, orig_yaw_rd, orig_yaw_rff, orig_yaw_dff, orig_yaw_fltt, orig_yaw_smax, orig_yaw_rLPF, orig_yaw_sp, orig_yaw_accel; bool orig_bf_feedforward; // currently being tuned parameter values diff --git a/libraries/AC_AutoTune/AC_AutoTune_Multi.cpp b/libraries/AC_AutoTune/AC_AutoTune_Multi.cpp index f304c3e70acb91..37d9d3f415bc79 100644 --- a/libraries/AC_AutoTune/AC_AutoTune_Multi.cpp +++ b/libraries/AC_AutoTune/AC_AutoTune_Multi.cpp @@ -149,6 +149,7 @@ void AC_AutoTune_Multi::backup_gains_and_initialise() orig_roll_ri = attitude_control->get_rate_roll_pid().kI(); orig_roll_rd = attitude_control->get_rate_roll_pid().kD(); orig_roll_rff = attitude_control->get_rate_roll_pid().ff(); + orig_roll_dff = attitude_control->get_rate_roll_pid().kDff(); orig_roll_fltt = attitude_control->get_rate_roll_pid().filt_T_hz(); orig_roll_smax = attitude_control->get_rate_roll_pid().slew_limit(); orig_roll_sp = attitude_control->get_angle_roll_p().kP(); @@ -162,6 +163,7 @@ void AC_AutoTune_Multi::backup_gains_and_initialise() orig_pitch_ri = attitude_control->get_rate_pitch_pid().kI(); orig_pitch_rd = attitude_control->get_rate_pitch_pid().kD(); orig_pitch_rff = attitude_control->get_rate_pitch_pid().ff(); + orig_pitch_dff = attitude_control->get_rate_pitch_pid().kDff(); orig_pitch_fltt = attitude_control->get_rate_pitch_pid().filt_T_hz(); orig_pitch_smax = attitude_control->get_rate_pitch_pid().slew_limit(); orig_pitch_sp = attitude_control->get_angle_pitch_p().kP(); @@ -175,6 +177,7 @@ void AC_AutoTune_Multi::backup_gains_and_initialise() orig_yaw_ri = attitude_control->get_rate_yaw_pid().kI(); orig_yaw_rd = attitude_control->get_rate_yaw_pid().kD(); orig_yaw_rff = attitude_control->get_rate_yaw_pid().ff(); + orig_yaw_dff = attitude_control->get_rate_yaw_pid().kDff(); orig_yaw_fltt = attitude_control->get_rate_yaw_pid().filt_T_hz(); orig_yaw_smax = attitude_control->get_rate_yaw_pid().slew_limit(); orig_yaw_rLPF = attitude_control->get_rate_yaw_pid().filt_E_hz(); @@ -206,6 +209,7 @@ void AC_AutoTune_Multi::load_orig_gains() attitude_control->get_rate_roll_pid().kI(orig_roll_ri); attitude_control->get_rate_roll_pid().kD(orig_roll_rd); attitude_control->get_rate_roll_pid().ff(orig_roll_rff); + attitude_control->get_rate_roll_pid().kDff(orig_roll_dff); attitude_control->get_rate_roll_pid().filt_T_hz(orig_roll_fltt); attitude_control->get_rate_roll_pid().slew_limit(orig_roll_smax); attitude_control->get_angle_roll_p().kP(orig_roll_sp); @@ -218,6 +222,7 @@ void AC_AutoTune_Multi::load_orig_gains() attitude_control->get_rate_pitch_pid().kI(orig_pitch_ri); attitude_control->get_rate_pitch_pid().kD(orig_pitch_rd); attitude_control->get_rate_pitch_pid().ff(orig_pitch_rff); + attitude_control->get_rate_pitch_pid().kDff(orig_pitch_dff); attitude_control->get_rate_pitch_pid().filt_T_hz(orig_pitch_fltt); attitude_control->get_rate_pitch_pid().slew_limit(orig_pitch_smax); attitude_control->get_angle_pitch_p().kP(orig_pitch_sp); @@ -230,6 +235,7 @@ void AC_AutoTune_Multi::load_orig_gains() attitude_control->get_rate_yaw_pid().kI(orig_yaw_ri); attitude_control->get_rate_yaw_pid().kD(orig_yaw_rd); attitude_control->get_rate_yaw_pid().ff(orig_yaw_rff); + attitude_control->get_rate_yaw_pid().kDff(orig_yaw_dff); attitude_control->get_rate_yaw_pid().filt_E_hz(orig_yaw_rLPF); attitude_control->get_rate_yaw_pid().filt_T_hz(orig_yaw_fltt); attitude_control->get_rate_yaw_pid().slew_limit(orig_yaw_smax); @@ -253,6 +259,7 @@ void AC_AutoTune_Multi::load_tuned_gains() attitude_control->get_rate_roll_pid().kI(tune_roll_rp*AUTOTUNE_PI_RATIO_FINAL); attitude_control->get_rate_roll_pid().kD(tune_roll_rd); attitude_control->get_rate_roll_pid().ff(orig_roll_rff); + attitude_control->get_rate_roll_pid().kDff(orig_roll_dff); attitude_control->get_angle_roll_p().kP(tune_roll_sp); attitude_control->set_accel_roll_max_cdss(tune_roll_accel); } @@ -263,6 +270,7 @@ void AC_AutoTune_Multi::load_tuned_gains() attitude_control->get_rate_pitch_pid().kI(tune_pitch_rp*AUTOTUNE_PI_RATIO_FINAL); attitude_control->get_rate_pitch_pid().kD(tune_pitch_rd); attitude_control->get_rate_pitch_pid().ff(orig_pitch_rff); + attitude_control->get_rate_pitch_pid().kDff(orig_pitch_dff); attitude_control->get_angle_pitch_p().kP(tune_pitch_sp); attitude_control->set_accel_pitch_max_cdss(tune_pitch_accel); } @@ -278,6 +286,7 @@ void AC_AutoTune_Multi::load_tuned_gains() attitude_control->get_rate_yaw_pid().filt_E_hz(tune_yaw_rLPF); } attitude_control->get_rate_yaw_pid().ff(orig_yaw_rff); + attitude_control->get_rate_yaw_pid().kDff(orig_yaw_dff); attitude_control->get_angle_yaw_p().kP(tune_yaw_sp); attitude_control->set_accel_yaw_max_cdss(tune_yaw_accel); } @@ -296,6 +305,7 @@ void AC_AutoTune_Multi::load_intra_test_gains() attitude_control->get_rate_roll_pid().kI(orig_roll_rp*AUTOTUNE_PI_RATIO_FOR_TESTING); attitude_control->get_rate_roll_pid().kD(orig_roll_rd); attitude_control->get_rate_roll_pid().ff(orig_roll_rff); + attitude_control->get_rate_roll_pid().kDff(orig_roll_dff); attitude_control->get_rate_roll_pid().filt_T_hz(orig_roll_fltt); attitude_control->get_rate_roll_pid().slew_limit(orig_roll_smax); attitude_control->get_angle_roll_p().kP(orig_roll_sp); @@ -305,6 +315,7 @@ void AC_AutoTune_Multi::load_intra_test_gains() attitude_control->get_rate_pitch_pid().kI(orig_pitch_rp*AUTOTUNE_PI_RATIO_FOR_TESTING); attitude_control->get_rate_pitch_pid().kD(orig_pitch_rd); attitude_control->get_rate_pitch_pid().ff(orig_pitch_rff); + attitude_control->get_rate_pitch_pid().kDff(orig_pitch_dff); attitude_control->get_rate_pitch_pid().filt_T_hz(orig_pitch_fltt); attitude_control->get_rate_pitch_pid().slew_limit(orig_pitch_smax); attitude_control->get_angle_pitch_p().kP(orig_pitch_sp); @@ -314,6 +325,7 @@ void AC_AutoTune_Multi::load_intra_test_gains() attitude_control->get_rate_yaw_pid().kI(orig_yaw_rp*AUTOTUNE_PI_RATIO_FOR_TESTING); attitude_control->get_rate_yaw_pid().kD(orig_yaw_rd); attitude_control->get_rate_yaw_pid().ff(orig_yaw_rff); + attitude_control->get_rate_yaw_pid().kDff(orig_yaw_dff); attitude_control->get_rate_yaw_pid().filt_T_hz(orig_yaw_fltt); attitude_control->get_rate_yaw_pid().slew_limit(orig_yaw_smax); attitude_control->get_rate_yaw_pid().filt_E_hz(orig_yaw_rLPF); @@ -331,6 +343,7 @@ void AC_AutoTune_Multi::load_test_gains() attitude_control->get_rate_roll_pid().kI(tune_roll_rp*0.01f); attitude_control->get_rate_roll_pid().kD(tune_roll_rd); attitude_control->get_rate_roll_pid().ff(0.0f); + attitude_control->get_rate_roll_pid().kDff(0.0f); attitude_control->get_rate_roll_pid().filt_T_hz(0.0f); attitude_control->get_rate_roll_pid().slew_limit(0.0f); attitude_control->get_angle_roll_p().kP(tune_roll_sp); @@ -340,6 +353,7 @@ void AC_AutoTune_Multi::load_test_gains() attitude_control->get_rate_pitch_pid().kI(tune_pitch_rp*0.01f); attitude_control->get_rate_pitch_pid().kD(tune_pitch_rd); attitude_control->get_rate_pitch_pid().ff(0.0f); + attitude_control->get_rate_pitch_pid().kDff(0.0f); attitude_control->get_rate_pitch_pid().filt_T_hz(0.0f); attitude_control->get_rate_pitch_pid().slew_limit(0.0f); attitude_control->get_angle_pitch_p().kP(tune_pitch_sp); @@ -349,6 +363,7 @@ void AC_AutoTune_Multi::load_test_gains() attitude_control->get_rate_yaw_pid().kP(tune_yaw_rp); attitude_control->get_rate_yaw_pid().kI(tune_yaw_rp*0.01f); attitude_control->get_rate_yaw_pid().ff(0.0f); + attitude_control->get_rate_yaw_pid().kDff(0.0f); if (axis == YAW_D) { attitude_control->get_rate_yaw_pid().kD(tune_yaw_rd); } else { @@ -383,6 +398,7 @@ void AC_AutoTune_Multi::save_tuning_gains() attitude_control->get_rate_roll_pid().kI(tune_roll_rp*AUTOTUNE_PI_RATIO_FINAL); attitude_control->get_rate_roll_pid().kD(tune_roll_rd); attitude_control->get_rate_roll_pid().ff(orig_roll_rff); + attitude_control->get_rate_roll_pid().kDff(orig_roll_dff); attitude_control->get_rate_roll_pid().filt_T_hz(orig_roll_fltt); attitude_control->get_rate_roll_pid().slew_limit(orig_roll_smax); attitude_control->get_rate_roll_pid().save_gains(); @@ -399,6 +415,7 @@ void AC_AutoTune_Multi::save_tuning_gains() orig_roll_ri = attitude_control->get_rate_roll_pid().kI(); orig_roll_rd = attitude_control->get_rate_roll_pid().kD(); orig_roll_rff = attitude_control->get_rate_roll_pid().ff(); + orig_roll_dff = attitude_control->get_rate_roll_pid().kDff(); orig_roll_sp = attitude_control->get_angle_roll_p().kP(); orig_roll_accel = attitude_control->get_accel_roll_max_cdss(); } @@ -409,6 +426,7 @@ void AC_AutoTune_Multi::save_tuning_gains() attitude_control->get_rate_pitch_pid().kI(tune_pitch_rp*AUTOTUNE_PI_RATIO_FINAL); attitude_control->get_rate_pitch_pid().kD(tune_pitch_rd); attitude_control->get_rate_pitch_pid().ff(orig_pitch_rff); + attitude_control->get_rate_pitch_pid().kDff(orig_pitch_dff); attitude_control->get_rate_pitch_pid().filt_T_hz(orig_pitch_fltt); attitude_control->get_rate_pitch_pid().slew_limit(orig_pitch_smax); attitude_control->get_rate_pitch_pid().save_gains(); @@ -425,6 +443,7 @@ void AC_AutoTune_Multi::save_tuning_gains() orig_pitch_ri = attitude_control->get_rate_pitch_pid().kI(); orig_pitch_rd = attitude_control->get_rate_pitch_pid().kD(); orig_pitch_rff = attitude_control->get_rate_pitch_pid().ff(); + orig_pitch_dff = attitude_control->get_rate_pitch_pid().kDff(); orig_pitch_sp = attitude_control->get_angle_pitch_p().kP(); orig_pitch_accel = attitude_control->get_accel_pitch_max_cdss(); } @@ -435,6 +454,7 @@ void AC_AutoTune_Multi::save_tuning_gains() attitude_control->get_rate_yaw_pid().kP(tune_yaw_rp); attitude_control->get_rate_yaw_pid().kI(tune_yaw_rp*AUTOTUNE_YAW_PI_RATIO_FINAL); attitude_control->get_rate_yaw_pid().ff(orig_yaw_rff); + attitude_control->get_rate_yaw_pid().kDff(orig_yaw_dff); attitude_control->get_rate_yaw_pid().filt_T_hz(orig_yaw_fltt); attitude_control->get_rate_yaw_pid().slew_limit(orig_yaw_smax); if (yaw_d_enabled()) { @@ -457,6 +477,7 @@ void AC_AutoTune_Multi::save_tuning_gains() orig_yaw_ri = attitude_control->get_rate_yaw_pid().kI(); orig_yaw_rd = attitude_control->get_rate_yaw_pid().kD(); orig_yaw_rff = attitude_control->get_rate_yaw_pid().ff(); + orig_yaw_dff = attitude_control->get_rate_yaw_pid().kDff(); orig_yaw_rLPF = attitude_control->get_rate_yaw_pid().filt_E_hz(); orig_yaw_sp = attitude_control->get_angle_yaw_p().kP(); orig_yaw_accel = attitude_control->get_accel_yaw_max_cdss(); diff --git a/libraries/AP_BattMonitor/AP_BattMonitor.cpp b/libraries/AP_BattMonitor/AP_BattMonitor.cpp index d929b8182a06df..15f44291aa67bd 100644 --- a/libraries/AP_BattMonitor/AP_BattMonitor.cpp +++ b/libraries/AP_BattMonitor/AP_BattMonitor.cpp @@ -66,6 +66,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: _ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: _ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[0], "_", 41, AP_BattMonitor, backend_var_info[0]), #if AP_BATT_MONITOR_MAX_INSTANCES > 1 @@ -87,6 +89,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: 2_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: 2_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[1], "2_", 42, AP_BattMonitor, backend_var_info[1]), #endif @@ -109,6 +113,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: 3_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: 3_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[2], "3_", 43, AP_BattMonitor, backend_var_info[2]), #endif @@ -131,6 +137,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: 4_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: 4_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[3], "4_", 44, AP_BattMonitor, backend_var_info[3]), #endif @@ -153,6 +161,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: 5_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: 5_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[4], "5_", 45, AP_BattMonitor, backend_var_info[4]), #endif @@ -175,6 +185,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: 6_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: 6_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[5], "6_", 46, AP_BattMonitor, backend_var_info[5]), #endif @@ -197,6 +209,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: 7_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: 7_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[6], "7_", 47, AP_BattMonitor, backend_var_info[6]), #endif @@ -219,6 +233,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: 8_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: 8_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[7], "8_", 48, AP_BattMonitor, backend_var_info[7]), #endif @@ -241,6 +257,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: 9_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: 9_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[8], "9_", 49, AP_BattMonitor, backend_var_info[8]), #endif @@ -263,6 +281,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: A_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: A_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[9], "A_", 50, AP_BattMonitor, backend_var_info[9]), #endif @@ -285,6 +305,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: B_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: B_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[10], "B_", 51, AP_BattMonitor, backend_var_info[10]), #endif @@ -307,6 +329,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: C_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: C_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[11], "C_", 52, AP_BattMonitor, backend_var_info[11]), #endif @@ -329,6 +353,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: D_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: D_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[12], "D_", 53, AP_BattMonitor, backend_var_info[12]), #endif @@ -351,6 +377,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: E_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: E_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[13], "E_", 54, AP_BattMonitor, backend_var_info[13]), #endif @@ -373,6 +401,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: F_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: F_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[14], "F_", 55, AP_BattMonitor, backend_var_info[14]), #endif @@ -395,6 +425,8 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] = { // @Path: AP_BattMonitor_Synthetic_Current.cpp // @Group: G_ // @Path: AP_BattMonitor_INA2xx.cpp + // @Group: G_ + // @Path: AP_BattMonitor_ESC.cpp AP_SUBGROUPVARPTR(drivers[15], "G_", 56, AP_BattMonitor, backend_var_info[15]), #endif diff --git a/libraries/AP_BattMonitor/AP_BattMonitor_DroneCAN.cpp b/libraries/AP_BattMonitor/AP_BattMonitor_DroneCAN.cpp index 3c7d35fd9e5b9a..0af65b951d0a27 100644 --- a/libraries/AP_BattMonitor/AP_BattMonitor_DroneCAN.cpp +++ b/libraries/AP_BattMonitor/AP_BattMonitor_DroneCAN.cpp @@ -26,7 +26,7 @@ const AP_Param::GroupInfo AP_BattMonitor_DroneCAN::var_info[] = { // @User: Advanced AP_GROUPINFO("CURR_MULT", 30, AP_BattMonitor_DroneCAN, _curr_mult, 1.0), - // Param indexes must be between 30 and 39 to avoid conflict with other battery monitor param tables loaded by pointer + // Param indexes must be between 30 and 35 to avoid conflict with other battery monitor param tables loaded by pointer AP_GROUPEND }; diff --git a/libraries/AP_BattMonitor/AP_BattMonitor_ESC.cpp b/libraries/AP_BattMonitor/AP_BattMonitor_ESC.cpp index c633217f531aeb..a1c309a6e60ef3 100644 --- a/libraries/AP_BattMonitor/AP_BattMonitor_ESC.cpp +++ b/libraries/AP_BattMonitor/AP_BattMonitor_ESC.cpp @@ -20,6 +20,32 @@ #include "AP_BattMonitor_ESC.h" +const AP_Param::GroupInfo AP_BattMonitor_ESC::var_info[] = { + + // Param indexes must be between 36 and 39 to avoid conflict with other battery monitor param tables loaded by pointer + + // @Param: ESC_MASK + // @DisplayName: ESC mask + // @Description: If 0 all connected ESCs will be used. If non-zero, only those selected in will be used. + // @Bitmask: 0: ESC 1, 1: ESC 2, 2: ESC 3, 3: ESC 4, 4: ESC 5, 5: ESC 6, 6: ESC 7, 7: ESC 8, 8: ESC 9, 9: ESC 10, 10: ESC 11, 11: ESC 12, 12: ESC 13, 13: ESC 14, 14: ESC 15, 15: ESC 16, 16: ESC 17, 17: ESC 18, 18: ESC 19, 19: ESC 20, 20: ESC 21, 21: ESC 22, 22: ESC 23, 23: ESC 24, 24: ESC 25, 25: ESC 26, 26: ESC 27, 27: ESC 28, 28: ESC 29, 29: ESC 30, 30: ESC 31, 31: ESC 32 + // @User: Standard + AP_GROUPINFO("ESC_MASK", 36, AP_BattMonitor_ESC, _mask, 0), + + // Param indexes must be between 36 and 39 to avoid conflict with other battery monitor param tables loaded by pointer + + AP_GROUPEND +}; + +// constructor. This incorporates initialisation as well. +AP_BattMonitor_ESC::AP_BattMonitor_ESC(AP_BattMonitor &mon, + AP_BattMonitor::BattMonitor_State &mon_state, + AP_BattMonitor_Params ¶ms): + AP_BattMonitor_Backend(mon, mon_state, params) +{ + AP_Param::setup_object_defaults(this, var_info); + _state.var_info = var_info; +}; + void AP_BattMonitor_ESC::init(void) { } @@ -34,9 +60,15 @@ void AP_BattMonitor_ESC::read(void) float current_sum = 0; float temperature_sum = 0; uint32_t highest_ms = 0; - _state.consumed_mah = delta_mah; + _state.consumed_mah = delta_mah; + const bool all_enabled = _mask == 0; for (uint8_t i=0; isnprintf(failure_msg, failure_msg_len, LOG_FMT, get_name(), "missing 3D GPS fix on either GPS"); return false; } - if (!filter_state_healthy(FilterState(filter_status.state))) { - hal.util->snprintf(failure_msg, failure_msg_len, LOG_FMT, get_name(), "filter not healthy"); - return false; - } return true; } diff --git a/libraries/AP_GPS/AP_GPS.h b/libraries/AP_GPS/AP_GPS.h index e45aef88c44c95..e21bf665246316 100644 --- a/libraries/AP_GPS/AP_GPS.h +++ b/libraries/AP_GPS/AP_GPS.h @@ -197,7 +197,7 @@ class AP_GPS uint16_t time_week; ///< GPS week number Location location; ///< last fix location float ground_speed; ///< ground speed in m/s - float ground_course; ///< ground course in degrees + float ground_course; ///< ground course in degrees, wrapped 0-360 float gps_yaw; ///< GPS derived yaw information, if available (degrees) uint32_t gps_yaw_time_ms; ///< timestamp of last GPS yaw reading bool gps_yaw_configured; ///< GPS is configured to provide yaw diff --git a/libraries/AP_GPS/AP_GPS_GSOF.cpp b/libraries/AP_GPS/AP_GPS_GSOF.cpp index 4fbfef5833a2d5..4327c9f4d4bbba 100644 --- a/libraries/AP_GPS/AP_GPS_GSOF.cpp +++ b/libraries/AP_GPS/AP_GPS_GSOF.cpp @@ -326,7 +326,7 @@ AP_GPS_GSOF::process_message(void) if ((vflag & 1) == 1) { state.ground_speed = SwapFloat(msg.data, a + 1); - state.ground_course = degrees(SwapFloat(msg.data, a + 5)); + state.ground_course = wrap_360(degrees(SwapFloat(msg.data, a + 5))); fill_3d_velocity(); state.velocity.z = -SwapFloat(msg.data, a + 9); state.have_vertical_velocity = true; diff --git a/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/README.md b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/README.md new file mode 100644 index 00000000000000..37dfb7934484ed --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/README.md @@ -0,0 +1,106 @@ +# iFlight BLITZ Wing H743 Flight Controller + +The BLITZ Wing H743 is a flight controller produced by [iFlight](https://shop.iflight.com/electronics-cat27/BLITZ-Wing-H743-Flight-Controller-Pro2174). + +## Features + + - MCU - STM32H743 32-bit processor running at 480 MHz + - Gyro: ICM42688 + - SDCard for logging + - 5V 3A BEC for Flight Controller + - 9V 3A BEC for VTX + - 5-8.4V 6A BEC for Servo + - Barometer: DPS310 + - OSD: AT7456E + - 7x UARTs + - 13x PWM Outputs (12 Motor Output, 1 LED) + - Battery input voltage: 2S-8S + - 2x I2C for external compass, airspeed, etc. + - CAN port + +## Physical + - Mount pattern: 30.5*30.5mm/?4 + - Dimensions: 36.9*52mm + - Weight: 35g + +## Pinout + +![BLITZ Wing H743 Board](blitz_h7_wing_top.PNG "BLITZ Wing H743 Top") +![BLITZ Wing H743 Board](blitz_h7_wing_middle.PNG "BLITZ Wing H743 Middle") +![BLITZ Wing H743 Board](blitz_h7_wing_bottom.PNG "BLITZ Wing H743 Bottom") + +## UART Mapping + +The UARTs are marked Rn and Tn in the above pinouts. The Rn pin is the +receive pin for UARTn. The Tn pin is the transmit pin for UARTn. +|Name|Pin|Function| +|:-|:-|:-| +|SERIAL0|COMPUTER|USB| +|SERIAL1|RX1/TX1|UART1 (DJI connector, DMA-enabled)| +|SERIAL2|TX2/RX2|UART2 (RX, DMA-enabled)| +|SERIAL3|TX3/RX3|UART3 (DMA-enabled)| +|SERIAL4|TX4/RX4|UART4 (GPS, DMA-enabled)| +|SERIAL6|TX6/RX6|UART6| +|SERIAL7|TX7/RX7|UART7| +|SERIAL8|TX8/RX8|UART8 (ESC Telemetry)| + +## RC Input + +RC input is configured on the (UART2_RX/UART2_TX) pins which forms part of the DJI connector. It supports all serial RC protocols. + +## OSD Support + +The BLITZ Wing H743 supports OSD using OSD_TYPE 1 (MAX7456 driver). Simultaneously, DisplayPort HD OSD is enabled by default and available on the HD VTX connector. + +## PWM Output + +The BLITZ Wing H743 has 13 PWM outputs. The first 8 outputs support bi-directional DShot and DShot, as well as all PWM types. Outputs 9-10 support DShot, as well as all PWM types and outputs 11-12 only support PWM. + +The PWM are in in five groups: + + - PWM 1-2 in group1 + - PWM 3-6 in group2 + - PWM 7-10 in group3 + - PWM 11-12 in group4 + - PWM 13 in group5 + +Channels within the same group need to use the same output rate. If +any channel in a group uses DShot then all channels in the group need +to use DShot. + +## Video Power Control + +The 9V video power can be turned off/on using GPIO 81 which is already assigned by default to RELAY2. This relay can be controlled either from the GCS or using a transmitter channel (See :ref:`common-auxiliary-functions`) + +## Analog Airspeed Input + +The analog airspeed pin is "4" + +## Battery Monitoring + +The board has a built-in voltage sensor and current sensor. The voltage sensor can handle up to 8S +LiPo batteries. + +The correct battery setting parameters are: + + - BATT_MONITOR 4 + - BATT_VOLT_PIN 10 + - BATT_VOLT_MULT 11 + - BATT_CURR_PIN 11 + - BATT_CURR_MULT 50 + +These are set by default in the firmware and shouldn't need to be adjusted + +## Compass + +The BLITZ Wing H743 does not have a builtin compass, but you can attach an external compass to I2C pins. + +## Loading Firmware + +Initial firmware load can be done with DFU by plugging in USB with the +bootloader button pressed. Then you should load the "with_bl.hex" +firmware, using your favourite DFU loading tool. + +Once the initial firmware is loaded you can update the firmware using +any ArduPilot ground station software. Updates should be done with the +*.apj firmware files. diff --git a/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/blitz_h7_wing_bottom.PNG b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/blitz_h7_wing_bottom.PNG new file mode 100644 index 00000000000000..9de0830011dd31 Binary files /dev/null and b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/blitz_h7_wing_bottom.PNG differ diff --git a/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/blitz_h7_wing_middle.PNG b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/blitz_h7_wing_middle.PNG new file mode 100644 index 00000000000000..1aad2f38886b8d Binary files /dev/null and b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/blitz_h7_wing_middle.PNG differ diff --git a/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/blitz_h7_wing_top.PNG b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/blitz_h7_wing_top.PNG new file mode 100644 index 00000000000000..6ec7202d6ae388 Binary files /dev/null and b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/blitz_h7_wing_top.PNG differ diff --git a/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/defaults.parm b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/defaults.parm new file mode 100644 index 00000000000000..5d4fab1adaed4b --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/defaults.parm @@ -0,0 +1,4 @@ +# setup for LEDs on chan9 +SERVO13_FUNCTION 120 +NTF_LED_TYPES 257 +OSD_TYPE2 5 diff --git a/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/hwdef-bl.dat b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/hwdef-bl.dat new file mode 100644 index 00000000000000..2406ec403c5e77 --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/hwdef-bl.dat @@ -0,0 +1,3 @@ +include ../BlitzH743Pro/hwdef-bl.dat + +APJ_BOARD_ID AP_HW_BlitzH7Wing \ No newline at end of file diff --git a/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/hwdef.dat b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/hwdef.dat new file mode 100644 index 00000000000000..2332cd2e028032 --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/BlitzWingH743/hwdef.dat @@ -0,0 +1,13 @@ +include ../BlitzH743Pro/hwdef.dat + +APJ_BOARD_ID AP_HW_BlitzH7Wing + +undef SERIAL_ORDER +SERIAL_ORDER OTG1 USART1 USART2 USART3 UART4 EMPTY USART6 UART7 UART8 OTG2 + +undef DEFAULT_SERIAL5_PROTOCOL +define DEFAULT_SERIAL8_PROTOCOL SerialProtocol_ESCTelemetry +undef HAL_FRAME_TYPE_DEFAULT + +undef PC5 +undef BOARD_RSSI_ANA_PIN diff --git a/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py b/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py index 8744b43a3896fc..4e1e04a75563e6 100644 --- a/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py +++ b/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py @@ -2613,14 +2613,6 @@ def write_hwdef_header(self, outfilename): self.embed_bootloader(f) - if len(self.romfs) > 0: - # Allow lua to load from ROMFS if any lua files are added - for file in self.romfs.keys(): - if file.startswith("scripts") and file.endswith(".lua"): - f.write('#define HAL_HAVE_AP_ROMFS_EMBEDDED_LUA 1\n') - break - f.write('#define HAL_HAVE_AP_ROMFS_EMBEDDED_H 1\n') - if self.mcu_series.startswith('STM32F1'): f.write(''' /* diff --git a/libraries/AP_HAL_Linux/GPIO_RPI.cpp b/libraries/AP_HAL_Linux/GPIO_RPI.cpp index 974e6523e4a61b..74d300185e0f80 100644 --- a/libraries/AP_HAL_Linux/GPIO_RPI.cpp +++ b/libraries/AP_HAL_Linux/GPIO_RPI.cpp @@ -8,237 +8,64 @@ CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_OBAL_V1 || \ CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_CANZERO -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "GPIO.h" +#include "GPIO_RPI.h" +#include "GPIO_RPI_BCM.h" +#include "GPIO_RPI_RP1.h" #include "Util_RPI.h" -#define GPIO_RPI_MAX_NUMBER_PINS 32 - -using namespace Linux; - extern const AP_HAL::HAL& hal; -// Range based in the first memory address of the first register and the last memory addres -// for the GPIO section (0x7E20'00B4 - 0x7E20'0000). -const uint8_t GPIO_RPI::_gpio_registers_memory_range = 0xB4; -const char* GPIO_RPI::_system_memory_device_path = "/dev/mem"; +using namespace Linux; GPIO_RPI::GPIO_RPI() { } -void GPIO_RPI::set_gpio_mode_alt(int pin, int alternative) -{ - // Each register can contain 10 pins - const uint8_t pins_per_register = 10; - // Calculates the position of the 3 bit mask in the 32 bits register - const uint8_t tree_bits_position_in_register = (pin%pins_per_register)*3; - /** Creates a mask to enable the alternative function based in the following logic: - * - * | Alternative Function | 3 bits value | - * |:--------------------:|:------------:| - * | Function 0 | 0b100 | - * | Function 1 | 0b101 | - * | Function 2 | 0b110 | - * | Function 3 | 0b111 | - * | Function 4 | 0b011 | - * | Function 5 | 0b010 | - */ - const uint8_t alternative_value = - (alternative < 4 ? (alternative + 4) : (alternative == 4 ? 3 : 2)); - // 0b00'000'000'000'000'000'000'ALT'000'000'000 enables alternative for the 4th pin - const uint32_t mask_with_alt = static_cast(alternative_value) << tree_bits_position_in_register; - const uint32_t mask = 0b111 << tree_bits_position_in_register; - // Clear all bits in our position and apply our mask with alt values - uint32_t register_value = _gpio[pin / pins_per_register]; - register_value &= ~mask; - _gpio[pin / pins_per_register] = register_value | mask_with_alt; -} - -void GPIO_RPI::set_gpio_mode_in(int pin) -{ - // Each register can contain 10 pins - const uint8_t pins_per_register = 10; - // Calculates the position of the 3 bit mask in the 32 bits register - const uint8_t tree_bits_position_in_register = (pin%pins_per_register)*3; - // Create a mask that only removes the bits in this specific GPIO pin, E.g: - // 0b11'111'111'111'111'111'111'000'111'111'111 for the 4th pin - const uint32_t mask = ~(0b111<(address) + static_cast(offset); -} - -volatile uint32_t* GPIO_RPI::get_memory_pointer(uint32_t address, uint32_t range) const -{ - auto pointer = mmap( - nullptr, // Any adddress in our space will do - range, // Map length - PROT_READ|PROT_WRITE|PROT_EXEC, // Enable reading & writing to mapped memory - MAP_SHARED|MAP_LOCKED, // Shared with other processes - _system_memory_device, // File to map - address // Offset to GPIO peripheral - ); - - if (pointer == MAP_FAILED) { - return nullptr; - } - - return static_cast(pointer); -} - -bool GPIO_RPI::openMemoryDevice() -{ - _system_memory_device = open(_system_memory_device_path, O_RDWR|O_SYNC|O_CLOEXEC); - if (_system_memory_device < 0) { - AP_HAL::panic("Can't open %s", GPIO_RPI::_system_memory_device_path); - return false; - } - - return true; -} - -void GPIO_RPI::closeMemoryDevice() -{ - close(_system_memory_device); - // Invalidate device variable - _system_memory_device = -1; -} - void GPIO_RPI::init() { const LINUX_BOARD_TYPE rpi_version = UtilRPI::from(hal.util)->detect_linux_board_type(); - GPIO_RPI::Address peripheral_base; - if(rpi_version == LINUX_BOARD_TYPE::RPI_ZERO_1) { - peripheral_base = Address::BCM2708_PERIPHERAL_BASE; - } else if (rpi_version == LINUX_BOARD_TYPE::RPI_2_3_ZERO2) { - peripheral_base = Address::BCM2709_PERIPHERAL_BASE; - } else if (rpi_version == LINUX_BOARD_TYPE::RPI_4) { - peripheral_base = Address::BCM2711_PERIPHERAL_BASE; - } else { - AP_HAL::panic("Unknown rpi_version, cannot locate peripheral base address"); - return; - } - - if (!openMemoryDevice()) { - AP_HAL::panic("Failed to initialize memory device."); - return; - } - - const uint32_t gpio_address = get_address(peripheral_base, PeripheralOffset::GPIO); - - _gpio = get_memory_pointer(gpio_address, _gpio_registers_memory_range); - if (!_gpio) { - AP_HAL::panic("Failed to get GPIO memory map."); + switch (rpi_version) { + case LINUX_BOARD_TYPE::RPI_ZERO_1: + case LINUX_BOARD_TYPE::RPI_2_3_ZERO2: + case LINUX_BOARD_TYPE::RPI_4: + gpioDriver = new GPIO_RPI_BCM(); + gpioDriver->init(); + break; + case LINUX_BOARD_TYPE::RPI_5: + gpioDriver = new GPIO_RPI_RP1(); + gpioDriver->init(); + break; + default: + AP_HAL::panic("Unknown rpi_version, cannot locate peripheral base address"); + return; } - - // No need to keep mem_fd open after mmap - closeMemoryDevice(); } void GPIO_RPI::pinMode(uint8_t pin, uint8_t output) { - if (output == HAL_GPIO_INPUT) { - set_gpio_mode_in(pin); - } else { - set_gpio_mode_in(pin); - set_gpio_mode_out(pin); - } + gpioDriver->pinMode(pin, output); } void GPIO_RPI::pinMode(uint8_t pin, uint8_t output, uint8_t alt) { - if (output == HAL_GPIO_INPUT) { - set_gpio_mode_in(pin); - } else if (output == HAL_GPIO_ALT) { - set_gpio_mode_in(pin); - set_gpio_mode_alt(pin, alt); - } else { - set_gpio_mode_in(pin); - set_gpio_mode_out(pin); - } + gpioDriver->pinMode(pin, output, alt); } uint8_t GPIO_RPI::read(uint8_t pin) { - if (pin >= GPIO_RPI_MAX_NUMBER_PINS) { - return 0; - } - return static_cast(get_gpio_logic_state(pin)); + return gpioDriver->read(pin); } void GPIO_RPI::write(uint8_t pin, uint8_t value) { - if (value != 0) { - set_gpio_high(pin); - } else { - set_gpio_low(pin); - } + gpioDriver->write(pin, value); } void GPIO_RPI::toggle(uint8_t pin) { - if (pin >= GPIO_RPI_MAX_NUMBER_PINS) { - return ; - } - uint32_t flag = (1 << pin); - _gpio_output_port_status ^= flag; - write(pin, (_gpio_output_port_status & flag) >> pin); + gpioDriver->toggle(pin); } /* Alternative interface: */ diff --git a/libraries/AP_HAL_Linux/GPIO_RPI.h b/libraries/AP_HAL_Linux/GPIO_RPI.h index f694dce679041a..ac934a42ef8418 100644 --- a/libraries/AP_HAL_Linux/GPIO_RPI.h +++ b/libraries/AP_HAL_Linux/GPIO_RPI.h @@ -2,6 +2,7 @@ #include #include "AP_HAL_Linux.h" +#include "GPIO_RPI_HAL.h" /** * @brief Check for valid Raspberry Pi pin range @@ -15,13 +16,12 @@ template constexpr uint8_t RPI_GPIO_() return pin; } + namespace Linux { /** * @brief Class for Raspberry PI GPIO control * - * For more information: https://elinux.org/RPi_BCM2835_GPIOs - * */ class GPIO_RPI : public AP_HAL::GPIO { public: @@ -40,161 +40,7 @@ class GPIO_RPI : public AP_HAL::GPIO { bool usb_connected(void) override; private: - // Raspberry Pi BASE memory address - enum class Address : uint32_t { - BCM2708_PERIPHERAL_BASE = 0x20000000, // Raspberry Pi 0/1 - BCM2709_PERIPHERAL_BASE = 0x3F000000, // Raspberry Pi 2/3 - BCM2711_PERIPHERAL_BASE = 0xFE000000, // Raspberry Pi 4 - }; - - // Offset between peripheral base address - enum class PeripheralOffset : uint32_t { - GPIO = 0x200000, - }; - - /** - * @brief Open memory device to allow gpio address access - * Should be used before get_memory_pointer calls in the initialization - * - * @return true - * @return false - */ - bool openMemoryDevice(); - - /** - * @brief Close open memory device - * - */ - void closeMemoryDevice(); - - /** - * @brief Return pointer to memory location with specific range access - * - * @param address - * @param range - * @return volatile uint32_t* - */ - volatile uint32_t* get_memory_pointer(uint32_t address, uint32_t range) const; - - /** - * @brief Get memory address based in base address and peripheral offset - * - * @param address - * @param offset - * @return uint32_t - */ - uint32_t get_address(GPIO_RPI::Address address, GPIO_RPI::PeripheralOffset offset) const; - - /** - * @brief Change functionality of GPIO Function Select Registers (GPFSELn) to any alternative function. - * Each GPIO pin is mapped to 3 bits inside a 32 bits register, E.g: - * - * 0b00...'010'101 - * ││ │││ ││└── GPIO Pin N, 1st bit, LSBit - * ││ │││ │└─── GPIO Pin N, 2nd bit - * ││ │││ └──── GPIO Pin N, 3rd bit, MSBit - * ││ ││└────── GPIO Pin N+1, 1st bit, LSBit - * ││ │└─────── GPIO Pin N+1, 2nd bit, - * ││ └──────── GPIO Pin N+1, 3rd bit, MSBit - * ││ ... - * │└───────────── Reserved - * └────────────── Reserved - * - * And the value of this 3 bits selects the functionality of the GPIO pin, E.g: - * 000 = GPIO Pin N is an input - * 001 = GPIO Pin N is an output - * 100 = GPIO Pin N takes alternate function 0 - * 101 = GPIO Pin N takes alternate function 1 - * 110 = GPIO Pin N takes alternate function 2 - * 111 = GPIO Pin N takes alternate function 3 - * 011 = GPIO Pin N takes alternate function 4 - * 010 = GPIO Pin N takes alternate function 5 - * - * The alternative functions are defined in the BCM datasheet under "Alternative Function" - * section for each pin. - * - * This information is also valid for: - * - Linux::GPIO_RPI::set_gpio_mode_in - * - Linux::GPIO_RPI::set_gpio_mode_out - * - * @param pin - */ - void set_gpio_mode_alt(int pin, int alternative); - - /** - * @brief Set a specific GPIO as input - * Check Linux::GPIO_RPI::set_gpio_mode_alt for more information. - * - * @param pin - */ - void set_gpio_mode_in(int pin); - - /** - * @brief Set a specific GPIO as output - * Check Linux::GPIO_RPI::set_gpio_mode_alt for more information. - * - * @param pin - */ - void set_gpio_mode_out(int pin); - - /** - * @brief Modify GPSET0 (GPIO Pin Output Set 0) register to set pin as high - * Writing zero to this register has no effect, please use Linux::GPIO_RPI::set_gpio_low - * to set pin as low. - * - * GPSET0 is a 32bits register that each bit points to a respective GPIO pin: - * 0b...101 - * ││└── GPIO Pin 1, 1st bit, LSBit, defined as High - * │└─── GPIO Pin 2, 2nd bit, No effect - * └──── GPIO Pin 3, 3rd bit, defined as High - * ... - * - * @param pin - */ - void set_gpio_high(int pin); - - /** - * @brief Modify GPCLR0 (GPIO Pin Output Clear 0) register to set pin as low - * Writing zero to this register has no effect, please use Linux::GPIO_RPI::set_gpio_high - * to set pin as high. - * - * GPCLR0 is a 32bits register that each bit points to a respective GPIO pin: - * 0b...101 - * ││└── GPIO Pin 1, 1st bit, LSBit, defined as Low - * │└─── GPIO Pin 2, 2nd bit, No effect - * └──── GPIO Pin 3, 3rd bit, defined as Low - * - * @param pin - */ - void set_gpio_low(int pin); - - /** - * @brief Read GPLEV0 (GPIO Pin Level 0) register check the logic state of a specific pin - * - * GPLEV0 is a 32bits register that each bit points to a respective GPIO pin: - * 0b...101 - * ││└── GPIO Pin 1, 1st bit, LSBit, Pin is in High state - * │└─── GPIO Pin 2, 2nd bit, Pin is in Low state - * └──── GPIO Pin 3, 3rd bit, Pin is in High state - * - * @param pin - * @return true - * @return false - */ - bool get_gpio_logic_state(int pin); - - // Memory pointer to gpio registers - volatile uint32_t* _gpio; - // Memory range for the gpio registers - static const uint8_t _gpio_registers_memory_range; - // Path to memory device (E.g: /dev/mem) - static const char* _system_memory_device_path; - // File descriptor for the memory device file - // If it's negative, then there was an error opening the file. - int _system_memory_device; - // store GPIO output status. - uint32_t _gpio_output_port_status = 0x00; - + GPIO_RPI_HAL* gpioDriver; }; } diff --git a/libraries/AP_HAL_Linux/GPIO_RPI_BCM.cpp b/libraries/AP_HAL_Linux/GPIO_RPI_BCM.cpp new file mode 100644 index 00000000000000..38f20237ff55e7 --- /dev/null +++ b/libraries/AP_HAL_Linux/GPIO_RPI_BCM.cpp @@ -0,0 +1,241 @@ +#include + +#include +#include +#include +#include +#include + +#include "GPIO.h" +#include "Util_RPI.h" +#include "GPIO_RPI_BCM.h" + +#define GPIO_RPI_MAX_NUMBER_PINS 32 + +using namespace Linux; + +extern const AP_HAL::HAL& hal; + +// Range based in the first memory address of the first register and the last memory addres +// for the GPIO section (0x7E20'00B4 - 0x7E20'0000). +const uint8_t GPIO_RPI_BCM::_gpio_registers_memory_range = 0xB4; +const char* GPIO_RPI_BCM::_system_memory_device_path = "/dev/mem"; + +GPIO_RPI_BCM::GPIO_RPI_BCM() +{ +} + +void GPIO_RPI_BCM::set_gpio_mode_alt(int pin, int alternative) +{ + // Each register can contain 10 pins + const uint8_t pins_per_register = 10; + // Calculates the position of the 3 bit mask in the 32 bits register + const uint8_t tree_bits_position_in_register = (pin%pins_per_register)*3; + /** Creates a mask to enable the alternative function based in the following logic: + * + * | Alternative Function | 3 bits value | + * |:--------------------:|:------------:| + * | Function 0 | 0b100 | + * | Function 1 | 0b101 | + * | Function 2 | 0b110 | + * | Function 3 | 0b111 | + * | Function 4 | 0b011 | + * | Function 5 | 0b010 | + */ + const uint8_t alternative_value = + (alternative < 4 ? (alternative + 4) : (alternative == 4 ? 3 : 2)); + // 0b00'000'000'000'000'000'000'ALT'000'000'000 enables alternative for the 4th pin + const uint32_t mask_with_alt = static_cast(alternative_value) << tree_bits_position_in_register; + const uint32_t mask = 0b111 << tree_bits_position_in_register; + // Clear all bits in our position and apply our mask with alt values + uint32_t register_value = _gpio[pin / pins_per_register]; + register_value &= ~mask; + _gpio[pin / pins_per_register] = register_value | mask_with_alt; +} + +void GPIO_RPI_BCM::set_gpio_mode_in(int pin) +{ + // Each register can contain 10 pins + const uint8_t pins_per_register = 10; + // Calculates the position of the 3 bit mask in the 32 bits register + const uint8_t tree_bits_position_in_register = (pin%pins_per_register)*3; + // Create a mask that only removes the bits in this specific GPIO pin, E.g: + // 0b11'111'111'111'111'111'111'000'111'111'111 for the 4th pin + const uint32_t mask = ~(0b111<(address) + static_cast(offset); +} + +volatile uint32_t* GPIO_RPI_BCM::get_memory_pointer(uint32_t address, uint32_t range) const +{ + auto pointer = mmap( + nullptr, // Any adddress in our space will do + range, // Map length + PROT_READ|PROT_WRITE|PROT_EXEC, // Enable reading & writing to mapped memory + MAP_SHARED|MAP_LOCKED, // Shared with other processes + _system_memory_device, // File to map + address // Offset to GPIO peripheral + ); + + if (pointer == MAP_FAILED) { + return nullptr; + } + + return static_cast(pointer); +} + +bool GPIO_RPI_BCM::openMemoryDevice() +{ + _system_memory_device = open(_system_memory_device_path, O_RDWR|O_SYNC|O_CLOEXEC); + if (_system_memory_device < 0) { + AP_HAL::panic("Can't open %s", GPIO_RPI_BCM::_system_memory_device_path); + return false; + } + + return true; +} + +void GPIO_RPI_BCM::closeMemoryDevice() +{ + close(_system_memory_device); + // Invalidate device variable + _system_memory_device = -1; +} + +void GPIO_RPI_BCM::init() +{ + const LINUX_BOARD_TYPE rpi_version = UtilRPI::from(hal.util)->detect_linux_board_type(); + + GPIO_RPI_BCM::Address peripheral_base; + if(rpi_version == LINUX_BOARD_TYPE::RPI_ZERO_1) { + peripheral_base = Address::BCM2708_PERIPHERAL_BASE; + } else if (rpi_version == LINUX_BOARD_TYPE::RPI_2_3_ZERO2) { + peripheral_base = Address::BCM2709_PERIPHERAL_BASE; + } else if (rpi_version == LINUX_BOARD_TYPE::RPI_4) { + peripheral_base = Address::BCM2711_PERIPHERAL_BASE; + } else { + AP_HAL::panic("Unknown rpi_version, cannot locate peripheral base address"); + return; + } + + if (!openMemoryDevice()) { + AP_HAL::panic("Failed to initialize memory device."); + return; + } + + const uint32_t gpio_address = get_address(peripheral_base, PeripheralOffset::GPIO); + + _gpio = get_memory_pointer(gpio_address, _gpio_registers_memory_range); + if (!_gpio) { + AP_HAL::panic("Failed to get GPIO memory map."); + } + + // No need to keep mem_fd open after mmap + closeMemoryDevice(); +} + +void GPIO_RPI_BCM::pinMode(uint8_t pin, uint8_t output) +{ + if (output == HAL_GPIO_INPUT) { + set_gpio_mode_in(pin); + } else { + set_gpio_mode_in(pin); + set_gpio_mode_out(pin); + } +} + +void GPIO_RPI_BCM::pinMode(uint8_t pin, uint8_t output, uint8_t alt) +{ + if (output == HAL_GPIO_INPUT) { + set_gpio_mode_in(pin); + } else if (output == HAL_GPIO_ALT) { + set_gpio_mode_in(pin); + set_gpio_mode_alt(pin, alt); + } else { + set_gpio_mode_in(pin); + set_gpio_mode_out(pin); + } +} + +uint8_t GPIO_RPI_BCM::read(uint8_t pin) +{ + if (pin >= GPIO_RPI_MAX_NUMBER_PINS) { + return 0; + } + return static_cast(get_gpio_logic_state(pin)); +} + +void GPIO_RPI_BCM::write(uint8_t pin, uint8_t value) +{ + if (value != 0) { + set_gpio_high(pin); + } else { + set_gpio_low(pin); + } +} + +void GPIO_RPI_BCM::toggle(uint8_t pin) +{ + if (pin >= GPIO_RPI_MAX_NUMBER_PINS) { + return ; + } + uint32_t flag = (1 << pin); + _gpio_output_port_status ^= flag; + write(pin, (_gpio_output_port_status & flag) >> pin); +} + +/* Alternative interface: */ +AP_HAL::DigitalSource* GPIO_RPI_BCM::channel(uint16_t n) +{ + return new DigitalSource(n); +} + +bool GPIO_RPI_BCM::usb_connected(void) +{ + return false; +} diff --git a/libraries/AP_HAL_Linux/GPIO_RPI_BCM.h b/libraries/AP_HAL_Linux/GPIO_RPI_BCM.h new file mode 100644 index 00000000000000..f0bf6c293bfd74 --- /dev/null +++ b/libraries/AP_HAL_Linux/GPIO_RPI_BCM.h @@ -0,0 +1,188 @@ +#pragma once + +#include +#include "GPIO_RPI_HAL.h" + +namespace Linux { + +/** + * @brief Class for Raspberry PI GPIO control + * + * For more information: https://elinux.org/RPi_BCM2835_GPIOs + * + */ +class GPIO_RPI_BCM : public GPIO_RPI_HAL { +public: + GPIO_RPI_BCM(); + void init() override; + void pinMode(uint8_t pin, uint8_t output) override; + void pinMode(uint8_t pin, uint8_t output, uint8_t alt) override; + uint8_t read(uint8_t pin) override; + void write(uint8_t pin, uint8_t value) override; + void toggle(uint8_t pin) override; + + /* Alternative interface: */ + AP_HAL::DigitalSource* channel(uint16_t n); + + /* return true if USB cable is connected */ + bool usb_connected(void); + +private: + // Raspberry Pi BASE memory address + enum class Address : uint32_t { + BCM2708_PERIPHERAL_BASE = 0x20000000, // Raspberry Pi 0/1 + BCM2709_PERIPHERAL_BASE = 0x3F000000, // Raspberry Pi 2/3 + BCM2711_PERIPHERAL_BASE = 0xFE000000, // Raspberry Pi 4 + }; + + // Offset between peripheral base address + enum class PeripheralOffset : uint32_t { + GPIO = 0x200000, + }; + + /** + * @brief Open memory device to allow gpio address access + * Should be used before get_memory_pointer calls in the initialization + * + * @return true + * @return false + */ + bool openMemoryDevice(); + + /** + * @brief Close open memory device + * + */ + void closeMemoryDevice(); + + /** + * @brief Return pointer to memory location with specific range access + * + * @param address + * @param range + * @return volatile uint32_t* + */ + volatile uint32_t* get_memory_pointer(uint32_t address, uint32_t range) const; + + /** + * @brief Get memory address based in base address and peripheral offset + * + * @param address + * @param offset + * @return uint32_t + */ + uint32_t get_address(GPIO_RPI_BCM::Address address, GPIO_RPI_BCM::PeripheralOffset offset) const; + + /** + * @brief Change functionality of GPIO Function Select Registers (GPFSELn) to any alternative function. + * Each GPIO pin is mapped to 3 bits inside a 32 bits register, E.g: + * + * 0b00...'010'101 + * ││ │││ ││└── GPIO Pin N, 1st bit, LSBit + * ││ │││ │└─── GPIO Pin N, 2nd bit + * ││ │││ └──── GPIO Pin N, 3rd bit, MSBit + * ││ ││└────── GPIO Pin N+1, 1st bit, LSBit + * ││ │└─────── GPIO Pin N+1, 2nd bit, + * ││ └──────── GPIO Pin N+1, 3rd bit, MSBit + * ││ ... + * │└───────────── Reserved + * └────────────── Reserved + * + * And the value of this 3 bits selects the functionality of the GPIO pin, E.g: + * 000 = GPIO Pin N is an input + * 001 = GPIO Pin N is an output + * 100 = GPIO Pin N takes alternate function 0 + * 101 = GPIO Pin N takes alternate function 1 + * 110 = GPIO Pin N takes alternate function 2 + * 111 = GPIO Pin N takes alternate function 3 + * 011 = GPIO Pin N takes alternate function 4 + * 010 = GPIO Pin N takes alternate function 5 + * + * The alternative functions are defined in the BCM datasheet under "Alternative Function" + * section for each pin. + * + * This information is also valid for: + * - Linux::GPIO_RPI_BCM::set_gpio_mode_in + * - Linux::GPIO_RPI_BCM::set_gpio_mode_out + * + * @param pin + */ + void set_gpio_mode_alt(int pin, int alternative); + + /** + * @brief Set a specific GPIO as input + * Check Linux::GPIO_RPI_BCM::set_gpio_mode_alt for more information. + * + * @param pin + */ + void set_gpio_mode_in(int pin); + + /** + * @brief Set a specific GPIO as output + * Check Linux::GPIO_RPI_BCM::set_gpio_mode_alt for more information. + * + * @param pin + */ + void set_gpio_mode_out(int pin); + + /** + * @brief Modify GPSET0 (GPIO Pin Output Set 0) register to set pin as high + * Writing zero to this register has no effect, please use Linux::GPIO_RPI_BCM::set_gpio_low + * to set pin as low. + * + * GPSET0 is a 32bits register that each bit points to a respective GPIO pin: + * 0b...101 + * ││└── GPIO Pin 1, 1st bit, LSBit, defined as High + * │└─── GPIO Pin 2, 2nd bit, No effect + * └──── GPIO Pin 3, 3rd bit, defined as High + * ... + * + * @param pin + */ + void set_gpio_high(int pin); + + /** + * @brief Modify GPCLR0 (GPIO Pin Output Clear 0) register to set pin as low + * Writing zero to this register has no effect, please use Linux::GPIO_RPI_BCM::set_gpio_high + * to set pin as high. + * + * GPCLR0 is a 32bits register that each bit points to a respective GPIO pin: + * 0b...101 + * ││└── GPIO Pin 1, 1st bit, LSBit, defined as Low + * │└─── GPIO Pin 2, 2nd bit, No effect + * └──── GPIO Pin 3, 3rd bit, defined as Low + * + * @param pin + */ + void set_gpio_low(int pin); + + /** + * @brief Read GPLEV0 (GPIO Pin Level 0) register check the logic state of a specific pin + * + * GPLEV0 is a 32bits register that each bit points to a respective GPIO pin: + * 0b...101 + * ││└── GPIO Pin 1, 1st bit, LSBit, Pin is in High state + * │└─── GPIO Pin 2, 2nd bit, Pin is in Low state + * └──── GPIO Pin 3, 3rd bit, Pin is in High state + * + * @param pin + * @return true + * @return false + */ + bool get_gpio_logic_state(int pin); + + // Memory pointer to gpio registers + volatile uint32_t* _gpio; + // Memory range for the gpio registers + static const uint8_t _gpio_registers_memory_range; + // Path to memory device (E.g: /dev/mem) + static const char* _system_memory_device_path; + // File descriptor for the memory device file + // If it's negative, then there was an error opening the file. + int _system_memory_device; + // store GPIO output status. + uint32_t _gpio_output_port_status = 0x00; + +}; + +} diff --git a/libraries/AP_HAL_Linux/GPIO_RPI_HAL.h b/libraries/AP_HAL_Linux/GPIO_RPI_HAL.h new file mode 100644 index 00000000000000..7cec066a94340d --- /dev/null +++ b/libraries/AP_HAL_Linux/GPIO_RPI_HAL.h @@ -0,0 +1,13 @@ +#pragma once + +class GPIO_RPI_HAL { +public: + GPIO_RPI_HAL() {} + virtual void init() = 0; + virtual void pinMode(uint8_t pin, uint8_t output) = 0; + virtual void pinMode(uint8_t pin, uint8_t output, uint8_t alt) {}; + + virtual uint8_t read(uint8_t pin) = 0; + virtual void write(uint8_t pin, uint8_t value) = 0; + virtual void toggle(uint8_t pin) = 0; +}; diff --git a/libraries/AP_HAL_Linux/GPIO_RPI_RP1.cpp b/libraries/AP_HAL_Linux/GPIO_RPI_RP1.cpp new file mode 100644 index 00000000000000..bef2897ba430d2 --- /dev/null +++ b/libraries/AP_HAL_Linux/GPIO_RPI_RP1.cpp @@ -0,0 +1,178 @@ +#include + +#include "GPIO_RPI_RP1.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace Linux; + +using namespace AP_HAL; + +GPIO_RPI_RP1::GPIO_RPI_RP1() { +} + +bool GPIO_RPI_RP1::openMemoryDevice() { + _system_memory_device = open(PATH_DEV_GPIOMEM, O_RDWR | O_SYNC | O_CLOEXEC); + if (_system_memory_device < 0) { + AP_HAL::panic("Can't open %s", PATH_DEV_GPIOMEM); + return false; + } + return true; +} + +void GPIO_RPI_RP1::closeMemoryDevice() { + close(_system_memory_device); + _system_memory_device = -1; +} + +volatile uint32_t* GPIO_RPI_RP1::get_memory_pointer(uint32_t address, uint32_t length) const { + auto pointer = mmap( + nullptr, + length, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_SHARED | MAP_LOCKED, // Shared with other processes + _system_memory_device, // File to map + address // Offset to GPIO peripheral + ); + + if (pointer == MAP_FAILED) { + return nullptr; + } + + return static_cast(pointer); +} + +void GPIO_RPI_RP1::init() { + if (!openMemoryDevice()) { + AP_HAL::panic("Failed to initialize memory device."); + return; + } + + _gpio = get_memory_pointer(IO_BANK0_OFFSET, MEM_SIZE); + if (!_gpio) { + AP_HAL::panic("Failed to get GPIO memory map."); + } + + closeMemoryDevice(); +} + +uint32_t GPIO_RPI_RP1::read_register(uint32_t offset) const { + return _gpio[offset]; +} + +void GPIO_RPI_RP1::write_register(uint32_t offset, uint32_t value) { + _gpio[offset] = value; +} + +GPIO_RPI_RP1::Mode GPIO_RPI_RP1::direction(uint8_t pin) const { + uint32_t offset = (SYS_RIO0_OFFSET + RIO_OE) / REG_SIZE; + uint32_t value = (read_register(offset) >> pin) & 0b1; + return value > 0 ? Mode::Output : Mode::Input; +} + +void GPIO_RPI_RP1::set_direction(uint8_t pin, Mode mode) { + uint32_t offset = (SYS_RIO0_OFFSET + RIO_OE) / REG_SIZE; + offset += (mode == Mode::Output ? SET_OFFSET : CLR_OFFSET) / REG_SIZE; + write_register(offset, 1 << pin); +} + +void GPIO_RPI_RP1::input_enable(uint8_t pin) { + uint32_t offset = (PADS_BANK0_OFFSET + PADS_GPIO + pin * PADS_OFFSET + SET_OFFSET) / REG_SIZE; + write_register(offset, PADS_IN_ENABLE_MASK); +} + +void GPIO_RPI_RP1::input_disable(uint8_t pin) { + uint32_t offset = (PADS_BANK0_OFFSET + PADS_GPIO + pin * PADS_OFFSET + CLR_OFFSET) / REG_SIZE; + write_register(offset, PADS_IN_ENABLE_MASK); +} + +void GPIO_RPI_RP1::output_enable(uint8_t pin) { + uint32_t offset = (PADS_BANK0_OFFSET + PADS_GPIO + pin * PADS_OFFSET + CLR_OFFSET) / REG_SIZE; + write_register(offset, PADS_OUT_DISABLE_MASK); +} + +void GPIO_RPI_RP1::output_disable(uint8_t pin) { + uint32_t offset = (PADS_BANK0_OFFSET + PADS_GPIO + pin * PADS_OFFSET + SET_OFFSET) / REG_SIZE; + write_register(offset, PADS_OUT_DISABLE_MASK); +} + +void GPIO_RPI_RP1::pinMode(uint8_t pin, uint8_t mode) { + if (mode == HAL_GPIO_INPUT) { + input_enable(pin); + set_direction(pin, Mode::Input); + set_mode(pin, Mode::Input); + } else if (mode == HAL_GPIO_OUTPUT) { + output_enable(pin); + set_direction(pin, Mode::Output); + set_mode(pin, Mode::Input); + } +} + +void GPIO_RPI_RP1::pinMode(uint8_t pin, uint8_t mode, uint8_t alt) { + if (mode == HAL_GPIO_ALT) { + set_mode(pin, static_cast(alt)); + return; + } + pinMode(pin, mode); +} + +void GPIO_RPI_RP1::set_mode(uint8_t pin, Mode mode) { + FunctionSelect alt_value; + + switch (mode) { + // ALT5 is used for GPIO, check datasheet pinout alternative functions + case Mode::Alt5: + case Mode::Input: + case Mode::Output: + alt_value = FunctionSelect::Alt5; + break; + case Mode::Alt0: alt_value = FunctionSelect::Alt0; break; + case Mode::Alt1: alt_value = FunctionSelect::Alt1; break; + case Mode::Alt2: alt_value = FunctionSelect::Alt2; break; + case Mode::Alt3: alt_value = FunctionSelect::Alt3; break; + case Mode::Alt4: alt_value = FunctionSelect::Alt4; break; + case Mode::Alt6: alt_value = FunctionSelect::Alt6; break; + case Mode::Alt7: alt_value = FunctionSelect::Alt7; break; + case Mode::Alt8: alt_value = FunctionSelect::Alt8; break; + default: alt_value = FunctionSelect::Null; break; + } + + uint32_t ctrl_offset = (IO_BANK0_OFFSET + GPIO_CTRL + (pin * GPIO_OFFSET) + RW_OFFSET) / REG_SIZE; + uint32_t reg_val = read_register(ctrl_offset); + reg_val &= ~CTRL_FUNCSEL_MASK; // Clear existing function select bits + reg_val |= (static_cast(alt_value) << CTRL_FUNCSEL_LSB); + write_register(ctrl_offset, reg_val); + +} + +void GPIO_RPI_RP1::set_pull(uint8_t pin, PadsPull mode) { + uint32_t pads_offset = (PADS_BANK0_OFFSET + PADS_GPIO + (pin * PADS_OFFSET) + RW_OFFSET) / REG_SIZE; + uint32_t reg_val = read_register(pads_offset); + reg_val &= ~PADS_PULL_MASK; // Clear existing bias bits + reg_val |= (static_cast(mode) << PADS_PULL_LSB); + write_register(pads_offset, reg_val); +} + +uint8_t GPIO_RPI_RP1::read(uint8_t pin) { + uint32_t in_offset = (SYS_RIO0_OFFSET + RIO_IN) / REG_SIZE; + uint32_t reg_val = read_register(in_offset); + return (reg_val >> pin) & 0x1; +} + +void GPIO_RPI_RP1::write(uint8_t pin, uint8_t value) { + uint32_t register_offset = value ? SET_OFFSET : CLR_OFFSET; + uint32_t offset = (SYS_RIO0_OFFSET + RIO_OUT + register_offset) / REG_SIZE; + write_register(offset, 1 << pin); +} + +void GPIO_RPI_RP1::toggle(uint8_t pin) { + uint32_t flag = (1 << pin); + _gpio_output_port_status ^= flag; + write(pin, (_gpio_output_port_status & flag) >> pin); +} diff --git a/libraries/AP_HAL_Linux/GPIO_RPI_RP1.h b/libraries/AP_HAL_Linux/GPIO_RPI_RP1.h new file mode 100644 index 00000000000000..8ea1f342fd4c1d --- /dev/null +++ b/libraries/AP_HAL_Linux/GPIO_RPI_RP1.h @@ -0,0 +1,169 @@ +#pragma once + +#include +#include "GPIO_RPI_HAL.h" + +namespace Linux { + +/** + * @brief Class for Raspberry PI 5 GPIO control + * + * For more information: + * - RP1 datasheet: https://datasheets.raspberrypi.com/rp1/rp1-peripherals.pdf + * - gpiomem0: https://github.com/raspberrypi/linux/blob/1e53604087930e7cf42eee3d42572d0d6f54c86a/arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi#L178 + * - Address: 0x400d'0000, Size: 0x3'0000 + * + */ +class GPIO_RPI_RP1 : public GPIO_RPI_HAL { +public: + GPIO_RPI_RP1(); + void init() override; + void pinMode(uint8_t pin, uint8_t mode) override; + void pinMode(uint8_t pin, uint8_t mode, uint8_t alt) override; + + uint8_t read(uint8_t pin) override; + void write(uint8_t pin, uint8_t value) override; + void toggle(uint8_t pin) override; + + enum class PadsPull : uint8_t { + Off = 0, + Down = 1, + Up = 2, + }; + + void set_pull(uint8_t pin, PadsPull mode); + +private: + // gpiomem0 already maps the 0x400d'0000 address for us + static constexpr const char* PATH_DEV_GPIOMEM = "/dev/gpiomem0"; + static constexpr uint32_t MEM_SIZE = 0x30000; + static constexpr uint32_t REG_SIZE = sizeof(uint32_t); + + // Register offsets from RP1 datasheet 'Table 2. Peripheral Address Map' + // E.g: + // - IO_BANK0_OFFSET: 0x0'0000 result in 0x400d'0000 + // - SYS_RIO0_OFFSET: 0x1'0000 result in 0x400e'0000 + // ... + static constexpr uint32_t IO_BANK0_OFFSET = 0x00000; + static constexpr uint32_t SYS_RIO0_OFFSET = 0x10000; + static constexpr uint32_t PADS_BANK0_OFFSET = 0x20000; + + // GPIO control from https://github.com/raspberrypi/linux/blob/21012295fe87a7ccc1c356d1e268fd289aafbad1/drivers/pinctrl/pinctrl-rp1.c + static constexpr uint32_t RIO_OUT = 0x00; + static constexpr uint32_t RIO_OE = 0x04; + static constexpr uint32_t RIO_IN = 0x08; + + // GPIO control from '2.4. Atomic register access' + static constexpr uint32_t RW_OFFSET = 0x0000; + static constexpr uint32_t XOR_OFFSET = 0x1000; + static constexpr uint32_t SET_OFFSET = 0x2000; + static constexpr uint32_t CLR_OFFSET = 0x3000; + + static constexpr uint32_t GPIO_CTRL = 0x0004; + static constexpr uint32_t GPIO_OFFSET = 8; + + static constexpr uint32_t PADS_GPIO = 0x04; + static constexpr uint32_t PADS_OFFSET = 4; + + /** + * GPIO control from 'Table 8. GPI0_CTRL, GPI1_CTRL, ...' + * + * 0b0000'0000'0000'0000'0000'0000'0001'1101 + * ├┘│├─┘├┘├─┘├┘├─┘├┘├─┘├┘│ ├──────┘└────┴─ Bits 4:0 FUNCSEL: Function select + * │ ││ │ │ │ │ │ │ │ │ └────────────── Bits 11:5 F_M: Filter/debounce time constant M + * │ ││ │ │ │ │ │ │ │ └──────────────── Bits 13:12 OUTOVER: Output control + * │ ││ │ │ │ │ │ │ └────────────────── Bits 15:14 OEOVER: Output enable control + * │ ││ │ │ │ │ │ └───────────────────── Bits 17:16 INOVER: Input control + * │ ││ │ │ │ │ └─────────────────────── Bits 19:18 Reserved + * │ ││ │ │ │ └────────────────────────── Bits 20:21 IRQMASK_EDGE_LOW/HIGH + * │ ││ │ │ └──────────────────────────── Bits 22:23 IRQMASK_LEVEL_LOW/HIGH + * │ ││ │ └─────────────────────────────── Bits 24:25 IRQMASK_F_EDGE_LOW/HIGH + * │ ││ └───────────────────────────────── Bits 26:27 IRQMASK_DB_LEVEL_LOW/HIGH + * │ │└──────────────────────────────────── Bit 28 IRQRESET: Interrupt edge detector reset + * │ └───────────────────────────────────── Bit 29 Reserved + * └─────────────────────────────────────── Bits 31:30 IRQOVER: Interrupt control + */ + static constexpr uint32_t CTRL_FUNCSEL_MASK = 0x001f; + static constexpr uint32_t CTRL_FUNCSEL_LSB = 0; + static constexpr uint32_t CTRL_OUTOVER_MASK = 0x3000; + static constexpr uint32_t CTRL_OUTOVER_LSB = 12; + static constexpr uint32_t CTRL_OEOVER_MASK = 0xc000; + static constexpr uint32_t CTRL_OEOVER_LSB = 14; + static constexpr uint32_t CTRL_INOVER_MASK = 0x30000; + static constexpr uint32_t CTRL_INOVER_LSB = 16; + static constexpr uint32_t CTRL_IRQOVER_MASK = 0xc0000000; + static constexpr uint32_t CTRL_IRQOVER_LSB = 30; + + /** + * Mask for PADS_BANK control from 'Table 21.' + * + * 0b0...001'1101 + * ├──┘││├─┘││└─ Bit 1 SLEWFAST: Slew rate control. 1 = Fast, 0 = Slow + * │ │││ │└── Bit 2 SCHMITT: Enable schmitt trigger + * │ │││ └─── Bit 3 PDE: Pull down enable + * │ ││└────── Bits 4:5 DRIVE: Drive strength + * │ │└─────── Bit 6 IE: Input enable + * │ └──────── Bit 7 OD: Output disable. Has priority over output enable from + * └──────────── Bits 31:8 Reserved + */ + static constexpr uint32_t PADS_IN_ENABLE_MASK = 0x40; + static constexpr uint32_t PADS_OUT_DISABLE_MASK = 0x80; + static constexpr uint32_t PADS_PULL_MASK = 0x0c; + static constexpr uint32_t PADS_PULL_LSB = 2; + + enum class FunctionSelect : uint8_t { + Alt0 = 0, + Alt1 = 1, + Alt2 = 2, + Alt3 = 3, + Alt4 = 4, + Alt5 = 5, + Alt6 = 6, + Alt7 = 7, + Alt8 = 8, + Null = 31 + }; + + enum Mode { + Input, + Output, + Alt0, + Alt1, + Alt2, + Alt3, + Alt4, + Alt5, + Alt6, + Alt7, + Alt8, + Null + }; + + enum Bias { + Off, + PullDown, + PullUp + }; + + volatile uint32_t* _gpio; + int _system_memory_device; + uint32_t _gpio_output_port_status = 0; + + bool openMemoryDevice(); + void closeMemoryDevice(); + volatile uint32_t* get_memory_pointer(uint32_t address, uint32_t range) const; + + uint32_t read_register(uint32_t offset) const; + void write_register(uint32_t offset, uint32_t value); + + Mode direction(uint8_t pin) const; + void set_direction(uint8_t pin, Mode mode); + void input_enable(uint8_t pin); + void input_disable(uint8_t pin); + void output_enable(uint8_t pin); + void output_disable(uint8_t pin); + + void set_mode(uint8_t pin, Mode mode); +}; + +} diff --git a/libraries/AP_HAL_Linux/Util_RPI.cpp b/libraries/AP_HAL_Linux/Util_RPI.cpp index 9f464374d7c191..f39606675e77f7 100644 --- a/libraries/AP_HAL_Linux/Util_RPI.cpp +++ b/libraries/AP_HAL_Linux/Util_RPI.cpp @@ -62,25 +62,29 @@ void UtilRPI::_get_board_type_using_peripheral_base() _linux_board_version = LINUX_BOARD_TYPE::UNKNOWN_BOARD; printf("Cannot detect board-type \r\n"); break; + case 0x10: + _linux_board_version = LINUX_BOARD_TYPE::RPI_5; + printf("RPI 5 \r\n"); + break; case 0x20000000: _linux_board_version = LINUX_BOARD_TYPE::RPI_ZERO_1; printf("RPI Zero / 1 \r\n"); - printf("Peripheral base address is %x\n", base); break; case 0x3f000000: _linux_board_version = LINUX_BOARD_TYPE::RPI_2_3_ZERO2; printf("RPI 2, 3 or Zero-2 \r\n"); - printf("Peripheral base address is %x\n", base); break; case 0xfe000000: _linux_board_version = LINUX_BOARD_TYPE::RPI_4; printf("RPI 4 \r\n"); - printf("Peripheral base address is %x\n", base); break; case 0x40000000: _linux_board_version = LINUX_BOARD_TYPE::ALLWINNWER_H616; printf("AllWinner-H616 \r\n"); break; + default: + printf("Unknown board \n\r"); + printf("Peripheral base address is %x\n", base); } return ; diff --git a/libraries/AP_HAL_Linux/Util_RPI.h b/libraries/AP_HAL_Linux/Util_RPI.h index 67a6fc8ead44fe..4aa3427dca88fc 100644 --- a/libraries/AP_HAL_Linux/Util_RPI.h +++ b/libraries/AP_HAL_Linux/Util_RPI.h @@ -8,6 +8,7 @@ enum class LINUX_BOARD_TYPE: int { RPI_ZERO_1=0, RPI_2_3_ZERO2=1, RPI_4=2, + RPI_5=3, ALLWINNWER_H616=100, UNKNOWN_BOARD=999 }; diff --git a/libraries/AP_RangeFinder/AP_RangeFinder_Lua.cpp b/libraries/AP_RangeFinder/AP_RangeFinder_Lua.cpp index 75e22b2aaba5f4..9d5facdb5af91a 100644 --- a/libraries/AP_RangeFinder/AP_RangeFinder_Lua.cpp +++ b/libraries/AP_RangeFinder/AP_RangeFinder_Lua.cpp @@ -48,16 +48,11 @@ bool AP_RangeFinder_Lua::handle_script_msg(float dist_m) { WITH_SEMAPHORE(_sem); - // Time out on incoming data; if we don't get new data in 500ms, dump it - if (now - _state_pending.last_reading_ms > AP_RANGEFINDER_LUA_TIMEOUT_MS) { - set_status(_state_pending, RangeFinder::Status::NoData); - } else { - _state_pending.last_reading_ms = now; - _state_pending.distance_m = dist_m; - _state_pending.signal_quality_pct = RangeFinder::SIGNAL_QUALITY_UNKNOWN; - _state_pending.voltage_mv = 0; - update_status(_state_pending); - } + _state_pending.last_reading_ms = now; + _state_pending.distance_m = dist_m; + _state_pending.signal_quality_pct = RangeFinder::SIGNAL_QUALITY_UNKNOWN; + _state_pending.voltage_mv = 0; + update_status(_state_pending); return true; } @@ -66,6 +61,12 @@ bool AP_RangeFinder_Lua::handle_script_msg(float dist_m) { void AP_RangeFinder_Lua::update(void) { WITH_SEMAPHORE(_sem); + + // Time out on incoming data + if (_state_pending.status != RangeFinder::Status::NotConnected && + AP_HAL::millis() - _state_pending.last_reading_ms > AP_RANGEFINDER_LUA_TIMEOUT_MS) { + set_status(_state_pending, RangeFinder::Status::NoData); + } state = _state_pending; } diff --git a/libraries/GCS_MAVLink/MissionItemProtocol.cpp b/libraries/GCS_MAVLink/MissionItemProtocol.cpp index d29faaa7f6e8a9..4e0ba9d16bc542 100644 --- a/libraries/GCS_MAVLink/MissionItemProtocol.cpp +++ b/libraries/GCS_MAVLink/MissionItemProtocol.cpp @@ -73,6 +73,8 @@ void MissionItemProtocol::handle_mission_count( // the upload count may have changed; free resources and // allocate them again: free_upload_resources(); + receiving = false; + link = nullptr; } if (packet.count > max_items()) { diff --git a/libraries/SITL/SIM_GPS.cpp b/libraries/SITL/SIM_GPS.cpp index 38735248d97e2d..15eafb90b01c08 100644 --- a/libraries/SITL/SIM_GPS.cpp +++ b/libraries/SITL/SIM_GPS.cpp @@ -462,10 +462,9 @@ GPS_Data GPS::interpolate_data(const GPS_Data &d, uint32_t delay_ms) return _gps_history[N-1]; } -float GPS_Data::heading() const +float GPS_Data::ground_track_rad() const { - const auto velocity = Vector2d{speedE, speedN}; - return velocity.angle(); + return atan2f(speedE, speedN); } float GPS_Data::speed_2d() const diff --git a/libraries/SITL/SIM_GPS.h b/libraries/SITL/SIM_GPS.h index f92375f55844a4..954bbd45acef34 100644 --- a/libraries/SITL/SIM_GPS.h +++ b/libraries/SITL/SIM_GPS.h @@ -49,8 +49,9 @@ struct GPS_Data { float speed_acc; uint8_t num_sats; - // Get heading [rad], where 0 = North in WGS-84 coordinate system - float heading() const WARN_IF_UNUSED; + // Get course over ground [rad], where 0 = North in WGS-84 coordinate system. + // Calculated from 2D velocity. + float ground_track_rad() const WARN_IF_UNUSED; // Get 2D speed [m/s] in WGS-84 coordinate system float speed_2d() const WARN_IF_UNUSED; diff --git a/libraries/SITL/SIM_GPS_NMEA.cpp b/libraries/SITL/SIM_GPS_NMEA.cpp index c4b16b89da44fd..bda820cabfbddf 100644 --- a/libraries/SITL/SIM_GPS_NMEA.cpp +++ b/libraries/SITL/SIM_GPS_NMEA.cpp @@ -79,13 +79,13 @@ void GPS_NMEA::publish(const GPS_Data *d) const float speed_mps = d->speed_2d(); const float speed_knots = speed_mps * M_PER_SEC_TO_KNOTS; - const auto heading_rad = d->heading(); + const auto ground_track_deg = degrees(d->ground_track_rad()); //$GPVTG,133.18,T,120.79,M,0.11,N,0.20,K,A*24 nmea_printf("$GPVTG,%.2f,T,%.2f,M,%.2f,N,%.2f,K,A", tstring, - heading_rad, - heading_rad, + ground_track_deg, + ground_track_deg, speed_knots, speed_knots * KNOTS_TO_METERS_PER_SECOND * 3.6); @@ -95,7 +95,7 @@ void GPS_NMEA::publish(const GPS_Data *d) lat_string, lng_string, speed_knots, - heading_rad, + ground_track_deg, dstring); if (_sitl->gps_hdg_enabled[instance] == SITL::SIM::GPS_HEADING_HDT) { @@ -112,7 +112,7 @@ void GPS_NMEA::publish(const GPS_Data *d) d->altitude, wrap_360(d->yaw_deg), d->pitch_deg, - heading_rad, + ground_track_deg, speed_mps, d->roll_deg, d->have_lock?1:0, // 2=rtkfloat 3=rtkfixed, diff --git a/libraries/SITL/SIM_GPS_Trimble.cpp b/libraries/SITL/SIM_GPS_Trimble.cpp index 1e1726b33376ba..9bb3edd541eac0 100644 --- a/libraries/SITL/SIM_GPS_Trimble.cpp +++ b/libraries/SITL/SIM_GPS_Trimble.cpp @@ -175,7 +175,7 @@ void GPS_Trimble::publish(const GPS_Data *d) GSOF_VEL_LEN, vel_flags, gsof_pack_float(d->speed_2d()), - gsof_pack_float(d->heading()), + gsof_pack_float(d->ground_track_rad()), // Trimble API has ambiguous direction here. // Intentionally narrow from double. gsof_pack_float(static_cast(d->speedD))