mirror of https://github.com/lumapu/ahoy.git
				
				
			
				 25 changed files with 1980 additions and 658 deletions
			
			
		@ -0,0 +1,437 @@ | 
				
			|||
Attribution-NonCommercial-ShareAlike 4.0 International | 
				
			|||
 | 
				
			|||
======================================================================= | 
				
			|||
 | 
				
			|||
Creative Commons Corporation ("Creative Commons") is not a law firm and | 
				
			|||
does not provide legal services or legal advice. Distribution of | 
				
			|||
Creative Commons public licenses does not create a lawyer-client or | 
				
			|||
other relationship. Creative Commons makes its licenses and related | 
				
			|||
information available on an "as-is" basis. Creative Commons gives no | 
				
			|||
warranties regarding its licenses, any material licensed under their | 
				
			|||
terms and conditions, or any related information. Creative Commons | 
				
			|||
disclaims all liability for damages resulting from their use to the | 
				
			|||
fullest extent possible. | 
				
			|||
 | 
				
			|||
Using Creative Commons Public Licenses | 
				
			|||
 | 
				
			|||
Creative Commons public licenses provide a standard set of terms and | 
				
			|||
conditions that creators and other rights holders may use to share | 
				
			|||
original works of authorship and other material subject to copyright | 
				
			|||
and certain other rights specified in the public license below. The | 
				
			|||
following considerations are for informational purposes only, are not | 
				
			|||
exhaustive, and do not form part of our licenses. | 
				
			|||
 | 
				
			|||
     Considerations for licensors: Our public licenses are | 
				
			|||
     intended for use by those authorized to give the public | 
				
			|||
     permission to use material in ways otherwise restricted by | 
				
			|||
     copyright and certain other rights. Our licenses are | 
				
			|||
     irrevocable. Licensors should read and understand the terms | 
				
			|||
     and conditions of the license they choose before applying it. | 
				
			|||
     Licensors should also secure all rights necessary before | 
				
			|||
     applying our licenses so that the public can reuse the | 
				
			|||
     material as expected. Licensors should clearly mark any | 
				
			|||
     material not subject to the license. This includes other CC- | 
				
			|||
     licensed material, or material used under an exception or | 
				
			|||
     limitation to copyright. More considerations for licensors: | 
				
			|||
    wiki.creativecommons.org/Considerations_for_licensors | 
				
			|||
 | 
				
			|||
     Considerations for the public: By using one of our public | 
				
			|||
     licenses, a licensor grants the public permission to use the | 
				
			|||
     licensed material under specified terms and conditions. If | 
				
			|||
     the licensor's permission is not necessary for any reason--for | 
				
			|||
     example, because of any applicable exception or limitation to | 
				
			|||
     copyright--then that use is not regulated by the license. Our | 
				
			|||
     licenses grant only permissions under copyright and certain | 
				
			|||
     other rights that a licensor has authority to grant. Use of | 
				
			|||
     the licensed material may still be restricted for other | 
				
			|||
     reasons, including because others have copyright or other | 
				
			|||
     rights in the material. A licensor may make special requests, | 
				
			|||
     such as asking that all changes be marked or described. | 
				
			|||
     Although not required by our licenses, you are encouraged to | 
				
			|||
     respect those requests where reasonable. More considerations | 
				
			|||
     for the public: | 
				
			|||
    wiki.creativecommons.org/Considerations_for_licensees | 
				
			|||
 | 
				
			|||
======================================================================= | 
				
			|||
 | 
				
			|||
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International | 
				
			|||
Public License | 
				
			|||
 | 
				
			|||
By exercising the Licensed Rights (defined below), You accept and agree | 
				
			|||
to be bound by the terms and conditions of this Creative Commons | 
				
			|||
Attribution-NonCommercial-ShareAlike 4.0 International Public License | 
				
			|||
("Public License"). To the extent this Public License may be | 
				
			|||
interpreted as a contract, You are granted the Licensed Rights in | 
				
			|||
consideration of Your acceptance of these terms and conditions, and the | 
				
			|||
Licensor grants You such rights in consideration of benefits the | 
				
			|||
Licensor receives from making the Licensed Material available under | 
				
			|||
these terms and conditions. | 
				
			|||
 | 
				
			|||
 | 
				
			|||
Section 1 -- Definitions. | 
				
			|||
 | 
				
			|||
  a. Adapted Material means material subject to Copyright and Similar | 
				
			|||
     Rights that is derived from or based upon the Licensed Material | 
				
			|||
     and in which the Licensed Material is translated, altered, | 
				
			|||
     arranged, transformed, or otherwise modified in a manner requiring | 
				
			|||
     permission under the Copyright and Similar Rights held by the | 
				
			|||
     Licensor. For purposes of this Public License, where the Licensed | 
				
			|||
     Material is a musical work, performance, or sound recording, | 
				
			|||
     Adapted Material is always produced where the Licensed Material is | 
				
			|||
     synched in timed relation with a moving image. | 
				
			|||
 | 
				
			|||
  b. Adapter's License means the license You apply to Your Copyright | 
				
			|||
     and Similar Rights in Your contributions to Adapted Material in | 
				
			|||
     accordance with the terms and conditions of this Public License. | 
				
			|||
 | 
				
			|||
  c. BY-NC-SA Compatible License means a license listed at | 
				
			|||
     creativecommons.org/compatiblelicenses, approved by Creative | 
				
			|||
     Commons as essentially the equivalent of this Public License. | 
				
			|||
 | 
				
			|||
  d. Copyright and Similar Rights means copyright and/or similar rights | 
				
			|||
     closely related to copyright including, without limitation, | 
				
			|||
     performance, broadcast, sound recording, and Sui Generis Database | 
				
			|||
     Rights, without regard to how the rights are labeled or | 
				
			|||
     categorized. For purposes of this Public License, the rights | 
				
			|||
     specified in Section 2(b)(1)-(2) are not Copyright and Similar | 
				
			|||
     Rights. | 
				
			|||
 | 
				
			|||
  e. Effective Technological Measures means those measures that, in the | 
				
			|||
     absence of proper authority, may not be circumvented under laws | 
				
			|||
     fulfilling obligations under Article 11 of the WIPO Copyright | 
				
			|||
     Treaty adopted on December 20, 1996, and/or similar international | 
				
			|||
     agreements. | 
				
			|||
 | 
				
			|||
  f. Exceptions and Limitations means fair use, fair dealing, and/or | 
				
			|||
     any other exception or limitation to Copyright and Similar Rights | 
				
			|||
     that applies to Your use of the Licensed Material. | 
				
			|||
 | 
				
			|||
  g. License Elements means the license attributes listed in the name | 
				
			|||
     of a Creative Commons Public License. The License Elements of this | 
				
			|||
     Public License are Attribution, NonCommercial, and ShareAlike. | 
				
			|||
 | 
				
			|||
  h. Licensed Material means the artistic or literary work, database, | 
				
			|||
     or other material to which the Licensor applied this Public | 
				
			|||
     License. | 
				
			|||
 | 
				
			|||
  i. Licensed Rights means the rights granted to You subject to the | 
				
			|||
     terms and conditions of this Public License, which are limited to | 
				
			|||
     all Copyright and Similar Rights that apply to Your use of the | 
				
			|||
     Licensed Material and that the Licensor has authority to license. | 
				
			|||
 | 
				
			|||
  j. Licensor means the individual(s) or entity(ies) granting rights | 
				
			|||
     under this Public License. | 
				
			|||
 | 
				
			|||
  k. NonCommercial means not primarily intended for or directed towards | 
				
			|||
     commercial advantage or monetary compensation. For purposes of | 
				
			|||
     this Public License, the exchange of the Licensed Material for | 
				
			|||
     other material subject to Copyright and Similar Rights by digital | 
				
			|||
     file-sharing or similar means is NonCommercial provided there is | 
				
			|||
     no payment of monetary compensation in connection with the | 
				
			|||
     exchange. | 
				
			|||
 | 
				
			|||
  l. Share means to provide material to the public by any means or | 
				
			|||
     process that requires permission under the Licensed Rights, such | 
				
			|||
     as reproduction, public display, public performance, distribution, | 
				
			|||
     dissemination, communication, or importation, and to make material | 
				
			|||
     available to the public including in ways that members of the | 
				
			|||
     public may access the material from a place and at a time | 
				
			|||
     individually chosen by them. | 
				
			|||
 | 
				
			|||
  m. Sui Generis Database Rights means rights other than copyright | 
				
			|||
     resulting from Directive 96/9/EC of the European Parliament and of | 
				
			|||
     the Council of 11 March 1996 on the legal protection of databases, | 
				
			|||
     as amended and/or succeeded, as well as other essentially | 
				
			|||
     equivalent rights anywhere in the world. | 
				
			|||
 | 
				
			|||
  n. You means the individual or entity exercising the Licensed Rights | 
				
			|||
     under this Public License. Your has a corresponding meaning. | 
				
			|||
 | 
				
			|||
 | 
				
			|||
Section 2 -- Scope. | 
				
			|||
 | 
				
			|||
  a. License grant. | 
				
			|||
 | 
				
			|||
       1. Subject to the terms and conditions of this Public License, | 
				
			|||
          the Licensor hereby grants You a worldwide, royalty-free, | 
				
			|||
          non-sublicensable, non-exclusive, irrevocable license to | 
				
			|||
          exercise the Licensed Rights in the Licensed Material to: | 
				
			|||
 | 
				
			|||
            a. reproduce and Share the Licensed Material, in whole or | 
				
			|||
               in part, for NonCommercial purposes only; and | 
				
			|||
 | 
				
			|||
            b. produce, reproduce, and Share Adapted Material for | 
				
			|||
               NonCommercial purposes only. | 
				
			|||
 | 
				
			|||
       2. Exceptions and Limitations. For the avoidance of doubt, where | 
				
			|||
          Exceptions and Limitations apply to Your use, this Public | 
				
			|||
          License does not apply, and You do not need to comply with | 
				
			|||
          its terms and conditions. | 
				
			|||
 | 
				
			|||
       3. Term. The term of this Public License is specified in Section | 
				
			|||
          6(a). | 
				
			|||
 | 
				
			|||
       4. Media and formats; technical modifications allowed. The | 
				
			|||
          Licensor authorizes You to exercise the Licensed Rights in | 
				
			|||
          all media and formats whether now known or hereafter created, | 
				
			|||
          and to make technical modifications necessary to do so. The | 
				
			|||
          Licensor waives and/or agrees not to assert any right or | 
				
			|||
          authority to forbid You from making technical modifications | 
				
			|||
          necessary to exercise the Licensed Rights, including | 
				
			|||
          technical modifications necessary to circumvent Effective | 
				
			|||
          Technological Measures. For purposes of this Public License, | 
				
			|||
          simply making modifications authorized by this Section 2(a) | 
				
			|||
          (4) never produces Adapted Material. | 
				
			|||
 | 
				
			|||
       5. Downstream recipients. | 
				
			|||
 | 
				
			|||
            a. Offer from the Licensor -- Licensed Material. Every | 
				
			|||
               recipient of the Licensed Material automatically | 
				
			|||
               receives an offer from the Licensor to exercise the | 
				
			|||
               Licensed Rights under the terms and conditions of this | 
				
			|||
               Public License. | 
				
			|||
 | 
				
			|||
            b. Additional offer from the Licensor -- Adapted Material. | 
				
			|||
               Every recipient of Adapted Material from You | 
				
			|||
               automatically receives an offer from the Licensor to | 
				
			|||
               exercise the Licensed Rights in the Adapted Material | 
				
			|||
               under the conditions of the Adapter's License You apply. | 
				
			|||
 | 
				
			|||
            c. No downstream restrictions. You may not offer or impose | 
				
			|||
               any additional or different terms or conditions on, or | 
				
			|||
               apply any Effective Technological Measures to, the | 
				
			|||
               Licensed Material if doing so restricts exercise of the | 
				
			|||
               Licensed Rights by any recipient of the Licensed | 
				
			|||
               Material. | 
				
			|||
 | 
				
			|||
       6. No endorsement. Nothing in this Public License constitutes or | 
				
			|||
          may be construed as permission to assert or imply that You | 
				
			|||
          are, or that Your use of the Licensed Material is, connected | 
				
			|||
          with, or sponsored, endorsed, or granted official status by, | 
				
			|||
          the Licensor or others designated to receive attribution as | 
				
			|||
          provided in Section 3(a)(1)(A)(i). | 
				
			|||
 | 
				
			|||
  b. Other rights. | 
				
			|||
 | 
				
			|||
       1. Moral rights, such as the right of integrity, are not | 
				
			|||
          licensed under this Public License, nor are publicity, | 
				
			|||
          privacy, and/or other similar personality rights; however, to | 
				
			|||
          the extent possible, the Licensor waives and/or agrees not to | 
				
			|||
          assert any such rights held by the Licensor to the limited | 
				
			|||
          extent necessary to allow You to exercise the Licensed | 
				
			|||
          Rights, but not otherwise. | 
				
			|||
 | 
				
			|||
       2. Patent and trademark rights are not licensed under this | 
				
			|||
          Public License. | 
				
			|||
 | 
				
			|||
       3. To the extent possible, the Licensor waives any right to | 
				
			|||
          collect royalties from You for the exercise of the Licensed | 
				
			|||
          Rights, whether directly or through a collecting society | 
				
			|||
          under any voluntary or waivable statutory or compulsory | 
				
			|||
          licensing scheme. In all other cases the Licensor expressly | 
				
			|||
          reserves any right to collect such royalties, including when | 
				
			|||
          the Licensed Material is used other than for NonCommercial | 
				
			|||
          purposes. | 
				
			|||
 | 
				
			|||
 | 
				
			|||
Section 3 -- License Conditions. | 
				
			|||
 | 
				
			|||
Your exercise of the Licensed Rights is expressly made subject to the | 
				
			|||
following conditions. | 
				
			|||
 | 
				
			|||
  a. Attribution. | 
				
			|||
 | 
				
			|||
       1. If You Share the Licensed Material (including in modified | 
				
			|||
          form), You must: | 
				
			|||
 | 
				
			|||
            a. retain the following if it is supplied by the Licensor | 
				
			|||
               with the Licensed Material: | 
				
			|||
 | 
				
			|||
                 i. identification of the creator(s) of the Licensed | 
				
			|||
                    Material and any others designated to receive | 
				
			|||
                    attribution, in any reasonable manner requested by | 
				
			|||
                    the Licensor (including by pseudonym if | 
				
			|||
                    designated); | 
				
			|||
 | 
				
			|||
                ii. a copyright notice; | 
				
			|||
 | 
				
			|||
               iii. a notice that refers to this Public License; | 
				
			|||
 | 
				
			|||
                iv. a notice that refers to the disclaimer of | 
				
			|||
                    warranties; | 
				
			|||
 | 
				
			|||
                 v. a URI or hyperlink to the Licensed Material to the | 
				
			|||
                    extent reasonably practicable; | 
				
			|||
 | 
				
			|||
            b. indicate if You modified the Licensed Material and | 
				
			|||
               retain an indication of any previous modifications; and | 
				
			|||
 | 
				
			|||
            c. indicate the Licensed Material is licensed under this | 
				
			|||
               Public License, and include the text of, or the URI or | 
				
			|||
               hyperlink to, this Public License. | 
				
			|||
 | 
				
			|||
       2. You may satisfy the conditions in Section 3(a)(1) in any | 
				
			|||
          reasonable manner based on the medium, means, and context in | 
				
			|||
          which You Share the Licensed Material. For example, it may be | 
				
			|||
          reasonable to satisfy the conditions by providing a URI or | 
				
			|||
          hyperlink to a resource that includes the required | 
				
			|||
          information. | 
				
			|||
       3. If requested by the Licensor, You must remove any of the | 
				
			|||
          information required by Section 3(a)(1)(A) to the extent | 
				
			|||
          reasonably practicable. | 
				
			|||
 | 
				
			|||
  b. ShareAlike. | 
				
			|||
 | 
				
			|||
     In addition to the conditions in Section 3(a), if You Share | 
				
			|||
     Adapted Material You produce, the following conditions also apply. | 
				
			|||
 | 
				
			|||
       1. The Adapter's License You apply must be a Creative Commons | 
				
			|||
          license with the same License Elements, this version or | 
				
			|||
          later, or a BY-NC-SA Compatible License. | 
				
			|||
 | 
				
			|||
       2. You must include the text of, or the URI or hyperlink to, the | 
				
			|||
          Adapter's License You apply. You may satisfy this condition | 
				
			|||
          in any reasonable manner based on the medium, means, and | 
				
			|||
          context in which You Share Adapted Material. | 
				
			|||
 | 
				
			|||
       3. You may not offer or impose any additional or different terms | 
				
			|||
          or conditions on, or apply any Effective Technological | 
				
			|||
          Measures to, Adapted Material that restrict exercise of the | 
				
			|||
          rights granted under the Adapter's License You apply. | 
				
			|||
 | 
				
			|||
 | 
				
			|||
Section 4 -- Sui Generis Database Rights. | 
				
			|||
 | 
				
			|||
Where the Licensed Rights include Sui Generis Database Rights that | 
				
			|||
apply to Your use of the Licensed Material: | 
				
			|||
 | 
				
			|||
  a. for the avoidance of doubt, Section 2(a)(1) grants You the right | 
				
			|||
     to extract, reuse, reproduce, and Share all or a substantial | 
				
			|||
     portion of the contents of the database for NonCommercial purposes | 
				
			|||
     only; | 
				
			|||
 | 
				
			|||
  b. if You include all or a substantial portion of the database | 
				
			|||
     contents in a database in which You have Sui Generis Database | 
				
			|||
     Rights, then the database in which You have Sui Generis Database | 
				
			|||
     Rights (but not its individual contents) is Adapted Material, | 
				
			|||
     including for purposes of Section 3(b); and | 
				
			|||
 | 
				
			|||
  c. You must comply with the conditions in Section 3(a) if You Share | 
				
			|||
     all or a substantial portion of the contents of the database. | 
				
			|||
 | 
				
			|||
For the avoidance of doubt, this Section 4 supplements and does not | 
				
			|||
replace Your obligations under this Public License where the Licensed | 
				
			|||
Rights include other Copyright and Similar Rights. | 
				
			|||
 | 
				
			|||
 | 
				
			|||
Section 5 -- Disclaimer of Warranties and Limitation of Liability. | 
				
			|||
 | 
				
			|||
  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE | 
				
			|||
     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS | 
				
			|||
     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF | 
				
			|||
     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, | 
				
			|||
     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, | 
				
			|||
     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR | 
				
			|||
     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, | 
				
			|||
     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT | 
				
			|||
     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT | 
				
			|||
     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. | 
				
			|||
 | 
				
			|||
  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE | 
				
			|||
     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, | 
				
			|||
     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, | 
				
			|||
     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, | 
				
			|||
     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR | 
				
			|||
     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN | 
				
			|||
     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR | 
				
			|||
     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR | 
				
			|||
     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. | 
				
			|||
 | 
				
			|||
  c. The disclaimer of warranties and limitation of liability provided | 
				
			|||
     above shall be interpreted in a manner that, to the extent | 
				
			|||
     possible, most closely approximates an absolute disclaimer and | 
				
			|||
     waiver of all liability. | 
				
			|||
 | 
				
			|||
 | 
				
			|||
Section 6 -- Term and Termination. | 
				
			|||
 | 
				
			|||
  a. This Public License applies for the term of the Copyright and | 
				
			|||
     Similar Rights licensed here. However, if You fail to comply with | 
				
			|||
     this Public License, then Your rights under this Public License | 
				
			|||
     terminate automatically. | 
				
			|||
 | 
				
			|||
  b. Where Your right to use the Licensed Material has terminated under | 
				
			|||
     Section 6(a), it reinstates: | 
				
			|||
 | 
				
			|||
       1. automatically as of the date the violation is cured, provided | 
				
			|||
          it is cured within 30 days of Your discovery of the | 
				
			|||
          violation; or | 
				
			|||
 | 
				
			|||
       2. upon express reinstatement by the Licensor. | 
				
			|||
 | 
				
			|||
     For the avoidance of doubt, this Section 6(b) does not affect any | 
				
			|||
     right the Licensor may have to seek remedies for Your violations | 
				
			|||
     of this Public License. | 
				
			|||
 | 
				
			|||
  c. For the avoidance of doubt, the Licensor may also offer the | 
				
			|||
     Licensed Material under separate terms or conditions or stop | 
				
			|||
     distributing the Licensed Material at any time; however, doing so | 
				
			|||
     will not terminate this Public License. | 
				
			|||
 | 
				
			|||
  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public | 
				
			|||
     License. | 
				
			|||
 | 
				
			|||
 | 
				
			|||
Section 7 -- Other Terms and Conditions. | 
				
			|||
 | 
				
			|||
  a. The Licensor shall not be bound by any additional or different | 
				
			|||
     terms or conditions communicated by You unless expressly agreed. | 
				
			|||
 | 
				
			|||
  b. Any arrangements, understandings, or agreements regarding the | 
				
			|||
     Licensed Material not stated herein are separate from and | 
				
			|||
     independent of the terms and conditions of this Public License. | 
				
			|||
 | 
				
			|||
 | 
				
			|||
Section 8 -- Interpretation. | 
				
			|||
 | 
				
			|||
  a. For the avoidance of doubt, this Public License does not, and | 
				
			|||
     shall not be interpreted to, reduce, limit, restrict, or impose | 
				
			|||
     conditions on any use of the Licensed Material that could lawfully | 
				
			|||
     be made without permission under this Public License. | 
				
			|||
 | 
				
			|||
  b. To the extent possible, if any provision of this Public License is | 
				
			|||
     deemed unenforceable, it shall be automatically reformed to the | 
				
			|||
     minimum extent necessary to make it enforceable. If the provision | 
				
			|||
     cannot be reformed, it shall be severed from this Public License | 
				
			|||
     without affecting the enforceability of the remaining terms and | 
				
			|||
     conditions. | 
				
			|||
 | 
				
			|||
  c. No term or condition of this Public License will be waived and no | 
				
			|||
     failure to comply consented to unless expressly agreed to by the | 
				
			|||
     Licensor. | 
				
			|||
 | 
				
			|||
  d. Nothing in this Public License constitutes or may be interpreted | 
				
			|||
     as a limitation upon, or waiver of, any privileges and immunities | 
				
			|||
     that apply to the Licensor or You, including from the legal | 
				
			|||
     processes of any jurisdiction or authority. | 
				
			|||
 | 
				
			|||
======================================================================= | 
				
			|||
 | 
				
			|||
Creative Commons is not a party to its public | 
				
			|||
licenses. Notwithstanding, Creative Commons may elect to apply one of | 
				
			|||
its public licenses to material it publishes and in those instances | 
				
			|||
will be considered the “Licensor.” The text of the Creative Commons | 
				
			|||
public licenses is dedicated to the public domain under the CC0 Public | 
				
			|||
Domain Dedication. Except for the limited purpose of indicating that | 
				
			|||
material is shared under a Creative Commons public license or as | 
				
			|||
otherwise permitted by the Creative Commons policies published at | 
				
			|||
creativecommons.org/policies, Creative Commons does not authorize the | 
				
			|||
use of the trademark "Creative Commons" or any other trademark or logo | 
				
			|||
of Creative Commons without its prior written consent including, | 
				
			|||
without limitation, in connection with any unauthorized modifications | 
				
			|||
to any of its public licenses or any other arrangements, | 
				
			|||
understandings, or agreements concerning use of licensed material. For | 
				
			|||
the avoidance of doubt, this paragraph does not form part of the | 
				
			|||
public licenses. | 
				
			|||
 | 
				
			|||
Creative Commons may be contacted at creativecommons.org. | 
				
			|||
@ -0,0 +1,7 @@ | 
				
			|||
License | 
				
			|||
 | 
				
			|||
CC-CY-NC-SA 3.0 | 
				
			|||
 | 
				
			|||
https://creativecommons.org/licenses/by-nc-sa/3.0/de | 
				
			|||
 | 
				
			|||
This project is for non-commercial use only! | 
				
			|||
@ -0,0 +1,113 @@ | 
				
			|||
#ifndef __DISPLAY__ | 
				
			|||
#define __DISPLAY__ | 
				
			|||
 | 
				
			|||
#include <Timezone.h> | 
				
			|||
#include <U8g2lib.h> | 
				
			|||
 | 
				
			|||
#include "../../hm/hmSystem.h" | 
				
			|||
#include "../../utils/helper.h" | 
				
			|||
#include "Display_Mono.h" | 
				
			|||
#include "Display_ePaper.h" | 
				
			|||
 | 
				
			|||
template <class HMSYSTEM> | 
				
			|||
class Display { | 
				
			|||
   public: | 
				
			|||
        Display() {} | 
				
			|||
 | 
				
			|||
        void setup(display_t *cfg, HMSYSTEM *sys, uint32_t *utcTs, uint8_t disp_reset, const char *version) { | 
				
			|||
            mCfg = cfg; | 
				
			|||
            mSys = sys; | 
				
			|||
            mUtcTs = utcTs; | 
				
			|||
            mNewPayload = false; | 
				
			|||
            mLoopCnt = 0; | 
				
			|||
            mVersion = version; | 
				
			|||
 | 
				
			|||
            if (mCfg->type == 0) | 
				
			|||
                return; | 
				
			|||
 | 
				
			|||
            if ((1 < mCfg->type) && (mCfg->type < 10)) { | 
				
			|||
                mMono.config(mCfg->pwrSaveAtIvOffline, mCfg->pxShift, mCfg->contrast); | 
				
			|||
                mMono.init(mCfg->type, mCfg->rot, mCfg->disp_cs, mCfg->disp_dc, mCfg->disp_reset, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mVersion); | 
				
			|||
            } else if (mCfg->type >= 10) { | 
				
			|||
                #if defined(ESP32) | 
				
			|||
                mRefreshCycle = 0; | 
				
			|||
                mEpaper.config(mCfg->rot); | 
				
			|||
                mEpaper.init(mCfg->type, mCfg->disp_cs, mCfg->disp_dc, mCfg->disp_reset, mCfg->disp_busy, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mVersion); | 
				
			|||
                #endif | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void payloadEventListener(uint8_t cmd) { | 
				
			|||
            mNewPayload = true; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void tickerSecond() { | 
				
			|||
            if (mNewPayload || ((++mLoopCnt % 10) == 0)) { | 
				
			|||
                mNewPayload = false; | 
				
			|||
                mLoopCnt = 0; | 
				
			|||
                DataScreen(); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    private: | 
				
			|||
        void DataScreen() { | 
				
			|||
            if (mCfg->type == 0) | 
				
			|||
                return; | 
				
			|||
            if (*mUtcTs == 0) | 
				
			|||
                return; | 
				
			|||
 | 
				
			|||
            float totalPower = 0; | 
				
			|||
            float totalYieldDay = 0; | 
				
			|||
            float totalYieldTotal = 0; | 
				
			|||
 | 
				
			|||
            uint8_t isprod = 0; | 
				
			|||
 | 
				
			|||
            Inverter<> *iv; | 
				
			|||
            record_t<> *rec; | 
				
			|||
            for (uint8_t i = 0; i < mSys->getNumInverters(); i++) { | 
				
			|||
                iv = mSys->getInverterByPos(i); | 
				
			|||
                rec = iv->getRecordStruct(RealTimeRunData_Debug); | 
				
			|||
                if (iv == NULL) | 
				
			|||
                    continue; | 
				
			|||
 | 
				
			|||
                if (iv->isProducing(*mUtcTs)) | 
				
			|||
                    isprod++; | 
				
			|||
 | 
				
			|||
                totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec); | 
				
			|||
                totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec); | 
				
			|||
                totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            if ((1 < mCfg->type) && (mCfg->type < 10)) { | 
				
			|||
                mMono.loop(totalPower, totalYieldDay, totalYieldTotal, isprod); | 
				
			|||
            } else if (mCfg->type >= 10) { | 
				
			|||
                #if defined(ESP32) | 
				
			|||
                mEpaper.loop(totalPower, totalYieldDay, totalYieldTotal, isprod); | 
				
			|||
                mRefreshCycle++; | 
				
			|||
                #endif | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            #if defined(ESP32) | 
				
			|||
            if (mRefreshCycle > 480) { | 
				
			|||
                mEpaper.fullRefresh(); | 
				
			|||
                mRefreshCycle = 0; | 
				
			|||
            } | 
				
			|||
            #endif | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        // private member variables
 | 
				
			|||
        bool mNewPayload; | 
				
			|||
        uint8_t mLoopCnt; | 
				
			|||
        uint32_t *mUtcTs; | 
				
			|||
        const char *mVersion; | 
				
			|||
        display_t *mCfg; | 
				
			|||
        HMSYSTEM *mSys; | 
				
			|||
        uint16_t mRefreshCycle; | 
				
			|||
 | 
				
			|||
        #if defined(ESP32) | 
				
			|||
        DisplayEPaper mEpaper; | 
				
			|||
        #endif | 
				
			|||
        DisplayMono mMono; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
#endif /*__DISPLAY__*/ | 
				
			|||
@ -0,0 +1,149 @@ | 
				
			|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			|||
#include "Display_Mono.h" | 
				
			|||
 | 
				
			|||
#ifdef ESP8266 | 
				
			|||
    #include <ESP8266WiFi.h> | 
				
			|||
#elif defined(ESP32) | 
				
			|||
    #include <WiFi.h> | 
				
			|||
#endif | 
				
			|||
#include "../../utils/helper.h" | 
				
			|||
 | 
				
			|||
//#ifdef U8X8_HAVE_HW_SPI
 | 
				
			|||
//#include <SPI.h>
 | 
				
			|||
//#endif
 | 
				
			|||
//#ifdef U8X8_HAVE_HW_I2C
 | 
				
			|||
//#include <Wire.h>
 | 
				
			|||
//#endif
 | 
				
			|||
 | 
				
			|||
DisplayMono::DisplayMono() { | 
				
			|||
    mEnPowerSafe = true; | 
				
			|||
    mEnScreenSaver = true; | 
				
			|||
    mLuminance = 60; | 
				
			|||
    _dispY = 0; | 
				
			|||
    mTimeout = DISP_DEFAULT_TIMEOUT;  // interval at which to power save (milliseconds)
 | 
				
			|||
    mUtcTs = NULL; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
void DisplayMono::init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char* version) { | 
				
			|||
    if ((0 < type) && (type < 4)) { | 
				
			|||
        u8g2_cb_t *rot = (u8g2_cb_t *)((rot != 0x00) ? U8G2_R2 : U8G2_R0); | 
				
			|||
        switch(type) { | 
				
			|||
            case 1: | 
				
			|||
                mDisplay = new U8G2_PCD8544_84X48_F_4W_HW_SPI(rot, cs, dc, reset); | 
				
			|||
                break; | 
				
			|||
            case 2: | 
				
			|||
                mDisplay = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(rot, reset, clock, data); | 
				
			|||
                break; | 
				
			|||
            default: | 
				
			|||
            case 3: | 
				
			|||
                mDisplay = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(rot, reset, clock, data); | 
				
			|||
                break; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        mUtcTs = utcTs; | 
				
			|||
 | 
				
			|||
        mDisplay->begin(); | 
				
			|||
 | 
				
			|||
        mIsLarge = (mDisplay->getWidth() > 120); | 
				
			|||
        calcLineHeights(); | 
				
			|||
 | 
				
			|||
        mDisplay->clearBuffer(); | 
				
			|||
        mDisplay->setContrast(mLuminance); | 
				
			|||
        printText("AHOY!", 0, 35); | 
				
			|||
        printText("ahoydtu.de", 2, 20); | 
				
			|||
        printText(version, 3, 46); | 
				
			|||
        mDisplay->sendBuffer(); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono::config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) { | 
				
			|||
    mEnPowerSafe = enPowerSafe; | 
				
			|||
    mEnScreenSaver = enScreenSaver; | 
				
			|||
    mLuminance = lum; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono::loop(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) { | 
				
			|||
    if (mEnPowerSafe) | 
				
			|||
        if(mTimeout != 0) | 
				
			|||
           mTimeout--; | 
				
			|||
 | 
				
			|||
    mDisplay->clearBuffer(); | 
				
			|||
 | 
				
			|||
    // set Contrast of the Display to raise the lifetime
 | 
				
			|||
    mDisplay->setContrast(mLuminance); | 
				
			|||
 | 
				
			|||
    if ((totalPower > 0) && (isprod > 0)) { | 
				
			|||
        mTimeout = DISP_DEFAULT_TIMEOUT; | 
				
			|||
        mDisplay->setPowerSave(false); | 
				
			|||
        if (totalPower > 999) { | 
				
			|||
            snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000)); | 
				
			|||
        } else { | 
				
			|||
            snprintf(_fmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower); | 
				
			|||
        } | 
				
			|||
        printText(_fmtText, 0); | 
				
			|||
    } else { | 
				
			|||
        printText("offline", 0, 25); | 
				
			|||
        // check if it's time to enter power saving mode
 | 
				
			|||
        if (mTimeout == 0) | 
				
			|||
            mDisplay->setPowerSave(mEnPowerSafe); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    snprintf(_fmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay); | 
				
			|||
    printText(_fmtText, 1); | 
				
			|||
 | 
				
			|||
    snprintf(_fmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal); | 
				
			|||
    printText(_fmtText, 2); | 
				
			|||
 | 
				
			|||
    IPAddress ip = WiFi.localIP(); | 
				
			|||
    if (!(_mExtra % 10) && (ip)) { | 
				
			|||
        printText(ip.toString().c_str(), 3); | 
				
			|||
    } else if (!(_mExtra % 5)) { | 
				
			|||
        snprintf(_fmtText, DISP_FMT_TEXT_LEN, "#%d Inverter online", isprod); | 
				
			|||
        printText(_fmtText, 3); | 
				
			|||
    } else { | 
				
			|||
        if(mIsLarge && (NULL != mUtcTs)) | 
				
			|||
            printText(ah::getDateTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); | 
				
			|||
        else | 
				
			|||
            printText(ah::getTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    mDisplay->sendBuffer(); | 
				
			|||
 | 
				
			|||
    _dispY = 0; | 
				
			|||
    _mExtra++; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono::calcLineHeights() { | 
				
			|||
    uint8_t yOff = 0; | 
				
			|||
    for (uint8_t i = 0; i < 4; i++) { | 
				
			|||
        setFont(i); | 
				
			|||
        yOff += (mDisplay->getMaxCharHeight()); | 
				
			|||
        mLineOffsets[i] = yOff; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
inline void DisplayMono::setFont(uint8_t line) { | 
				
			|||
    switch (line) { | 
				
			|||
        case 0: | 
				
			|||
            mDisplay->setFont((mIsLarge) ? u8g2_font_ncenB14_tr : u8g2_font_logisoso16_tr); | 
				
			|||
            break; | 
				
			|||
        case 3: | 
				
			|||
            mDisplay->setFont(u8g2_font_5x8_tr); | 
				
			|||
            break; | 
				
			|||
        default: | 
				
			|||
            mDisplay->setFont((mIsLarge) ? u8g2_font_ncenB10_tr : u8g2_font_5x8_tr); | 
				
			|||
            break; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayMono::printText(const char* text, uint8_t line, uint8_t dispX) { | 
				
			|||
    if (!mIsLarge) { | 
				
			|||
        dispX = (line == 0) ? 10 : 5; | 
				
			|||
    } | 
				
			|||
    setFont(line); | 
				
			|||
 | 
				
			|||
    dispX += (mEnPowerSafe) ? (_mExtra % 7) : 0; | 
				
			|||
    mDisplay->drawStr(dispX, mLineOffsets[line], text); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,36 @@ | 
				
			|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			|||
#pragma once | 
				
			|||
 | 
				
			|||
#include <U8g2lib.h> | 
				
			|||
#define DISP_DEFAULT_TIMEOUT 60  // in seconds
 | 
				
			|||
#define DISP_FMT_TEXT_LEN    32 | 
				
			|||
 | 
				
			|||
class DisplayMono { | 
				
			|||
   public: | 
				
			|||
      DisplayMono(); | 
				
			|||
 | 
				
			|||
      void init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char* version); | 
				
			|||
      void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum); | 
				
			|||
      void loop(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod); | 
				
			|||
 | 
				
			|||
   private: | 
				
			|||
      void calcLineHeights(); | 
				
			|||
      void setFont(uint8_t line); | 
				
			|||
      void printText(const char* text, uint8_t line, uint8_t dispX = 5); | 
				
			|||
 | 
				
			|||
      U8G2* mDisplay; | 
				
			|||
 | 
				
			|||
      bool mEnPowerSafe, mEnScreenSaver; | 
				
			|||
      uint8_t mLuminance; | 
				
			|||
 | 
				
			|||
      bool mIsLarge = false; | 
				
			|||
      uint8_t mLoopCnt; | 
				
			|||
      uint32_t* mUtcTs; | 
				
			|||
      uint8_t mLineOffsets[5]; | 
				
			|||
 | 
				
			|||
      uint16_t _dispY; | 
				
			|||
 | 
				
			|||
      uint8_t _mExtra; | 
				
			|||
      uint16_t mTimeout; | 
				
			|||
      char _fmtText[DISP_FMT_TEXT_LEN]; | 
				
			|||
}; | 
				
			|||
@ -0,0 +1,197 @@ | 
				
			|||
#include "Display_ePaper.h" | 
				
			|||
 | 
				
			|||
#ifdef ESP8266 | 
				
			|||
    #include <ESP8266WiFi.h> | 
				
			|||
#elif defined(ESP32) | 
				
			|||
    #include <WiFi.h> | 
				
			|||
#endif | 
				
			|||
#include "../../utils/helper.h" | 
				
			|||
#include "imagedata.h" | 
				
			|||
 | 
				
			|||
#if defined(ESP32) | 
				
			|||
 | 
				
			|||
static const uint32_t spiClk = 4000000;  // 4 MHz
 | 
				
			|||
 | 
				
			|||
#if defined(ESP32) && defined(USE_HSPI_FOR_EPD) | 
				
			|||
SPIClass hspi(HSPI); | 
				
			|||
#endif | 
				
			|||
 | 
				
			|||
DisplayEPaper::DisplayEPaper() { | 
				
			|||
    mDisplayRotation = 2; | 
				
			|||
    mHeadFootPadding = 16; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
//***************************************************************************
 | 
				
			|||
void DisplayEPaper::init(uint8_t type, uint8_t _CS, uint8_t _DC, uint8_t _RST, uint8_t _BUSY, uint8_t _SCK, uint8_t _MOSI, uint32_t *utcTs, const char *version) { | 
				
			|||
    mUtcTs = utcTs; | 
				
			|||
 | 
				
			|||
    if (type > 9) { | 
				
			|||
        Serial.begin(115200); | 
				
			|||
        _display = new GxEPD2_BW<GxEPD2_150_BN, GxEPD2_150_BN::HEIGHT>(GxEPD2_150_BN(_CS, _DC, _RST, _BUSY)); | 
				
			|||
        hspi.begin(_SCK, _BUSY, _MOSI, _CS); | 
				
			|||
 | 
				
			|||
#if defined(ESP32) && defined(USE_HSPI_FOR_EPD) | 
				
			|||
        _display->epd2.selectSPI(hspi, SPISettings(spiClk, MSBFIRST, SPI_MODE0)); | 
				
			|||
#endif | 
				
			|||
        _display->init(115200, true, 2, false); | 
				
			|||
        _display->setRotation(mDisplayRotation); | 
				
			|||
        _display->setFullWindow(); | 
				
			|||
 | 
				
			|||
        // Logo
 | 
				
			|||
        _display->fillScreen(GxEPD_BLACK); | 
				
			|||
        _display->drawBitmap(0, 0, logo, 200, 200, GxEPD_WHITE); | 
				
			|||
        while (_display->nextPage()) | 
				
			|||
            ; | 
				
			|||
 | 
				
			|||
        // clean the screen
 | 
				
			|||
        delay(2000); | 
				
			|||
        _display->fillScreen(GxEPD_WHITE); | 
				
			|||
        while (_display->nextPage()) | 
				
			|||
            ; | 
				
			|||
 | 
				
			|||
        headlineIP(); | 
				
			|||
 | 
				
			|||
        // call the PowerPage to change the PV Power Values
 | 
				
			|||
        actualPowerPaged(0, 0, 0, 0); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
void DisplayEPaper::config(uint8_t rotation) { | 
				
			|||
    mDisplayRotation = rotation; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
//***************************************************************************
 | 
				
			|||
void DisplayEPaper::fullRefresh() { | 
				
			|||
    // screen complete black
 | 
				
			|||
    _display->fillScreen(GxEPD_BLACK); | 
				
			|||
    while (_display->nextPage()) | 
				
			|||
        ; | 
				
			|||
    delay(2000); | 
				
			|||
    // screen complete white
 | 
				
			|||
    _display->fillScreen(GxEPD_WHITE); | 
				
			|||
    while (_display->nextPage()) | 
				
			|||
        ; | 
				
			|||
} | 
				
			|||
//***************************************************************************
 | 
				
			|||
void DisplayEPaper::headlineIP() { | 
				
			|||
    int16_t tbx, tby; | 
				
			|||
    uint16_t tbw, tbh; | 
				
			|||
 | 
				
			|||
    _display->setFont(&FreeSans9pt7b); | 
				
			|||
    _display->setTextColor(GxEPD_WHITE); | 
				
			|||
 | 
				
			|||
    _display->setPartialWindow(0, 0, _display->width(), mHeadFootPadding); | 
				
			|||
    _display->fillScreen(GxEPD_BLACK); | 
				
			|||
 | 
				
			|||
    do { | 
				
			|||
        if ((WiFi.isConnected() == true) && (WiFi.localIP() > 0)) { | 
				
			|||
            snprintf(_fmtText, sizeof(_fmtText), "%s", WiFi.localIP().toString().c_str()); | 
				
			|||
        } else { | 
				
			|||
            snprintf(_fmtText, sizeof(_fmtText), "WiFi not connected"); | 
				
			|||
        } | 
				
			|||
        _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); | 
				
			|||
        uint16_t x = ((_display->width() - tbw) / 2) - tbx; | 
				
			|||
 | 
				
			|||
        _display->setCursor(x, (mHeadFootPadding - 2)); | 
				
			|||
        _display->println(_fmtText); | 
				
			|||
    } while (_display->nextPage()); | 
				
			|||
} | 
				
			|||
//***************************************************************************
 | 
				
			|||
void DisplayEPaper::lastUpdatePaged() { | 
				
			|||
    int16_t tbx, tby; | 
				
			|||
    uint16_t tbw, tbh; | 
				
			|||
 | 
				
			|||
    _display->setFont(&FreeSans9pt7b); | 
				
			|||
    _display->setTextColor(GxEPD_WHITE); | 
				
			|||
 | 
				
			|||
    _display->setPartialWindow(0, _display->height() - mHeadFootPadding, _display->width(), mHeadFootPadding); | 
				
			|||
    _display->fillScreen(GxEPD_BLACK); | 
				
			|||
    do { | 
				
			|||
        if (NULL != mUtcTs) { | 
				
			|||
            snprintf(_fmtText, sizeof(_fmtText), ah::getDateTimeStr(gTimezone.toLocal(*mUtcTs)).c_str()); | 
				
			|||
 | 
				
			|||
            _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); | 
				
			|||
            uint16_t x = ((_display->width() - tbw) / 2) - tbx; | 
				
			|||
 | 
				
			|||
            _display->setCursor(x, (_display->height() - 3)); | 
				
			|||
            _display->println(_fmtText); | 
				
			|||
        } | 
				
			|||
    } while (_display->nextPage()); | 
				
			|||
} | 
				
			|||
//***************************************************************************
 | 
				
			|||
void DisplayEPaper::actualPowerPaged(float _totalPower, float _totalYieldDay, float _totalYieldTotal, uint8_t _isprod) { | 
				
			|||
    int16_t tbx, tby; | 
				
			|||
    uint16_t tbw, tbh, x, y; | 
				
			|||
 | 
				
			|||
    _display->setFont(&FreeSans24pt7b); | 
				
			|||
    _display->setTextColor(GxEPD_BLACK); | 
				
			|||
 | 
				
			|||
    _display->setPartialWindow(0, mHeadFootPadding, _display->width(), _display->height() - (mHeadFootPadding * 2)); | 
				
			|||
    _display->fillScreen(GxEPD_WHITE); | 
				
			|||
    do { | 
				
			|||
        if (_totalPower > 9999) { | 
				
			|||
            snprintf(_fmtText, sizeof(_fmtText), "%.1f kW", (_totalPower / 10000)); | 
				
			|||
            _changed = true; | 
				
			|||
        } else if ((_totalPower > 0) && (_totalPower <= 9999)) { | 
				
			|||
            snprintf(_fmtText, sizeof(_fmtText), "%.0f W", _totalPower); | 
				
			|||
            _changed = true; | 
				
			|||
        } else { | 
				
			|||
            snprintf(_fmtText, sizeof(_fmtText), "offline"); | 
				
			|||
        } | 
				
			|||
        _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); | 
				
			|||
        x = ((_display->width() - tbw) / 2) - tbx; | 
				
			|||
        _display->setCursor(x, mHeadFootPadding + tbh + 10); | 
				
			|||
        _display->print(_fmtText); | 
				
			|||
 | 
				
			|||
        _display->setFont(&FreeSans12pt7b); | 
				
			|||
        y = _display->height() / 2; | 
				
			|||
        _display->setCursor(0, y); | 
				
			|||
        _display->print("today:"); | 
				
			|||
        snprintf(_fmtText, _display->width(), "%.0f", _totalYieldDay); | 
				
			|||
        _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); | 
				
			|||
        x = ((_display->width() - tbw) / 2) - tbx; | 
				
			|||
        _display->setCursor(x, y); | 
				
			|||
        _display->print(_fmtText); | 
				
			|||
        _display->setCursor(_display->width() - 33, y); | 
				
			|||
        _display->println("Wh"); | 
				
			|||
 | 
				
			|||
        y = y + tbh + 7; | 
				
			|||
        _display->setCursor(0, y); | 
				
			|||
        _display->print("total:"); | 
				
			|||
        snprintf(_fmtText, _display->width(), "%.1f", _totalYieldTotal); | 
				
			|||
        _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); | 
				
			|||
        x = ((_display->width() - tbw) / 2) - tbx; | 
				
			|||
        _display->setCursor(x, y); | 
				
			|||
        _display->print(_fmtText); | 
				
			|||
        _display->setCursor(_display->width() - 45, y); | 
				
			|||
        _display->println("kWh"); | 
				
			|||
 | 
				
			|||
        _display->setCursor(0, _display->height() - (mHeadFootPadding + 10)); | 
				
			|||
        snprintf(_fmtText, sizeof(_fmtText), "#%d Inverter online", _isprod); | 
				
			|||
        _display->println(_fmtText); | 
				
			|||
 | 
				
			|||
    } while (_display->nextPage()); | 
				
			|||
} | 
				
			|||
//***************************************************************************
 | 
				
			|||
void DisplayEPaper::loop(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) { | 
				
			|||
    // check if the IP has changed
 | 
				
			|||
    if (_settedIP != WiFi.localIP().toString().c_str()) { | 
				
			|||
        // save the new IP and call the Headline Funktion to adapt the Headline
 | 
				
			|||
        _settedIP = WiFi.localIP().toString().c_str(); | 
				
			|||
        headlineIP(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    // call the PowerPage to change the PV Power Values
 | 
				
			|||
    actualPowerPaged(totalPower, totalYieldDay, totalYieldTotal, isprod); | 
				
			|||
 | 
				
			|||
    // if there was an change and the Inverter is producing set a new Timestam in the footline
 | 
				
			|||
    if ((isprod > 0) && (_changed)) { | 
				
			|||
        _changed = false; | 
				
			|||
        lastUpdatePaged(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    _display->powerOff(); | 
				
			|||
} | 
				
			|||
//***************************************************************************
 | 
				
			|||
#endif // ESP32
 | 
				
			|||
@ -0,0 +1,52 @@ | 
				
			|||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			|||
#pragma once | 
				
			|||
 | 
				
			|||
#if defined(ESP32) | 
				
			|||
 | 
				
			|||
// uncomment next line to use HSPI for EPD (and VSPI for SD), e.g. with Waveshare ESP32 Driver Board
 | 
				
			|||
#define USE_HSPI_FOR_EPD | 
				
			|||
 | 
				
			|||
/// uncomment next line to use class GFX of library GFX_Root instead of Adafruit_GFX, to use less code and ram
 | 
				
			|||
// #include <GFX.h>
 | 
				
			|||
// base class GxEPD2_GFX can be used to pass references or pointers to the display instance as parameter, uses ~1.2k more code
 | 
				
			|||
// enable GxEPD2_GFX base class
 | 
				
			|||
#define ENABLE_GxEPD2_GFX 1 | 
				
			|||
 | 
				
			|||
#include <GxEPD2_3C.h> | 
				
			|||
#include <GxEPD2_BW.h> | 
				
			|||
#include <SPI.h> | 
				
			|||
 | 
				
			|||
#include <map> | 
				
			|||
// FreeFonts from Adafruit_GFX
 | 
				
			|||
#include <Fonts/FreeSans12pt7b.h> | 
				
			|||
#include <Fonts/FreeSans18pt7b.h> | 
				
			|||
#include <Fonts/FreeSans24pt7b.h> | 
				
			|||
#include <Fonts/FreeSans9pt7b.h> | 
				
			|||
 | 
				
			|||
// GDEW027C44   2.7 " b/w/r 176x264, IL91874
 | 
				
			|||
// GDEH0154D67  1.54" b/w   200x200
 | 
				
			|||
 | 
				
			|||
class DisplayEPaper { | 
				
			|||
   public: | 
				
			|||
      DisplayEPaper(); | 
				
			|||
      void fullRefresh(); | 
				
			|||
      void init(uint8_t type, uint8_t _CS, uint8_t _DC, uint8_t _RST, uint8_t _BUSY, uint8_t _SCK, uint8_t _MOSI, uint32_t *utcTs, const char* version); | 
				
			|||
      void config(uint8_t rotation); | 
				
			|||
      void loop(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod); | 
				
			|||
 | 
				
			|||
 | 
				
			|||
   private: | 
				
			|||
      void headlineIP(); | 
				
			|||
      void actualPowerPaged(float _totalPower, float _totalYieldDay, float _totalYieldTotal, uint8_t _isprod); | 
				
			|||
      void lastUpdatePaged(); | 
				
			|||
 | 
				
			|||
      uint8_t mDisplayRotation; | 
				
			|||
      bool _changed = false; | 
				
			|||
      char _fmtText[35]; | 
				
			|||
      const char* _settedIP; | 
				
			|||
      uint8_t mHeadFootPadding; | 
				
			|||
      GxEPD2_GFX* _display; | 
				
			|||
      uint32_t *mUtcTs; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
#endif // ESP32
 | 
				
			|||
@ -0,0 +1,329 @@ | 
				
			|||
// GxEPD2_ESP32_ESP8266_WifiData_V1_und_V2
 | 
				
			|||
 | 
				
			|||
#ifndef __IMAGEDATA_H__ | 
				
			|||
#define __IMAGEDATA_H__ | 
				
			|||
 | 
				
			|||
#if defined(__AVR__) || defined(ARDUINO_ARCH_SAMD) | 
				
			|||
#include <avr/pgmspace.h> | 
				
			|||
#elif defined(ESP8266) || defined(ESP32) | 
				
			|||
#include <pgmspace.h> | 
				
			|||
#endif | 
				
			|||
 | 
				
			|||
// 'Logo', 200x200px
 | 
				
			|||
const unsigned char logo[] PROGMEM = { | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, | 
				
			|||
    0x0b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xfe, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x06, | 
				
			|||
    0x0f, 0xff, 0xff, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x7e, 0x0f, 0xff, 0xff, 0xfc, 0x03, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, | 
				
			|||
    0x03, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x19, 0xfe, 0x07, 0xff, 0xff, 0xff, 0xfe, | 
				
			|||
    0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xe0, 0x70, 0x7f, 0x07, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xe0, 0x3f, 0x07, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xfc, 0x0f, 0xe0, 0x3f, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xe0, 0x1f, 0x83, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xe0, 0x1f, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xe0, | 
				
			|||
    0x0f, 0x83, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xe0, 0x0f, 0x83, 0xff, 0xff, 0xff, 0xff, 0xfe, | 
				
			|||
    0x07, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, | 
				
			|||
    0xff, 0xc1, 0x07, 0x80, 0x07, 0xfe, 0xff, 0xff, 0xfc, 0x07, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xe1, 0x07, 0xc0, 0x01, 0xe0, 0x0f, | 
				
			|||
    0xff, 0xfc, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xfc, 0xff, 0xe1, 0x83, 0xc0, 0x01, 0xc0, 0x07, 0xff, 0xf8, 0x0f, 0xfc, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xe1, 0x83, 0xc0, 0x00, | 
				
			|||
    0xc0, 0x07, 0x8f, 0xf8, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xfe, 0x7f, 0xe0, 0x01, 0xc0, 0x00, 0x81, 0x83, 0x07, 0xf0, 0x3f, 0xf9, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xe0, 0x01, | 
				
			|||
    0xe0, 0xe0, 0x87, 0xe3, 0x0f, 0xf0, 0x3f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x00, 0xe0, 0xe0, 0x87, 0xe1, 0x0c, 0x60, 0x7f, | 
				
			|||
    0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, | 
				
			|||
    0xe0, 0x00, 0xe1, 0xf0, 0x87, 0xe1, 0x08, 0x60, 0x7f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xe0, 0xe0, 0xe0, 0xe0, 0x87, 0xc2, 0x00, | 
				
			|||
    0x40, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0x8f, 0xc0, 0xe0, 0x60, 0xe0, 0xc0, 0x82, 0x00, 0xc0, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xc0, 0xe0, 0x60, 0xe0, 0xc0, | 
				
			|||
    0x06, 0x01, 0x81, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xcf, 0xe0, 0xe0, 0x20, 0xe0, 0xe0, 0x0c, 0x03, 0x81, 0xff, 0x1f, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xc0, 0xf0, 0x30, | 
				
			|||
    0xe1, 0xf8, 0x18, 0x07, 0xe1, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xc0, 0xf0, 0x7f, 0xff, 0xff, 0xf0, 0x1f, 0xf3, 0xfe, 0x01, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xc0, | 
				
			|||
    0xfb, 0xff, 0xff, 0xff, 0xe0, 0x3e, 0x1f, 0xfc, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xfc, 0x0f, | 
				
			|||
    0xf8, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, | 
				
			|||
    0x33, 0xef, 0xff, 0xff, 0xff, 0xff, 0x81, 0xfc, 0x0f, 0xf1, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf1, 0xff, 0xff, 0xa0, 0x00, 0x7f, 0xe3, | 
				
			|||
    0xfc, 0x0f, 0xf3, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xf1, 0xf9, 0xff, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x0f, 0xe7, 0xff, 0xe0, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xf9, 0xff, 0x80, 0x3f, 0xff, | 
				
			|||
    0xe0, 0x0f, 0xfe, 0x1f, 0xc7, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xcf, 0xf8, 0xf0, 0x07, 0xff, 0xff, 0xff, 0x81, 0xff, 0xff, 0x8f, 0xff, 0xfc, | 
				
			|||
    0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xfc, 0x70, 0x3f, | 
				
			|||
    0xff, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0x1f, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xfc, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0x3f, | 
				
			|||
    0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, | 
				
			|||
    0x23, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7e, 0x3f, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x23, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, | 
				
			|||
    0x0c, 0x7f, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, | 
				
			|||
    0x7f, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xfc, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xf8, | 
				
			|||
    0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x87, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xfc, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x00, 0x3f, 0xff, 0xf8, 0x00, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xfc, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x55, 0x00, 0x3f, 0xf8, 0x00, | 
				
			|||
    0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0x01, 0xff, 0xff, 0xf8, 0x0f, 0xfc, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0x9f, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xff, 0x03, | 
				
			|||
    0xfc, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xe3, 0xf1, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xe0, 0xfe, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xe7, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xf8, 0x7e, 0x06, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xcf, | 
				
			|||
    0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0x03, 0x3f, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xcf, 0xfc, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0x1f, 0x23, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, | 
				
			|||
    0xff, 0x9f, 0xfe, 0x7f, 0xff, 0xf3, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xf1, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0x9f, 0xfe, 0x7f, 0xff, 0xe3, 0xf8, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xfe, 0x7f, 0xff, 0x9f, 0xff, 0x0f, 0xff, 0x8f, 0xf1, 0xff, 0xff, 0xff, 0xfe, 0xf5, 0x90, 0x07, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0x9f, 0xff, 0x03, 0xff, | 
				
			|||
    0x1f, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xfe, 0x7f, 0xff, 0x3f, 0xfe, 0x31, 0xfe, 0x7f, 0xe7, 0xff, 0x80, 0x00, 0x40, 0x00, | 
				
			|||
    0x07, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0x3f, 0x3c, | 
				
			|||
    0xf9, 0xfc, 0xff, 0xe7, 0xfe, 0x3f, 0xc9, 0xff, 0xf1, 0x1f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x3f, 0x3c, 0xf9, 0xf9, 0xff, 0xc7, 0xfc, 0xff, 0x90, | 
				
			|||
    0x7f, 0xf3, 0x03, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, | 
				
			|||
    0x3f, 0x39, 0xfd, 0xf3, 0xff, 0xcf, 0xfc, 0xff, 0x90, 0x3f, 0xf3, 0x83, 0xf8, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x3f, 0x39, 0xf9, 0xc7, 0xff, 0xcf, 0xfc, | 
				
			|||
    0xff, 0x32, 0x7f, 0xe4, 0x77, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, | 
				
			|||
    0xff, 0xff, 0x7f, 0x33, 0xf9, 0x8f, 0xff, 0xcf, 0xf9, 0xff, 0x00, 0x7f, 0xe0, 0x67, 0xfc, 0x7f, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x7f, 0xb3, 0xf3, 0xbf, 0xff, | 
				
			|||
    0xcf, 0xf9, 0xff, 0x00, 0xff, 0xfe, 0x47, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xf9, 0xff, 0xff, 0x7f, 0xf7, 0xf3, 0xff, 0xff, 0xcf, 0xf9, 0xff, 0xe0, 0xff, 0xfc, 0x0f, | 
				
			|||
    0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x7f, 0xe7, 0xe7, | 
				
			|||
    0xff, 0xff, 0xcf, 0xf9, 0xff, 0xe1, 0xff, 0xfc, 0x1f, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x3f, 0xef, 0xe7, 0xef, 0xff, 0xc7, 0xf9, 0xff, 0xc3, 0xff, | 
				
			|||
    0xfc, 0x3f, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x3f, | 
				
			|||
    0xef, 0xef, 0xc0, 0xff, 0xe7, 0xf9, 0xff, 0xc3, 0xff, 0xf8, 0x3f, 0xff, 0x3f, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x3f, 0xef, 0xcf, 0xf0, 0x01, 0xe7, 0xf1, 0xff, | 
				
			|||
    0x87, 0xff, 0xf8, 0x7f, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, | 
				
			|||
    0xff, 0xbf, 0xcf, 0xe7, 0xff, 0xc1, 0xe3, 0xe1, 0xff, 0x8f, 0xff, 0xf0, 0xff, 0xff, 0x9f, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x9f, 0xef, 0xe7, 0xff, 0xff, 0xf3, | 
				
			|||
    0xc1, 0xff, 0x96, 0xaf, 0xf9, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xf9, 0xff, 0xff, 0x9f, 0xe7, 0xe3, 0xff, 0xff, 0xf1, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, | 
				
			|||
    0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xcf, 0xe7, 0xf3, 0xff, | 
				
			|||
    0xff, 0xf8, 0xc0, 0x00, 0x4a, 0x90, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xf9, 0xff, 0xff, 0xef, 0xf3, 0xf3, 0x9f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			|||
    0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xe7, 0xf1, | 
				
			|||
    0xe7, 0xc7, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xf3, 0xf0, 0x07, 0xe3, 0xff, 0xff, 0x81, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xfe, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, | 
				
			|||
    0xf8, 0x07, 0x1f, 0xf1, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xfc, 0x1f, 0x9f, 0xf8, 0xff, 0xff, 0xc3, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, | 
				
			|||
    0xff, 0xff, 0xf8, 0xff, 0x9f, 0xfe, 0x7f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xf9, 0xff, 0x9f, 0xfe, 0x3f, | 
				
			|||
    0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xfd, 0xff, 0xff, 0xf1, 0xff, 0x9f, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0x3f, 0x3f, 0xff, 0xff, | 
				
			|||
    0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xe1, 0xff, 0xcf, | 
				
			|||
    0xff, 0xc7, 0xff, 0xf3, 0xff, 0x3f, 0x9f, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xe1, 0xff, 0x8f, 0xff, 0xe7, 0xff, 0xf3, 0xff, 0x3f, 0x9f, | 
				
			|||
    0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xc1, | 
				
			|||
    0xff, 0xcf, 0xff, 0xf3, 0xff, 0xf3, 0xff, 0x3f, 0x9f, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x81, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xf3, 0xff, | 
				
			|||
    0x3f, 0x9f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, | 
				
			|||
    0xff, 0x91, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xf3, 0xff, 0x3f, 0x9f, 0xff, 0xff, 0xfe, 0x3f, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0x11, 0xff, 0x9f, 0xff, 0xff, 0xff, | 
				
			|||
    0xf3, 0xff, 0x1f, 0x9f, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xfe, 0x7f, 0xff, 0x21, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xbf, 0x9f, 0xff, 0xff, 0xfe, | 
				
			|||
    0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x20, 0xff, 0x9f, 0xff, | 
				
			|||
    0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x60, 0x7f, 0x9f, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0x64, 0x3f, | 
				
			|||
    0x1f, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xe7, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, | 
				
			|||
    0xff, 0x3f, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xfc, | 
				
			|||
    0xe7, 0x80, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf1, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xf8, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, | 
				
			|||
    0xff, 0xff, 0xfe, 0x7f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0x9f, 0xf9, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xe7, 0xff, 0xfe, 0x7f, 0xff, 0xc3, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xf9, 0xe7, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xf3, 0xf3, 0xff, 0xfc, 0x7f, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xcf, 0xf9, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xff, 0xf8, 0xff, 0xff, | 
				
			|||
    0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xf9, 0xe7, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xf3, 0xf9, 0xff, 0xe1, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0x3f, 0x07, | 
				
			|||
    0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xf3, 0xe7, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfe, 0x00, 0x1f, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, | 
				
			|||
    0xe0, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, | 
				
			|||
    0xf3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xe3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xf7, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xf8, 0x83, 0xe7, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x13, 0xe7, 0xff, 0xfc, 0x03, | 
				
			|||
    0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xfc, 0x31, 0xe7, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xfe, | 
				
			|||
    0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x39, 0xe3, 0xff, | 
				
			|||
    0xfc, 0x00, 0x1f, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x31, 0xf3, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xc7, 0xff, 0xff, | 
				
			|||
    0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, | 
				
			|||
    0xf3, 0xff, 0xfc, 0x00, 0x07, 0xff, 0x87, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xf3, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x07, | 
				
			|||
    0xff, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0x83, 0xf3, 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xf3, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xf8, 0x07, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xe3, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xfe, 0x1f, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xe1, 0xff, 0xfe, | 
				
			|||
    0x01, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xe1, 0xff, 0xf0, 0x00, 0x3f, 0x80, 0x07, 0xff, 0xff, 0xf0, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x4c, | 
				
			|||
    0xff, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0c, 0xff, 0xf0, 0x00, 0x00, 0x0b, 0x87, 0xff, | 
				
			|||
    0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0x0e, 0x7f, 0xf8, 0x00, 0x3f, 0xff, 0xc7, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x86, 0x7f, 0xfe, 0x00, 0xff, 0xff, | 
				
			|||
    0xc3, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0x87, 0xff, 0xff, 0xf3, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xf3, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfe, 0x07, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xf3, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xf3, 0xc0, 0x7f, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xe3, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0xe0, | 
				
			|||
    0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x03, 0xff, | 
				
			|||
    0xfe, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xf0, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x17, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 
				
			|||
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
#endif /*__IMAGEDATA_H__*/ | 
				
			|||
@ -1,217 +0,0 @@ | 
				
			|||
#ifndef __MONOCHROME_DISPLAY__ | 
				
			|||
#define __MONOCHROME_DISPLAY__ | 
				
			|||
 | 
				
			|||
#include <U8g2lib.h> | 
				
			|||
#include <Timezone.h> | 
				
			|||
 | 
				
			|||
#include "../../utils/helper.h" | 
				
			|||
#include "../../hm/hmSystem.h" | 
				
			|||
 | 
				
			|||
#define DISP_DEFAULT_TIMEOUT        60  // in seconds
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
static uint8_t bmp_logo[] PROGMEM = { | 
				
			|||
    B00000000, B00000000, // ................
 | 
				
			|||
    B11101100, B00110111, // ..##.######.##..
 | 
				
			|||
    B11101100, B00110111, // ..##.######.##..
 | 
				
			|||
    B11100000, B00000111, // .....######.....
 | 
				
			|||
    B11010000, B00001011, // ....#.####.#....
 | 
				
			|||
    B10011000, B00011001, // ...##..##..##...
 | 
				
			|||
    B10000000, B00000001, // .......##.......
 | 
				
			|||
    B00000000, B00000000, // ................
 | 
				
			|||
    B01111000, B00011110, // ...####..####...
 | 
				
			|||
    B11111100, B00111111, // ..############..
 | 
				
			|||
    B01111100, B00111110, // ..#####..#####..
 | 
				
			|||
    B00000000, B00000000, // ................
 | 
				
			|||
    B11111100, B00111111, // ..############..
 | 
				
			|||
    B11111110, B01111111, // .##############.
 | 
				
			|||
    B01111110, B01111110, // .######..######.
 | 
				
			|||
    B00000000, B00000000 // ................
 | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
static uint8_t bmp_arrow[] PROGMEM = { | 
				
			|||
    B00000000, B00011100, B00011100, B00001110, B00001110, B11111110, B01111111, | 
				
			|||
    B01110000, B01110000, B00110000, B00111000, B00011000, B01111111, B00111111, | 
				
			|||
    B00011110, B00001110, B00000110, B00000000, B00000000, B00000000, B00000000 | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
template<class HMSYSTEM> | 
				
			|||
class MonochromeDisplay { | 
				
			|||
    public: | 
				
			|||
        MonochromeDisplay() {} | 
				
			|||
 | 
				
			|||
        void setup(display_t *cfg, HMSYSTEM *sys, uint32_t *utcTs, uint8_t disp_reset, const char *version) { | 
				
			|||
            mCfg   = cfg; | 
				
			|||
            mSys   = sys; | 
				
			|||
            mUtcTs = utcTs; | 
				
			|||
            mNewPayload = false; | 
				
			|||
            mLoopCnt = 0; | 
				
			|||
            mTimeout = DISP_DEFAULT_TIMEOUT; // power off timeout (after inverters go offline)
 | 
				
			|||
 | 
				
			|||
            u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot180) ? U8G2_R2 : U8G2_R0); | 
				
			|||
 | 
				
			|||
            if(mCfg->type) { | 
				
			|||
                switch(mCfg->type) { | 
				
			|||
                    case 1: | 
				
			|||
                        mDisplay = new U8G2_PCD8544_84X48_F_4W_HW_SPI(rot, mCfg->pin0, mCfg->pin1, disp_reset); | 
				
			|||
                        break; | 
				
			|||
                    case 2: | 
				
			|||
                        mDisplay = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(rot, disp_reset, mCfg->pin0, mCfg->pin1); | 
				
			|||
                        break; | 
				
			|||
                    case 3: | 
				
			|||
                        mDisplay = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(rot, disp_reset, mCfg->pin0, mCfg->pin1); | 
				
			|||
                        break; | 
				
			|||
                } | 
				
			|||
                mDisplay->begin(); | 
				
			|||
 | 
				
			|||
                mIsLarge = ((mDisplay->getWidth() > 120) && (mDisplay->getHeight() > 60)); | 
				
			|||
                calcLineHeights(); | 
				
			|||
 | 
				
			|||
                mDisplay->clearBuffer(); | 
				
			|||
                mDisplay->setContrast(mCfg->contrast); | 
				
			|||
                printText("Ahoy!", 0, 35); | 
				
			|||
                printText("ahoydtu.de", 2, 20); | 
				
			|||
                printText(version, 3, 46); | 
				
			|||
                mDisplay->sendBuffer(); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void payloadEventListener(uint8_t cmd) { | 
				
			|||
            mNewPayload = true; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void tickerSecond() { | 
				
			|||
            if(mCfg->pwrSaveAtIvOffline) { | 
				
			|||
                if(mTimeout != 0) | 
				
			|||
                    mTimeout--; | 
				
			|||
            } | 
				
			|||
            if(mNewPayload || ((++mLoopCnt % 10) == 0)) { | 
				
			|||
                mNewPayload = false; | 
				
			|||
                mLoopCnt = 0; | 
				
			|||
                DataScreen(); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    private: | 
				
			|||
        void DataScreen() { | 
				
			|||
            if (mCfg->type == 0) | 
				
			|||
                return; | 
				
			|||
            if(*mUtcTs == 0) | 
				
			|||
                return; | 
				
			|||
 | 
				
			|||
            float totalPower = 0; | 
				
			|||
            float totalYieldDay = 0; | 
				
			|||
            float totalYieldTotal = 0; | 
				
			|||
 | 
				
			|||
            bool isprod = false; | 
				
			|||
 | 
				
			|||
            Inverter<> *iv; | 
				
			|||
            record_t<> *rec; | 
				
			|||
            for (uint8_t i = 0; i < mSys->getNumInverters(); i++) { | 
				
			|||
                iv = mSys->getInverterByPos(i); | 
				
			|||
                rec = iv->getRecordStruct(RealTimeRunData_Debug); | 
				
			|||
                if (iv == NULL) | 
				
			|||
                    continue; | 
				
			|||
 | 
				
			|||
                if (iv->isProducing(*mUtcTs)) | 
				
			|||
                    isprod = true; | 
				
			|||
 | 
				
			|||
                totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec); | 
				
			|||
                totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec); | 
				
			|||
                totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            mDisplay->clearBuffer(); | 
				
			|||
 | 
				
			|||
            // Logos
 | 
				
			|||
            //   pxMovement +x (0 - 6 px)
 | 
				
			|||
            uint8_t ex = (_mExtra % 7); | 
				
			|||
            if (isprod) { | 
				
			|||
                mDisplay->drawXBMP(5 + ex, 1, 8, 17, bmp_arrow); | 
				
			|||
                if (mCfg->logoEn) | 
				
			|||
                    mDisplay->drawXBMP(mDisplay->getWidth() - 24 + ex, 2, 16, 16, bmp_logo); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            if ((totalPower > 0) && isprod) { | 
				
			|||
                mTimeout = DISP_DEFAULT_TIMEOUT; | 
				
			|||
                mDisplay->setPowerSave(false); | 
				
			|||
                mDisplay->setContrast(mCfg->contrast); | 
				
			|||
                if (totalPower > 999) | 
				
			|||
                    snprintf(_fmtText, sizeof(_fmtText), "%2.1f kW", (totalPower / 1000)); | 
				
			|||
                else | 
				
			|||
                    snprintf(_fmtText, sizeof(_fmtText), "%3.0f W", totalPower); | 
				
			|||
                printText(_fmtText, 0, 20); | 
				
			|||
            } else { | 
				
			|||
                printText("offline", 0, 25); | 
				
			|||
                if(mCfg->pwrSaveAtIvOffline) { | 
				
			|||
                    if(mTimeout == 0) | 
				
			|||
                        mDisplay->setPowerSave(true); | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            snprintf(_fmtText, sizeof(_fmtText), "today: %4.0f Wh", totalYieldDay); | 
				
			|||
            printText(_fmtText, 1); | 
				
			|||
 | 
				
			|||
            snprintf(_fmtText, sizeof(_fmtText), "total: %.1f kWh", totalYieldTotal); | 
				
			|||
            printText(_fmtText, 2); | 
				
			|||
 | 
				
			|||
            IPAddress ip = WiFi.localIP(); | 
				
			|||
            if (!(_mExtra % 10) && (ip)) { | 
				
			|||
                printText(ip.toString().c_str(), 3); | 
				
			|||
            } else { | 
				
			|||
                // Get current time
 | 
				
			|||
                if(mIsLarge) | 
				
			|||
                    printText(ah::getDateTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); | 
				
			|||
                else | 
				
			|||
                    printText(ah::getTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); | 
				
			|||
            } | 
				
			|||
            mDisplay->sendBuffer(); | 
				
			|||
 | 
				
			|||
            _mExtra++; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void calcLineHeights() { | 
				
			|||
            uint8_t yOff = 0; | 
				
			|||
            for(uint8_t i = 0; i < 4; i++) { | 
				
			|||
                setFont(i); | 
				
			|||
                yOff += (mDisplay->getMaxCharHeight() + 1); | 
				
			|||
                mLineOffsets[i] = yOff; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        inline void setFont(uint8_t line) { | 
				
			|||
            switch (line) { | 
				
			|||
                case 0:  mDisplay->setFont((mIsLarge) ? u8g2_font_ncenB14_tr : u8g2_font_lubBI14_tr); break; | 
				
			|||
                case 3:  mDisplay->setFont(u8g2_font_5x8_tr); break; | 
				
			|||
                default: mDisplay->setFont((mIsLarge) ? u8g2_font_ncenB10_tr : u8g2_font_5x8_tr); break; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        void printText(const char* text, uint8_t line, uint8_t dispX = 5) { | 
				
			|||
            if(!mIsLarge) | 
				
			|||
                dispX = (line == 0) ? 10 : 5; | 
				
			|||
            setFont(line); | 
				
			|||
            if(mCfg->pxShift) | 
				
			|||
                dispX += (_mExtra % 7); // add pixel movement
 | 
				
			|||
            mDisplay->drawStr(dispX, mLineOffsets[line], text); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        // private member variables
 | 
				
			|||
        U8G2* mDisplay; | 
				
			|||
 | 
				
			|||
        uint8_t _mExtra; | 
				
			|||
        uint16_t mTimeout; // interval at which to power save (milliseconds)
 | 
				
			|||
        char _fmtText[32]; | 
				
			|||
 | 
				
			|||
        bool mNewPayload; | 
				
			|||
        bool mIsLarge; | 
				
			|||
        uint8_t mLoopCnt; | 
				
			|||
        uint32_t *mUtcTs; | 
				
			|||
        uint8_t mLineOffsets[5]; | 
				
			|||
        display_t *mCfg; | 
				
			|||
        HMSYSTEM *mSys; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
#endif /*__MONOCHROME_DISPLAY__*/ | 
				
			|||
					Loading…
					
					
				
		Reference in new issue