From nobody Sat Jan 28 14:58:40 2023 X-Original-To: freebsd-arm@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4P3yJm4s8xz3b2rH for ; Sat, 28 Jan 2023 14:59:20 +0000 (UTC) (envelope-from karl@denninger.net) Received: from colo1.denninger.net (colo1.denninger.net [104.236.120.189]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4P3yJl6bxHz3sb2 for ; Sat, 28 Jan 2023 14:59:19 +0000 (UTC) (envelope-from karl@denninger.net) Authentication-Results: mx1.freebsd.org; dkim=none; spf=pass (mx1.freebsd.org: domain of karl@denninger.net designates 104.236.120.189 as permitted sender) smtp.mailfrom=karl@denninger.net; dmarc=pass (policy=none) header.from=denninger.net Received: from denninger.net (097-081-026-048.res.spectrum.com [97.81.26.48]) by colo1.denninger.net (Postfix) with ESMTP id 3B0492110C9 for ; Sat, 28 Jan 2023 09:58:43 -0500 (EST) Received: from [192.168.10.25] (D15.Denninger.Net [192.168.10.25]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by denninger.net (Postfix) with ESMTPSA id CAAEB1D1E9F for ; Sat, 28 Jan 2023 09:58:42 -0500 (EST) Message-ID: <5b816cb7-5c65-bbc3-ac14-bb3bcf078175@denninger.net> Date: Sat, 28 Jan 2023 09:58:40 -0500 List-Id: Porting FreeBSD to ARM processors List-Archive: https://lists.freebsd.org/archives/freebsd-arm List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-freebsd-arm@freebsd.org MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.6.1 Subject: Re: GPIO inputs on Pis? Content-Language: en-US To: freebsd-arm@freebsd.org References: <0b235f83-7cb3-1d14-7c64-aee7c1c0c23d@denninger.net> <01070185e46b1a6e-ee34b885-1215-45c7-ac18-83320c02cac2-000000@eu-central-1.amazonses.com> <01070185e4732fd8-c0bede0b-d9df-4557-a174-cb237fa4bfaf-000000@eu-central-1.amazonses.com> <01070185e534f221-14f362b5-2b96-43f0-b0b0-f496ad9994fe-000000@eu-central-1.amazonses.com> <1cd552a7-b015-c935-06fc-9f12e1b37daa@denninger.net> <01070185ec3ff177-a3ef6a92-17ae-4b94-819b-c86b90ebb681-000000@eu-central-1.amazonses.com> From: Karl Denninger In-Reply-To: <01070185ec3ff177-a3ef6a92-17ae-4b94-819b-c86b90ebb681-000000@eu-central-1.amazonses.com> Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-512; boundary="------------ms060401080303050203050306" X-Spamd-Result: default: False [-4.13 / 15.00]; SIGNED_SMIME(-2.00)[]; SUBJECT_ENDS_QUESTION(1.00)[]; NEURAL_HAM_MEDIUM(-1.00)[-1.000]; NEURAL_HAM_LONG(-1.00)[-1.000]; DMARC_POLICY_ALLOW(-0.50)[denninger.net,none]; NEURAL_HAM_SHORT(-0.23)[-0.229]; MIME_GOOD(-0.20)[multipart/signed,multipart/alternative,text/plain]; R_SPF_ALLOW(-0.20)[+mx]; ARC_NA(0.00)[]; ASN(0.00)[asn:14061, ipnet:104.236.64.0/18, country:US]; MLMMJ_DEST(0.00)[freebsd-arm@freebsd.org]; R_DKIM_NA(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; RCVD_COUNT_THREE(0.00)[3]; RCVD_TLS_LAST(0.00)[]; RCPT_COUNT_ONE(0.00)[1]; FROM_HAS_DN(0.00)[]; FREEFALL_USER(0.00)[karl]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+,1:+,2:+,3:~,4:~]; TO_MATCH_ENVRCPT_ALL(0.00)[]; PREVIOUSLY_DELIVERED(0.00)[freebsd-arm@freebsd.org]; HAS_ATTACHMENT(0.00)[]; TO_DN_NONE(0.00)[]; MID_RHS_MATCH_FROM(0.00)[] X-Rspamd-Queue-Id: 4P3yJl6bxHz3sb2 X-Spamd-Bar: ---- X-ThisMailContainsUnwantedMimeParts: N This is a cryptographically signed message in MIME format. --------------ms060401080303050203050306 Content-Type: multipart/alternative; boundary="------------6X6bDqpDPj0DJmDVneqyOCYF" --------------6X6bDqpDPj0DJmDVneqyOCYF Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 1/25/2023 23:04, Dr. Rolf Jansen wrote: >> Am 25.01.2023 um 13:45 schrieb Karl Denninger: >> >> On 1/24/2023 14:15, Dr. Rolf Jansen wrote: >>> Yes, and for this reason, this GPIO event code which was developed by Christian Krämer in the course of the GSoC-2018 and has been submitted in 2020 by Ian Lepore to the freebsd tree is perfect. >>> >>> Ian tested it with a 10 MHz sqaure wave on an imx6 (ARMv7, 1GHz) and got an event every 10 µs. That means the max. speed without event losses would be 100 kHz. I did not do exact measurements, however, my impression is that my RPi4B can do it a tad faster than my BeagleBone Black. With the RPi4, I needed to improve the debouncing of the encoder and the buttons, because it saw hundreds of bounces which the BBB didn’t. However, it may also be, that the internal GPIO circuits of the BBB have a different damping characteristic. >>> >>> Anyway for my applications, 100 kHz way faster than what I need. >>> >>> On my GitHub repository I placed another example on using the GPIO events for the RPi: >>> >>> https://github.com/cyclaero/shutdd >>> >>> See also the respective thread on this mailing list: >>> >>> https://lists.freebsd.org/archives/freebsd-arm/2022-July/001576.html >> So..... just to see if I'm understanding this correctly (pretty sure I am having read through the test code). >> >> Presume I have "X" pins configured as inputs and "Y" configured as outputs. I use the ioctl calls to set the outputs (which works just fine) and can read current input state (which also works.) >> >> If I set on the same descriptor (not on the specific pins; it applies to all input pins on that descriptor as it appears there's no pin-specific setting in the configuration flags to enable this on a pin-by-pin basis) the event report config type I want I can then select() on the descriptor with the usual timeouts (or zero for a poll) and get a "ready" (much as one would for any other sort of I/O) and, if I do get a "ready" return on the descriptor a read() on that descriptor will return zero or more structures of the type I said I configured, each of which describes either an individual state change on one of configured input pins that is set up for individual event reporting OR a structure of the summary of changes for a given pin. >> > My understanding of what you wrote above sounds correct. However, I don’t use select(), since I am very comfortable with calling a blocking read() from a loop in a pthread. The advantage with this is, that there is almost no time gap in the user land between reading of the events. Below comes an example It does indeed work "as-expected" from my testing; this is a welcome addition that I did not realize was there (when I originally started working with this stuff it wasn't in the kernel, materially before the ARM code was considered Tier 1.) BTW one warning which might be worthy of at least a note in the man page -- if you enable reporting but do not assign any pins to have interrupts enabled you will get a "ready for read" immediately on a poll or select, but an attempt to read the descriptor comes back with ENXIO. IMHO a select() or poll() should not return a ready state for reads unless it really is ready to be read (it would be ok to return a "ready on error/exception" of course; I haven't checked that.)  The man page is too sparse to know if this is intended behavior or a bug against which perhaps I should file a PR. I also generated a panic in the provided test code on the Pi3 by setting nonblocking and using select.  Unfortunately I do not have a crash dump from it as it occurred on an embedded test board. Thanks. -- Karl Denninger karl@denninger.net /The Market Ticker/ /[S/MIME encrypted email preferred]/ --------------6X6bDqpDPj0DJmDVneqyOCYF Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit
On 1/25/2023 23:04, Dr. Rolf Jansen wrote:
Am 25.01.2023 um 13:45 schrieb Karl Denninger <karl@denninger.net>:

On 1/24/2023 14:15, Dr. Rolf Jansen wrote:
Yes, and for this reason, this GPIO event code which was developed by Christian Krämer in the course of the GSoC-2018 and has been submitted in 2020 by Ian Lepore to the freebsd tree is perfect.

Ian tested it with a 10 MHz sqaure wave on an imx6 (ARMv7, 1GHz) and got an event every 10 µs. That means the max. speed without event losses would be 100 kHz. I did not do exact measurements, however, my impression is that my RPi4B can do it a tad faster than my BeagleBone Black. With the RPi4, I needed to improve the debouncing of the encoder and the buttons, because it saw hundreds of bounces which the BBB didn’t. However, it may also be, that the internal GPIO circuits of the BBB have a different damping characteristic.

Anyway for my applications, 100 kHz way faster than what I need.

On my GitHub repository I placed another example on using the GPIO events for the RPi:

https://github.com/cyclaero/shutdd

See also the respective thread on this mailing list:

https://lists.freebsd.org/archives/freebsd-arm/2022-July/001576.html
So..... just to see  if I'm understanding this correctly (pretty sure I am having read through the test code).

Presume I have "X" pins configured as inputs and "Y" configured as outputs.  I use the ioctl calls to set the outputs (which works just fine) and can read current input state (which also works.)

If I set on the same descriptor (not on the specific pins; it applies to all input pins on that descriptor as it appears there's no pin-specific setting in the configuration flags to enable this on a pin-by-pin basis) the event report config type I want I can then select() on the descriptor with the usual timeouts (or zero for a poll) and get a "ready" (much as one would for any other sort of I/O) and, if I do get a "ready" return on the descriptor a read() on that descriptor will return zero or more structures of the type I said I configured, each of which describes either an individual state change on one of configured input pins that is set up for individual event reporting OR a structure of the summary of changes for a given pin.

My understanding of what you wrote above sounds correct. However, I don’t use select(), since I am very comfortable with calling a blocking read() from a loop in a pthread. The advantage with this is, that there is almost no time gap in the user land between reading of the events. Below comes an example

It does indeed work "as-expected" from my testing; this is a welcome addition that I did not realize was there (when I originally started working with this stuff it wasn't in the kernel, materially before the ARM code was considered Tier 1.)

BTW one warning which might be worthy of at least a note in the man page -- if you enable reporting but do not assign any pins to have interrupts enabled you will get a "ready for read" immediately on a poll or select, but an attempt to read the descriptor comes back with ENXIO. 

IMHO a select() or poll() should not return a ready state for reads unless it really is ready to be read (it would be ok to return a "ready on error/exception" of course; I haven't checked that.)  The man page is too sparse to know if this is intended behavior or a bug against which perhaps I should file a PR.

I also generated a panic in the provided test code on the Pi3 by setting nonblocking and using select.  Unfortunately I do not have a crash dump from it as it occurred on an embedded test board.

Thanks.

--
Karl Denninger
karl@denninger.net
The Market Ticker
[S/MIME encrypted email preferred]
--------------6X6bDqpDPj0DJmDVneqyOCYF-- --------------ms060401080303050203050306 Content-Type: application/pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" Content-Description: S/MIME Cryptographic Signature MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQMEAgMFADCABgkqhkiG9w0BBwEAAKCC DbowggagMIIEiKADAgECAhMA5EiKghDOXrvfxYxjITXYDdhIMA0GCSqGSIb3DQEBCwUAMIGL MQswCQYDVQQGEwJVUzEQMA4GA1UECAwHRmxvcmlkYTESMBAGA1UEBwwJTmljZXZpbGxlMRkw FwYDVQQKDBBDdWRhIFN5c3RlbXMgTExDMRgwFgYDVQQLDA9DdWRhIFN5c3RlbXMgQ0ExITAf BgNVBAMMGEN1ZGEgU3lzdGVtcyBMTEMgMjAxNyBDQTAeFw0xNzA4MTcxNjQyMTdaFw0yNzA4 MTUxNjQyMTdaMHsxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdGbG9yaWRhMRkwFwYDVQQKDBBD dWRhIFN5c3RlbXMgTExDMRgwFgYDVQQLDA9DdWRhIFN5c3RlbXMgQ0ExJTAjBgNVBAMMHEN1 ZGEgU3lzdGVtcyBMTEMgMjAxNyBJbnQgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK AoICAQC1aJotNUI+W4jP7xQDO8L/b4XiF4Rss9O0B+3vMH7Njk85fZ052QhZpMVlpaaO+sCI KqG3oNEbuOHzJB/NDJFnqh7ijBwhdWutdsq23Ux6TvxgakyMPpT6TRNEJzcBVQA0kpby1DVD 0EKSK/FrWWBiFmSxg7qUfmIq/mMzgE6epHktyRM3OGq3dbRdOUgfumWrqHXOrdJz06xE9NzY vc9toqZnd79FUtE/nSZVm1VS3Grq7RKV65onvX3QOW4W1ldEHwggaZxgWGNiR/D4eosAGFxn uYeWlKEC70c99Mp1giWux+7ur6hc2E+AaTGh+fGeijO5q40OGd+dNMgK8Es0nDRw81lRcl24 SWUEky9y8DArgIFlRd6d3ZYwgc1DMTWkTavx3ZpASp5TWih6yI8ACwboTvlUYeooMsPtNa9E 6UQ1nt7VEi5syjxnDltbEFoLYcXBcqhRhFETJe9CdenItAHAtOya3w5+fmC2j/xJz29og1KH YqWHlo3Kswi9G77an+zh6nWkMuHs+03DU8DaOEWzZEav3lVD4u76bKRDTbhh0bMAk4eXriGL h4MUoX3Imfcr6JoyheVrAdHDL/BixbMH1UUspeRuqQMQ5b2T6pabXP0oOB4FqldWiDgJBGRd zWLgCYG8wPGJGYgHibl5rFiI5Ix3FQncipc6SdUzOQIDAQABo4IBCjCCAQYwHQYDVR0OBBYE FF3AXsKnjdPND5+bxVECGKtc047PMIHABgNVHSMEgbgwgbWAFBu1oRhUMNEzjODolDka5k4Q EDBioYGRpIGOMIGLMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHRmxvcmlkYTESMBAGA1UEBwwJ TmljZXZpbGxlMRkwFwYDVQQKDBBDdWRhIFN5c3RlbXMgTExDMRgwFgYDVQQLDA9DdWRhIFN5 c3RlbXMgQ0ExITAfBgNVBAMMGEN1ZGEgU3lzdGVtcyBMTEMgMjAxNyBDQYIJAKxAy1WBo2kY MBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IC AQCB5686UCBVIT52jO3sz9pKuhxuC2npi8ZvoBwt/IH9piPA15/CGF1XeXUdu2qmhOjHkVLN gO7XB1G8CuluxofOIUce0aZGyB+vZ1ylHXlMeB0R82f5dz3/T7RQso55Y2Vog2Zb7PYTC5B9 oNy3ylsnNLzanYlcW3AAfzZcbxYuAdnuq0Im3EpGm8DoItUcf1pDezugKm/yKtNtY6sDyENj tExZ377cYA3IdIwqn1Mh4OAT/Rmh8au2rZAo0+bMYBy9C11Ex0hQ8zWcvPZBDn4v4RtO8g+K uQZQcJnO09LJNtw94W3d2mj4a7XrsKMnZKvm6W9BJIQ4Nmht4wXAtPQ1xA+QpxPTmsGAU0Cv HmqVC7XC3qxFhaOrD2dsvOAK6Sn3MEpH/YrfYCX7a7cz5zW3DsJQ6o3pYfnnQz+hnwLlz4MK 17NIA0WOdAF9IbtQqarf44+PEyUbKtz1r0KGeGLs+VGdd2FLA0e7yuzxJDYcaBTVwqaHhU2/ Fna/jGU7BhrKHtJbb/XlLeFJ24yvuiYKpYWQSSyZu1R/gvZjHeGb344jGBsZdCDrdxtQQcVA 6OxsMAPSUPMrlg9LWELEEYnVulQJerWxpUecGH92O06wwmPgykkz//UmmgjVSh7ErNvL0lUY UMfunYVO/O5hwhW+P4gviCXzBFeTtDZH259O7TCCBxIwggT6oAMCAQICEgLG8yH4PQFdbd9x Ugmpzl1jXzANBgkqhkiG9w0BAQsFADB7MQswCQYDVQQGEwJVUzEQMA4GA1UECAwHRmxvcmlk YTEZMBcGA1UECgwQQ3VkYSBTeXN0ZW1zIExMQzEYMBYGA1UECwwPQ3VkYSBTeXN0ZW1zIENB MSUwIwYDVQQDDBxDdWRhIFN5c3RlbXMgTExDIDIwMTcgSW50IENBMB4XDTIyMDYyOTE2MTYz NloXDTI3MDYyODE2MTYzNlowOjELMAkGA1UEBhMCVVMxEjAQBgNVBAgMCVRlbm5lc3NlZTEX MBUGA1UEAwwOS2FybCBEZW5uaW5nZXIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC AQC+HVSyxVtJhy3Ohs+PAGRuO//Dha9A16l5FPATr6wude9zjX5f2lrkRyU8vhCXTZW7WbvW ZKpcZ8r0dtZmiK9uF58Ec6hhvfkxJzbg96WHBw5Fumd5ahZzuCJDtCAWW8R7/KN+zwzQf1+B 3MVLmbaXAFBuKzySKhKMcHbK3/wjUYTgy+3UK6v2SBrowvkUBC+jxNg3Wy12GsTXcUS/8FYI XgVVPgfZZrbJJb5HWOQpvvhILpPCD3xsYJFNKEPltXKWHT7Qtc2HNqikgNwj8oqOb+PeZGMi WapsatKm8mxuOOGOEBhAoTVTwUHlMNTg6QUCJtuWFCK38qOCyk9Haj+86lUU8RG6FkRXWgMb NQm1mWREQhw3axgGLSntjjnznJr5vsvXSYR6c+XKLd5KQZcS6LL8FHYNjqVKHBYM+hDnrTZM qa20JLAF1YagutDiMRURU23iWS7bA9tMcXcqkclTSDtFtxahRifXRI7Epq2GSKuEXe/1Tfb5 CE8QsbCpGsfSwv2tZ/SpqVG08MdRiXxN5tmZiQWo15IyWoeKOXl/hKxA9KPuDHngXX022b1l y+5ZOZbxBAZZMod4y4b4FiRUhRI97r9lCxsP/EPHuuTIZ82BYhrhbtab8HuRo2ofne2TfAWY 2BlA7ExM8XShMd9bRPZrNTokPQPUCWCgCdIATQIDAQABo4IBzzCCAcswPAYIKwYBBQUHAQEE MDAuMCwGCCsGAQUFBzABhiBodHRwOi8vb2NzcC5jdWRhc3lzdGVtcy5uZXQ6ODg4ODAJBgNV HRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYwFAYI KwYBBQUHAwIGCCsGAQUFBwMEMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBD bGllbnQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFLElmNWeVgsBPe7O8NiBzjvjYnpRMIHKBgNV HSMEgcIwgb+AFF3AXsKnjdPND5+bxVECGKtc047PoYGRpIGOMIGLMQswCQYDVQQGEwJVUzEQ MA4GA1UECAwHRmxvcmlkYTESMBAGA1UEBwwJTmljZXZpbGxlMRkwFwYDVQQKDBBDdWRhIFN5 c3RlbXMgTExDMRgwFgYDVQQLDA9DdWRhIFN5c3RlbXMgQ0ExITAfBgNVBAMMGEN1ZGEgU3lz dGVtcyBMTEMgMjAxNyBDQYITAORIioIQzl6738WMYyE12A3YSDAdBgNVHREEFjAUgRJrYXJs QGRlbm5pbmdlci5uZXQwDQYJKoZIhvcNAQELBQADggIBAKquc7cu0xc8FNtAQauZvocDzWQj 7HG9YvMbWnMi+ckhiA3rdW5NwWg0HBhBho1YlnqV+ntCVE2L8ezohHWm+KAdfXgpraL86Vsn 3ywNlZu/3COMpo2ALuHln8YQtH3Y8ebvzKMdlf2b5WB+7mOFIxXIr4AnNOLKCkq5ZhzC6JW6 Jvw3P0csiGa3UrfatYID5NvPgkaQvEgimEjG3psZqwQTL2Wxohvw783PrDt3wS0XeNhvQ61g 3QJFZKuv+bmGH3YBSPo1t6NUGAr+JozX5lDihB8JGkBt/NwdYec49a08uL0BbPaAJ7NjuIPG 7Y0Ak7PXZT37yx/Zla9PzLMJFgbelOkaatdzbblMZPDEVZ27l4lGMmV83Lm3YP17sdAyS/Wp mav7WmJUkQ9iuIKzSpdc82i9Mfujl1vbBtwtkHNPPtKuulIFM4ZwrPKjlVdLqTSqD8m9yHEi Y0PuAooq63OpJWF6hvMaiIPBWEAVIaDW9uG0MshLl9DnHnMyrJTfuC33Z9mOGMz7dRBjJd5Y W02xAzYnUuEBOpj+LQv5R8XIFMHFXktqEKvQrXeM2RU+PcZqKOBkTktxBLn3NI5VfA15Jk0c 5V5XcOqo3p2hvrwvXrinrb2pEREnoqmfrkXT3zOq5Y6ryRH8u734lGEF0dILXzoV4PM7XFit oTePoEjmMYIFBDCCBQACAQEwgZEwezELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB0Zsb3JpZGEx GTAXBgNVBAoMEEN1ZGEgU3lzdGVtcyBMTEMxGDAWBgNVBAsMD0N1ZGEgU3lzdGVtcyBDQTEl MCMGA1UEAwwcQ3VkYSBTeXN0ZW1zIExMQyAyMDE3IEludCBDQQISAsbzIfg9AV1t33FSCanO XWNfMA0GCWCGSAFlAwQCAwUAoIICQzAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqG SIb3DQEJBTEPFw0yMzAxMjgxNDU4NDJaME8GCSqGSIb3DQEJBDFCBEC76ARfKEOzHT/ggGRx G6AREG1CZQacWSih79slavEM/bmgDxR3spKE4YWlWxvCfnjId9jXD7Akm5SyTYzN6C1pMGwG CSqGSIb3DQEJDzFfMF0wCwYJYIZIAWUDBAEqMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAO BggqhkiG9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgw gaIGCSsGAQQBgjcQBDGBlDCBkTB7MQswCQYDVQQGEwJVUzEQMA4GA1UECAwHRmxvcmlkYTEZ MBcGA1UECgwQQ3VkYSBTeXN0ZW1zIExMQzEYMBYGA1UECwwPQ3VkYSBTeXN0ZW1zIENBMSUw IwYDVQQDDBxDdWRhIFN5c3RlbXMgTExDIDIwMTcgSW50IENBAhICxvMh+D0BXW3fcVIJqc5d Y18wgaQGCyqGSIb3DQEJEAILMYGUoIGRMHsxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdGbG9y aWRhMRkwFwYDVQQKDBBDdWRhIFN5c3RlbXMgTExDMRgwFgYDVQQLDA9DdWRhIFN5c3RlbXMg Q0ExJTAjBgNVBAMMHEN1ZGEgU3lzdGVtcyBMTEMgMjAxNyBJbnQgQ0ECEgLG8yH4PQFdbd9x Ugmpzl1jXzANBgkqhkiG9w0BAQEFAASCAgCil3PFMXJD0g70e9ciADKq2+1JSM0qReWI2meJ eTUz+cTr1tvHEHsYsA/qMH0HagIXrED3GtAPs6qMZcxtZoyx4Wq7rFKCLFHoW467bpmV/bay RQTfHGWE7oXgMQaQrn5WTWEC98WKQcmyptMuMzXYRJFH4cErtpC701NuftWXsWFQ3QlIFJdV yoJu8Xp1zu14q9lW+1pEbLcvW0/NCQC9/ly0FOUcw+bAnCaimBE1GEDb+wz9Zs6SANdSHwYu TSUhr5GoYMw0b067uYUuiQsJE7ctSdQW8V0jCkykI3ly6lGaguduTgC4IToGcjS/nMgjjdJR OF0A/tpy/cUg2tWyQjEOfbQlKr1RjmKqqir12dKKRYkPQVdbJbXGdm+qclo/uBcZIEOxmBWx lin6vMhJ34AJ855mZQbAX3aUN/J36TDWOjKcJPMTHKiKmdgpwDMbwmJKD9WtPGRtKQpFRCT/ gjH2id/WTbos+dljn8zcvy2j8B/P3ncAznBAUiOwNiiQM/APPpikOmOhfeSnfSzT5TcZL51u tLJQKFkUb7Aet9x7iMUD2M+ishSVfvmisI1cAO5g7ZYOucql3A1MiDjS1Kxcr4HiiXUaUf8C QUk4JbY2JXD0cdVyP45huiNmQ1XNkFP161cMAkRNW6KEGIkXABeT96B642T9PyWIeAa5nQAA AAAAAA== --------------ms060401080303050203050306--