mirror of
https://github.com/usetrmnl/bb_epaper.git
synced 2026-04-29 13:43:26 -07:00
added Group5 to bb_eink
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
@@ -1,64 +1,103 @@
|
||||
License text copyright © 2024 MariaDB plc, All Rights Reserved.
|
||||
“Business Source License” is a trademark of MariaDB plc.
|
||||
Business Source License 1.1
|
||||
|
||||
Terms
|
||||
=====
|
||||
The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute,
|
||||
and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant,
|
||||
above, permitting limited production use.
|
||||
Parameters
|
||||
|
||||
Effective on the Change Date, or the fourth anniversary of the first publicly available
|
||||
distribution of a specific version of the Licensed Work under this License, whichever comes first,
|
||||
the Licensor hereby grants you rights under the terms of the Change License, and the rights granted
|
||||
in the paragraph above terminate.
|
||||
Licensor: BitBank Software, Inc.
|
||||
Licensed Works: bb_eink and Group5 1-bit imaging codec
|
||||
The Licensed Work is (c) 2024 BitBank Software, Inc.
|
||||
Additional Use Grant: You may make use of the Licensed Work, provided that
|
||||
you may not use the Licensed Work for a Commercial
|
||||
Product or Service.
|
||||
|
||||
If your use of the Licensed Work does not comply with the requirements currently in effect as
|
||||
described in this License, you must purchase a commercial license from the Licensor, its affiliated
|
||||
entities, or authorized resellers, or you must refrain from using the Licensed Work.
|
||||
A “Commercial Product or Service” is a commercial offering that
|
||||
allows third parties (other than your employees and
|
||||
contractors) to access the functionality of the
|
||||
Licensed Work without first having paid for a
|
||||
license.
|
||||
|
||||
All copies of the original and modified Licensed Work, and derivative works of the Licensed Work,
|
||||
are subject to this License. This License applies separately for each version of the Licensed Work
|
||||
and the Change Date may vary for each version of the Licensed Work released by Licensor.
|
||||
Change Date: 2028-10-01
|
||||
|
||||
You must conspicuously display this License on each original or modified copy of the Licensed Work.
|
||||
If you receive the Licensed Work in original or modified form from a third party, the terms and
|
||||
conditions set forth in this License apply to your use of that work.
|
||||
Change License: Apache License, Version 2.0
|
||||
|
||||
Any use of the Licensed Work in violation of this License will automatically terminate your rights
|
||||
under this License for the current and all other versions of the Licensed Work.
|
||||
|
||||
This License does not grant you any right in any trademark or logo of Licensor or its affiliates
|
||||
(provided that you may use a trademark or logo of Licensor as expressly required by this License).
|
||||
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN “AS IS” BASIS.
|
||||
LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING
|
||||
(WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
NON-INFRINGEMENT, AND TITLE. MariaDB hereby grants you permission to use this License’s text to
|
||||
license your works, and to refer to it using the trademark “Business Source License”, as long as
|
||||
you comply with the Covenants of Licensor below.
|
||||
|
||||
Covenants of Licensor
|
||||
=====================
|
||||
In consideration of the right to use this License’s text and the “Business Source License”
|
||||
name and trademark, Licensor covenants to BitBank Software, Inc., and to all other recipients
|
||||
of the licensed work to be provided by Licensor:
|
||||
|
||||
To specify as the Change License the GPL Version 2.0 or any later version, or a license that is
|
||||
compatible with GPL Version 2.0 or a later version, where “compatible” means that software
|
||||
provided under the Change License can be included in a program with software provided under GPL
|
||||
Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation.
|
||||
To either: (a) specify an additional grant of rights to use that does not impose any additional
|
||||
restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the
|
||||
text “None” to specify a Change Date. Not to modify this License in any other way.
|
||||
For information about alternative licensing arrangements for the Software,
|
||||
please visit: https://bitbanksoftware.com/
|
||||
|
||||
Notice
|
||||
======
|
||||
The Business Source License (this document, or the “License”) is not an Open Source license.
|
||||
However, the Licensed Work will eventually be made available under an Open Source License,
|
||||
as stated in this License.
|
||||
|
||||
For more information on the use of the Business Source License for BitBank Software, Inc. products,
|
||||
please visit the site: https://bitbanksoftware.com
|
||||
The Business Source License (this document, or the “License”) is not an Open
|
||||
Source license. However, the Licensed Work will eventually be made available
|
||||
under an Open Source License, as stated in this License.
|
||||
|
||||
For more information on the use of the Business Source License generally, please visit
|
||||
the FAQ at https://mariadb.com/bsl-faq-adopting/
|
||||
License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
|
||||
“Business Source License” is a trademark of MariaDB Corporation Ab.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Business Source License 1.1
|
||||
|
||||
Terms
|
||||
|
||||
The Licensor hereby grants you the right to copy, modify, create derivative
|
||||
works, redistribute, and make non-production use of the Licensed Work. The
|
||||
Licensor may make an Additional Use Grant, above, permitting limited
|
||||
production use.
|
||||
|
||||
Effective on the Change Date, or the fourth anniversary of the first publicly
|
||||
available distribution of a specific version of the Licensed Work under this
|
||||
License, whichever comes first, the Licensor hereby grants you rights under
|
||||
the terms of the Change License, and the rights granted in the paragraph
|
||||
above terminate.
|
||||
|
||||
If your use of the Licensed Work does not comply with the requirements
|
||||
currently in effect as described in this License, you must purchase a
|
||||
commercial license from the Licensor, its affiliated entities, or authorized
|
||||
resellers, or you must refrain from using the Licensed Work.
|
||||
|
||||
All copies of the original and modified Licensed Work, and derivative works
|
||||
of the Licensed Work, are subject to this License. This License applies
|
||||
separately for each version of the Licensed Work and the Change Date may vary
|
||||
for each version of the Licensed Work released by Licensor.
|
||||
|
||||
You must conspicuously display this License on each original or modified copy
|
||||
of the Licensed Work. If you receive the Licensed Work in original or
|
||||
modified form from a third party, the terms and conditions set forth in this
|
||||
License apply to your use of that work.
|
||||
|
||||
Any use of the Licensed Work in violation of this License will automatically
|
||||
terminate your rights under this License for the current and all other
|
||||
versions of the Licensed Work.
|
||||
|
||||
This License does not grant you any right in any trademark or logo of
|
||||
Licensor or its affiliates (provided that you may use a trademark or logo of
|
||||
Licensor as expressly required by this License).
|
||||
|
||||
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
||||
AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
||||
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
||||
TITLE.
|
||||
|
||||
MariaDB hereby grants you permission to use this License’s text to license
|
||||
your works, and to refer to it using the trademark “Business Source License”,
|
||||
as long as you comply with the Covenants of Licensor below.
|
||||
|
||||
Covenants of Licensor
|
||||
|
||||
In consideration of the right to use this License’s text and the “Business
|
||||
Source License” name and trademark, Licensor covenants to MariaDB, and to all
|
||||
other recipients of the licensed work to be provided by Licensor:
|
||||
|
||||
1. To specify as the Change License the GPL Version 2.0 or any later version,
|
||||
or a license that is compatible with GPL Version 2.0 or a later version,
|
||||
where “compatible” means that software provided under the Change License can
|
||||
be included in a program with software provided under GPL Version 2.0 or a
|
||||
later version. Licensor may specify additional Change Licenses without
|
||||
limitation.
|
||||
|
||||
2. To either: (a) specify an additional grant of rights to use that does not
|
||||
impose any additional restriction on the right granted in this License, as
|
||||
the Additional Use Grant; or (b) insert the text “None”.
|
||||
|
||||
3. To specify a Change Date.
|
||||
|
||||
4. Not to modify this License in any other way.
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
//
|
||||
// I/O wrapper functions for the ESP-IDF
|
||||
//
|
||||
#ifndef __ESP_IDF_IO__
|
||||
#define __ESP_IDF_IO__
|
||||
|
||||
#define INPUT 0
|
||||
#define INPUT_PULLUP 1
|
||||
#define OUTPUT 2
|
||||
#define DISABLED 3
|
||||
#define PROGMEM
|
||||
#define HIGH 1
|
||||
#define LOW 0
|
||||
#define PIN_SCK 4
|
||||
#define PIN_MOSI 6
|
||||
|
||||
void digitalWrite(int iPin, int iState) {
|
||||
gpio_set_level((gpio_num_t)iPin, (uint32_t)iState);
|
||||
}
|
||||
void pinMode(int iPin, int iMode)
|
||||
{
|
||||
gpio_config_t io_conf = {};
|
||||
|
||||
gpio_reset_pin(iPin);
|
||||
if (iMode == DISABLED) return;
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
|
||||
//bit mask of the pins that you want to set,e.g.GPIO18/19
|
||||
io_conf.pin_bit_mask = (1ULL << iPin);
|
||||
io_conf.pull_down_en = 0; //disable pull-down mode
|
||||
io_conf.pull_up_en = (iMode == INPUT_PULLUP); // pull-up mode
|
||||
if (iMode == INPUT || iMode == INPUT_PULLUP) {
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
} else { // must be output
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
}
|
||||
gpio_config(&io_conf); //configure GPIO with the given settings
|
||||
} /* pinMode() */
|
||||
int digitalRead(int iPin)
|
||||
{
|
||||
return (int)gpio_get_level((gpio_num_t)iPin);
|
||||
} /* digitalRead() */
|
||||
void delayMicroseconds(long l)
|
||||
{
|
||||
l *= 40;
|
||||
while (l) {
|
||||
__asm__ __volatile__ ("nop");
|
||||
l--;
|
||||
}
|
||||
}
|
||||
void _delay(long l)
|
||||
{
|
||||
delayMicroseconds(l*1000);
|
||||
}
|
||||
void mymemset(void *d, uint8_t u8, int len)
|
||||
{
|
||||
uint8_t *d8;
|
||||
if (((intptr_t)d & 3) == 0) { // dword aligned
|
||||
uint32_t u32, *d32 = (uint32_t *)d;
|
||||
u32 = u8 | (u8 << 8);
|
||||
u32 |= (u32 << 16);
|
||||
while (len >= 4) {
|
||||
*d32++ = u32;
|
||||
len -= 4;
|
||||
}
|
||||
d = d32;
|
||||
}
|
||||
d8 = (uint8_t *)d;
|
||||
while (len) {
|
||||
*d8++ = u8;
|
||||
len--;
|
||||
}
|
||||
} /* mymemset() */
|
||||
void mymemcpy(void *d, void *s, size_t iLen)
|
||||
{
|
||||
uint8_t *d8 = (uint8_t *)d;
|
||||
uint8_t *s8 = (uint8_t *)s;
|
||||
while (iLen) {
|
||||
*d8++ = *s8++;
|
||||
iLen--;
|
||||
}
|
||||
} /* mymemcpy() */
|
||||
//
|
||||
// Convert a number into a fixed length, zero-terminated string
|
||||
//
|
||||
void i2strf(char *pDest, int iVal, int iDigits)
|
||||
{
|
||||
char *d = pDest;
|
||||
int i;
|
||||
pDest[iDigits] = 0;
|
||||
while (iDigits) {
|
||||
iDigits--;
|
||||
i = iVal % 10;
|
||||
d[iDigits] = '0' + (char)i;
|
||||
iVal /= 10;
|
||||
}
|
||||
} /* i2strf() */
|
||||
//
|
||||
// Convert a number into a zero-terminated string
|
||||
//
|
||||
int i2str(char *pDest, int iVal)
|
||||
{
|
||||
char *d = pDest;
|
||||
int i, iPlaceVal = 10000;
|
||||
int iDigits = 0;
|
||||
|
||||
if (iVal < 0) {
|
||||
iDigits++;
|
||||
*d++ = '-';
|
||||
iVal = -iVal;
|
||||
}
|
||||
while (iPlaceVal) {
|
||||
if (iVal >= iPlaceVal) {
|
||||
i = iVal / iPlaceVal;
|
||||
*d++ = '0' + (char)i;
|
||||
iVal -= (i*iPlaceVal);
|
||||
iDigits++;
|
||||
} else if (iDigits != 0) {
|
||||
*d++ = '0'; // non-zeros were already displayed
|
||||
}
|
||||
iPlaceVal /= 10;
|
||||
}
|
||||
if (d == pDest) // must be zero
|
||||
*d++ = '0';
|
||||
*d++ = 0; // terminator
|
||||
return (int)(d - pDest - 1); // string length
|
||||
} /* i2str() */
|
||||
void delayCycles(int i)
|
||||
{
|
||||
while (i > 3) {
|
||||
__asm__ __volatile__ ("nop\n\t");
|
||||
i -= 3;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Bit Bang SPI
|
||||
//
|
||||
void SPIWriteByte(uint8_t uc)
|
||||
{
|
||||
if (uc == 0 || uc == 0xff) { // special case
|
||||
digitalWrite(PIN_MOSI, (uc & 1));
|
||||
delayCycles(5);
|
||||
for (int i=0; i<8; i++) {
|
||||
digitalWrite(PIN_SCK, 1); // no delays needed since it runs at a slow clock
|
||||
delayCycles(5);
|
||||
digitalWrite(PIN_SCK, 0);
|
||||
delayCycles(5);
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<8; i++) {
|
||||
digitalWrite(PIN_MOSI, (uc & 0x80) != 0); // MSB first
|
||||
delayCycles(5);
|
||||
digitalWrite(PIN_SCK, 1);
|
||||
uc <<= 1;
|
||||
delayCycles(5);
|
||||
digitalWrite(PIN_SCK, 0);
|
||||
delayCycles(5);
|
||||
}
|
||||
}
|
||||
} /* SPIWriteByte() */
|
||||
//
|
||||
// Need to bit-bang I2C
|
||||
//
|
||||
uint8_t SDA_READ(void)
|
||||
{
|
||||
return digitalRead(PIN_SDA);
|
||||
}
|
||||
void SDA_HIGH(void)
|
||||
{
|
||||
pinMode(PIN_SDA, INPUT_PULLUP);
|
||||
}
|
||||
void SDA_LOW(void)
|
||||
{
|
||||
pinMode(PIN_SDA, OUTPUT);
|
||||
digitalWrite(PIN_SDA, LOW);
|
||||
}
|
||||
void SCL_HIGH(void)
|
||||
{
|
||||
pinMode(PIN_SCL, INPUT_PULLUP);
|
||||
}
|
||||
void SCL_LOW(void)
|
||||
{
|
||||
pinMode(PIN_SCL, OUTPUT);
|
||||
digitalWrite(PIN_SCL, LOW);
|
||||
}
|
||||
// Transmit a byte and read the ack bit
|
||||
// if we get a NACK (negative acknowledge) return 0
|
||||
// otherwise return 1 for success
|
||||
//
|
||||
|
||||
int i2cByteOut(uint8_t b)
|
||||
{
|
||||
uint8_t i, ack;
|
||||
|
||||
for (i=0; i<8; i++) {
|
||||
// my_sleep_us(iDelay);
|
||||
if (b & 0x80)
|
||||
SDA_HIGH(); // set data line to 1
|
||||
else
|
||||
SDA_LOW(); // set data line to 0
|
||||
b <<= 1;
|
||||
// my_sleep_us(iDelay);
|
||||
SCL_HIGH(); // clock high (slave latches data)
|
||||
delayMicroseconds(1);
|
||||
SCL_LOW(); // clock low
|
||||
delayMicroseconds(1);
|
||||
} // for i
|
||||
//my_sleep_us(iDelay);
|
||||
// read ack bit
|
||||
SDA_HIGH(); // set data line for reading
|
||||
//my_sleep_us(iDelay);
|
||||
SCL_HIGH(); // clock line high
|
||||
delayMicroseconds(1);
|
||||
ack = SDA_READ();
|
||||
//my_sleep_us(iDelay);
|
||||
SCL_LOW(); // clock low
|
||||
delayMicroseconds(1);
|
||||
SDA_LOW(); // data low
|
||||
return (ack == 0); // a low ACK bit means success
|
||||
} /* i2cByteOut() */
|
||||
//
|
||||
// Receive a byte and read the ack bit
|
||||
// if we get a NACK (negative acknowledge) return 0
|
||||
// otherwise return 1 for success
|
||||
//
|
||||
uint8_t i2cByteIn(uint8_t bLast)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t b = 0;
|
||||
|
||||
SDA_HIGH(); // set data line as input
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
delayMicroseconds(1);
|
||||
SCL_HIGH(); // clock high (slave latches data)
|
||||
delayMicroseconds(1);
|
||||
b <<= 1;
|
||||
if (SDA_READ() != 0) // read the data bit
|
||||
b |= 1; // set data bit
|
||||
SCL_LOW(); // clock low
|
||||
} // for i
|
||||
if (bLast)
|
||||
SDA_HIGH(); // last byte sends a NACK
|
||||
else
|
||||
SDA_LOW();
|
||||
// my_sleep_us(iDelay);
|
||||
SCL_HIGH(); // clock high
|
||||
delayMicroseconds(1);
|
||||
SCL_LOW(); // clock low to send ack
|
||||
delayMicroseconds(1);
|
||||
// SDA_HIGH();
|
||||
SDA_LOW(); // data low
|
||||
return b;
|
||||
} /* i2cByteIn() */
|
||||
//
|
||||
// Send I2C STOP condition
|
||||
//
|
||||
void i2cEnd(void)
|
||||
{
|
||||
SDA_LOW(); // data line low
|
||||
delayMicroseconds(1);
|
||||
SCL_HIGH(); // clock high
|
||||
delayMicroseconds(1);
|
||||
SDA_HIGH(); // data high
|
||||
delayMicroseconds(1);
|
||||
} /* i2cEnd() */
|
||||
|
||||
int i2cBegin(uint8_t addr, uint8_t bRead)
|
||||
{
|
||||
int rc;
|
||||
// SCL_HIGH();
|
||||
// my_sleep_us(iDelay);
|
||||
SDA_LOW(); // data line low first
|
||||
delayMicroseconds(1);
|
||||
SCL_LOW(); // then clock line low is a START signal
|
||||
addr <<= 1;
|
||||
if (bRead)
|
||||
addr++; // set read bit
|
||||
rc = i2cByteOut(addr); // send the slave address and R/W bit
|
||||
return rc;
|
||||
} /* i2cBegin() */
|
||||
void I2CWrite(uint8_t addr, uint8_t *pData, int iLen)
|
||||
{
|
||||
uint8_t b;
|
||||
int rc;
|
||||
|
||||
i2cBegin(addr, 0);
|
||||
rc = 1;
|
||||
while (iLen && rc == 1)
|
||||
{
|
||||
b = *pData++;
|
||||
rc = i2cByteOut(b);
|
||||
if (rc == 1) // success
|
||||
{
|
||||
iLen--;
|
||||
}
|
||||
} // for each byte
|
||||
i2cEnd();
|
||||
//return (rc == 1) ? (iOldLen - iLen) : 0; // 0 indicates bad ack from sending a byte
|
||||
} /* I2CWrite() */
|
||||
int I2CRead(uint8_t addr, uint8_t *pData, int iLen)
|
||||
{
|
||||
i2cBegin(addr, 1);
|
||||
while (iLen--)
|
||||
{
|
||||
*pData++ = i2cByteIn(iLen == 0);
|
||||
} // for each byte
|
||||
i2cEnd();
|
||||
return 1;
|
||||
} /* I2CRead() */
|
||||
|
||||
int I2CTest(uint8_t addr)
|
||||
{
|
||||
int response = 0;
|
||||
|
||||
if (i2cBegin(addr, 0)) // try to write to the given address
|
||||
{
|
||||
response = 1;
|
||||
}
|
||||
i2cEnd();
|
||||
return response;
|
||||
} /* I2CTest() */
|
||||
|
||||
void I2CInit(void)
|
||||
{
|
||||
pinMode(PIN_SDA, INPUT_PULLUP);
|
||||
pinMode(PIN_SCL, INPUT_PULLUP);
|
||||
}
|
||||
void I2CDeInit(void)
|
||||
{
|
||||
pinMode(PIN_SDA, DISABLED);
|
||||
pinMode(PIN_SCL, DISABLED);
|
||||
}
|
||||
//
|
||||
// Read N bytes starting at a specific I2C internal register
|
||||
// returns 1 for success, 0 for error
|
||||
//
|
||||
void I2CReadRegister(uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen)
|
||||
{
|
||||
I2CWrite(iAddr, &u8Register, 1);
|
||||
I2CRead(iAddr, pData, iLen);
|
||||
} /* I2CReadRegister() */
|
||||
|
||||
#endif // __ESP_IDF_IO__
|
||||
@@ -0,0 +1,331 @@
|
||||
// Created with image_to_c
|
||||
// https://github.com/bitbank2/image_to_c
|
||||
//
|
||||
// Roboto_Black_40
|
||||
// Data size = 5105 bytes
|
||||
//
|
||||
// for non-Arduino builds...
|
||||
#ifndef PROGMEM
|
||||
#define PROGMEM
|
||||
#endif
|
||||
const uint8_t Roboto_Black_40[] PROGMEM = {
|
||||
0xff,0xbb,0x20,0x00,0x7e,0x00,0x5c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x13,
|
||||
0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x0e,0x16,0x38,0x00,0x04,0x00,0xca,0xff,
|
||||
0x21,0x00,0x16,0x19,0x16,0x00,0x01,0x00,0xc6,0xff,0x2d,0x00,0x2b,0x2d,0x37,0x00,
|
||||
0x01,0x00,0xca,0xff,0x68,0x00,0x27,0x2d,0x49,0x00,0x03,0x00,0xc1,0xff,0xba,0x00,
|
||||
0x34,0x3a,0x39,0x00,0x03,0x00,0xc9,0xff,0x18,0x01,0x31,0x35,0x39,0x00,0x02,0x00,
|
||||
0xc9,0xff,0x68,0x01,0x09,0x0c,0x16,0x00,0x02,0x00,0xc6,0xff,0x6d,0x01,0x15,0x1c,
|
||||
0x4e,0x00,0x05,0x00,0xc4,0xff,0xa2,0x01,0x17,0x1b,0x4e,0x00,0x01,0x00,0xc4,0xff,
|
||||
0xde,0x01,0x23,0x24,0x22,0x00,0x01,0x00,0xca,0xff,0x14,0x02,0x26,0x2a,0x27,0x00,
|
||||
0x02,0x00,0xd4,0xff,0x2d,0x02,0x0e,0x15,0x19,0x00,0x02,0x00,0xf7,0xff,0x3f,0x02,
|
||||
0x17,0x23,0x0a,0x00,0x06,0x00,0xe4,0xff,0x41,0x02,0x0f,0x18,0x0d,0x00,0x04,0x00,
|
||||
0xf4,0xff,0x50,0x02,0x1c,0x1b,0x3c,0x00,0xff,0xff,0xca,0xff,0x79,0x02,0x27,0x2d,
|
||||
0x39,0x00,0x03,0x00,0xc9,0xff,0xb1,0x02,0x1a,0x2d,0x37,0x00,0x06,0x00,0xca,0xff,
|
||||
0xd1,0x02,0x28,0x2d,0x38,0x00,0x02,0x00,0xc9,0xff,0x0a,0x03,0x28,0x2d,0x39,0x00,
|
||||
0x02,0x00,0xc9,0xff,0x4f,0x03,0x29,0x2d,0x37,0x00,0x02,0x00,0xca,0xff,0x7e,0x03,
|
||||
0x27,0x2d,0x38,0x00,0x03,0x00,0xca,0xff,0xbb,0x03,0x28,0x2d,0x39,0x00,0x03,0x00,
|
||||
0xc9,0xff,0x00,0x04,0x28,0x2d,0x37,0x00,0x02,0x00,0xca,0xff,0x24,0x04,0x27,0x2d,
|
||||
0x39,0x00,0x03,0x00,0xc9,0xff,0x6b,0x04,0x27,0x2d,0x39,0x00,0x03,0x00,0xc9,0xff,
|
||||
0xae,0x04,0x0f,0x17,0x2b,0x00,0x04,0x00,0xd6,0xff,0xcf,0x04,0x10,0x16,0x3a,0x00,
|
||||
0x03,0x00,0xd6,0xff,0xf6,0x04,0x21,0x28,0x26,0x00,0x02,0x00,0xd7,0xff,0x23,0x05,
|
||||
0x23,0x2e,0x1b,0x00,0x05,0x00,0xdb,0xff,0x2b,0x05,0x22,0x28,0x26,0x00,0x04,0x00,
|
||||
0xd7,0xff,0x56,0x05,0x24,0x28,0x38,0x00,0x01,0x00,0xc9,0xff,0x8d,0x05,0x41,0x46,
|
||||
0x47,0x00,0x02,0x00,0xcb,0xff,0x16,0x06,0x35,0x35,0x37,0x00,0x00,0x00,0xca,0xff,
|
||||
0x4e,0x06,0x2b,0x32,0x37,0x00,0x04,0x00,0xca,0xff,0x7a,0x06,0x2e,0x33,0x39,0x00,
|
||||
0x03,0x00,0xc9,0xff,0xb8,0x06,0x2c,0x32,0x37,0x00,0x04,0x00,0xca,0xff,0xe1,0x06,
|
||||
0x26,0x2c,0x37,0x00,0x04,0x00,0xca,0xff,0xf4,0x06,0x25,0x2b,0x37,0x00,0x04,0x00,
|
||||
0xca,0xff,0x06,0x07,0x2f,0x35,0x39,0x00,0x03,0x00,0xc9,0xff,0x47,0x07,0x2f,0x37,
|
||||
0x37,0x00,0x04,0x00,0xca,0xff,0x5e,0x07,0x0d,0x18,0x37,0x00,0x05,0x00,0xca,0xff,
|
||||
0x65,0x07,0x27,0x2c,0x38,0x00,0x01,0x00,0xca,0xff,0x8c,0x07,0x2f,0x32,0x37,0x00,
|
||||
0x04,0x00,0xca,0xff,0xba,0x07,0x25,0x2a,0x37,0x00,0x04,0x00,0xca,0xff,0xcb,0x07,
|
||||
0x3c,0x44,0x37,0x00,0x04,0x00,0xca,0xff,0x01,0x08,0x2f,0x37,0x37,0x00,0x04,0x00,
|
||||
0xca,0xff,0x26,0x08,0x30,0x36,0x39,0x00,0x03,0x00,0xc9,0xff,0x69,0x08,0x2c,0x33,
|
||||
0x37,0x00,0x04,0x00,0xca,0xff,0x8d,0x08,0x30,0x36,0x42,0x00,0x03,0x00,0xc9,0xff,
|
||||
0xdc,0x08,0x2d,0x33,0x37,0x00,0x04,0x00,0xca,0xff,0x07,0x09,0x2b,0x31,0x39,0x00,
|
||||
0x03,0x00,0xc9,0xff,0x52,0x09,0x2f,0x31,0x37,0x00,0x01,0x00,0xca,0xff,0x6e,0x09,
|
||||
0x2c,0x34,0x38,0x00,0x04,0x00,0xca,0xff,0x95,0x09,0x34,0x34,0x37,0x00,0x00,0x00,
|
||||
0xca,0xff,0xcc,0x09,0x42,0x44,0x37,0x00,0x01,0x00,0xca,0xff,0x17,0x0a,0x32,0x32,
|
||||
0x37,0x00,0x00,0x00,0xca,0xff,0x5a,0x0a,0x31,0x31,0x37,0x00,0x00,0x00,0xca,0xff,
|
||||
0x8d,0x0a,0x2c,0x30,0x37,0x00,0x02,0x00,0xca,0xff,0xb6,0x0a,0x11,0x16,0x4e,0x00,
|
||||
0x04,0x00,0xc0,0xff,0xcb,0x0a,0x25,0x21,0x3c,0x00,0xff,0xff,0xca,0xff,0xf7,0x0a,
|
||||
0x11,0x16,0x4e,0x00,0x01,0x00,0xc0,0xff,0x11,0x0b,0x21,0x23,0x1b,0x00,0x01,0x00,
|
||||
0xca,0xff,0x31,0x0b,0x22,0x22,0x0a,0x00,0x00,0x00,0x01,0x00,0x33,0x0b,0x15,0x1a,
|
||||
0x0c,0x00,0x02,0x00,0xc6,0xff,0x40,0x0b,0x26,0x29,0x2b,0x00,0x02,0x00,0xd7,0xff,
|
||||
0x78,0x0b,0x26,0x2c,0x3c,0x00,0x04,0x00,0xc6,0xff,0xa3,0x0b,0x25,0x29,0x2b,0x00,
|
||||
0x02,0x00,0xd7,0xff,0xd4,0x0b,0x26,0x2c,0x3c,0x00,0x02,0x00,0xc6,0xff,0x05,0x0c,
|
||||
0x27,0x2a,0x2b,0x00,0x02,0x00,0xd7,0xff,0x3c,0x0c,0x1c,0x1c,0x3b,0x00,0x00,0x00,
|
||||
0xc6,0xff,0x63,0x0c,0x27,0x2d,0x3a,0x00,0x02,0x00,0xd7,0xff,0xa8,0x0c,0x25,0x2c,
|
||||
0x3b,0x00,0x03,0x00,0xc6,0xff,0xc7,0x0c,0x0e,0x15,0x3a,0x00,0x03,0x00,0xc7,0xff,
|
||||
0xe6,0x0c,0x16,0x15,0x4b,0x00,0xfc,0xff,0xc7,0xff,0x15,0x0d,0x28,0x2b,0x3b,0x00,
|
||||
0x04,0x00,0xc6,0xff,0x3d,0x0d,0x0d,0x15,0x3b,0x00,0x04,0x00,0xc6,0xff,0x45,0x0d,
|
||||
0x3b,0x43,0x2a,0x00,0x04,0x00,0xd7,0xff,0x74,0x0d,0x26,0x2c,0x2a,0x00,0x03,0x00,
|
||||
0xd7,0xff,0x91,0x0d,0x28,0x2c,0x2b,0x00,0x02,0x00,0xd7,0xff,0xc3,0x0d,0x26,0x2c,
|
||||
0x3a,0x00,0x04,0x00,0xd7,0xff,0xee,0x0d,0x26,0x2c,0x3a,0x00,0x02,0x00,0xd7,0xff,
|
||||
0x20,0x0e,0x19,0x1e,0x2a,0x00,0x04,0x00,0xd7,0xff,0x32,0x0e,0x25,0x28,0x2b,0x00,
|
||||
0x01,0x00,0xd7,0xff,0x72,0x0e,0x19,0x1b,0x34,0x00,0x01,0x00,0xce,0xff,0x95,0x0e,
|
||||
0x26,0x2c,0x2a,0x00,0x03,0x00,0xd8,0xff,0xb2,0x0e,0x28,0x28,0x29,0x00,0x00,0x00,
|
||||
0xd8,0xff,0xd9,0x0e,0x37,0x39,0x29,0x00,0x01,0x00,0xd8,0xff,0x13,0x0f,0x28,0x28,
|
||||
0x29,0x00,0x00,0x00,0xd8,0xff,0x43,0x0f,0x28,0x28,0x3a,0x00,0x00,0x00,0xd8,0xff,
|
||||
0x78,0x0f,0x23,0x28,0x29,0x00,0x03,0x00,0xd8,0xff,0x94,0x0f,0x17,0x19,0x4b,0x00,
|
||||
0x01,0x00,0xc4,0xff,0xcc,0x0f,0x07,0x14,0x41,0x00,0x07,0x00,0xca,0xff,0xd5,0x0f,
|
||||
0x17,0x19,0x4b,0x00,0x01,0x00,0xc4,0xff,0x0f,0x10,0x2a,0x31,0x12,0x00,0x03,0x00,
|
||||
0xe1,0xff,0x42,0x90,0x1f,0xff,0xff,0xff,0xff,0xff,0xaf,0xff,0xff,0xff,0xdf,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xc9,0x36,0x83,0xc2,0x7d,0x8f,0xc8,0x0f,0x5b,
|
||||
0x58,0x61,0x40,0x32,0x6f,0xff,0xff,0xfd,0x7f,0xfd,0x7f,0xff,0xfd,0x7f,0xf0,0x28,
|
||||
0x3c,0xc4,0x62,0xf3,0x34,0xbf,0xeb,0xff,0xf5,0xff,0x5f,0xae,0xbf,0xff,0x5f,0xf5,
|
||||
0xfa,0xeb,0xe5,0x74,0x7f,0xff,0xf3,0x96,0x41,0x37,0xff,0xaf,0xd7,0xfd,0x7f,0xaf,
|
||||
0xfa,0xfd,0x62,0x27,0x44,0x8f,0xff,0x28,0x20,0xc4,0x63,0x90,0x97,0xfe,0xba,0xfd,
|
||||
0x75,0xff,0xfa,0xff,0xaf,0xd7,0x5f,0xff,0xaf,0xe0,0x28,0x48,0xb9,0x0f,0xff,0xff,
|
||||
0xff,0x82,0x0f,0x04,0x0f,0x08,0x3c,0x27,0xa0,0xf4,0xf5,0xd3,0xef,0x5e,0x63,0xeb,
|
||||
0xe1,0x3e,0xaf,0xd5,0xf7,0xff,0xff,0xc7,0x7b,0x7d,0xf7,0xb0,0xf6,0x0f,0x87,0xb0,
|
||||
0xf0,0xc3,0xdb,0xd8,0x78,0x6f,0x0d,0xe0,0xde,0x1f,0x0d,0xe1,0xbd,0xf7,0x9c,0xd3,
|
||||
0x3b,0x7f,0xf2,0x02,0xfd,0xa5,0xda,0xf6,0xbb,0x1f,0x5b,0xed,0x6d,0x6d,0x6d,0x61,
|
||||
0xac,0x30,0xb0,0x67,0x30,0xe8,0x30,0x5f,0xff,0xff,0xff,0x00,0x28,0x24,0xe4,0x4f,
|
||||
0x04,0x0f,0x4f,0x09,0xf7,0xa6,0x63,0x0e,0xa8,0x3e,0x62,0xa6,0x1f,0x4d,0xa7,0xd7,
|
||||
0x51,0xba,0xfa,0x5f,0xfa,0x5f,0x5e,0xb2,0x03,0x54,0xbb,0xfe,0xd5,0x2e,0x29,0x2d,
|
||||
0xfd,0xa4,0xba,0xac,0x34,0xbb,0x09,0x2c,0x18,0x5e,0x29,0x69,0x7e,0x97,0xe9,0x17,
|
||||
0x91,0xa4,0x08,0x1f,0xa7,0xa4,0x83,0xe9,0x75,0x4f,0x4a,0xfd,0x18,0xa9,0xd2,0xa7,
|
||||
0xd2,0xa7,0xff,0xd2,0xff,0xee,0x97,0xd2,0xff,0xd6,0x97,0xf5,0x7e,0xb6,0x17,0x06,
|
||||
0x98,0xf0,0xf5,0x8b,0x5b,0xec,0x2d,0xac,0x18,0x28,0x28,0x40,0xe4,0xbf,0x04,0x0f,
|
||||
0x09,0xe8,0x3d,0x3d,0x3d,0x7b,0xd7,0xbe,0x63,0x2f,0x49,0xfd,0xfa,0xff,0xff,0xfe,
|
||||
0xd7,0xd2,0xdb,0x5f,0x09,0x6c,0x57,0x5b,0x5d,0x6d,0x75,0xc2,0xd4,0xe5,0x17,0xa7,
|
||||
0xe1,0x3f,0x4f,0xd3,0xff,0xd1,0x8d,0x2d,0x74,0x9b,0xaf,0x6f,0xea,0x38,0xdf,0x6b,
|
||||
0x7d,0xf6,0xad,0xf6,0xa4,0x05,0xd7,0x0c,0x2f,0x17,0xb7,0xde,0xfb,0x7b,0x7b,0x33,
|
||||
0x45,0xe1,0x85,0x78,0x61,0x37,0x06,0x72,0xe0,0x00,0xff,0xd7,0xff,0xff,0xf0,0x28,
|
||||
0x90,0x43,0x0b,0x84,0xf5,0xd3,0xad,0x69,0x75,0xa5,0xa5,0xd6,0xba,0x5f,0xa5,0xfd,
|
||||
0x6b,0xfd,0x6b,0xff,0xa5,0xff,0xff,0x1d,0x7f,0xff,0xff,0xff,0xf7,0x20,0x3f,0xff,
|
||||
0xfd,0xbf,0xfd,0xfb,0xfd,0xfb,0xfd,0xbf,0xdb,0xdf,0xbd,0xbd,0xbe,0xf6,0xef,0x7b,
|
||||
0x5b,0xe1,0xac,0x3c,0x20,0x65,0x34,0xa0,0xfb,0xd0,0x7d,0xf7,0x17,0x20,0x5d,0xbd,
|
||||
0xbe,0xf7,0xdb,0xef,0x7e,0xf7,0xfd,0xbf,0xef,0xf7,0xef,0xff,0x7e,0xff,0xff,0xff,
|
||||
0xff,0xbf,0xff,0xff,0xeb,0xff,0xff,0xff,0xfa,0xd7,0xff,0xad,0x7f,0xad,0x7a,0xfd,
|
||||
0x7a,0xd7,0xad,0x2d,0x7a,0xd2,0xd7,0x4a,0x2a,0x40,0x57,0x5b,0x0b,0xad,0x85,0x00,
|
||||
0x28,0x38,0xe4,0x25,0xff,0xff,0xaf,0xff,0xc8,0x9e,0x62,0x97,0x0f,0x05,0xd0,0x78,
|
||||
0x4f,0x83,0x70,0xbc,0x38,0xe2,0x2e,0x40,0x96,0x0c,0xec,0x95,0x39,0x28,0xe0,0xc1,
|
||||
0x7e,0x9e,0x9e,0x8c,0x41,0x7a,0x57,0xab,0x7a,0x4f,0xa5,0x7e,0xde,0x95,0xed,0x35,
|
||||
0x87,0x61,0x6d,0x56,0xd3,0x0a,0x28,0x34,0xe6,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xe2,0x66,0x57,0xfc,0xa0,0xd3,0x98,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x20,
|
||||
0x9f,0xff,0xff,0xff,0xfd,0x2f,0xff,0xd2,0xfd,0x2f,0x8a,0xa9,0x01,0xe1,0xac,0x35,
|
||||
0x00,0xff,0xc0,0x20,0xa4,0xba,0x10,0x7a,0x7a,0x7f,0x17,0x20,0x3d,0x7e,0xd6,0xd6,
|
||||
0x18,0x50,0x28,0x9e,0xba,0xfd,0x7a,0xfd,0x7a,0xfd,0x7a,0xff,0xd2,0xff,0xd2,0xff,
|
||||
0xd7,0xaf,0xd7,0xaf,0xd7,0xaf,0xfd,0x2f,0xfd,0x2f,0xfd,0x2f,0xfd,0x2f,0xfd,0x7a,
|
||||
0xfd,0x7a,0xff,0xd2,0xff,0xd2,0xff,0xd2,0xff,0x8a,0xe0,0x28,0x3c,0xe4,0xa1,0x39,
|
||||
0x68,0xe1,0x07,0xa7,0xa7,0xa7,0xa7,0xa7,0xaf,0x7a,0x31,0xf7,0xd3,0x7d,0x3e,0x93,
|
||||
0x7f,0xff,0xd3,0xff,0x1d,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf9,0x01,0xd7,0xfd,
|
||||
0xaf,0xff,0xed,0xa5,0xda,0xf6,0x96,0xc7,0xb5,0xfb,0x5b,0x5b,0x5b,0x5b,0x58,0x61,
|
||||
0x60,0xc1,0x40,0x28,0xbe,0x0b,0x05,0x82,0xc1,0x60,0xb0,0x58,0x28,0xfe,0x66,0x18,
|
||||
0x2c,0x16,0x54,0xb8,0x5f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0x80,0x28,0x3c,0xe5,0x9d,0x04,0x0f,0x08,0x3c,0x20,0xf4,0xf4,0xf4,0xf4,
|
||||
0xf5,0xef,0x46,0x3e,0xfa,0x0f,0xa4,0xfd,0x7f,0x71,0x4f,0xff,0xd4,0xa1,0x9f,0xeb,
|
||||
0xd6,0xbd,0x6b,0xa5,0xaf,0x5a,0x5a,0x5a,0x5a,0x5a,0xe9,0x69,0x69,0x69,0x69,0x69,
|
||||
0x69,0x69,0x69,0x69,0x6b,0xa5,0xa3,0x4c,0x2b,0xff,0xff,0xfe,0x28,0x38,0xe5,0x9f,
|
||||
0x04,0x74,0x8b,0x84,0x1e,0x10,0x7a,0x7a,0x7a,0x7a,0x7a,0xf7,0xa3,0x21,0xbc,0x26,
|
||||
0xfa,0x7f,0x7e,0xbc,0x7f,0xff,0xfd,0x2d,0x70,0x96,0x73,0x57,0xeb,0xae,0xb8,0x5d,
|
||||
0xf0,0xfb,0xef,0xbc,0xeb,0x9f,0x86,0xf7,0xfd,0xbf,0xf9,0xcd,0x3b,0xea,0xf6,0x94,
|
||||
0x80,0x86,0x17,0x8a,0xdf,0xad,0xf6,0x16,0xd6,0xd6,0x18,0x58,0x30,0xb0,0x67,0x2c,
|
||||
0xf0,0x28,0x58,0xe6,0x9b,0x5f,0xd7,0xf5,0xd7,0xf5,0xd7,0xf5,0xd7,0xf5,0xfd,0x75,
|
||||
0xe6,0x28,0xf5,0xf4,0xbe,0xbd,0x7d,0x2f,0xfd,0x2f,0xaf,0x5f,0x4b,0xff,0x4b,0xd2,
|
||||
0xff,0xd0,0x99,0x3f,0xc7,0xc8,0x0f,0xff,0x3a,0xc6,0xff,0xff,0xff,0xff,0xff,0xfc,
|
||||
0x20,0x81,0x0f,0xff,0xff,0xff,0xd7,0xf9,0xcc,0x67,0xff,0xf5,0xfa,0xff,0xf9,0x61,
|
||||
0x1e,0x08,0xe7,0x95,0x8b,0xe1,0xf7,0xde,0x9f,0xf7,0xcc,0x76,0xe4,0xdc,0x37,0x98,
|
||||
0xa4,0xf8,0xbf,0xef,0xdf,0xff,0xf3,0x9a,0x6e,0x95,0xfa,0xc8,0x0b,0xf8,0x61,0x2d,
|
||||
0x8f,0xad,0xad,0xf6,0xb6,0xb6,0xb0,0xc2,0xc3,0x0b,0x39,0xe4,0xc0,0x28,0x60,0xbc,
|
||||
0x99,0xd4,0x2f,0x05,0xc2,0xe1,0x75,0xc2,0xeb,0xae,0xba,0x3a,0x87,0x67,0x41,0x2a,
|
||||
0x0b,0x4b,0xad,0x2e,0xb4,0xbf,0xa2,0xe2,0x35,0x04,0x0f,0xc2,0x0f,0xa4,0xf8,0xb8,
|
||||
0xbb,0xef,0x99,0x1a,0xe1,0x07,0xa7,0xa7,0xee,0xff,0xff,0xc8,0x0f,0xfe,0xd2,0xff,
|
||||
0x6d,0x7b,0x4b,0x6c,0x2f,0x1e,0xd6,0xd7,0x5b,0xec,0x2c,0x35,0xb0,0xb0,0xc2,0xce,
|
||||
0x81,0x30,0xff,0x5c,0xa1,0xa5,0xfa,0xf5,0xaf,0x5a,0xf5,0xaf,0xf5,0xaf,0x5a,0xf5,
|
||||
0xaf,0xe9,0x7e,0x97,0xe9,0x7f,0x5a,0xfe,0x97,0xe9,0x7e,0x97,0xeb,0xd6,0xbd,0x7e,
|
||||
0x97,0xeb,0xd6,0xbd,0x6b,0xd4,0x28,0x38,0xe5,0x9f,0x04,0x0f,0x04,0x0f,0x4f,0x4f,
|
||||
0x4f,0x4f,0x4f,0xf4,0xf9,0x8f,0xbe,0x9f,0x49,0xbe,0x9f,0xff,0xff,0xff,0x6d,0x2f,
|
||||
0xfb,0x5d,0xb4,0xb6,0x2b,0xf6,0xb0,0xc2,0xda,0xfc,0x20,0xf4,0xf4,0xf4,0xf4,0x63,
|
||||
0xeb,0xe1,0x07,0xd2,0x6f,0xfe,0x9e,0x3b,0xff,0xfe,0xd4,0x80,0xeb,0xb5,0xe1,0x85,
|
||||
0xe2,0xb7,0xda,0xfd,0xad,0xac,0x30,0xb6,0xb0,0xc2,0xce,0x71,0x70,0x28,0x3c,0xe4,
|
||||
0xa1,0x04,0x0f,0x08,0x3c,0x27,0xa0,0xf4,0xf4,0xf5,0xd3,0xef,0x46,0x3e,0xfa,0x6f,
|
||||
0x49,0xfa,0x7f,0xb8,0xaf,0x7f,0xfe,0xff,0xfd,0xfc,0x80,0xb5,0xda,0xed,0x6c,0x7e,
|
||||
0xd7,0xef,0xbe,0xcc,0x99,0xed,0x2e,0x1a,0xac,0x18,0x2f,0x15,0xeb,0x5e,0xb0,0xba,
|
||||
0x58,0x5c,0x12,0xce,0x43,0x1d,0x75,0xd7,0x5c,0x2e,0xb8,0x2e,0x17,0x39,0x0c,0x00,
|
||||
0x20,0xa4,0xba,0x10,0x7a,0x7a,0x7f,0x17,0x20,0x3d,0x7e,0xd6,0xd6,0x18,0x58,0xff,
|
||||
0xff,0xff,0xff,0xe4,0xb7,0x08,0x3d,0x3d,0x3f,0x8b,0x90,0x1e,0xbf,0x6b,0x6b,0x0c,
|
||||
0x28,0x20,0xc4,0xb6,0x10,0x7a,0x7a,0x7f,0xa7,0xef,0xaf,0xda,0xda,0xc3,0x0b,0x1f,
|
||||
0xff,0xff,0xff,0xff,0xf2,0xc5,0x7f,0xff,0xff,0xff,0xff,0xfe,0x97,0xff,0xe9,0x7e,
|
||||
0x97,0xc5,0x54,0x80,0xf0,0xd6,0x1a,0x80,0x28,0x83,0x0b,0x05,0x85,0x82,0xc2,0xc2,
|
||||
0xc1,0x61,0x60,0xb0,0xb0,0x58,0x41,0x61,0x05,0x10,0x50,0x50,0x50,0x50,0x5c,0x1c,
|
||||
0x1c,0x1c,0x1c,0x80,0x83,0xc3,0x0f,0x0c,0x38,0x3c,0x3c,0x1e,0x1e,0x0f,0x0f,0x0f,
|
||||
0x07,0x87,0x83,0xc3,0x80,0xff,0xca,0x28,0xff,0xf3,0x47,0x7f,0xe0,0x29,0x9c,0x1c,
|
||||
0x38,0x38,0x70,0xe0,0xe1,0xc1,0xc3,0x83,0x87,0x20,0x41,0xe0,0xc1,0xe0,0xdc,0x1e,
|
||||
0x0f,0x07,0x83,0xd6,0x0b,0x0b,0x05,0x82,0xc1,0x2c,0x10,0x28,0x85,0x0a,0x0a,0x14,
|
||||
0x14,0x28,0x50,0x50,0xa0,0xa1,0x41,0x40,0x28,0x34,0xe5,0xa1,0x04,0x74,0x8c,0x82,
|
||||
0x0f,0x4f,0x4f,0x4f,0x4f,0x4f,0xf5,0xe6,0x3e,0xbd,0x3e,0x9c,0x7a,0xf9,0x42,0xff,
|
||||
0xe9,0x6b,0xa5,0xae,0x96,0x96,0x96,0x96,0x97,0x5a,0x5d,0x75,0xd6,0xbf,0xd7,0xfe,
|
||||
0x3f,0xf9,0x8f,0xd8,0x4f,0x41,0xeb,0xdf,0xff,0xff,0x5b,0xed,0x61,0x85,0x00,0x28,
|
||||
0x3a,0x71,0x87,0xe7,0x30,0x57,0x08,0x1e,0x08,0x3d,0x07,0x84,0x1e,0x9e,0x11,0xc8,
|
||||
0x8a,0x7a,0x38,0xe2,0x4f,0x41,0x06,0xf4,0x10,0x6f,0x49,0xf8,0x4d,0xe9,0x37,0xa4,
|
||||
0xfd,0x37,0xa9,0xc8,0x08,0x7d,0x20,0x40,0xef,0xa0,0x83,0x7d,0x50,0x7f,0x49,0xb7,
|
||||
0xeb,0xe9,0x2f,0xe8,0xc2,0xf2,0xfa,0x4b,0x7d,0x6b,0xbe,0x92,0xfa,0xaf,0xeb,0xf5,
|
||||
0xaf,0xff,0xf5,0xfd,0x7f,0xeb,0xff,0x5f,0xff,0xaf,0xff,0xaf,0xd7,0xff,0xff,0xd7,
|
||||
0xff,0xff,0xaf,0xd5,0x7d,0xff,0xed,0x52,0xef,0xff,0xb0,0xa9,0x6e,0xc4,0x30,0x97,
|
||||
0xc7,0xdb,0x31,0x22,0xbd,0xa6,0xb6,0xda,0xaf,0x61,0x06,0x17,0x61,0x84,0x18,0x5b,
|
||||
0x88,0xf7,0xb7,0xde,0xde,0xde,0xc3,0xd8,0x66,0x28,0xf6,0x72,0x03,0x3b,0x1e,0xde,
|
||||
0xf8,0x7c,0x35,0x83,0x05,0x9c,0xc8,0xd8,0x28,0x50,0xe6,0xaf,0xf4,0xff,0xf4,0xff,
|
||||
0x4f,0xff,0x4f,0xff,0x4f,0xf4,0x63,0x0b,0xff,0xfd,0x5b,0xeb,0xff,0x5b,0xe9,0xfe,
|
||||
0xf5,0xfa,0x7d,0x6f,0xfe,0x9f,0x5b,0xff,0xa6,0xf5,0xff,0xd0,0xbf,0xfd,0x3f,0xef,
|
||||
0x5f,0xd3,0xfe,0x73,0x53,0xeb,0x7f,0xf4,0xfa,0xdf,0xfe,0xde,0x97,0xfc,0x76,0x9c,
|
||||
0x3b,0x6a,0x9d,0xf4,0x41,0xc3,0xbb,0xbb,0xee,0x73,0x4b,0xe1,0xf6,0xf7,0xff,0xff,
|
||||
0xfe,0xb5,0xd2,0xc2,0xc5,0x55,0x55,0x43,0x87,0x77,0x39,0xa6,0xf0,0xde,0xfd,0xff,
|
||||
0x7f,0x5f,0xe9,0x61,0x63,0xae,0xaa,0xaa,0x14,0x29,0xdd,0x4c,0x28,0x48,0xe5,0xa7,
|
||||
0x39,0xc9,0x61,0x03,0xc2,0x0f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x99,0x0f,0xd0,0x41,
|
||||
0xbd,0x27,0xe9,0xbe,0x9f,0x5f,0xab,0xee,0x3f,0xc5,0x7f,0xff,0xff,0xff,0x67,0x4c,
|
||||
0xde,0x40,0x6b,0xfd,0xd7,0xfb,0x6b,0xeb,0xb0,0xd2,0xe1,0x85,0xd8,0xad,0xae,0xb7,
|
||||
0xda,0xc3,0x0b,0x6b,0x0c,0x2c,0x30,0x58,0x30,0x50,0x3b,0x0c,0x03,0x83,0x87,0x70,
|
||||
0xee,0xef,0x9c,0xe2,0x1e,0x1b,0xc3,0xed,0xfe,0xdf,0xef,0xdf,0xef,0xfd,0xff,0xff,
|
||||
0xff,0xff,0xaf,0xd7,0xff,0x4b,0xf4,0xbf,0x4b,0x0b,0x84,0xa2,0xba,0xa8,0x55,0x50,
|
||||
0xa0,0xa0,0xa0,0xff,0xce,0x73,0x5f,0xff,0xff,0x9a,0x3b,0xff,0xff,0x9c,0xe6,0xbf,
|
||||
0xff,0xff,0xcd,0x32,0xff,0x80,0xff,0xce,0x73,0x5f,0xff,0xff,0xe6,0x8e,0xff,0xff,
|
||||
0xe7,0x39,0xaf,0xff,0xff,0xff,0xff,0xfc,0x28,0x4c,0xe5,0xa5,0x39,0xe9,0xe1,0x07,
|
||||
0x84,0x1e,0x13,0xd0,0x7a,0x7a,0xe9,0xf7,0xa3,0x23,0xfc,0x20,0xde,0x93,0xf4,0xfa,
|
||||
0x57,0xef,0xa5,0xff,0xff,0x43,0xf1,0xff,0xf9,0xca,0x5f,0xff,0xff,0xfe,0x74,0xce,
|
||||
0x20,0x3f,0x7f,0xff,0x6f,0xfe,0xfb,0x7e,0xd6,0xc1,0x85,0xb1,0xfb,0x5b,0x5b,0x5b,
|
||||
0x58,0x61,0x61,0x85,0x86,0x0b,0x3a,0x66,0x40,0x39,0xc9,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0x8f,0xfe,0x73,0x93,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x28,0x67,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x9c,0xe2,0xfc,0x80,0xeb,0xfe,0xd7,0xd7,0x86,
|
||||
0x96,0xc7,0xd6,0xd6,0xfd,0x6d,0x61,0x85,0xb5,0x86,0x16,0x73,0x8a,0x80,0x39,0xc8,
|
||||
0x69,0x69,0x75,0xa5,0xaf,0x5a,0x5a,0x5d,0x6b,0xa5,0xd6,0x96,0xba,0x5d,0x69,0x69,
|
||||
0x7e,0x96,0x97,0x51,0xd5,0xf7,0x7d,0xf7,0x7c,0xc9,0x27,0x5d,0x37,0x57,0xbd,0x37,
|
||||
0xde,0xfd,0xef,0xde,0xde,0xfd,0xef,0xde,0xdf,0xed,0xed,0x80,0x39,0xcd,0x7f,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x9a,0x57,0xff,0x00,0x3a,0x4c,0x7b,
|
||||
0xeb,0xdf,0x5f,0xda,0xfe,0xd7,0xf6,0xbc,0xc6,0x1c,0xc5,0x1e,0xd7,0xbf,0xfa,0xdd,
|
||||
0xfd,0xd7,0xf5,0xef,0xee,0xab,0xeb,0xdf,0xdd,0x7f,0x5e,0xfe,0xeb,0xfa,0xf7,0xf7,
|
||||
0x5f,0xd7,0xbf,0xb1,0xfa,0xff,0x7d,0xd7,0xfb,0xfa,0xff,0x6b,0xff,0xed,0x7f,0xfd,
|
||||
0xaf,0xf7,0xc0,0x39,0xc9,0xdf,0xdf,0xdf,0xde,0xfe,0xfe,0xfe,0xf7,0xf7,0xf7,0xf7,
|
||||
0x98,0xe2,0xff,0xdb,0xff,0x6f,0xbf,0xbe,0xdf,0xfb,0x7f,0xec,0x77,0xf7,0xf7,0xf7,
|
||||
0xbf,0xbf,0xbf,0xbd,0xfd,0xfd,0xef,0xc0,0x28,0x4c,0xe5,0x27,0x39,0xe9,0x61,0x07,
|
||||
0x84,0x1e,0x9e,0x13,0xd0,0x7a,0x7a,0xf7,0xa3,0x23,0x9e,0x82,0x0f,0xc2,0x6f,0x57,
|
||||
0xe9,0xbe,0xbd,0x5b,0xff,0xa7,0x8f,0xef,0xf5,0xdf,0xff,0xff,0xf5,0xef,0xff,0x52,
|
||||
0x03,0xfb,0x5f,0xf7,0x4b,0xbf,0xb4,0xb6,0xd7,0xb4,0xb6,0x18,0x5d,0x8a,0xeb,0x7d,
|
||||
0xad,0xac,0x30,0xb6,0xb0,0xc2,0xc3,0x0b,0x3a,0x65,0x40,0x3b,0x8a,0x1e,0x04,0x03,
|
||||
0x87,0x77,0x77,0x77,0x39,0xc5,0xf0,0xde,0xfb,0xed,0xff,0xff,0xff,0xd2,0xd7,0x0b,
|
||||
0x15,0xd5,0x55,0x42,0xa8,0x29,0xdc,0x50,0xe7,0x45,0xff,0xff,0xff,0xff,0xe0,0x28,
|
||||
0x4c,0xe5,0x27,0x39,0xe9,0x61,0x07,0x84,0x1e,0x9e,0x10,0x7a,0x7a,0x7f,0xa7,0xa3,
|
||||
0x23,0x9f,0x08,0x3e,0x82,0x6f,0xdf,0x49,0xbe,0x9f,0x5b,0xff,0xa7,0xfe,0x3b,0xfe,
|
||||
0xeb,0xff,0xff,0xff,0x7d,0x7f,0x20,0x3f,0xd7,0x6b,0xfe,0xf5,0xda,0xed,0xaf,0x69,
|
||||
0x6d,0xa5,0xc3,0x0b,0xb1,0x5b,0x5f,0xb5,0xb5,0x86,0xb6,0xf0,0xc3,0xc3,0x79,0xd3,
|
||||
0x67,0x3b,0x88,0xe1,0x87,0xb7,0x61,0x6d,0x61,0xad,0xad,0xad,0x85,0x00,0x3b,0x8a,
|
||||
0x1e,0x04,0x01,0xdc,0x3b,0xbb,0xee,0x73,0x8b,0xe1,0xf6,0xf7,0xfd,0xff,0xff,0xf5,
|
||||
0xeb,0x5d,0x70,0x94,0x75,0x55,0x55,0x0b,0xee,0x63,0xbf,0x6f,0xf6,0xff,0x6f,0xf6,
|
||||
0xff,0xbd,0xfb,0xdf,0xbd,0xfb,0xdf,0xbd,0xbe,0x28,0x44,0xe5,0xa9,0x39,0xa9,0xe0,
|
||||
0x83,0xc2,0x0f,0x4f,0x4f,0x4f,0x4f,0x4f,0xf4,0x64,0x73,0xe1,0x07,0xd2,0x6f,0x4f,
|
||||
0xfd,0x3e,0xfe,0x3b,0xdb,0xef,0x87,0xb0,0xf6,0x0f,0x83,0xd8,0x7b,0x07,0x86,0xf6,
|
||||
0x1e,0x1b,0xc3,0x0f,0x0f,0x86,0xf0,0x6f,0x06,0xf0,0xf8,0x7d,0xb3,0x9a,0x86,0xff,
|
||||
0xbf,0x90,0x16,0xbb,0x5c,0x30,0x96,0xc7,0xbf,0x5b,0x5b,0x58,0x6b,0x6b,0x0c,0x2c,
|
||||
0x18,0x59,0xd1,0x32,0xff,0xca,0x11,0x39,0xa9,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,
|
||||
0x39,0xc8,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xa9,0x01,0xfd,0xaf,0x6b,0xb6,0x97,0x0c,0x2e,0xc5,0x7e,0xd6,0xd6,0xd6,0xd6,
|
||||
0xd6,0x18,0x58,0x60,0xb3,0xa0,0x64,0x39,0xeb,0x48,0x0e,0xbb,0x5f,0xf7,0xaf,0x5e,
|
||||
0xfd,0xeb,0xfe,0xd7,0x7a,0xff,0xfd,0xb4,0xbf,0xff,0x74,0xbb,0xff,0xde,0xbb,0x5f,
|
||||
0xf7,0xaf,0x5e,0xfd,0xeb,0xff,0x5d,0xba,0xff,0xfd,0xb4,0xbf,0xff,0x74,0xbb,0xff,
|
||||
0xde,0xb8,0xff,0x6b,0xff,0x6b,0xfa,0xdf,0xfa,0xdf,0xfa,0xdf,0xfa,0x80,0x38,0xd1,
|
||||
0xc7,0x18,0x3b,0xd5,0xf5,0x20,0x35,0xfe,0xff,0xff,0xd2,0xdb,0xff,0x5f,0xef,0xff,
|
||||
0xfd,0x2d,0xb5,0xfe,0xff,0xff,0xff,0xeb,0x75,0x5e,0xef,0xff,0xff,0xdd,0x6b,0xed,
|
||||
0x7b,0xff,0xff,0x98,0x51,0xd6,0xeb,0xff,0xb7,0xff,0xaf,0x75,0xfe,0xbd,0x6f,0xb7,
|
||||
0xff,0xff,0xc7,0xc5,0x7b,0xb5,0xff,0xfd,0x7e,0xd6,0xff,0xfd,0x7e,0xff,0x5b,0xff,
|
||||
0xf5,0xfb,0xef,0x5f,0xf5,0xfb,0xfd,0x6f,0xc0,0x20,0x27,0x3d,0x24,0x3b,0x4b,0x7f,
|
||||
0x6d,0x2f,0xf6,0xd2,0xff,0x6d,0x2f,0xad,0xb5,0xde,0xbb,0x5d,0xeb,0xb5,0xde,0xbb,
|
||||
0x4b,0x7f,0xd2,0xd8,0xf6,0xbf,0x6b,0xad,0xfa,0xdf,0x6b,0xf5,0xef,0x4f,0xf4,0xf5,
|
||||
0xef,0x5e,0xf4,0x63,0x8b,0xf7,0xd2,0xbd,0x5f,0xab,0xd5,0xfa,0xbd,0x5b,0xeb,0xd5,
|
||||
0xbd,0x2f,0xdb,0xd2,0xfd,0xbd,0x2b,0xf7,0xd2,0xb8,0xdb,0x00,0x39,0xca,0x48,0x0b,
|
||||
0xaf,0xf6,0xd2,0xff,0x6d,0x2f,0xf7,0x4b,0xbf,0x7a,0xed,0x77,0xae,0xd7,0x7a,0xf5,
|
||||
0xdb,0xaf,0xf6,0xd2,0xff,0x6d,0x2f,0xf7,0x4b,0xbf,0x7a,0xe3,0xda,0xfd,0xaf,0xda,
|
||||
0xfd,0xaf,0xda,0xfd,0xaf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x43,
|
||||
0xff,0xfa,0xa9,0x43,0x7d,0x2d,0x2f,0xd2,0xd2,0xd7,0xad,0x2d,0x7a,0xd2,0xd7,0xad,
|
||||
0x2d,0x74,0xba,0xd2,0xd7,0xad,0x2d,0x7a,0xd2,0xd7,0xad,0x2d,0x74,0xba,0xd7,0x4b,
|
||||
0xad,0x74,0x6a,0xa7,0xaf,0xff,0xff,0xc0,0xff,0xce,0xd5,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe6,0x8f,0xff,0x80,0x39,0xcd,0x10,
|
||||
0x1f,0x7b,0xff,0x7b,0xff,0x7b,0xf7,0xbf,0xf7,0xbf,0x7b,0xff,0x7b,0xf7,0xfb,0xf7,
|
||||
0xbf,0xf7,0xbf,0x7b,0xff,0x7b,0xf7,0xfb,0xf7,0xbf,0xf7,0xbf,0x7b,0xff,0x7b,0xf7,
|
||||
0xfb,0xf7,0xbf,0xf7,0xbf,0x7b,0xff,0x7b,0xf6,0xff,0xc8,0x27,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0x8f,0xfe,0x28,0x30,0xe5,0x25,0x5f,0xd3,0xfe,0xf5,0xfd,0x3f,0xd3,0xe6,0x24,
|
||||
0xfe,0xf4,0x9f,0xfd,0x5b,0xeb,0xd6,0xfa,0x7f,0xbd,0x5f,0xaf,0x5b,0xe9,0xf5,0xbf,
|
||||
0xe2,0x9b,0x00,0xff,0xc0,0x3b,0x94,0x40,0x5e,0xfb,0x7b,0x7b,0xed,0xed,0xef,0xb7,
|
||||
0xdd,0xc0,0x28,0x34,0xe5,0xa1,0x04,0x0f,0x08,0x3c,0x20,0xf4,0xf4,0xf4,0xf5,0xef,
|
||||
0x46,0x3e,0x78,0x41,0xfe,0xfd,0xff,0xc7,0xff,0xce,0x6a,0xf9,0xc9,0x6f,0x05,0xd7,
|
||||
0x0b,0xaf,0xe8,0xc7,0xff,0x0b,0x8a,0xff,0xff,0xf5,0xd6,0x1a,0xc7,0x20,0x3f,0xdf,
|
||||
0x6f,0x66,0x4c,0xf6,0xbc,0x30,0x9b,0x86,0x10,0x80,0x39,0xad,0xff,0xff,0xff,0xff,
|
||||
0xcb,0x48,0xc2,0x07,0x84,0x1c,0x5d,0xdf,0x7d,0xcc,0x85,0xc2,0x0d,0xd7,0xbf,0xed,
|
||||
0xff,0xff,0xff,0xff,0xfd,0x2f,0xfb,0x58,0x61,0x28,0xfa,0xae,0xa6,0x30,0xaa,0x6b,
|
||||
0x0c,0x29,0x42,0x40,0xa0,0x28,0x3c,0xe4,0xa1,0x39,0x68,0xe1,0x07,0xa7,0xa7,0xa7,
|
||||
0xa7,0xa7,0xaf,0x7a,0x31,0xf7,0xc2,0x7d,0x5b,0xd7,0xdf,0x5f,0xc6,0x3f,0xff,0xe4,
|
||||
0x07,0xe7,0x30,0xcd,0xff,0xda,0xdd,0x2e,0x1a,0xec,0x7d,0x6f,0xb5,0xb5,0xb5,0xb5,
|
||||
0xb5,0x86,0x16,0x73,0xc9,0x80,0x28,0x67,0xff,0xff,0xff,0xff,0xff,0xff,0x39,0x84,
|
||||
0x70,0x41,0xf0,0x9f,0x43,0xad,0x7d,0x7d,0x73,0x1f,0x74,0x10,0x7e,0xfa,0xfe,0x2b,
|
||||
0xff,0xff,0xff,0xff,0xf2,0x02,0xff,0xef,0xeb,0x61,0x85,0xc7,0x7f,0x7f,0x66,0x50,
|
||||
0xed,0x70,0xd7,0x69,0xe0,0xc1,0x08,0x28,0x3c,0xe5,0x1f,0x04,0x0f,0x08,0x3c,0x20,
|
||||
0xf4,0xf4,0xf4,0xf4,0xff,0x4f,0x98,0xed,0xd2,0x0d,0xf5,0xe9,0x3f,0xff,0x7a,0xf1,
|
||||
0x8f,0xf3,0x9a,0xd9,0x01,0x7f,0xd9,0x90,0x3f,0x7b,0x69,0xf6,0x17,0x61,0x84,0xf8,
|
||||
0xbd,0xbe,0xf6,0xb6,0xb6,0xb0,0xd6,0x18,0x58,0x61,0x60,0xce,0x51,0xc0,0x28,0x8a,
|
||||
0x18,0x27,0x0b,0x5a,0xd6,0xbe,0xbf,0x3b,0xd5,0x85,0xaf,0x5f,0xff,0xf1,0x35,0x6f,
|
||||
0xff,0xf9,0x06,0x3b,0x5b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xe0,0x28,0x34,0xe4,0x27,0x04,0x0c,0xb0,0xb8,0x4d,0x69,0xf4,
|
||||
0x3a,0xd7,0xd6,0xb9,0x90,0xbc,0x20,0xf4,0x9f,0xfa,0xfe,0x3d,0x7f,0xff,0xff,0xfc,
|
||||
0x80,0xbf,0xfb,0xff,0x6d,0x70,0xc2,0xe3,0xbd,0xfd,0xef,0x7b,0x32,0x27,0x0c,0x2e,
|
||||
0x0c,0x2e,0x3c,0x9c,0xad,0x95,0x1f,0xa6,0x96,0x81,0x85,0xd0,0xaf,0xd2,0xd2,0xfc,
|
||||
0x30,0xb6,0xb0,0xc2,0xc3,0x0b,0x06,0x72,0xd0,0x00,0x39,0xad,0xff,0xff,0xff,0xff,
|
||||
0xcb,0xc8,0xc1,0x03,0xd3,0xd3,0xd3,0x8b,0xbf,0xb3,0x21,0xa1,0x3a,0x7f,0xef,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x20,0x84,0xda,0x83,0xd3,0xd3,0x1f,
|
||||
0x90,0x1d,0xad,0xad,0x85,0x8f,0xf9,0x4e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x28,0x61,0x36,0x84,0xf4,0xf4,0xfb,0xff,
|
||||
0xfd,0x6d,0x6d,0x61,0xac,0x7f,0xce,0x86,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,
|
||||
0xc7,0x5d,0x75,0x50,0xa1,0x42,0x80,0x39,0xad,0xff,0xff,0xff,0xff,0xf3,0x94,0x86,
|
||||
0x96,0x97,0x5a,0x5a,0x5a,0x5a,0x5f,0xa5,0xa5,0xa5,0x15,0x55,0xd7,0x7d,0xf7,0x7d,
|
||||
0xcc,0x7a,0x75,0xd3,0x7d,0xef,0xb7,0xfb,0x7d,0xef,0xde,0xde,0xfd,0xed,0x80,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x28,0x50,0xe4,0x1c,0x72,0x4d,0x31,0x94,0x30,
|
||||
0x83,0xc2,0x0c,0x20,0xf4,0xd3,0xd5,0x38,0xb5,0x8b,0xfb,0x32,0x14,0xc9,0x58,0x4c,
|
||||
0x27,0x4d,0x3a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0x00,0x28,0x54,0xe4,0x16,0x63,0x30,0x76,0x10,0x7a,0x7a,
|
||||
0x71,0xdf,0x7c,0xc8,0x6c,0x27,0xde,0xbd,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xfc,0x28,0x3c,0xe5,0x1f,0x04,0x0f,0x04,0x1e,0x83,0xd3,0xd3,0xd3,0xd3,
|
||||
0xd7,0xbd,0x18,0xfa,0xfa,0x0f,0xa4,0xfd,0x37,0xff,0x5c,0x7e,0xfd,0xff,0xff,0xfe,
|
||||
0x97,0xc8,0x0b,0xff,0xed,0x2d,0xb5,0xed,0x76,0x2b,0xf6,0xb6,0xb6,0xb6,0xb6,0xb6,
|
||||
0x16,0x18,0x59,0xcf,0x2a,0x28,0x48,0xe4,0x1c,0x63,0x20,0x3c,0x27,0xa0,0xe2,0xef,
|
||||
0xbe,0xe6,0x42,0xe1,0x37,0x4f,0xbf,0xfe,0xdf,0xff,0xff,0xff,0xf4,0xbf,0xf5,0xb5,
|
||||
0x86,0x94,0x75,0xd5,0x70,0xa6,0x34,0xac,0x35,0x86,0x0b,0x1f,0xff,0xff,0xff,0x80,
|
||||
0x28,0x30,0xe4,0x29,0x04,0x19,0x69,0x74,0x1f,0x09,0xf4,0x3a,0xfa,0xfa,0xe6,0x3e,
|
||||
0xe8,0x20,0xfd,0xf5,0xfc,0x57,0xff,0xff,0xff,0xff,0x20,0x3f,0x7f,0xf7,0xf5,0xb0,
|
||||
0xc2,0xe3,0xbf,0xbd,0xfd,0xe1,0x99,0x03,0xb0,0xb8,0x30,0xb8,0xff,0xff,0xff,0xff,
|
||||
0xff,0xf8,0x28,0x94,0xcc,0x9a,0xd6,0xbc,0x7f,0x3c,0x5e,0x15,0x57,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xc0,0x28,0x34,0xe5,0xa1,0x04,0x74,0x8c,0x84,0x1e,0x9e,0x13,0xd3,
|
||||
0xef,0x4f,0xf4,0x63,0xab,0xe8,0x3f,0x5f,0xb7,0xfe,0x38,0x7c,0x3d,0x9d,0x44,0x73,
|
||||
0xb0,0x6d,0x87,0xb0,0xf6,0x1e,0xde,0x1b,0xc3,0xe0,0xde,0x74,0xd1,0xc1,0xf7,0x9c,
|
||||
0xc3,0x19,0x01,0x7f,0xae,0xd7,0x86,0xbb,0x1e,0xd7,0xed,0x6d,0x6c,0x2c,0x35,0x86,
|
||||
0x16,0x0c,0xe5,0xa0,0x20,0xa7,0x6b,0xbf,0xff,0xff,0xff,0xfc,0x4f,0x34,0x7f,0xff,
|
||||
0x90,0x53,0xb5,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbe,0x6a,
|
||||
0x7f,0xef,0xef,0x7b,0xde,0x0c,0x28,0x39,0xa6,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xfc,0x80,0xb5,0xeb,0x86,0x17,0x1f,0xbf,0xbf,0xb3,0x28,0x76,0x17,
|
||||
0x0d,0x70,0x60,0x84,0x39,0xc6,0x75,0x20,0x3f,0xfe,0xd2,0xdf,0xff,0xd2,0xdb,0xff,
|
||||
0xff,0x74,0xbb,0xff,0xde,0xbd,0x7b,0xf7,0xaf,0xfd,0x76,0xeb,0xff,0xf7,0x4b,0x8f,
|
||||
0xf6,0xbf,0xf6,0xbf,0xf6,0xbf,0xf6,0xbf,0xf6,0xbf,0xe0,0x39,0x85,0x9c,0x92,0xaf,
|
||||
0xa9,0x01,0xa7,0xff,0xff,0xfa,0xfb,0xda,0x5d,0xff,0xff,0xaf,0xf7,0x5b,0xff,0xeb,
|
||||
0xda,0x7f,0xf5,0xbf,0xff,0xfa,0x31,0x25,0xaf,0xfd,0x6d,0xff,0xe9,0x3f,0xfd,0xff,
|
||||
0xf5,0xbf,0x1f,0x14,0xff,0xff,0xb5,0x5e,0xff,0xff,0xd3,0x5b,0xff,0xf5,0xfb,0x5b,
|
||||
0xff,0xf4,0xff,0x5b,0xf0,0x20,0x27,0x38,0xbd,0xd2,0xee,0xb7,0x5e,0xeb,0x75,0xdb,
|
||||
0xaf,0x5d,0xba,0xf4,0xb6,0xfe,0x2b,0x7e,0xb7,0xeb,0x7d,0xaf,0xda,0xfd,0x3d,0x7b,
|
||||
0xd7,0xbd,0x7b,0xd7,0x98,0xd2,0xf4,0xbf,0x6f,0x4a,0xf5,0x7e,0xaf,0x57,0xea,0xf5,
|
||||
0x7e,0xaf,0x57,0x8a,0xb0,0x39,0xc6,0xeb,0xc8,0x0e,0xbb,0x5d,0xff,0xaf,0xf6,0xd7,
|
||||
0xeb,0xfd,0xb4,0xbf,0xff,0x74,0xbb,0xff,0xde,0xbb,0x5f,0xf7,0xaf,0x5e,0x3d,0xaf,
|
||||
0xfd,0xaf,0xfd,0xaf,0xfd,0xaf,0xeb,0x7f,0xda,0xff,0xda,0xff,0xd2,0xfd,0x7a,0xc2,
|
||||
0xe5,0xa9,0xf5,0xfd,0x7f,0x5d,0x75,0xc2,0xd8,0x50,0x43,0xff,0xfa,0xa9,0x42,0x2b,
|
||||
0xf4,0xb4,0xb4,0xbf,0x4b,0x4b,0x4b,0x5e,0xb4,0xb4,0xb4,0xbf,0x4b,0x4b,0x4b,0xf4,
|
||||
0xb4,0xb4,0x68,0xa8,0xff,0xc0,0x28,0x98,0x21,0x82,0x78,0x5d,0x74,0xf5,0xd3,0xa0,
|
||||
0xba,0xd2,0xfd,0x2f,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0x7f,0xaf,0xd7,0xac,0x2c,
|
||||
0x57,0x50,0xaa,0xe1,0xdf,0x20,0x6f,0x0f,0xde,0xff,0xdf,0xef,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xb7,0xfb,0x7d,0xec,0x3b,0x5b,0xef,0xb5,0x87,0xc1,0xa8,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x20,0x65,0x34,0xa0,0x7c,0x3e,0xf4,0xfb,0x8b,
|
||||
0x90,0x27,0xbe,0xdf,0xed,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf7,0xfb,0xff,0x7f,
|
||||
0xb0,0xf6,0x0f,0xde,0x1e,0xf5,0x85,0xaf,0xa0,0x5a,0x0b,0xfa,0xfd,0x7f,0xaf,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xd7,0xaf,0xd2,0xd6,0x2a,0x40,0x57,0x5b,0x5d,0x70,0xb6,
|
||||
0x0a,0x28,0x24,0xe4,0x3f,0x08,0x33,0x9c,0x4d,0x07,0xd3,0xe9,0xf4,0xd6,0x9f,0x86,
|
||||
0xb8,0xad,0x79,0x8b,0x9e,0x83,0x5d,0x3f,0xb5,0x1b,0x5b,0x52,0x0c,0x83,0x58,0x86,
|
||||
0x0a};
|
||||
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// Compressed font example
|
||||
// written by Larry Bank
|
||||
//
|
||||
// This sketch demonstrates how to work with BBF (BitBank Font) files
|
||||
// and render the characters to a color LCD display
|
||||
// This should definitely be considered an advanced topic. Some of this functionality will be baked into
|
||||
// my display libraries eventually, but the paid vs free divide makes it necessary to demonstrate how to
|
||||
// work with the compressed font files created by the Group5 fontconvert tool
|
||||
//
|
||||
#include <Group5.h>
|
||||
#include "bb_font.h"
|
||||
#include <bb_spi_lcd.h>
|
||||
#include "Roboto_Black_40.h" // BBF (BitBank Font file included as hex data to compile with the sketch)
|
||||
|
||||
BB_SPI_LCD lcd; // class instance of bb_spi_lcd display library
|
||||
G5DECODER g5dec; // class instance of Group5 image decoder
|
||||
uint16_t u16Temp[256]; // holds one line of a character being displayed
|
||||
|
||||
//
|
||||
// Draw a string of characters in the given font at the given position and color
|
||||
// The y coordinate is relative to the baseline of the character, not the top
|
||||
// This means that drawing at coordinate 0,0 on the display will usually get clipped 100%
|
||||
// For this example, a 40pt font is about 64 pixels tall, so the baseline should be top+64
|
||||
//
|
||||
void DrawString(const char *szMsg, const BB_FONT *pFont, int x, int y, uint16_t u16FG, uint16_t u16BG)
|
||||
{
|
||||
int i, rc, iBitOff, dx, dy, cx, cy, tx, ty;
|
||||
char c;
|
||||
BB_GLYPH *pGlyph;
|
||||
uint8_t *s, u8, u8Mask, *pG5, u8Temp[32]; // 32 bytes can hold 256 1-bit pixels (of each character)
|
||||
uint16_t *d;
|
||||
|
||||
u16FG = __builtin_bswap16(u16FG); // swap for big endian (the SPI LCD data format)
|
||||
u16BG = __builtin_bswap16(u16BG);
|
||||
i = 0;
|
||||
cx = (pFont->last - pFont->first + 1); // Glyph count
|
||||
pG5 = (uint8_t *)&pFont->glyphs[cx]; // compressed data starts after the last glyph
|
||||
while (szMsg[i] != 0 && x < lcd.width()) {
|
||||
c = szMsg[i++];
|
||||
if (c < pFont->first || c > pFont->last) // undefined character
|
||||
continue; // skip it
|
||||
c -= pFont->first; // subtract first char of font defined to start from index 0
|
||||
pGlyph = (BB_GLYPH *)&pFont->glyphs[c];
|
||||
// set up the destination window (rectangle) on the display
|
||||
dx = x + pGlyph->xOffset; // offset from character UL to start drawing
|
||||
dy = y + pGlyph->yOffset;
|
||||
cx = pGlyph->width;
|
||||
cy = pGlyph->height;
|
||||
if (dy + cy > lcd.height())
|
||||
cy = lcd.height() - dy; // clip bottom edge
|
||||
if (dx + cx > lcd.width())
|
||||
cx = lcd.width() - dx; // clip right edge
|
||||
lcd.setAddrWindow(dx, dy, cx, cy); // tell the LCD the memory window in advance of writing the pixels
|
||||
s = pG5 + pGlyph->bitmapOffset; // start of bitmap data
|
||||
ty = (pGlyph[1].bitmapOffset - pGlyph[0].bitmapOffset); // compressed size
|
||||
if (ty < 0 || ty > 4096) ty = 4096; // DEBUG
|
||||
rc = g5dec.init(pGlyph->width, cy, s, ty);
|
||||
if (rc != G5_SUCCESS) return;
|
||||
for (ty=0; ty<cy && rc == G5_SUCCESS; ty++) { // loop over the lines (all equal width)
|
||||
rc = g5dec.decodeLine(u8Temp); // decode the 1-bit image one line at a time
|
||||
s = u8Temp;
|
||||
d = u16Temp; // point to start of output buffer
|
||||
u8Mask = 0x80; // MSB first
|
||||
u8 = *s++; // preload first byte
|
||||
for (tx=0; tx<cx; tx++) { // loop over the pixels on this line and convert from 1 to 16-bits
|
||||
*d++ = (u8 & u8Mask) ? u16FG : u16BG; // 1/0 foreground or background color is written
|
||||
u8Mask >>= 1;
|
||||
if (u8Mask == 0) { // next source byte
|
||||
u8 = *s++;
|
||||
u8Mask = 0x80;
|
||||
}
|
||||
} // for x
|
||||
lcd.pushPixels(u16Temp, cx); // write to the memory window one line at a time
|
||||
} // for ty
|
||||
x += pGlyph->xAdvance;
|
||||
} // while characters
|
||||
} /* DrawString() */
|
||||
|
||||
void setup()
|
||||
{
|
||||
lcd.begin(DISPLAY_CYD_2USB); // easy initialization of a named display type (ESP32 w/ 2.8" 240x320 ST7789)
|
||||
lcd.fillScreen(TFT_BLACK);
|
||||
DrawString("Hello", (BB_FONT *)Roboto_Black_40, 0, 70, TFT_GREEN, TFT_BLACK);
|
||||
DrawString("World!", (BB_FONT *)Roboto_Black_40, 0, 140, TFT_BLUE, TFT_BLACK);
|
||||
} /* setup() */
|
||||
|
||||
void loop()
|
||||
{
|
||||
} /* loop() */
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// Created with image_to_c
|
||||
// https://github.com/bitbank2/image_to_c
|
||||
//
|
||||
// bart
|
||||
// Data size = 349 bytes
|
||||
//
|
||||
// for non-Arduino builds...
|
||||
#ifndef PROGMEM
|
||||
#define PROGMEM
|
||||
#endif
|
||||
const uint8_t bart[] PROGMEM = {
|
||||
0xcc,0xa8,0xe9,0xcc,0x9f,0x09,0x1c,0x2c,0x3c,0x14,0x11,0x0a,0xa0,0xb6,0xe6,0x3e,
|
||||
0xe1,0x04,0xec,0xbc,0x74,0x21,0xf6,0x61,0x35,0x91,0xc5,0x98,0x25,0x74,0x14,0x1e,
|
||||
0xe0,0x91,0x09,0x98,0x29,0xa5,0x22,0xe6,0x0a,0x32,0x23,0x84,0x08,0x17,0xce,0x10,
|
||||
0x4e,0xa9,0x88,0xf0,0x49,0x8b,0xb2,0x13,0xac,0xc2,0x3f,0x85,0x08,0x84,0xec,0x96,
|
||||
0x18,0x51,0x79,0x85,0xcc,0x7f,0x59,0xc2,0x43,0x43,0x5f,0xfe,0xa0,0xcc,0x1b,0x61,
|
||||
0x75,0x94,0x85,0x84,0x42,0x5f,0xa0,0x47,0x10,0x09,0x91,0x10,0x88,0x4a,0xff,0xff,
|
||||
0x6c,0xc2,0xfa,0xa6,0x08,0x5e,0xbd,0x90,0xdf,0xbb,0xfb,0xff,0xfe,0xa6,0x1c,0x3c,
|
||||
0xa4,0x2b,0xff,0xc7,0x08,0x2c,0x76,0x88,0x55,0xa5,0xeb,0x44,0x26,0x1a,0x11,0x61,
|
||||
0xcc,0x21,0xbf,0x4f,0xe1,0xc8,0x48,0x8c,0x90,0xc7,0xfd,0xf0,0xcb,0xc3,0x57,0x1f,
|
||||
0xc2,0x46,0x28,0x39,0x82,0x09,0x84,0xd2,0xca,0xc2,0x3f,0x48,0xc2,0xfb,0xc6,0x2b,
|
||||
0x58,0xf4,0x83,0xee,0xa3,0x5b,0xc8,0xa7,0x79,0x48,0x58,0x44,0x26,0x08,0x84,0xd9,
|
||||
0x50,0x98,0x41,0xbf,0xc1,0x16,0x04,0x84,0x13,0x21,0x3f,0x0b,0xdd,0xff,0xf7,0xf4,
|
||||
0x92,0x77,0xf4,0x08,0x84,0xf6,0x42,0xbf,0x0a,0x9f,0xfa,0xf7,0xfe,0xde,0x4a,0xbb,
|
||||
0x5f,0xfb,0x05,0xf7,0xdd,0xeb,0xaf,0xac,0x77,0x5f,0x75,0xff,0x82,0x6a,0x96,0xd3,
|
||||
0xe8,0x11,0x0b,0xeb,0x4b,0xe9,0x38,0xfd,0x06,0x0f,0x58,0xfa,0xde,0xba,0xce,0x10,
|
||||
0x27,0x54,0x38,0x44,0x26,0x1f,0xe2,0x99,0x0a,0xf5,0x2a,0x09,0x5f,0xbe,0xb6,0x44,
|
||||
0xce,0x10,0x19,0xaa,0x7f,0xa5,0x7d,0x37,0x24,0x2f,0x09,0x61,0x90,0xef,0x5d,0x78,
|
||||
0x8b,0x55,0x5b,0xfd,0x3d,0x61,0x91,0xad,0x56,0xff,0x61,0xb2,0x2c,0x9c,0x49,0xac,
|
||||
0x45,0x32,0x19,0xfa,0x1e,0xc3,0xab,0x4f,0xa5,0x83,0x12,0xa1,0xa1,0x08,0x84,0xea,
|
||||
0x45,0xd6,0x0d,0x3f,0x4a,0xb4,0x85,0x8f,0x07,0x82,0x05,0x92,0x1f,0x87,0xd3,0xfc,
|
||||
0x6d,0x7f,0xf5,0xff,0xe8,0xe1,0x61,0x7f,0xff,0x8f,0xf3,0x88,0x05,0x7e,0x94,0xc3,
|
||||
0x52,0xc2,0xfb,0x89,0x82,0x16,0xfd,0x4c,0x3f,0xc2,0x56,0x86,0x38};
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Getting_started with the Group5 image compression library
|
||||
// Written by Larry Bank, September 20, 2024
|
||||
//
|
||||
// This sketch will demonstrate how to decode a 128x64 1-bit image
|
||||
// and display it on an OLED display
|
||||
//
|
||||
#include <Group5.h>
|
||||
#include <OneBitDisplay.h>
|
||||
#include "bart.h" // a pre-compressed image made with the Linux CLI tool in this repo
|
||||
|
||||
ONE_BIT_DISPLAY oled;
|
||||
G5DECODER g5dec;
|
||||
uint8_t u8Buffer[1024]; // big enough to hold the OLED contents
|
||||
#define IMAGE_WIDTH 128
|
||||
#define IMAGE_HEIGHT 64
|
||||
//
|
||||
// Image files are normally organized as horizontal bytes with the MSB on the left
|
||||
// The SSD1306 OLED is vertical bytes with the LSB as the top pixel of each set of 8 rows
|
||||
// So we need to rotate the pixels to the display's memory layout
|
||||
//
|
||||
void DrawLine(int y, uint8_t *u8Line)
|
||||
{
|
||||
uint8_t u8, u8SrcMask, u8DestMask, *s, *d;
|
||||
int x;
|
||||
u8DestMask = 1 << (y & 7);
|
||||
d = &u8Buffer[(y>>3) * IMAGE_WIDTH];
|
||||
s = u8Line;
|
||||
u8SrcMask = 0x80; // image encoding is MSB first (left pixel of each byte)
|
||||
u8 = *s++;
|
||||
for (x=0; x<IMAGE_WIDTH; x++) {
|
||||
if (u8 & u8SrcMask)
|
||||
d[x] |= u8DestMask;
|
||||
else
|
||||
d[x] &= ~u8DestMask;
|
||||
u8SrcMask >>= 1;
|
||||
if (u8SrcMask == 0) { // next byte
|
||||
u8SrcMask = 0x80;
|
||||
u8 = *s++;
|
||||
}
|
||||
} // for x
|
||||
} /* DrawLine() */
|
||||
|
||||
void setup()
|
||||
{
|
||||
oled.I2Cbegin(OLED_128x64); // use default I2C interface for target board
|
||||
oled.fillScreen(OBD_WHITE); // really black on OLEDs
|
||||
oled.setFont(FONT_12x16);
|
||||
oled.println("Group5 Demo");
|
||||
oled.setBuffer(u8Buffer);
|
||||
delay(2000);
|
||||
} /* setup() */
|
||||
|
||||
void loop()
|
||||
{
|
||||
int rc, y;
|
||||
long lTime;
|
||||
uint8_t u8Line[16]; // current decoded line
|
||||
|
||||
rc = g5dec.init(IMAGE_WIDTH, IMAGE_HEIGHT, (uint8_t *)bart, sizeof(bart));
|
||||
if (rc == G5_SUCCESS) {
|
||||
lTime = millis();
|
||||
for (y=0; y<IMAGE_HEIGHT && rc == G5_SUCCESS; y++) {
|
||||
rc = g5dec.decodeLine(u8Line);
|
||||
DrawLine(y, u8Line); // draw this into the correct bit direction for the OLED
|
||||
}
|
||||
lTime = millis() - lTime;
|
||||
oled.display();
|
||||
delay(2000);
|
||||
oled.fillScreen(OBD_WHITE);
|
||||
oled.println("Decoded in");
|
||||
oled.print((int)lTime, DEC);
|
||||
oled.println(" msec");
|
||||
delay(3000);
|
||||
}
|
||||
} /* loop() */
|
||||
@@ -0,0 +1,12 @@
|
||||
all: fontconvert
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -I/usr/local/include/freetype2 -I/usr/include/freetype2 -I/usr/include -I/opt/homebrew/include/freetype2
|
||||
LIBS = -L/opt/homebrew/lib -lfreetype
|
||||
|
||||
fontconvert: fontconvert.c
|
||||
$(CC) $(CFLAGS) $< $(LIBS) -o $@
|
||||
strip $@
|
||||
|
||||
clean:
|
||||
rm -f fontconvert
|
||||
@@ -0,0 +1,263 @@
|
||||
//
|
||||
// TrueType to bb_font converter
|
||||
// Written by Larry Bank
|
||||
// August 31, 2024
|
||||
// The bb_font format is a losslessly compressed bitmap font of a single point size
|
||||
// The data is compressed with a compression scheme based on CCITT T.6
|
||||
// The font structure includes overall size, per-character glyph info and then the
|
||||
// compressed image data at the end.
|
||||
// The font file format is designed to allow both dynamic loading of font data from
|
||||
// external memory/disk or compiling the data as const into a progarm.
|
||||
//
|
||||
// Example usage:
|
||||
// ./fontconvert <my_font.ttf> <out.bbf> <pt size> <start char> <end char>
|
||||
// This code requires the freetype library
|
||||
// found here: www.freetype.org
|
||||
//
|
||||
#include <ctype.h>
|
||||
#include <ft2build.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include FT_GLYPH_H
|
||||
#include FT_MODULE_H
|
||||
#include FT_TRUETYPE_DRIVER_H
|
||||
#include "../src/bb_font.h" // BitBank font structures
|
||||
#include "../src/g5enc.h" // Group5 image compression library
|
||||
G5ENCIMAGE g5enc; // Group5 encoder state
|
||||
|
||||
#define DPI 141 // Approximate resolution of common displays
|
||||
#define OUTBUF_SIZE 65536
|
||||
//
|
||||
// Rotate a character 90/180/270 degrees
|
||||
//
|
||||
int RotateBitmap(int iAngle, uint8_t *pSrc, int iWidth, int iHeight, int iSrcPitch, uint8_t *pDst)
|
||||
{
|
||||
int x, y, tx, ty, iDstPitch;
|
||||
uint8_t *s, *d, uc, ucMask;
|
||||
|
||||
switch (iAngle) {
|
||||
case 90:
|
||||
iDstPitch = (iHeight+7)/8;
|
||||
for (y=0; y<iWidth; y++) {
|
||||
ucMask = 0x80 >> (y & 7);
|
||||
s = &pSrc[(y>>3) + (iHeight-1) * iSrcPitch]; // work from bottom up
|
||||
d = &pDst[y * iDstPitch];
|
||||
memset(d, 0, iDstPitch);
|
||||
for (x=0; x<iHeight; x++) {
|
||||
if (s[0] & ucMask) {
|
||||
d[x >> 3] |= (0x80 >> (x & 7));
|
||||
}
|
||||
s -= iSrcPitch;
|
||||
} // for x
|
||||
} // for y
|
||||
break;
|
||||
case 180:
|
||||
iDstPitch = iSrcPitch;
|
||||
for (y=0; y<iHeight; y++) {
|
||||
s = &pSrc[(iHeight-y-1) * iSrcPitch]; // work from bottom up
|
||||
d = &pDst[y * iDstPitch];
|
||||
memset(d, 0, iDstPitch);
|
||||
for (x=0; x<iWidth; x++) {
|
||||
tx = (iWidth-x-1); // reverse x direction
|
||||
// This code doesn't need to be efficient
|
||||
uc = s[tx>>3] & (0x80 >> (tx & 7)); // source pixel
|
||||
if (uc) { // set
|
||||
d[x >> 3] |= (0x80 >> (x & 7));
|
||||
}
|
||||
} // for x
|
||||
} // for y
|
||||
break;
|
||||
case 270:
|
||||
iDstPitch = (iHeight+7)/8;
|
||||
for (y=0; y<iWidth; y++) {
|
||||
ty = (iWidth-1-y);
|
||||
ucMask = 0x80 >> (ty & 7);
|
||||
s = &pSrc[ty>>3]; // work from bottom up
|
||||
d = &pDst[y * iDstPitch];
|
||||
memset(d, 0, iDstPitch);
|
||||
for (x=0; x<iHeight; x++) {
|
||||
if (s[0] & ucMask) {
|
||||
d[x >> 3] |= (0x80 >> (x & 7));
|
||||
}
|
||||
s += iSrcPitch;
|
||||
} // for x
|
||||
} // for y
|
||||
break;
|
||||
default:
|
||||
return -1; // invalid
|
||||
}
|
||||
return iDstPitch;
|
||||
} /* RotateBitmap() */
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, err, size, first = ' ', last = '~', y;
|
||||
int iLen ,iOffset = 0;
|
||||
int iRotation = 0;
|
||||
uint8_t *pBitmap, *pTemp;
|
||||
FILE *fOut;
|
||||
// TrueType library structures
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
FT_Glyph glyph;
|
||||
FT_Bitmap *bitmap;
|
||||
FT_BitmapGlyphRec *g;
|
||||
// BitBank Font structures
|
||||
BB_GLYPH *pGlyphs;
|
||||
BB_FONT bbff;
|
||||
|
||||
if (argc < 4) {
|
||||
printf("Usage: %s <in.ttf> <out.bbf> point_size [first_char] [last_char] [rotation (90/180/270)]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
size = atoi(argv[3]);
|
||||
|
||||
if (argc == 5) {
|
||||
last = atoi(argv[4]); // only ending character was provided
|
||||
} else if (argc >= 6) {
|
||||
first = atoi(argv[4]); // start + end character codes were provided
|
||||
last = atoi(argv[5]);
|
||||
}
|
||||
if (argc == 7) { // rotation angle provided
|
||||
iRotation = atoi(argv[6]);
|
||||
if (iRotation != 90 && iRotation != 180 && iRotation != 270) {
|
||||
printf("Rotation angle can only be 90/180/270\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (last < first) {
|
||||
printf("Something went wrong - the starting character comes after the ending character. Try again...\n");
|
||||
return 1;
|
||||
}
|
||||
pGlyphs = (BB_GLYPH *)malloc((last - first + 1) * sizeof(BB_GLYPH));
|
||||
if (!pGlyphs) {
|
||||
printf("Error allocating memory for glyph data\n");
|
||||
return 1;
|
||||
}
|
||||
pBitmap = (uint8_t *)malloc(OUTBUF_SIZE); // Enough to hold the output
|
||||
pTemp = (uint8_t *)malloc(OUTBUF_SIZE); // for rotated bitmaps
|
||||
if (!pBitmap || ! pTemp) {
|
||||
printf("Error allocating memory for bitmap data\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Init FreeType lib, load font
|
||||
if ((err = FT_Init_FreeType(&library))) {
|
||||
printf("FreeType init error: %d", err);
|
||||
return err;
|
||||
}
|
||||
// Print parameters
|
||||
printf("fontconvert %s to %s, size: %dpt, first: %d, last: %d, rotation: %d\n", argv[1], argv[2], size, first, last, iRotation);
|
||||
|
||||
// Use TrueType engine version 35, without subpixel rendering.
|
||||
// This improves clarity of fonts since this library does not
|
||||
// support rendering multiple levels of gray in a glyph.
|
||||
// See https://github.com/adafruit/Adafruit-GFX-Library/issues/103
|
||||
FT_UInt interpreter_version = TT_INTERPRETER_VERSION_35;
|
||||
FT_Property_Set(library, "truetype", "interpreter-version",
|
||||
&interpreter_version);
|
||||
|
||||
if ((err = FT_New_Face(library, argv[1], 0, &face))) {
|
||||
printf("Font load error: %d", err);
|
||||
FT_Done_FreeType(library);
|
||||
return err;
|
||||
}
|
||||
|
||||
// Shift the size left by 6 because the library uses '26dot6' fixed-point format
|
||||
FT_Set_Char_Size(face, size << 6, 0, DPI, 0);
|
||||
|
||||
// Currently all symbols from 'first' to 'last' are processed.
|
||||
// Fonts may contain WAY more glyphs than that, but this code
|
||||
// will need to handle encoding stuff to deal with extracting
|
||||
// the right symbols, and that's not done yet.
|
||||
|
||||
// Process glyphs and output huge bitmap data array
|
||||
for (i = first; i <= last; i++) {
|
||||
int index = i - first;
|
||||
uint8_t *s;
|
||||
int iPitch;
|
||||
// MONO renderer provides clean image with perfect crop
|
||||
// (no wasted pixels) via bitmap struct.
|
||||
if ((err = FT_Load_Char(face, i, FT_LOAD_TARGET_MONO))) {
|
||||
printf("Error %d loading char '%c'\n", err, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((err = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO))) {
|
||||
printf("Error %d rendering char '%c'\n", err, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((err = FT_Get_Glyph(face->glyph, &glyph))) {
|
||||
printf("Error %d getting glyph '%c'\n", err, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
bitmap = &face->glyph->bitmap;
|
||||
g = (FT_BitmapGlyphRec *)glyph;
|
||||
|
||||
// Minimal font and per-glyph information is stored to
|
||||
// reduce flash space requirements. Glyph bitmaps are
|
||||
// fully bit-packed; no per-scanline pad, though end of
|
||||
// each character may be padded to next byte boundary
|
||||
// when needed. 16-bit offset means 64K max for bitmaps,
|
||||
// code currently doesn't check for overflow. (Doesn't
|
||||
// check that size & offsets are within bounds either for
|
||||
// that matter...please convert fonts responsibly.)
|
||||
pGlyphs[index].bitmapOffset = iOffset;
|
||||
pGlyphs[index].width = bitmap->width;
|
||||
pGlyphs[index].height = bitmap->rows;
|
||||
pGlyphs[index].xAdvance = face->glyph->advance.x >> 6;
|
||||
pGlyphs[index].xOffset = g->left;
|
||||
pGlyphs[index].yOffset = 1 - g->top;
|
||||
s = bitmap->buffer;
|
||||
iPitch = bitmap->pitch;
|
||||
if (iRotation != 0) {
|
||||
iPitch = RotateBitmap(iRotation, bitmap->buffer, bitmap->width, bitmap->rows, bitmap->pitch, pTemp);
|
||||
s = pTemp;
|
||||
g5_encode_init(&g5enc, bitmap->rows, bitmap->width, &pBitmap[iOffset], OUTBUF_SIZE-iOffset);
|
||||
for (y = 0; y < bitmap->width; y++) {
|
||||
g5_encode_encodeLine(&g5enc, &s[y * iPitch]);
|
||||
} // for y
|
||||
} else { // not rotated
|
||||
g5_encode_init(&g5enc, bitmap->width, bitmap->rows, &pBitmap[iOffset], OUTBUF_SIZE-iOffset);
|
||||
for (y = 0; y < bitmap->rows; y++) {
|
||||
g5_encode_encodeLine(&g5enc, &s[y * iPitch]);
|
||||
} // for y
|
||||
}
|
||||
iLen = g5_encode_getOutSize(&g5enc);
|
||||
iOffset += iLen;
|
||||
|
||||
FT_Done_Glyph(glyph);
|
||||
} // for each glyph
|
||||
|
||||
// Try to create the output file
|
||||
fOut = fopen(argv[2], "w+b");
|
||||
if (!fOut) {
|
||||
printf("Error creating output file: %s\n", argv[2]);
|
||||
return 1;
|
||||
}
|
||||
// Write the file header
|
||||
bbff.u16Marker = BB_MARKER;
|
||||
bbff.first = first;
|
||||
bbff.last = last;
|
||||
bbff.rotation = iRotation; // save rotation angle
|
||||
if (face->size->metrics.height == 0) {
|
||||
// No face height info, assume fixed width and get from a glyph.
|
||||
bbff.height = pGlyphs[0].height;
|
||||
} else {
|
||||
bbff.height = (face->size->metrics.height >> 6);
|
||||
}
|
||||
fwrite(&bbff, 1, sizeof(bbff), fOut);
|
||||
// Write the glyph table
|
||||
fwrite(pGlyphs, (last-first+1), sizeof(BB_GLYPH), fOut);
|
||||
// Write the compressed bitmap data
|
||||
fwrite(pBitmap, 1, iOffset, fOut);
|
||||
fflush(fOut);
|
||||
iLen = ftell(fOut);
|
||||
fclose(fOut); // done!
|
||||
FT_Done_FreeType(library);
|
||||
printf("Success!\nFont file size: %d bytes\n", iLen);
|
||||
|
||||
return 0;
|
||||
} /* main() */
|
||||
+2
-3
@@ -3,9 +3,8 @@ version=1.0.0
|
||||
author=Larry Bank
|
||||
maintainer=Larry Bank
|
||||
sentence=A frustration-free eink library.
|
||||
paragraph=Supports most common 24-pin SPI eink panels with a rich API. Both buffered and bufferless graphics supported. This means you can do interesting things on very constrained MCUs.
|
||||
paragraph=Supports most common 24-pin SPI eink panels with a rich API. Includes an efficient image compression scheme. Both buffered and bufferless graphics supported; this means you can do interesting things on very constrained MCUs.
|
||||
category=Display
|
||||
url=https://github.com/bitbank2/bb_eink
|
||||
architectures=*
|
||||
includes=bb_eink.h
|
||||
depends=Group5
|
||||
includes=bb_eink.h,Group5.h
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
CFLAGS=-D__LINUX__ -Wall -O2
|
||||
LIBS =
|
||||
|
||||
all: g5_demo
|
||||
|
||||
g5_demo: main.o
|
||||
$(CC) main.o -o g5_demo
|
||||
|
||||
main.o: main.c ../src/Group5.h ../src/g5dec.h ../src/g5enc.h
|
||||
$(CC) $(CFLAGS) -c main.c
|
||||
|
||||
clean:
|
||||
rm -rf *.o g5_demo
|
||||
@@ -0,0 +1,138 @@
|
||||
//
|
||||
// main.c
|
||||
// Group5
|
||||
//
|
||||
// Created by Larry Bank on 8/19/24.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../src/g5dec.h"
|
||||
#include "../src/g5enc.h"
|
||||
//
|
||||
// Read a Windows BMP file into memory
|
||||
//
|
||||
uint8_t * ReadBMP(const char *fname, int *width, int *height, int *bpp, unsigned char *pPal)
|
||||
{
|
||||
int y, w, h, bits, offset;
|
||||
uint8_t *s, *d, *pTemp, *pBitmap;
|
||||
int pitch, bytewidth;
|
||||
int iSize, iDelta;
|
||||
FILE *infile;
|
||||
|
||||
infile = fopen(fname, "r+b");
|
||||
if (infile == NULL) {
|
||||
printf("Error opening input file %s\n", fname);
|
||||
return NULL;
|
||||
}
|
||||
// Read the bitmap into RAM
|
||||
fseek(infile, 0, SEEK_END);
|
||||
iSize = (int)ftell(infile);
|
||||
fseek(infile, 0, SEEK_SET);
|
||||
pBitmap = (uint8_t *)malloc(iSize);
|
||||
pTemp = (uint8_t *)malloc(iSize);
|
||||
fread(pTemp, 1, iSize, infile);
|
||||
fclose(infile);
|
||||
|
||||
if (pTemp[0] != 'B' || pTemp[1] != 'M' || pTemp[14] < 0x28) {
|
||||
free(pBitmap);
|
||||
free(pTemp);
|
||||
printf("Not a Windows BMP file!\n");
|
||||
return NULL;
|
||||
}
|
||||
w = *(int32_t *)&pTemp[18];
|
||||
h = *(int32_t *)&pTemp[22];
|
||||
bits = *(int16_t *)&pTemp[26] * *(int16_t *)&pTemp[28];
|
||||
if (bits <= 8 && pPal != NULL) { // it has a palette, copy it
|
||||
uint8_t *p = pPal;
|
||||
for (int i=0; i<(1<<bits); i++)
|
||||
{
|
||||
*p++ = pTemp[54+i*4];
|
||||
*p++ = pTemp[55+i*4];
|
||||
*p++ = pTemp[56+i*4];
|
||||
}
|
||||
}
|
||||
offset = *(int32_t *)&pTemp[10]; // offset to bits
|
||||
if (bits == 1) {
|
||||
bytewidth = (w+7) >> 3;
|
||||
} else {
|
||||
bytewidth = (w * bits) >> 3;
|
||||
}
|
||||
pitch = (bytewidth + 3) & 0xfffc; // DWORD aligned
|
||||
// move up the pixels
|
||||
d = pBitmap;
|
||||
s = &pTemp[offset];
|
||||
iDelta = pitch;
|
||||
if (h > 0) {
|
||||
iDelta = -pitch;
|
||||
s = &pTemp[offset + (h-1) * pitch];
|
||||
} else {
|
||||
h = -h;
|
||||
}
|
||||
for (y=0; y<h; y++) {
|
||||
if (bits == 32) {// need to swap red and blue
|
||||
for (int i=0; i<bytewidth; i+=4) {
|
||||
d[i] = s[i+2];
|
||||
d[i+1] = s[i+1];
|
||||
d[i+2] = s[i];
|
||||
d[i+3] = s[i+3];
|
||||
}
|
||||
} else {
|
||||
memcpy(d, s, bytewidth);
|
||||
}
|
||||
d += bytewidth;
|
||||
s += iDelta;
|
||||
}
|
||||
*width = w;
|
||||
*height = h;
|
||||
*bpp = bits;
|
||||
free(pTemp);
|
||||
return pBitmap;
|
||||
|
||||
} /* ReadBMP() */
|
||||
|
||||
#define OUTSIZE 65536
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
uint8_t *pBMP, *pOut = NULL;
|
||||
int rc, w, h, y, bpp;
|
||||
int iOutSize, iPitch;
|
||||
G5ENCIMAGE g5enc;
|
||||
|
||||
printf("G5 file compressor\n");
|
||||
if (argc != 3) {
|
||||
printf("Usage: ./Group5 <WinBMP 1-bpp image> <g5 compressed image>\n");
|
||||
return -1;
|
||||
}
|
||||
pBMP = ReadBMP(argv[1], &w, &h, &bpp, NULL);
|
||||
if (bpp == 1) {
|
||||
uint8_t *s = pBMP;
|
||||
|
||||
printf("bmp size %d x %d\n", w, h);
|
||||
iPitch = (w+7) >> 3;
|
||||
pOut = (uint8_t *)malloc(OUTSIZE);
|
||||
rc = g5_encode_init(&g5enc, w, h, pOut, OUTSIZE);
|
||||
for (y=0; y<h && rc == G5_SUCCESS; y++) {
|
||||
rc = g5_encode_addLine(&g5enc, s);
|
||||
s += iPitch;
|
||||
}
|
||||
if (rc == G5_ENCODE_COMPLETE) {
|
||||
FILE *fOut;
|
||||
printf("Encode succeeded!\n");
|
||||
iOutSize = g5_encode_getOutSize(&g5enc);
|
||||
printf("Input size = %d, output size = %d\n", iPitch*h, iOutSize);
|
||||
fOut = fopen(argv[2], "w+b");
|
||||
if (fOut) {
|
||||
fwrite(pOut, 1, iOutSize, fOut);
|
||||
fflush(fOut);
|
||||
fclose(fOut);
|
||||
} else {
|
||||
printf("Error opening output file: %s\n", argv[2]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("Only 1-bpp images are supported.\n");
|
||||
}
|
||||
free(pBMP);
|
||||
free(pOut);
|
||||
return 0;
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
//
|
||||
// bb_eink I/O wrapper functions for Raspberry Pi
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
// Written by Larry Bank (bitbank@pobox.com)
|
||||
// Project started 9/11/2024
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Adapt these functions to whatever target platform you're using
|
||||
// and the rest of the code can remain unchanged
|
||||
//
|
||||
#ifndef __BB_EI_IO__
|
||||
#define __BB_EI_IO__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <linux/spi/spidev.h>
|
||||
#include <gpiod.h>
|
||||
#include <math.h>
|
||||
struct gpiod_chip *chip = NULL;
|
||||
struct gpiod_line *lines[64];
|
||||
static int spi_fd; // SPI handle
|
||||
|
||||
void SPI_transfer(BBEIDISP *pBBEI, uint8_t *pBuf, int iLen)
|
||||
{
|
||||
struct spi_ioc_transfer spi;
|
||||
memset(&spi, 0, sizeof(spi));
|
||||
spi.tx_buf = (unsigned long)pBuf;
|
||||
spi.len = iLen;
|
||||
spi.speed_hz = pBBEI->iSpeed;
|
||||
spi.bits_per_word = 8;
|
||||
ioctl(spi_fd, SPI_IOC_MESSAGE(1), &spi);
|
||||
} /* SPI_transfer() */
|
||||
|
||||
int digitalRead(int iPin)
|
||||
{
|
||||
return gpiod_line_get_value(lines[iPin]);
|
||||
} /* digitalRead() */
|
||||
|
||||
void digitalWrite(int iPin, int iState)
|
||||
{
|
||||
gpiod_line_set_value(lines[iPin], iState);
|
||||
} /* digitalWrite() */
|
||||
|
||||
void pinMode(int iPin, int iMode)
|
||||
{
|
||||
if (chip == NULL) {
|
||||
chip = gpiod_chip_open_by_name("gpiochip0");
|
||||
}
|
||||
lines[iPin] = gpiod_chip_get_line(chip, iPin);
|
||||
if (iMode == OUTPUT) {
|
||||
gpiod_line_request_output(lines[iPin], CONSUMER, 0);
|
||||
} else if (iMode == INPUT_PULLUP) {
|
||||
gpiod_line_request_input_flags(lines[iPin], CONSUMER, GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP);
|
||||
} else { // plain input
|
||||
gpiod_line_request_input(lines[iPin], CONSUMER);
|
||||
}
|
||||
} /* pinMode() */
|
||||
|
||||
static void delay(int iMS)
|
||||
{
|
||||
usleep(iMS * 1000);
|
||||
} /* delay() */
|
||||
|
||||
static void delayMicroseconds(int iMS)
|
||||
{
|
||||
usleep(iMS);
|
||||
} /* delayMicroseconds() */
|
||||
|
||||
//
|
||||
// Initialize the GPIO pins and SPI for use by bb_eink
|
||||
//
|
||||
void bbeiInitIO(BBEIDISP *pBBEI, uint32_t u32Speed)
|
||||
{
|
||||
pinMode(pBBEI->iDCPin, OUTPUT);
|
||||
pinMode(pBBEI->iRSTPin, OUTPUT);
|
||||
digitalWrite(pBBEI->iRSTPin, LOW);
|
||||
delay(100);
|
||||
digitalWrite(pBBEI->iRSTPin, HIGH);
|
||||
delay(100);
|
||||
if (pBBEI->iBUSYPin != 0xff) {
|
||||
pinMode(pBBEI->iBUSYPin, INPUT);
|
||||
}
|
||||
pBBEI->iSpeed = u32Speed;
|
||||
pinMode(pBBEI->iCSPin, OUTPUT);
|
||||
digitalWrite(pBBEI->iCSPin, HIGH); // we have to manually control the CS pin
|
||||
spi_fd = open("/dev/spidev0.1", O_RDWR); // DEBUG - open SPI channel 0
|
||||
} /* bbeiInitIO() */
|
||||
//
|
||||
// Toggle the reset line to wake up the eink from deep sleep
|
||||
//
|
||||
void bbeiWakeUp(BBEIDISP *pBBEI)
|
||||
{
|
||||
digitalWrite(pBBEI->iRSTPin, LOW);
|
||||
delay(10);
|
||||
digitalWrite(pBBEI->iRSTPin, HIGH);
|
||||
delay(10);
|
||||
} /* bbeiWakeUp() */
|
||||
//
|
||||
// Wait for the busy status line to show idle
|
||||
// The polarity of the busy signal is reversed on the UC81xx compared
|
||||
// to the SSD16xx controllers
|
||||
//
|
||||
void bbeiWaitBusy(BBEIDISP *pBBEI)
|
||||
{
|
||||
uint8_t busy_idle = (pBBEI->chip_type == BBEI_CHIP_UC81xx) ? HIGH : LOW;
|
||||
delay(1); // some panels need a short delay before testing the BUSY line
|
||||
while (1) {
|
||||
if (digitalRead(pBBEI->iBUSYPin) == busy_idle) break;
|
||||
}
|
||||
} /* bbeiWaitBusy() */
|
||||
//
|
||||
// Convenience function to write a command byte along with a data
|
||||
// byte (it's single parameter)
|
||||
//
|
||||
void bbeiCMD2(BBEIDISP *pBBEI, uint8_t cmd1, uint8_t cmd2)
|
||||
{
|
||||
if (!pBBEI->is_awake) {
|
||||
// if it's asleep, it can't receive commands
|
||||
bbeiWakeUp(pBBEI);
|
||||
pBBEI->is_awake = 1;
|
||||
}
|
||||
digitalWrite(pBBEI->iDCPin, LOW);
|
||||
digitalWrite(pBBEI->iCSPin, LOW);
|
||||
SPI_transfer(pBBEI, &cmd1, 1);
|
||||
digitalWrite(pBBEI->iDCPin, HIGH);
|
||||
SPI_transfer(pBBEI, &cmd2, 1); // second byte is data
|
||||
digitalWrite(pBBEI->iCSPin, HIGH);
|
||||
digitalWrite(pBBEI->iDCPin, HIGH); // leave data mode as the default
|
||||
} /* bbeiCMD2() */
|
||||
//
|
||||
// Write a single byte as a COMMAND (D/C set low)
|
||||
//
|
||||
void bbeiWriteCmd(BBEIDISP *pBBEI, uint8_t cmd)
|
||||
{
|
||||
if (!pBBEI->is_awake) {
|
||||
// if it's asleep, it can't receive commands
|
||||
bbeiWakeUp(pBBEI);
|
||||
pBBEI->is_awake = 1;
|
||||
}
|
||||
digitalWrite(pBBEI->iDCPin, LOW);
|
||||
digitalWrite(pBBEI->iCSPin, LOW);
|
||||
SPI_transfer(pBBEI, &cmd, 1);
|
||||
digitalWrite(pBBEI->iCSPin, HIGH);
|
||||
digitalWrite(pBBEI->iDCPin, HIGH); // leave data mode as the default
|
||||
} /* bbeiWriteCmd() */
|
||||
//
|
||||
// Put the eink into light or deep sleep
|
||||
//
|
||||
void bbeiSleep(BBEIDISP *pBBEI, int bDeep)
|
||||
{
|
||||
if (pBBEI->chip_type == BBEI_CHIP_UC81xx) {
|
||||
bbeiCMD2(pBBEI, UC8151_CDI, 0x17); // border floating
|
||||
bbeiWriteCmd(pBBEI, UC8151_POFF); // power off
|
||||
bbeiWaitBusy(pBBEI);
|
||||
if (bDeep) {
|
||||
bbeiCMD2(pBBEI, UC8151_DSLP, 0xa5); // deep sleep
|
||||
}
|
||||
} else {
|
||||
bbeiCMD2(pBBEI, SSD1608_DEEP_SLEEP, (bDeep) ? 0x02 : 0x01); // deep sleep mode 1 keeps RAM, mode 2 loses RAM
|
||||
}
|
||||
pBBEI->is_awake = 0;
|
||||
} /* bbeiSleep() */
|
||||
//
|
||||
// Write 1 or more bytes as DATA (D/C set high)
|
||||
//
|
||||
void bbeiWriteData(BBEIDISP *pBBEI, uint8_t *pData, int iLen)
|
||||
{
|
||||
digitalWrite(pBBEI->iCSPin, LOW);
|
||||
SPI_transfer(pBBEI, pData, iLen);
|
||||
digitalWrite(pBBEI->iCSPin, HIGH);
|
||||
} /* bbeiWriteData() */
|
||||
|
||||
#endif // __BB_EI_IO__
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "g5enc.inl"
|
||||
#include "g5dec.inl"
|
||||
//
|
||||
// Group5 1-bit image compression library
|
||||
// Written by Larry Bank
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file ./LICENSE.
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// ./APL.txt.
|
||||
|
||||
//
|
||||
// Decoder C++ wrapper functions
|
||||
//
|
||||
int G5DECODER::init(int iWidth, int iHeight, uint8_t *pData, int iDataSize)
|
||||
{
|
||||
return g5_decode_init(&_g5dec, iWidth, iHeight, pData, iDataSize);
|
||||
} /* init() */
|
||||
|
||||
int G5DECODER::decodeLine(uint8_t *pOut)
|
||||
{
|
||||
return g5_decode_line(&_g5dec, pOut);
|
||||
} /* decodeLine() */
|
||||
|
||||
//
|
||||
// Encoder C++ wrapper functions
|
||||
//
|
||||
int G5ENCODER::init(int iWidth, int iHeight, uint8_t *pOut, int iOutSize)
|
||||
{
|
||||
return g5_encode_init(&_g5enc, iWidth, iHeight, pOut, iOutSize);
|
||||
} /* init() */
|
||||
|
||||
int G5ENCODER::encodeLine(uint8_t *pPixels)
|
||||
{
|
||||
return g5_encode_encodeLine(&_g5enc, pPixels);
|
||||
} /* encodeLine() */
|
||||
|
||||
int G5ENCODER::size()
|
||||
{
|
||||
return g5_encode_getOutSize(&_g5enc);
|
||||
} /* size() */
|
||||
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
#ifndef __GROUP5__
|
||||
#define __GROUP5__
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
//
|
||||
// Group5 1-bit image compression library
|
||||
// Written by Larry Bank
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file ./LICENSE.
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// ./APL.txt.
|
||||
//
|
||||
// The name "Group5" is derived from the CCITT Group4 standard
|
||||
// This code is based on a lot of the good ideas from CCITT T.6
|
||||
// for FAX image compression, but modified to work in a very
|
||||
// constrained environment. The Huffman tables for horizontal
|
||||
// mode have been replaced with a simple 2-bit flag followed by
|
||||
// short or long counts of a fixed length. The short codes are
|
||||
// always 3 bits (run lengths 0-7) and the long codes are the
|
||||
// number of bits needed to encode the width of the image.
|
||||
// For example, if a 320 pixel wide image is being compressed,
|
||||
// the longest horizontal run needed is 320, which requires 9
|
||||
// bits to encode. The 2 prefix bits have the following meaning:
|
||||
// 00 = short, short (3+3 bits)
|
||||
// 01 = short, long (3+N bits)
|
||||
// 10 = long, short (N+3 bits)
|
||||
// 11 = long, long (N+N bits)
|
||||
// The rest of the code works identically to Group4 2D FAX
|
||||
//
|
||||
// Caution - this is the maximum number of color changes per line
|
||||
// The default value is set low to work embedded systems with little RAM
|
||||
// for font compression, this is plenty since each line of a character should have
|
||||
// a maximum of 7 color changes
|
||||
// You can define this in your compiler macros to override the default vlaue
|
||||
//
|
||||
#ifndef MAX_IMAGE_FLIPS
|
||||
#define MAX_IMAGE_FLIPS 32
|
||||
#endif
|
||||
// Horizontal prefix bits
|
||||
enum {
|
||||
HORIZ_SHORT_SHORT=0,
|
||||
HORIZ_SHORT_LONG,
|
||||
HORIZ_LONG_SHORT,
|
||||
HORIZ_LONG_LONG
|
||||
};
|
||||
|
||||
// Return code for encoder and decoder
|
||||
enum {
|
||||
G5_SUCCESS = 0,
|
||||
G5_INVALID_PARAMETER,
|
||||
G5_DECODE_ERROR,
|
||||
G5_UNSUPPORTED_FEATURE,
|
||||
G5_ENCODE_COMPLETE,
|
||||
G5_DECODE_COMPLETE,
|
||||
G5_NOT_INITIALIZED,
|
||||
G5_DATA_OVERFLOW,
|
||||
};
|
||||
//
|
||||
// Decoder state
|
||||
//
|
||||
typedef struct g5_dec_image_tag
|
||||
{
|
||||
int iWidth, iHeight; // image size
|
||||
int iError;
|
||||
int y; // last y value drawn
|
||||
int iVLCSize;
|
||||
int iHLen; // length of 'long' horizontal codes for this image
|
||||
int iPitch; // width in bytes of output buffer
|
||||
uint32_t u32Accum; // fractional scaling accumulator
|
||||
uint32_t ulBitOff, ulBits; // vlc decode variables
|
||||
uint8_t *pSrc, *pBuf; // starting & current buffer pointer
|
||||
int16_t *pCur, *pRef; // current state of current vs reference flips
|
||||
int16_t CurFlips[MAX_IMAGE_FLIPS];
|
||||
int16_t RefFlips[MAX_IMAGE_FLIPS];
|
||||
} G5DECIMAGE;
|
||||
|
||||
// Due to unaligned memory causing an exception, we have to do these macros the slow way
|
||||
#define TIFFMOTOLONG(p) (((uint32_t)(*p)<<24UL) + ((uint32_t)(*(p+1))<<16UL) + ((uint32_t)(*(p+2))<<8UL) + (uint32_t)(*(p+3)))
|
||||
#define TOP_BIT 0x80000000
|
||||
#define MAX_VALUE 0xffffffff
|
||||
// Must be a 32-bit target processor
|
||||
#define REGISTER_WIDTH 32
|
||||
#define BIGUINT uint32_t
|
||||
|
||||
//
|
||||
// G5 Encoder
|
||||
//
|
||||
|
||||
typedef struct pil_buffered_bits
|
||||
{
|
||||
unsigned char *pBuf; // buffer pointer
|
||||
uint32_t ulBits; // buffered bits
|
||||
uint32_t ulBitOff; // current bit offset
|
||||
uint32_t ulDataSize; // available data
|
||||
} BUFFERED_BITS;
|
||||
|
||||
//
|
||||
// Encoder state
|
||||
//
|
||||
typedef struct g5_enc_image_tag
|
||||
{
|
||||
int iWidth, iHeight; // image size
|
||||
int iError;
|
||||
int y; // last y encoded
|
||||
int iOutSize;
|
||||
int iDataSize; // generated output size
|
||||
uint8_t *pOutBuf;
|
||||
int16_t *pCur, *pRef; // pointers to swap current and reference lines
|
||||
BUFFERED_BITS bb;
|
||||
int16_t CurFlips[MAX_IMAGE_FLIPS];
|
||||
int16_t RefFlips[MAX_IMAGE_FLIPS];
|
||||
} G5ENCIMAGE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
//
|
||||
// The G5 classes wrap portable C code which does the actual work
|
||||
//
|
||||
class G5ENCODER
|
||||
{
|
||||
public:
|
||||
int init(int iWidth, int iHeight, uint8_t *pOut, int iOutSize);
|
||||
int encodeLine(uint8_t *pPixels);
|
||||
int size();
|
||||
|
||||
private:
|
||||
G5ENCIMAGE _g5enc;
|
||||
};
|
||||
class G5DECODER
|
||||
{
|
||||
public:
|
||||
int init(int iWidth, int iHeight, uint8_t *pData, int iDataSize);
|
||||
int decodeLine(uint8_t *pOut);
|
||||
|
||||
private:
|
||||
G5DECIMAGE _g5dec;
|
||||
};
|
||||
#else
|
||||
// C function definitions
|
||||
int g5_decode_init(G5DECIMAGE *pImage, int iWidth, int iHeight, uint8_t *pData, int iDataSize);
|
||||
int g5_decode_line(G5DECIMAGE *pImage, uint8_t *pOut);
|
||||
int g5_encode_init(G5ENCIMAGE *pImage, int iWidth, int iHeight, uint8_t *pOut, int iOutSize);
|
||||
int g5_encode_encodeLine(G5ENCIMAGE *pImage, uint8_t *pPixels);
|
||||
int g5_encode_getOutSize(G5ENCIMAGE *pImage);
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __GROUP5__
|
||||
@@ -19,7 +19,7 @@
|
||||
//
|
||||
#ifndef __BB_EI_IO__
|
||||
#define __BB_EI_IO__
|
||||
#ifdef ARDUINO
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
//
|
||||
@@ -114,23 +114,6 @@ void bbeiWriteCmd(BBEIDISP *pBBEI, uint8_t cmd)
|
||||
digitalWrite(pBBEI->iDCPin, HIGH); // leave data mode as the default
|
||||
} /* bbeiWriteCmd() */
|
||||
//
|
||||
// Put the eink into light or deep sleep
|
||||
//
|
||||
void bbeiSleep(BBEIDISP *pBBEI, int bDeep)
|
||||
{
|
||||
if (pBBEI->chip_type == BBEI_CHIP_UC81xx) {
|
||||
bbeiCMD2(pBBEI, UC8151_CDI, 0x17); // border floating
|
||||
bbeiWriteCmd(pBBEI, UC8151_POFF); // power off
|
||||
bbeiWaitBusy(pBBEI);
|
||||
if (bDeep) {
|
||||
bbeiCMD2(pBBEI, UC8151_DSLP, 0xa5); // deep sleep
|
||||
}
|
||||
} else {
|
||||
bbeiCMD2(pBBEI, SSD1608_DEEP_SLEEP, (bDeep) ? 0x02 : 0x01); // deep sleep mode 1 keeps RAM, mode 2 loses RAM
|
||||
}
|
||||
pBBEI->is_awake = 0;
|
||||
} /* bbeiSleep() */
|
||||
//
|
||||
// Write 1 or more bytes as DATA (D/C set high)
|
||||
//
|
||||
void bbeiWriteData(BBEIDISP *pBBEI, uint8_t *pData, int iLen)
|
||||
@@ -145,6 +128,4 @@ void bbeiWriteData(BBEIDISP *pBBEI, uint8_t *pData, int iLen)
|
||||
#endif
|
||||
} /* bbeiWriteData() */
|
||||
|
||||
#else // LINUX
|
||||
#endif // ARDUINO / LINUX
|
||||
#endif // __BB_EI_IO__
|
||||
@@ -1037,6 +1037,24 @@ void bbeiSetPosition(BBEIDISP *pBBEI, int x, int y, int cx, int cy)
|
||||
// bbeiCMD2(pBBEI, SSD1608_DATA_MODE, 0x3);
|
||||
}
|
||||
} /* bbeiSetPosition() */
|
||||
//
|
||||
// Put the eink into light or deep sleep
|
||||
//
|
||||
void bbeiSleep(BBEIDISP *pBBEI, int bDeep)
|
||||
{
|
||||
if (pBBEI->chip_type == BBEI_CHIP_UC81xx) {
|
||||
bbeiCMD2(pBBEI, UC8151_CDI, 0x17); // border floating
|
||||
bbeiWriteCmd(pBBEI, UC8151_POFF); // power off
|
||||
bbeiWaitBusy(pBBEI);
|
||||
if (bDeep) {
|
||||
bbeiCMD2(pBBEI, UC8151_DSLP, 0xa5); // deep sleep
|
||||
}
|
||||
} else {
|
||||
bbeiCMD2(pBBEI, SSD1608_DEEP_SLEEP, 0x01); // deep sleep mode 1 keeps RAM,only uses about 1uA
|
||||
}
|
||||
pBBEI->is_awake = 0;
|
||||
} /* bbeiSleep() */
|
||||
|
||||
//
|
||||
// More efficient means of sending commands, data and busy-pauses
|
||||
//
|
||||
|
||||
+75
-81
@@ -304,65 +304,38 @@ void bbeiDrawSprite(BBEIDISP *pBBEI, const uint8_t *pSprite, int cx, int cy, int
|
||||
int bbeiSetPixel(BBEIDISP *pBBEI, int x, int y, unsigned char ucColor)
|
||||
{
|
||||
int i;
|
||||
unsigned char uc, ucOld;
|
||||
int iPitch, iSize;
|
||||
|
||||
iPitch = pBBEI->width;
|
||||
iSize = iPitch * ((pBBEI->height+7)/8);
|
||||
// only available for local buffer operations
|
||||
if (!pBBEI || !pBBEI->ucScreen) return BBEI_ERROR_BAD_PARAMETER;
|
||||
|
||||
iPitch = (pBBEI->native_width+7)>>3;
|
||||
iSize = iPitch * pBBEI->native_height;
|
||||
|
||||
i = ((y >> 3) * iPitch) + x;
|
||||
i = (x >> 3) + (y * iPitch);
|
||||
if (i < 0 || i > iSize-1) { // off the screen
|
||||
return BBEI_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
// Special case for 4-color e-ink
|
||||
if (pBBEI->iFlags & BBEI_4COLOR) {
|
||||
uint8_t ucMask = (1 << (y & 7));
|
||||
ucColor ^= 1; // invert low bit
|
||||
if (ucColor & 1)
|
||||
pBBEI->ucScreen[i] |= ucMask;
|
||||
else
|
||||
pBBEI->ucScreen[i] &= ~ucMask;
|
||||
if (ucColor & 2)
|
||||
pBBEI->ucScreen[iSize + i] |= ucMask;
|
||||
else
|
||||
pBBEI->ucScreen[iSize + i] &= ~ucMask;
|
||||
return BBEI_SUCCESS;
|
||||
}
|
||||
// special case for 3-color e-ink
|
||||
if (pBBEI->iFlags & BBEI_3COLOR) {
|
||||
if (ucColor >= BBEI_YELLOW) { // yellow/red has priority
|
||||
pBBEI->ucScreen[iSize + i] |= (1 << (y & 7));
|
||||
pBBEI->ucScreen[iSize + i] |= (0x80 >> (x & 7));
|
||||
} else {
|
||||
pBBEI->ucScreen[iSize + i] &= ~(1 << (y & 7)); // clear red plane bit
|
||||
pBBEI->ucScreen[iSize + i] &= ~(0x80 >> (x & 7)); // clear red plane bit
|
||||
if (ucColor == BBEI_WHITE) {
|
||||
pBBEI->ucScreen[i] &= ~(1 << (y & 7));
|
||||
pBBEI->ucScreen[i] &= ~(0x80 >> (x & 7));
|
||||
} else { // must be black
|
||||
pBBEI->ucScreen[i] |= (1 << (y & 7));
|
||||
pBBEI->ucScreen[i] |= (0x80 >> (x & 7));
|
||||
}
|
||||
}
|
||||
return BBEI_SUCCESS;
|
||||
} else { // 2-color
|
||||
if (ucColor == BBEI_WHITE) {
|
||||
pBBEI->ucScreen[i] &= ~(0x80 >> (x & 7));
|
||||
} else { // must be black
|
||||
pBBEI->ucScreen[i] |= (0x80 >> (x & 7));
|
||||
}
|
||||
}
|
||||
bbeiSetPosition(pBBEI, x, y, 8, 1);
|
||||
|
||||
if (pBBEI->ucScreen)
|
||||
uc = ucOld = pBBEI->ucScreen[i];
|
||||
else
|
||||
uc = ucOld = 0;
|
||||
|
||||
uc &= ~(0x1 << (y & 7));
|
||||
if (ucColor)
|
||||
{
|
||||
uc |= (0x1 << (y & 7));
|
||||
}
|
||||
if (uc != ucOld) // pixel changed
|
||||
{
|
||||
// obdSetPosition(x, y>>3);
|
||||
if (pBBEI->ucScreen)
|
||||
{
|
||||
bbeiWriteData(pBBEI, &uc, 1);
|
||||
pBBEI->ucScreen[i] = uc;
|
||||
}
|
||||
}
|
||||
return BBEI_SUCCESS;
|
||||
} /* obdSetPixel() */
|
||||
|
||||
@@ -614,7 +587,7 @@ void bbeiSetTextWrap(BBEIDISP *pBBEI, int bWrap)
|
||||
//
|
||||
void bbeiWriteStringCustom(BBEIDISP *pBBEI, BB_FONT *pFont, int x, int y, char *szMsg, int iColor, uint8_t iPlane)
|
||||
{
|
||||
int rc, i, h, w, end_y, dx, dy, ty, iSrcPitch, iPitch;
|
||||
int rc, i, h, w, end_y, dx, dy, tx, ty, iSrcPitch, iPitch;
|
||||
unsigned int c;
|
||||
uint8_t *s, bInvert = 0;
|
||||
BB_GLYPH *pGlyph;
|
||||
@@ -671,44 +644,65 @@ uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
||||
if (ty < 0 || ty > 4096) ty = 4096; // DEBUG
|
||||
rc = g5_decode_init(&g5dec, w, h, s, ty);
|
||||
if (rc != G5_SUCCESS) return; // corrupt data?
|
||||
// set the memory window for this character
|
||||
iSrcPitch = (w+7)/8;
|
||||
w += (dx & 7); // add parital byte
|
||||
bbeiSetPosition(pBBEI, dx, dy, w, h);
|
||||
iPitch = (w+7)/8;
|
||||
// start writing into the correct plane
|
||||
if (pBBEI->chip_type == BBEI_CHIP_UC81xx) {
|
||||
u8CMD1 = UC8151_DTM2;
|
||||
u8CMD2 = UC8151_DTM1;
|
||||
} else {
|
||||
u8CMD1 = SSD1608_WRITE_RAM;
|
||||
u8CMD2 = SSD1608_WRITE_ALTRAM;
|
||||
if (pBBEI->ucScreen) { // backbuffer, draw pixels
|
||||
for (ty=dy; ty<end_y && ty < pBBEI->native_height; ty++) {
|
||||
uint8_t u8, u8Count;
|
||||
g5_decode_line(&g5dec, u8Cache);
|
||||
s = u8Cache;
|
||||
u8 = *s++;
|
||||
u8Count = 8;
|
||||
for (tx=x; tx<x+w; tx++) {
|
||||
if (u8 & 0x80) {
|
||||
bbeiSetPixel(pBBEI, tx, ty, iColor);
|
||||
}
|
||||
u8 <<= 1;
|
||||
u8Count--;
|
||||
if (u8Count == 0) {
|
||||
u8Count = 8;
|
||||
u8 = *s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // draw directly into EPD memory
|
||||
// set the memory window for this character
|
||||
iSrcPitch = (w+7)/8;
|
||||
w += (dx & 7); // add parital byte
|
||||
bbeiSetPosition(pBBEI, dx, dy, w, h);
|
||||
iPitch = (w+7)/8;
|
||||
// start writing into the correct plane
|
||||
if (pBBEI->chip_type == BBEI_CHIP_UC81xx) {
|
||||
u8CMD1 = UC8151_DTM2;
|
||||
u8CMD2 = UC8151_DTM1;
|
||||
} else {
|
||||
u8CMD1 = SSD1608_WRITE_RAM;
|
||||
u8CMD2 = SSD1608_WRITE_ALTRAM;
|
||||
}
|
||||
u8CMD = u8CMD1;
|
||||
if (iColor == BBEI_BLACK) bInvert = 1;
|
||||
else if (iColor == BBEI_RED && (pBBEI->iFlags & BBEI_3COLOR)) {
|
||||
u8CMD = u8CMD2; // second plane is red (inverted)
|
||||
}
|
||||
bbeiWriteCmd(pBBEI, u8CMD); // memory write command
|
||||
for (ty=dy; ty<end_y && ty < pBBEI->native_height; ty++) {
|
||||
g5_decode_line(&g5dec, u8Cache);
|
||||
u8Cache[iSrcPitch-1] &= u8EndMask; // clean pixels beyond character width
|
||||
u8Cache[iSrcPitch] = 0;
|
||||
if (dx & 7) { // need to shift it over by 1-7 bits
|
||||
uint8_t *s = u8Cache, uc1, uc0 = 0; // last shifted byte
|
||||
uint8_t n = dx & 7; // shift amount
|
||||
for (int j=0; j<w+7; j+= 8) {
|
||||
uc1 = *s;
|
||||
uc0 |= (uc1 >> n);
|
||||
*s++ = uc0;
|
||||
uc0 = uc1 << (8-n);
|
||||
}
|
||||
*s++ = uc0; // store final byte
|
||||
*s++ = 0; // and a zero for good measure
|
||||
}
|
||||
if (bInvert) InvertBytes(u8Cache, iPitch);
|
||||
bbeiWriteData(pBBEI, u8Cache, iPitch); // write each row into the EPD framebuffer
|
||||
} // for y
|
||||
}
|
||||
u8CMD = u8CMD1;
|
||||
if (iColor == BBEI_BLACK) bInvert = 1;
|
||||
else if (iColor == BBEI_RED && (pBBEI->iFlags & BBEI_3COLOR)) {
|
||||
u8CMD = u8CMD2; // second plane is red (inverted)
|
||||
}
|
||||
bbeiWriteCmd(pBBEI, u8CMD); // memory write command
|
||||
for (ty=dy; ty<end_y && ty < pBBEI->native_height; ty++) {
|
||||
g5_decode_line(&g5dec, u8Cache);
|
||||
u8Cache[iSrcPitch-1] &= u8EndMask; // clean pixels beyond character width
|
||||
u8Cache[iSrcPitch] = 0;
|
||||
if (dx & 7) { // need to shift it over by 1-7 bits
|
||||
uint8_t *s = u8Cache, uc1, uc0 = 0; // last shifted byte
|
||||
uint8_t n = dx & 7; // shift amount
|
||||
for (int j=0; j<w+7; j+= 8) {
|
||||
uc1 = *s;
|
||||
uc0 |= (uc1 >> n);
|
||||
*s++ = uc0;
|
||||
uc0 = uc1 << (8-n);
|
||||
}
|
||||
*s++ = uc0; // store final byte
|
||||
*s++ = 0; // and a zero for good measure
|
||||
}
|
||||
if (bInvert) InvertBytes(u8Cache, iPitch);
|
||||
bbeiWriteData(pBBEI, u8Cache, iPitch); // write each row into the EPD framebuffer
|
||||
} // for y
|
||||
} // if not drawing a space
|
||||
if (pFont->rotation == 0 || pFont->rotation == 180) {
|
||||
x += pGlyph->xAdvance; // width of this character
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ void delay(int);
|
||||
#endif // _LINUX_
|
||||
|
||||
#include "bb_eink.h"
|
||||
#include "bb_ei_io.inl" // I/O (non-portable) code is in here
|
||||
#include "arduino_io.inl" // I/O (non-portable) code is in here
|
||||
#include "bb_ei.inl" // All of the display interface code is in here
|
||||
#include "bb_ei_gfx.inl" // drawing code
|
||||
#include "Group5.h" // Group5 data compression library
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// C structures for defining a BB_FONT file
|
||||
// Written by Larry Bank
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file ./LICENSE.
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// ./APL.txt.
|
||||
//
|
||||
// The BB_FONT is at the start of the file
|
||||
// followed by BB_GLYPH structures for each character
|
||||
// and finally the packed bitmap data (one after another)
|
||||
// is at the end of the file
|
||||
//
|
||||
|
||||
#ifndef _BB_FONT_H_
|
||||
#define _BB_FONT_H_
|
||||
|
||||
// 16-bit marker at the start of a BB_FONT file
|
||||
// (BitBank FontFile)
|
||||
#define BB_MARKER 0xBBFF
|
||||
// Font info per character (glyph)
|
||||
typedef struct {
|
||||
uint16_t bitmapOffset; // Offset to compressed bitmap data for this glyph (starting from the end of the BB_GLYPH[] array)
|
||||
uint8_t width; // bitmap width in pixels
|
||||
uint8_t xAdvance; // total width in pixels (bitmap + padding)
|
||||
uint16_t height; // bitmap height in pixels
|
||||
int16_t xOffset; // left padding to upper left corner
|
||||
int16_t yOffset; // padding from baseline to upper left corner (usually negative)
|
||||
} BB_GLYPH;
|
||||
|
||||
// This structure is stored at the beginning of a BB_FONT file
|
||||
typedef struct {
|
||||
uint16_t u16Marker; // 16-bit Marker defining a BB_FONT file
|
||||
uint16_t first; // first char (ASCII value)
|
||||
uint16_t last; // last char (ASCII value)
|
||||
uint16_t height; // total height of font
|
||||
uint32_t rotation; // store this as 32-bits to not have a struct packing problem
|
||||
BB_GLYPH glyphs[]; // Array of glyphs (one for each char)
|
||||
} BB_FONT;
|
||||
|
||||
#endif // _BB_FONT_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user